diff --git a/include/api.php b/include/api.php index 68723a0f42..16396c263b 100644 --- a/include/api.php +++ b/include/api.php @@ -61,6 +61,7 @@ use Friendica\Security\OAuth; use Friendica\Util\DateTimeFormat; use Friendica\Util\Images; use Friendica\Util\Network; +use Friendica\Util\Proxy; use Friendica\Util\Strings; use Friendica\Util\XML; @@ -614,10 +615,10 @@ function api_get_user(App $a, $contact_id = null) 'screen_name' => (($contact['nick']) ? $contact['nick'] : $contact['name']), 'location' => ($contact["location"] != "") ? $contact["location"] : ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol']), 'description' => BBCode::toPlaintext($contact["about"] ?? ''), - 'profile_image_url' => $contact["micro"], - 'profile_image_url_https' => $contact["micro"], - 'profile_image_url_profile_size' => $contact["thumb"], - 'profile_image_url_large' => $contact["photo"], + 'profile_image_url' => Contact::getAvatarUrlForUrl($contact['url'], api_user(), Proxy::SIZE_MICRO), + 'profile_image_url_https' => Contact::getAvatarUrlForUrl($contact['url'], api_user(), Proxy::SIZE_MICRO), + 'profile_image_url_profile_size' => Contact::getAvatarUrlForUrl($contact['url'], api_user(), Proxy::SIZE_THUMB), + 'profile_image_url_large' => Contact::getAvatarUrlForUrl($contact['url'], api_user(), Proxy::SIZE_SMALL), 'url' => $contact["url"], 'protected' => false, 'followers_count' => 0, @@ -688,10 +689,10 @@ function api_get_user(App $a, $contact_id = null) 'screen_name' => (($uinfo[0]['nick']) ? $uinfo[0]['nick'] : $uinfo[0]['name']), 'location' => $location, 'description' => BBCode::toPlaintext($description ?? ''), - 'profile_image_url' => $uinfo[0]['micro'], - 'profile_image_url_https' => $uinfo[0]['micro'], - 'profile_image_url_profile_size' => $uinfo[0]["thumb"], - 'profile_image_url_large' => $uinfo[0]["photo"], + 'profile_image_url' => Contact::getAvatarUrlForUrl($uinfo[0]['url'], api_user(), Proxy::SIZE_MICRO), + 'profile_image_url_https' => Contact::getAvatarUrlForUrl($uinfo[0]['url'], api_user(), Proxy::SIZE_MICRO), + 'profile_image_url_profile_size' => Contact::getAvatarUrlForUrl($uinfo[0]['url'], api_user(), Proxy::SIZE_THUMB), + 'profile_image_url_large' => Contact::getAvatarUrlForUrl($uinfo[0]['url'], api_user(), Proxy::SIZE_SMALL), 'url' => $uinfo[0]['url'], 'protected' => false, 'followers_count' => intval($countfollowers), @@ -1983,7 +1984,7 @@ function api_conversation_show($type) // 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]); if (!DBA::isResult($item)) { - throw new BadRequestException("There is no status with this id."); + throw new BadRequestException("There is no status with the id $id."); } $parent = Post::selectFirst(['id'], ['uri-id' => $item['parent-uri-id'], 'uid' => [0, api_user()]], ['order' => ['uid' => true]]); diff --git a/mod/api.php b/src/Module/Api/Friendica/Index.php similarity index 59% rename from mod/api.php rename to src/Module/Api/Friendica/Index.php index 0a801a8a1e..8891d218a9 100644 --- a/mod/api.php +++ b/src/Module/Api/Friendica/Index.php @@ -2,7 +2,7 @@ /** * @copyright Copyright (C) 2010-2021, the Friendica project * - * @license GNU AGPL version 3 or any later version + * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,21 +19,31 @@ * */ -use Friendica\App; +namespace Friendica\Module\Api\Friendica; + use Friendica\DI; +use Friendica\Module\BaseApi; -require_once __DIR__ . '/../include/api.php'; - -function api_post(App $a) +/** + * api/friendica + * + * @package Friendica\Module\Api\Friendica + */ +class Index extends BaseApi { - if (!$a->isLoggedIn()) { - notice(DI::l10n()->t('Permission denied.')); - return; + public static function post(array $parameters = []) + { + self::checkAllowedScope(self::SCOPE_WRITE); + } + + public static function delete(array $parameters = []) + { + self::checkAllowedScope(self::SCOPE_WRITE); + } + + public static function rawContent(array $parameters = []) + { + echo api_call(DI::app()); + exit(); } } - -function api_content(App $a) -{ - echo api_call($a); - exit(); -} diff --git a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php index a00d51a605..ca0141691b 100644 --- a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php +++ b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php @@ -21,6 +21,7 @@ namespace Friendica\Module\Api\Mastodon\Timelines; +use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\System; use Friendica\Database\DBA; @@ -100,7 +101,11 @@ class PublicTimeline extends BaseApi $statuses = []; while ($item = Post::fetch($items)) { self::setBoundaries($item['uri-id']); - $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); + try { + $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid); + } catch (\Throwable $th) { + Logger::info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'error' => $th]); + } } DBA::close($items); diff --git a/static/routes.config.php b/static/routes.config.php index d1f11567a2..6c786ab1d3 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -40,6 +40,118 @@ $profileRoutes = [ '/media' => [Module\Profile\Media::class, [R::GET]], ]; +$apiRoutes = [ + '/account' => [ + '/verify_credentials[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/rate_limit_status[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/update_profile[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/update_profile_image[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + ], + + '/blocks/list[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/conversation/show[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/direct_messages' => [ + '/all[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/conversation[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/destroy[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::DELETE, R::POST]], + '/new[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/sent[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + ], + '/direct_messages[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET, R::POST]], + + '/externalprofile/show[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/favorites/create[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/favorites/destroy[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class , [R::DELETE, R::POST]], + '/favorites[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/followers/ids[.{extension:json|xml|rss|atom}]' => [Module\Api\Twitter\FollowersIds::class, [R::GET ]], + '/followers/list[.{extension:json|xml|rss|atom}]' => [Module\Api\Twitter\FollowersList::class, [R::GET ]], + '/friends/ids[.{extension:json|xml|rss|atom}]' => [Module\Api\Twitter\FriendsIds::class, [R::GET ]], + '/friends/list[.{extension:json|xml|rss|atom}]' => [Module\Api\Twitter\FriendsList::class, [R::GET ]], + '/friendships/destroy[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/friendships/incoming[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + + '/friendica' => [ + '/activity/attendmaybe[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/attendno[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/attendyes[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/dislike[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/like[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/unattendmaybe[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/unattendno[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/unattendyes[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/undislike[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/activity/unlike[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/notification/seen[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/notification[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/direct_messages_setseen[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/direct_messages_search[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/events[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Events\Index::class, [R::GET ]], + '/group_show[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/group_create[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/group_delete[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::DELETE ]], + '/group_update[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/profile/show[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Profile\Show::class, [R::GET ]], + '/photoalbum/delete[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::DELETE ]], + '/photoalbum/update[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/photos/list[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/photo/create[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/photo/delete[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::DELETE ]], + '/photo/update[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/photo[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + ], + + '/gnusocial/config[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/gnusocial/version[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/help/test[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + + '/lists' => [ + '/create[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/destroy[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::DELETE, R::POST]], + '/list[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/ownerships[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/statuses[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/subscriptions[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/update[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + ], + + '/media/upload[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/media/metadata/create[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/saved_searches/list[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/search/tweets[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/search[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/statusnet/config[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/statusnet/conversation[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/statusnet/conversation/{id:\d+}[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/statusnet/version[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + + '/statuses' => [ + '/destroy[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::DELETE, R::POST]], + '/followers[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/friends[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/friends_timeline[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/home_timeline[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/mediap[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/mentions[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/mentions_timeline[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/networkpublic_timeline[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/public_timeline[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/replies[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/retweet[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/show[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/show/{id:\d+}[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/update[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/update_with_media[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [ R::POST]], + '/user_timeline[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + ], + + '/users' => [ + '/lookup[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/search[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/show[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + '/show/{id:\d+}[.{extension:json|xml|rss|atom}]' => [Module\Api\Friendica\Index::class, [R::GET ]], + ], +]; + return [ '/' => [Module\Home::class, [R::GET]], @@ -58,6 +170,8 @@ return [ ], '/api' => [ + '' => $apiRoutes, + '/1.1' => $apiRoutes, '/v1' => [ '/accounts' => [Module\Api\Mastodon\Unimplemented::class, [ R::POST]], // not supported '/accounts/{id:\d+}' => [Module\Api\Mastodon\Accounts::class, [R::GET ]], @@ -160,14 +274,6 @@ return [ '/v{version:\d+}' => [ '/search' => [Module\Api\Mastodon\Search::class, [R::GET ]], ], - '/friendica' => [ - '/profile/show' => [Module\Api\Friendica\Profile\Show::class, [R::GET ]], - '/events' => [Module\Api\Friendica\Events\Index::class, [R::GET ]], - ], - '/followers/ids' => [Module\Api\Twitter\FollowersIds::class, [R::GET ]], - '/followers/list' => [Module\Api\Twitter\FollowersList::class, [R::GET ]], - '/friends/ids' => [Module\Api\Twitter\FriendsIds::class, [R::GET ]], - '/friends/list' => [Module\Api\Twitter\FriendsList::class, [R::GET ]], '/meta' => [Module\Api\Mastodon\Unimplemented::class, [R::POST ]], // not supported '/oembed' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], '/proofs' => [Module\Api\Mastodon\Proofs::class, [R::GET ]], // Dummy, not supported