Twitter-compatible API - Favorites now working!

darcs-hash:20080930194435-462f3-a0a7fec3f0d05dc3b1fe8a9219155f4d59092e43.gz
This commit is contained in:
zach 2008-09-30 15:44:35 -04:00
parent bbd5f6b471
commit 37b3bd5489
4 changed files with 254 additions and 115 deletions

View File

@ -24,34 +24,179 @@ require_once(INSTALLDIR.'/lib/twitterapi.php');
class TwitapifavoritesAction extends TwitterapiAction { class TwitapifavoritesAction extends TwitterapiAction {
function is_readonly() { function is_readonly() {
static $write_methods = array('favorites'); static $write_methods = array('favorites');
$cmdtext = explode('.', $this->arg('method')); $cmdtext = explode('.', $this->arg('method'));
if (in_array($cmdtext[0], $write_methods)) { if (in_array($cmdtext[0], $write_methods)) {
return false; return false;
} }
return true; return true;
} }
function favorites($args, $apidata) { function favorites($args, $apidata) {
parent::handle($args); parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
$user = null;
// function was called with an argument /favorites/api_arg.format
if (isset($apidata['api_arg'])) {
if (is_numeric($apidata['api_arg'])) {
$user = User::staticGet($apidata['api_arg']);
} else {
$nickname = common_canonical_nickname($apidata['api_arg']);
$user = User::staticGet('nickname', $nickname);
}
} else {
// if no user was specified, then we'll use the authenticated user
$user = $apidata['user'];
}
if (!$user) {
// Set the user to be the auth user if asked-for can't be found
// honestly! This is what Twitter does, I swear --Zach
$user = $apidata['user'];
}
$profile = $user->getProfile();
if (!$profile) {
common_server_error(_('User has no profile.'));
exit();
}
$page = $this->arg('page');
if (!$page) {
$page = 1;
}
if (!$count) {
$count = 20;
}
$notice = $user->favoriteNotices((($page-1)*20), $count);
if (!$notice) {
common_server_error(_('Could not retrieve favorite notices.'));
exit();
}
$sitename = common_config('site', 'name');
$siteserver = common_config('site', 'server');
$title = sprintf(_('%s / Favorites from %s'), $sitename, $user->nickname);
$id = "tag:$siteserver:favorites:".$user->id;
$link = common_local_url('favorites', array('nickname' => $user->nickname));
$subtitle = sprintf(_('%s updates favorited by %s / %s.'), $sitename, $profile->getBestName(), $user->nickname);
switch($apidata['content-type']) {
case 'xml':
$this->show_xml_timeline($notice);
break;
case 'rss':
$this->show_rss_timeline($notice, $title, $id, $link, $subtitle);
break;
case 'atom':
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle);
break;
case 'json':
$this->show_json_timeline($notice);
break;
default:
common_user_error(_('API method not found!'), $code = 404);
}
exit(); exit();
} }
function create($args, $apidata) { function create($args, $apidata) {
parent::handle($args); parent::handle($args);
common_server_error(_('API method under construction.'), $code=501);
// Check for RESTfulness
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
// XXX: Twitter just prints the err msg, no XML / JSON.
$this->client_error(_('This method requires a POST or DELETE.'), 400, $apidata['content-type']);
exit();
}
$user = $apidata['user'];
$notice_id = $apidata['api_arg'];
$notice = Notice::staticGet($notice_id);
if (!$notice) {
$this->client_error(_('No status found with that ID.'), 404, $apidata['content-type']);
exit();
}
// XXX: Twitter lets you fave things repeatedly via api.
if ($user->hasFave($notice)) {
$this->client_error(_('This notice is already a favorite!'), 403, $apidata['content-type']);
exit();
}
common_debug("notice: " . $apidata['api_arg']);
$fave = Fave::addNew($user, $notice);
if (!$fave) {
common_server_error(_('Could not create favorite.'));
exit();
}
$this->notify($fave, $notice, $user);
$user->blowFavesCache();
if ($apidata['content-type'] == 'xml') {
$this->show_single_xml_status($notice);
} elseif ($apidata['content-type'] == 'json') {
$this->show_single_json_status($notice);
}
exit(); exit();
} }
function destroy($args, $apidata) { function destroy($args, $apidata) {
parent::handle($args); parent::handle($args);
common_server_error(_('API method under construction.'), $code=501); common_server_error(_('API method under construction.'), $code=501);
exit(); exit();
} }
// XXX: these two funcs swiped from faves. Maybe put in util.php, or some common base class?
function notify($fave, $notice, $user) {
$other = User::staticGet('id', $notice->profile_id);
if ($other && $other->id != $user->id) {
if ($other->email && $other->emailnotifyfav) {
$this->notify_mail($other, $user, $notice);
}
# XXX: notify by IM
# XXX: notify by SMS
}
}
function notify_mail($other, $user, $notice) {
$profile = $user->getProfile();
$bestname = $profile->getBestName();
$subject = sprintf(_('%s added your notice as a favorite'), $bestname);
$body = sprintf(_("%1\$s just added your notice from %2\$s as one of their favorites.\n\n" .
"In case you forgot, you can see the text of your notice here:\n\n" .
"%3\$s\n\n" .
"You can see the list of %1\$s's favorites here:\n\n" .
"%4\$s\n\n" .
"Faithfully yours,\n" .
"%5\$s\n"),
$bestname,
common_exact_date($notice->created),
common_local_url('shownotice', array('notice' => $notice->id)),
common_local_url('showfavorites', array('nickname' => $user->nickname)),
common_config('site', 'name'));
mail_to_user($other, $subject, $body);
}
} }

