From cfe67a9c0192129448ea3f0b98aadf49e962fd4d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 12 Dec 2009 16:00:27 -0500 Subject: [PATCH] add statuses/retweets_of_me to API --- actions/apitimelineretweetsofme.php | 126 ++++++++++++++++++++++++++++ classes/Notice.php | 14 ++++ classes/User.php | 53 ++++++++++++ lib/router.php | 4 + 4 files changed, 197 insertions(+) create mode 100644 actions/apitimelineretweetsofme.php diff --git a/actions/apitimelineretweetsofme.php b/actions/apitimelineretweetsofme.php new file mode 100644 index 0000000000..479bff4315 --- /dev/null +++ b/actions/apitimelineretweetsofme.php @@ -0,0 +1,126 @@ +. + * + * @category API + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/mediafile.php'; + +/** + * Show authenticating user's most recent notices that have been repeated + * + * @category API + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiTimelineRetweetsOfMeAction extends ApiAuthAction +{ + const DEFAULTCOUNT = 20; + const MAXCOUNT = 200; + const MAXNOTICES = 3200; + + var $repeats = null; + var $cnt = self::DEFAULTCOUNT; + var $page = 1; + var $since_id = null; + var $max_id = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $cnt = $this->int('count', self::DEFAULTCOUNT, self::MAXCOUNT, 1); + + $page = $this->int('page', 1, (self::MAXNOTICES/$this->cnt)); + + $since_id = $this->int('since_id'); + + $max_id = $this->int('max_id'); + + return true; + } + + /** + * Handle the request + * + * show a timeline of the user's repeated notices + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + + $offset = ($this->page-1) * $this->cnt; + $limit = $this->cnt; + + $strm = $this->auth_user->repeatsOfMe($offset, $limit, $this->since_id, $this->max_id); + + switch ($this->format) { + case 'xml': + $this->showXmlTimeline($strm); + break; + case 'json': + $this->showJsonTimeline($strm); + break; + case 'atom': + $profile = $this->auth_user->getProfile(); + + $title = sprintf(_("Repeats of %s"), $this->auth_user->nickname); + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:RepeatsOfMe:" . $this->auth_user->id; + $link = common_local_url('showstream', + array('nickname' => $this->auth_user->nickname)); + + $this->showAtomTimeline($strm, $title, $id, $link); + break; + + default: + $this->clientError(_('API method not found!'), $code = 404); + break; + } + } +} diff --git a/classes/Notice.php b/classes/Notice.php index 6a701ae0cd..eb611f314f 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -463,6 +463,20 @@ class Notice extends Memcached_DataObject $user->free(); unset($user); } + + $original = Notice::staticGet('id', $this->repeat_of); + + if (!empty($original)) { + $originalUser = User::staticGet('id', $original->profile_id); + if (!empty($originalUser)) { + $ouk = common_cache_key('user:repeats_of_me:'.$originalUser->id); + $cache->delete($ouk); + $originalUser->free(); + unset($originalUser); + } + $original->free(); + unset($original); + } } } } diff --git a/classes/User.php b/classes/User.php index 4b7365fc7a..b3da448a68 100644 --- a/classes/User.php +++ b/classes/User.php @@ -793,4 +793,57 @@ class User extends Memcached_DataObject return $ids; } + + function repeatsOfMe($offset=0, $limit=20, $since_id=null, $max_id=null) + { + $ids = Notice::stream(array($this, '_repeatsOfMeDirect'), + array(), + 'user:repeats_of_me:'.$this->id, + $offset, $limit, $since_id, $max_id, null); + + return Notice::getStreamByIds($ids); + } + + function _repeatsOfMeDirect($offset, $limit, $since_id, $max_id, $since) + { + $qry = + 'SELECT DISTINCT original.id AS id ' . + 'FROM notice original JOIN notice rept ON original.id = rept.repeat_of ' . + 'WHERE original.profile_id = ' . $this->id . ' '; + + if ($since_id != 0) { + $qry .= 'AND original.id > ' . $since_id . ' '; + } + + if ($max_id != 0) { + $qry .= 'AND original.id <= ' . $max_id . ' '; + } + + if (!is_null($since)) { + $qry .= 'AND original.modified > \'' . date('Y-m-d H:i:s', $since) . '\' '; + } + + // NOTE: we sort by fave time, not by notice time! + + $qry .= 'ORDER BY original.id DESC '; + + if (!is_null($offset)) { + $qry .= "LIMIT $limit OFFSET $offset"; + } + + $ids = array(); + + $notice = new Notice(); + + $notice->query($qry); + + while ($notice->fetch()) { + $ids[] = $notice->id; + } + + $notice->free(); + $notice = NULL; + + return $ids; + } } diff --git a/lib/router.php b/lib/router.php index 5c1bd3c4ff..732caa1c7e 100644 --- a/lib/router.php +++ b/lib/router.php @@ -323,6 +323,10 @@ class Router array('action' => 'ApiTimelineRetweetedByMe', 'format' => '(xml|json|atom)')); + $m->connect('api/statuses/retweets_of_me.:format', + array('action' => 'ApiTimelineRetweetsOfMe', + 'format' => '(xml|json|atom)')); + $m->connect('api/statuses/friends.:format', array('action' => 'ApiUserFriends', 'format' => '(xml|json)'));