diff options
author | Mario <mario@mariovavti.com> | 2024-01-25 10:13:10 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2024-01-25 10:13:10 +0000 |
commit | c0a7dfe2f6554fc66e753c456551dd580c479820 (patch) | |
tree | 2a5fe12284f8c2bfd44eb9e2af19fc9ef4e65cb4 /Zotlabs | |
parent | fe50d78a0f3d7655cd5eefb7cdae44779c52b2b1 (diff) | |
download | volse-hubzilla-c0a7dfe2f6554fc66e753c456551dd580c479820.tar.gz volse-hubzilla-c0a7dfe2f6554fc66e753c456551dd580c479820.tar.bz2 volse-hubzilla-c0a7dfe2f6554fc66e753c456551dd580c479820.zip |
refactor fetch_and_store_parents() and inroduce the fetchparents daemon
Diffstat (limited to 'Zotlabs')
-rw-r--r-- | Zotlabs/Daemon/Fetchparents.php | 39 | ||||
-rw-r--r-- | Zotlabs/Lib/Activity.php | 531 | ||||
-rw-r--r-- | Zotlabs/Lib/Libzot.php | 15 | ||||
-rw-r--r-- | Zotlabs/Module/Share.php | 22 |
4 files changed, 123 insertions, 484 deletions
diff --git a/Zotlabs/Daemon/Fetchparents.php b/Zotlabs/Daemon/Fetchparents.php new file mode 100644 index 000000000..4daf8c019 --- /dev/null +++ b/Zotlabs/Daemon/Fetchparents.php @@ -0,0 +1,39 @@ +<?php + +namespace Zotlabs\Daemon; + +use Zotlabs\Lib\Activity; + +class Fetchparents { + + static public function run($argc, $argv) { + + logger('Fetchparents invoked: ' . print_r($argv, true)); + + if ($argc < 4) { + return; + } + + $channel = channelx_by_n(intval($argv[1])); + if (!$channel) { + return; + } + + $observer_hash = $argv[2]; + if (!$observer_hash) { + return; + } + + $mid = $argv[3]; + if (!$mid) { + return; + } + + $force = $argv[4] ?? false; + + Activity::fetch_and_store_parents($channel, $observer_hash, $mid, null, $force); + + return; + + } +} diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index cf0cf8734..c2049bb7b 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -1869,31 +1869,6 @@ class Activity { } } - static function create_action($channel, $observer_hash, $act) { - - if (in_array($act->obj['type'], ['Note', 'Article', 'Video'])) { - self::create_note($channel, $observer_hash, $act); - } - - - } - - static function announce_action($channel, $observer_hash, $act) { - - if (in_array($act->type, ['Announce'])) { - self::announce_note($channel, $observer_hash, $act); - } - - } - - static function like_action($channel, $observer_hash, $act) { - - if (in_array($act->obj['type'], ['Note', 'Article', 'Video'])) { - self::like_note($channel, $observer_hash, $act); - } - - - } // sort function width decreasing static function vid_sort($a, $b) { @@ -2965,6 +2940,24 @@ class Activity { intval($channel['channel_id']) ); + if (!$parent) { + if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || $is_sys_channel) { + if ($item['verb'] === 'Announce') { + $force = true; + } + + if ($fetch_parents) { + Master::Summon(['Fetchparents', $channel['channel_id'], $observer_hash, $item['mid'], $force]); + //self::fetch_and_store_parents($channel, $observer_hash, $item, $act, $force); + return; + } + + logger('no parent'); + return; + } + } + + // TODO: if we do not have a parent stop here and move the fetch to background? if ($parent && $parent[0]['obj_type'] === 'Question') { @@ -3159,35 +3152,8 @@ class Activity { } if ($is_child_node) { - if (!$parent) { - if (!plugin_is_installed('pubcrawl')) { - return; - } - - $fetch = false; - - if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || $is_sys_channel) { - if ($item['verb'] === 'Announce') { - $force = true; - } - - $fetch = (($fetch_parents) ? self::fetch_and_store_parents($channel, $observer_hash, $item, $force) : false); - } - if ($fetch) { - $parent = q("select * from item where mid = '%s' and uid = %d", - dbesc($item['parent_mid']), - intval($item['uid']) - ); - } - } - - if (!$parent) { - logger('no parent'); - return; - } - - $item['owner_xchan'] = (($item['verb'] === 'Announce') ? $parent[0]['author_xchan'] : $parent[0]['owner_xchan']); + $item['owner_xchan'] = $parent[0]['owner_xchan']; if ($parent[0]['parent_mid'] !== $item['parent_mid']) { $item['thr_parent'] = $item['parent_mid']; @@ -3306,15 +3272,44 @@ class Activity { } - static public function fetch_and_store_parents($channel, $observer_hash, $item, $force = false) { + /** + * @brief fetch a thread upwards by either providing a message id or an item/activity pair + * + * @param array $channel + * @param array $observer_hash + * @param array $item string|array + * @param object $act activitystreams object (optional) default null + * @param bool $force disregard permissions and force storage (optional) default false + * @return bool + */ + + static public function fetch_and_store_parents($channel, $observer_hash, $item, $act = null, $force = false) { logger('fetching parents'); + if (!$item) { + return false; + } + $p = []; + $announce_init = false; + + if (is_object($act) && is_array($item)) { + $p[] = [$act, $item]; + $announce_init = ($item['verb'] === 'Announce'); + } - $announce_init = $item['verb'] === 'Announce'; + if (is_string($item)) { + $mid = $item; + $item = [ + 'parent_mid' => $mid, + 'mid' => '' + ]; + } $current_item = $item; + $i = 0; + while ($current_item['parent_mid'] !== $current_item['mid']) { $n = self::fetch($current_item['parent_mid'], $channel); @@ -3357,16 +3352,6 @@ class Activity { $item['item_fetched'] = true; - if (intval($channel['channel_system']) && intval($item['item_private'])) { - $p = []; - break; - } - - if (count($p) > 100) { - $p = []; - break; - } - if ($announce_init) { // Store the sender of the initial announce $item['source_xchan'] = $observer_hash; @@ -3376,427 +3361,43 @@ class Activity { $item['parent_mid'] = $item['thr_parent'] = $item['mid']; $item['item_thread_top'] = 1; } - - array_unshift($p, [$a, $item]); - - if ($announce_init || $item['parent_mid'] === $item['mid']) { - break; - } - } - - $current_item = $item; - } - - - if ($p) { - foreach ($p as $pv) { - if ($pv[0]->is_valid()) { - Activity::store($channel, $observer_hash, $pv[0], $pv[1], false, $force); + else { + $announce_init = ($i === 0 && $item['verb'] === 'Announce'); } - } - return true; - } - - return false; - } - /* - static public function fetch_and_store_parents($channel, $item) { - - logger('fetching parents'); - - $p = []; - - $current_item = $item; - - while ($current_item['parent_mid'] !== $current_item['mid']) { - $n = self::fetch($current_item['parent_mid'], $channel); - if (!$n) { + if (intval($channel['channel_system']) && intval($item['item_private'])) { + $p = []; break; } - $a = new ActivityStreams($n); - - //logger($a->debug()); - if (!$a->is_valid()) { + if (count($p) > 100) { + $p = []; break; } - if (is_array($a->actor) && array_key_exists('id', $a->actor)) { - self::actor_store($a->actor); - } - - $replies = null; - if (isset($a->obj['replies']['first']['items'])) { - $replies = $a->obj['replies']['first']['items']; - // we already have this one - array_diff($replies, [$current_item['mid']]); - } - - $item = null; - - switch ($a->type) { - case 'Create': - case 'Update': - //case 'Like': - //case 'Dislike': - case 'Announce': - $item = self::decode_note($a); - break; - default: - break; - - } - - $hookinfo = [ - 'a' => $a, - 'item' => $item - ]; - - call_hooks('fetch_and_store', $hookinfo); - - $item = $hookinfo['item']; - - if ($item) { - - array_unshift($p, [$a, $item, $replies]); - - if ($item['parent_mid'] === $item['mid'] || count($p) > 20) { - break; - } - - } - $current_item = $item; - } - - if ($p) { - foreach ($p as $pv) { - self::store($channel, $pv[0]->actor['id'], $pv[0], $pv[1], false); - if ($pv[2]) - self::fetch_and_store_replies($channel, $pv[2]); - } - return true; - } - - return false; - } - - static public function fetch_and_store_replies($channel, $arr) { - - logger('fetching replies'); - logger(print_r($arr, true)); - - $p = []; - - foreach ($arr as $url) { - - $n = self::fetch($url, $channel); - if (!$n) { - break; - } - - $a = new ActivityStreams($n); - - if (!$a->is_valid()) { - break; - } - - $item = null; + array_unshift($p, [$a, $item]); - switch ($a->type) { - case 'Create': - case 'Update': - case 'Like': - case 'Dislike': - case 'Announce': - $item = self::decode_note($a); - break; - default: + if ($item['parent_mid'] === $item['mid']) { break; - } - - $hookinfo = [ - 'a' => $a, - 'item' => $item - ]; - - call_hooks('fetch_and_store', $hookinfo); - - $item = $hookinfo['item']; + } - if ($item) { - array_unshift($p, [$a, $item]); } + $current_item = $item; + $i++; } if ($p) { foreach ($p as $pv) { - self::store($channel, $pv[0]->actor['id'], $pv[0], $pv[1], false); - } - } - - } -*/ - -/* this is deprecated and not used anymore - static function announce_note($channel, $observer_hash, $act) { - - $s = []; - $is_sys_channel = is_sys_channel($channel['channel_id']); - - if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !$is_sys_channel) { - logger('no permission'); - return; - } - - $content = self::get_content($act->obj); - - if (!$content) { - logger('no content'); - return; - } - - $s['owner_xchan'] = $s['author_xchan'] = $observer_hash; - - $s['aid'] = $channel['channel_account_id']; - $s['uid'] = $channel['channel_id']; - $s['mid'] = urldecode($act->obj['id']); - $s['plink'] = urldecode($act->obj['id']); - - if (!$s['created']) - $s['created'] = datetime_convert(); - - if (!$s['edited']) - $s['edited'] = $s['created']; - - - $s['parent_mid'] = $s['mid']; - - $s['verb'] = ACTIVITY_POST; - $s['obj_type'] = ACTIVITY_OBJ_NOTE; - $s['app'] = t('ActivityPub'); - - if ($channel['channel_system']) { - if (!MessageFilter::evaluate($s, get_config('system', 'pubstream_incl'), get_config('system', 'pubstream_excl'))) { - logger('post is filtered'); - return; - } - } - - $abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", - dbesc($observer_hash), - intval($channel['channel_id']) - ); - - if ($abook) { - if (!post_is_importable($s, $abook[0])) { - logger('post is filtered'); - return; - } - } - - if ($act->obj['conversation']) { - set_iconfig($s, 'ostatus', 'conversation', $act->obj['conversation'], 1); - } - - $a = self::decode_taxonomy($act->obj); - if ($a) { - $s['term'] = $a; - } - - $a = self::decode_attachment($act->obj); - if ($a) { - $s['attach'] = $a; - } - - $body = "[share author='" . urlencode($act->sharee['name']) . - "' profile='" . $act->sharee['url'] . - "' avatar='" . $act->sharee['photo_s'] . - "' link='" . ((is_array($act->obj['url'])) ? $act->obj['url']['href'] : $act->obj['url']) . - "' auth='" . ((is_matrix_url($act->obj['url'])) ? 'true' : 'false') . - "' posted='" . $act->obj['published'] . - "' message_id='" . $act->obj['id'] . - "']"; - - if ($content['name']) - $body .= self::bb_content($content, 'name') . "\r\n"; - - $body .= self::bb_content($content, 'content'); - - if ($act->obj['type'] === 'Note' && $s['attach']) { - $body .= self::bb_attach($s['attach'], $body); - } - - $body .= "[/share]"; - - $s['title'] = self::bb_content($content, 'name'); - $s['body'] = $body; - - if ($act->recips && (!in_array(ACTIVITY_PUBLIC_INBOX, $act->recips))) - $s['item_private'] = 1; - - set_iconfig($s, 'activitypub', 'recips', $act->raw_recips); - - $r = q("select created, edited from item where mid = '%s' and uid = %d limit 1", - dbesc($s['mid']), - intval($s['uid']) - ); - if ($r) { - if ($s['edited'] > $r[0]['edited']) { - $x = item_store_update($s); - } - else { - return; - } - } - else { - $x = item_store($s); - } - - if (is_array($x) && $x['item_id']) { - if ($s['owner_xchan'] === $channel['channel_hash']) { - // We are the owner of this conversation, so send all received comments back downstream - Master::Summon(['Notifier', 'comment-import', $x['item_id']]); - } - $r = q("select * from item where id = %d limit 1", - intval($x['item_id']) - ); - if ($r) { - send_status_notifications($x['item_id'], $r[0]); + if ($pv[0]->is_valid()) { + Activity::store($channel, $observer_hash, $pv[0], $pv[1], false, $force); + } } - - sync_an_item($channel['channel_id'], $x['item_id']); + return true; } - + return false; } -*/ - - static function like_note($channel, $observer_hash, $act) { - - $s = []; - - $parent = $act->obj['id']; - - if ($act->type === 'Like') - $s['verb'] = ACTIVITY_LIKE; - if ($act->type === 'Dislike') - $s['verb'] = ACTIVITY_DISLIKE; - - if (!$parent) - return; - - $r = q("select * from item where uid = %d and ( mid = '%s' or mid = '%s' ) limit 1", - intval($channel['channel_id']), - dbesc($parent), - dbesc(urldecode(basename($parent))) - ); - - if (!$r) { - logger('parent not found.'); - return; - } - - xchan_query($r); - $parent_item = $r[0]; - if ($parent_item['owner_xchan'] === $channel['channel_hash']) { - if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'post_comments')) { - logger('no comment permission.'); - return; - } - } - - if ($parent_item['mid'] === $parent_item['parent_mid']) { - $s['parent_mid'] = $parent_item['mid']; - } - else { - $s['thr_parent'] = $parent_item['mid']; - $s['parent_mid'] = $parent_item['parent_mid']; - } - - $s['owner_xchan'] = $parent_item['owner_xchan']; - $s['author_xchan'] = $observer_hash; - - $s['aid'] = $channel['channel_account_id']; - $s['uid'] = $channel['channel_id']; - $s['mid'] = $act->id; - - if (!$s['parent_mid']) - $s['parent_mid'] = $s['mid']; - - - $post_type = (($parent_item['resource_type'] === 'photo') ? t('photo') : t('post')); - - $links = [['rel' => 'alternate', 'type' => 'text/html', 'href' => $parent_item['plink']]]; - $objtype = (($parent_item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE); - - $z = q("select * from xchan where xchan_hash = '%s' limit 1", - dbesc($parent_item['author_xchan']) - ); - if ($z) - $item_author = $z[0]; - - $object = json_encode([ - 'type' => $post_type, - 'id' => $parent_item['mid'], - 'parent' => (($parent_item['thr_parent']) ? $parent_item['thr_parent'] : $parent_item['parent_mid']), - 'link' => $links, - 'title' => $parent_item['title'], - 'content' => $parent_item['body'], - 'created' => $parent_item['created'], - 'edited' => $parent_item['edited'], - 'author' => [ - 'name' => $item_author['xchan_name'], - 'address' => $item_author['xchan_addr'], - 'guid' => $item_author['xchan_guid'], - 'guid_sig' => $item_author['xchan_guid_sig'], - 'link' => [ - ['rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']], - ['rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m']]], - ], - ], JSON_UNESCAPED_SLASHES - ); - - if ($act->type === 'Like') - $bodyverb = t('%1$s likes %2$s\'s %3$s'); - if ($act->type === 'Dislike') - $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); - - $ulink = '[url=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/url]'; - $alink = '[url=' . $parent_item['author']['xchan_url'] . ']' . $parent_item['author']['xchan_name'] . '[/url]'; - $plink = '[url=' . z_root() . '/display/' . urlencode($act->id) . ']' . $post_type . '[/url]'; - $s['body'] = sprintf($bodyverb, $ulink, $alink, $plink); - - $s['app'] = t('ActivityPub'); - - // set the route to that of the parent so downstream hubs won't reject it. - - $s['route'] = $parent_item['route']; - $s['item_private'] = $parent_item['item_private']; - $s['obj_type'] = $objtype; - $s['obj'] = $object; - - if ($act->obj['conversation']) { - set_iconfig($s, 'ostatus', 'conversation', $act->obj['conversation'], 1); - } - - if ($act->recips && (!in_array(ACTIVITY_PUBLIC_INBOX, $act->recips))) - $s['item_private'] = 1; - - set_iconfig($s, 'activitypub', 'recips', $act->raw_recips); - - $result = item_store($s); - - if ($result['success']) { - // if the message isn't already being relayed, notify others - if (intval($parent_item['item_origin'])) - Master::Summon(['Notifier', 'comment-import', $result['item_id']]); - sync_an_item($channel['channel_id'], $result['item_id']); - } - - return; - } public static function bb_attach($item) { diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 265bcb376..4a327e24f 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1672,24 +1672,13 @@ class Libzot { } if ($arr['verb'] === 'Announce') { - - // TODO: move this to background - - if (!Activity::fetch_and_store_parents($channel, $sender, $arr, true)) { - continue; - } - - $parent = q("select * from item where mid = '%s' and uid = %d limit 1", - dbesc($arr['parent_mid']), - intval($channel['channel_id']) - ); - + Master::Summon(['Fetchparents', $channel['channel_id'], $sender, $arr['mid'], true]); } else { Master::Summon(['Zotconvo', $channel['channel_id'], $arr['parent_mid']]); - continue; } + continue; } logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"'); diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index 342e8f6e5..ea9313fa8 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -65,8 +65,6 @@ class Share extends \Zotlabs\Web\Controller { $item = $r[0]; - $owner_uid = $r[0]['uid']; - $owner_aid = $r[0]['aid']; /* $can_comment = false; if((array_key_exists('owner',$item)) && intval($item['owner']['abook_self'])) @@ -96,21 +94,33 @@ class Share extends \Zotlabs\Web\Controller { else killme(); - - $arr['aid'] = $owner_aid; - $arr['uid'] = $owner_uid; + $arr['aid'] = $item['aid']; + $arr['uid'] = $item['uid']; $arr['item_origin'] = 1; $arr['item_wall'] = $item['item_wall']; + $arr['item_private'] = $item['item_private']; $arr['uuid'] = item_message_id(); $arr['mid'] = z_root() . '/activity/' . $arr['uuid']; - $arr['parent_mid'] = $item['mid']; + $arr['parent_mid'] = $item['parent_mid']; + $arr['thr_parent'] = $item['mid']; + + $created = datetime_convert(); + + $arr['created'] = $created; + $arr['edited'] = $created; + $arr['commented'] = $created; + $arr['received'] = $created; + $arr['changed'] = $created; + $arr['item_type'] = ITEM_TYPE_POST; $mention = '@[zrl=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/zrl]'; $arr['body'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, Activity::activity_obj_mapper($item['obj_type'])); $arr['author_xchan'] = $channel['channel_hash']; $arr['owner_xchan'] = $item['author_xchan']; + $arr['source_xchan'] = ''; + $arr['obj'] = $item['obj']; $arr['obj_type'] = $item['obj_type']; $arr['verb'] = ACTIVITY_SHARE; |