refactor fetching code

This commit is contained in:
Mike Macgirvin 2024-07-10 09:16:36 +10:00
parent aea775c999
commit 253c82bbfb

View file

@ -4559,37 +4559,6 @@ class Activity
} }
// experimental code that needs more work. What this did was once we fetched a conversation to find the root node,
// start at that root node and fetch children, so you get all the branches and not just the branch related to the current node.
// Unfortunately there is no standard method for achieving this. Mastodon provides a 'replies' collection and Nomad projects
// can fetch the 'context'. For other platforms it's a wild guess. Additionally, when we tested this, it started an infinite
// recursion and has been disabled until the recursive behaviour is tracked down and fixed.
// if ($fetch_parents && $parent && ! intval($parent_item['item_private'])) {
// logger('topfetch', LOGGER_DEBUG);
// // if the thread owner is a connnection, we will already receive any additional comments to their posts
// // but if they are not we can try to fetch others in the background
// $x = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
// WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
// intval($channel['channel_id']),
// dbesc($parent_item['owner_xchan'])
// );
// if (! $x) {
// // determine if the top-level post provides a replies collection
// if ($parent_item['obj']) {
// $parent_item['obj'] = json_decode($parent_item['obj'],true);
// }
// logger('topfetch: ' . print_r($parent_item,true), LOGGER_ALL);
// $id = ((array_path_exists('obj/replies/id',$parent_item)) ? $parent_item['obj']['replies']['id'] : false);
// if (! $id) {
// $id = ((array_path_exists('obj/replies',$parent_item) && is_string($parent_item['obj']['replies'])) ? $parent_item['obj']['replies'] : false);
// }
// if ($id) {
// Run::Summon( [ 'Convo', $id, $channel['channel_id'], $observer_hash ] );
// }
// }
// }
if (is_array($x) && $x['item_id']) { if (is_array($x) && $x['item_id']) {
tag_deliver($channel['channel_id'], $x['item_id']); tag_deliver($channel['channel_id'], $x['item_id']);
if ($is_child_node) { if ($is_child_node) {
@ -4682,16 +4651,76 @@ class Activity
$current_item = $item; $current_item = $item;
while ($current_item['parent_mid'] !== $current_item['mid']) { while ($current_item['parent_mid'] !== $current_item['mid']) {
$isCollectionOperation = false;
// recursion breaker // recursion breaker
if (in_array($current_item['parent_mid'], $seen_mids)) { if (in_array($current_item['parent_mid'], $seen_mids)) {
break; break;
} }
$json = self::fetch($current_item['parent_mid']);
$fetched = self::fetch_and_parse($current_item['parent_mid']);
$seen_mids[] = $current_item['parent_mid']; $seen_mids[] = $current_item['parent_mid'];
if (!$json) {
if (! $fetched) {
break; break;
} }
$item = $fetched['item'];
$activity = $fetched['activity'];
$collection = $fetched['collection'];
// don't leak any private conversations to the public stream
// even if they contain publicly addressed comments/reactions
if (intval($channel['channel_system']) && intval($item['item_private'])) {
logger('private conversation ignored');
$conversation = [];
break;
}
// We're fetching upstream starting with the initial post,
// so push each fetched activity to the head of the conversation.
array_unshift($conversation, ['activity' => $activity, 'item' => $item, 'collection' => $collection]);
if ($item['parent_mid'] === $item['mid']) {
break;
}
$current_item = $item;
}
if ($conversation) {
$parent_item = $conversation[0]['item'];
// // determine if the top-level post provides a replies collection
// if ($parent_item['obj']) {
// $parent_item['obj'] = json_decode($parent_item['obj'],true);
// }
// logger('topfetch: ' . print_r($parent_item,true), LOGGER_ALL);
// $id = ((array_path_exists('obj/replies/id',$parent_item)) ? $parent_item['obj']['replies']['id'] : false);
// if (! $id) {
// $id = ((array_path_exists('obj/replies',$parent_item) && is_string($parent_item['obj']['replies'])) ? $parent_item['obj']['replies'] : false);
// }
// if ($id) {
// Run::Summon( [ 'Convo', $id, $channel['channel_id'], $observer_hash ] );
// }
if ($conversation[0]['item']['mid'] === $conversation[0]['item']['parent_mid']) {
foreach ($conversation as $post) {
if ($post['activity']->is_valid()) {
self::store($channel, $observer_hash, $post['activity'], $post['item'], false, isCollectionOperation: $post['collection']);
}
}
return true;
}
}
return false;
}
public static function fetch_and_parse($message_id)
{
$json = self::fetch($message_id);
if (!$json) {
return false;
}
// set client flag to convert objects to implied activities // set client flag to convert objects to implied activities
$activity = new ActivityStreams($json, null, true); $activity = new ActivityStreams($json, null, true);
if ( if (
@ -4721,7 +4750,7 @@ class Activity
if (!$activity->is_valid()) { if (!$activity->is_valid()) {
logger('not a valid activity'); logger('not a valid activity');
break; return false;
} }
if (is_array($activity->actor) && array_key_exists('id', $activity->actor)) { if (is_array($activity->actor) && array_key_exists('id', $activity->actor)) {
self::actor_store($activity->actor['id'], $activity->actor); self::actor_store($activity->actor['id'], $activity->actor);
@ -4731,53 +4760,21 @@ class Activity
$item = self::decode_note($activity, true); $item = self::decode_note($activity, true);
if (!$item) { if (!$item) {
break; return false;
} }
logger('decoded_note: ' . print_r($item,true), LOGGER_DATA); logger('decoded_note: ' . print_r($item,true), LOGGER_DATA);
$hookinfo = [ $hookinfo = [
'activity' => $activity, 'activity' => $activity,
'item' => $item 'item' => $item,
'collection' => $isCollectionOperation,
]; ];
Hook::call('fetch_and_store', $hookinfo); Hook::call('fetch_and_store', $hookinfo);
$item = $hookinfo['item']; return $hookinfo;
if ($item) {
// don't leak any private conversations to the public stream
// even if they contain publicly addressed comments/reactions
if (intval($channel['channel_system']) && intval($item['item_private'])) {
logger('private conversation ignored');
$conversation = [];
break;
} }
// We're fetching upstream starting with the initial post,
// so push each fetched activity to the head of the conversation.
array_unshift($conversation, ['activity' => $activity, 'item' => $item, 'collection' => $isCollectionOperation]);
if ($item['parent_mid'] === $item['mid']) {
break;
}
}
$current_item = $item;
}
if ($conversation && $conversation[0]['item']['mid'] === $conversation[0]['item']['parent_mid']) {
foreach ($conversation as $post) {
if ($post['activity']->is_valid()) {
self::store($channel, $observer_hash, $post['activity'], $post['item'], false, isCollectionOperation: $post['collection']);
}
}
return true;
}
return false;
}
// This function is designed to work with Nomad attachments and item body // This function is designed to work with Nomad attachments and item body