X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=plugins%2FOStatus%2FOStatusPlugin.php;h=6cd935c9e52ebbb63a12ae329b0f2147f583774d;hb=0f1fc36a05c8d858827718255bef20e8d0c0d3f6;hp=ad4f613891206ce03cab76a72efc317cfd265c07;hpb=62d5f1addb1b710a387f7732ace1dd33bd1b86c1;p=quix0rs-gnu-social.git diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index ad4f613891..6cd935c9e5 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -28,6 +28,15 @@ set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/ext class FeedSubException extends Exception { + function __construct($msg=null) + { + $type = get_class($this); + if ($msg) { + parent::__construct("$type: $msg"); + } else { + parent::__construct($type); + } + } } class OStatusPlugin extends Plugin @@ -87,6 +96,8 @@ class OStatusPlugin extends Plugin // Outgoing from our internal PuSH hub $qm->connect('hubconf', 'HubConfQueueHandler'); + $qm->connect('hubprep', 'HubPrepQueueHandler'); + $qm->connect('hubout', 'HubOutQueueHandler'); // Outgoing Salmon replies (when we don't need a return value) @@ -102,7 +113,10 @@ class OStatusPlugin extends Plugin */ function onStartEnqueueNotice($notice, &$transports) { - $transports[] = 'ostatus'; + if ($notice->isLocal()) { + // put our transport first, in case there's any conflict (like OMB) + array_unshift($transports, 'ostatus'); + } return true; } @@ -153,6 +167,9 @@ class OStatusPlugin extends Plugin // Also, we'll add in the salmon link $salmon = common_local_url($salmonAction, array('id' => $id)); + $feed->addLink($salmon, array('rel' => Salmon::REL_SALMON)); + + // XXX: these are deprecated $feed->addLink($salmon, array('rel' => Salmon::NS_REPLIES)); $feed->addLink($salmon, array('rel' => Salmon::NS_MENTIONS)); } @@ -206,6 +223,7 @@ class OStatusPlugin extends Plugin array('nickname' => $profile->nickname)); $output->element('a', array('href' => $url, 'class' => 'entity_remote_subscribe'), + // TRANS: Link description for link to subscribe to a remote user. _m('Subscribe')); $output->elementEnd('li'); @@ -224,23 +242,13 @@ class OStatusPlugin extends Plugin array('group' => $group->nickname)); $output->element('a', array('href' => $url, 'class' => 'entity_remote_subscribe'), + // TRANS: Link description for link to join a remote group. _m('Join')); } return true; } - /** - * Check if we've got remote replies to send via Salmon. - * - * @fixme push webfinger lookup & sending to a background queue - * @fixme also detect short-form name for remote subscribees where not ambiguous - */ - - function onEndNoticeSave($notice) - { - } - /** * Find any explicit remote mentions. Accepted forms: * Webfinger: @user@example.com @@ -256,7 +264,7 @@ class OStatusPlugin extends Plugin $matches = array(); // Webfinger matches: @user@example.com - if (preg_match_all('!(?:^|\s+)@((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)!', + if (preg_match_all('!(?:^|\s+)@((?:\w+\.)*\w+@(?:\w+\-?\w+\.)*\w+(?:\w+\-\w+)*\.\w+)!', $text, $wmatches, PREG_OFFSET_CAPTURE)) { @@ -290,7 +298,7 @@ class OStatusPlugin extends Plugin $url = "$scheme://$target"; $this->log(LOG_INFO, "Checking profile address '$url'"); try { - $oprofile = Ostatus_profile::ensureProfile($url); + $oprofile = Ostatus_profile::ensureProfileURL($url); if ($oprofile && !$oprofile->isGroup()) { $profile = $oprofile->localProfile(); $matches[$pos] = array('mentioned' => array($profile), @@ -321,6 +329,86 @@ class OStatusPlugin extends Plugin return true; } + /** + * Allow remote profile references to be used in commands: + * sub update@status.net + * whois evan@identi.ca + * reply http://identi.ca/evan hey what's up + * + * @param Command $command + * @param string $arg + * @param Profile &$profile + * @return hook return code + */ + function onStartCommandGetProfile($command, $arg, &$profile) + { + $oprofile = $this->pullRemoteProfile($arg); + if ($oprofile && !$oprofile->isGroup()) { + $profile = $oprofile->localProfile(); + return false; + } else { + return true; + } + } + + /** + * Allow remote group references to be used in commands: + * join group+statusnet@identi.ca + * join http://identi.ca/group/statusnet + * drop identi.ca/group/statusnet + * + * @param Command $command + * @param string $arg + * @param User_group &$group + * @return hook return code + */ + function onStartCommandGetGroup($command, $arg, &$group) + { + $oprofile = $this->pullRemoteProfile($arg); + if ($oprofile && $oprofile->isGroup()) { + $group = $oprofile->localGroup(); + return false; + } else { + return true; + } + } + + protected function pullRemoteProfile($arg) + { + $oprofile = null; + if (preg_match('!^((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)$!', $arg)) { + // webfinger lookup + try { + return Ostatus_profile::ensureWebfinger($arg); + } catch (Exception $e) { + common_log(LOG_ERR, 'Webfinger lookup failed for ' . + $arg . ': ' . $e->getMessage()); + } + } + + // Look for profile URLs, with or without scheme: + $urls = array(); + if (preg_match('!^https?://((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) { + $urls[] = $arg; + } + if (preg_match('!^((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) { + $schemes = array('http', 'https'); + foreach ($schemes as $scheme) { + $urls[] = "$scheme://$arg"; + } + } + + foreach ($urls as $url) { + try { + return Ostatus_profile::ensureProfileURL($url); + } catch (Exception $e) { + common_log(LOG_ERR, 'Profile lookup failed for ' . + $arg . ': ' . $e->getMessage()); + } + } + return null; + } + /** * Make sure necessary tables are filled out. */ @@ -335,12 +423,12 @@ class OStatusPlugin extends Plugin } function onEndShowStatusNetStyles($action) { - $action->cssLink(common_path('plugins/OStatus/theme/base/css/ostatus.css')); + $action->cssLink('plugins/OStatus/theme/base/css/ostatus.css'); return true; } function onEndShowStatusNetScripts($action) { - $action->script(common_path('plugins/OStatus/js/ostatus.js')); + $action->script('plugins/OStatus/js/ostatus.js'); return true; } @@ -367,10 +455,12 @@ class OStatusPlugin extends Plugin } $url = $notice->url; + // TRANSLATE: %s is a domain. $title = sprintf(_m("Sent from %s via OStatus"), $domain); return false; } } + return true; } /** @@ -390,6 +480,24 @@ class OStatusPlugin extends Plugin } } + /** + * Tell the FeedSub infrastructure whether we have any active OStatus + * usage for the feed; if not it'll be able to garbage-collect the + * feed subscription. + * + * @param FeedSub $feedsub + * @param integer $count in/out + * @return mixed hook return code + */ + function onFeedSubSubscriberCount($feedsub, &$count) + { + $oprofile = Ostatus_profile::staticGet('feeduri', $feedsub->uri); + if ($oprofile) { + $count += $oprofile->subscriberCount(); + } + return true; + } + /** * When about to subscribe to a remote user, start a server-to-server * PuSH subscription if needed. If we can't establish that, abort. @@ -419,6 +527,7 @@ class OStatusPlugin extends Plugin } if (!$oprofile->subscribe()) { + // TRANS: Exception. throw new Exception(_m('Could not set up remote subscription.')); } } @@ -448,23 +557,10 @@ class OStatusPlugin extends Plugin return true; } - $act = new Activity(); - - $act->verb = ActivityVerb::FOLLOW; + $sub = Subscription::pkeyGet(array('subscriber' => $subscriber->id, + 'subscribed' => $other->id)); - $act->id = TagURI::mint('follow:%d:%d:%s', - $subscriber->id, - $other->id, - common_date_iso8601(time())); - - $act->time = time(); - $act->title = _("Follow"); - $act->content = sprintf(_("%s is now following %s."), - $subscriber->getBestName(), - $other->getBestName()); - - $act->actor = ActivityObject::fromProfile($subscriber); - $act->object = ActivityObject::fromProfile($other); + $act = $sub->asActivity(); $oprofile->notifyActivity($act, $subscriber); @@ -506,8 +602,10 @@ class OStatusPlugin extends Plugin common_date_iso8601(time())); $act->time = time(); - $act->title = _("Unfollow"); - $act->content = sprintf(_("%s stopped following %s."), + $act->title = _m('Unfollow'); + // TRANS: Success message for unsubscribe from user attempt through OStatus. + // TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name. + $act->content = sprintf(_m('%1$s stopped following %2$s.'), $profile->getBestName(), $other->getBestName()); @@ -538,6 +636,9 @@ class OStatusPlugin extends Plugin throw new Exception(_m('Could not set up remote group membership.')); } + // NOTE: we don't use Group_member::asActivity() since that record + // has not yet been created. + $member = Profile::staticGet($user->id); $act = new Activity(); @@ -552,7 +653,9 @@ class OStatusPlugin extends Plugin $act->time = time(); $act->title = _m("Join"); - $act->content = sprintf(_m("%s has joined group %s."), + // TRANS: Success message for subscribe to group attempt through OStatus. + // TRANS: %1$s is the member name, %2$s is the subscribed group's name. + $act->content = sprintf(_m("%1$s has joined group %2$s."), $member->getBestName(), $oprofile->getBestName()); @@ -560,6 +663,7 @@ class OStatusPlugin extends Plugin return true; } else { $oprofile->garbageCollect(); + // TRANS: Exception. throw new Exception(_m("Failed joining remote group.")); } } @@ -601,7 +705,9 @@ class OStatusPlugin extends Plugin $act->time = time(); $act->title = _m("Leave"); - $act->content = sprintf(_m("%s has left group %s."), + // TRANS: Success message for unsubscribe from group attempt through OStatus. + // TRANS: %1$s is the member name, %2$s is the unsubscribed group's name. + $act->content = sprintf(_m("%1$s has left group %2$s."), $member->getBestName(), $oprofile->getBestName()); @@ -616,7 +722,6 @@ class OStatusPlugin extends Plugin * @param Notice $notice being favored * @return hook return value */ - function onEndFavorNotice(Profile $profile, Notice $notice) { $user = User::staticGet('id', $profile->id); @@ -631,22 +736,15 @@ class OStatusPlugin extends Plugin return true; } - $act = new Activity(); + $fav = Fave::pkeyGet(array('user_id' => $user->id, + 'notice_id' => $notice->id)); - $act->verb = ActivityVerb::FAVORITE; - $act->id = TagURI::mint('favor:%d:%d:%s', - $profile->id, - $notice->id, - common_date_iso8601(time())); - - $act->time = time(); - $act->title = _("Favor"); - $act->content = sprintf(_("%s marked notice %s as a favorite."), - $profile->getBestName(), - $notice->uri); + if (empty($fav)) { + // That's weird. + return true; + } - $act->actor = ActivityObject::fromProfile($profile); - $act->object = ActivityObject::fromNotice($notice); + $act = $fav->asActivity(); $oprofile->notifyActivity($act, $profile); @@ -684,8 +782,10 @@ class OStatusPlugin extends Plugin $notice->id, common_date_iso8601(time())); $act->time = time(); - $act->title = _("Disfavor"); - $act->content = sprintf(_("%s marked notice %s as no longer a favorite."), + $act->title = _m('Disfavor'); + // TRANS: Success message for remove a favorite notice through OStatus. + // TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice. + $act->content = sprintf(_m('%1$s marked notice %2$s as no longer a favorite.'), $profile->getBestName(), $notice->uri); @@ -759,8 +859,9 @@ class OStatusPlugin extends Plugin $action->elementStart('p', array('id' => 'entity_remote_subscribe', 'class' => 'entity_subscribe')); $action->element('a', array('href' => common_local_url($target), - 'class' => 'entity_remote_subscribe') - , _m('Remote')); + 'class' => 'entity_remote_subscribe'), + // TRANS: Link text for link to remote subscribe. + _m('Remote')); $action->elementEnd('p'); $action->elementEnd('div'); } @@ -799,7 +900,10 @@ class OStatusPlugin extends Plugin $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()); @@ -829,6 +933,7 @@ class OStatusPlugin extends Plugin array('nickname' => $profileUser->nickname)); $output->element('a', array('href' => $url, 'class' => 'entity_remote_subscribe'), + // TRANS: Link text for a user to subscribe to an OStatus user. _m('Subscribe')); $output->elementEnd('li'); } @@ -836,4 +941,61 @@ class OStatusPlugin extends Plugin return true; } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'OStatus', + 'version' => STATUSNET_VERSION, + 'author' => 'Evan Prodromou, James Walker, Brion Vibber, Zach Copley', + 'homepage' => 'http://status.net/wiki/Plugin:OStatus', + // TRANS: Plugin description. + 'rawdescription' => _m('Follow people across social networks that implement '. + 'OStatus.')); + + return true; + } + + /** + * Utility function to check if the given URL is a canonical group profile + * page, and if so return the ID number. + * + * @param string $url + * @return mixed int or false + */ + public static function localGroupFromUrl($url) + { + $template = common_local_url('groupbyid', array('id' => '31337')); + $template = preg_quote($template, '/'); + $template = str_replace('31337', '(\d+)', $template); + if (preg_match("/$template/", $url, $matches)) { + return intval($matches[1]); + } + return false; + } + + public function onStartProfileGetAtomFeed($profile, &$feed) + { + $oprofile = Ostatus_profile::staticGet('profile_id', $profile->id); + + if (empty($oprofile)) { + return true; + } + + $feed = $oprofile->feeduri; + return false; + } + + function onStartGetProfileFromURI($uri, &$profile) { + + // XXX: do discovery here instead (OStatus_profile::ensureProfileURI($uri)) + + $oprofile = Ostatus_profile::staticGet('uri', $uri); + + if (!empty($oprofile) && !$oprofile->isGroup()) { + $profile = $oprofile->localProfile(); + return false; + } + + return true; + } }