From 6fbb03801c7a5a3c6daaab52d603dffbadd8ff98 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sat, 20 Jun 2015 08:44:29 +0200 Subject: [PATCH 01/11] The OStatus completion is now called before the original item is stored. --- include/items.php | 5 +- include/ostatus.php | 33 +-- include/ostatus_conversation.php | 343 +++++++++++++++++++++---------- 3 files changed, 259 insertions(+), 122 deletions(-) diff --git a/include/items.php b/include/items.php index fa370c82a8..b085ac8cfa 100644 --- a/include/items.php +++ b/include/items.php @@ -1192,12 +1192,15 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa // If there is no guid then take the same guid that was taken before for the same plink if ((trim($arr['guid']) == "") AND (trim($arr['plink']) != "") AND (trim($arr['network']) != "")) { logger('item_store: checking for an existing guid for plink '.$arr['plink'], LOGGER_DEBUG); - $r = q("SELECT `guid` FROM `guid` WHERE `plink` = '%s' AND `network` = '%s' LIMIT 1", + $r = q("SELECT `guid`, `uri` FROM `guid` WHERE `plink` = '%s' AND `network` = '%s' LIMIT 1", dbesc(trim($arr['plink'])), dbesc(trim($arr['network']))); if(count($r)) { $arr['guid'] = $r[0]["guid"]; logger('item_store: found guid '.$arr['guid'].' for plink '.$arr['plink'], LOGGER_DEBUG); + + if ($r[0]["uri"] != $arr['uri']) + logger('Different uri for same guid: '.$arr['uri'].' and '.$r[0]["uri"].' - this shouldnt happen!', LOGGER_DEBUG); } } diff --git a/include/ostatus.php b/include/ostatus.php index 86d0e36dbe..996cbea1fd 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -186,6 +186,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item["body"] = add_page_info_to_body(html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue)); $item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue; + $item["object"] = $xml; $item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue; if ($item["verb"] == ACTIVITY_FOLLOW) { @@ -218,6 +219,9 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { if ($georsspoint) $item["coord"] = $georsspoint->item(0)->nodeValue; + // To-Do + // $item["location"] = + $categories = $xpath->query('atom:category', $entry); if ($categories) { foreach ($categories AS $category) { @@ -292,7 +296,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $repeat_of = ""; $notice_info = $xpath->query('statusnet:notice_info', $entry); - if ($notice_info) + if ($notice_info AND ($notice_info->length > 0)) { foreach($notice_info->item(0)->attributes AS $attributes) { if ($attributes->name == "source") $item["app"] = strip_tags($attributes->textContent); @@ -301,6 +305,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { if ($attributes->name == "repeat_of") $repeat_of = $attributes->textContent; } + } // Is it a repeated post? if ($repeat_of != "") { @@ -376,12 +381,19 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { } else $item["parent-uri"] = $item["uri"]; - // We risk the chance of getting orphan items, we correct it some lines later - // To-Do: See To-Do line below. - $item_id = item_store($item, true); + $item_id = ostatus_completion($conversation, $importer["uid"], $item); + + if ($item_id <= 0) { + $reason = $item_id; + $item["app"] .= $item_id; + $item_id = item_store($item, true); + if ($item_id) { + logger("Shouldn't happen. Code ".$reason." - uri ".$item["uri"], LOGGER_DEBUG); + complete_conversation($item_id, $conversation_url, true); + } + } //echo $xml; //print_r($item); - //echo $item_id." ".$item["parent-uri"]."\n"; if (!$item_id) { logger("Error storing item ".print_r($item, true), LOGGER_DEBUG); @@ -414,16 +426,5 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { 'parent' => $item["parent"] )); } - - if ($conversation != "") { - // Check for duplicates. We really don't need to check the same conversation twice. - if (!in_array($conversation, $conversationlist)) { - // To-Do: - // Call this before item_store is called to avoid posts with orphans - // The routine then needs to get the item array. - complete_conversation($item_id, $conversation); - $conversationlist[] = $conversation; - } - } } } diff --git a/include/ostatus_conversation.php b/include/ostatus_conversation.php index e61f5fab4f..fd90ba3dd1 100644 --- a/include/ostatus_conversation.php +++ b/include/ostatus_conversation.php @@ -1,6 +1,8 @@ time()) { - logger('poll interval not reached'); - return; - } - } + if ($last AND !$override) { + $next = $last + ($poll_interval * 60); + if ($next > time()) { + logger('poll interval not reached'); + return; + } + } - logger('cron_start'); + logger('cron_start'); - $start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60)); - $conversations = q("SELECT `oid`, `url` FROM `term` WHERE `type` = 7 AND `term` > '%s' GROUP BY `url` ORDER BY `term` DESC", - dbesc($start)); + $start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60)); + $conversations = q("SELECT `oid`, `url`, `uid` FROM `term` WHERE `type` = 7 AND `term` > '%s' GROUP BY `url`, `uid` ORDER BY `term` DESC", + dbesc($start)); - foreach ($conversations AS $conversation) { - $id = $conversation['oid']; - $url = $conversation['url']; - complete_conversation($id, $url); - } + foreach ($conversations AS $conversation) { + ostatus_completion($conversation['url'], $conversation['uid']); + } - logger('cron_end'); + logger('cron_end'); - set_config('system','ostatus_last_poll', time()); + set_config('system','ostatus_last_poll', time()); } -function complete_conversation($itemid, $conversation_url, $only_add_conversation = false) { - global $a; +function ostatus_completion($conversation_url, $uid, $item = array()) { + + $item_stored = -3; $conversation_url = ostatus_convert_href($conversation_url); +/* +To-Do: if (intval(get_config('system','ostatus_poll_interval')) == -2) return; @@ -81,43 +84,56 @@ function complete_conversation($itemid, $conversation_url, $only_add_conversatio $a->last_ostatus_conversation_url = $conversation_url; - $messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid)); - if (!$messages) - return; - $message = $messages[0]; - - // Store conversation url if not done before - $conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d", - intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION)); - - if (!$conversation) { - $r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')", - intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), - dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"])); - logger('Storing conversation url '.$conversation_url.' for id '.$itemid); - } - - if ($only_add_conversation) - return; +*/ // Get the parent - $parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", - intval($message["uid"]), intval($message["parent"])); - if (!$parents) - return; - $parent = $parents[0]; + $parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN + (SELECT `parent` FROM `item` WHERE `id` IN + (SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))", + intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url)); - require_once('include/html2bbcode.php'); - require_once('include/items.php'); + if ($parents) + $parent = $parents[0]; + elseif (count($item) > 0) { + $parent = $item; + $parent["type"] = "remote"; + $parent["verb"] = ACTIVITY_POST; + $parent["visible"] = 1; + } else { + // Preset the parent + $r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid); + if (!$r) + return(-1); + + $parent = array(); + $parent["id"] = 0; + $parent["parent"] = 0; + $parent["uri"] = ""; + $parent["contact-id"] = $r[0]["id"]; + $parent["type"] = "remote"; + $parent["verb"] = ACTIVITY_POST; + $parent["visible"] = 1; + } $conv = str_replace("/conversation/", "/api/statusnet/conversation/", $conversation_url).".as"; $pageno = 1; $items = array(); - logger('fetching conversation url '.$conv.' for id '.$itemid.' and parent '.$parent["id"]); + logger('fetching conversation url '.$conv.' for user '.$uid); do { - $conv_as = fetch_url($conv."?page=".$pageno); + $conv_arr = z_fetch_url($conv."?page=".$pageno); + + // If it is a non-ssl site and there is an error, then try ssl or vice versa + if (!$conv_arr["success"] AND (substr($conv, 0, 7) == "http://")) { + $conv = str_replace("http://", "https://", $conv); + $conv_as = fetch_url($conv."?page=".$pageno); + } elseif (!$conv_arr["success"] AND (substr($conv, 0, 8) == "https://")) { + $conv = str_replace("https://", "http://", $conv); + $conv_as = fetch_url($conv."?page=".$pageno); + } else + $conv_as = $conv_arr["body"]; + $conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as); $conv_as = json_decode($conv_as); @@ -130,69 +146,102 @@ function complete_conversation($itemid, $conversation_url, $only_add_conversatio } while (true); - if (!sizeof($items)) - return; + logger('fetching conversation done. Found '.count($items).' items'); + + if (!sizeof($items)) { + if (count($item) > 0) { + $item_stored = item_store($item, true); + logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG); + + if ($item_stored) + complete_conversation($item_id, $conversation_url, true); + + return($item_stored); + } else + return(-2); + } $items = array_reverse($items); foreach ($items as $single_conv) { + + // Test - remove before flight + //$tempfile = tempnam(get_temppath(), "conversation"); + //file_put_contents($tempfile, json_encode($single_conv)); + + if (isset($single_conv->object->id)) $single_conv->id = $single_conv->object->id; - //logger("Got id ".$single_conv->id, LOGGER_DEBUG); - $plink = ostatus_convert_href($single_conv->id); if (isset($single_conv->object->url)) $plink = ostatus_convert_href($single_conv->object->url); - //logger("Got url ".$plink, LOGGER_DEBUG); - if (@!$single_conv->id) continue; + logger("Got id ".$single_conv->id, LOGGER_DEBUG); + if ($first_id == "") { $first_id = $single_conv->id; - $new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", - intval($message["uid"]), dbesc($first_id), - dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); - if ($new_parents) { - // It can happen that OStatus servers have incomplete threads. - // Then keep the current parent - if ($parent["id"] == $parent["parent"]) { - $parent = $new_parents[0]; - - if ($parent["id"] != $message["parent"]) - logger('Fetch new parent id '.$parent["id"].' - Old parent: '.$message["parent"]); + // The first post of the conversation isn't our first post. There are three options: + // 1. Our conversation hasn't the "real" thread starter + // 2. This first post is a post inside our thread + // 3. This first post is a post inside another thread + if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) { + $new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN + (SELECT `parent` FROM `item` + WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1", + intval($uid), dbesc($first_id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); + if ($new_parents) { + if ($new_parents[0]["parent"] == $parent["parent"]) { + // Option 2: This post is already present inside our thread - but not as thread starter + logger("Option 2: uri present in our thread: ".$first_id, LOGGER_DEBUG); + $first_id = $parent["uri"]; + } else { + // Option 3: Not so good. We have mixed parents. We have to see how to clean this up. + // For now just take the new parent. + $parent = $new_parents[0]; + $first_id = $parent["uri"]; + logger("Option 3: mixed parents for uri ".$first_id, LOGGER_DEBUG); + } } else { - $first_id = $parent["uri"]; - //logger('Keep parent for '.$itemid.' - Old parent: '.$message["parent"]); + // Option 1: We hadn't got the real thread starter + // We have to clean up our existing messages. + $parent["id"] = 0; + $parent["uri"] = $first_id; + logger("Option 1: we have a new parent: ".$first_id, LOGGER_DEBUG); } - } else { + } elseif ($parent["uri"] == "") { $parent["id"] = 0; $parent["uri"] = $first_id; } } - if (isset($single_conv->context->inReplyTo->id)) + if (isset($single_conv->context->inReplyTo->id)) { $parent_uri = $single_conv->context->inReplyTo->id; - else + + $parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", + intval($uid), dbesc($parent_uri), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); + if (!$parent_exists) { + logger("Parent ".$parent_uri." wasn't found here", LOGGER_DEBUG); + $parent_uri = $parent["uri"]; + } + } else $parent_uri = $parent["uri"]; - $message_exists = q("SELECT `id`, `parent` FROM `item` WHERE `uid` = %d AND `plink` = '%s' AND `network` IN ('%s','%s') LIMIT 1", - intval($message["uid"]), dbesc($plink), - dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); - - if (!$message_exists) - $message_exists = q("SELECT `id`, `parent` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", - intval($message["uid"]), dbesc($single_conv->id), - dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); - + $message_exists = q("SELECT `id`, `parent`, `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", + intval($uid), dbesc($single_conv->id), + dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); if ($message_exists) { + logger("Message ".$single_conv->id." already existed on the system", LOGGER_DEBUG); + if ($parent["id"] != 0) { $existing_message = $message_exists[0]; // We improved the way we fetch OStatus messages, this shouldn't happen very often now + // To-Do: we have to change the shadow copies as well. This way here is really ugly. if ($existing_message["parent"] != $parent["id"]) { logger('updating id '.$existing_message["id"].' with parent '.$existing_message["parent"].' to parent '.$parent["id"].' uri '.$parent["uri"].' thread '.$parent_uri, LOGGER_DEBUG); @@ -216,6 +265,13 @@ function complete_conversation($itemid, $conversation_url, $only_add_conversatio delete_thread($existing_message["parent"]); } } + + // The item we are having on the system is the one that we wanted to store via the item array + if (isset($item["uri"]) AND ($item["uri"] == $existing_message["uri"])) { + $item = array(); + $item_stored = 0; + } + continue; } @@ -224,7 +280,7 @@ function complete_conversation($itemid, $conversation_url, $only_add_conversatio $actor = $single_conv->actor->url; $contact = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'", - $message["uid"], normalise_link($actor), NETWORK_STATUSNET); + $uid, normalise_link($actor), NETWORK_STATUSNET); if (count($contact)) { logger("Found contact for url ".$actor, LOGGER_DEBUG); @@ -245,29 +301,19 @@ function complete_conversation($itemid, $conversation_url, $only_add_conversatio $arr["network"] = NETWORK_OSTATUS; $arr["uri"] = $single_conv->id; $arr["plink"] = $plink; - $arr["uid"] = $message["uid"]; + $arr["uid"] = $uid; $arr["contact-id"] = $contact_id; - if ($parent["id"] != 0) - $arr["parent"] = $parent["id"]; - $arr["parent-uri"] = $parent["uri"]; - $arr["thr-parent"] = $parent_uri; + $arr["parent-uri"] = $parent_uri; $arr["created"] = $single_conv->published; $arr["edited"] = $single_conv->published; - $arr["owner-name"] = $single_conv->actor->contact->displayName; - //$arr["owner-name"] = $single_conv->actor->contact->preferredUsername; + $arr["owner-name"] = $single_conv->actor->displayName; + if ($arr["owner-name"] == '') + $arr["owner-name"] = $single_conv->actor->contact->displayName; if ($arr["owner-name"] == '') $arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName; - if ($arr["owner-name"] == '') - $arr["owner-name"] = $single_conv->actor->displayName; - if ($arr["owner-name"] == '') - $arr["owner-name"] = $single_conv->actor->portablecontacts_net->preferredUsername; - if ($arr["owner-name"] == '') - $arr["owner-name"] = $single_conv->actor->preferredUsername; $arr["owner-link"] = $actor; $arr["owner-avatar"] = $single_conv->actor->image->url; - //$arr["author-name"] = $single_conv->actor->contact->displayName; - //$arr["author-name"] = $single_conv->actor->contact->preferredUsername; $arr["author-name"] = $arr["owner-name"]; $arr["author-link"] = $actor; $arr["author-avatar"] = $single_conv->actor->image->url; @@ -284,33 +330,120 @@ function complete_conversation($itemid, $conversation_url, $only_add_conversatio else $arr["app"] = "OStatus"; + $arr["app"] .= "*"; + + $arr["object"] = json_encode($single_conv); $arr["verb"] = $parent["verb"]; $arr["visible"] = $parent["visible"]; $arr["location"] = $single_conv->location->displayName; $arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon); + // Is it a reshared item? + if (isset($item->verb) AND ($item->verb == "share") AND isset($item->object)) { + if (is_array($item->object)) + $item->object = $item->object[0]; + + logger("Found reshared item ".$single_conv->object->id); + + // $single_conv->object->context->conversation; + + $plink = ostatus_convert_href($single_conv->object->url); + + $arr["uri"] = $single_conv->object->id; + $arr["plink"] = $plink; + $arr["created"] = $single_conv->object->published; + $arr["edited"] = $single_conv->object->published; + + $arr["author-name"] = $single_conv->object->actor->displayName; + if ($arr["owner-name"] == '') + $arr["author-name"] = $single_conv->object->actor->contact->displayName; + + $arr["author-link"] = $single_conv->object->actor->url; + $arr["author-avatar"] = $single_conv->object->actor->image->url; + + $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content)); + $arr["app"] = $single_conv->object->provider->displayName."#"; + //$arr["verb"] = $single_conv->object->verb; + + $arr["location"] = $single_conv->object->location->displayName; + $arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon); + } + if ($arr["location"] == "") unset($arr["location"]); if ($arr["coord"] == "") unset($arr["coord"]); - $newitem = item_store($arr); + // Copy fields from given item array + if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) { + $copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar", + "gravity", "body", "object-type", "verb", "created", "edited", "coord", "tag", + "attach", "app", "type", "location", "contact-id"); + foreach ($copy_fields AS $field) + if (isset($item[$field])) + $arr[$field] = $item[$field]; - logger('Stored new item '.$plink.' for parent '.$arr["parent"].' under id '.$newitem, LOGGER_DEBUG); + $arr["app"] .= "+"; + } + + $newitem = item_store($arr); + if (!$newitem) { + logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG); + continue; + } + + if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) { + $item = array(); + $item_stored = $newitem; + } + + logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG); // Add the conversation entry (but don't fetch the whole conversation) complete_conversation($newitem, $conversation_url, true); // If the newly created item is the top item then change the parent settings of the thread // This shouldn't happen anymore. This is supposed to be absolote. - if ($newitem AND ($arr["uri"] == $first_id)) { + if ($arr["uri"] == $first_id) { logger('setting new parent to id '.$newitem); $new_parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", - intval($message["uid"]), intval($newitem)); + intval($uid), intval($newitem)); if ($new_parents) $parent = $new_parents[0]; } } +// Test +/* if ((count($item) > 0) AND ($item_stored <= 0)) { + $item_stored = item_store($item, true); + logger("In the conversation ".$conversation_url." the item uri ".$item["uri"]." wasn't found: ".$item_stored, LOGGER_DEBUG); + + if ($item_stored) + complete_conversation($item_id, $conversation_url, true); + } */ + + return($item_stored); +} + +function complete_conversation($itemid, $conversation_url, $only_add_conversation = false) { + global $a; + + $conversation_url = ostatus_convert_href($conversation_url); + + $messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid)); + if (!$messages) + return; + $message = $messages[0]; + + // Store conversation url if not done before + $conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d", + intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION)); + + if (!$conversation) { + $r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')", + intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), + dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"])); + logger('Storing conversation url '.$conversation_url.' for id '.$itemid); + } } ?> From 168906f9c9b3792462a0d494c15a186042239c0b Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sat, 20 Jun 2015 09:15:19 +0200 Subject: [PATCH 02/11] Code cleanup --- include/items.php | 32 -------------------------------- include/ostatus.php | 2 +- include/ostatus_conversation.php | 30 ++++++++---------------------- 3 files changed, 9 insertions(+), 55 deletions(-) diff --git a/include/items.php b/include/items.php index b085ac8cfa..7a30130bbc 100644 --- a/include/items.php +++ b/include/items.php @@ -9,7 +9,6 @@ require_once('include/tags.php'); require_once('include/files.php'); require_once('include/text.php'); require_once('include/email.php'); -//require_once('include/ostatus_conversation.php'); require_once('include/threads.php'); require_once('include/socgraph.php'); require_once('include/plaintext.php'); @@ -481,7 +480,6 @@ function get_atom_elements($feed, $item, $contact = array()) { // but for now let's just find any author photo // Additionally we look for an alternate author link. On OStatus this one is the one we want. - // Search for ostatus conversation url $authorlinks = $item->feed->data["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["feed"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["author"][0]["child"]["http://www.w3.org/2005/Atom"]["link"]; if (is_array($authorlinks)) { foreach ($authorlinks as $link) { @@ -886,23 +884,6 @@ function get_atom_elements($feed, $item, $contact = array()) { } } -// // Search for ostatus conversation url -// $links = $item->feed->data["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["feed"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["entry"][0]["child"]["http://www.w3.org/2005/Atom"]["link"]; -// -// if (is_array($links)) { -// foreach ($links as $link) { -// $conversation = array_shift($link["attribs"]); -// -// if ($conversation["rel"] == "ostatus:conversation") { -// $res["ostatus_conversation"] = ostatus_convert_href($conversation["href"]); -// logger('get_atom_elements: found conversation url '.$res["ostatus_conversation"]); -// //} elseif ($conversation["rel"] == "alternate") { -// // $res["plink"] = $conversation["href"]; -// // logger('get_atom_elements: found plink '.$res["plink"]); -// } -// }; -// } - if (isset($contact["network"]) AND ($contact["network"] == NETWORK_FEED) AND $contact['fetch_further_information']) { $preview = ""; @@ -1139,15 +1120,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa $arr['plink'] = ostatus_convert_href($arr['uri']); } -// // if an OStatus conversation url was passed in, it is stored and then -// // removed from the array. -// $ostatus_conversation = null; - -// if (isset($arr["ostatus_conversation"])) { -// $ostatus_conversation = $arr["ostatus_conversation"]; -// unset($arr["ostatus_conversation"]); -// } - if(x($arr, 'gravity')) $arr['gravity'] = intval($arr['gravity']); elseif($arr['parent-uri'] === $arr['uri']) @@ -1540,10 +1512,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa intval($current_post) ); - // Complete ostatus threads - //if ($ostatus_conversation) - // complete_conversation($current_post, $ostatus_conversation); - $arr['id'] = $current_post; $arr['parent'] = $parent_id; $arr['allow_cid'] = $allow_cid; diff --git a/include/ostatus.php b/include/ostatus.php index 996cbea1fd..bf88efab9a 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -389,7 +389,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item_id = item_store($item, true); if ($item_id) { logger("Shouldn't happen. Code ".$reason." - uri ".$item["uri"], LOGGER_DEBUG); - complete_conversation($item_id, $conversation_url, true); + complete_conversation($item_id, $conversation_url); } } //echo $xml; diff --git a/include/ostatus_conversation.php b/include/ostatus_conversation.php index fd90ba3dd1..03678cbb4a 100644 --- a/include/ostatus_conversation.php +++ b/include/ostatus_conversation.php @@ -74,17 +74,11 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { $conversation_url = ostatus_convert_href($conversation_url); -/* -To-Do: - if (intval(get_config('system','ostatus_poll_interval')) == -2) - return; - - if ($a->last_ostatus_conversation_url == $conversation_url) - return; - - $a->last_ostatus_conversation_url = $conversation_url; - -*/ + // If the thread shouldn't be completed then store the item and go away + if ((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) { + $item_stored = item_store($item, true); + return($item_stored); + } // Get the parent $parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN @@ -154,7 +148,7 @@ To-Do: logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG); if ($item_stored) - complete_conversation($item_id, $conversation_url, true); + complete_conversation($item_id, $conversation_url); return($item_stored); } else @@ -401,7 +395,7 @@ To-Do: logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG); // Add the conversation entry (but don't fetch the whole conversation) - complete_conversation($newitem, $conversation_url, true); + complete_conversation($newitem, $conversation_url); // If the newly created item is the top item then change the parent settings of the thread // This shouldn't happen anymore. This is supposed to be absolote. @@ -413,19 +407,11 @@ To-Do: $parent = $new_parents[0]; } } -// Test -/* if ((count($item) > 0) AND ($item_stored <= 0)) { - $item_stored = item_store($item, true); - logger("In the conversation ".$conversation_url." the item uri ".$item["uri"]." wasn't found: ".$item_stored, LOGGER_DEBUG); - - if ($item_stored) - complete_conversation($item_id, $conversation_url, true); - } */ return($item_stored); } -function complete_conversation($itemid, $conversation_url, $only_add_conversation = false) { +function complete_conversation($itemid, $conversation_url) { global $a; $conversation_url = ostatus_convert_href($conversation_url); From c8430f4c44f34641953e29e65fd1e268bcc332b1 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sat, 20 Jun 2015 14:40:30 +0200 Subject: [PATCH 03/11] Moved all OStatus code in a single file. --- boot.php | 3 - include/acl_selectors.php | 2 +- include/ostatus.php | 450 ++++++++++++++++++++++++++++++- include/ostatus_conversation.php | 435 ------------------------------ 4 files changed, 444 insertions(+), 446 deletions(-) delete mode 100644 include/ostatus_conversation.php diff --git a/boot.php b/boot.php index 6c9c8fdc4a..0aa7ab6341 100644 --- a/boot.php +++ b/boot.php @@ -415,9 +415,6 @@ if(! class_exists('App')) { // array of instanced template engines ('name'=>'instance') public $template_engine_instance = array(); - // Used for reducing load to the ostatus completion - public $last_ostatus_conversation_url; - private $ldelim = array( 'internal' => '', 'smarty3' => '{{' diff --git a/include/acl_selectors.php b/include/acl_selectors.php index b2c4b31c81..dc2f8d4164 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -422,7 +422,7 @@ function acl_lookup(&$a, $out_type = 'json') { WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != '' $sql_extra2" , - intval(local_user()) + intval(local_user()), ); $contact_count = (int)$r[0]['c']; } diff --git a/include/ostatus.php b/include/ostatus.php index bf88efab9a..f6056170f2 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -1,11 +1,15 @@ query('activity:verb/text()', $entry)->item(0)->nodeValue; + if ($item["verb"] == ACTIVITY_JOIN) { + // ignore "Join" messages + continue; + } + if ($item["verb"] == ACTIVITY_FOLLOW) { // ignore "Follow" messages continue; @@ -389,7 +398,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item_id = item_store($item, true); if ($item_id) { logger("Shouldn't happen. Code ".$reason." - uri ".$item["uri"], LOGGER_DEBUG); - complete_conversation($item_id, $conversation_url); + ostatus_store_conversation($item_id, $conversation_url); } } //echo $xml; @@ -428,3 +437,430 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { } } } + +function ostatus_convert_href($href) { + $elements = explode(":",$href); + + if ((count($elements) <= 2) OR ($elements[0] != "tag")) + return $href; + + $server = explode(",", $elements[1]); + $conversation = explode("=", $elements[2]); + + if ((count($elements) == 4) AND ($elements[2] == "post")) + return "http://".$server[0]."/notice/".$elements[3]; + + if ((count($conversation) != 2) OR ($conversation[1] =="")) + return $href; + + if ($elements[3] == "objectType=thread") + return "http://".$server[0]."/conversation/".$conversation[1]; + else + return "http://".$server[0]."/notice/".$conversation[1]; + + return $href; +} + +function check_conversations($override = false) { + $last = get_config('system','ostatus_last_poll'); + + $poll_interval = intval(get_config('system','ostatus_poll_interval')); + if(! $poll_interval) + $poll_interval = OSTATUS_DEFAULT_POLL_INTERVAL; + + // Don't poll if the interval is set negative + if (($poll_interval < 0) AND !$override) + return; + + $poll_timeframe = intval(get_config('system','ostatus_poll_timeframe')); + if (!$poll_timeframe) + $poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME; + + if ($last AND !$override) { + $next = $last + ($poll_interval * 60); + if ($next > time()) { + logger('poll interval not reached'); + return; + } + } + + logger('cron_start'); + + $start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60)); + $conversations = q("SELECT `oid`, `url`, `uid` FROM `term` WHERE `type` = 7 AND `term` > '%s' GROUP BY `url`, `uid` ORDER BY `term` DESC", + dbesc($start)); + + foreach ($conversations AS $conversation) { + ostatus_completion($conversation['url'], $conversation['uid']); + } + + logger('cron_end'); + + set_config('system','ostatus_last_poll', time()); +} + +function ostatus_completion($conversation_url, $uid, $item = array()) { + + $item_stored = -3; + + $conversation_url = ostatus_convert_href($conversation_url); + + // If the thread shouldn't be completed then store the item and go away + if ((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) { + $item_stored = item_store($item, true); + return($item_stored); + } + + // Get the parent + $parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN + (SELECT `parent` FROM `item` WHERE `id` IN + (SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))", + intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url)); + + if ($parents) + $parent = $parents[0]; + elseif (count($item) > 0) { + $parent = $item; + $parent["type"] = "remote"; + $parent["verb"] = ACTIVITY_POST; + $parent["visible"] = 1; + } else { + // Preset the parent + $r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid); + if (!$r) + return(-1); + + $parent = array(); + $parent["id"] = 0; + $parent["parent"] = 0; + $parent["uri"] = ""; + $parent["contact-id"] = $r[0]["id"]; + $parent["type"] = "remote"; + $parent["verb"] = ACTIVITY_POST; + $parent["visible"] = 1; + } + + $conv = str_replace("/conversation/", "/api/statusnet/conversation/", $conversation_url).".as"; + $pageno = 1; + $items = array(); + + logger('fetching conversation url '.$conv.' for user '.$uid); + + do { + $conv_arr = z_fetch_url($conv."?page=".$pageno); + + // If it is a non-ssl site and there is an error, then try ssl or vice versa + if (!$conv_arr["success"] AND (substr($conv, 0, 7) == "http://")) { + $conv = str_replace("http://", "https://", $conv); + $conv_as = fetch_url($conv."?page=".$pageno); + } elseif (!$conv_arr["success"] AND (substr($conv, 0, 8) == "https://")) { + $conv = str_replace("https://", "http://", $conv); + $conv_as = fetch_url($conv."?page=".$pageno); + } else + $conv_as = $conv_arr["body"]; + + $conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as); + $conv_as = json_decode($conv_as); + + if (@is_array($conv_as->items)) + $items = array_merge($items, $conv_as->items); + else + break; + + $pageno++; + + } while (true); + + logger('fetching conversation done. Found '.count($items).' items'); + + if (!sizeof($items)) { + if (count($item) > 0) { + $item_stored = item_store($item, true); + logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG); + + if ($item_stored) + ostatus_store_conversation($item_id, $conversation_url); + + return($item_stored); + } else + return(-2); + } + + $items = array_reverse($items); + + foreach ($items as $single_conv) { + + // Test - remove before flight + //$tempfile = tempnam(get_temppath(), "conversation"); + //file_put_contents($tempfile, json_encode($single_conv)); + + + if (isset($single_conv->object->id)) + $single_conv->id = $single_conv->object->id; + + $plink = ostatus_convert_href($single_conv->id); + if (isset($single_conv->object->url)) + $plink = ostatus_convert_href($single_conv->object->url); + + if (@!$single_conv->id) + continue; + + logger("Got id ".$single_conv->id, LOGGER_DEBUG); + + if ($first_id == "") { + $first_id = $single_conv->id; + + // The first post of the conversation isn't our first post. There are three options: + // 1. Our conversation hasn't the "real" thread starter + // 2. This first post is a post inside our thread + // 3. This first post is a post inside another thread + if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) { + $new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN + (SELECT `parent` FROM `item` + WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1", + intval($uid), dbesc($first_id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); + if ($new_parents) { + if ($new_parents[0]["parent"] == $parent["parent"]) { + // Option 2: This post is already present inside our thread - but not as thread starter + logger("Option 2: uri present in our thread: ".$first_id, LOGGER_DEBUG); + $first_id = $parent["uri"]; + } else { + // Option 3: Not so good. We have mixed parents. We have to see how to clean this up. + // For now just take the new parent. + $parent = $new_parents[0]; + $first_id = $parent["uri"]; + logger("Option 3: mixed parents for uri ".$first_id, LOGGER_DEBUG); + } + } else { + // Option 1: We hadn't got the real thread starter + // We have to clean up our existing messages. + $parent["id"] = 0; + $parent["uri"] = $first_id; + logger("Option 1: we have a new parent: ".$first_id, LOGGER_DEBUG); + } + } elseif ($parent["uri"] == "") { + $parent["id"] = 0; + $parent["uri"] = $first_id; + } + } + + if (isset($single_conv->context->inReplyTo->id)) { + $parent_uri = $single_conv->context->inReplyTo->id; + + $parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", + intval($uid), dbesc($parent_uri), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); + if (!$parent_exists) { + logger("Parent ".$parent_uri." wasn't found here", LOGGER_DEBUG); + $parent_uri = $parent["uri"]; + } + } else + $parent_uri = $parent["uri"]; + + $message_exists = q("SELECT `id`, `parent`, `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", + intval($uid), dbesc($single_conv->id), + dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); + if ($message_exists) { + logger("Message ".$single_conv->id." already existed on the system", LOGGER_DEBUG); + + if ($parent["id"] != 0) { + $existing_message = $message_exists[0]; + + // We improved the way we fetch OStatus messages, this shouldn't happen very often now + // To-Do: we have to change the shadow copies as well. This way here is really ugly. + if ($existing_message["parent"] != $parent["id"]) { + logger('updating id '.$existing_message["id"].' with parent '.$existing_message["parent"].' to parent '.$parent["id"].' uri '.$parent["uri"].' thread '.$parent_uri, LOGGER_DEBUG); + + // Update the parent id of the selected item + $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `id` = %d", + intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["id"])); + + // Update the parent uri in the thread - but only if it points to itself + $r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE `id` = %d AND `uri` = `thr-parent`", + dbesc($parent_uri), intval($existing_message["id"])); + + // try to change all items of the same parent + $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `parent` = %d", + intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["parent"])); + + // Update the parent uri in the thread - but only if it points to itself + $r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE (`parent` = %d) AND (`uri` = `thr-parent`)", + dbesc($parent["uri"]), intval($existing_message["parent"])); + + // Now delete the thread + delete_thread($existing_message["parent"]); + } + } + + // The item we are having on the system is the one that we wanted to store via the item array + if (isset($item["uri"]) AND ($item["uri"] == $existing_message["uri"])) { + $item = array(); + $item_stored = 0; + } + + continue; + } + + $actor = $single_conv->actor->id; + if (isset($single_conv->actor->url)) + $actor = $single_conv->actor->url; + + $contact = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'", + $uid, normalise_link($actor), NETWORK_STATUSNET); + + if (count($contact)) { + logger("Found contact for url ".$actor, LOGGER_DEBUG); + $contact_id = $contact[0]["id"]; + } else { + logger("No contact found for url ".$actor, LOGGER_DEBUG); + + // Adding a global contact + // To-Do: Use this data for the post + $global_contact_id = get_contact($actor, 0); + + logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG); + + $contact_id = $parent["contact-id"]; + } + + $arr = array(); + $arr["network"] = NETWORK_OSTATUS; + $arr["uri"] = $single_conv->id; + $arr["plink"] = $plink; + $arr["uid"] = $uid; + $arr["contact-id"] = $contact_id; + $arr["parent-uri"] = $parent_uri; + $arr["created"] = $single_conv->published; + $arr["edited"] = $single_conv->published; + $arr["owner-name"] = $single_conv->actor->displayName; + if ($arr["owner-name"] == '') + $arr["owner-name"] = $single_conv->actor->contact->displayName; + if ($arr["owner-name"] == '') + $arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName; + + $arr["owner-link"] = $actor; + $arr["owner-avatar"] = $single_conv->actor->image->url; + $arr["author-name"] = $arr["owner-name"]; + $arr["author-link"] = $actor; + $arr["author-avatar"] = $single_conv->actor->image->url; + $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->content)); + + if (isset($single_conv->status_net->notice_info->source)) + $arr["app"] = strip_tags($single_conv->status_net->notice_info->source); + elseif (isset($single_conv->statusnet->notice_info->source)) + $arr["app"] = strip_tags($single_conv->statusnet->notice_info->source); + elseif (isset($single_conv->statusnet_notice_info->source)) + $arr["app"] = strip_tags($single_conv->statusnet_notice_info->source); + elseif (isset($single_conv->provider->displayName)) + $arr["app"] = $single_conv->provider->displayName; + else + $arr["app"] = "OStatus"; + + $arr["app"] .= " (Conversation)"; + + $arr["object"] = json_encode($single_conv); + $arr["verb"] = $parent["verb"]; + $arr["visible"] = $parent["visible"]; + $arr["location"] = $single_conv->location->displayName; + $arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon); + + // Is it a reshared item? + if (isset($item->verb) AND ($item->verb == "share") AND isset($item->object)) { + if (is_array($item->object)) + $item->object = $item->object[0]; + + logger("Found reshared item ".$single_conv->object->id); + + // $single_conv->object->context->conversation; + + $plink = ostatus_convert_href($single_conv->object->url); + + $arr["uri"] = $single_conv->object->id; + $arr["plink"] = $plink; + $arr["created"] = $single_conv->object->published; + $arr["edited"] = $single_conv->object->published; + + $arr["author-name"] = $single_conv->object->actor->displayName; + if ($arr["owner-name"] == '') + $arr["author-name"] = $single_conv->object->actor->contact->displayName; + + $arr["author-link"] = $single_conv->object->actor->url; + $arr["author-avatar"] = $single_conv->object->actor->image->url; + + $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content)); + $arr["app"] = $single_conv->object->provider->displayName."#"; + //$arr["verb"] = $single_conv->object->verb; + + $arr["location"] = $single_conv->object->location->displayName; + $arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon); + } + + if ($arr["location"] == "") + unset($arr["location"]); + + if ($arr["coord"] == "") + unset($arr["coord"]); + + // Copy fields from given item array + if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) { + $copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar", + "gravity", "body", "object-type", "verb", "created", "edited", "coord", "tag", + "attach", "app", "type", "location", "contact-id"); + foreach ($copy_fields AS $field) + if (isset($item[$field])) + $arr[$field] = $item[$field]; + + $arr["app"] .= " (OStatus)"; + } + + $newitem = item_store($arr); + if (!$newitem) { + logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG); + continue; + } + + if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) { + $item = array(); + $item_stored = $newitem; + } + + logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG); + + // Add the conversation entry (but don't fetch the whole conversation) + ostatus_store_conversation($newitem, $conversation_url); + + // If the newly created item is the top item then change the parent settings of the thread + // This shouldn't happen anymore. This is supposed to be absolote. + if ($arr["uri"] == $first_id) { + logger('setting new parent to id '.$newitem); + $new_parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", + intval($uid), intval($newitem)); + if ($new_parents) + $parent = $new_parents[0]; + } + } + + return($item_stored); +} + +function ostatus_store_conversation($itemid, $conversation_url) { + global $a; + + $conversation_url = ostatus_convert_href($conversation_url); + + $messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid)); + if (!$messages) + return; + $message = $messages[0]; + + // Store conversation url if not done before + $conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d", + intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION)); + + if (!$conversation) { + $r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')", + intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), + dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"])); + logger('Storing conversation url '.$conversation_url.' for id '.$itemid); + } +} +?> diff --git a/include/ostatus_conversation.php b/include/ostatus_conversation.php deleted file mode 100644 index 03678cbb4a..0000000000 --- a/include/ostatus_conversation.php +++ /dev/null @@ -1,435 +0,0 @@ - time()) { - logger('poll interval not reached'); - return; - } - } - - logger('cron_start'); - - $start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60)); - $conversations = q("SELECT `oid`, `url`, `uid` FROM `term` WHERE `type` = 7 AND `term` > '%s' GROUP BY `url`, `uid` ORDER BY `term` DESC", - dbesc($start)); - - foreach ($conversations AS $conversation) { - ostatus_completion($conversation['url'], $conversation['uid']); - } - - logger('cron_end'); - - set_config('system','ostatus_last_poll', time()); -} - -function ostatus_completion($conversation_url, $uid, $item = array()) { - - $item_stored = -3; - - $conversation_url = ostatus_convert_href($conversation_url); - - // If the thread shouldn't be completed then store the item and go away - if ((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) { - $item_stored = item_store($item, true); - return($item_stored); - } - - // Get the parent - $parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN - (SELECT `parent` FROM `item` WHERE `id` IN - (SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))", - intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url)); - - if ($parents) - $parent = $parents[0]; - elseif (count($item) > 0) { - $parent = $item; - $parent["type"] = "remote"; - $parent["verb"] = ACTIVITY_POST; - $parent["visible"] = 1; - } else { - // Preset the parent - $r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid); - if (!$r) - return(-1); - - $parent = array(); - $parent["id"] = 0; - $parent["parent"] = 0; - $parent["uri"] = ""; - $parent["contact-id"] = $r[0]["id"]; - $parent["type"] = "remote"; - $parent["verb"] = ACTIVITY_POST; - $parent["visible"] = 1; - } - - $conv = str_replace("/conversation/", "/api/statusnet/conversation/", $conversation_url).".as"; - $pageno = 1; - $items = array(); - - logger('fetching conversation url '.$conv.' for user '.$uid); - - do { - $conv_arr = z_fetch_url($conv."?page=".$pageno); - - // If it is a non-ssl site and there is an error, then try ssl or vice versa - if (!$conv_arr["success"] AND (substr($conv, 0, 7) == "http://")) { - $conv = str_replace("http://", "https://", $conv); - $conv_as = fetch_url($conv."?page=".$pageno); - } elseif (!$conv_arr["success"] AND (substr($conv, 0, 8) == "https://")) { - $conv = str_replace("https://", "http://", $conv); - $conv_as = fetch_url($conv."?page=".$pageno); - } else - $conv_as = $conv_arr["body"]; - - $conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as); - $conv_as = json_decode($conv_as); - - if (@is_array($conv_as->items)) - $items = array_merge($items, $conv_as->items); - else - break; - - $pageno++; - - } while (true); - - logger('fetching conversation done. Found '.count($items).' items'); - - if (!sizeof($items)) { - if (count($item) > 0) { - $item_stored = item_store($item, true); - logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG); - - if ($item_stored) - complete_conversation($item_id, $conversation_url); - - return($item_stored); - } else - return(-2); - } - - $items = array_reverse($items); - - foreach ($items as $single_conv) { - - // Test - remove before flight - //$tempfile = tempnam(get_temppath(), "conversation"); - //file_put_contents($tempfile, json_encode($single_conv)); - - - if (isset($single_conv->object->id)) - $single_conv->id = $single_conv->object->id; - - $plink = ostatus_convert_href($single_conv->id); - if (isset($single_conv->object->url)) - $plink = ostatus_convert_href($single_conv->object->url); - - if (@!$single_conv->id) - continue; - - logger("Got id ".$single_conv->id, LOGGER_DEBUG); - - if ($first_id == "") { - $first_id = $single_conv->id; - - // The first post of the conversation isn't our first post. There are three options: - // 1. Our conversation hasn't the "real" thread starter - // 2. This first post is a post inside our thread - // 3. This first post is a post inside another thread - if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) { - $new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN - (SELECT `parent` FROM `item` - WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1", - intval($uid), dbesc($first_id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); - if ($new_parents) { - if ($new_parents[0]["parent"] == $parent["parent"]) { - // Option 2: This post is already present inside our thread - but not as thread starter - logger("Option 2: uri present in our thread: ".$first_id, LOGGER_DEBUG); - $first_id = $parent["uri"]; - } else { - // Option 3: Not so good. We have mixed parents. We have to see how to clean this up. - // For now just take the new parent. - $parent = $new_parents[0]; - $first_id = $parent["uri"]; - logger("Option 3: mixed parents for uri ".$first_id, LOGGER_DEBUG); - } - } else { - // Option 1: We hadn't got the real thread starter - // We have to clean up our existing messages. - $parent["id"] = 0; - $parent["uri"] = $first_id; - logger("Option 1: we have a new parent: ".$first_id, LOGGER_DEBUG); - } - } elseif ($parent["uri"] == "") { - $parent["id"] = 0; - $parent["uri"] = $first_id; - } - } - - if (isset($single_conv->context->inReplyTo->id)) { - $parent_uri = $single_conv->context->inReplyTo->id; - - $parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", - intval($uid), dbesc($parent_uri), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); - if (!$parent_exists) { - logger("Parent ".$parent_uri." wasn't found here", LOGGER_DEBUG); - $parent_uri = $parent["uri"]; - } - } else - $parent_uri = $parent["uri"]; - - $message_exists = q("SELECT `id`, `parent`, `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1", - intval($uid), dbesc($single_conv->id), - dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); - if ($message_exists) { - logger("Message ".$single_conv->id." already existed on the system", LOGGER_DEBUG); - - if ($parent["id"] != 0) { - $existing_message = $message_exists[0]; - - // We improved the way we fetch OStatus messages, this shouldn't happen very often now - // To-Do: we have to change the shadow copies as well. This way here is really ugly. - if ($existing_message["parent"] != $parent["id"]) { - logger('updating id '.$existing_message["id"].' with parent '.$existing_message["parent"].' to parent '.$parent["id"].' uri '.$parent["uri"].' thread '.$parent_uri, LOGGER_DEBUG); - - // Update the parent id of the selected item - $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `id` = %d", - intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["id"])); - - // Update the parent uri in the thread - but only if it points to itself - $r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE `id` = %d AND `uri` = `thr-parent`", - dbesc($parent_uri), intval($existing_message["id"])); - - // try to change all items of the same parent - $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `parent` = %d", - intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["parent"])); - - // Update the parent uri in the thread - but only if it points to itself - $r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE (`parent` = %d) AND (`uri` = `thr-parent`)", - dbesc($parent["uri"]), intval($existing_message["parent"])); - - // Now delete the thread - delete_thread($existing_message["parent"]); - } - } - - // The item we are having on the system is the one that we wanted to store via the item array - if (isset($item["uri"]) AND ($item["uri"] == $existing_message["uri"])) { - $item = array(); - $item_stored = 0; - } - - continue; - } - - $actor = $single_conv->actor->id; - if (isset($single_conv->actor->url)) - $actor = $single_conv->actor->url; - - $contact = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'", - $uid, normalise_link($actor), NETWORK_STATUSNET); - - if (count($contact)) { - logger("Found contact for url ".$actor, LOGGER_DEBUG); - $contact_id = $contact[0]["id"]; - } else { - logger("No contact found for url ".$actor, LOGGER_DEBUG); - - // Adding a global contact - // To-Do: Use this data for the post - $global_contact_id = get_contact($actor, 0); - - logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG); - - $contact_id = $parent["contact-id"]; - } - - $arr = array(); - $arr["network"] = NETWORK_OSTATUS; - $arr["uri"] = $single_conv->id; - $arr["plink"] = $plink; - $arr["uid"] = $uid; - $arr["contact-id"] = $contact_id; - $arr["parent-uri"] = $parent_uri; - $arr["created"] = $single_conv->published; - $arr["edited"] = $single_conv->published; - $arr["owner-name"] = $single_conv->actor->displayName; - if ($arr["owner-name"] == '') - $arr["owner-name"] = $single_conv->actor->contact->displayName; - if ($arr["owner-name"] == '') - $arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName; - - $arr["owner-link"] = $actor; - $arr["owner-avatar"] = $single_conv->actor->image->url; - $arr["author-name"] = $arr["owner-name"]; - $arr["author-link"] = $actor; - $arr["author-avatar"] = $single_conv->actor->image->url; - $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->content)); - - if (isset($single_conv->status_net->notice_info->source)) - $arr["app"] = strip_tags($single_conv->status_net->notice_info->source); - elseif (isset($single_conv->statusnet->notice_info->source)) - $arr["app"] = strip_tags($single_conv->statusnet->notice_info->source); - elseif (isset($single_conv->statusnet_notice_info->source)) - $arr["app"] = strip_tags($single_conv->statusnet_notice_info->source); - elseif (isset($single_conv->provider->displayName)) - $arr["app"] = $single_conv->provider->displayName; - else - $arr["app"] = "OStatus"; - - $arr["app"] .= "*"; - - $arr["object"] = json_encode($single_conv); - $arr["verb"] = $parent["verb"]; - $arr["visible"] = $parent["visible"]; - $arr["location"] = $single_conv->location->displayName; - $arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon); - - // Is it a reshared item? - if (isset($item->verb) AND ($item->verb == "share") AND isset($item->object)) { - if (is_array($item->object)) - $item->object = $item->object[0]; - - logger("Found reshared item ".$single_conv->object->id); - - // $single_conv->object->context->conversation; - - $plink = ostatus_convert_href($single_conv->object->url); - - $arr["uri"] = $single_conv->object->id; - $arr["plink"] = $plink; - $arr["created"] = $single_conv->object->published; - $arr["edited"] = $single_conv->object->published; - - $arr["author-name"] = $single_conv->object->actor->displayName; - if ($arr["owner-name"] == '') - $arr["author-name"] = $single_conv->object->actor->contact->displayName; - - $arr["author-link"] = $single_conv->object->actor->url; - $arr["author-avatar"] = $single_conv->object->actor->image->url; - - $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content)); - $arr["app"] = $single_conv->object->provider->displayName."#"; - //$arr["verb"] = $single_conv->object->verb; - - $arr["location"] = $single_conv->object->location->displayName; - $arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon); - } - - if ($arr["location"] == "") - unset($arr["location"]); - - if ($arr["coord"] == "") - unset($arr["coord"]); - - // Copy fields from given item array - if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) { - $copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar", - "gravity", "body", "object-type", "verb", "created", "edited", "coord", "tag", - "attach", "app", "type", "location", "contact-id"); - foreach ($copy_fields AS $field) - if (isset($item[$field])) - $arr[$field] = $item[$field]; - - $arr["app"] .= "+"; - } - - $newitem = item_store($arr); - if (!$newitem) { - logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG); - continue; - } - - if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) { - $item = array(); - $item_stored = $newitem; - } - - logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG); - - // Add the conversation entry (but don't fetch the whole conversation) - complete_conversation($newitem, $conversation_url); - - // If the newly created item is the top item then change the parent settings of the thread - // This shouldn't happen anymore. This is supposed to be absolote. - if ($arr["uri"] == $first_id) { - logger('setting new parent to id '.$newitem); - $new_parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", - intval($uid), intval($newitem)); - if ($new_parents) - $parent = $new_parents[0]; - } - } - - return($item_stored); -} - -function complete_conversation($itemid, $conversation_url) { - global $a; - - $conversation_url = ostatus_convert_href($conversation_url); - - $messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid)); - if (!$messages) - return; - $message = $messages[0]; - - // Store conversation url if not done before - $conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d", - intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION)); - - if (!$conversation) { - $r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')", - intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), - dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"])); - logger('Storing conversation url '.$conversation_url.' for id '.$itemid); - } -} -?> From 1bbbf2a5f26c420d688705a70c287865267a7426 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sat, 20 Jun 2015 14:41:53 +0200 Subject: [PATCH 04/11] Stuff ... --- include/acl_selectors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acl_selectors.php b/include/acl_selectors.php index dc2f8d4164..b2c4b31c81 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -422,7 +422,7 @@ function acl_lookup(&$a, $out_type = 'json') { WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != '' $sql_extra2" , - intval(local_user()), + intval(local_user()) ); $contact_count = (int)$r[0]['c']; } From 846edd5bbb7adb965303c9dfd1912c006b2c6668 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sat, 20 Jun 2015 17:26:47 +0200 Subject: [PATCH 05/11] Bugfix for repeated items in conversations --- include/ostatus.php | 64 +++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/include/ostatus.php b/include/ostatus.php index f6056170f2..80a67f201c 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -322,29 +322,33 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { if (is_object($activityobjects)) { - $orig_uris = $xpath->query("activity:object/atom:link[@rel='alternate']", $activityobjects); - if ($orig_uris) - foreach($orig_uris->item(0)->attributes AS $attributes) - if ($attributes->name == "href") - $orig_uri = $attributes->textContent; - - if (!isset($orig_uri)) - $orig_uri = $xpath->query("atom:link[@rel='alternate']", $activityobjects)->item(0)->nodeValue; - - if (!isset($orig_uri)) - $orig_uri = $xpath->query("activity:object/atom:id", $activityobjects)->item(0)->nodeValue; - + $orig_uri = $xpath->query("activity:object/atom:id", $activityobjects)->item(0)->nodeValue; if (!isset($orig_uri)) $orig_uri = $xpath->query('atom:id/text()', $activityobjects)->item(0)->nodeValue; - $orig_body = $xpath->query('atom:content/text()', $activityobjects)->item(0)->nodeValue; + $orig_links = $xpath->query("activity:object/atom:link[@rel='alternate']", $activityobjects); + if ($orig_links AND ($orig_links->length > 0)) + foreach($orig_links->item(0)->attributes AS $attributes) + if ($attributes->name == "href") + $orig_link = $attributes->textContent; + + if (!isset($orig_link)) + $orig_link = $xpath->query("atom:link[@rel='alternate']", $activityobjects)->item(0)->nodeValue; + + if (!isset($orig_link)) + $orig_link = ostatus_convert_href($orig_uri); + + $orig_body = $xpath->query('activity:object/atom:content/text()', $activityobjects)->item(0)->nodeValue; + if (!isset($orig_body)) + $orig_body = $xpath->query('atom:content/text()', $activityobjects)->item(0)->nodeValue; + $orig_created = $xpath->query('atom:published/text()', $activityobjects)->item(0)->nodeValue; $orig_contact = $contact; $orig_author = ostatus_fetchauthor($xpath, $activityobjects, $importer, $orig_contact); //if (!intval(get_config('system','wall-to-wall_share'))) { - // $prefix = share_header($orig_author['author-name'], $orig_author['author-link'], $orig_author['author-avatar'], "", $orig_created, $orig_uri); + // $prefix = share_header($orig_author['author-name'], $orig_author['author-link'], $orig_author['author-avatar'], "", $orig_created, $orig_link); // $item["body"] = $prefix.add_page_info_to_body(html2bbcode($orig_body))."[/share]"; //} else { $item["author-name"] = $orig_author["author-name"]; @@ -354,10 +358,14 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item["created"] = $orig_created; $item["uri"] = $orig_uri; + $item["plink"] = $orig_link; //} $item["verb"] = $xpath->query('activity:verb/text()', $activityobjects)->item(0)->nodeValue; - $item["object-type"] = $xpath->query('activity:object-type/text()', $activityobjects)->item(0)->nodeValue; + + $item["object-type"] = $xpath->query('activity:object/activity:object-type/text()', $activityobjects)->item(0)->nodeValue; + if (!isset($item["object-type"])) + $item["object-type"] = $xpath->query('activity:object-type/text()', $activityobjects)->item(0)->nodeValue; } } @@ -397,7 +405,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item["app"] .= $item_id; $item_id = item_store($item, true); if ($item_id) { - logger("Shouldn't happen. Code ".$reason." - uri ".$item["uri"], LOGGER_DEBUG); + logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation, LOGGER_DEBUG); ostatus_store_conversation($item_id, $conversation_url); } } @@ -764,18 +772,31 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { $arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon); // Is it a reshared item? - if (isset($item->verb) AND ($item->verb == "share") AND isset($item->object)) { - if (is_array($item->object)) - $item->object = $item->object[0]; + if (isset($single_conv->verb) AND ($single_conv->verb == "share") AND isset($single_conv->object)) { + if (is_array($single_conv->object)) + $single_conv->object = $single_conv->object[0]; logger("Found reshared item ".$single_conv->object->id); // $single_conv->object->context->conversation; - $plink = ostatus_convert_href($single_conv->object->url); + if (isset($single_conv->object->object->id)) + $arr["uri"] = $single_conv->object->object->id; + else + $arr["uri"] = $single_conv->object->id; + + if (isset($single_conv->object->object->url)) + $plink = ostatus_convert_href($single_conv->object->object->url); + else + $plink = ostatus_convert_href($single_conv->object->url); + + if (isset($single_conv->object->object->content)) + $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->object->content)); + else + $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content)); - $arr["uri"] = $single_conv->object->id; $arr["plink"] = $plink; + $arr["created"] = $single_conv->object->published; $arr["edited"] = $single_conv->object->published; @@ -786,7 +807,6 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { $arr["author-link"] = $single_conv->object->actor->url; $arr["author-avatar"] = $single_conv->object->actor->image->url; - $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content)); $arr["app"] = $single_conv->object->provider->displayName."#"; //$arr["verb"] = $single_conv->object->verb; From df7b907bc48923316520bc7504d1379361d2b270 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 21 Jun 2015 01:34:57 +0200 Subject: [PATCH 06/11] Display: Look for the network name when fetching the contact (important because of the statusnet connector) --- mod/display.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/mod/display.php b/mod/display.php index 02ff37bf83..c8b72ecc40 100644 --- a/mod/display.php +++ b/mod/display.php @@ -102,8 +102,17 @@ function display_fetchauthor($a, $item) { $profiledata["network"] = $item["network"]; // Fetching further contact data from the contact table - $r = q("SELECT `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d", - normalise_link($profiledata["url"]), $item["uid"]); + $r = q("SELECT `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `network` = '%s'", + dbesc(normalise_link($profiledata["url"])), intval($item["uid"]), dbesc($item["network"])); + + if (!count($r)) + $r = q("SELECT `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d", + dbesc(normalise_link($profiledata["url"])), intval($item["uid"])); + + if (!count($r)) + $r = q("SELECT `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0", + dbesc(normalise_link($profiledata["url"]))); + if (count($r)) { $profiledata["photo"] = proxy_url($r[0]["photo"]); $profiledata["address"] = proxy_parse_html(bbcode($r[0]["location"])); @@ -113,7 +122,7 @@ function display_fetchauthor($a, $item) { } // Fetching profile data from unique contacts - $r = q("SELECT `avatar`, `nick`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'", normalise_link($profiledata["url"])); + $r = q("SELECT `avatar`, `nick`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($profiledata["url"]))); if (count($r)) { if ($profiledata["photo"] == "") $profiledata["photo"] = proxy_url($r[0]["avatar"]); @@ -181,7 +190,7 @@ function display_fetchauthor($a, $item) { // Fetching profile data from unique contacts if ($profiledata["url"] != "") { - $r = q("SELECT `avatar`, `nick`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'", normalise_link($profiledata["url"])); + $r = q("SELECT `avatar`, `nick`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($profiledata["url"]))); if (count($r)) { $profiledata["photo"] = proxy_url($r[0]["avatar"]); $profiledata["address"] = proxy_parse_html(bbcode($r[0]["location"])); From 8229737d2d63c31a02af000b08bc63fbd5586193 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 21 Jun 2015 01:36:23 +0200 Subject: [PATCH 07/11] Small restructuring --- include/ostatus.php | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/include/ostatus.php b/include/ostatus.php index 80a67f201c..a03e561320 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -400,18 +400,6 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item_id = ostatus_completion($conversation, $importer["uid"], $item); - if ($item_id <= 0) { - $reason = $item_id; - $item["app"] .= $item_id; - $item_id = item_store($item, true); - if ($item_id) { - logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation, LOGGER_DEBUG); - ostatus_store_conversation($item_id, $conversation_url); - } - } - //echo $xml; - //print_r($item); - if (!$item_id) { logger("Error storing item ".print_r($item, true), LOGGER_DEBUG); continue; @@ -509,7 +497,7 @@ function check_conversations($override = false) { function ostatus_completion($conversation_url, $uid, $item = array()) { - $item_stored = -3; + $item_stored = -1; $conversation_url = ostatus_convert_href($conversation_url); @@ -536,7 +524,7 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { // Preset the parent $r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid); if (!$r) - return(-1); + return(-2); $parent = array(); $parent["id"] = 0; @@ -591,7 +579,7 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { return($item_stored); } else - return(-2); + return(-3); } $items = array_reverse($items); @@ -821,10 +809,10 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { unset($arr["coord"]); // Copy fields from given item array - if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) { + if (isset($item["uri"]) AND (($item["uri"] == $arr["uri"]) OR ($item["uri"] == $single_conv->id))) { $copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar", "gravity", "body", "object-type", "verb", "created", "edited", "coord", "tag", - "attach", "app", "type", "location", "contact-id"); + "attach", "app", "type", "location", "contact-id", "uri"); foreach ($copy_fields AS $field) if (isset($item[$field])) $arr[$field] = $item[$field]; @@ -859,6 +847,14 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { } } + if (($item_stored < 0) AND (count($item) > 0)) { + $item_stored = item_store($item, true); + if ($item_stored) { + logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation_url, LOGGER_DEBUG); + ostatus_store_conversation($item_stored, $conversation_url); + } + } + return($item_stored); } From 5221f38db79490847b62e58861639fed63a0ce53 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 21 Jun 2015 01:37:09 +0200 Subject: [PATCH 08/11] ACL: Don't show OStatus contacts in ACL, since you cannot send private messages to them. --- include/acl_selectors.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/acl_selectors.php b/include/acl_selectors.php index b2c4b31c81..c1e62ac36b 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -399,6 +399,7 @@ function acl_lookup(&$a, $out_type = 'json') { $search = $_REQUEST['query']; } + logger("Searching for ".$search." - type ".$type, LOGGER_DEBUG); if ($search!=""){ $sql_extra = "AND `name` LIKE '%%".dbesc($search)."%%'"; @@ -496,9 +497,11 @@ function acl_lookup(&$a, $out_type = 'json') { $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, forum FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != '' + AND NOT (`network` IN ('%s', '%s')) $sql_extra2 ORDER BY `name` ASC ", - intval(local_user()) + intval(local_user()), + dbesc(NETWORK_OSTATUS), dbesc(NETWORK_STATUSNET) ); } elseif($type == 'm') { From 2afc9c31f96b613bdf985197806fb0bebbb128c3 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 21 Jun 2015 08:32:03 +0200 Subject: [PATCH 09/11] Changed logging behaviour --- include/ostatus.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/ostatus.php b/include/ostatus.php index a03e561320..d1a1f4f988 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -401,7 +401,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item_id = ostatus_completion($conversation, $importer["uid"], $item); if (!$item_id) { - logger("Error storing item ".print_r($item, true), LOGGER_DEBUG); + logger("Error storing item", LOGGER_DEBUG); continue; } @@ -572,10 +572,11 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { if (!sizeof($items)) { if (count($item) > 0) { $item_stored = item_store($item, true); - logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG); - if ($item_stored) + if ($item_stored) { + logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG); ostatus_store_conversation($item_id, $conversation_url); + } return($item_stored); } else From da9bbc92d378e3b000bdf72f637516fd691618e6 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 21 Jun 2015 22:02:44 +0200 Subject: [PATCH 10/11] OStatus: Support for bookmarks --- include/ostatus.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/include/ostatus.php b/include/ostatus.php index d1a1f4f988..ab5c00a6a0 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -190,6 +190,12 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item["body"] = add_page_info_to_body(html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue)); $item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue; + + if ($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) { + $item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue; + $item["body"] = $xpath->query('atom:summary/text()', $entry)->item(0)->nodeValue; + } + $item["object"] = $xml; $item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue; @@ -283,11 +289,14 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]'; break; case "related": - if (!isset($item["parent-uri"])) - $item["parent-uri"] = $href; + if ($item["object-type"] != ACTIVITY_OBJ_BOOKMARK) { + if (!isset($item["parent-uri"])) + $item["parent-uri"] = $href; - if ($related == "") - $related = $href; + if ($related == "") + $related = $href; + } else + $item["body"] .= add_page_info($href); break; case "self": $self = $href; @@ -812,8 +821,8 @@ function ostatus_completion($conversation_url, $uid, $item = array()) { // Copy fields from given item array if (isset($item["uri"]) AND (($item["uri"] == $arr["uri"]) OR ($item["uri"] == $single_conv->id))) { $copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar", - "gravity", "body", "object-type", "verb", "created", "edited", "coord", "tag", - "attach", "app", "type", "location", "contact-id", "uri"); + "gravity", "body", "object-type", "object", "verb", "created", "edited", "coord", "tag", + "title", "attach", "app", "type", "location", "contact-id", "uri"); foreach ($copy_fields AS $field) if (isset($item[$field])) $arr[$field] = $item[$field]; From e9542a8d1715279faadf3a36fd2db8ce3f8c4589 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Sun, 21 Jun 2015 22:36:24 +0200 Subject: [PATCH 11/11] OStatus: Support for events and questions --- boot.php | 1 + include/ostatus.php | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/boot.php b/boot.php index 0aa7ab6341..193b34a60b 100644 --- a/boot.php +++ b/boot.php @@ -290,6 +290,7 @@ define ( 'ACTIVITY_OBJ_EVENT', NAMESPACE_ACTIVITY_SCHEMA . 'event' ); define ( 'ACTIVITY_OBJ_GROUP', NAMESPACE_ACTIVITY_SCHEMA . 'group' ); define ( 'ACTIVITY_OBJ_TAGTERM', NAMESPACE_DFRN . '/tagterm' ); define ( 'ACTIVITY_OBJ_PROFILE', NAMESPACE_DFRN . '/profile' ); +define ( 'ACTIVITY_OBJ_QUESTION', 'http://activityschema.org/object/question' ); /** * item weight for query ordering diff --git a/include/ostatus.php b/include/ostatus.php index ab5c00a6a0..463ebcd30a 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -191,10 +191,11 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { $item["body"] = add_page_info_to_body(html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue)); $item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue; - if ($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) { + if (($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) OR ($item["object-type"] == ACTIVITY_OBJ_EVENT)) { $item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue; $item["body"] = $xpath->query('atom:summary/text()', $entry)->item(0)->nodeValue; - } + } elseif ($item["object-type"] == ACTIVITY_OBJ_QUESTION) + $item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue; $item["object"] = $xml; $item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue; @@ -277,6 +278,9 @@ function ostatus_import($xml,$importer,&$contact, &$hub) { switch($rel) { case "alternate": $item["plink"] = $href; + if (($item["object-type"] == ACTIVITY_OBJ_QUESTION) OR + ($item["object-type"] == ACTIVITY_OBJ_EVENT)) + $item["body"] .= add_page_info($href); break; case "ostatus:conversation": $conversation = $href;