+ $schema->ensureTable('magicsig', Magicsig::schemaDef());
+ return true;
+ }
+
+ function onEndShowStatusNetStyles($action) {
+ $action->cssLink(common_path('plugins/OStatus/theme/base/css/ostatus.css'));
+ return true;
+ }
+
+ function onEndShowStatusNetScripts($action) {
+ $action->script(common_path('plugins/OStatus/js/ostatus.js'));
+ return true;
+ }
+
+ /**
+ * Override the "from ostatus" bit in notice lists to link to the
+ * original post and show the domain it came from.
+ *
+ * @param Notice in $notice
+ * @param string out &$name
+ * @param string out &$url
+ * @param string out &$title
+ * @return mixed hook return code
+ */
+ function onStartNoticeSourceLink($notice, &$name, &$url, &$title)
+ {
+ if ($notice->source == 'ostatus') {
+ $bits = parse_url($notice->uri);
+ $domain = $bits['host'];
+
+ $name = $domain;
+ $url = $notice->uri;
+ $title = sprintf(_m("Sent from %s via OStatus"), $domain);
+ return false;
+ }
+ }
+
+ /**
+ * Send incoming PuSH feeds for OStatus endpoints in for processing.
+ *
+ * @param FeedSub $feedsub
+ * @param DOMDocument $feed
+ * @return mixed hook return code
+ */
+ function onStartFeedSubReceive($feedsub, $feed)
+ {
+ $oprofile = Ostatus_profile::staticGet('feeduri', $feedsub->uri);
+ if ($oprofile) {
+ $oprofile->processFeed($feed);
+ } else {
+ common_log(LOG_DEBUG, "No ostatus profile for incoming feed $feedsub->uri");
+ }
+ }
+
+ /**
+ * When about to subscribe to a remote user, start a server-to-server
+ * PuSH subscription if needed. If we can't establish that, abort.
+ *
+ * @fixme If something else aborts later, we could end up with a stray
+ * PuSH subscription. This is relatively harmless, though.
+ *
+ * @param Profile $subscriber
+ * @param Profile $other
+ *
+ * @return hook return code
+ *
+ * @throws Exception
+ */
+ function onStartSubscribe($subscriber, $other)
+ {
+ $user = User::staticGet('id', $subscriber->id);
+
+ if (empty($user)) {
+ return true;
+ }
+
+ $oprofile = Ostatus_profile::staticGet('profile_id', $other->id);
+
+ if (empty($oprofile)) {
+ return true;
+ }
+
+ if (!$oprofile->subscribe()) {
+ throw new Exception(_m('Could not set up remote subscription.'));
+ }
+ }
+
+ /**
+ * Having established a remote subscription, send a notification to the
+ * remote OStatus profile's endpoint.
+ *
+ * @param Profile $subscriber
+ * @param Profile $other
+ *
+ * @return hook return code
+ *
+ * @throws Exception
+ */
+ function onEndSubscribe($subscriber, $other)
+ {
+ $user = User::staticGet('id', $subscriber->id);
+
+ if (empty($user)) {
+ return true;
+ }
+
+ $oprofile = Ostatus_profile::staticGet('profile_id', $other->id);
+
+ if (empty($oprofile)) {
+ return true;
+ }
+
+ $act = new Activity();
+
+ $act->verb = ActivityVerb::FOLLOW;
+
+ $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);
+
+ $oprofile->notifyActivity($act);
+
+ return true;
+ }
+
+ /**
+ * Notify remote server and garbage collect unused feeds on unsubscribe.
+ * @fixme send these operations to background queues
+ *
+ * @param User $user
+ * @param Profile $other
+ * @return hook return value
+ */
+ function onEndUnsubscribe($profile, $other)
+ {
+ $user = User::staticGet('id', $profile->id);
+
+ if (empty($user)) {
+ return true;
+ }
+
+ $oprofile = Ostatus_profile::staticGet('profile_id', $other->id);
+
+ if (empty($oprofile)) {
+ return true;
+ }
+
+ // Drop the PuSH subscription if there are no other subscribers.
+ $oprofile->garbageCollect();
+
+ $act = new Activity();
+
+ $act->verb = ActivityVerb::UNFOLLOW;
+
+ $act->id = TagURI::mint('unfollow:%d:%d:%s',
+ $profile->id,
+ $other->id,
+ common_date_iso8601(time()));
+
+ $act->time = time();
+ $act->title = _("Unfollow");
+ $act->content = sprintf(_("%s stopped following %s."),
+ $profile->getBestName(),
+ $other->getBestName());
+
+ $act->actor = ActivityObject::fromProfile($profile);
+ $act->object = ActivityObject::fromProfile($other);
+
+ $oprofile->notifyActivity($act);
+
+ return true;
+ }
+
+ /**
+ * When one of our local users tries to join a remote group,
+ * notify the remote server. If the notification is rejected,
+ * deny the join.
+ *
+ * @param User_group $group
+ * @param User $user
+ *
+ * @return mixed hook return value
+ */
+
+ function onStartJoinGroup($group, $user)
+ {
+ $oprofile = Ostatus_profile::staticGet('group_id', $group->id);
+ if ($oprofile) {
+ if (!$oprofile->subscribe()) {
+ throw new Exception(_m('Could not set up remote group membership.'));
+ }
+
+ $member = Profile::staticGet($user->id);
+
+ $act = new Activity();
+ $act->id = TagURI::mint('join:%d:%d:%s',
+ $member->id,
+ $group->id,
+ common_date_iso8601(time()));
+
+ $act->actor = ActivityObject::fromProfile($member);
+ $act->verb = ActivityVerb::JOIN;
+ $act->object = $oprofile->asActivityObject();
+
+ $act->time = time();
+ $act->title = _m("Join");
+ $act->content = sprintf(_m("%s has joined group %s."),
+ $member->getBestName(),
+ $oprofile->getBestName());
+
+ if ($oprofile->notifyActivity($act)) {
+ return true;
+ } else {
+ $oprofile->garbageCollect();
+ throw new Exception(_m("Failed joining remote group."));
+ }
+ }
+ }
+
+ /**
+ * When one of our local users leaves a remote group, notify the remote
+ * server.
+ *
+ * @fixme Might be good to schedule a resend of the leave notification
+ * if it failed due to a transitory error. We've canceled the local
+ * membership already anyway, but if the remote server comes back up
+ * it'll be left with a stray membership record.
+ *
+ * @param User_group $group
+ * @param User $user
+ *
+ * @return mixed hook return value
+ */
+
+ function onEndLeaveGroup($group, $user)
+ {
+ $oprofile = Ostatus_profile::staticGet('group_id', $group->id);
+ if ($oprofile) {
+ // Drop the PuSH subscription if there are no other subscribers.
+
+ $members = $group->getMembers(0, 1);
+ if ($members->N == 0) {
+ common_log(LOG_INFO, "Unsubscribing from now-unused group feed $oprofile->feeduri");
+ $oprofile->unsubscribe();
+ }
+
+ $member = Profile::staticGet($user->id);
+
+ $act = new Activity();
+ $act->id = TagURI::mint('leave:%d:%d:%s',
+ $member->id,
+ $group->id,
+ common_date_iso8601(time()));
+
+ $act->actor = ActivityObject::fromProfile($member);
+ $act->verb = ActivityVerb::LEAVE;
+ $act->object = $oprofile->asActivityObject();
+
+ $act->time = time();
+ $act->title = _m("Leave");
+ $act->content = sprintf(_m("%s has left group %s."),
+ $member->getBestName(),
+ $oprofile->getBestName());
+
+ $oprofile->notifyActivity($act);
+ }
+ }
+
+ /**
+ * Notify remote users when their notices get favorited.
+ *
+ * @param Profile or User $profile of local user doing the faving
+ * @param Notice $notice being favored
+ * @return hook return value
+ */
+
+ function onEndFavorNotice(Profile $profile, Notice $notice)
+ {
+ $user = User::staticGet('id', $profile->id);
+
+ if (empty($user)) {
+ return true;
+ }
+
+ $oprofile = Ostatus_profile::staticGet('profile_id', $notice->profile_id);
+
+ if (empty($oprofile)) {
+ return true;
+ }
+
+ $act = new Activity();
+
+ $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);
+
+ $act->actor = ActivityObject::fromProfile($profile);
+ $act->object = ActivityObject::fromNotice($notice);
+
+ $oprofile->notifyActivity($act);
+
+ return true;
+ }
+
+ /**
+ * Notify remote users when their notices get de-favorited.
+ *
+ * @param Profile $profile Profile person doing the de-faving
+ * @param Notice $notice Notice being favored
+ *
+ * @return hook return value
+ */
+
+ function onEndDisfavorNotice(Profile $profile, Notice $notice)
+ {
+ $user = User::staticGet('id', $profile->id);
+
+ if (empty($user)) {
+ return true;
+ }
+
+ $oprofile = Ostatus_profile::staticGet('profile_id', $notice->profile_id);
+
+ if (empty($oprofile)) {
+ return true;
+ }
+
+ $act = new Activity();
+
+ $act->verb = ActivityVerb::UNFAVORITE;
+ $act->id = TagURI::mint('disfavor:%d:%d:%s',
+ $profile->id,
+ $notice->id,
+ common_date_iso8601(time()));
+ $act->time = time();
+ $act->title = _("Disfavor");
+ $act->content = sprintf(_("%s marked notice %s as no longer a favorite."),
+ $profile->getBestName(),
+ $notice->uri);
+
+ $act->actor = ActivityObject::fromProfile($profile);
+ $act->object = ActivityObject::fromNotice($notice);
+
+ $oprofile->notifyActivity($act);
+