API: several fixes to the Twitter/Statusnet API

This commit is contained in:
Michael 2022-02-25 19:16:40 +00:00
parent 093dd70e79
commit bf5c8a2c43
22 changed files with 94 additions and 70 deletions

View file

@ -70,7 +70,7 @@ class Status extends BaseFactory
* @param int $uriId Uri-ID of the item
* @param int $uid Item user
*
* @return \Friendica\Object\Api\Mastodon\Status
* @return \Friendica\Object\Api\Twitter\Status
* @throws HTTPException\InternalServerErrorException
* @throws ImagickException|HTTPException\NotFoundException
*/
@ -89,13 +89,13 @@ class Status extends BaseFactory
* @param int $uriId Uri-ID of the item
* @param int $uid Item user
*
* @return \Friendica\Object\Api\Mastodon\Status
* @return \Friendica\Object\Api\Twitter\Status
* @throws HTTPException\InternalServerErrorException
* @throws ImagickException|HTTPException\NotFoundException
*/
public function createFromUriId(int $uriId, $uid = 0, $include_entities = false): \Friendica\Object\Api\Twitter\Status
{
$fields = ['id', 'parent', 'uri-id', 'uid', 'author-id', 'author-link', 'author-network', 'owner-id', 'starred', 'app', 'title', 'body', 'raw-body', 'created', 'network',
$fields = ['parent-uri-id', 'uri-id', 'uid', 'author-id', 'author-link', 'author-network', 'owner-id', 'starred', 'app', 'title', 'body', 'raw-body', 'created', 'network',
'thr-parent-id', 'parent-author-id', 'parent-author-nick', 'language', 'uri', 'plink', 'private', 'vid', 'gravity', 'coord'];
$item = Post::selectFirst($fields, ['uri-id' => $uriId, 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (!$item) {
@ -108,7 +108,7 @@ class Status extends BaseFactory
* @param array $item item array
* @param int $uid Item user
*
* @return \Friendica\Object\Api\Mastodon\Status
* @return \Friendica\Object\Api\Twitter\Status
* @throws HTTPException\InternalServerErrorException
* @throws ImagickException|HTTPException\NotFoundException
*/

View file

@ -21,9 +21,10 @@
namespace Friendica\Module\Api\Friendica;
use Friendica\DI;
use Friendica\Model\Item;
use Friendica\Model\Post;
use Friendica\Module\BaseApi;
use Friendica\Network\HTTPException\BadRequestException;
/**
* API endpoints:
@ -49,7 +50,12 @@ class Activity extends BaseApi
'id' => 0, // Id of the post
], $request);
$res = Item::performActivity($request['id'], $this->parameters['verb'], $uid);
$post = Post::selectFirst(['id'], ['uri-id' => $request['id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (empty($post['id'])) {
throw new BadRequestException('Item id not found');
}
$res = Item::performActivity($post['id'], $this->parameters['verb'], $uid);
if ($res) {
if (($this->parameters['extension'] ?? '') == 'xml') {

View file

@ -23,7 +23,6 @@ namespace Friendica\Module\Api\Friendica\Events;
use Friendica\Content\Text\BBCode;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Module\BaseApi;
/**
@ -40,7 +39,7 @@ class Index extends BaseApi
$request = $this->getRequest([
'since_id' => 0,
'count' => 0,
'count' => 50,
], $request);
$condition = ["`id` > ? AND `uid` = ?", $request['since_id'], $uid];

View file

@ -32,7 +32,7 @@ use Friendica\Network\HTTPException;
*/
class Show extends BaseApi
{
protected function post(array $request = [])
protected function rawContent(array $request = [])
{
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();

View file

@ -44,7 +44,7 @@ class Photo extends BaseApi
$this->friendicaPhoto = $friendicaPhoto;
}
protected function post(array $request = [])
protected function rawContent(array $request = [])
{
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();

View file

@ -56,7 +56,7 @@ class Conversation extends BaseApi
Logger::info(BaseApi::LOG_PREFIX . '{subaction}', ['module' => 'api', 'action' => 'conversation', 'subaction' => 'show', 'id' => $id]);
// try to fetch the item for the local user - or the public item, if there is no local one
$item = Post::selectFirst(['parent-uri-id'], ['id' => $id]);
$item = Post::selectFirst(['parent-uri-id'], ['uri-id' => $id]);
if (!DBA::isResult($item)) {
throw new BadRequestException("There is no status with the id $id.");
}
@ -68,15 +68,15 @@ class Conversation extends BaseApi
$id = $parent['id'];
$condition = ["`parent` = ? AND `uid` IN (0, ?) AND `gravity` IN (?, ?) AND `id` > ?",
$condition = ["`parent` = ? AND `uid` IN (0, ?) AND `gravity` IN (?, ?) AND `uri-id` > ?",
$id, $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, [], $condition, $params);
if (!DBA::isResult($statuses)) {

View file

@ -53,13 +53,13 @@ class Favorites extends BaseApi
$start = max(0, ($page - 1) * $count);
$condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `starred`",
$condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `uri-id` > ? AND `starred`",
$uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}

View file

@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Twitter\Favorites;
use Friendica\DI;
use Friendica\Model\Item;
use Friendica\Model\Post;
use Friendica\Module\BaseApi;
use Friendica\Network\HTTPException\BadRequestException;
@ -42,9 +43,14 @@ class Create extends BaseApi
throw new BadRequestException('Item id not specified');
}
Item::performActivity($id, 'like', $uid);
$post = Post::selectFirst(['id'], ['uri-id' => $request['id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (empty($post['id'])) {
throw new BadRequestException('Item id not found');
}
$status_info = DI::twitterStatus()->createFromItemId($id, $uid)->toArray();
Item::performActivity($post['id'], 'like', $uid);
$status_info = DI::twitterStatus()->createFromUriId($id, $uid)->toArray();
$this->response->exit('status', ['status' => $status_info], $this->parameters['extension'] ?? null);
}

View file

@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Twitter\Favorites;
use Friendica\DI;
use Friendica\Model\Item;
use Friendica\Model\Post;
use Friendica\Module\BaseApi;
use Friendica\Network\HTTPException\BadRequestException;
@ -42,9 +43,14 @@ class Destroy extends BaseApi
throw new BadRequestException('Item id not specified');
}
Item::performActivity($id, 'unlike', $uid);
$post = Post::selectFirst(['id'], ['uri-id' => $request['id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (empty($post['id'])) {
throw new BadRequestException('Item id not found');
}
$status_info = DI::twitterStatus()->createFromItemId($id, $uid)->toArray();
Item::performActivity($post['id'], 'unlike', $uid);
$status_info = DI::twitterStatus()->createFromUriId($id, $uid)->toArray();
$this->response->exit('status', ['status' => $status_info], $this->parameters['extension'] ?? null);
}

View file

@ -78,10 +78,10 @@ class Statuses extends BaseApi
$groups = $this->dba->selectToArray('group_member', ['contact-id'], ['gid' => $request['list_id']]);
$gids = array_column($groups, 'contact-id');
$condition = ['uid' => $uid, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'contact-id' => $gids];
$condition = DBA::mergeConditions($condition, ["`id` > ?", $since_id]);
$condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $since_id]);
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
if ($exclude_replies) {
@ -89,11 +89,11 @@ class Statuses extends BaseApi
$condition[] = GRAVITY_PARENT;
}
if ($conversation_id > 0) {
$condition[0] .= " AND `parent` = ?";
$condition[0] .= " AND `parent-uri-id` = ?";
$condition[] = $conversation_id;
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, [], $condition, $params);
$items = [];

View file

@ -59,10 +59,10 @@ class Tweets extends BaseApi
$start = max(0, ($page - 1) * $count);
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) {
$searchTerm = $matches[1];
$condition = ["`iid` > ? AND `name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $since_id, $searchTerm, $uid];
$condition = ["`uri-id` > ? AND `name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $since_id, $searchTerm, $uid];
$tags = DBA::select('tag-search-view', ['uri-id'], $condition);
$uriids = [];
@ -83,13 +83,13 @@ class Tweets extends BaseApi
$params['group_by'] = ['uri-id'];
} else {
$condition = ["`id` > ?
$condition = ["`uri-id` > ?
" . ($exclude_replies ? " AND `gravity` = " . GRAVITY_PARENT : ' ') . "
AND (`uid` = 0 OR (`uid` = ? AND NOT `global`))
AND `body` LIKE CONCAT('%',?,'%')",
$since_id, $uid, $_REQUEST['q']];
if ($max_id > 0) {
$condition[0] .= ' AND `id` <= ?';
$condition[0] .= ' AND `uri-id` <= ?';
$condition[] = $max_id;
}
}

View file

@ -25,6 +25,7 @@ use Friendica\Module\BaseApi;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Model\Post;
use Friendica\Network\HTTPException\BadRequestException;
/**
@ -45,13 +46,18 @@ class Destroy extends BaseApi
throw new BadRequestException('An id is missing.');
}
$post = Post::selectFirst(['id'], ['uri-id' => $request['id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (empty($post['id'])) {
throw new BadRequestException('Item id not found');
}
$this->logger->notice('API: api_statuses_destroy: ' . $id);
$include_entities = $this->getRequestValue($request, 'include_entities', false);
$ret = DI::twitterStatus()->createFromItemId($id, $uid, $include_entities)->toArray();
$ret = DI::twitterStatus()->createFromUriId($id, $uid, $include_entities)->toArray();
Item::deleteForUser(['id' => $id], $uid);
Item::deleteForUser(['id' => $post['id']], $uid);
$this->response->exit('status', ['status' => $ret], $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid));
}

View file

@ -53,11 +53,11 @@ class HomeTimeline extends BaseApi
$start = max(0, ($page - 1) * $count);
$condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ?",
$condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `uri-id` > ?",
$uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
if ($exclude_replies) {
@ -65,11 +65,11 @@ class HomeTimeline extends BaseApi
$condition[] = GRAVITY_PARENT;
}
if ($conversation_id > 0) {
$condition[0] .= " AND `parent` = ?";
$condition[0] .= " AND `parent-uri-id` = ?";
$condition[] = $conversation_id;
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, [], $condition, $params);
$ret = [];

View file

@ -52,7 +52,7 @@ class Mentions extends BaseApi
$query = "`gravity` IN (?, ?) AND `uri-id` IN
(SELECT `uri-id` FROM `post-user-notification` WHERE `uid` = ? AND `notification-type` & ? != 0 ORDER BY `uri-id`)
AND (`uid` = 0 OR (`uid` = ? AND NOT `global`)) AND `id` > ?";
AND (`uid` = 0 OR (`uid` = ? AND NOT `global`)) AND `uri-id` > ?";
$condition = [
GRAVITY_PARENT, GRAVITY_COMMENT,
@ -64,13 +64,13 @@ class Mentions extends BaseApi
];
if ($max_id > 0) {
$query .= " AND `id` <= ?";
$query .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
array_unshift($condition, $query);
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, [], $condition, $params);
$ret = [];

View file

@ -46,15 +46,15 @@ class NetworkPublicTimeline extends BaseApi
$start = max(0, ($page - 1) * $count);
$condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `id` > ? AND `private` = ?",
$condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `uri-id` > ? AND `private` = ?",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, Item::DISPLAY_FIELDLIST, $condition, $params);
$ret = [];

View file

@ -52,30 +52,30 @@ class PublicTimeline extends BaseApi
$start = max(0, ($page - 1) * $count);
if ($exclude_replies && !$conversation_id) {
$condition = ["`gravity` = ? AND `id` > ? AND `private` = ? AND `wall` AND NOT `author-hidden`",
$condition = ["`gravity` = ? AND `uri-id` > ? AND `private` = ? AND `wall` AND NOT `author-hidden`",
GRAVITY_PARENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, [], $condition, $params);
} else {
$condition = ["`gravity` IN (?, ?) AND `id` > ? AND `private` = ? AND `wall` AND `origin` AND NOT `author-hidden`",
$condition = ["`gravity` IN (?, ?) AND `uri-id` > ? AND `private` = ? AND `wall` AND `origin` AND NOT `author-hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
if ($conversation_id > 0) {
$condition[0] .= " AND `parent` = ?";
$condition[0] .= " AND `parent-uri-id` = ?";
$condition[] = $conversation_id;
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, [], $condition, $params);
}

View file

@ -50,8 +50,8 @@ class Retweet extends BaseApi
throw new BadRequestException('An id is missing.');
}
$fields = ['uri-id', 'network', 'body', 'title', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink'];
$item = Post::selectFirst($fields, ['id' => $id, 'private' => [Item::PUBLIC, Item::UNLISTED]]);
$fields = ['id', 'uri-id', 'network', 'body', 'title', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink'];
$item = Post::selectFirst($fields, ['uri-id' => $id, 'uid' => [0, $uid], 'private' => [Item::PUBLIC, Item::UNLISTED]], ['order' => ['uid' => true]]);
if (DBA::isResult($item) && !empty($item['body'])) {
if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::TWITTER])) {
@ -59,7 +59,7 @@ class Retweet extends BaseApi
throw new InternalServerErrorException();
}
$item_id = $id;
$item_id = $item['id'];
} else {
$item_id = Diaspora::performReshare($item['uri-id'], $uid);
}

View file

@ -52,23 +52,18 @@ class Show extends BaseApi
$conversation = !empty($request['conversation']);
// try to fetch the item for the local user - or the public item, if there is no local one
$uri_item = Post::selectFirst(['uri-id'], ['id' => $id]);
if (!DBA::isResult($uri_item)) {
throw new BadRequestException(sprintf("There is no status with the id %d", $id));
}
$item = Post::selectFirst(['id'], ['uri-id' => $uri_item['uri-id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
$item = Post::selectFirst(['id'], ['uri-id' => $id, 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (!DBA::isResult($item)) {
throw new BadRequestException(sprintf("There is no status with the uri-id %d for the given user.", $uri_item['uri-id']));
throw new BadRequestException(sprintf("There is no status with the uri-id %d for the given user.", $id));
}
$id = $item['id'];
$item_id = $item['id'];
if ($conversation) {
$condition = ['parent' => $id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
$params = ['order' => ['id' => true]];
$condition = ['parent' => $item_id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
$params = ['order' => ['uri-id' => true]];
} else {
$condition = ['id' => $id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
$condition = ['id' => $item_id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
$params = [];
}

View file

@ -53,7 +53,7 @@ class UserTimeline extends BaseApi
$start = max(0, ($page - 1) * $count);
$condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`)) AND `gravity` IN (?, ?) AND `id` > ? AND `author-id` = ?",
$condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`)) AND `gravity` IN (?, ?) AND `uri-id` > ? AND `author-id` = ?",
0, $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $cid];
if ($exclude_replies) {
@ -62,15 +62,15 @@ class UserTimeline extends BaseApi
}
if ($conversation_id > 0) {
$condition[0] .= " AND `parent` = ?";
$condition[0] .= " AND `parent-uri-id` = ?";
$condition[] = $conversation_id;
}
if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?";
$condition[0] .= " AND `uri-id` <= ?";
$condition[] = $max_id;
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$params = ['order' => ['uri-id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser($uid, [], $condition, $params);
$ret = [];

View file

@ -92,6 +92,11 @@ class Receive extends BaseModule
$this->logger->info('Diaspora: Receiving post.');
$importer = User::getByGuid($this->parameters['guid']);
if (empty($importer)) {
// We haven't found the user.
// To avoid the remote system trying again we send the message that we accepted the content.
throw new HTTPException\AcceptedException();
}
if ($importer['account-type'] == User::ACCOUNT_TYPE_COMMUNITY) {
// Communities aren't working with the Diaspora protoccol
@ -99,7 +104,7 @@ class Receive extends BaseModule
throw new HTTPException\AcceptedException();
}
$msg = $this->decodePost(false, $importer['prvkey'] ?? '');
$msg = $this->decodePost(false, $importer['prvkey']);
$this->logger->info('Diaspora: Dispatching.');

View file

@ -100,9 +100,9 @@ class Status extends BaseDataTransferObject
*/
public function __construct(string $text, string $statusnetHtml, string $friendicaHtml, array $item, User $author, User $owner, array $retweeted, array $quoted, array $geo, array $friendica_activities, array $entities, array $attachments, int $friendica_comments, bool $liked)
{
$this->id = (int)$item['id'];
$this->id_str = (string)$item['id'];
$this->statusnet_conversation_id = (int)$item['parent'];
$this->id = (int)$item['uri-id'];
$this->id_str = (string)$item['uri-id'];
$this->statusnet_conversation_id = (int)$item['parent-uri-id'];
$this->created_at = DateTimeFormat::utc($item['created'], DateTimeFormat::API);

View file

@ -77,6 +77,7 @@ $apiRoutes = [
=> [Module\Api\Friendica\Activity::class, [ R::POST]],
'/notification/seen[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification\Seen::class, [ R::POST]],
'/notification[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification::class, [R::GET ]],
'/notifications[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Notification::class, [R::GET ]],
'/direct_messages_setseen[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\DirectMessages\Setseen::class, [ R::POST]],
'/direct_messages_search[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\DirectMessages\Search ::class, [R::GET ]],
'/events[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Events\Index::class, [R::GET ]],