diff --git a/boot.php b/boot.php index 6c9c8fdc4a..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 @@ -415,9 +416,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..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') { diff --git a/include/items.php b/include/items.php index fa370c82a8..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']) @@ -1192,12 +1164,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); } } @@ -1537,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 86d0e36dbe..463ebcd30a 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -1,11 +1,15 @@ 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) 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; + if ($item["verb"] == ACTIVITY_JOIN) { + // ignore "Join" messages + continue; + } + if ($item["verb"] == ACTIVITY_FOLLOW) { // ignore "Follow" messages continue; @@ -218,6 +235,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) { @@ -258,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; @@ -270,11 +293,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; @@ -292,7 +318,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 +327,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 != "") { @@ -308,29 +335,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"]; @@ -340,10 +371,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; } } @@ -376,15 +411,10 @@ 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); - //echo $xml; - //print_r($item); - //echo $item_id." ".$item["parent-uri"]."\n"; + $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; } @@ -414,16 +444,453 @@ 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; - } - } } } + +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 = -1; + + $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(-2); + + $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); + + 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 + return(-3); + } + + $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($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; + + 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["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["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"]) 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", "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]; + + $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]; + } + } + + 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); +} + +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 e61f5fab4f..0000000000 --- a/include/ostatus_conversation.php +++ /dev/null @@ -1,316 +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` FROM `term` WHERE `type` = 7 AND `term` > '%s' GROUP BY `url` ORDER BY `term` DESC", - dbesc($start)); - - foreach ($conversations AS $conversation) { - $id = $conversation['oid']; - $url = $conversation['url']; - complete_conversation($id, $url); - } - - logger('cron_end'); - - set_config('system','ostatus_last_poll', time()); -} - -function complete_conversation($itemid, $conversation_url, $only_add_conversation = false) { - global $a; - - $conversation_url = ostatus_convert_href($conversation_url); - - 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; - - $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]; - - require_once('include/html2bbcode.php'); - require_once('include/items.php'); - - $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"]); - - do { - $conv_as = fetch_url($conv."?page=".$pageno); - $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); - - if (!sizeof($items)) - return; - - $items = array_reverse($items); - - foreach ($items as $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; - - 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"]); - } else { - $first_id = $parent["uri"]; - //logger('Keep parent for '.$itemid.' - Old parent: '.$message["parent"]); - } - } else { - $parent["id"] = 0; - $parent["uri"] = $first_id; - } - } - - if (isset($single_conv->context->inReplyTo->id)) - $parent_uri = $single_conv->context->inReplyTo->id; - 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)); - - if ($message_exists) { - if ($parent["id"] != 0) { - $existing_message = $message_exists[0]; - - // We improved the way we fetch OStatus messages, this shouldn't happen very often now - 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"]); - } - } - 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'", - $message["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"] = $message["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["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; - 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; - $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["verb"] = $parent["verb"]; - $arr["visible"] = $parent["visible"]; - $arr["location"] = $single_conv->location->displayName; - $arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon); - - if ($arr["location"] == "") - unset($arr["location"]); - - if ($arr["coord"] == "") - unset($arr["coord"]); - - $newitem = item_store($arr); - - logger('Stored new item '.$plink.' for parent '.$arr["parent"].' 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)) { - 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)); - if ($new_parents) - $parent = $new_parents[0]; - } - } -} -?> 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"]));