1
0
Fork 0

Merge pull request #11003 from annando/fix-api

Fix legacy API
This commit is contained in:
Hypolite Petovan 2021-11-21 07:55:25 -05:00 committed by GitHub
commit 23c56b108b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 382 additions and 755 deletions

View file

@ -221,101 +221,11 @@ function api_call(App $a, App\Arguments $args = null)
Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString()]); Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString()]);
throw new NotFoundException(); throw new NotFoundException();
} catch (HTTPException $e) { } catch (HTTPException $e) {
Logger::notice(API_LOG_PREFIX . 'got exception', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString(), 'error' => $e]);
DI::apiResponse()->error($e->getCode(), $e->getDescription(), $e->getMessage(), $type); DI::apiResponse()->error($e->getCode(), $e->getDescription(), $e->getMessage(), $type);
} }
} }
/**
* Set values for RSS template
*
* @param array $arr Array to be passed to template
* @param array $user_info User info
* @return array
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @todo find proper type-hints
*/
function api_rss_extra($arr, $user_info)
{
if (is_null($user_info)) {
$uid = BaseApi::getCurrentUserID();
if (empty($uid)) {
throw new ForbiddenException();
}
$user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
}
$arr['$user'] = $user_info;
$arr['$rss'] = [
'alternate' => $user_info['url'],
'self' => DI::baseUrl() . "/" . DI::args()->getQueryString(),
'base' => DI::baseUrl(),
'updated' => DateTimeFormat::utc(null, DateTimeFormat::API),
'atom_updated' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
'language' => $user_info['lang'],
'logo' => DI::baseUrl() . "/images/friendica-32.png",
];
return $arr;
}
/**
* Unique contact to contact url.
*
* @param int $id Contact id
* @return bool|string
* Contact url or False if contact id is unknown
* @throws Exception
*/
function api_unique_id_to_nurl($id)
{
$r = DBA::selectFirst('contact', ['nurl'], ['id' => $id]);
if (DBA::isResult($r)) {
return $r["nurl"];
} else {
return false;
}
}
/**
* return api-formatted array for item's author and owner
*
* @param App $a App
* @param array $item item from db
* @return array(array:author, array:owner)
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_item_get_user(App $a, $item)
{
if (empty($item['author-id'])) {
$item['author-id'] = Contact::getPublicIdByUserId(BaseApi::getCurrentUserID());
}
$status_user = DI::twitterUser()->createFromContactId($item['author-id'], BaseApi::getCurrentUserID())->toArray();
$author_user = $status_user;
$status_user["protected"] = isset($item['private']) && ($item['private'] == Item::PRIVATE);
if (($item['thr-parent'] ?? '') == ($item['uri'] ?? '')) {
if (empty($item['owner-id'])) {
$item['owner-id'] = Contact::getPublicIdByUserId(BaseApi::getCurrentUserID());
}
$owner_user = DI::twitterUser()->createFromContactId($item['owner-id'], BaseApi::getCurrentUserID())->toArray();
} else {
$owner_user = $author_user;
}
return ([$status_user, $author_user, $owner_user]);
}
/** /**
* TWITTER API * TWITTER API
*/ */
@ -337,6 +247,7 @@ function api_item_get_user(App $a, $item)
function api_account_verify_credentials($type) function api_account_verify_credentials($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
unset($_REQUEST['user_id']); unset($_REQUEST['user_id']);
unset($_GET['user_id']); unset($_GET['user_id']);
@ -346,7 +257,7 @@ function api_account_verify_credentials($type)
$skip_status = $_REQUEST['skip_status'] ?? false; $skip_status = $_REQUEST['skip_status'] ?? false;
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $user_info = DI::twitterUser()->createFromUserId($uid, $skip_status)->toArray();
// "verified" isn't used here in the standard // "verified" isn't used here in the standard
unset($user_info["verified"]); unset($user_info["verified"]);
@ -360,8 +271,8 @@ function api_account_verify_credentials($type)
} }
// "uid" and "self" are only needed for some internal stuff, so remove it from here // "uid" and "self" are only needed for some internal stuff, so remove it from here
unset($user_info["uid"]); unset($user_info['uid']);
unset($user_info["self"]); unset($user_info['self']);
return DI::apiResponse()->formatData("user", $type, ['user' => $user_info]); return DI::apiResponse()->formatData("user", $type, ['user' => $user_info]);
} }
@ -400,17 +311,14 @@ function requestdata($k)
*/ */
function api_statuses_mediap($type) function api_statuses_mediap($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
$a = DI::app(); $a = DI::app();
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); $_REQUEST['profile_uid'] = $uid;
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$_REQUEST['profile_uid'] = BaseApi::getCurrentUserID();
$_REQUEST['api_source'] = true; $_REQUEST['api_source'] = true;
$txt = requestdata('status') ?? ''; $txt = requestdata('status') ?? '';
/// @TODO old-lost code?
//$txt = urldecode(requestdata('status'));
if ((strpos($txt, '<') !== false) || (strpos($txt, '>') !== false)) { if ((strpos($txt, '<') !== false) || (strpos($txt, '>') !== false)) {
$txt = HTML::toBBCodeVideo($txt); $txt = HTML::toBBCodeVideo($txt);
@ -421,8 +329,6 @@ function api_statuses_mediap($type)
} }
$txt = HTML::toBBCode($txt); $txt = HTML::toBBCode($txt);
DI::args()->getArgv()[1] = $user_info['screen_name']; //should be set to username?
$picture = wall_upload_post($a, false); $picture = wall_upload_post($a, false);
// now that we have the img url in bbcode we can add it to the status and insert the wall item. // now that we have the img url in bbcode we can add it to the status and insert the wall item.
@ -452,9 +358,10 @@ api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD
*/ */
function api_statuses_update($type) function api_statuses_update($type)
{ {
$a = DI::app();
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
$a = DI::app();
// convert $_POST array items to the form we use for web posts. // convert $_POST array items to the form we use for web posts.
if (requestdata('htmlstatus')) { if (requestdata('htmlstatus')) {
@ -492,7 +399,7 @@ function api_statuses_update($type)
if (requestdata('lat') && requestdata('long')) { if (requestdata('lat') && requestdata('long')) {
$_REQUEST['coord'] = sprintf("%s %s", requestdata('lat'), requestdata('long')); $_REQUEST['coord'] = sprintf("%s %s", requestdata('lat'), requestdata('long'));
} }
$_REQUEST['profile_uid'] = BaseApi::getCurrentUserID(); $_REQUEST['profile_uid'] = $uid;
if (!$parent) { if (!$parent) {
// Check for throttling (maximum posts per day, week and month) // Check for throttling (maximum posts per day, week and month)
@ -500,11 +407,11 @@ function api_statuses_update($type)
if ($throttle_day > 0) { if ($throttle_day > 0) {
$datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60); $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60);
$condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, BaseApi::getCurrentUserID(), $datefrom]; $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, $uid, $datefrom];
$posts_day = Post::count($condition); $posts_day = Post::count($condition);
if ($posts_day > $throttle_day) { if ($posts_day > $throttle_day) {
logger::info('Daily posting limit reached for user '.BaseApi::getCurrentUserID()); logger::info('Daily posting limit reached for user ' . $uid);
// die(api_error($type, DI::l10n()->t("Daily posting limit of %d posts reached. The post was rejected.", $throttle_day)); // die(api_error($type, DI::l10n()->t("Daily posting limit of %d posts reached. The post was rejected.", $throttle_day));
throw new TooManyRequestsException(DI::l10n()->tt("Daily posting limit of %d post reached. The post was rejected.", "Daily posting limit of %d posts reached. The post was rejected.", $throttle_day)); throw new TooManyRequestsException(DI::l10n()->tt("Daily posting limit of %d post reached. The post was rejected.", "Daily posting limit of %d posts reached. The post was rejected.", $throttle_day));
} }
@ -514,11 +421,11 @@ function api_statuses_update($type)
if ($throttle_week > 0) { if ($throttle_week > 0) {
$datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7); $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7);
$condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, BaseApi::getCurrentUserID(), $datefrom]; $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, $uid, $datefrom];
$posts_week = Post::count($condition); $posts_week = Post::count($condition);
if ($posts_week > $throttle_week) { if ($posts_week > $throttle_week) {
logger::info('Weekly posting limit reached for user '.BaseApi::getCurrentUserID()); logger::info('Weekly posting limit reached for user ' . $uid);
// die(api_error($type, DI::l10n()->t("Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week))); // die(api_error($type, DI::l10n()->t("Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week)));
throw new TooManyRequestsException(DI::l10n()->tt("Weekly posting limit of %d post reached. The post was rejected.", "Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week)); throw new TooManyRequestsException(DI::l10n()->tt("Weekly posting limit of %d post reached. The post was rejected.", "Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week));
} }
@ -528,11 +435,11 @@ function api_statuses_update($type)
if ($throttle_month > 0) { if ($throttle_month > 0) {
$datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30); $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30);
$condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, BaseApi::getCurrentUserID(), $datefrom]; $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, $uid, $datefrom];
$posts_month = Post::count($condition); $posts_month = Post::count($condition);
if ($posts_month > $throttle_month) { if ($posts_month > $throttle_month) {
logger::info('Monthly posting limit reached for user '.BaseApi::getCurrentUserID()); logger::info('Monthly posting limit reached for user ' . $uid);
// die(api_error($type, DI::l10n()->t("Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month)); // die(api_error($type, DI::l10n()->t("Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month));
throw new TooManyRequestsException(DI::l10n()->t("Monthly posting limit of %d post reached. The post was rejected.", "Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month)); throw new TooManyRequestsException(DI::l10n()->t("Monthly posting limit of %d post reached. The post was rejected.", "Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month));
} }
@ -557,7 +464,7 @@ function api_statuses_update($type)
$media = DBA::toArray(DBA::p("SELECT `resource-id`, `scale`, `nickname`, `type`, `desc`, `filename`, `datasize`, `width`, `height` FROM `photo` $media = DBA::toArray(DBA::p("SELECT `resource-id`, `scale`, `nickname`, `type`, `desc`, `filename`, `datasize`, `width`, `height` FROM `photo`
INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN
(SELECT `resource-id` FROM `photo` WHERE `id` = ?) AND `photo`.`uid` = ? (SELECT `resource-id` FROM `photo` WHERE `id` = ?) AND `photo`.`uid` = ?
ORDER BY `photo`.`width` DESC LIMIT 2", $id, BaseApi::getCurrentUserID())); ORDER BY `photo`.`width` DESC LIMIT 2", $id, $uid));
if (!empty($media)) { if (!empty($media)) {
$ressources[] = $media[0]['resource-id']; $ressources[] = $media[0]['resource-id'];
@ -605,7 +512,7 @@ function api_statuses_update($type)
if (!empty($ressources) && !empty($item_id)) { if (!empty($ressources) && !empty($item_id)) {
$item = Post::selectFirst(['uri-id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'], ['id' => $item_id]); $item = Post::selectFirst(['uri-id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'], ['id' => $item_id]);
foreach ($ressources as $ressource) { foreach ($ressources as $ressource) {
Photo::setPermissionForRessource($ressource, BaseApi::getCurrentUserID(), $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']); Photo::setPermissionForRessource($ressource, $uid, $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
} }
} }
@ -630,8 +537,6 @@ api_register_func('api/statuses/update_with_media', 'api_statuses_update', true,
*/ */
function api_media_upload() function api_media_upload()
{ {
$a = DI::app();
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
if (empty($_FILES['media'])) { if (empty($_FILES['media'])) {
@ -639,7 +544,7 @@ function api_media_upload()
throw new BadRequestException("No media."); throw new BadRequestException("No media.");
} }
$media = wall_upload_post($a, false); $media = wall_upload_post(DI::app(), false);
if (!$media) { if (!$media) {
// Output error // Output error
throw new InternalServerErrorException(); throw new InternalServerErrorException();
@ -681,6 +586,7 @@ api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST)
function api_media_metadata_create($type) function api_media_metadata_create($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
$postdata = Network::postdata(); $postdata = Network::postdata();
@ -703,7 +609,7 @@ function api_media_metadata_create($type)
Logger::info('Updating metadata', ['media_id' => $data['media_id']]); Logger::info('Updating metadata', ['media_id' => $data['media_id']]);
$condition = ['id' => $data['media_id'], 'uid' => BaseApi::getCurrentUserID()]; $condition = ['id' => $data['media_id'], 'uid' => $uid];
$photo = DBA::selectFirst('photo', ['resource-id'], $condition); $photo = DBA::selectFirst('photo', ['resource-id'], $condition);
if (!DBA::isResult($photo)) { if (!DBA::isResult($photo)) {
throw new BadRequestException("Metadata not found."); throw new BadRequestException("Metadata not found.");
@ -787,8 +693,9 @@ function api_get_item(array $condition)
function api_users_show($type) function api_users_show($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
$item = api_get_last_status($user_info['pid'], $user_info['uid']); $item = api_get_last_status($user_info['pid'], $user_info['uid']);
if (!empty($item)) { if (!empty($item)) {
@ -820,6 +727,9 @@ api_register_func('api/externalprofile/show', 'api_users_show');
*/ */
function api_users_search($type) function api_users_search($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$userlist = []; $userlist = [];
if (!empty($_GET['q'])) { if (!empty($_GET['q'])) {
@ -837,7 +747,7 @@ function api_users_search($type)
if (DBA::isResult($contacts)) { if (DBA::isResult($contacts)) {
$k = 0; $k = 0;
foreach ($contacts as $contact) { foreach ($contacts as $contact) {
$user_info = DI::twitterUser()->createFromContactId($contact['id'], BaseApi::getCurrentUserID())->toArray(); $user_info = DI::twitterUser()->createFromContactId($contact['id'], $uid)->toArray();
if ($type == 'xml') { if ($type == 'xml') {
$userlist[$k++ . ':user'] = $user_info; $userlist[$k++ . ':user'] = $user_info;
@ -875,15 +785,15 @@ api_register_func('api/users/search', 'api_users_search');
*/ */
function api_users_lookup($type) function api_users_lookup($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$users = []; $users = [];
if (!empty($_REQUEST['user_id'])) { if (!empty($_REQUEST['user_id'])) {
foreach (explode(',', $_REQUEST['user_id']) as $id) { foreach (explode(',', $_REQUEST['user_id']) as $cid) {
if (!empty($id)) { if (!empty($cid) && is_numeric($cid)) {
$cid = BaseApi::getContactIDForSearchterm($id); $users[] = DI::twitterUser()->createFromContactId((int)$cid, $uid)->toArray();
if (!empty($cid)) {
$users[] = DI::twitterUser()->createFromContactId($cid, BaseApi::getCurrentUserID())->toArray();
}
} }
} }
} }
@ -915,8 +825,7 @@ api_register_func('api/users/lookup', 'api_users_lookup', true);
function api_search($type) function api_search($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
if (empty($_REQUEST['q'])) { if (empty($_REQUEST['q'])) {
throw new BadRequestException('q parameter is required.'); throw new BadRequestException('q parameter is required.');
@ -943,7 +852,7 @@ function api_search($type)
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) { if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) {
$searchTerm = $matches[1]; $searchTerm = $matches[1];
$condition = ["`iid` > ? AND `name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $since_id, $searchTerm, BaseApi::getCurrentUserID()]; $condition = ["`iid` > ? AND `name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $since_id, $searchTerm, $uid];
$tags = DBA::select('tag-search-view', ['uri-id'], $condition); $tags = DBA::select('tag-search-view', ['uri-id'], $condition);
$uriids = []; $uriids = [];
while ($tag = DBA::fetch($tags)) { while ($tag = DBA::fetch($tags)) {
@ -966,7 +875,7 @@ function api_search($type)
" . ($exclude_replies ? " AND `gravity` = " . GRAVITY_PARENT : ' ') . " " . ($exclude_replies ? " AND `gravity` = " . GRAVITY_PARENT : ' ') . "
AND (`uid` = 0 OR (`uid` = ? AND NOT `global`)) AND (`uid` = 0 OR (`uid` = ? AND NOT `global`))
AND `body` LIKE CONCAT('%',?,'%')", AND `body` LIKE CONCAT('%',?,'%')",
$since_id, BaseApi::getCurrentUserID(), $_REQUEST['q']]; $since_id, $uid, $_REQUEST['q']];
if ($max_id > 0) { if ($max_id > 0) {
$condition[0] .= ' AND `id` <= ?'; $condition[0] .= ' AND `id` <= ?';
$condition[] = $max_id; $condition[] = $max_id;
@ -976,7 +885,7 @@ function api_search($type)
$statuses = []; $statuses = [];
if (parse_url($searchTerm, PHP_URL_SCHEME) != '') { if (parse_url($searchTerm, PHP_URL_SCHEME) != '') {
$id = Item::fetchByLink($searchTerm, BaseApi::getCurrentUserID()); $id = Item::fetchByLink($searchTerm, $uid);
if (!$id) { if (!$id) {
// Public post // Public post
$id = Item::fetchByLink($searchTerm); $id = Item::fetchByLink($searchTerm);
@ -987,11 +896,15 @@ function api_search($type)
} }
} }
$statuses = $statuses ?: Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = $statuses ?: Post::selectForUser($uid, [], $condition, $params);
$data['status'] = api_format_items(Post::toArray($statuses), $user_info); $ret = [];
while ($status = DBA::fetch($statuses)) {
$ret[] = api_format_item($status, $type);
}
DBA::close($statuses);
bindComments($data['status']); $data['status'] = $ret;
return DI::apiResponse()->formatData('statuses', $type, $data); return DI::apiResponse()->formatData('statuses', $type, $data);
} }
@ -1019,8 +932,7 @@ api_register_func('api/search', 'api_search', true);
function api_statuses_home_timeline($type) function api_statuses_home_timeline($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
unset($_REQUEST['user_id']); unset($_REQUEST['user_id']);
unset($_GET['user_id']); unset($_GET['user_id']);
@ -1041,7 +953,7 @@ function api_statuses_home_timeline($type)
$start = max(0, ($page - 1) * $count); $start = max(0, ($page - 1) * $count);
$condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ?", $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ?",
BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
if ($max_id > 0) { if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?"; $condition[0] .= " AND `id` <= ?";
@ -1057,17 +969,15 @@ function api_statuses_home_timeline($type)
} }
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
$items = Post::toArray($statuses); $ret = [];
$ret = api_format_items($items, $user_info, false, $type);
// Set all posts from the query above to seen
$idarray = []; $idarray = [];
foreach ($items as $item) { while ($status = DBA::fetch($statuses)) {
$idarray[] = intval($item["id"]); $ret[] = api_format_item($status, $type);
$idarray[] = intval($status['id']);
} }
DBA::close($statuses);
if (!empty($idarray)) { if (!empty($idarray)) {
$unseen = Post::exists(['unseen' => true, 'id' => $idarray]); $unseen = Post::exists(['unseen' => true, 'id' => $idarray]);
@ -1076,18 +986,7 @@ function api_statuses_home_timeline($type)
} }
} }
bindComments($ret); return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
$data = ['status' => $ret];
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
}
return DI::apiResponse()->formatData("statuses", $type, $data);
} }
@ -1110,8 +1009,7 @@ api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline',
function api_statuses_public_timeline($type) function api_statuses_public_timeline($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
// get last network messages // get last network messages
@ -1135,9 +1033,7 @@ function api_statuses_public_timeline($type)
} }
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
$r = Post::toArray($statuses);
} else { } else {
$condition = ["`gravity` IN (?, ?) AND `id` > ? AND `private` = ? AND `wall` AND `origin` AND NOT `author-hidden`", $condition = ["`gravity` IN (?, ?) AND `id` > ? AND `private` = ? AND `wall` AND `origin` AND NOT `author-hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC]; GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
@ -1152,25 +1048,16 @@ function api_statuses_public_timeline($type)
} }
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
$r = Post::toArray($statuses);
} }
$ret = api_format_items($r, $user_info, false, $type); $ret = [];
while ($status = DBA::fetch($statuses)) {
bindComments($ret); $ret[] = api_format_item($status, $type);
$data = ['status' => $ret];
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
} }
DBA::close($statuses);
return DI::apiResponse()->formatData("statuses", $type, $data); return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -1190,11 +1077,10 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline'
function api_statuses_networkpublic_timeline($type) function api_statuses_networkpublic_timeline($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $since_id = $_REQUEST['since_id'] ?? 0;
$max_id = $_REQUEST['max_id'] ?? 0;
$since_id = $_REQUEST['since_id'] ?? 0;
$max_id = $_REQUEST['max_id'] ?? 0;
// pagination // pagination
$count = $_REQUEST['count'] ?? 20; $count = $_REQUEST['count'] ?? 20;
@ -1211,22 +1097,15 @@ function api_statuses_networkpublic_timeline($type)
} }
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::toArray(Post::selectForUser(BaseApi::getCurrentUserID(), Item::DISPLAY_FIELDLIST, $condition, $params)); $statuses = Post::selectForUser($uid, Item::DISPLAY_FIELDLIST, $condition, $params);
$ret = api_format_items($statuses, $user_info, false, $type); $ret = [];
while ($status = DBA::fetch($statuses)) {
bindComments($ret); $ret[] = api_format_item($status, $type);
$data = ['status' => $ret];
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
} }
DBA::close($statuses);
return DI::apiResponse()->formatData("statuses", $type, $data); return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -1248,8 +1127,7 @@ api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpu
function api_statuses_show($type) function api_statuses_show($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
// params // params
$id = intval(DI::args()->getArgv()[3] ?? 0); $id = intval(DI::args()->getArgv()[3] ?? 0);
@ -1273,7 +1151,7 @@ function api_statuses_show($type)
throw new BadRequestException(sprintf("There is no status with the id %d", $id)); 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, BaseApi::getCurrentUserID()]], ['order' => ['uid' => true]]); $item = Post::selectFirst(['id'], ['uri-id' => $uri_item['uri-id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (!DBA::isResult($item)) { 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.", $uri_item['uri-id']));
} }
@ -1288,14 +1166,18 @@ function api_statuses_show($type)
$params = []; $params = [];
} }
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
/// @TODO How about copying this to above methods which don't check $r ? /// @TODO How about copying this to above methods which don't check $r ?
if (!DBA::isResult($statuses)) { if (!DBA::isResult($statuses)) {
throw new BadRequestException(sprintf("There is no status or conversation with the id %d.", $id)); throw new BadRequestException(sprintf("There is no status or conversation with the id %d.", $id));
} }
$ret = api_format_items(Post::toArray($statuses), $user_info, false, $type); $ret = [];
while ($status = DBA::fetch($statuses)) {
$ret[] = api_format_item($status, $type);
}
DBA::close($statuses);
if ($conversation) { if ($conversation) {
$data = ['status' => $ret]; $data = ['status' => $ret];
@ -1324,8 +1206,7 @@ api_register_func('api/statuses/show', 'api_statuses_show', true);
function api_conversation_show($type) function api_conversation_show($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
// params // params
$id = intval(DI::args()->getArgv()[3] ?? 0); $id = intval(DI::args()->getArgv()[3] ?? 0);
@ -1353,7 +1234,7 @@ function api_conversation_show($type)
throw new BadRequestException("There is no status with the id $id."); throw new BadRequestException("There is no status with the id $id.");
} }
$parent = Post::selectFirst(['id'], ['uri-id' => $item['parent-uri-id'], 'uid' => [0, BaseApi::getCurrentUserID()]], ['order' => ['uid' => true]]); $parent = Post::selectFirst(['id'], ['uri-id' => $item['parent-uri-id'], 'uid' => [0, $uid]], ['order' => ['uid' => true]]);
if (!DBA::isResult($parent)) { if (!DBA::isResult($parent)) {
throw new BadRequestException("There is no status with this id."); throw new BadRequestException("There is no status with this id.");
} }
@ -1361,7 +1242,7 @@ function api_conversation_show($type)
$id = $parent['id']; $id = $parent['id'];
$condition = ["`parent` = ? AND `uid` IN (0, ?) AND `gravity` IN (?, ?) AND `id` > ?", $condition = ["`parent` = ? AND `uid` IN (0, ?) AND `gravity` IN (?, ?) AND `id` > ?",
$id, BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; $id, $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
if ($max_id > 0) { if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?"; $condition[0] .= " AND `id` <= ?";
@ -1369,13 +1250,17 @@ function api_conversation_show($type)
} }
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
if (!DBA::isResult($statuses)) { if (!DBA::isResult($statuses)) {
throw new BadRequestException("There is no status with id $id."); throw new BadRequestException("There is no status with id $id.");
} }
$ret = api_format_items(Post::toArray($statuses), $user_info, false, $type); $ret = [];
while ($status = DBA::fetch($statuses)) {
$ret[] = api_format_item($status, $type);
}
DBA::close($statuses);
$data = ['status' => $ret]; $data = ['status' => $ret];
return DI::apiResponse()->formatData("statuses", $type, $data); return DI::apiResponse()->formatData("statuses", $type, $data);
@ -1400,9 +1285,8 @@ api_register_func('api/statusnet/conversation', 'api_conversation_show', true);
*/ */
function api_statuses_repeat($type) function api_statuses_repeat($type)
{ {
$a = DI::app();
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params // params
$id = intval(DI::args()->getArgv()[3] ?? 0); $id = intval(DI::args()->getArgv()[3] ?? 0);
@ -1423,7 +1307,7 @@ function api_statuses_repeat($type)
if (DBA::isResult($item) && !empty($item['body'])) { if (DBA::isResult($item) && !empty($item['body'])) {
if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::TWITTER])) { if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::TWITTER])) {
if (!Item::performActivity($id, 'announce', BaseApi::getCurrentUserID())) { if (!Item::performActivity($id, 'announce', $uid)) {
throw new InternalServerErrorException(); throw new InternalServerErrorException();
} }
@ -1443,14 +1327,14 @@ function api_statuses_repeat($type)
$post .= "[/share]"; $post .= "[/share]";
} }
$_REQUEST['body'] = $post; $_REQUEST['body'] = $post;
$_REQUEST['profile_uid'] = BaseApi::getCurrentUserID(); $_REQUEST['profile_uid'] = $uid;
$_REQUEST['api_source'] = true; $_REQUEST['api_source'] = true;
if (empty($_REQUEST['source'])) { if (empty($_REQUEST['source'])) {
$_REQUEST['source'] = api_source(); $_REQUEST['source'] = api_source();
} }
$item_id = item_post($a); $item_id = item_post(DI::app());
} }
} else { } else {
throw new ForbiddenException(); throw new ForbiddenException();
@ -1479,6 +1363,7 @@ api_register_func('api/statuses/retweet', 'api_statuses_repeat', true, API_METHO
function api_statuses_destroy($type) function api_statuses_destroy($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params // params
$id = intval(DI::args()->getArgv()[3] ?? 0); $id = intval(DI::args()->getArgv()[3] ?? 0);
@ -1496,7 +1381,7 @@ function api_statuses_destroy($type)
$ret = api_statuses_show($type); $ret = api_statuses_show($type);
Item::deleteForUser(['id' => $id], BaseApi::getCurrentUserID()); Item::deleteForUser(['id' => $id], $uid);
return $ret; return $ret;
} }
@ -1520,8 +1405,7 @@ api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METH
function api_statuses_mentions($type) function api_statuses_mentions($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
unset($_REQUEST['user_id']); unset($_REQUEST['user_id']);
unset($_GET['user_id']); unset($_GET['user_id']);
@ -1545,11 +1429,11 @@ function api_statuses_mentions($type)
$condition = [ $condition = [
GRAVITY_PARENT, GRAVITY_COMMENT, GRAVITY_PARENT, GRAVITY_COMMENT,
BaseApi::getCurrentUserID(), $uid,
Post\UserNotification::TYPE_EXPLICIT_TAGGED | Post\UserNotification::TYPE_IMPLICIT_TAGGED | Post\UserNotification::TYPE_EXPLICIT_TAGGED | Post\UserNotification::TYPE_IMPLICIT_TAGGED |
Post\UserNotification::TYPE_THREAD_COMMENT | Post\UserNotification::TYPE_DIRECT_COMMENT | Post\UserNotification::TYPE_THREAD_COMMENT | Post\UserNotification::TYPE_DIRECT_COMMENT |
Post\UserNotification::TYPE_DIRECT_THREAD_COMMENT, Post\UserNotification::TYPE_DIRECT_THREAD_COMMENT,
BaseApi::getCurrentUserID(), $since_id, $uid, $since_id,
]; ];
if ($max_id > 0) { if ($max_id > 0) {
@ -1560,20 +1444,15 @@ function api_statuses_mentions($type)
array_unshift($condition, $query); array_unshift($condition, $query);
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
$ret = api_format_items(Post::toArray($statuses), $user_info, false, $type); $ret = [];
while ($status = DBA::fetch($statuses)) {
$data = ['status' => $ret]; $ret[] = api_format_item($status, $type);
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
} }
DBA::close($statuses);
return DI::apiResponse()->formatData("statuses", $type, $data); return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -1595,11 +1474,11 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true);
function api_statuses_user_timeline($type) function api_statuses_user_timeline($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); Logger::info('api_statuses_user_timeline', ['api_user' => $uid, '_REQUEST' => $_REQUEST]);
Logger::info('api_statuses_user_timeline', ['api_user' => BaseApi::getCurrentUserID(), 'user_info' => $user_info, '_REQUEST' => $_REQUEST]);
$cid = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['user_id'] ?? 0, $uid);
$since_id = $_REQUEST['since_id'] ?? 0; $since_id = $_REQUEST['since_id'] ?? 0;
$max_id = $_REQUEST['max_id'] ?? 0; $max_id = $_REQUEST['max_id'] ?? 0;
$exclude_replies = !empty($_REQUEST['exclude_replies']); $exclude_replies = !empty($_REQUEST['exclude_replies']);
@ -1611,12 +1490,8 @@ function api_statuses_user_timeline($type)
$start = max(0, ($page - 1) * $count); $start = max(0, ($page - 1) * $count);
$condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `contact-id` = ?", $condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`)) AND `gravity` IN (?, ?) AND `id` > ? AND `author-id` = ?",
BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $user_info['cid']]; 0, $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $cid];
if ($user_info['self'] == 1) {
$condition[0] .= ' AND `wall` ';
}
if ($exclude_replies) { if ($exclude_replies) {
$condition[0] .= ' AND `gravity` = ?'; $condition[0] .= ' AND `gravity` = ?';
@ -1633,22 +1508,15 @@ function api_statuses_user_timeline($type)
$condition[] = $max_id; $condition[] = $max_id;
} }
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
$ret = api_format_items(Post::toArray($statuses), $user_info, true, $type); $ret = [];
while ($status = DBA::fetch($statuses)) {
bindComments($ret); $ret[] = api_format_item($status, $type);
$data = ['status' => $ret];
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
} }
DBA::close($statuses);
return DI::apiResponse()->formatData("statuses", $type, $data); return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -1671,6 +1539,7 @@ api_register_func('api/statuses/user_timeline', 'api_statuses_user_timeline', tr
function api_favorites_create_destroy($type) function api_favorites_create_destroy($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// for versioned api. // for versioned api.
/// @TODO We need a better global soluton /// @TODO We need a better global soluton
@ -1689,7 +1558,7 @@ function api_favorites_create_destroy($type)
$itemid = intval($_REQUEST['id'] ?? 0); $itemid = intval($_REQUEST['id'] ?? 0);
} }
$item = Post::selectFirstForUser(BaseApi::getCurrentUserID(), [], ['id' => $itemid, 'uid' => BaseApi::getCurrentUserID()]); $item = Post::selectFirstForUser($uid, [], ['id' => $itemid, 'uid' => $uid]);
if (!DBA::isResult($item)) { if (!DBA::isResult($item)) {
throw new BadRequestException("Invalid item."); throw new BadRequestException("Invalid item.");
@ -1712,20 +1581,9 @@ function api_favorites_create_destroy($type)
throw new InternalServerErrorException("DB error"); throw new InternalServerErrorException("DB error");
} }
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $ret = api_format_item($item, $type);
$rets = api_format_items([$item], $user_info, false, $type);
$ret = $rets[0];
$data = ['status' => $ret]; return DI::apiResponse()->formatData("status", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
}
return DI::apiResponse()->formatData("status", $type, $data);
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -1747,51 +1605,39 @@ api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true,
function api_favorites($type) function api_favorites($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
// in friendica starred item are private // in friendica starred item are private
// return favorites only for self // return favorites only for self
Logger::info(API_LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites', 'self' => $user_info['self']]); Logger::info(API_LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites']);
if ($user_info['self'] == 0) { // params
$ret = []; $since_id = $_REQUEST['since_id'] ?? 0;
} else { $max_id = $_REQUEST['max_id'] ?? 0;
// params $count = $_GET['count'] ?? 20;
$since_id = $_REQUEST['since_id'] ?? 0; $page = $_REQUEST['page'] ?? 1;
$max_id = $_REQUEST['max_id'] ?? 0;
$count = $_GET['count'] ?? 20;
$page = $_REQUEST['page'] ?? 1;
$start = max(0, ($page - 1) * $count); $start = max(0, ($page - 1) * $count);
$condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `starred`", $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `starred`",
BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; $uid, GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
if ($max_id > 0) { if ($max_id > 0) {
$condition[0] .= " AND `id` <= ?"; $condition[0] .= " AND `id` <= ?";
$condition[] = $max_id; $condition[] = $max_id;
}
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params);
$ret = api_format_items(Post::toArray($statuses), $user_info, false, $type);
} }
bindComments($ret); $statuses = Post::selectForUser($uid, [], $condition, $params);
$data = ['status' => $ret]; $ret = [];
switch ($type) { while ($status = DBA::fetch($statuses)) {
case "atom": $ret[] = api_format_item($status, $type);
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
} }
DBA::close($statuses);
return DI::apiResponse()->formatData("statuses", $type, $data); return DI::apiResponse()->formatData("statuses", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -2230,7 +2076,7 @@ function api_format_items_activities($item, $type = "json")
//builtin_activity_puller($i, $activities); //builtin_activity_puller($i, $activities);
// get user data and add it to the array of the activity // get user data and add it to the array of the activity
$user = DI::twitterUser()->createFromContactId($parent_item['author-id'], BaseApi::getCurrentUserID())->toArray(); $user = DI::twitterUser()->createFromContactId($parent_item['author-id'], $item['uid'])->toArray();
switch ($parent_item['verb']) { switch ($parent_item['verb']) {
case Activity::LIKE: case Activity::LIKE:
$activities['like'][] = $user; $activities['like'][] = $user;
@ -2274,45 +2120,6 @@ function api_format_items_activities($item, $type = "json")
return $activities; return $activities;
} }
/**
* format items to be returned by api
*
* @param array $items array of items
* @param array $user_info
* @param bool $filter_user filter items by $user_info
* @param string $type Return type (atom, rss, xml, json)
* @return array
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_format_items($items, $user_info, $filter_user = false, $type = "json")
{
$a = DI::app();
$ret = [];
if (empty($items)) {
return $ret;
}
foreach ((array)$items as $item) {
[$status_user, $author_user, $owner_user] = api_item_get_user($a, $item);
// Look if the posts are matching if they should be filtered by user id
if ($filter_user && ($status_user["id"] != $user_info["id"])) {
continue;
}
$status = api_format_item($item, $type, $status_user, $author_user, $owner_user);
$ret[] = $status;
}
return $ret;
}
/** /**
* @param array $item Item record * @param array $item Item record
* @param string $type Return format (atom, rss, xml, json) * @param string $type Return format (atom, rss, xml, json)
@ -2325,13 +2132,10 @@ function api_format_items($items, $user_info, $filter_user = false, $type = "jso
* @throws InternalServerErrorException * @throws InternalServerErrorException
* @throws UnauthorizedException * @throws UnauthorizedException
*/ */
function api_format_item($item, $type = "json", $status_user = null, $author_user = null, $owner_user = null) function api_format_item($item, $type = "json")
{ {
$a = DI::app(); $author_user = DI::twitterUser()->createFromContactId($item['author-id'], $item['uid'])->toArray();
$owner_user = DI::twitterUser()->createFromContactId($item['owner-id'], $item['uid'])->toArray();
if (empty($status_user) || empty($author_user) || empty($owner_user)) {
[$status_user, $author_user, $owner_user] = api_item_get_user($a, $item);
}
DI::contentItem()->localize($item); DI::contentItem()->localize($item);
@ -2359,7 +2163,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
'in_reply_to_screen_name' => $in_reply_to['screen_name'], 'in_reply_to_screen_name' => $in_reply_to['screen_name'],
$geo => null, $geo => null,
'favorited' => $item['starred'] ? true : false, 'favorited' => $item['starred'] ? true : false,
'user' => $status_user, 'user' => $author_user,
'friendica_author' => $author_user, 'friendica_author' => $author_user,
'friendica_owner' => $owner_user, 'friendica_owner' => $owner_user,
'friendica_private' => $item['private'] == Item::PRIVATE, 'friendica_private' => $item['private'] == Item::PRIVATE,
@ -2369,7 +2173,8 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
'external_url' => DI::baseUrl() . "/display/" . $item['guid'], 'external_url' => DI::baseUrl() . "/display/" . $item['guid'],
'friendica_activities' => api_format_items_activities($item, $type), 'friendica_activities' => api_format_items_activities($item, $type),
'friendica_title' => $item['title'], 'friendica_title' => $item['title'],
'friendica_html' => BBCode::convertForUriId($item['uri-id'], $item['body'], BBCode::EXTERNAL) 'friendica_html' => BBCode::convertForUriId($item['uri-id'], $item['body'], BBCode::EXTERNAL),
'friendica_comments' => Post::countPosts(['thr-parent-id' => $item['uri-id'], 'deleted' => false, 'gravity' => GRAVITY_COMMENT])
]; ];
if (count($converted["attachments"]) > 0) { if (count($converted["attachments"]) > 0) {
@ -2394,7 +2199,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
if (!empty($announce)) { if (!empty($announce)) {
$retweeted_item = $item; $retweeted_item = $item;
$item = $announce; $item = $announce;
$status['friendica_owner'] = DI::twitterUser()->createFromContactId($announce['author-id'], BaseApi::getCurrentUserID())->toArray(); $status['friendica_owner'] = DI::twitterUser()->createFromContactId($announce['author-id'], $item['uid'])->toArray();
} }
} }
@ -2413,7 +2218,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
$quoted_status['text'] = $conv_quoted['text']; $quoted_status['text'] = $conv_quoted['text'];
$quoted_status['statusnet_html'] = $conv_quoted['html']; $quoted_status['statusnet_html'] = $conv_quoted['html'];
try { try {
$quoted_status["user"] = DI::twitterUser()->createFromContactId($quoted_item['author-id'], BaseApi::getCurrentUserID())->toArray(); $quoted_status["user"] = DI::twitterUser()->createFromContactId($quoted_item['author-id'], $item['uid'])->toArray();
} catch (BadRequestException $e) { } catch (BadRequestException $e) {
// user not found. should be found? // user not found. should be found?
/// @todo check if the user should be always found /// @todo check if the user should be always found
@ -2435,7 +2240,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
unset($retweeted_status['statusnet_conversation_id']); unset($retweeted_status['statusnet_conversation_id']);
$status['user'] = $status['friendica_owner']; $status['user'] = $status['friendica_owner'];
try { try {
$retweeted_status["user"] = DI::twitterUser()->createFromContactId($retweeted_item['author-id'], BaseApi::getCurrentUserID())->toArray(); $retweeted_status["user"] = DI::twitterUser()->createFromContactId($retweeted_item['author-id'], $item['uid'])->toArray();
} catch (BadRequestException $e) { } catch (BadRequestException $e) {
// user not found. should be found? // user not found. should be found?
/// @todo check if the user should be always found /// @todo check if the user should be always found
@ -2464,8 +2269,8 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
} }
// "uid" and "self" are only needed for some internal stuff, so remove it from here // "uid" and "self" are only needed for some internal stuff, so remove it from here
unset($status["user"]["uid"]); unset($status["user"]['uid']);
unset($status["user"]["self"]); unset($status["user"]['self']);
if ($item["coord"] != "") { if ($item["coord"] != "") {
$coords = explode(' ', $item["coord"]); $coords = explode(' ', $item["coord"]);
@ -2518,10 +2323,10 @@ api_register_func('api/lists/subscriptions', 'api_lists_list', true);
function api_lists_ownerships($type) function api_lists_ownerships($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
$uid = $user_info['uid'];
$groups = DBA::select('group', [], ['deleted' => 0, 'uid' => $uid]); $groups = DBA::select('group', [], ['deleted' => 0, 'uid' => $uid]);
@ -2563,8 +2368,7 @@ api_register_func('api/lists/ownerships', 'api_lists_ownerships', true);
function api_lists_statuses($type) function api_lists_statuses($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
unset($_REQUEST['user_id']); unset($_REQUEST['user_id']);
unset($_GET['user_id']); unset($_GET['user_id']);
@ -2588,7 +2392,7 @@ function api_lists_statuses($type)
$groups = DBA::selectToArray('group_member', ['contact-id'], ['gid' => 1]); $groups = DBA::selectToArray('group_member', ['contact-id'], ['gid' => 1]);
$gids = array_column($groups, 'contact-id'); $gids = array_column($groups, 'contact-id');
$condition = ['uid' => BaseApi::getCurrentUserID(), 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'group-id' => $gids]; $condition = ['uid' => $uid, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'group-id' => $gids];
$condition = DBA::mergeConditions($condition, ["`id` > ?", $since_id]); $condition = DBA::mergeConditions($condition, ["`id` > ?", $since_id]);
if ($max_id > 0) { if ($max_id > 0) {
@ -2605,20 +2409,15 @@ function api_lists_statuses($type)
} }
$params = ['order' => ['id' => true], 'limit' => [$start, $count]]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition, $params); $statuses = Post::selectForUser($uid, [], $condition, $params);
$items = api_format_items(Post::toArray($statuses), $user_info, false, $type); $items = [];
while ($status = DBA::fetch($statuses)) {
$data = ['status' => $items]; $items[] = api_format_item($status, $type);
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
} }
DBA::close($statuses);
return DI::apiResponse()->formatData("statuses", $type, $data); return DI::apiResponse()->formatData("statuses", $type, ['status' => $items], Contact::getPublicIdByUserId($uid));
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -2641,6 +2440,7 @@ api_register_func('api/lists/statuses', 'api_lists_statuses', true);
function api_statuses_f($qtype) function api_statuses_f($qtype)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
// pagination // pagination
$count = $_GET['count'] ?? 20; $count = $_GET['count'] ?? 20;
@ -2648,7 +2448,7 @@ function api_statuses_f($qtype)
$start = max(0, ($page - 1) * $count); $start = max(0, ($page - 1) * $count);
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
if (!empty($_GET['cursor']) && $_GET['cursor'] == 'undefined') { if (!empty($_GET['cursor']) && $_GET['cursor'] == 'undefined') {
/* this is to stop Hotot to load friends multiple times /* this is to stop Hotot to load friends multiple times
@ -2668,11 +2468,6 @@ function api_statuses_f($qtype)
$sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(Contact::FOLLOWER), intval(Contact::FRIEND)); $sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(Contact::FOLLOWER), intval(Contact::FRIEND));
} }
// friends and followers only for self
if ($user_info['self'] == 0) {
$sql_extra = " AND false ";
}
if ($qtype == 'blocks') { if ($qtype == 'blocks') {
$sql_filter = 'AND `blocked` AND NOT `pending`'; $sql_filter = 'AND `blocked` AND NOT `pending`';
} elseif ($qtype == 'incoming') { } elseif ($qtype == 'incoming') {
@ -2691,17 +2486,17 @@ function api_statuses_f($qtype)
$sql_extra $sql_extra
ORDER BY `nick` ORDER BY `nick`
LIMIT ?, ?", LIMIT ?, ?",
BaseApi::getCurrentUserID(), $uid,
$start, $start,
$count $count
)); ));
$ret = []; $ret = [];
foreach ($r as $cid) { foreach ($r as $cid) {
$user = DI::twitterUser()->createFromContactId($cid['id'], BaseApi::getCurrentUserID())->toArray(); $user = DI::twitterUser()->createFromContactId($cid['id'], $uid)->toArray();
// "uid" and "self" are only needed for some internal stuff, so remove it from here // "uid" and "self" are only needed for some internal stuff, so remove it from here
unset($user["uid"]); unset($user['uid']);
unset($user["self"]); unset($user['self']);
if ($user) { if ($user) {
$ret[] = $user; $ret[] = $user;
@ -2823,7 +2618,6 @@ api_register_func('api/friendships/incoming', 'api_friendships_incoming', true);
function api_direct_messages_new($type) function api_direct_messages_new($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID(); $uid = BaseApi::getCurrentUserID();
if (empty($_POST["text"]) || empty($_POST['screen_name']) && empty($_POST['user_id'])) { if (empty($_POST["text"]) || empty($_POST['screen_name']) && empty($_POST['user_id'])) {
@ -2832,29 +2626,14 @@ function api_direct_messages_new($type)
$sender = DI::twitterUser()->createFromUserId($uid)->toArray(); $sender = DI::twitterUser()->createFromUserId($uid)->toArray();
$recipient = null; $cid = BaseApi::getContactIDForSearchterm($_POST['screen_name'] ?? '', $_POST['user_id'] ?? 0, $uid);
if (!empty($_POST['screen_name'])) { if (empty($cid)) {
$contacts = Contact::selectToArray(['id', 'nurl', 'network'], ['uid' => BaseApi::getCurrentUserID(), 'nick' => $_POST['screen_name']]);
if (DBA::isResult($contacts)) {
// Selecting the id by priority, friendica first
api_best_nickname($contacts);
$recipient = DI::twitterUser()->createFromContactId($contacts[0]['id'], $uid)->toArray();
}
} else {
$cid = BaseApi::getContactIDForSearchterm($_POST['user_id']);
if (!empty($cid)) {
$recipient = DI::twitterUser()->createFromContactId($cid, $uid)->toArray();
}
}
if (empty($recipient)) {
throw new NotFoundException('Recipient not found'); throw new NotFoundException('Recipient not found');
} }
$replyto = ''; $replyto = '';
if (!empty($_REQUEST['replyto'])) { if (!empty($_REQUEST['replyto'])) {
$mail = DBA::selectFirst('mail', ['parent-uri', 'title'], ['uid' => BaseApi::getCurrentUserID(), 'id' => $_REQUEST['replyto']]); $mail = DBA::selectFirst('mail', ['parent-uri', 'title'], ['uid' => $uid, 'id' => $_REQUEST['replyto']]);
$replyto = $mail['parent-uri']; $replyto = $mail['parent-uri'];
$sub = $mail['title']; $sub = $mail['title'];
} else { } else {
@ -2865,26 +2644,18 @@ function api_direct_messages_new($type)
} }
} }
$id = Mail::send($recipient['cid'], $_POST['text'], $sub, $replyto); $cdata = Contact::getPublicAndUserContactID($cid, $uid);
$id = Mail::send($cdata['user'], $_POST['text'], $sub, $replyto);
if ($id > -1) { if ($id > -1) {
$mail = DBA::selectFirst('mail', [], ['id' => $id]); $mail = DBA::selectFirst('mail', [], ['id' => $id]);
$ret = api_format_messages($mail, $recipient, $sender); $ret = api_format_messages($mail, DI::twitterUser()->createFromContactId($cid, $uid)->toArray(), $sender);
} else { } else {
$ret = ["error" => $id]; $ret = ["error" => $id];
} }
$data = ['direct_message'=>$ret]; return DI::apiResponse()->formatData("direct-messages", $type, ['direct_message' => $ret], Contact::getPublicIdByUserId($uid));
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $sender);
break;
}
return DI::apiResponse()->formatData("direct-messages", $type, $data);
} }
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
@ -2905,9 +2676,8 @@ api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, AP
function api_direct_messages_destroy($type) function api_direct_messages_destroy($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
//required //required
$id = $_REQUEST['id'] ?? 0; $id = $_REQUEST['id'] ?? 0;
// optional // optional
@ -2915,7 +2685,6 @@ function api_direct_messages_destroy($type)
$verbose = (!empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"); $verbose = (!empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false");
/// @todo optional parameter 'include_entities' from Twitter API not yet implemented /// @todo optional parameter 'include_entities' from Twitter API not yet implemented
$uid = $user_info['uid'];
// error if no id or parenturi specified (for clients posting parent-uri as well) // error if no id or parenturi specified (for clients posting parent-uri as well)
if ($verbose == "true" && ($id == 0 || $parenturi == "")) { if ($verbose == "true" && ($id == 0 || $parenturi == "")) {
$answer = ['result' => 'error', 'message' => 'message id or parenturi not specified']; $answer = ['result' => 'error', 'message' => 'message id or parenturi not specified'];
@ -3053,6 +2822,7 @@ api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, AP
function api_direct_messages_box($type, $box, $verbose) function api_direct_messages_box($type, $box, $verbose)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
// params // params
$count = $_GET['count'] ?? 20; $count = $_GET['count'] ?? 20;
@ -3071,7 +2841,7 @@ function api_direct_messages_box($type, $box, $verbose)
unset($_REQUEST['screen_name']); unset($_REQUEST['screen_name']);
unset($_GET['screen_name']); unset($_GET['screen_name']);
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
$profile_url = $user_info["url"]; $profile_url = $user_info["url"];
@ -3103,7 +2873,7 @@ function api_direct_messages_box($type, $box, $verbose)
$r = DBA::toArray(DBA::p( $r = DBA::toArray(DBA::p(
"SELECT `mail`.*, `contact`.`nurl` AS `contact-url` FROM `mail`,`contact` WHERE `mail`.`contact-id` = `contact`.`id` AND `mail`.`uid` = ? AND $sql_extra AND `mail`.`id` > ? ORDER BY `mail`.`id` DESC LIMIT ?,?", "SELECT `mail`.*, `contact`.`nurl` AS `contact-url` FROM `mail`,`contact` WHERE `mail`.`contact-id` = `contact`.`id` AND `mail`.`uid` = ? AND $sql_extra AND `mail`.`id` > ? ORDER BY `mail`.`id` DESC LIMIT ?,?",
BaseApi::getCurrentUserID(), $uid,
$since_id, $since_id,
$start, $start,
$count $count
@ -3117,9 +2887,9 @@ function api_direct_messages_box($type, $box, $verbose)
foreach ($r as $item) { foreach ($r as $item) {
if ($box == "inbox" || $item['from-url'] != $profile_url) { if ($box == "inbox" || $item['from-url'] != $profile_url) {
$recipient = $user_info; $recipient = $user_info;
$sender = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray(); $sender = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
} elseif ($box == "sentbox" || $item['from-url'] == $profile_url) { } elseif ($box == "sentbox" || $item['from-url'] == $profile_url) {
$recipient = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray(); $recipient = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
$sender = $user_info; $sender = $user_info;
} }
@ -3128,17 +2898,7 @@ function api_direct_messages_box($type, $box, $verbose)
} }
} }
return DI::apiResponse()->formatData("direct-messages", $type, ['direct_message' => $ret], Contact::getPublicIdByUserId($uid));
$data = ['direct_message' => $ret];
switch ($type) {
case "atom":
break;
case "rss":
$data = api_rss_extra($data, $user_info);
break;
}
return DI::apiResponse()->formatData("direct-messages", $type, $data);
} }
/** /**
@ -3218,12 +2978,13 @@ api_register_func('api/direct_messages', 'api_direct_messages_inbox', true);
function api_fr_photos_list($type) function api_fr_photos_list($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
$r = DBA::toArray(DBA::p( $r = DBA::toArray(DBA::p(
"SELECT `resource-id`, MAX(scale) AS `scale`, `album`, `filename`, `type`, MAX(`created`) AS `created`, "SELECT `resource-id`, MAX(scale) AS `scale`, `album`, `filename`, `type`, MAX(`created`) AS `created`,
MAX(`edited`) AS `edited`, MAX(`desc`) AS `desc` FROM `photo` MAX(`edited`) AS `edited`, MAX(`desc`) AS `desc` FROM `photo`
WHERE `uid` = ? AND NOT `photo-type` IN (?, ?) GROUP BY `resource-id`, `album`, `filename`, `type`", WHERE `uid` = ? AND NOT `photo-type` IN (?, ?) GROUP BY `resource-id`, `album`, `filename`, `type`",
BaseApi::getCurrentUserID(), Photo::CONTACT_AVATAR, Photo::CONTACT_BANNER $uid, Photo::CONTACT_AVATAR, Photo::CONTACT_BANNER
)); ));
$typetoext = [ $typetoext = [
'image/jpeg' => 'jpg', 'image/jpeg' => 'jpg',
@ -3268,6 +3029,7 @@ function api_fr_photos_list($type)
function api_fr_photo_create_update($type) function api_fr_photo_create_update($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// input params // input params
$photo_id = $_REQUEST['photo_id'] ?? null; $photo_id = $_REQUEST['photo_id'] ?? null;
@ -3301,24 +3063,24 @@ function api_fr_photo_create_update($type)
$mode = "update"; $mode = "update";
// check if photo is existing in databasei // check if photo is existing in databasei
if (!Photo::exists(['resource-id' => $photo_id, 'uid' => BaseApi::getCurrentUserID(), 'album' => $album])) { if (!Photo::exists(['resource-id' => $photo_id, 'uid' => $uid, 'album' => $album])) {
throw new BadRequestException("photo not available"); throw new BadRequestException("photo not available");
} }
} }
// checks on acl strings provided by clients // checks on acl strings provided by clients
$acl_input_error = false; $acl_input_error = false;
$acl_input_error |= check_acl_input($allow_cid); $acl_input_error |= check_acl_input($allow_cid, $uid);
$acl_input_error |= check_acl_input($deny_cid); $acl_input_error |= check_acl_input($deny_cid, $uid);
$acl_input_error |= check_acl_input($allow_gid); $acl_input_error |= check_acl_input($allow_gid, $uid);
$acl_input_error |= check_acl_input($deny_gid); $acl_input_error |= check_acl_input($deny_gid, $uid);
if ($acl_input_error) { if ($acl_input_error) {
throw new BadRequestException("acl data invalid"); throw new BadRequestException("acl data invalid");
} }
// now let's upload the new media in create-mode // now let's upload the new media in create-mode
if ($mode == "create") { if ($mode == "create") {
$media = $_FILES['media']; $media = $_FILES['media'];
$data = save_media_to_database("photo", $media, $type, $album, trim($allow_cid), trim($deny_cid), trim($allow_gid), trim($deny_gid), $desc, Photo::DEFAULT, $visibility); $data = save_media_to_database("photo", $media, $type, $album, trim($allow_cid), trim($deny_cid), trim($allow_gid), trim($deny_gid), $desc, Photo::DEFAULT, $visibility, null, $uid);
// return success of updating or error message // return success of updating or error message
if (!is_null($data)) { if (!is_null($data)) {
@ -3363,7 +3125,7 @@ function api_fr_photo_create_update($type)
$result = false; $result = false;
if (count($updated_fields) > 0) { if (count($updated_fields) > 0) {
$nothingtodo = false; $nothingtodo = false;
$result = Photo::update($updated_fields, ['uid' => BaseApi::getCurrentUserID(), 'resource-id' => $photo_id, 'album' => $album]); $result = Photo::update($updated_fields, ['uid' => $uid, 'resource-id' => $photo_id, 'album' => $album]);
} else { } else {
$nothingtodo = true; $nothingtodo = true;
} }
@ -3371,7 +3133,7 @@ function api_fr_photo_create_update($type)
if (!empty($_FILES['media'])) { if (!empty($_FILES['media'])) {
$nothingtodo = false; $nothingtodo = false;
$media = $_FILES['media']; $media = $_FILES['media'];
$data = save_media_to_database("photo", $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, Photo::DEFAULT, $visibility, $photo_id); $data = save_media_to_database("photo", $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, Photo::DEFAULT, $visibility, $photo_id, $uid);
if (!is_null($data)) { if (!is_null($data)) {
return DI::apiResponse()->formatData("photo_update", $type, $data); return DI::apiResponse()->formatData("photo_update", $type, $data);
} }
@ -3436,6 +3198,7 @@ function api_fr_photo_detail($type)
function api_account_update_profile_image($type) function api_account_update_profile_image($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// input params // input params
$profile_id = $_REQUEST['profile_id'] ?? 0; $profile_id = $_REQUEST['profile_id'] ?? 0;
@ -3447,7 +3210,7 @@ function api_account_update_profile_image($type)
// check if specified profile id is valid // check if specified profile id is valid
if ($profile_id != 0) { if ($profile_id != 0) {
$profile = DBA::selectFirst('profile', ['is-default'], ['uid' => BaseApi::getCurrentUserID(), 'id' => $profile_id]); $profile = DBA::selectFirst('profile', ['is-default'], ['uid' => $uid, 'id' => $profile_id]);
// error message if specified profile id is not in database // error message if specified profile id is not in database
if (!DBA::isResult($profile)) { if (!DBA::isResult($profile)) {
throw new BadRequestException("profile_id not available"); throw new BadRequestException("profile_id not available");
@ -3465,7 +3228,7 @@ function api_account_update_profile_image($type)
$media = $_FILES['media']; $media = $_FILES['media'];
} }
// save new profile image // save new profile image
$data = save_media_to_database("profileimage", $media, $type, DI::l10n()->t(Photo::PROFILE_PHOTOS), "", "", "", "", "", Photo::USER_AVATAR); $data = save_media_to_database("profileimage", $media, $type, DI::l10n()->t(Photo::PROFILE_PHOTOS), "", "", "", "", "", Photo::USER_AVATAR, false, null, $uid);
// get filetype // get filetype
if (is_array($media['type'])) { if (is_array($media['type'])) {
@ -3483,18 +3246,18 @@ function api_account_update_profile_image($type)
// change specified profile or all profiles to the new resource-id // change specified profile or all profiles to the new resource-id
if ($is_default_profile) { if ($is_default_profile) {
$condition = ["`profile` AND `resource-id` != ? AND `uid` = ?", $data['photo']['id'], BaseApi::getCurrentUserID()]; $condition = ["`profile` AND `resource-id` != ? AND `uid` = ?", $data['photo']['id'], $uid];
Photo::update(['profile' => false, 'photo-type' => Photo::DEFAULT], $condition); Photo::update(['profile' => false, 'photo-type' => Photo::DEFAULT], $condition);
} else { } else {
$fields = ['photo' => DI::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $fileext, $fields = ['photo' => DI::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $fileext,
'thumb' => DI::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $fileext]; 'thumb' => DI::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $fileext];
DBA::update('profile', $fields, ['id' => $_REQUEST['profile'], 'uid' => BaseApi::getCurrentUserID()]); DBA::update('profile', $fields, ['id' => $_REQUEST['profile'], 'uid' => $uid]);
} }
Contact::updateSelfFromUserID(BaseApi::getCurrentUserID(), true); Contact::updateSelfFromUserID($uid, true);
// Update global directory in background // Update global directory in background
Profile::publishUpdate(BaseApi::getCurrentUserID()); Profile::publishUpdate($uid);
// output for client // output for client
if ($data) { if ($data) {
@ -3527,25 +3290,24 @@ api_register_func('api/account/update_profile_image', 'api_account_update_profil
function api_account_update_profile($type) function api_account_update_profile($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
$local_user = BaseApi::getCurrentUserID(); $api_user = DI::twitterUser()->createFromUserId($uid)->toArray();
$api_user = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
if (!empty($_POST['name'])) { if (!empty($_POST['name'])) {
DBA::update('profile', ['name' => $_POST['name']], ['uid' => $local_user]); DBA::update('profile', ['name' => $_POST['name']], ['uid' => $uid]);
DBA::update('user', ['username' => $_POST['name']], ['uid' => $local_user]); DBA::update('user', ['username' => $_POST['name']], ['uid' => $uid]);
Contact::update(['name' => $_POST['name']], ['uid' => $local_user, 'self' => 1]); Contact::update(['name' => $_POST['name']], ['uid' => $uid, 'self' => 1]);
Contact::update(['name' => $_POST['name']], ['id' => $api_user['id']]); Contact::update(['name' => $_POST['name']], ['id' => $api_user['id']]);
} }
if (isset($_POST['description'])) { if (isset($_POST['description'])) {
DBA::update('profile', ['about' => $_POST['description']], ['uid' => $local_user]); DBA::update('profile', ['about' => $_POST['description']], ['uid' => $uid]);
Contact::update(['about' => $_POST['description']], ['uid' => $local_user, 'self' => 1]); Contact::update(['about' => $_POST['description']], ['uid' => $uid, 'self' => 1]);
Contact::update(['about' => $_POST['description']], ['id' => $api_user['id']]); Contact::update(['about' => $_POST['description']], ['id' => $api_user['id']]);
} }
Profile::publishUpdate($local_user); Profile::publishUpdate($uid);
return api_account_verify_credentials($type); return api_account_verify_credentials($type);
} }
@ -3556,10 +3318,11 @@ api_register_func('api/account/update_profile', 'api_account_update_profile', tr
/** /**
* *
* @param string $acl_string * @param string $acl_string
* @param int $uid
* @return bool * @return bool
* @throws Exception * @throws Exception
*/ */
function check_acl_input($acl_string) function check_acl_input($acl_string, $uid)
{ {
if (empty($acl_string)) { if (empty($acl_string)) {
return false; return false;
@ -3575,7 +3338,7 @@ function check_acl_input($acl_string)
foreach ($cid_array as $cid) { foreach ($cid_array as $cid) {
$cid = str_replace("<", "", $cid); $cid = str_replace("<", "", $cid);
$cid = str_replace(">", "", $cid); $cid = str_replace(">", "", $cid);
$condition = ['id' => $cid, 'uid' => BaseApi::getCurrentUserID()]; $condition = ['id' => $cid, 'uid' => $uid];
$contact_not_found |= !DBA::exists('contact', $condition); $contact_not_found |= !DBA::exists('contact', $condition);
} }
return $contact_not_found; return $contact_not_found;
@ -3594,6 +3357,7 @@ function check_acl_input($acl_string)
* @param integer $phototype * @param integer $phototype
* @param boolean $visibility * @param boolean $visibility
* @param string $photo_id * @param string $photo_id
* @param int $uid
* @return array * @return array
* @throws BadRequestException * @throws BadRequestException
* @throws ForbiddenException * @throws ForbiddenException
@ -3602,7 +3366,7 @@ function check_acl_input($acl_string)
* @throws NotFoundException * @throws NotFoundException
* @throws UnauthorizedException * @throws UnauthorizedException
*/ */
function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, $phototype = 0, $visibility = false, $photo_id = null) function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, $phototype, $visibility, $photo_id, $uid)
{ {
$visitor = 0; $visitor = 0;
$src = ""; $src = "";
@ -3677,13 +3441,13 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
// upload normal image (scales 0, 1, 2) // upload normal image (scales 0, 1, 2)
logger::info("photo upload: starting new photo upload"); logger::info("photo upload: starting new photo upload");
$r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 0, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 0, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
if (!$r) { if (!$r) {
logger::notice("photo upload: image upload with scale 0 (original size) failed"); logger::notice("photo upload: image upload with scale 0 (original size) failed");
} }
if ($width > 640 || $height > 640) { if ($width > 640 || $height > 640) {
$Image->scaleDown(640); $Image->scaleDown(640);
$r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 1, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 1, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
if (!$r) { if (!$r) {
logger::notice("photo upload: image upload with scale 1 (640x640) failed"); logger::notice("photo upload: image upload with scale 1 (640x640) failed");
} }
@ -3691,7 +3455,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
if ($width > 320 || $height > 320) { if ($width > 320 || $height > 320) {
$Image->scaleDown(320); $Image->scaleDown(320);
$r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 2, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 2, Photo::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
if (!$r) { if (!$r) {
logger::notice("photo upload: image upload with scale 2 (320x320) failed"); logger::notice("photo upload: image upload with scale 2 (320x320) failed");
} }
@ -3703,7 +3467,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
if ($width > 300 || $height > 300) { if ($width > 300 || $height > 300) {
$Image->scaleDown(300); $Image->scaleDown(300);
$r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 4, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 4, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
if (!$r) { if (!$r) {
logger::notice("photo upload: profile image upload with scale 4 (300x300) failed"); logger::notice("photo upload: profile image upload with scale 4 (300x300) failed");
} }
@ -3711,7 +3475,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
if ($width > 80 || $height > 80) { if ($width > 80 || $height > 80) {
$Image->scaleDown(80); $Image->scaleDown(80);
$r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 5, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 5, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
if (!$r) { if (!$r) {
logger::notice("photo upload: profile image upload with scale 5 (80x80) failed"); logger::notice("photo upload: profile image upload with scale 5 (80x80) failed");
} }
@ -3719,7 +3483,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
if ($width > 48 || $height > 48) { if ($width > 48 || $height > 48) {
$Image->scaleDown(48); $Image->scaleDown(48);
$r = Photo::store($Image, BaseApi::getCurrentUserID(), $visitor, $resource_id, $filename, $album, 6, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); $r = Photo::store($Image, $uid, $visitor, $resource_id, $filename, $album, 6, $phototype, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
if (!$r) { if (!$r) {
logger::notice("photo upload: profile image upload with scale 6 (48x48) failed"); logger::notice("photo upload: profile image upload with scale 6 (48x48) failed");
} }
@ -3731,7 +3495,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
if (!empty($r)) { if (!empty($r)) {
// create entry in 'item'-table on new uploads to enable users to comment/like/dislike the photo // create entry in 'item'-table on new uploads to enable users to comment/like/dislike the photo
if ($photo_id == null && $mediatype == "photo") { if ($photo_id == null && $mediatype == "photo") {
post_photo_item($resource_id, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility); post_photo_item($resource_id, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility, $uid);
} }
// on success return image data in json/xml format (like /api/friendica/photo does when no scale is given) // on success return image data in json/xml format (like /api/friendica/photo does when no scale is given)
return prepare_photo_data($type, false, $resource_id); return prepare_photo_data($type, false, $resource_id);
@ -3749,17 +3513,18 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
* @param string $deny_gid * @param string $deny_gid
* @param string $filetype * @param string $filetype
* @param boolean $visibility * @param boolean $visibility
* @param int $uid
* @throws InternalServerErrorException * @throws InternalServerErrorException
*/ */
function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility = false) function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility, $uid)
{ {
// get data about the api authenticated user // get data about the api authenticated user
$uri = Item::newURI(intval(BaseApi::getCurrentUserID())); $uri = Item::newURI(intval($uid));
$owner_record = DBA::selectFirst('contact', [], ['uid' => BaseApi::getCurrentUserID(), 'self' => true]); $owner_record = DBA::selectFirst('contact', [], ['uid' => $uid, 'self' => true]);
$arr = []; $arr = [];
$arr['guid'] = System::createUUID(); $arr['guid'] = System::createUUID();
$arr['uid'] = intval(BaseApi::getCurrentUserID()); $arr['uid'] = intval($uid);
$arr['uri'] = $uri; $arr['uri'] = $uri;
$arr['type'] = 'photo'; $arr['type'] = 'photo';
$arr['wall'] = 1; $arr['wall'] = 1;
@ -3811,8 +3576,7 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
function prepare_photo_data($type, $scale, $photo_id) function prepare_photo_data($type, $scale, $photo_id)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale))); $scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale)));
$data_sql = ($scale === false ? "" : "data, "); $data_sql = ($scale === false ? "" : "data, ");
@ -3826,7 +3590,7 @@ function prepare_photo_data($type, $scale, $photo_id)
FROM `photo` WHERE `uid` = ? AND `resource-id` = ? $scale_sql GROUP BY FROM `photo` WHERE `uid` = ? AND `resource-id` = ? $scale_sql GROUP BY
`resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`, `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
`type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`", `type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`",
BaseApi::getCurrentUserID(), $uid,
$photo_id $photo_id
)); ));
@ -3869,7 +3633,7 @@ function prepare_photo_data($type, $scale, $photo_id)
} }
// retrieve item element for getting activities (like, dislike etc.) related to photo // retrieve item element for getting activities (like, dislike etc.) related to photo
$condition = ['uid' => BaseApi::getCurrentUserID(), 'resource-id' => $photo_id]; $condition = ['uid' => $uid, 'resource-id' => $photo_id];
$item = Post::selectFirst(['id', 'uid', 'uri', 'parent', 'allow_cid', 'deny_cid', 'allow_gid', 'deny_gid'], $condition); $item = Post::selectFirst(['id', 'uid', 'uri', 'parent', 'allow_cid', 'deny_cid', 'allow_gid', 'deny_gid'], $condition);
if (!DBA::isResult($item)) { if (!DBA::isResult($item)) {
throw new NotFoundException('Photo-related item not found.'); throw new NotFoundException('Photo-related item not found.');
@ -3879,12 +3643,17 @@ function prepare_photo_data($type, $scale, $photo_id)
// retrieve comments on photo // retrieve comments on photo
$condition = ["`parent` = ? AND `uid` = ? AND `gravity` IN (?, ?)", $condition = ["`parent` = ? AND `uid` = ? AND `gravity` IN (?, ?)",
$item['parent'], BaseApi::getCurrentUserID(), GRAVITY_PARENT, GRAVITY_COMMENT]; $item['parent'], $uid, GRAVITY_PARENT, GRAVITY_COMMENT];
$statuses = Post::selectForUser(BaseApi::getCurrentUserID(), [], $condition); $statuses = Post::selectForUser($uid, [], $condition);
// prepare output of comments // prepare output of comments
$commentData = api_format_items(Post::toArray($statuses), $user_info, false, $type); $commentData = [];
while ($status = DBA::fetch($statuses)) {
$commentData[] = api_format_item($status, $type);
}
DBA::close($statuses);
$comments = []; $comments = [];
if ($type == "xml") { if ($type == "xml") {
$k = 0; $k = 0;
@ -3958,7 +3727,7 @@ function api_in_reply_to($item)
$in_reply_to['user_id_str'] = null; $in_reply_to['user_id_str'] = null;
$in_reply_to['screen_name'] = null; $in_reply_to['screen_name'] = null;
if (($item['thr-parent'] != $item['uri']) && ($item['gravity'] != GRAVITY_PARENT)) { if (!empty($item['thr-parent']) && ($item['thr-parent'] != $item['uri']) && ($item['gravity'] != GRAVITY_PARENT)) {
$parent = Post::selectFirst(['id'], ['uid' => $item['uid'], 'uri' => $item['thr-parent']]); $parent = Post::selectFirst(['id'], ['uid' => $item['uid'], 'uri' => $item['thr-parent']]);
if (DBA::isResult($parent)) { if (DBA::isResult($parent)) {
$in_reply_to['status_id'] = intval($parent['id']); $in_reply_to['status_id'] = intval($parent['id']);
@ -4019,74 +3788,6 @@ function api_clean_plain_items($text)
return $text; return $text;
} }
/**
*
* @param array $contacts
*
* @return void
*/
function api_best_nickname(&$contacts)
{
$best_contact = [];
if (count($contacts) == 0) {
return;
}
foreach ($contacts as $contact) {
if ($contact["network"] == "") {
$contact["network"] = "dfrn";
$best_contact = [$contact];
}
}
if (sizeof($best_contact) == 0) {
foreach ($contacts as $contact) {
if ($contact["network"] == "dfrn") {
$best_contact = [$contact];
}
}
}
if (sizeof($best_contact) == 0) {
foreach ($contacts as $contact) {
if ($contact["network"] == "dspr") {
$best_contact = [$contact];
}
}
}
if (sizeof($best_contact) == 0) {
foreach ($contacts as $contact) {
if ($contact["network"] == "stat") {
$best_contact = [$contact];
}
}
}
if (sizeof($best_contact) == 0) {
foreach ($contacts as $contact) {
if ($contact["network"] == "pump") {
$best_contact = [$contact];
}
}
}
if (sizeof($best_contact) == 0) {
foreach ($contacts as $contact) {
if ($contact["network"] == "twit") {
$best_contact = [$contact];
}
}
}
if (sizeof($best_contact) == 1) {
$contacts = $best_contact;
} else {
$contacts = [$contacts[0]];
}
}
/** /**
* Return all or a specified group of the user with the containing contacts. * Return all or a specified group of the user with the containing contacts.
* *
@ -4102,11 +3803,10 @@ function api_best_nickname(&$contacts)
function api_friendica_group_show($type) function api_friendica_group_show($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$gid = $_REQUEST['gid'] ?? 0; $gid = $_REQUEST['gid'] ?? 0;
$uid = $user_info['uid'];
// get data of the specified group id or all groups if not specified // get data of the specified group id or all groups if not specified
if ($gid != 0) { if ($gid != 0) {
@ -4130,13 +3830,13 @@ function api_friendica_group_show($type)
$user_element = "users"; $user_element = "users";
$k = 0; $k = 0;
foreach ($members as $member) { foreach ($members as $member) {
$user = DI::twitterUser()->createFromContactId($member['contact-id'], BaseApi::getCurrentUserID())->toArray(); $user = DI::twitterUser()->createFromContactId($member['contact-id'], $uid)->toArray();
$users[$k++.":user"] = $user; $users[$k++.":user"] = $user;
} }
} else { } else {
$user_element = "user"; $user_element = "user";
foreach ($members as $member) { foreach ($members as $member) {
$user = DI::twitterUser()->createFromContactId($member['contact-id'], BaseApi::getCurrentUserID())->toArray(); $user = DI::twitterUser()->createFromContactId($member['contact-id'], $uid)->toArray();
$users[] = $user; $users[] = $user;
} }
} }
@ -4163,11 +3863,10 @@ api_register_func('api/friendica/group_show', 'api_friendica_group_show', true);
function api_lists_destroy($type) function api_lists_destroy($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$gid = $_REQUEST['list_id'] ?? 0; $gid = $_REQUEST['list_id'] ?? 0;
$uid = $user_info['uid'];
// error if no gid specified // error if no gid specified
if ($gid == 0) { if ($gid == 0) {
@ -4186,7 +3885,7 @@ function api_lists_destroy($type)
'name' => $group['name'], 'name' => $group['name'],
'id' => intval($gid), 'id' => intval($gid),
'id_str' => (string) $gid, 'id_str' => (string) $gid,
'user' => $user_info 'user' => DI::twitterUser()->createFromUserId($uid)->toArray()
]; ];
return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]); return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]);
@ -4264,11 +3963,10 @@ function group_create($name, $uid, $users = [])
function api_friendica_group_create($type) function api_friendica_group_create($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$name = $_REQUEST['name'] ?? ''; $name = $_REQUEST['name'] ?? '';
$uid = $user_info['uid'];
$json = json_decode($_POST['json'], true); $json = json_decode($_POST['json'], true);
$users = $json['user']; $users = $json['user'];
@ -4295,11 +3993,10 @@ api_register_func('api/friendica/group_create', 'api_friendica_group_create', tr
function api_lists_create($type) function api_lists_create($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$name = $_REQUEST['name'] ?? ''; $name = $_REQUEST['name'] ?? '';
$uid = $user_info['uid'];
$success = group_create($name, $uid); $success = group_create($name, $uid);
if ($success['success']) { if ($success['success']) {
@ -4307,7 +4004,7 @@ function api_lists_create($type)
'name' => $success['name'], 'name' => $success['name'],
'id' => intval($success['gid']), 'id' => intval($success['gid']),
'id_str' => (string) $success['gid'], 'id_str' => (string) $success['gid'],
'user' => $user_info 'user' => DI::twitterUser()->createFromUserId($uid)->toArray()
]; ];
return DI::apiResponse()->formatData("lists", $type, ['lists' => $grp]); return DI::apiResponse()->formatData("lists", $type, ['lists' => $grp]);
@ -4331,10 +4028,9 @@ api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST)
function api_friendica_group_update($type) function api_friendica_group_update($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$uid = $user_info['uid'];
$gid = $_REQUEST['gid'] ?? 0; $gid = $_REQUEST['gid'] ?? 0;
$name = $_REQUEST['name'] ?? ''; $name = $_REQUEST['name'] ?? '';
$json = json_decode($_POST['json'], true); $json = json_decode($_POST['json'], true);
@ -4401,12 +4097,11 @@ api_register_func('api/friendica/group_update', 'api_friendica_group_update', tr
function api_lists_update($type) function api_lists_update($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
$gid = $_REQUEST['list_id'] ?? 0; $gid = $_REQUEST['list_id'] ?? 0;
$name = $_REQUEST['name'] ?? ''; $name = $_REQUEST['name'] ?? '';
$uid = $user_info['uid'];
// error if no gid specified // error if no gid specified
if ($gid == 0) { if ($gid == 0) {
@ -4425,7 +4120,7 @@ function api_lists_update($type)
'name' => $name, 'name' => $name,
'id' => intval($gid), 'id' => intval($gid),
'id_str' => (string) $gid, 'id_str' => (string) $gid,
'user' => $user_info 'user' => DI::twitterUser()->createFromUserId($uid)->toArray()
]; ];
return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]); return DI::apiResponse()->formatData("lists", $type, ['lists' => $list]);
@ -4450,8 +4145,7 @@ api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST)
function api_friendica_notification_seen($type) function api_friendica_notification_seen($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID();
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray();
if (DI::args()->getArgc() !== 4) { if (DI::args()->getArgc() !== 4) {
throw new BadRequestException('Invalid argument count'); throw new BadRequestException('Invalid argument count');
@ -4461,7 +4155,7 @@ function api_friendica_notification_seen($type)
try { try {
$Notify = DI::notify()->selectOneById($id); $Notify = DI::notify()->selectOneById($id);
if ($Notify->uid !== BaseApi::getCurrentUserID()) { if ($Notify->uid !== $uid) {
throw new NotFoundException(); throw new NotFoundException();
} }
@ -4473,10 +4167,10 @@ function api_friendica_notification_seen($type)
DI::notify()->save($Notify); DI::notify()->save($Notify);
if ($Notify->otype === Notification\ObjectType::ITEM) { if ($Notify->otype === Notification\ObjectType::ITEM) {
$item = Post::selectFirstForUser(BaseApi::getCurrentUserID(), [], ['id' => $Notify->iid, 'uid' => BaseApi::getCurrentUserID()]); $item = Post::selectFirstForUser($uid, [], ['id' => $Notify->iid, 'uid' => $uid]);
if (DBA::isResult($item)) { if (DBA::isResult($item)) {
// we found the item, return it to the user // we found the item, return it to the user
$ret = api_format_items([$item], $user_info, false, $type); $ret = [api_format_item($item, $type)];
$data = ['status' => $ret]; $data = ['status' => $ret];
return DI::apiResponse()->formatData('status', $type, $data); return DI::apiResponse()->formatData('status', $type, $data);
} }
@ -4511,11 +4205,11 @@ api_register_func('api/friendica/notification/seen', 'api_friendica_notification
function api_friendica_direct_messages_search($type, $box = "") function api_friendica_direct_messages_search($type, $box = "")
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$uid = BaseApi::getCurrentUserID();
// params // params
$user_info = DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray(); $user_info = DI::twitterUser()->createFromUserId($uid)->toArray();
$searchstring = $_REQUEST['searchstring'] ?? ''; $searchstring = $_REQUEST['searchstring'] ?? '';
$uid = $user_info['uid'];
// error if no searchstring specified // error if no searchstring specified
if ($searchstring == "") { if ($searchstring == "") {
@ -4542,9 +4236,9 @@ function api_friendica_direct_messages_search($type, $box = "")
foreach ($r as $item) { foreach ($r as $item) {
if ($box == "inbox" || $item['from-url'] != $profile_url) { if ($box == "inbox" || $item['from-url'] != $profile_url) {
$recipient = $user_info; $recipient = $user_info;
$sender = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray(); $sender = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
} elseif ($box == "sentbox" || $item['from-url'] == $profile_url) { } elseif ($box == "sentbox" || $item['from-url'] == $profile_url) {
$recipient = DI::twitterUser()->createFromContactId($item['contact-id'], BaseApi::getCurrentUserID())->toArray(); $recipient = DI::twitterUser()->createFromContactId($item['contact-id'], $uid)->toArray();
$sender = $user_info; $sender = $user_info;
} }
@ -4560,81 +4254,3 @@ function api_friendica_direct_messages_search($type, $box = "")
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_messages_search', true); api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_messages_search', true);
/*
* Number of comments
*
* Bind comment numbers(friendica_comments: Int) on each statuses page of *_timeline / favorites / search
*
* @param object $data [Status, Status]
*
* @return void
*/
function bindComments(&$data)
{
if (count($data) == 0) {
return;
}
$ids = [];
$comments = [];
foreach ($data as $item) {
$ids[] = $item['id'];
}
$idStr = DBA::escape(implode(', ', $ids));
$sql = "SELECT `parent`, COUNT(*) as comments FROM `post-user-view` WHERE `parent` IN ($idStr) AND `deleted` = ? AND `gravity`= ? GROUP BY `parent`";
$items = DBA::p($sql, 0, GRAVITY_COMMENT);
$itemsData = DBA::toArray($items);
foreach ($itemsData as $item) {
$comments[$item['parent']] = $item['comments'];
}
foreach ($data as $idx => $item) {
$id = $item['id'];
$data[$idx]['friendica_comments'] = isset($comments[$id]) ? $comments[$id] : 0;
}
}
/*
@TODO Maybe open to implement?
To.Do:
[pagename] => api/1.1/statuses/lookup.json
[id] => 605138389168451584
[include_cards] => true
[cards_platform] => Android-12
[include_entities] => true
[include_my_retweet] => 1
[include_rts] => 1
[include_reply_count] => true
[include_descendent_reply_count] => true
(?)
Not implemented by now:
statuses/retweets_of_me
friendships/create
friendships/destroy
friendships/exists
friendships/show
account/update_location
account/update_profile_background_image
blocks/create
blocks/destroy
friendica/profile/update
friendica/profile/create
friendica/profile/delete
Not implemented in status.net:
statuses/retweeted_to_me
statuses/retweeted_by_me
direct_messages/destroy
account/end_session
account/update_delivery_device
notifications/follow
notifications/leave
blocks/exists
blocks/blocking
lists
*/

View file

@ -3,11 +3,14 @@
namespace Friendica\Module\Api; namespace Friendica\Module\Api;
use Friendica\App\Arguments; use Friendica\App\Arguments;
use Friendica\App\BaseURL;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Util\Arrays; use Friendica\Util\Arrays;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\HTTPInputData; use Friendica\Util\HTTPInputData;
use Friendica\Util\XML; use Friendica\Util\XML;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Friendica\Factory\Api\Twitter\User as TwitterUser;
/** /**
* This class is used to format and return API responses * This class is used to format and return API responses
@ -26,11 +29,13 @@ class ApiResponse
* @param Arguments $args * @param Arguments $args
* @param LoggerInterface $logger * @param LoggerInterface $logger
*/ */
public function __construct(L10n $l10n, Arguments $args, LoggerInterface $logger) public function __construct(L10n $l10n, Arguments $args, LoggerInterface $logger, BaseURL $baseurl, TwitterUser $twitteruser)
{ {
$this->l10n = $l10n; $this->l10n = $l10n;
$this->args = $args; $this->args = $args;
$this->logger = $logger; $this->logger = $logger;
$this->baseurl = $baseurl;
$this->twitterUser = $twitteruser;
} }
/** /**
@ -102,20 +107,51 @@ class ApiResponse
return XML::fromArray($data3, $xml, false, $namespaces); return XML::fromArray($data3, $xml, false, $namespaces);
} }
/**
* Set values for RSS template
*
* @param array $arr Array to be passed to template
* @param int $cid Contact ID of template
* @return array
*/
private function addRSSValues(array $arr, int $cid)
{
if (empty($cid)) {
return $arr;
}
$user_info = $this->twitterUser->createFromContactId($cid)->toArray();
$arr['$user'] = $user_info;
$arr['$rss'] = [
'alternate' => $user_info['url'],
'self' => $this->baseurl . '/' . $this->args->getQueryString(),
'base' => $this->baseurl,
'updated' => DateTimeFormat::utc(null, DateTimeFormat::API),
'atom_updated' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
'language' => $user_info['lang'],
'logo' => $this->baseurl . '/images/friendica-32.png',
];
return $arr;
}
/** /**
* Formats the data according to the data type * Formats the data according to the data type
* *
* @param string $root_element Name of the root element * @param string $root_element Name of the root element
* @param string $type Return type (atom, rss, xml, json) * @param string $type Return type (atom, rss, xml, json)
* @param array $data JSON style array * @param array $data JSON style array
* @param int $cid ID of the contact for RSS
* *
* @return array|string (string|array) XML data or JSON data * @return array|string (string|array) XML data or JSON data
*/ */
public function formatData(string $root_element, string $type, array $data) public function formatData(string $root_element, string $type, array $data, int $cid = 0)
{ {
switch ($type) { switch ($type) {
case 'atom':
case 'rss': case 'rss':
$data = $this->addRSSValues($data, $cid);
case 'atom':
case 'xml': case 'xml':
return $this->createXML($data, $root_element); return $this->createXML($data, $root_element);
case 'json': case 'json':

View file

@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Friendica;
use Friendica\DI; use Friendica\DI;
use Friendica\Module\BaseApi; use Friendica\Module\BaseApi;
require_once __DIR__ . '/../../../../include/api.php';
/** /**
* api/friendica * api/friendica

View file

@ -27,6 +27,7 @@ use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Model\User;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Security\BasicAuth; use Friendica\Security\BasicAuth;
use Friendica\Security\OAuth; use Friendica\Security\OAuth;
@ -292,12 +293,23 @@ class BaseApi extends BaseModule
} }
} }
public static function getContactIDForSearchterm($searchterm) public static function getContactIDForSearchterm(string $screen_name, int $cid, int $uid)
{ {
if (intval($searchterm) == 0) { if (!empty($cid)) {
$cid = Contact::getIdForURL($searchterm, 0, false); return $cid;
}
if (strpos($screen_name, '@') !== false) {
$cid = Contact::getIdForURL($screen_name, 0, false);
} else { } else {
$cid = intval($searchterm); $user = User::getByNickname($screen_name, ['uid']);
if (!empty($user['uid'])) {
$cid = Contact::getPublicIdByUserId($user['uid']);
}
}
if (empty($cid) && ($uid != 0)) {
$cid = Contact::getPublicIdByUserId($uid);
} }
return $cid; return $cid;

View file

@ -303,6 +303,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
], ],
@ -317,6 +318,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
], ],
@ -331,6 +333,7 @@ return [
'causer-id' => 43, 'causer-id' => 43,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
], ],
@ -345,6 +348,7 @@ return [
'causer-id' => 44, 'causer-id' => 44,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
], ],
@ -359,6 +363,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
], ],
@ -373,6 +378,7 @@ return [
'causer-id' => 44, 'causer-id' => 44,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
], ],
@ -392,6 +398,7 @@ return [
'parent-uri-id' => 1, 'parent-uri-id' => 1,
'thr-parent-id' => 1, 'thr-parent-id' => 1,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'gravity' => GRAVITY_PARENT, 'gravity' => GRAVITY_PARENT,
'network' => Protocol::DFRN, 'network' => Protocol::DFRN,
'wall' => 1, 'wall' => 1,
@ -413,6 +420,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 1, 'wall' => 1,
@ -433,6 +441,7 @@ return [
'causer-id' => 43, 'causer-id' => 43,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 1, 'wall' => 1,
@ -453,6 +462,7 @@ return [
'causer-id' => 44, 'causer-id' => 44,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 1, 'wall' => 1,
@ -473,6 +483,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 1, 'wall' => 1,
@ -493,6 +504,7 @@ return [
'causer-id' => 44, 'causer-id' => 44,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 1, 'wall' => 1,
@ -513,6 +525,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 0, 'wall' => 0,
@ -533,6 +546,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 0, 'wall' => 0,
@ -553,6 +567,7 @@ return [
'causer-id' => 43, 'causer-id' => 43,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 0, 'wall' => 0,
@ -573,6 +588,7 @@ return [
'causer-id' => 44, 'causer-id' => 44,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 0, 'wall' => 0,
@ -593,6 +609,7 @@ return [
'causer-id' => 42, 'causer-id' => 42,
'vid' => 8, 'vid' => 8,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'visible' => 1, 'visible' => 1,
'deleted' => 0, 'deleted' => 0,
'wall' => 0, 'wall' => 0,
@ -611,6 +628,7 @@ return [
'parent-uri-id' => 6, 'parent-uri-id' => 6,
'thr-parent-id' => 6, 'thr-parent-id' => 6,
'private' => Item::PUBLIC, 'private' => Item::PUBLIC,
'global' => true,
'gravity' => GRAVITY_PARENT, 'gravity' => GRAVITY_PARENT,
'network' => Protocol::DFRN, 'network' => Protocol::DFRN,
'origin' => 0, 'origin' => 0,

View file

@ -10,6 +10,7 @@ use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Post;
use Friendica\Module\Api\ApiResponse; use Friendica\Module\Api\ApiResponse;
use Friendica\Module\BaseApi; use Friendica\Module\BaseApi;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
@ -555,6 +556,7 @@ class ApiTest extends FixtureTest
*/ */
public function testApiRssExtra() public function testApiRssExtra()
{ {
/*
$user_info = ['url' => 'user_url', 'lang' => 'en']; $user_info = ['url' => 'user_url', 'lang' => 'en'];
$result = api_rss_extra([], $user_info); $result = api_rss_extra([], $user_info);
self::assertEquals($user_info, $result['$user']); self::assertEquals($user_info, $result['$user']);
@ -565,6 +567,7 @@ class ApiTest extends FixtureTest
self::assertArrayHasKey('atom_updated', $result['$rss']); self::assertArrayHasKey('atom_updated', $result['$rss']);
self::assertArrayHasKey('language', $result['$rss']); self::assertArrayHasKey('language', $result['$rss']);
self::assertArrayHasKey('logo', $result['$rss']); self::assertArrayHasKey('logo', $result['$rss']);
*/
} }
/** /**
@ -574,6 +577,7 @@ class ApiTest extends FixtureTest
*/ */
public function testApiRssExtraWithoutUserInfo() public function testApiRssExtraWithoutUserInfo()
{ {
/*
$result = api_rss_extra([], null); $result = api_rss_extra([], null);
self::assertIsArray($result['$user']); self::assertIsArray($result['$user']);
self::assertArrayHasKey('alternate', $result['$rss']); self::assertArrayHasKey('alternate', $result['$rss']);
@ -583,26 +587,7 @@ class ApiTest extends FixtureTest
self::assertArrayHasKey('atom_updated', $result['$rss']); self::assertArrayHasKey('atom_updated', $result['$rss']);
self::assertArrayHasKey('language', $result['$rss']); self::assertArrayHasKey('language', $result['$rss']);
self::assertArrayHasKey('logo', $result['$rss']); self::assertArrayHasKey('logo', $result['$rss']);
} */
/**
* Test the api_unique_id_to_nurl() function.
*
* @return void
*/
public function testApiUniqueIdToNurl()
{
self::assertFalse(api_unique_id_to_nurl($this->wrongUserId));
}
/**
* Test the api_unique_id_to_nurl() function with a correct ID.
*
* @return void
*/
public function testApiUniqueIdToNurlWithCorrectId()
{
self::assertEquals($this->otherUser['nurl'], api_unique_id_to_nurl($this->otherUser['id']));
} }
/** /**
@ -763,29 +748,6 @@ class ApiTest extends FixtureTest
self::assertSelfUser(DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray()); self::assertSelfUser(DI::twitterUser()->createFromUserId(BaseApi::getCurrentUserID())->toArray());
} }
/**
* Test the api_item_get_user() function.
*
* @return void
*/
public function testApiItemGetUser()
{
$users = api_item_get_user($this->app, []);
self::assertSelfUser($users[0]);
}
/**
* Test the api_item_get_user() function with a different item parent.
*
* @return void
*/
public function testApiItemGetUserWithDifferentParent()
{
$users = api_item_get_user($this->app, ['thr-parent' => 'item_parent', 'uri' => 'item_uri']);
self::assertSelfUser($users[0]);
self::assertEquals($users[0], $users[1]);
}
/** /**
* Test the Arrays::walkRecursive() function. * Test the Arrays::walkRecursive() function.
* *
@ -1790,10 +1752,12 @@ class ApiTest extends FixtureTest
*/ */
public function testApiStatusesUserTimeline() public function testApiStatusesUserTimeline()
{ {
$_REQUEST['user_id'] = 42;
$_REQUEST['max_id'] = 10; $_REQUEST['max_id'] = 10;
$_REQUEST['exclude_replies'] = true; $_REQUEST['exclude_replies'] = true;
$_REQUEST['conversation_id'] = 1; $_REQUEST['conversation_id'] = 7;
$result = api_statuses_user_timeline('json');
$result = api_statuses_user_timeline('json');
self::assertNotEmpty($result['status']); self::assertNotEmpty($result['status']);
foreach ($result['status'] as $status) { foreach ($result['status'] as $status) {
self::assertStatus($status); self::assertStatus($status);
@ -1807,8 +1771,10 @@ class ApiTest extends FixtureTest
*/ */
public function testApiStatusesUserTimelineWithNegativePage() public function testApiStatusesUserTimelineWithNegativePage()
{ {
$_REQUEST['page'] = -2; $_REQUEST['user_id'] = 42;
$result = api_statuses_user_timeline('json'); $_REQUEST['page'] = -2;
$result = api_statuses_user_timeline('json');
self::assertNotEmpty($result['status']); self::assertNotEmpty($result['status']);
foreach ($result['status'] as $status) { foreach ($result['status'] as $status) {
self::assertStatus($status); self::assertStatus($status);
@ -2262,21 +2228,9 @@ class ApiTest extends FixtureTest
*/ */
public function testApiFormatItems() public function testApiFormatItems()
{ {
$items = [ $items = Post::selectToArray([], ['uid' => 42]);
[ foreach ($items as $item) {
'item_network' => 'item_network', $status = api_format_item($item);
'source' => 'web',
'coord' => '5 7',
'body' => '',
'verb' => '',
'author-id' => 43,
'author-network' => Protocol::DFRN,
'author-link' => 'http://localhost/profile/othercontact',
'plink' => '',
]
];
$result = api_format_items($items, ['id' => 0], true);
foreach ($result as $status) {
self::assertStatus($status); self::assertStatus($status);
} }
} }
@ -2287,19 +2241,9 @@ class ApiTest extends FixtureTest
*/ */
public function testApiFormatItemsWithXml() public function testApiFormatItemsWithXml()
{ {
$items = [ $items = Post::selectToArray([], ['uid' => 42]);
[ foreach ($items as $item) {
'coord' => '5 7', $status = api_format_item($item, 'xml');
'body' => '',
'verb' => '',
'author-id' => 43,
'author-network' => Protocol::DFRN,
'author-link' => 'http://localhost/profile/othercontact',
'plink' => '',
]
];
$result = api_format_items($items, ['id' => 0], true, 'xml');
foreach ($result as $status) {
self::assertStatus($status); self::assertStatus($status);
} }
} }
@ -2602,9 +2546,9 @@ class ApiTest extends FixtureTest
public function testApiDirectMessagesNewWithScreenName() public function testApiDirectMessagesNewWithScreenName()
{ {
$this->app->setLoggedInUserNickname($this->selfUser['nick']); $this->app->setLoggedInUserNickname($this->selfUser['nick']);
$_POST['text'] = 'message_text'; $_POST['text'] = 'message_text';
$_POST['screen_name'] = $this->friendUser['nick']; $_POST['user_id'] = $this->friendUser['id'];
$result = api_direct_messages_new('json'); $result = api_direct_messages_new('json');
self::assertStringContainsString('message_text', $result['direct_message']['text']); self::assertStringContainsString('message_text', $result['direct_message']['text']);
self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']); self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
self::assertEquals(1, $result['direct_message']['friendica_seen']); self::assertEquals(1, $result['direct_message']['friendica_seen']);
@ -2618,10 +2562,10 @@ class ApiTest extends FixtureTest
public function testApiDirectMessagesNewWithTitle() public function testApiDirectMessagesNewWithTitle()
{ {
$this->app->setLoggedInUserNickname($this->selfUser['nick']); $this->app->setLoggedInUserNickname($this->selfUser['nick']);
$_POST['text'] = 'message_text'; $_POST['text'] = 'message_text';
$_POST['screen_name'] = $this->friendUser['nick']; $_POST['user_id'] = $this->friendUser['id'];
$_REQUEST['title'] = 'message_title'; $_REQUEST['title'] = 'message_title';
$result = api_direct_messages_new('json'); $result = api_direct_messages_new('json');
self::assertStringContainsString('message_text', $result['direct_message']['text']); self::assertStringContainsString('message_text', $result['direct_message']['text']);
self::assertStringContainsString('message_title', $result['direct_message']['text']); self::assertStringContainsString('message_title', $result['direct_message']['text']);
self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']); self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
@ -2636,9 +2580,9 @@ class ApiTest extends FixtureTest
public function testApiDirectMessagesNewWithRss() public function testApiDirectMessagesNewWithRss()
{ {
$this->app->setLoggedInUserNickname($this->selfUser['nick']); $this->app->setLoggedInUserNickname($this->selfUser['nick']);
$_POST['text'] = 'message_text'; $_POST['text'] = 'message_text';
$_POST['screen_name'] = $this->friendUser['nick']; $_POST['user_id'] = $this->friendUser['id'];
$result = api_direct_messages_new('rss'); $result = api_direct_messages_new('rss');
self::assertXml($result, 'direct-messages'); self::assertXml($result, 'direct-messages');
} }
@ -3068,7 +3012,7 @@ class ApiTest extends FixtureTest
*/ */
public function testCheckAclInput() public function testCheckAclInput()
{ {
$result = check_acl_input('<aclstring>'); $result = check_acl_input('<aclstring>', BaseApi::getCurrentUserID());
// Where does this result come from? // Where does this result come from?
self::assertEquals(1, $result); self::assertEquals(1, $result);
} }
@ -3080,7 +3024,7 @@ class ApiTest extends FixtureTest
*/ */
public function testCheckAclInputWithEmptyAclString() public function testCheckAclInputWithEmptyAclString()
{ {
$result = check_acl_input(' '); $result = check_acl_input(' ', BaseApi::getCurrentUserID());
self::assertFalse($result); self::assertFalse($result);
} }
@ -3161,18 +3105,6 @@ class ApiTest extends FixtureTest
self::assertEquals('some_text [url="some_url"]"some_url"[/url]', $result); self::assertEquals('some_text [url="some_url"]"some_url"[/url]', $result);
} }
/**
* Test the api_best_nickname() function.
*
* @return void
*/
public function testApiBestNickname()
{
$contacts = [];
$result = api_best_nickname($contacts);
self::assertNull($result);
}
/** /**
* Test the api_best_nickname() function with contacts. * Test the api_best_nickname() function with contacts.
* *

View file

@ -3,7 +3,9 @@
namespace Friendica\Test\src\Module\Api; namespace Friendica\Test\src\Module\Api;
use Friendica\App\Arguments; use Friendica\App\Arguments;
use Friendica\App\BaseURL;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Factory\Api\Twitter\User;
use Friendica\Test\MockedTest; use Friendica\Test\MockedTest;
use Friendica\Test\Util\ApiResponseDouble; use Friendica\Test\Util\ApiResponseDouble;
use Psr\Log\NullLogger; use Psr\Log\NullLogger;
@ -22,8 +24,10 @@ class ApiResponseTest extends MockedTest
$l10n = \Mockery::mock(L10n::class); $l10n = \Mockery::mock(L10n::class);
$args = \Mockery::mock(Arguments::class); $args = \Mockery::mock(Arguments::class);
$args->shouldReceive('getQueryString')->andReturn(''); $args->shouldReceive('getQueryString')->andReturn('');
$baseUrl = \Mockery::mock(BaseURL::class);
$twitterUser = \Mockery::mock(User::class);
$response = new ApiResponseDouble($l10n, $args, new NullLogger()); $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
$response->error(200, 'OK', 'error_message', 'json'); $response->error(200, 'OK', 'error_message', 'json');
self::assertEquals('{"error":"error_message","code":"200 OK","request":""}', ApiResponseDouble::getOutput()); self::assertEquals('{"error":"error_message","code":"200 OK","request":""}', ApiResponseDouble::getOutput());
@ -34,8 +38,10 @@ class ApiResponseTest extends MockedTest
$l10n = \Mockery::mock(L10n::class); $l10n = \Mockery::mock(L10n::class);
$args = \Mockery::mock(Arguments::class); $args = \Mockery::mock(Arguments::class);
$args->shouldReceive('getQueryString')->andReturn(''); $args->shouldReceive('getQueryString')->andReturn('');
$baseUrl = \Mockery::mock(BaseURL::class);
$twitterUser = \Mockery::mock(User::class);
$response = new ApiResponseDouble($l10n, $args, new NullLogger()); $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
$response->error(200, 'OK', 'error_message', 'xml'); $response->error(200, 'OK', 'error_message', 'xml');
self::assertEquals('<?xml version="1.0"?>' . "\n" . self::assertEquals('<?xml version="1.0"?>' . "\n" .
@ -54,8 +60,10 @@ class ApiResponseTest extends MockedTest
$l10n = \Mockery::mock(L10n::class); $l10n = \Mockery::mock(L10n::class);
$args = \Mockery::mock(Arguments::class); $args = \Mockery::mock(Arguments::class);
$args->shouldReceive('getQueryString')->andReturn(''); $args->shouldReceive('getQueryString')->andReturn('');
$baseUrl = \Mockery::mock(BaseURL::class);
$twitterUser = \Mockery::mock(User::class);
$response = new ApiResponseDouble($l10n, $args, new NullLogger()); $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
$response->error(200, 'OK', 'error_message', 'rss'); $response->error(200, 'OK', 'error_message', 'rss');
self::assertEquals( self::assertEquals(
@ -75,8 +83,10 @@ class ApiResponseTest extends MockedTest
$l10n = \Mockery::mock(L10n::class); $l10n = \Mockery::mock(L10n::class);
$args = \Mockery::mock(Arguments::class); $args = \Mockery::mock(Arguments::class);
$args->shouldReceive('getQueryString')->andReturn(''); $args->shouldReceive('getQueryString')->andReturn('');
$baseUrl = \Mockery::mock(BaseURL::class);
$twitterUser = \Mockery::mock(User::class);
$response = new ApiResponseDouble($l10n, $args, new NullLogger()); $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
$response->error(200, 'OK', 'error_message', 'atom'); $response->error(200, 'OK', 'error_message', 'atom');
self::assertEquals( self::assertEquals(
@ -99,8 +109,10 @@ class ApiResponseTest extends MockedTest
}); });
$args = \Mockery::mock(Arguments::class); $args = \Mockery::mock(Arguments::class);
$args->shouldReceive('getQueryString')->andReturn(''); $args->shouldReceive('getQueryString')->andReturn('');
$baseUrl = \Mockery::mock(BaseURL::class);
$twitterUser = \Mockery::mock(User::class);
$response = new ApiResponseDouble($l10n, $args, new NullLogger()); $response = new ApiResponseDouble($l10n, $args, new NullLogger(), $baseUrl, $twitterUser);
$response->unsupported(); $response->unsupported();
self::assertEquals('{"error":"API endpoint %s %s is not implemented","error_description":"The API endpoint is currently not implemented but might be in the future."}', ApiResponseDouble::getOutput()); self::assertEquals('{"error":"API endpoint %s %s is not implemented","error_description":"The API endpoint is currently not implemented but might be in the future."}', ApiResponseDouble::getOutput());