diff options
Diffstat (limited to 'Zotlabs/Lib/Activity.php')
-rw-r--r-- | Zotlabs/Lib/Activity.php | 640 |
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 |