aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Lib/Activity.php
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs/Lib/Activity.php')
-rw-r--r--Zotlabs/Lib/Activity.php640
1 files changed, 562 insertions, 78 deletions
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 6ddbbb9db..9aaf6d866 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -2,18 +2,21 @@
namespace Zotlabs\Lib;
-use Zotlabs\Lib\Libzot;
-use Zotlabs\Lib\Libsync;
-use Zotlabs\Lib\ActivityStreams;
-use Zotlabs\Lib\Group;
+use Zotlabs\Zot6\HTTPSig;
class Activity {
static function encode_object($x) {
+
if(($x) && (! is_array($x)) && (substr(trim($x),0,1)) === '{' ) {
$x = json_decode($x,true);
}
+
+ if(is_array($x) && array_key_exists('asld',$x)) {
+ $x = $x['asld'];
+ }
+
if($x['type'] === ACTIVITY_OBJ_PERSON) {
return self::fetch_person($x);
}
@@ -26,11 +29,57 @@ class Activity {
if($x['type'] === ACTIVITY_OBJ_THING) {
return self::fetch_thing($x);
}
+ if($x['type'] === ACTIVITY_OBJ_EVENT) {
+ return self::fetch_event($x);
+ }
+ if($x['type'] === ACTIVITY_OBJ_PHOTO) {
+ return self::fetch_image($x);
+ }
return $x;
}
+ static function fetch($url,$channel = null) {
+ $redirects = 0;
+ if(! check_siteallowed($url)) {
+ logger('blacklisted: ' . $url);
+ return null;
+ }
+ if(! $channel) {
+ $channel = get_sys_channel();
+ }
+
+ logger('fetch: ' . $url, LOGGER_DEBUG);
+
+ if(strpos($url,'x-zot:') === 0) {
+ $x = ZotURL::fetch($url,$channel);
+ }
+ else {
+ $m = parse_url($url);
+ $headers = [
+ 'Accept' => 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+ 'Host' => $m['host'],
+ '(request-target)' => 'get ' . get_request_string($url),
+ 'Date' => datetime_convert('UTC','UTC','now','D, d M Y H:i:s') . ' UTC'
+ ];
+ $h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
+ $x = z_fetch_url($url, true, $redirects, [ 'headers' => $h ] );
+ }
+
+ if($x['success']) {
+ $y = json_decode($x['body'],true);
+ logger('returned: ' . json_encode($y,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
+ return json_decode($x['body'], true);
+ }
+ else {
+ logger('fetch failed: ' . $url);
+ }
+ return null;
+ }
+
+
+
static function fetch_person($x) {
return self::fetch_profile($x);
@@ -93,6 +142,63 @@ class Activity {
}
}
+
+ static function fetch_image($x) {
+
+
+ $ret = [
+ 'type' => 'Image',
+ 'id' => $x['id'],
+ 'name' => $x['title'],
+ 'content' => bbcode($x['body']),
+ 'source' => [ 'mediaType' => 'text/bbcode', 'content' => $x['body'] ],
+ 'published' => datetime_convert('UTC','UTC',$x['created'],ATOM_TIME),
+ 'updated' => datetime_convert('UTC','UTC', $x['edited'],ATOM_TIME),
+ 'url' => [
+ 'type' => 'Link',
+ 'mediaType' => $x['link'][0]['type'],
+ 'href' => $x['link'][0]['href'],
+ 'width' => $x['link'][0]['width'],
+ 'height' => $x['link'][0]['height']
+ ]
+ ];
+ return $ret;
+ }
+
+ static function fetch_event($x) {
+
+ // convert old Zot event objects to ActivityStreams Event objects
+
+ if (array_key_exists('content',$x) && array_key_exists('dtstart',$x)) {
+ $ev = bbtoevent($x['content']);
+ if($ev) {
+
+ $actor = null;
+ if(array_key_exists('author',$x) && array_key_exists('link',$x['author'])) {
+ $actor = $x['author']['link'][0]['href'];
+ }
+ $y = [
+ 'type' => 'Event',
+ 'id' => z_root() . '/event/' . $ev['event_hash'],
+ 'summary' => bbcode($ev['summary']),
+ // RFC3339 Section 4.3
+ 'startTime' => (($ev['adjust']) ? datetime_convert('UTC','UTC',$ev['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$ev['dtstart'],'Y-m-d\\TH:i:s-00:00')),
+ 'content' => bbcode($ev['description']),
+ 'location' => [ 'type' => 'Place', 'content' => bbcode($ev['location']) ],
+ 'source' => [ 'content' => format_event_bbcode($ev), 'mediaType' => 'text/bbcode' ],
+ 'actor' => $actor,
+ ];
+ if($actor) {
+ return $y;
+ }
+ }
+ }
+
+ return $x;
+
+ }
+
+
static function encode_item_collection($items,$id,$type,$extra = null) {
$ret = [
@@ -167,7 +273,7 @@ class Activity {
$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid']));
if($i['title'])
- $ret['title'] = bbcode($i['title']);
+ $ret['name'] = $i['title'];
$ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME);
if($i['created'] !== $i['edited'])
@@ -342,10 +448,17 @@ class Activity {
$ret['type'] = 'Tombstone';
$ret['formerType'] = self::activity_obj_mapper($i['obj_type']);
$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid']));
+ $actor = self::encode_person($i['author'],false);
+ if($actor)
+ $ret['actor'] = $actor;
+ else
+ return [];
return $ret;
}
$ret['type'] = self::activity_mapper($i['verb']);
+
+
$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/activity/' . urlencode($i['mid']));
if($i['title'])
@@ -417,6 +530,10 @@ class Activity {
if(! is_array($i['obj'])) {
$i['obj'] = json_decode($i['obj'],true);
}
+ if($i['obj']['type'] === ACTIVITY_OBJ_PHOTO) {
+ $i['obj']['id'] = $i['id'];
+ }
+
$obj = self::encode_object($i['obj']);
if($obj)
$ret['object'] = $obj;
@@ -540,6 +657,12 @@ class Activity {
}
+
+
+
+
+
+
static function activity_mapper($verb) {
if(strpos($verb,'/') === false) {
@@ -556,6 +679,9 @@ class Activity {
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
+ 'http://purl.org/zot/activity/attendyes' => 'Accept',
+ 'http://purl.org/zot/activity/attendno' => 'Reject',
+ 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
];
@@ -582,6 +708,70 @@ class Activity {
}
+
+ static function activity_decode_mapper($verb) {
+
+ $acts = [
+ 'http://activitystrea.ms/schema/1.0/post' => 'Create',
+ 'http://activitystrea.ms/schema/1.0/share' => 'Announce',
+ 'http://activitystrea.ms/schema/1.0/update' => 'Update',
+ 'http://activitystrea.ms/schema/1.0/like' => 'Like',
+ 'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
+ 'http://purl.org/zot/activity/dislike' => 'Dislike',
+ 'http://activitystrea.ms/schema/1.0/tag' => 'Add',
+ 'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
+ 'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
+ 'http://purl.org/zot/activity/attendyes' => 'Accept',
+ 'http://purl.org/zot/activity/attendno' => 'Reject',
+ 'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
+ ];
+
+
+ foreach($acts as $k => $v) {
+ if($verb === $v) {
+ return $k;
+ }
+ }
+
+ logger('Unmapped activity: ' . $verb);
+ return 'Create';
+
+ }
+
+ static function activity_obj_decode_mapper($obj) {
+
+ $objs = [
+ 'http://activitystrea.ms/schema/1.0/note' => 'Note',
+ 'http://activitystrea.ms/schema/1.0/note' => 'Article',
+ 'http://activitystrea.ms/schema/1.0/comment' => 'Note',
+ 'http://activitystrea.ms/schema/1.0/person' => 'Person',
+ 'http://purl.org/zot/activity/profile' => 'Profile',
+ 'http://activitystrea.ms/schema/1.0/photo' => 'Image',
+ 'http://activitystrea.ms/schema/1.0/profile-photo' => 'Icon',
+ 'http://activitystrea.ms/schema/1.0/event' => 'Event',
+ 'http://activitystrea.ms/schema/1.0/wiki' => 'Document',
+ 'http://purl.org/zot/activity/location' => 'Place',
+ 'http://purl.org/zot/activity/chessgame' => 'Game',
+ 'http://purl.org/zot/activity/tagterm' => 'zot:Tag',
+ 'http://purl.org/zot/activity/thing' => 'Object',
+ 'http://purl.org/zot/activity/file' => 'zot:File',
+ 'http://purl.org/zot/activity/mood' => 'zot:Mood',
+
+ ];
+
+ foreach($objs as $k => $v) {
+ if($obj === $v) {
+ return $k;
+ }
+ }
+
+ logger('Unmapped activity object: ' . $obj);
+ return 'Note';
+ }
+
+
+
+
static function activity_obj_mapper($obj) {
if(strpos($obj,'/') === false) {
@@ -1149,7 +1339,7 @@ class Activity {
}
if($act->obj['type'] === 'Note' && $s['attach']) {
- $s['body'] .= self::bb_attach($s['attach']);
+ $s['body'] .= self::bb_attach($s['attach'],$s['body']);
}
// we will need a hook here to extract magnet links e.g. peertube
@@ -1230,21 +1420,39 @@ class Activity {
}
+ static function get_actor_bbmention($id) {
- static function decode_note($act) {
+ $x = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_hash = '%s' or hubloc_id_url = '%s' limit 1",
+ dbesc($id),
+ dbesc($id)
+ );
- $s = [];
+ if($x) {
+ return sprintf('@[zrl=%s]%s[/zrl]',$x[0]['xchan_url'],$x[0]['xchan_name']);
+ }
+ return '@{' . $id . '}';
+ }
- $content = self::get_content($act->obj);
+ static function decode_note($act) {
+
+ $response_activity = false;
+
+ $s = [];
+ if(is_array($act->obj)) {
+ $content = self::get_content($act->obj);
+ }
+
$s['owner_xchan'] = $act->actor['id'];
$s['author_xchan'] = $act->actor['id'];
- $s['mid'] = $act->id;
- $s['parent_mid'] = $act->parent_id;
+ // ensure we store the original actor
+ self::actor_store($act->actor['id'],$act->actor);
+ $s['mid'] = $act->obj['id'];
+ $s['parent_mid'] = $act->parent_id;
if($act->data['published']) {
$s['created'] = datetime_convert('UTC','UTC',$act->data['published']);
@@ -1259,105 +1467,325 @@ class Activity {
$s['edited'] = datetime_convert('UTC','UTC',$act->obj['updated']);
}
- if(! $s['created'])
- $s['created'] = datetime_convert();
- if(! $s['edited'])
- $s['edited'] = $s['created'];
+ if(in_array($act->type, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept' ])) {
- if(in_array($act->type,['Announce'])) {
- $root_content = self::get_content($act->raw);
+ $response_activity = true;
- $s['title'] = self::bb_content($root_content,'name');
- $s['summary'] = self::bb_content($root_content,'summary');
- $s['body'] = (self::bb_content($root_content,'bbcode') ? : self::bb_content($root_content,'content'));
+ $s['mid'] = $act->id;
+ $s['parent_mid'] = $act->obj['id'];
- if(strpos($s['body'],'[share') === false) {
+ // over-ride the object timestamp with the activity
- // @fixme - error check and set defaults
+ if($act->data['published']) {
+ $s['created'] = datetime_convert('UTC','UTC',$act->data['published']);
+ }
- $name = urlencode($act->obj['actor']['name']);
- $profile = $act->obj['actor']['id'];
- $photo = $act->obj['icon']['url'];
+ if($act->data['updated']) {
+ $s['edited'] = datetime_convert('UTC','UTC',$act->data['updated']);
+ }
+
+ $obj_actor = ((isset($act->obj['actor'])) ? $act->obj['actor'] : $act->get_actor('attributedTo', $act->obj));
+ // ensure we store the original actor
+ self::actor_store($obj_actor['id'],$obj_actor);
- $s['body'] .= "\r\n[share author='" . $name .
- "' profile='" . $profile .
- "' avatar='" . $photo .
- "' link='" . $act->obj['id'] .
- "' auth='" . ((is_matrix_url($act->obj['id'])) ? 'true' : 'false' ) .
- "' posted='" . $act->obj['published'] .
- "' message_id='" . $act->obj['id'] .
- "']";
+ $mention = self::get_actor_bbmention($obj_actor['id']);
+
+ if($act->type === 'Like') {
+ $content['content'] = sprintf( t('Likes %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
+ }
+ if($act->type === 'Dislike') {
+ $content['content'] = sprintf( t('Doesn\'t like %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
+ }
+ if($act->type === 'Accept' && $act->obj['type'] === 'Event' ) {
+ $content['content'] = sprintf( t('Will attend %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
+ }
+ if($act->type === 'Reject' && $act->obj['type'] === 'Event' ) {
+ $content['content'] = sprintf( t('Will not attend %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
+ }
+ if($act->type === 'TentativeAccept' && $act->obj['type'] === 'Event' ) {
+ $content['content'] = sprintf( t('May attend %1$s\'s %2$s'),$mention,$act->obj['type']) . "\n\n" . $content['content'];
+ }
+ if($act->type === 'Announce') {
+ $content['content'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, $act->obj['type']);
}
}
- else {
- $s['title'] = self::bb_content($content,'name');
- $s['summary'] = self::bb_content($content,'summary');
- $s['body'] = (self::bb_content($content,'bbcode') ? : self::bb_content($content,'content'));
- }
- $s['verb'] = self::activity_mapper($act->type);
+ if(! $s['created'])
+ $s['created'] = datetime_convert();
+
+ if(! $s['edited'])
+ $s['edited'] = $s['created'];
+
+ $s['title'] = self::bb_content($content,'name');
+ $s['summary'] = self::bb_content($content,'summary');
+ $s['body'] = ((self::bb_content($content,'bbcode') && (! $response_activity)) ? self::bb_content($content,'bbcode') : self::bb_content($content,'content'));
- if($act->type === 'Tombstone') {
+ $s['verb'] = self::activity_decode_mapper($act->type);
+
+
+ if($act->type === 'Tombstone' || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) {
$s['item_deleted'] = 1;
}
- $s['obj_type'] = self::activity_obj_mapper($act->obj['type']);
- $s['obj'] = $act->obj;
+ $s['obj_type'] = self::activity_obj_decode_mapper($act->obj['type']);
+ if($s['obj_type'] === ACTIVITY_OBJ_NOTE && $s['mid'] !== $s['parent_mid']) {
+ $s['obj_type'] = ACTIVITY_OBJ_COMMENT;
+ }
+
+ if($act->obj['type'] === 'Event') {
+ $s['obj'] = [];
+ $s['obj']['asld'] = $act->obj;
+ $s['obj']['type'] = ACTIVITY_OBJ_EVENT;
+ $s['obj']['id'] = $act->obj['id'];
+ $s['obj']['title'] = $act->obj['summary'];
+
+ if(strpos($act->obj['startTime'],'Z'))
+ $s['obj']['adjust'] = true;
+ else
+ $s['obj']['adjust'] = false;
+
+ $s['obj']['dtstart'] = datetime_convert('UTC','UTC',$act->obj['startTime']);
+ if($act->obj['endTime'])
+ $s['obj']['dtend'] = datetime_convert('UTC','UTC',$act->obj['endTime']);
+ else
+ $s['obj']['nofinish'] = true;
+ $s['obj']['description'] = $act->obj['content'];
+
+ if(array_path_exists('location/content',$act->obj))
+ $s['obj']['location'] = $act->obj['location']['content'];
+
+ }
+ else {
+ $s['obj'] = $act->obj;
+ }
$instrument = $act->get_property_obj('instrument');
- if(! $instrument)
+ if((! $instrument) && (! $response_activity)) {
$instrument = $act->get_property_obj('instrument',$act->obj);
+ }
if($instrument && array_key_exists('type',$instrument)
&& $instrument['type'] === 'Service' && array_key_exists('name',$instrument)) {
$s['app'] = escape_tags($instrument['name']);
}
- $a = self::decode_taxonomy($act->obj);
- if($a) {
- $s['term'] = $a;
+
+ if(! $response_activity) {
+ $a = self::decode_taxonomy($act->obj);
+ if($a) {
+ $s['term'] = $a;
+ foreach($a as $b) {
+ if($b['ttype'] === TERM_EMOJI) {
+ $s['title'] = str_replace($b['term'],'[img=16x16]' . $b['url'] . '[/img]',$s['title']);
+ $s['summary'] = str_replace($b['term'],'[img=16x16]' . $b['url'] . '[/img]',$s['summary']);
+ $s['body'] = str_replace($b['term'],'[img=16x16]' . $b['url'] . '[/img]',$s['body']);
+ }
+ }
+ }
+
+ $a = self::decode_attachment($act->obj);
+ if($a) {
+ $s['attach'] = $a;
+ }
}
- $a = self::decode_attachment($act->obj);
- if($a) {
- $s['attach'] = $a;
+ if($act->obj['type'] === 'Note' && $s['attach']) {
+ $s['body'] .= self::bb_attach($s['attach'],$s['body']);
}
+
// we will need a hook here to extract magnet links e.g. peertube
// right now just link to the largest mp4 we find that will fit in our
// standard content region
- if($act->obj['type'] === 'Video') {
+ if(! $response_activity) {
+ if($act->obj['type'] === 'Video') {
- $vtypes = [
- 'video/mp4',
- 'video/ogg',
- 'video/webm'
- ];
+ $vtypes = [
+ 'video/mp4',
+ 'video/ogg',
+ 'video/webm'
+ ];
- $mps = [];
- if(array_key_exists('url',$act->obj) && is_array($act->obj['url'])) {
- foreach($act->obj['url'] as $vurl) {
- if(in_array($vurl['mimeType'], $vtypes)) {
- if(! array_key_exists('width',$vurl)) {
- $vurl['width'] = 0;
+ $mps = [];
+ $ptr = null;
+
+ if(array_key_exists('url',$act->obj)) {
+ if(is_array($act->obj['url'])) {
+ if(array_key_exists(0,$act->obj['url'])) {
+ $ptr = $act->obj['url'];
}
- $mps[] = $vurl;
+ else {
+ $ptr = [ $act->obj['url'] ];
+ }
+ foreach($ptr as $vurl) {
+ // peertube uses the non-standard element name 'mimeType' here
+ if(array_key_exists('mimeType',$vurl)) {
+ if(in_array($vurl['mimeType'], $vtypes)) {
+ if(! array_key_exists('width',$vurl)) {
+ $vurl['width'] = 0;
+ }
+ $mps[] = $vurl;
+ }
+ }
+ elseif(array_key_exists('mediaType',$vurl)) {
+ if(in_array($vurl['mediaType'], $vtypes)) {
+ if(! array_key_exists('width',$vurl)) {
+ $vurl['width'] = 0;
+ }
+ $mps[] = $vurl;
+ }
+ }
+ }
+ }
+ if($mps) {
+ usort($mps,[ __CLASS__, 'vid_sort' ]);
+ foreach($mps as $m) {
+ if(intval($m['width']) < 500 && self::media_not_in_body($m['href'],$s['body'])) {
+ $s['body'] .= "\n\n" . '[video]' . $m['href'] . '[/video]';
+ break;
+ }
+ }
+ }
+ elseif(is_string($act->obj['url']) && self::media_not_in_body($act->obj['url'],$s['body'])) {
+ $s['body'] .= "\n\n" . '[video]' . $act->obj['url'] . '[/video]';
}
}
}
- if($mps) {
- usort($mps,'as_vid_sort');
- foreach($mps as $m) {
- if(intval($m['width']) < 500) {
- $s['body'] .= "\n\n" . '[video]' . $m['href'] . '[/video]';
- break;
+
+ if($act->obj['type'] === 'Audio') {
+
+ $atypes = [
+ 'audio/mpeg',
+ 'audio/ogg',
+ 'audio/wav'
+ ];
+
+ $ptr = null;
+
+ if(array_key_exists('url',$act->obj)) {
+ if(is_array($act->obj['url'])) {
+ if(array_key_exists(0,$act->obj['url'])) {
+ $ptr = $act->obj['url'];
+ }
+ else {
+ $ptr = [ $act->obj['url'] ];
+ }
+ foreach($ptr as $vurl) {
+ if(in_array($vurl['mediaType'], $atypes) && self::media_not_in_body($vurl['href'],$s['body'])) {
+ $s['body'] .= "\n\n" . '[audio]' . $vurl['href'] . '[/audio]';
+ break;
+ }
+ }
+ }
+ elseif(is_string($act->obj['url']) && self::media_not_in_body($act->obj['url'],$s['body'])) {
+ $s['body'] .= "\n\n" . '[audio]' . $act->obj['url'] . '[/audio]';
+ }
+ }
+
+ }
+
+ // avoid double images from hubzilla to zap/osada
+
+ if($act->obj['type'] === 'Image' && strpos($s['body'],'zrl=') === false) {
+
+ $ptr = null;
+
+ if(array_key_exists('url',$act->obj)) {
+ if(is_array($act->obj['url'])) {
+ if(array_key_exists(0,$act->obj['url'])) {
+ $ptr = $act->obj['url'];
+ }
+ else {
+ $ptr = [ $act->obj['url'] ];
+ }
+ foreach($ptr as $vurl) {
+ if(strpos($s['body'],$vurl['href']) === false) {
+ $s['body'] .= "\n\n" . '[zmg]' . $vurl['href'] . '[/zmg]';
+ break;
+ }
+ }
+ }
+ elseif(is_string($act->obj['url'])) {
+ if(strpos($s['body'],$act->obj['url']) === false) {
+ $s['body'] .= "\n\n" . '[zmg]' . $act->obj['url'] . '[/zmg]';
+ }
+ }
+ }
+ }
+
+
+ if($act->obj['type'] === 'Page' && ! $s['body']) {
+
+ $ptr = null;
+ $purl = EMPTY_STR;
+
+ if(array_key_exists('url',$act->obj)) {
+ if(is_array($act->obj['url'])) {
+ if(array_key_exists(0,$act->obj['url'])) {
+ $ptr = $act->obj['url'];
+ }
+ else {
+ $ptr = [ $act->obj['url'] ];
+ }
+ foreach($ptr as $vurl) {
+ if(array_key_exists('mediaType',$vurl) && $vurl['mediaType'] === 'text/html') {
+ $purl = $vurl['href'];
+ break;
+ }
+ elseif(array_key_exists('mimeType',$vurl) && $vurl['mimeType'] === 'text/html') {
+ $purl = $vurl['href'];
+ break;
+ }
+ }
+ }
+ elseif(is_string($act->obj['url'])) {
+ $purl = $act->obj['url'];
+ }
+ if($purl) {
+ $li = z_fetch_url(z_root() . '/linkinfo?binurl=' . bin2hex($purl));
+ if($li['success'] && $li['body']) {
+ $s['body'] .= "\n" . $li['body'];
+ }
+ else {
+ $s['body'] .= "\n\n" . $purl;
+ }
}
}
}
}
+
+
+ if(in_array($act->obj['type'],[ 'Note','Article','Page' ])) {
+ $ptr = null;
+
+ if(array_key_exists('url',$act->obj)) {
+ if(is_array($act->obj['url'])) {
+ if(array_key_exists(0,$act->obj['url'])) {
+ $ptr = $act->obj['url'];
+ }
+ else {
+ $ptr = [ $act->obj['url'] ];
+ }
+ foreach($ptr as $vurl) {
+ if(array_key_exists('mediaType',$vurl) && $vurl['mediaType'] === 'text/html') {
+ $s['plink'] = $vurl['href'];
+ break;
+ }
+ }
+ }
+ elseif(is_string($act->obj['url'])) {
+ $s['plink'] = $act->obj['url'];
+ }
+ }
+ }
+
+ if(! $s['plink']) {
+ $s['plink'] = $s['mid'];
+ }
+
if($act->recips && (! in_array(ACTIVITY_PUBLIC_INBOX,$act->recips)))
$s['item_private'] = 1;
@@ -1371,8 +1799,6 @@ class Activity {
}
-
-
static function announce_note($channel,$observer_hash,$act) {
$s = [];
@@ -1464,7 +1890,7 @@ class Activity {
$body .= self::bb_content($content,'content');
if($act->obj['type'] === 'Note' && $s['attach']) {
- $body .= self::bb_attach($s['attach']);
+ $body .= self::bb_attach($s['attach'],$body);
}
$body .= "[/share]";
@@ -1642,19 +2068,26 @@ class Activity {
}
- static function bb_attach($attach) {
+
+ static function bb_attach($attach,$body) {
$ret = false;
foreach($attach as $a) {
if(strpos($a['type'],'image') !== false) {
- $ret .= "\n\n" . '[img]' . $a['href'] . '[/img]';
+ if(self::media_not_in_body($a['href'],$body)) {
+ $ret .= "\n\n" . '[img]' . $a['href'] . '[/img]';
+ }
}
if(array_key_exists('type',$a) && strpos($a['type'], 'video') === 0) {
- $ret .= "\n\n" . '[video]' . $a['href'] . '[/video]';
+ if(self::media_not_in_body($a['href'],$body)) {
+ $ret .= "\n\n" . '[video]' . $a['href'] . '[/video]';
+ }
}
if(array_key_exists('type',$a) && strpos($a['type'], 'audio') === 0) {
- $ret .= "\n\n" . '[audio]' . $a['href'] . '[/audio]';
+ if(self::media_not_in_body($a['href'],$body)) {
+ $ret .= "\n\n" . '[audio]' . $a['href'] . '[/audio]';
+ }
}
}
@@ -1662,16 +2095,31 @@ class Activity {
}
+ // check for the existence of existing media link in body
+
+ static function media_not_in_body($s,$body) {
+
+ if((strpos($body,']' . $s . '[/img]') === false) &&
+ (strpos($body,']' . $s . '[/zmg]') === false) &&
+ (strpos($body,']' . $s . '[/video]') === false) &&
+ (strpos($body,']' . $s . '[/audio]') === false)) {
+ return true;
+ }
+ return false;
+ }
+
static function bb_content($content,$field) {
require_once('include/html2bbcode.php');
-
+ require_once('include/event.php');
$ret = false;
if(is_array($content[$field])) {
foreach($content[$field] as $k => $v) {
- $ret .= '[language=' . $k . ']' . html2bbcode($v) . '[/language]';
+ $ret .= html2bbcode($v);
+ // save this for auto-translate or dynamic filtering
+ // $ret .= '[language=' . $k . ']' . html2bbcode($v) . '[/language]';
}
}
else {
@@ -1682,6 +2130,9 @@ class Activity {
$ret = html2bbcode($content[$field]);
}
}
+ if($field === 'content' && $content['event'] && (! strpos($ret,'[event'))) {
+ $ret .= format_event_bbcode($content['event']);
+ }
return $ret;
}
@@ -1690,21 +2141,52 @@ class Activity {
static function get_content($act) {
$content = [];
- if (! $act) {
+ $event = null;
+
+ if ((! $act) || (! is_array($act))) {
return $content;
}
+ if($act['type'] === 'Event') {
+ $adjust = false;
+ $event = [];
+ $event['event_hash'] = $act['id'];
+ if(array_key_exists('startTime',$act) && strpos($act['startTime'],-1,1) === 'Z') {
+ $adjust = true;
+ $event['adjust'] = 1;
+ $event['dtstart'] = datetime_convert('UTC','UTC',$event['startTime'] . (($adjust) ? '' : 'Z'));
+ }
+ if(array_key_exists('endTime',$act)) {
+ $event['dtend'] = datetime_convert('UTC','UTC',$event['endTime'] . (($adjust) ? '' : 'Z'));
+ }
+ else {
+ $event['nofinish'] = true;
+ }
+ }
+
foreach ([ 'name', 'summary', 'content' ] as $a) {
if (($x = self::get_textfield($act,$a)) !== false) {
$content[$a] = $x;
}
}
+
+ if($event) {
+ $event['summary'] = html2bbcode($content['summary']);
+ $event['description'] = html2bbcode($content['content']);
+ if($event['summary'] && $event['dtstart']) {
+ $content['event'] = $event;
+ }
+ }
+
if (array_key_exists('source',$act) && array_key_exists('mediaType',$act['source'])) {
if ($act['source']['mediaType'] === 'text/bbcode') {
$content['bbcode'] = purify_html($act['source']['content']);
}
}
+
+
+
return $content;
}
@@ -1722,4 +2204,6 @@ class Activity {
}
return $content;
}
+
+
} \ No newline at end of file