summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorBrion Vibber <brion@pobox.com>2010-02-12 18:54:48 +0000
committerBrion Vibber <brion@pobox.com>2010-02-12 18:54:48 +0000
commitb39047d95b447251de75d15b986017286aca05e0 (patch)
tree672187a4803b899f1e4d2d709a8f820b938d00d6 /plugins
parentb57e3dfae2f48ef6097fef04df218201783abed1 (diff)
OStatus: prep work for sending notifications on sub/unsub/join/leave/favorite/unfavorite via Salmon; needs to be completed and hooked up once feed gen is fixed.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/OStatus/classes/Ostatus_profile.php153
1 files changed, 152 insertions, 1 deletions
diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php
index f7bbcd028..733d8843b 100644
--- a/plugins/OStatus/classes/Ostatus_profile.php
+++ b/plugins/OStatus/classes/Ostatus_profile.php
@@ -300,6 +300,71 @@ class Ostatus_profile extends Memcached_DataObject
}
/**
+ * Returns an XML string fragment with profile information as an
+ * Activity Streams noun object with the given element type.
+ *
+ * Assumes that 'activity' namespace has been previously defined.
+ *
+ * @param string $element one of 'actor', 'subject', 'object', 'target'
+ * @return string
+ */
+ function asActivityNoun($element)
+ {
+ $xs = new XMLStringer(true);
+
+ $avatarHref = Avatar::defaultImage(AVATAR_PROFILE_SIZE);
+ $avatarType = 'image/png';
+ if ($this->isGroup()) {
+ $type = 'http://activitystrea.ms/schema/1.0/group';
+ $self = $this->localGroup();
+
+ // @fixme put a standard getAvatar() interface on groups too
+ if ($self->homepage_logo) {
+ $avatarHref = $self->homepage_logo;
+ $map = array('png' => 'image/png',
+ 'jpg' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'gif' => 'image/gif');
+ $extension = pathinfo(parse_url($avatarHref, PHP_URL_PATH), PATHINFO_EXTENSION);
+ if (isset($map[$extension])) {
+ $avatarType = $map[$extension];
+ }
+ }
+ } else {
+ $type = 'http://activitystrea.ms/schema/1.0/person';
+ $self = $this->localProfile();
+ $avatar = $self->getAvatar(AVATAR_PROFILE_SIZE);
+ if ($avatar) {
+ $avatarHref = $avatar->
+ $avatarType = $avatar->mediatype;
+ }
+ }
+ $xs->elementStart('activity:' . $element);
+ $xs->element(
+ 'activity:object-type',
+ null,
+ $type
+ );
+ $xs->element(
+ 'id',
+ null,
+ $this->homeuri); // ?
+ $xs->element('title', null, $self->getBestName());
+
+ $xs->element(
+ 'link', array(
+ 'type' => $avatarType,
+ 'href' => $avatarHref
+ ),
+ ''
+ );
+
+ $xs->elementEnd('activity:' . $element);
+
+ return $xs->getString();
+ }
+
+ /**
* Damn dirty hack!
*/
function isGroup()
@@ -397,7 +462,7 @@ class Ostatus_profile extends Memcached_DataObject
}
/**
- * Send an unsubscription request to the hub for this feed.
+ * Send a PuSH unsubscription request to the hub for this feed.
* The hub will later send us a confirmation POST to /main/push/callback.
*
* @return bool true on success, false on failure
@@ -407,6 +472,92 @@ class Ostatus_profile extends Memcached_DataObject
}
/**
+ * Send an Activity Streams notification to the remote Salmon endpoint,
+ * if so configured.
+ *
+ * @param Profile $actor
+ * @param $verb eg Activity::SUBSCRIBE or Activity::JOIN
+ * @param $object object of the action; if null, the remote entity itself is assumed
+ */
+ public function notify(Profile $actor, $verb, $object=null)
+ {
+ if ($object == null) {
+ $object = $this;
+ }
+ if ($this->salmonuri) {
+ $text = 'update'; // @fixme
+ $id = 'tag:' . common_config('site', 'server') .
+ ':' . $verb .
+ ':' . $actor->id .
+ ':' . time(); // @fixme
+
+ $entry = new Atom10Entry();
+ $entry->elementStart('entry');
+ $entry->element('id', null, $id);
+ $entry->element('title', null, $text);
+ $entry->element('summary', null, $text);
+ $entry->element('published', null, common_date_w3dtf());
+
+ $entry->element('activity:verb', null, $verb);
+ $entry->raw($profile->asAtomAuthor());
+ $entry->raw($profile->asActivityActor());
+ $entry->raw($object->asActivityNoun('object'));
+ $entry->elmentEnd('entry');
+
+ $feed = $this->atomFeed($actor);
+ $feed->initFeed();
+ $feed->addEntry($entry);
+ $feed->renderEntries();
+ $feed->endFeed();
+
+ $xml = $feed->getString();
+ common_log(LOG_INFO, "Posting to Salmon endpoint $salmon: $xml");
+
+ $salmon = new Salmon(); // ?
+ $salmon->post($this->salmonuri, $xml);
+ }
+ }
+
+ function getBestName()
+ {
+ if ($this->isGroup()) {
+ return $this->localGroup()->getBestName();
+ } else {
+ return $this->localProfile()->getBestName();
+ }
+ }
+
+ function atomFeed($actor)
+ {
+ $feed = new Atom10Feed();
+ // @fixme should these be set up somewhere else?
+ $feed->addNamespace('activity', 'http://activitystrea.ms/spec/1.0/');
+ $feed->addNamesapce('thr', 'http://purl.org/syndication/thread/1.0');
+ $feed->addNamespace('georss', 'http://www.georss.org/georss');
+ $feed->addNamespace('ostatus', 'http://ostatus.org/schema/1.0');
+
+ $taguribase = common_config('integration', 'taguri');
+ $feed->setId("tag:{$taguribase}:UserTimeline:{$actor->id}"); // ???
+
+ $feed->setTitle($actor->getBestName() . ' timeline'); // @fixme
+ $feed->setUpdated(time());
+ $feed->setPublished(time());
+
+ $feed->addLink(common_url('ApiTimelineUser',
+ array('id' => $actor->id,
+ 'type' => 'atom')),
+ array('rel' => 'self',
+ 'type' => 'application/atom+xml'));
+
+ $feed->addLink(common_url('userbyid',
+ array('id' => $actor->id)),
+ array('rel' => 'alternate',
+ 'type' => 'text/html'));
+
+ return $feed;
+ }
+
+ /**
* Read and post notices for updates from the feed.
* Currently assumes that all items in the feed are new,
* coming from a PuSH hub.