From b3235c2d024f9eb150398011e1a3c503fba5ee54 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 7 Apr 2018 15:54:26 +0200 Subject: [PATCH] Implement parts of the list API: lists/statuses lists/destroy lists/update lists/create lists/ownerships --- doc/api.md | 84 +++++++++++- include/api.php | 321 +++++++++++++++++++++++++++++++++++++++++--- src/Model/Group.php | 13 ++ 3 files changed, 397 insertions(+), 21 deletions(-) diff --git a/doc/api.md b/doc/api.md index 3306c7d4dd..76b3f3dc80 100644 --- a/doc/api.md +++ b/doc/api.md @@ -294,6 +294,85 @@ Friendica doesn't allow showing the friends of other users. --- +### lists/ownerships (*; AUTH) + +#### Parameters + +* list_id: ID of the list +* count: Items per page +* page: Page number +* since_id: Minimum ID +* max_id: Maximum ID + +#### Unsupported parameters + +* slug +* owner_screen_name +* owner_id +* include_entities +* include_rts + +--- + +### lists/destroy (POST; AUTH) + +#### Parameters + +* list_id: ID of the list + +#### Unsupported parameters + +* owner_screen_name +* owner_id +* slug + +--- + +### lists/create (POST; AUTH) + +#### Parameters + +* name: name of the list + +#### Unsupported parameters + +* mode +* description + +--- + +### lists/update (POST; AUTH) + +#### Parameters + +* list_id: ID of the list +* name: name of the list + +#### Unsupported parameters + +* slug +* name +* mode +* description +* owner_screen_name +* owner_id + +--- + +### lists/statuses (*; AUTH) + +#### Parameters + +* user_id: ID of the user for whom to return results. + +#### Unsupported parameters + +* screen_name +* count +* cursor + +--- + ### media/upload (POST,PUT; AUTH) #### Parameters @@ -1237,7 +1316,6 @@ The following API calls from the Twitter API are not implemented in either Frien * users/suggestions/:slug/members * favorites/list * lists/list -* lists/statuses * lists/members/destroy * lists/memberships * lists/subscribers @@ -1248,13 +1326,9 @@ The following API calls from the Twitter API are not implemented in either Frien * lists/members/show * lists/members * lists/members/create -* lists/destroy -* lists/update -* lists/create * lists/show * lists/subscriptions * lists/members/destroy_all -* lists/ownerships * saved_searches/show/:id * saved_searches/create * saved_searches/destroy/:id diff --git a/include/api.php b/include/api.php index 898ce49ac3..8cd7d23a73 100644 --- a/include/api.php +++ b/include/api.php @@ -3269,12 +3269,14 @@ function api_help_test($type) api_register_func('api/help/test', 'api_help_test', false); /** + * Returns all lists the user subscribes to. * * @param string $type Return type (atom, rss, xml, json) * * @return array|string + * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-list */ -function api_lists($type) +function api_lists_list($type) { $ret = []; /// @TODO $ret is not filled here? @@ -3282,25 +3284,159 @@ function api_lists($type) } /// @TODO move to top of file or somewhere better -api_register_func('api/lists', 'api_lists', true); +api_register_func('api/lists/list', 'api_lists_list', true); +api_register_func('api/lists/subscriptions', 'api_lists_list', true); /** - * Returns all lists the user subscribes to. + * Returns all groups the user owns. * * @param string $type Return type (atom, rss, xml, json) * * @return array|string - * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-list + * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships */ -function api_lists_list($type) +function api_lists_ownerships($type) { - $ret = []; - /// @TODO $ret is not filled here? - return api_format_data('lists', $type, ["lists_list" => $ret]); + $a = get_app(); + + if (api_user() === false) { + throw new ForbiddenException(); + } + + // params + $user_info = api_get_user($a); + $uid = $user_info['uid']; + + $r = q( + "SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d", + intval($uid) + ); + + // loop through all groups + foreach ($r as $rr) { + if ($rr['visible']) { + $mode = 'public'; + } else { + $mode = 'private'; + } + $grps[] = [ + 'name' => $rr['name'], + 'id' => intval($rr['id']), + 'id_str' => (string) $rr['id'], + 'user' => $user_info, + 'mode' => $mode + ]; + } + return api_format_data("lists", $type, ['lists' => ['lists'=>$grps]]); } /// @TODO move to top of file or somewhere better -api_register_func('api/lists/list', 'api_lists_list', true); +api_register_func('api/lists/ownerships', 'api_lists_ownerships', true); + +/** + * Returns recent statuses from users in the specified group. + * + * @param string $type Return type (atom, rss, xml, json) + * + * @return array|string + * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships + */ +function api_lists_statuses($type) +{ + $a = get_app(); + + if (api_user() === false) { + throw new ForbiddenException(); + } + + unset($_REQUEST["user_id"]); + unset($_GET["user_id"]); + + unset($_REQUEST["screen_name"]); + unset($_GET["screen_name"]); + + $user_info = api_get_user($a); + // get last newtork messages + + // params + $count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20); + $page = (x($_REQUEST, 'page') ? $_REQUEST['page'] - 1 : 0); + if ($page < 0) { + $page = 0; + } + $since_id = (x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0); + $max_id = (x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0); + //$since_id = 0;//$since_id = (x($_REQUEST, 'since_id')?$_REQUEST['since_id'] : 0); + $exclude_replies = (x($_REQUEST, 'exclude_replies') ? 1 : 0); + $conversation_id = (x($_REQUEST, 'conversation_id') ? $_REQUEST['conversation_id'] : 0); + + $start = $page * $count; + + $sql_extra = ''; + if ($max_id > 0) { + $sql_extra .= ' AND `item`.`id` <= ' . intval($max_id); + } + if ($exclude_replies > 0) { + $sql_extra .= ' AND `item`.`parent` = `item`.`id`'; + } + if ($conversation_id > 0) { + $sql_extra .= ' AND `item`.`parent` = ' . intval($conversation_id); + } + + $r = q( + "SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`, + `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, + `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, + `contact`.`id` AS `cid`, `group_member`.`gid` + FROM `item` + STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid` + AND (NOT `contact`.`blocked` OR `contact`.`pending`) + STRAIGHT_JOIN `group_member` ON `group_member`.`contact-id` = `item`.`contact-id` + WHERE `item`.`uid` = %d AND `verb` = '%s' + AND `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted` + $sql_extra + AND `item`.`id`>%d + AND `group_member`.`gid` = %d + ORDER BY `item`.`id` DESC LIMIT %d ,%d ", + intval(api_user()), + dbesc(ACTIVITY_POST), + intval($since_id), + intval($_REQUEST['list_id']), + intval($start), + intval($count) + ); + + $ret = api_format_items($r, $user_info, false, $type); + + // Set all posts from the query above to seen + $idarray = []; + foreach ($r as $item) { + $idarray[] = intval($item["id"]); + } + + $idlist = implode(",", $idarray); + + if ($idlist != "") { + $unseen = q("SELECT `id` FROM `item` WHERE `unseen` AND `id` IN (%s)", $idlist); + + if ($unseen) { + q("UPDATE `item` SET `unseen` = 0 WHERE `unseen` AND `id` IN (%s)", $idlist); + } + } + + $data = ['status' => $ret]; + switch ($type) { + case "atom": + case "rss": + $data = api_rss_extra($a, $data, $user_info); + break; + } + + return api_format_data("statuses", $type, $data); +} + +/// @TODO move to top of file or somewhere better +api_register_func('api/lists/statuses', 'api_lists_statuses', true); /** * Considers friends and followers lists to be private and won't return @@ -5436,15 +5572,15 @@ function api_friendica_group_delete($type) } api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', true, API_METHOD_DELETE); - /** - * Create the specified group with the posted array of contacts. + * Delete a group. * * @param string $type Return type (atom, rss, xml, json) * * @return array|string + * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-destroy */ -function api_friendica_group_create($type) +function api_lists_destroy($type) { $a = get_app(); @@ -5454,11 +5590,49 @@ function api_friendica_group_create($type) // params $user_info = api_get_user($a); - $name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : ""); + $gid = (x($_REQUEST, 'list_id') ? $_REQUEST['list_id'] : 0); $uid = $user_info['uid']; - $json = json_decode($_POST['json'], true); - $users = $json['user']; + // error if no gid specified + if ($gid == 0) { + throw new BadRequestException('gid not specified'); + } + + // get data of the specified group id + $r = q( + "SELECT * FROM `group` WHERE `uid` = %d AND `id` = %d", + intval($uid), + intval($gid) + ); + // error message if specified gid is not in database + if (!DBM::is_result($r)) { + throw new BadRequestException('gid not available'); + } + + if (Group::remove($gid)) { + $grp = [ + 'name' => $r[0]['name'], + 'id' => intval($gid), + 'id_str' => (string) $gid, + 'user' => $user_info + ]; + + return api_format_data("lists", $type, ['lists'=>$grp]); + } +} +api_register_func('api/lists/destroy', 'api_lists_destroy', true, API_METHOD_DELETE); + +/** + * Add a new group to the database. + * + * @param string $name Group name + * @param int $uid User ID + * @param array $users List of users to add to the group + * + * @return array + */ +function group_create($name, $uid, $users = []) +{ // error if no name specified if ($name == "") { throw new BadRequestException('group name not specified'); @@ -5515,11 +5689,72 @@ function api_friendica_group_create($type) // return success message incl. missing users in array $status = ($erroraddinguser ? "missing user" : ($reactivate_group ? "reactivated" : "ok")); - $success = ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers]; + + return ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers]; +} + +/** + * Create the specified group with the posted array of contacts. + * + * @param string $type Return type (atom, rss, xml, json) + * + * @return array|string + */ +function api_friendica_group_create($type) +{ + $a = get_app(); + + if (api_user() === false) { + throw new ForbiddenException(); + } + + // params + $user_info = api_get_user($a); + $name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : ""); + $uid = $user_info['uid']; + $json = json_decode($_POST['json'], true); + $users = $json['user']; + + $success = group_create($name, $uid, $users); + return api_format_data("group_create", $type, ['result' => $success]); } api_register_func('api/friendica/group_create', 'api_friendica_group_create', true, API_METHOD_POST); +/** + * Create a new group. + * + * @param string $type Return type (atom, rss, xml, json) + * + * @return array|string + * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-create + */ +function api_list_create($type) +{ + $a = get_app(); + + if (api_user() === false) { + throw new ForbiddenException(); + } + + // params + $user_info = api_get_user($a); + $name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : ""); + $uid = $user_info['uid']; + + $success = group_create($name, $uid); + if ($success['success']) { + $grp = [ + 'name' => $success['name'], + 'id' => intval($success['gid']), + 'id_str' => (string) $success['gid'], + 'user' => $user_info + ]; + + return api_format_data("lists", $type, ['lists'=>$grp]); + } +} +api_register_func('api/lists/create', 'api_list_create', true, API_METHOD_POST); /** * Update the specified group with the posted array of contacts. @@ -5594,6 +5829,60 @@ function api_friendica_group_update($type) api_register_func('api/friendica/group_update', 'api_friendica_group_update', true, API_METHOD_POST); +/** + * Update information about a group. + * + * @param string $type Return type (atom, rss, xml, json) + * + * @return array|string + * @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-update + */ +function api_lists_update($type) +{ + $a = get_app(); + + if (api_user() === false) { + throw new ForbiddenException(); + } + + // params + $user_info = api_get_user($a); + $gid = (x($_REQUEST, 'list_id') ? $_REQUEST['list_id'] : 0); + $name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : ""); + $uid = $user_info['uid']; + + // error if no gid specified + if ($gid == 0) { + throw new BadRequestException('gid not specified'); + } + + // get data of the specified group id + $r = q( + "SELECT * FROM `group` WHERE `uid` = %d AND `id` = %d", + intval($uid), + intval($gid) + ); + // error message if specified gid is not in database + if (!DBM::is_result($r)) { + throw new BadRequestException('gid not available'); + } + + if (Group::update($gid, $name)) { + $grp = [ + 'name' => $name, + 'id' => intval($gid), + 'id_str' => (string) $gid, + 'user' => $user_info + ]; + + return api_format_data("lists", $type, ['lists'=>$grp]); + } + + return api_format_data("group_update", $type, ['result' => $success]); +} + +api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST); + /** * * @param string $type Return type (atom, rss, xml, json) diff --git a/src/Model/Group.php b/src/Model/Group.php index 28af7b045f..50a3affa19 100644 --- a/src/Model/Group.php +++ b/src/Model/Group.php @@ -54,6 +54,19 @@ class Group extends BaseObject return $return; } + /** + * Update group information. + * + * @param int $id Group ID + * @param string $name Group name + * + * @return bool Was the update successful? + */ + public static function update($id, $name) + { + return dba::update('group', ['name' => $name], ['id' => $id]); + } + /** * @brief Get a list of group ids a contact belongs to * -- 2.39.5