/** * Handle the request * * Show the user's groups * * @param array $args $_REQUEST data (unused) * * @return void */ function handle($args) { parent::handle($args); $sitename = common_config('site', 'name'); // TRANS: Message is used as a title. %s is a site name. $title = sprintf(_("%s groups"), $sitename); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:Groups"; $link = common_local_url('groups'); $subtitle = sprintf(_("groups on %s"), $sitename); switch ($this->format) { case 'xml': $this->showXmlGroups($this->groups); break; case 'rss': $this->showRssGroups($this->groups, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . 'api/statusnet/groups/list_all.atom'; $this->showAtomGroups($this->groups, $title, $id, $link, $subtitle, $selfuri); break; case 'json': $this->showJsonGroups($this->groups); break; default: $this->clientError(_('API method not found.'), 404, $this->format); break; } }
/** * Take arguments for running * * @param array $args $_REQUEST args * * @return boolean success flag * */ function prepare($args) { parent::prepare($args); $this->user = $this->auth_user; if (empty($this->user)) { // TRANS: Client error given when a user was not found (404). $this->clientError(_('No such user.'), 404, $this->format); return; } $server = common_root_url(); $taguribase = TagURI::base(); if ($this->arg('sent')) { // Action was called by /api/direct_messages/sent.format $this->title = sprintf(_("Direct messages from %s"), $this->user->nickname); $this->subtitle = sprintf(_("All the direct messages sent from %s"), $this->user->nickname); $this->link = $server . $this->user->nickname . '/outbox'; $this->selfuri_base = common_root_url() . 'api/direct_messages/sent'; $this->id = "tag:{$taguribase}:SentDirectMessages:" . $this->user->id; } else { $this->title = sprintf(_("Direct messages to %s"), $this->user->nickname); $this->subtitle = sprintf(_("All the direct messages sent to %s"), $this->user->nickname); $this->link = $server . $this->user->nickname . '/inbox'; $this->selfuri_base = common_root_url() . 'api/direct_messages'; $this->id = "tag:{$taguribase}:DirectMessages:" . $this->user->id; } $this->messages = $this->getMessages(); return true; }
/** * Handle the request * * Show the user's groups * * @return void */ protected function handle() { parent::handle(); $sitename = common_config('site', 'name'); // TRANS: Used as title in check for group membership. %s is a user name. $title = sprintf(_("%s's groups"), $this->target->nickname); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:Groups"; $link = common_local_url('usergroups', array('nickname' => $this->target->nickname)); $subtitle = sprintf(_('%1$s groups %2$s is a member of.'), $sitename, $this->target->nickname); switch ($this->format) { case 'xml': $this->showXmlGroups($this->groups); break; case 'rss': $this->showRssGroups($this->groups, $title, $link, $subtitle); break; case 'atom': $selfuri = common_local_url('ApiGroupList', array('id' => $this->target->id, 'format' => 'atom')); $this->showAtomGroups($this->groups, $title, $id, $link, $subtitle, $selfuri); break; case 'json': $this->showJsonGroups($this->groups); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), 404); } }
/** * Handle the request * * Show the user's groups * * @param array $args $_REQUEST data (unused) * * @return void */ function handle($args) { parent::handle($args); $sitename = common_config('site', 'name'); // TRANS: Used as title in check for group membership. %s is a user name. $title = sprintf(_("%s's groups"), $this->user->nickname); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:Groups"; $link = common_local_url('usergroups', array('nickname' => $this->user->nickname)); $subtitle = sprintf(_('%1$s groups %2$s is a member of.'), $sitename, $this->user->nickname); switch ($this->format) { case 'xml': $this->showXmlGroups($this->groups); break; case 'rss': $this->showRssGroups($this->groups, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . 'api/statusnet/groups/list/' . $this->user->id . '.atom'; $this->showAtomGroups($this->groups, $title, $id, $link, $subtitle, $selfuri); break; case 'json': $this->showJsonGroups($this->groups); break; default: $this->clientError(_('API method not found.'), 404, $this->format); break; } }
/** * Show the timeline of notices * * @return void */ function showTimeline() { $sitename = common_config('site', 'name'); $sitelogo = common_config('site', 'logo') ? common_config('site', 'logo') : Theme::path('logo.png'); // TRANS: Title for timeline with lastest notices with a given tag. // TRANS: %s is the tag. $title = sprintf(_("Notices tagged with %s"), $this->tag); $subtitle = sprintf(_('Updates tagged with %1$s on %2$s!'), $this->tag, $sitename); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:TagTimeline:" . $this->tag; $link = common_local_url('tag', array('tag' => $this->tag)); $self = $this->getSelfUri(); switch ($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $sitelogo, $self); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($sitelogo); $atom->setUpdated('now'); $atom->addLink($link); $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); $this->raw($atom->getString()); break; case 'json': $this->showJsonTimeline($this->notices); break; case 'as': header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); $doc = new ActivityStreamJSONDocument($this->auth_user); $doc->setTitle($title); $doc->addLink($link, 'alternate', 'text/html'); $doc->addItemsFromNotices($this->notices); $this->raw($doc->asString()); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), $code = 404); break; } }
/** * Factory method for creating a new conversation. * * Use this for locally initiated conversations. Remote notices should * preferrably supply their own conversation URIs in the OStatus feed. * * @return Conversation the new conversation DO */ static function create(Notice $notice, $uri = null) { if (empty($notice->id)) { throw new ServerException(_('Tried to create conversation for not yet inserted notice')); } $conv = new Conversation(); $conv->created = common_sql_now(); $conv->id = $notice->id; $conv->uri = $uri ?: sprintf('%s%s=%d:%s=%s:%s=%x', TagURI::mint(), 'noticeId', $notice->id, 'objectType', 'thread', 'crc32', crc32($notice->content)); $result = $conv->insert(); if ($result === false) { common_log_db_error($conv, 'INSERT', __FILE__); throw new ServerException(_('Failed to create conversation for notice')); } return $conv; }
/** * 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; // TRANS: Title for Atom feed "repeated to me". %s is the user nickname. $title = sprintf(_("Repeated to %s"), $this->auth_user->nickname); $subtitle = sprintf(_('%1$s notices that were to repeated to %2$s / %3$s.'), $sitename, $this->user->nickname, $profile->getBestName()); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:RepeatedToMe:" . $this->auth_user->id; $link = common_local_url('all', array('nickname' => $this->auth_user->nickname)); $strm = $this->auth_user->repeatedToMe($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': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setUpdated('now'); $atom->addLink($link); $id = $this->arg('id'); $atom->setSelfLink($self); $atom->addEntryFromNotices($strm); $this->raw($atom->getString()); break; case 'as': header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); $doc = new ActivityStreamJSONDocument($this->auth_user); $doc->setTitle($title); $doc->addLink($link, 'alternate', 'text/html'); $doc->addItemsFromNotices($strm); $this->raw($doc->asString()); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), $code = 404); break; } }
function asActivity() { $notice = Notice::staticGet('id', $this->notice_id); $profile = Profile::staticGet('id', $this->user_id); $act = new Activity(); $act->verb = ActivityVerb::FAVORITE; // FIXME: rationalize this with URL below $act->id = TagURI::mint('favor:%d:%d:%s', $profile->id, $notice->id, common_date_iso8601($this->modified)); $act->time = strtotime($this->modified); // TRANS: Activity title when marking a notice as favorite. $act->title = _("Favor"); // TRANS: Ntofication given when a user marks a notice as favorite. // TRANS: %1$s is a user nickname or full name, %2$s is a notice URI. $act->content = sprintf(_('%1$s marked notice %2$s as a favorite.'), $profile->getBestName(), $notice->uri); $act->actor = ActivityObject::fromProfile($profile); $act->objects[] = ActivityObject::fromNotice($notice); $url = common_local_url('AtomPubShowFavorite', array('profile' => $this->user_id, 'notice' => $this->notice_id)); $act->selfLink = $url; $act->editLink = $url; return $act; }
/** * Show the timeline of notices * * @return void */ function showTimeline() { $sitename = common_config('site', 'name'); $sitelogo = common_config('site', 'logo') ? common_config('site', 'logo') : Theme::path('logo.png'); $title = sprintf(_("%s public timeline"), $sitename); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:PublicTimeline"; $link = common_local_url('public'); $self = $this->getSelfUri(); $subtitle = sprintf(_("%s updates from everyone!"), $sitename); switch ($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $sitelogo, $self); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($sitelogo); $atom->setUpdated('now'); $atom->addLink(common_local_url('public')); $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); $this->raw($atom->getString()); break; case 'json': $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found.'), $code = 404); break; } }
/** * Delete any notifications tied to deleted notices and un-repeats * * @return boolean hook flag */ public function onNoticeDeleteRelated($notice) { $notif = new QvitterNotification(); // unrepeats if ($notice->isRepeat()) { $repeated_notice = Notice::getKV('id', $notice->repeat_of); $notif->notice_id = $repeated_notice->id; $notif->from_profile_id = $notice->profile_id; } else { $notif->notice_id = $notice->id; } $notif->delete(); // outputs an activity notice that this notice was deleted $profile = $notice->getProfile(); // don't delete if this is a user is being deleted // because that creates an infinite loop of deleting and creating notices... $user_is_deleted = false; $user = User::getKV('id', $profile->id); if ($user instanceof User && $user->hasRole(Profile_role::DELETED)) { $user_is_deleted = true; } if (!$user_is_deleted && class_exists('StatusNet') && !array_key_exists('ActivityModeration', StatusNet::getActivePlugins())) { $rendered = sprintf(_m('<a href="%1$s">%2$s</a> deleted notice <a href="%3$s">{{%4$s}}</a>.'), htmlspecialchars($profile->getUrl()), htmlspecialchars($profile->getBestName()), htmlspecialchars($notice->getUrl()), htmlspecialchars($notice->uri)); $text = sprintf(_m('%1$s deleted notice {{%2$s}}.'), $profile->getBestName(), $notice->uri); $uri = TagURI::mint('delete-notice:%d:%d:%s', $notice->profile_id, $notice->id, common_date_iso8601(common_sql_now())); $notice = Notice::saveNew($notice->profile_id, $text, ActivityPlugin::SOURCE, array('rendered' => $rendered, 'urls' => array(), 'uri' => $uri, 'verb' => 'qvitter-delete-notice', 'object_type' => ActivityObject::ACTIVITY)); } return true; }
function registrationActivity() { $profile = $this->getProfile(); $service = new ActivityObject(); $service->type = ActivityObject::SERVICE; $service->title = common_config('site', 'name'); $service->link = common_root_url(); $service->id = $service->link; $act = new Activity(); $act->actor = ActivityObject::fromProfile($profile); $act->verb = ActivityVerb::JOIN; $act->objects[] = $service; $act->id = TagURI::mint('user:register:%d', $this->id); $act->time = strtotime($this->created); $act->title = _("Register"); $act->content = sprintf(_('%1$s joined %2$s.'), $profile->getBestName(), $service->title); return $act; }
/** * Build an Atom entry similar to search.twitter.com's based on * a given notice * * @param Notice $notice the notice to use * * @return void */ function showEntry($notice) { $server = common_config('site', 'server'); $profile = $notice->getProfile(); $nurl = common_local_url('shownotice', array('notice' => $notice->id)); $this->elementStart('entry'); $taguribase = TagURI::base(); $this->element('id', null, "tag:{$taguribase}:{$notice->id}"); $this->element('published', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'text/html', 'rel' => 'alternate', 'href' => $nurl)); $this->element('title', null, common_xml_safe_str(trim($notice->content))); $this->element('content', array('type' => 'html'), $notice->rendered); $this->element('updated', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'image/png', 'rel' => 'related', 'href' => $profile->avatarUrl())); // TODO: Here is where we'd put in a link to an atom feed for threads $this->element("twitter:source", null, htmlentities($this->sourceLink($notice->source))); $this->elementStart('author'); $name = $profile->nickname; if ($profile->fullname) { $name .= ' (' . $profile->fullname . ')'; } $this->element('name', null, $name); $this->element('uri', null, common_profile_uri($profile)); $this->elementEnd('author'); $this->elementEnd('entry'); }
/** * Show the timeline of notices * * @return void */ function showTimeline() { $profile = $this->user->getProfile(); $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); $sitename = common_config('site', 'name'); $title = sprintf(_('%1$s / Bookmarks from %2$s'), $sitename, $this->user->nickname); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:Bookmarks:" . $this->user->id; $subtitle = sprintf(_('%1$s updates bookmarked by %2$s / %3$s.'), $sitename, $profile->getBestName(), $this->user->nickname); $logo = !empty($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); $link = common_local_url('bookmarks', array('nickname' => $this->user->nickname)); $self = $this->getSelfUri(); switch ($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo, $self); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($logo); $atom->setUpdated('now'); $atom->addLink($link); $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); $this->raw($atom->getString()); break; case 'json': $this->showJsonTimeline($this->notices); break; case 'as': header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); $doc = new ActivityStreamJSONDocument($this->auth_user); $doc->setTitle($title); $doc->addLink($link, 'alternate', 'text/html'); $doc->addItemsFromNotices($this->notices); $this->raw($doc->asString()); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), $code = 404); break; } }
/** * Factory method for creating a new conversation. * * Use this for locally initiated conversations. Remote notices should * preferrably supply their own conversation URIs in the OStatus feed. * * @return Conversation the new conversation DO */ static function create($uri = null, $created = null) { // Be aware that the Notice does not have an id yet since it's not inserted! $conv = new Conversation(); $conv->created = $created ?: common_sql_now(); $conv->uri = $uri ?: sprintf('%s%s=%s:%s=%s', TagURI::mint(), 'objectType', 'thread', 'nonce', common_random_hexstr(8)); // This insert throws exceptions on failure $conv->insert(); return $conv; }
/** * Show the timeline of notices * * @return void */ function showTimeline() { $sitename = common_config('site', 'name'); // TRANS: Title of API timeline for a user and friends. // TRANS: %s is a username. $title = sprintf(_("%s and friends"), $this->target->nickname); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:FriendsTimelineHiddenReplies:" . $this->target->id; $subtitle = sprintf(_('Updates from %1$s and friends on %2$s! (with replies to non-friends hidden)'), $this->target->nickname, $sitename); $logo = $this->target->avatarUrl(AVATAR_PROFILE_SIZE); $link = common_local_url('all', array('nickname' => $this->target->nickname)); $self = $this->getSelfUri(); switch ($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo, $self); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($logo); $atom->setUpdated('now'); $atom->addLink($link); $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); $this->raw($atom->getString()); break; case 'json': $this->showJsonTimeline($this->notices); break; case 'as': header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); $doc = new ActivityStreamJSONDocument($this->auth_user, $title); $doc->addLink($link, 'alternate', 'text/html'); $doc->addItemsFromNotices($this->notices); $this->raw($doc->asString()); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), 404); } }
/** * Show the timeline of notices * * @return void */ function showTimeline() { $sitename = common_config('site', 'name'); $sitelogo = common_config('site', 'logo') ? common_config('site', 'logo') : Theme::path('logo.png'); // TRANS: Title for site timeline. %s is the StatusNet sitename. $title = sprintf(_("%s public and external timeline"), $sitename); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:PublicAndExternalTimeline"; $link = common_local_url('public'); $self = $this->getSelfUri(); // TRANS: Subtitle for site timeline. %s is the StatusNet sitename. $subtitle = sprintf(_("%s updates from the whole known network!"), $sitename); switch ($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $sitelogo, $self); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($sitelogo); $atom->setUpdated('now'); $atom->addLink(common_local_url('public')); $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); $this->raw($atom->getString()); break; case 'json': $this->showJsonTimeline($this->notices); break; case 'as': header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE); $doc = new ActivityStreamJSONDocument($this->auth_user); $doc->setTitle($title); $doc->addLink($link, 'alternate', 'text/html'); $doc->addItemsFromNotices($this->notices); $this->raw($doc->asString()); break; default: // TRANS: Client error displayed when coming across a non-supported API method. $this->clientError(_('API method not found.'), $code = 404); break; } }
static function newURI($profile_id, $notice_id, $modified) { return TagURI::mint('favor:%d:%d:%s', $profile_id, $notice_id, common_date_iso8601($modified)); }
/** * Ping remote profiles with updates to this profile. * Salmon pings are queued for background processing. */ function onEndBroadcastProfile(Profile $profile) { $user = User::staticGet('id', $profile->id); // Find foreign accounts I'm subscribed to that support Salmon pings. // // @fixme we could run updates through the PuSH feed too, // in which case we can skip Salmon pings to folks who // are also subscribed to me. $sql = "SELECT * FROM ostatus_profile " . "WHERE profile_id IN " . "(SELECT subscribed FROM subscription WHERE subscriber=%d) " . "OR group_id IN " . "(SELECT group_id FROM group_member WHERE profile_id=%d)"; $oprofile = new Ostatus_profile(); $oprofile->query(sprintf($sql, $profile->id, $profile->id)); if ($oprofile->N == 0) { common_log(LOG_DEBUG, "No OStatus remote subscribees for {$profile->nickname}"); return true; } $act = new Activity(); $act->verb = ActivityVerb::UPDATE_PROFILE; $act->id = TagURI::mint('update-profile:%d:%s', $profile->id, common_date_iso8601(time())); $act->time = time(); // TRANS: Title for activity. $act->title = _m('Profile update'); // TRANS: Ping text for remote profile update through OStatus. // TRANS: %s is user that updated their profile. $act->content = sprintf(_m('%s has updated their profile page.'), $profile->getBestName()); $act->actor = ActivityObject::fromProfile($profile); $act->object = $act->actor; while ($oprofile->fetch()) { $oprofile->notifyDeferred($act, $profile); } return true; }
function onEndLeaveGroup($group, $profile) { // Only do this if config is enabled if (!$this->LeaveGroup) { return true; } if (!$profile->isLocal()) { return true; } // TRANS: Text for "left group" item in activity plugin. // TRANS: %1$s is a profile URL, %2$s is a profile name, // TRANS: %3$s is a group URL, %4$s is a group name. $rendered = sprintf(_m('<a href="%1$s">%2$s</a> left the group <a href="%3$s">%4$s</a>.'), $profile->getUrl(), $profile->getBestName(), $group->homeUrl(), $group->getBestName()); // TRANS: Text for "left group" item in activity plugin. // TRANS: %1$s is a profile name, %2$s is a profile URL, // TRANS: %3$s is a group name, %4$s is a group URL. $content = sprintf(_m('%1$s (%2$s) left the group %3$s (%4$s).'), $profile->getBestName(), $profile->getUrl(), $group->getBestName(), $group->homeUrl()); $uri = TagURI::mint('leave:%d:%d:%s', $profile->id, $group->id, common_date_iso8601(common_sql_now())); $notice = Notice::saveNew($profile->id, $content, ActivityPlugin::SOURCE, array('rendered' => $rendered, 'urls' => array(), 'groups' => array($group->id), 'uri' => $uri, 'verb' => ActivityVerb::LEAVE, 'object_type' => ActivityObject::GROUP)); return true; }
static function fromMessage(Message $message) { $object = new ActivityObject(); if (Event::handle('StartActivityObjectFromMessage', array($message, &$object))) { $object->type = ActivityObject::NOTE; $object->id = $message->uri ? $message->uri : ($message->url ? $message->url : TagURI::mint(sprintf("message:%d", $message->id))); $object->content = $message->rendered; $object->date = $message->created; if ($message->url) { $object->link = $message->url; } else { $object->link = common_local_url('showmessage', array('message' => $message->id)); } $object->extra[] = array('status_net', array('message_id' => $message->id)); Event::handle('EndActivityObjectFromMessage', array($message, &$object)); } return $object; }
/** * 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); common_debug(var_export($strm, true)); 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 = TagURI::base(); $id = "tag:{$taguribase}:RepeatsOfMe:" . $this->auth_user->id; header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setUpdated('now'); $atom->addLink(common_local_url('showstream', array('nickname' => $this->auth_user->nickname))); $id = $this->arg('id'); $aargs = array('format' => 'atom'); if (!empty($id)) { $aargs['id'] = $id; } $atom->addLink($this->getSelfUri('ApiTimelineRetweetsOfMe', $aargs), array('rel' => 'self', 'type' => 'application/atom+xml')); $atom->addEntryFromNotices($strm); $this->raw($atom->getString()); break; default: $this->clientError(_('API method not found.'), $code = 404); break; } }
/** * Show the timeline of notices * * @return void */ function showTimeline() { $profile = $this->user->getProfile(); $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); $sitename = common_config('site', 'name'); // TRANS: Timeline title for user and friends. %s is a user nickname. $title = sprintf(_("%s and friends"), $this->user->nickname); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:HomeTimeline:" . $this->user->id; $subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), $this->user->nickname, $sitename); $link = common_local_url('all', array('nickname' => $this->user->nickname)); $self = $this->getSelfUri(); $logo = !empty($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); switch ($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo, $self); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed($this->auth_user); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($logo); $atom->setUpdated('now'); $atom->addLink($link); $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); $this->raw($atom->getString()); break; case 'json': $this->showJsonTimeline($this->notices); break; default: // TRANS: Client error displayed when trying to handle an unknown API method. $this->clientError(_('API method not found.'), $code = 404); break; } }
function rssDirectMessageArray($message) { $entry = array(); $from = $message->getFrom(); $entry['title'] = sprintf('Message from %1$s to %2$s', $from->nickname, $message->getTo()->nickname); $entry['content'] = common_xml_safe_str($message->rendered); $entry['link'] = common_local_url('showmessage', array('message' => $message->id)); $entry['published'] = common_date_iso8601($message->created); $taguribase = TagURI::base(); $entry['id'] = "tag:{$taguribase}:{$entry['link']}"; $entry['updated'] = $entry['published']; $entry['author-name'] = $from->getBestName(); $entry['author-uri'] = $from->homepage; $avatar = $from->getAvatar(AVATAR_STREAM_SIZE); $entry['avatar'] = !empty($avatar) ? $avatar->url : Avatar::defaultImage(AVATAR_STREAM_SIZE); $entry['avatar-type'] = !empty($avatar) ? $avatar->mediatype : 'image/png'; // RSS item specific $entry['description'] = $entry['content']; $entry['pubDate'] = common_date_rfc2822($message->created); $entry['guid'] = $entry['link']; return $entry; }
static function newURI($profile_id, $group_id, $created) { return TagURI::mint('join:%d:%d:%s', $profile_id, $group_id, common_date_iso8601($created)); }
/** * Show the timeline of notices * * @return void */ function showTimeline() { $profile = $this->user->getProfile(); $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); $sitename = common_config('site', 'name'); $title = sprintf(_('%1$s / Updates mentioning %2$s'), $sitename, $this->user->nickname); $taguribase = TagURI::base(); $id = "tag:{$taguribase}:Mentions:" . $this->user->id; $link = common_local_url('replies', array('nickname' => $this->user->nickname)); $self = $this->getSelfUri(); $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $this->user->nickname, $profile->getBestName()); $logo = $avatar ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); switch ($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo, $self); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); $atom = new AtomNoticeFeed(); $atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($logo); $atom->setUpdated('now'); $atom->addLink($link); $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); $this->raw($atom->getString()); break; case 'json': $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found.'), $code = 404); break; } }
/** * Send an Activity Streams notification to the remote Salmon endpoint, * if so configured. * * @param Profile $actor Actor who did the activity * @param string $verb Activity::SUBSCRIBE or Activity::JOIN * @param Object $object object of the action; must define asActivityNoun($tag) */ public function notify($actor, $verb, $object = null, $target = null) { if (!$actor instanceof Profile) { $type = gettype($actor); if ($type == 'object') { $type = get_class($actor); } // TRANS: Server exception. // TRANS: %1$s is the method name the exception occured in, %2$s is the actor type. throw new ServerException(sprintf(_m('Invalid actor passed to %1$s: %2$s.'), __METHOD__, $type)); } if ($object == null) { $object = $this; } if ($this->salmonuri) { $text = 'update'; $id = TagURI::mint('%s:%s:%s', $verb, $actor->getURI(), common_date_iso8601(time())); // @todo FIXME: Consolidate all these NS settings somewhere. $attributes = array('xmlns' => Activity::ATOM, 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:media' => 'http://purl.org/syndication/atommedia'); $entry = new XMLStringer(); $entry->elementStart('entry', $attributes); $entry->element('id', null, $id); $entry->element('title', null, $text); $entry->element('summary', null, $text); $entry->element('published', null, common_date_w3dtf(common_sql_now())); $entry->element('activity:verb', null, $verb); $entry->raw($actor->asAtomAuthor()); $entry->raw($actor->asActivityActor()); $entry->raw($object->asActivityNoun('object')); if ($target != null) { $entry->raw($target->asActivityNoun('target')); } $entry->elementEnd('entry'); $xml = $entry->getString(); common_log(LOG_INFO, "Posting to Salmon endpoint {$this->salmonuri}: {$xml}"); $salmon = new Salmon(); // ? return $salmon->post($this->salmonuri, $xml, $actor); } return false; }
/** * Send an Activity Streams notification to the remote Salmon endpoint, * if so configured. * * @param Profile $actor Actor who did the activity * @param string $verb Activity::SUBSCRIBE or Activity::JOIN * @param Object $object object of the action; must define asActivityNoun($tag) */ public function notify(Profile $actor, $verb, $object = null, $target = null) { if ($object == null) { $object = $this; } if (empty($this->salmonuri)) { return false; } $text = 'update'; $id = TagURI::mint('%s:%s:%s', $verb, $actor->getURI(), common_date_iso8601(time())); // @todo FIXME: Consolidate all these NS settings somewhere. $attributes = array('xmlns' => Activity::ATOM, 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:media' => 'http://purl.org/syndication/atommedia'); $entry = new XMLStringer(); $entry->elementStart('entry', $attributes); $entry->element('id', null, $id); $entry->element('title', null, $text); $entry->element('summary', null, $text); $entry->element('published', null, common_date_w3dtf(common_sql_now())); $entry->element('activity:verb', null, $verb); $entry->raw($actor->asAtomAuthor()); $entry->raw($actor->asActivityActor()); $entry->raw($object->asActivityNoun('object')); if ($target != null) { $entry->raw($target->asActivityNoun('target')); } $entry->elementEnd('entry'); $xml = $entry->getString(); common_log(LOG_INFO, "Posting to Salmon endpoint {$this->salmonuri}: {$xml}"); Salmon::post($this->salmonuri, $xml, $actor); }
function insert() { $result = parent::insert(); if ($result === false) { common_log_db_error($this, 'INSERT', __FILE__); // TRANS: Server exception thrown when a stored object entry cannot be saved. throw new ServerException('Could not save Notice'); } // Profile::hasRepeated() abuses pkeyGet(), so we // have to clear manually if (!empty($this->repeat_of)) { $c = self::memcache(); if (!empty($c)) { $ck = self::multicacheKey('Notice', array('profile_id' => $this->profile_id, 'repeat_of' => $this->repeat_of)); $c->delete($ck); } } // Update possibly ID-dependent columns: URI, conversation // (now that INSERT has added the notice's local id) $orig = clone $this; $changed = false; // We can only get here if it's a local notice, since remote notices // should've bailed out earlier due to lacking a URI. if (empty($this->uri)) { $this->uri = sprintf('%s%s=%d:%s=%s', TagURI::mint(), 'noticeId', $this->id, 'objectType', $this->getObjectType(true)); $changed = true; } if ($changed && $this->update($orig) === false) { common_log_db_error($notice, 'UPDATE', __FILE__); // TRANS: Server exception thrown when a notice cannot be updated. throw new ServerException(_('Problem saving notice.')); } $this->blowOnInsert(); return $result; }
/** * Build an Atom entry similar to search.twitter.com's based on * a given notice * * @param Notice $notice the notice to use * * @return void */ function showEntry($notice) { $server = common_config('site', 'server'); $profile = $notice->getProfile(); $nurl = common_local_url('shownotice', array('notice' => $notice->id)); $this->elementStart('entry'); $taguribase = TagURI::base(); $this->element('id', null, "tag:{$taguribase}:{$notice->id}"); $this->element('published', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'text/html', 'rel' => 'alternate', 'href' => $nurl)); $this->element('title', null, common_xml_safe_str(trim($notice->content))); $this->element('content', array('type' => 'html'), $notice->getRendered()); $this->element('updated', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'image/png', 'rel' => 'related', 'href' => $profile->avatarUrl())); // @todo: Here is where we'd put in a link to an atom feed for threads $source = null; $ns = $notice->getSource(); if ($ns instanceof Notice_source) { if (!empty($ns->name) && !empty($ns->url)) { $source = '<a href="' . htmlspecialchars($ns->url) . '" rel="nofollow">' . htmlspecialchars($ns->name) . '</a>'; } else { $source = $ns->code; } } $this->element("twitter:source", null, $source); $this->elementStart('author'); $name = $profile->nickname; if ($profile->fullname) { // @todo Needs proper i18n? $name .= ' (' . $profile->fullname . ')'; } $this->element('name', null, $name); $this->element('uri', null, common_profile_uri($profile)); $this->elementEnd('author'); $this->elementEnd('entry'); }
function asActivity() { $subscriber = Profile::staticGet('id', $this->subscriber); $subscribed = Profile::staticGet('id', $this->subscribed); $act = new Activity(); $act->verb = ActivityVerb::FOLLOW; // XXX: rationalize this with the URL $act->id = TagURI::mint('follow:%d:%d:%s', $subscriber->id, $subscribed->id, common_date_iso8601($this->created)); $act->time = strtotime($this->created); // TRANS: Activity title when subscribing to another person. $act->title = _m('TITLE', 'Follow'); // TRANS: Notification given when one person starts following another. // TRANS: %1$s is the subscriber, %2$s is the subscribed. $act->content = sprintf(_('%1$s is now following %2$s.'), $subscriber->getBestName(), $subscribed->getBestName()); $act->actor = ActivityObject::fromProfile($subscriber); $act->objects[] = ActivityObject::fromProfile($subscribed); $url = common_local_url('AtomPubShowSubscription', array('subscriber' => $subscriber->id, 'subscribed' => $subscribed->id)); $act->selfLink = $url; $act->editLink = $url; return $act; }