View File

@ -58,7 +58,7 @@ class TwitapistatusesAction extends TwitterapiAction {
// of notices by users who have custom avatars, so fix this SQL -- Zach // of notices by users who have custom avatars, so fix this SQL -- Zach
$notice = Notice::publicStream(0, $MAX_PUBSTATUSES); $notice = Notice::publicStream(0, $MAX_PUBSTATUSES);
if ($notice) { if ($notice) {
switch($apidata['content-type']) { switch($apidata['content-type']) {
@ -86,103 +86,6 @@ class TwitapistatusesAction extends TwitterapiAction {
exit(); exit();
} }
function show_xml_timeline($notice) {
$this->init_document('xml');
common_element_start('statuses', array('type' => 'array'));
if (is_array($notice)) {
foreach ($notice as $n) {
$twitter_status = $this->twitter_status_array($n);
$this->show_twitter_xml_status($twitter_status);
}
} else {
while ($notice->fetch()) {
$twitter_status = $this->twitter_status_array($notice);
$this->show_twitter_xml_status($twitter_status);
}
}
common_element_end('statuses');
$this->end_document('xml');
}
function show_rss_timeline($notice, $title, $link, $subtitle) {
$this->init_document('rss');
common_element_start('channel');
common_element('title', NULL, $title);
common_element('link', NULL, $link);
common_element('description', NULL, $subtitle);
common_element('language', NULL, 'en-us');
common_element('ttl', NULL, '40');
if (is_array($notice)) {
foreach ($notice as $n) {
$entry = $this->twitter_rss_entry_array($n);
$this->show_twitter_rss_item($entry);
}
} else {
while ($notice->fetch()) {
$entry = $this->twitter_rss_entry_array($notice);
$this->show_twitter_rss_item($entry);
}
}
common_element_end('channel');
$this->end_twitter_rss();
}
function show_atom_timeline($notice, $title, $id, $link, $subtitle=NULL) {
$this->init_document('atom');
common_element('title', NULL, $title);
common_element('id', NULL, $id);
common_element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), NULL);
common_element('subtitle', NULL, $subtitle);
if (is_array($notice)) {
foreach ($notice as $n) {
$entry = $this->twitter_rss_entry_array($n);
$this->show_twitter_atom_entry($entry);
}
} else {
while ($notice->fetch()) {
$entry = $this->twitter_rss_entry_array($notice);
$this->show_twitter_atom_entry($entry);
}
}
$this->end_document('atom');
}
function show_json_timeline($notice) {
$this->init_document('json');
$statuses = array();
if (is_array($notice)) {
foreach ($notice as $n) {
$twitter_status = $this->twitter_status_array($n);
array_push($statuses, $twitter_status);
}
} else {
while ($notice->fetch()) {
$twitter_status = $this->twitter_status_array($notice);
array_push($statuses, $twitter_status);
}
}
$this->show_twitter_json_statuses($statuses);
$this->end_document('json');
}
/* /*
Returns the 20 most recent statuses posted by the authenticating user and that user's friends. Returns the 20 most recent statuses posted by the authenticating user and that user's friends.
This is the equivalent of /home on the Web. This is the equivalent of /home on the Web.
@ -461,7 +364,6 @@ class TwitapistatusesAction extends TwitterapiAction {
$title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname); $title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname);
$id = "tag:$siteserver:replies:".$user->id; $id = "tag:$siteserver:replies:".$user->id;
$link = common_local_url('replies', array('nickname' => $user->nickname)); $link = common_local_url('replies', array('nickname' => $user->nickname));
$subtitle = "gar";
$subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $user->nickname, $profile->getBestName()); $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $user->nickname, $profile->getBestName());
if (!$page) { if (!$page) {
@ -496,10 +398,7 @@ class TwitapistatusesAction extends TwitterapiAction {
common_user_error(_('API method not found!'), $code = 404); common_user_error(_('API method not found!'), $code = 404);
} }
exit(); exit();
} }
function show($args, $apidata) { function show($args, $apidata) {
@ -542,8 +441,6 @@ class TwitapistatusesAction extends TwitterapiAction {
parent::handle($args); parent::handle($args);
common_debug($_SERVER['REQUEST_METHOD']);
// Check for RESTfulness // Check for RESTfulness
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) { if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
// XXX: Twitter just prints the err msg, no XML / JSON. // XXX: Twitter just prints the err msg, no XML / JSON.

View File

@ -110,6 +110,7 @@ RewriteRule ^api/account/update_delivery_device(.*)$ index.php?action=api&apiact
RewriteRule ^api/account/rate_limit_status(.*)$ index.php?action=api&apiaction=account&method=rate_limit_status$1 [L,QSA] RewriteRule ^api/account/rate_limit_status(.*)$ index.php?action=api&apiaction=account&method=rate_limit_status$1 [L,QSA]
RewriteRule ^api/favorites/create/(.*)$ index.php?action=api&apiaction=favorites&method=create&argument=$1 [L,QSA] RewriteRule ^api/favorites/create/(.*)$ index.php?action=api&apiaction=favorites&method=create&argument=$1 [L,QSA]
RewriteRule ^api/favorites/destroy/(.*)$ index.php?action=api&apiaction=favorites&method=destroy&argument=$1 [L,QSA] RewriteRule ^api/favorites/destroy/(.*)$ index.php?action=api&apiaction=favorites&method=destroy&argument=$1 [L,QSA]
RewriteRule ^api/favorites/(.*)$ index.php?action=api&apiaction=favorites&method=favorites&argument=$1 [L,QSA]
RewriteRule ^api/favorites(.*)$ index.php?action=api&apiaction=favorites&method=favorites$1 [L,QSA] RewriteRule ^api/favorites(.*)$ index.php?action=api&apiaction=favorites&method=favorites$1 [L,QSA]
RewriteRule ^api/notifications/follow/(.*)$ index.php?action=api&apiaction=notifications&method=follow&argument=$1 [L,QSA] RewriteRule ^api/notifications/follow/(.*)$ index.php?action=api&apiaction=notifications&method=follow&argument=$1 [L,QSA]
RewriteRule ^api/notifications/leave/(.*)$ index.php?action=api&apiaction=notifications&method=leave&argument=$1 [L,QSA] RewriteRule ^api/notifications/leave/(.*)$ index.php?action=api&apiaction=notifications&method=leave&argument=$1 [L,QSA]

View File

@ -120,7 +120,6 @@ class TwitterapiAction extends Action {
return $entry; return $entry;
} }
function twitter_dmsg_array($message) { function twitter_dmsg_array($message) {
$twitter_dm = array(); $twitter_dm = array();
@ -240,6 +239,103 @@ class TwitterapiAction extends Action {
common_element_end('direct_message'); common_element_end('direct_message');
} }
function show_xml_timeline($notice) {
$this->init_document('xml');
common_element_start('statuses', array('type' => 'array'));
if (is_array($notice)) {
foreach ($notice as $n) {
$twitter_status = $this->twitter_status_array($n);
$this->show_twitter_xml_status($twitter_status);
}
} else {
while ($notice->fetch()) {
$twitter_status = $this->twitter_status_array($notice);
$this->show_twitter_xml_status($twitter_status);
}
}
common_element_end('statuses');
$this->end_document('xml');
}
function show_rss_timeline($notice, $title, $link, $subtitle) {
$this->init_document('rss');
common_element_start('channel');
common_element('title', NULL, $title);
common_element('link', NULL, $link);
common_element('description', NULL, $subtitle);
common_element('language', NULL, 'en-us');
common_element('ttl', NULL, '40');
if (is_array($notice)) {
foreach ($notice as $n) {
$entry = $this->twitter_rss_entry_array($n);
$this->show_twitter_rss_item($entry);
}
} else {
while ($notice->fetch()) {
$entry = $this->twitter_rss_entry_array($notice);
$this->show_twitter_rss_item($entry);
}
}
common_element_end('channel');
$this->end_twitter_rss();
}
function show_atom_timeline($notice, $title, $id, $link, $subtitle=NULL) {
$this->init_document('atom');
common_element('title', NULL, $title);
common_element('id', NULL, $id);
common_element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), NULL);
common_element('subtitle', NULL, $subtitle);
if (is_array($notice)) {
foreach ($notice as $n) {
$entry = $this->twitter_rss_entry_array($n);
$this->show_twitter_atom_entry($entry);
}
} else {
while ($notice->fetch()) {
$entry = $this->twitter_rss_entry_array($notice);
$this->show_twitter_atom_entry($entry);
}
}
$this->end_document('atom');
}
function show_json_timeline($notice) {
$this->init_document('json');
$statuses = array();
if (is_array($notice)) {
foreach ($notice as $n) {
$twitter_status = $this->twitter_status_array($n);
array_push($statuses, $twitter_status);
}
} else {
while ($notice->fetch()) {
$twitter_status = $this->twitter_status_array($notice);
array_push($statuses, $twitter_status);
}
}
$this->show_twitter_json_statuses($statuses);
$this->end_document('json');
}
// Anyone know what date format this is? // Anyone know what date format this is?
// Twitter's dates look like this: "Mon Jul 14 23:52:38 +0000 2008" -- Zach // Twitter's dates look like this: "Mon Jul 14 23:52:38 +0000 2008" -- Zach
function date_twitter($dt) { function date_twitter($dt) {