function pumpio_dopost(&$a, $client, $uid, $self, $post, $own_id, $threadcompletion = true) { require_once 'include/items.php'; require_once 'include/html2bbcode.php'; if ($post->verb == "like" or $post->verb == "favorite") { return pumpio_dolike($a, $uid, $self, $post, $own_id); } if ($post->verb == "unlike" or $post->verb == "unfavorite") { return pumpio_dounlike($a, $uid, $self, $post, $own_id); } if ($post->verb == "delete") { return pumpio_dodelete($a, $uid, $self, $post, $own_id); } if ($post->verb != "update") { // Two queries for speed issues $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($post->object->id), intval($uid)); if (count($r)) { return false; } $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1", dbesc($post->object->id), intval($uid)); if (count($r)) { return false; } } // Only handle these three types if (!strstr("post|share|update", $post->verb)) { return false; } $receiptians = array(); if (@is_array($post->cc)) { $receiptians = array_merge($receiptians, $post->cc); } if (@is_array($post->to)) { $receiptians = array_merge($receiptians, $post->to); } foreach ($receiptians as $receiver) { if (is_string($receiver->objectType)) { if ($receiver->id == "http://activityschema.org/collection/public") { $public = true; } } } $postarray = array(); $postarray['network'] = NETWORK_PUMPIO; $postarray['gravity'] = 0; $postarray['uid'] = $uid; $postarray['wall'] = 0; $postarray['uri'] = $post->object->id; $postarray['object-type'] = NAMESPACE_ACTIVITY_SCHEMA . strtolower($post->object->objectType); if ($post->object->objectType != "comment") { $contact_id = pumpio_get_contact($uid, $post->actor); if (!$contact_id) { $contact_id = $self[0]['id']; } $postarray['parent-uri'] = $post->object->id; if (!$public) { $postarray['private'] = 1; $postarray['allow_cid'] = '<' . $self[0]['id'] . '>'; } } else { $contact_id = 0; if (link_compare($post->actor->url, $own_id)) { $contact_id = $self[0]['id']; $post->actor->displayName = $self[0]['name']; $post->actor->url = $self[0]['url']; $post->actor->image->url = $self[0]['photo']; } else { // Take an existing contact, the contact of the note or - as a fallback - the id of the user $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1", dbesc($post->actor->url), intval($uid)); if (count($r)) { $contact_id = $r[0]['id']; } else { $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1", dbesc($post->actor->url), intval($uid)); if (count($r)) { $contact_id = $r[0]['id']; } else { $contact_id = $self[0]['id']; } } } $reply = new stdClass(); $reply->verb = "note"; $reply->cc = $post->cc; $reply->to = $post->to; $reply->object = new stdClass(); $reply->object->objectType = $post->object->inReplyTo->objectType; $reply->object->content = $post->object->inReplyTo->content; $reply->object->id = $post->object->inReplyTo->id; $reply->actor = $post->object->inReplyTo->author; $reply->url = $post->object->inReplyTo->url; $reply->generator = new stdClass(); $reply->generator->displayName = "pumpio"; $reply->published = $post->object->inReplyTo->published; $reply->received = $post->object->inReplyTo->updated; $reply->url = $post->object->inReplyTo->url; pumpio_dopost($a, $client, $uid, $self, $reply, $own_id, false); $postarray['parent-uri'] = $post->object->inReplyTo->id; } if ($post->object->pump_io->proxyURL) { $postarray['extid'] = $post->object->pump_io->proxyURL; } $postarray['contact-id'] = $contact_id; $postarray['verb'] = ACTIVITY_POST; $postarray['owner-name'] = $post->actor->displayName; $postarray['owner-link'] = $post->actor->url; $postarray['owner-avatar'] = $post->actor->image->url; $postarray['author-name'] = $post->actor->displayName; $postarray['author-link'] = $post->actor->url; $postarray['author-avatar'] = $post->actor->image->url; $postarray['plink'] = $post->object->url; $postarray['app'] = $post->generator->displayName; $postarray['body'] = html2bbcode($post->object->content); if ($post->object->fullImage->url != "") { $postarray["body"] = "[url=" . $post->object->fullImage->url . "][img]" . $post->object->image->url . "[/img][/url]\n" . $postarray["body"]; } if ($post->object->displayName != "") { $postarray['title'] = $post->object->displayName; } $postarray['created'] = datetime_convert('UTC', 'UTC', $post->published); $postarray['edited'] = datetime_convert('UTC', 'UTC', $post->received); if ($post->verb == "share") { if (!intval(get_config('system', 'wall-to-wall_share'))) { $postarray['body'] = "[share author='" . $post->object->author->displayName . "' profile='" . $post->object->author->url . "' avatar='" . $post->object->author->image->url . "' posted='" . datetime_convert('UTC', 'UTC', $post->object->created) . "' link='" . $post->links->self->href . "']" . $postarray['body'] . "[/share]"; } else { // Let shares look like wall-to-wall posts $postarray['author-name'] = $post->object->author->displayName; $postarray['author-link'] = $post->object->author->url; $postarray['author-avatar'] = $post->object->author->image->url; } } if (trim($postarray['body']) == "") { return false; } $top_item = item_store($postarray); $postarray["id"] = $top_item; if ($top_item == 0 and $post->verb == "update") { $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s' , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($postarray["title"]), dbesc($postarray["body"]), dbesc($postarray["edited"]), dbesc($postarray["uri"]), intval($uid)); } if ($post->object->objectType == "comment") { if ($threadcompletion) { pumpio_fetchallcomments($a, $uid, $postarray['parent-uri']); } $user = q("SELECT * FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1", intval($uid)); if (!count($user)) { return $top_item; } $importer_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname']; if (link_compare($own_id, $postarray['author-link'])) { return $top_item; } $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0", dbesc($postarray['parent-uri']), intval($uid)); if (count($myconv)) { foreach ($myconv as $conv) { // now if we find a match, it means we're in this conversation if (!link_compare($conv['author-link'], $importer_url) and !link_compare($conv['author-link'], $own_id)) { continue; } require_once 'include/enotify.php'; $conv_parent = $conv['parent']; notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $user[0]['notify-flags'], 'language' => $user[0]['language'], 'to_name' => $user[0]['username'], 'to_email' => $user[0]['email'], 'uid' => $user[0]['uid'], 'item' => $postarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($top_item)), 'source_name' => $postarray['author-name'], 'source_link' => $postarray['author-link'], 'source_photo' => $postarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $conv_parent)); // only send one notification break; } } } return $top_item; }
function local_delivery($importer, $data) { $a = get_app(); logger(__FUNCTION__, LOGGER_TRACE); if ($importer['readonly']) { // We aren't receiving stuff from this person. But we will quietly ignore them // rather than a blatant "go away" message. logger('local_delivery: ignoring'); return 0; //NOTREACHED } // Consume notification feed. This may differ from consuming a public feed in several ways // - might contain email or friend suggestions // - might contain remote followup to our message // - in which case we need to accept it and then notify other conversants // - we may need to send various email notifications $feed = new SimplePie(); $feed->set_raw_data($data); $feed->enable_order_by_date(false); $feed->init(); if ($feed->error()) { logger('local_delivery: Error parsing XML: ' . $feed->error()); } // Check at the feed level for updated contact name and/or photo $name_updated = ''; $new_name = ''; $photo_timestamp = ''; $photo_url = ''; $contact_updated = ''; $rawtags = $feed->get_feed_tags(NAMESPACE_DFRN, 'owner'); // Fallback should not be needed here. If it isn't DFRN it won't have DFRN updated tags // if(! $rawtags) // $rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); if ($rawtags) { $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]; if ($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) { $name_updated = $elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']; $new_name = $elems['name'][0]['data']; // Manually checking for changed contact names if ($new_name != $importer['name'] and $new_name != "" and $name_updated <= $importer['name-date']) { $name_updated = date("c"); $photo_timestamp = date("c"); } } if (x($elems, 'link') && $elems['link'][0]['attribs']['']['rel'] === 'photo' && $elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']) { if ($photo_timestamp == "") { $photo_timestamp = datetime_convert('UTC', 'UTC', $elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']); } $photo_url = $elems['link'][0]['attribs']['']['href']; } } if ($photo_timestamp && strlen($photo_url) && $photo_timestamp > $importer['avatar-date']) { $contact_updated = $photo_timestamp; logger('local_delivery: Updating photo for ' . $importer['name']); require_once "include/Photo.php"; $photos = import_profile_photo($photo_url, $importer['importer_uid'], $importer['id']); q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'\n\t\t\tWHERE `uid` = %d AND `id` = %d AND NOT `self`", dbesc(datetime_convert()), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($importer['importer_uid']), intval($importer['id'])); } if ($name_updated && strlen($new_name) && $name_updated > $importer['name-date']) { if ($name_updated > $contact_updated) { $contact_updated = $name_updated; } $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($importer['importer_uid']), intval($importer['id'])); $x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d AND `name` != '%s' AND NOT `self`", dbesc(notags(trim($new_name))), dbesc(datetime_convert()), intval($importer['importer_uid']), intval($importer['id']), dbesc(notags(trim($new_name)))); // do our best to update the name on content items if (count($r) and notags(trim($new_name)) != $r[0]['name']) { q("UPDATE `item` SET `author-name` = '%s' WHERE `author-name` = '%s' AND `author-link` = '%s' AND `uid` = %d AND `author-name` != '%s'", dbesc(notags(trim($new_name))), dbesc($r[0]['name']), dbesc($r[0]['url']), intval($importer['importer_uid']), dbesc(notags(trim($new_name)))); } } if ($contact_updated and $new_name and $photo_url) { poco_check($importer['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $importer['id'], $importer['importer_uid']); } // Currently unsupported - needs a lot of work $reloc = $feed->get_feed_tags(NAMESPACE_DFRN, 'relocate'); if (isset($reloc[0]['child'][NAMESPACE_DFRN])) { $base = $reloc[0]['child'][NAMESPACE_DFRN]; $newloc = array(); $newloc['uid'] = $importer['importer_uid']; $newloc['cid'] = $importer['id']; $newloc['name'] = notags(unxmlify($base['name'][0]['data'])); $newloc['photo'] = notags(unxmlify($base['photo'][0]['data'])); $newloc['thumb'] = notags(unxmlify($base['thumb'][0]['data'])); $newloc['micro'] = notags(unxmlify($base['micro'][0]['data'])); $newloc['url'] = notags(unxmlify($base['url'][0]['data'])); $newloc['request'] = notags(unxmlify($base['request'][0]['data'])); $newloc['confirm'] = notags(unxmlify($base['confirm'][0]['data'])); $newloc['notify'] = notags(unxmlify($base['notify'][0]['data'])); $newloc['poll'] = notags(unxmlify($base['poll'][0]['data'])); $newloc['sitepubkey'] = notags(unxmlify($base['sitepubkey'][0]['data'])); /** relocated user must have original key pair */ /*$newloc['pubkey'] = notags(unxmlify($base['pubkey'][0]['data'])); $newloc['prvkey'] = notags(unxmlify($base['prvkey'][0]['data']));*/ logger("items:relocate contact " . print_r($newloc, true) . print_r($importer, true), LOGGER_DEBUG); // update contact $r = q("SELECT photo, url FROM contact WHERE id=%d AND uid=%d;", intval($importer['id']), intval($importer['importer_uid'])); if ($r === false) { return 1; } $old = $r[0]; $x = q("UPDATE contact SET\n\t\t\t\t\tname = '%s',\n\t\t\t\t\tphoto = '%s',\n\t\t\t\t\tthumb = '%s',\n\t\t\t\t\tmicro = '%s',\n\t\t\t\t\turl = '%s',\n\t\t\t\t\tnurl = '%s',\n\t\t\t\t\trequest = '%s',\n\t\t\t\t\tconfirm = '%s',\n\t\t\t\t\tnotify = '%s',\n\t\t\t\t\tpoll = '%s',\n\t\t\t\t\t`site-pubkey` = '%s'\n\t\t\tWHERE id=%d AND uid=%d;", dbesc($newloc['name']), dbesc($newloc['photo']), dbesc($newloc['thumb']), dbesc($newloc['micro']), dbesc($newloc['url']), dbesc(normalise_link($newloc['url'])), dbesc($newloc['request']), dbesc($newloc['confirm']), dbesc($newloc['notify']), dbesc($newloc['poll']), dbesc($newloc['sitepubkey']), intval($importer['id']), intval($importer['importer_uid'])); if ($x === false) { return 1; } // update items $fields = array('owner-link' => array($old['url'], $newloc['url']), 'author-link' => array($old['url'], $newloc['url']), 'owner-avatar' => array($old['photo'], $newloc['photo']), 'author-avatar' => array($old['photo'], $newloc['photo'])); foreach ($fields as $n => $f) { $x = q("UPDATE `item` SET `%s`='%s' WHERE `%s`='%s' AND uid=%d", $n, dbesc($f[1]), $n, dbesc($f[0]), intval($importer['importer_uid'])); if ($x === false) { return 1; } } // TODO // merge with current record, current contents have priority // update record, set url-updated // update profile photos // schedule a scan? return 0; } // handle friend suggestion notification $sugg = $feed->get_feed_tags(NAMESPACE_DFRN, 'suggest'); if (isset($sugg[0]['child'][NAMESPACE_DFRN])) { $base = $sugg[0]['child'][NAMESPACE_DFRN]; $fsugg = array(); $fsugg['uid'] = $importer['importer_uid']; $fsugg['cid'] = $importer['id']; $fsugg['name'] = notags(unxmlify($base['name'][0]['data'])); $fsugg['photo'] = notags(unxmlify($base['photo'][0]['data'])); $fsugg['url'] = notags(unxmlify($base['url'][0]['data'])); $fsugg['request'] = notags(unxmlify($base['request'][0]['data'])); $fsugg['body'] = escape_tags(unxmlify($base['note'][0]['data'])); // Does our member already have a friend matching this description? $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `nurl` = '%s' AND `uid` = %d LIMIT 1", dbesc($fsugg['name']), dbesc(normalise_link($fsugg['url'])), intval($fsugg['uid'])); if (count($r)) { return 0; } // Do we already have an fcontact record for this person? $fid = 0; $r = q("SELECT * FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1", dbesc($fsugg['url']), dbesc($fsugg['name']), dbesc($fsugg['request'])); if (count($r)) { $fid = $r[0]['id']; // OK, we do. Do we already have an introduction for this person ? $r = q("select id from intro where uid = %d and fid = %d limit 1", intval($fsugg['uid']), intval($fid)); if (count($r)) { return 0; } } if (!$fid) { $r = q("INSERT INTO `fcontact` ( `name`,`url`,`photo`,`request` ) VALUES ( '%s', '%s', '%s', '%s' ) ", dbesc($fsugg['name']), dbesc($fsugg['url']), dbesc($fsugg['photo']), dbesc($fsugg['request'])); } $r = q("SELECT * FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1", dbesc($fsugg['url']), dbesc($fsugg['name']), dbesc($fsugg['request'])); if (count($r)) { $fid = $r[0]['id']; } else { return 0; } $hash = random_string(); $r = q("INSERT INTO `intro` ( `uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked` )\n\t\t\tVALUES( %d, %d, %d, '%s', '%s', '%s', %d )", intval($fsugg['uid']), intval($fid), intval($fsugg['cid']), dbesc($fsugg['body']), dbesc($hash), dbesc(datetime_convert()), intval(0)); notification(array('type' => NOTIFY_SUGGEST, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $fsugg, 'link' => $a->get_baseurl() . '/notifications/intros', 'source_name' => $importer['name'], 'source_link' => $importer['url'], 'source_photo' => $importer['photo'], 'verb' => ACTIVITY_REQ_FRIEND, 'otype' => 'intro')); return 0; } $ismail = false; $rawmail = $feed->get_feed_tags(NAMESPACE_DFRN, 'mail'); if (isset($rawmail[0]['child'][NAMESPACE_DFRN])) { logger('local_delivery: private message received'); $ismail = true; $base = $rawmail[0]['child'][NAMESPACE_DFRN]; $msg = array(); $msg['uid'] = $importer['importer_uid']; $msg['from-name'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['name'][0]['data'])); $msg['from-photo'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['avatar'][0]['data'])); $msg['from-url'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])); $msg['contact-id'] = $importer['id']; $msg['title'] = notags(unxmlify($base['subject'][0]['data'])); $msg['body'] = escape_tags(unxmlify($base['content'][0]['data'])); $msg['seen'] = 0; $msg['replied'] = 0; $msg['uri'] = notags(unxmlify($base['id'][0]['data'])); $msg['parent-uri'] = notags(unxmlify($base['in-reply-to'][0]['data'])); $msg['created'] = datetime_convert(notags(unxmlify('UTC', 'UTC', $base['sentdate'][0]['data']))); dbesc_array($msg); $r = dbq("INSERT INTO `mail` (`" . implode("`, `", array_keys($msg)) . "`) VALUES ('" . implode("', '", array_values($msg)) . "')"); // send notifications. require_once 'include/enotify.php'; $notif_params = array('type' => NOTIFY_MAIL, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $msg, 'source_name' => $msg['from-name'], 'source_link' => $importer['url'], 'source_photo' => $importer['thumb'], 'verb' => ACTIVITY_POST, 'otype' => 'mail'); notification($notif_params); return 0; // NOTREACHED } $community_page = 0; $rawtags = $feed->get_feed_tags(NAMESPACE_DFRN, 'community'); if ($rawtags) { $community_page = intval($rawtags[0]['data']); } if (intval($importer['forum']) != $community_page) { q("update contact set forum = %d where id = %d", intval($community_page), intval($importer['id'])); $importer['forum'] = (string) $community_page; } logger('local_delivery: feed item count = ' . $feed->get_item_quantity()); // process any deleted entries $del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry'); if (is_array($del_entries) && count($del_entries)) { foreach ($del_entries as $dentry) { $deleted = false; if (isset($dentry['attribs']['']['ref'])) { $uri = $dentry['attribs']['']['ref']; $deleted = true; if (isset($dentry['attribs']['']['when'])) { $when = $dentry['attribs']['']['when']; $when = datetime_convert('UTC', 'UTC', $when, 'Y-m-d H:i:s'); } else { $when = datetime_convert('UTC', 'UTC', 'now', 'Y-m-d H:i:s'); } } if ($deleted) { // check for relayed deletes to our conversation $is_reply = false; $r = q("select * from item where uri = '%s' and uid = %d limit 1", dbesc($uri), intval($importer['importer_uid'])); if (count($r)) { $parent_uri = $r[0]['parent-uri']; if ($r[0]['id'] != $r[0]['parent']) { $is_reply = true; } } if ($is_reply) { $community = false; if ($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) { $sql_extra = ''; $community = true; logger('local_delivery: possible community delete'); } else { $sql_extra = " and contact.self = 1 and item.wall = 1 "; } // was the top-level post for this reply written by somebody on this site? // Specifically, the recipient? $is_a_remote_delete = false; // POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used? $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`,\n\t\t\t\t\t\t`contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item`\n\t\t\t\t\t\tINNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`\n\t\t\t\t\t\tWHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')\n\t\t\t\t\t\tAND `item`.`uid` = %d\n\t\t\t\t\t\t{$sql_extra}\n\t\t\t\t\t\tLIMIT 1", dbesc($parent_uri), dbesc($parent_uri), dbesc($parent_uri), intval($importer['importer_uid'])); if ($r && count($r)) { $is_a_remote_delete = true; } // Does this have the characteristics of a community or private group comment? // If it's a reply to a wall post on a community/prvgroup page it's a // valid community comment. Also forum_mode makes it valid for sure. // If neither, it's not. if ($is_a_remote_delete && $community) { if (!$r[0]['forum_mode'] && !$r[0]['wall']) { $is_a_remote_delete = false; logger('local_delivery: not a community delete'); } } if ($is_a_remote_delete) { logger('local_delivery: received remote delete'); } } $r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN contact on `item`.`contact-id` = `contact`.`id`\n\t\t\t\t\tWHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1", dbesc($uri), intval($importer['importer_uid']), intval($importer['id'])); if (count($r)) { $item = $r[0]; if ($item['deleted']) { continue; } logger('local_delivery: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG); if ($item['object-type'] === ACTIVITY_OBJ_EVENT) { logger("Deleting event " . $item['event-id'], LOGGER_DEBUG); event_delete($item['event-id']); } if ($item['verb'] === ACTIVITY_TAG && $item['object-type'] === ACTIVITY_OBJ_TAGTERM) { $xo = parse_xml_string($item['object'], false); $xt = parse_xml_string($item['target'], false); if ($xt->type === ACTIVITY_OBJ_NOTE) { $i = q("select * from `item` where uri = '%s' and uid = %d limit 1", dbesc($xt->id), intval($importer['importer_uid'])); if (count($i)) { // For tags, the owner cannot remove the tag on the author's copy of the post. $owner_remove = $item['contact-id'] == $i[0]['contact-id'] ? true : false; $author_remove = $item['origin'] && $item['self'] ? true : false; $author_copy = $item['origin'] ? true : false; if ($owner_remove && $author_copy) { continue; } if ($author_remove || $owner_remove) { $tags = explode(',', $i[0]['tag']); $newtags = array(); if (count($tags)) { foreach ($tags as $tag) { if (trim($tag) !== trim($xo->body)) { $newtags[] = trim($tag); } } } q("update item set tag = '%s' where id = %d", dbesc(implode(',', $newtags)), intval($i[0]['id'])); create_tags_from_item($i[0]['id']); } } } } if ($item['uri'] == $item['parent-uri']) { $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',\n\t\t\t\t\t\t\t`body` = '', `title` = ''\n\t\t\t\t\t\t\tWHERE `parent-uri` = '%s' AND `uid` = %d", dbesc($when), dbesc(datetime_convert()), dbesc($item['uri']), intval($importer['importer_uid'])); create_tags_from_itemuri($item['uri'], $importer['importer_uid']); create_files_from_itemuri($item['uri'], $importer['importer_uid']); update_thread_uri($item['uri'], $importer['importer_uid']); } else { $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',\n\t\t\t\t\t\t\t`body` = '', `title` = ''\n\t\t\t\t\t\t\tWHERE `uri` = '%s' AND `uid` = %d", dbesc($when), dbesc(datetime_convert()), dbesc($uri), intval($importer['importer_uid'])); create_tags_from_itemuri($uri, $importer['importer_uid']); create_files_from_itemuri($uri, $importer['importer_uid']); update_thread_uri($uri, $importer['importer_uid']); if ($item['last-child']) { // ensure that last-child is set in case the comment that had it just got wiped. q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", dbesc(datetime_convert()), dbesc($item['parent-uri']), intval($item['uid'])); // who is the last child now? $r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d\n\t\t\t\t\t\t\t\tORDER BY `created` DESC LIMIT 1", dbesc($item['parent-uri']), intval($importer['importer_uid'])); if (count($r)) { q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d", intval($r[0]['id'])); } } // if this is a relayed delete, propagate it to other recipients if ($is_a_remote_delete) { proc_run('php', "include/notifier.php", "drop", $item['id']); } } } } } } foreach ($feed->get_items() as $item) { $is_reply = false; $item_id = $item->get_id(); $rawthread = $item->get_item_tags(NAMESPACE_THREAD, 'in-reply-to'); if (isset($rawthread[0]['attribs']['']['ref'])) { $is_reply = true; $parent_uri = $rawthread[0]['attribs']['']['ref']; } if ($is_reply) { $community = false; if ($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) { $sql_extra = ''; $community = true; logger('local_delivery: possible community reply'); } else { $sql_extra = " and contact.self = 1 and item.wall = 1 "; } // was the top-level post for this reply written by somebody on this site? // Specifically, the recipient? $is_a_remote_comment = false; $top_uri = $parent_uri; $r = q("select `item`.`parent-uri` from `item`\n\t\t\t\tWHERE `item`.`uri` = '%s'\n\t\t\t\tLIMIT 1", dbesc($parent_uri)); if ($r && count($r)) { $top_uri = $r[0]['parent-uri']; // POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used? $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`,\n\t\t\t\t\t`contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item`\n\t\t\t\t\tINNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`\n\t\t\t\t\tWHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')\n\t\t\t\t\tAND `item`.`uid` = %d\n\t\t\t\t\t{$sql_extra}\n\t\t\t\t\tLIMIT 1", dbesc($top_uri), dbesc($top_uri), dbesc($top_uri), intval($importer['importer_uid'])); if ($r && count($r)) { $is_a_remote_comment = true; } } // Does this have the characteristics of a community or private group comment? // If it's a reply to a wall post on a community/prvgroup page it's a // valid community comment. Also forum_mode makes it valid for sure. // If neither, it's not. if ($is_a_remote_comment && $community) { if (!$r[0]['forum_mode'] && !$r[0]['wall']) { $is_a_remote_comment = false; logger('local_delivery: not a community reply'); } } if ($is_a_remote_comment) { logger('local_delivery: received remote comment'); $is_like = false; // remote reply to our post. Import and then notify everybody else. $datarray = get_atom_elements($feed, $item); $r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid'])); // Update content if 'updated' changes if (count($r)) { $iid = $r[0]['id']; if (edited_timestamp_is_newer($r[0], $datarray)) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } logger('received updated comment', LOGGER_DEBUG); $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc(datetime_convert('UTC', 'UTC', $datarray['edited'])), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); create_tags_from_itemuri($item_id, $importer['importer_uid']); proc_run('php', "include/notifier.php", "comment-import", $iid); } continue; } $own = q("select name,url,thumb from contact where uid = %d and self = 1 limit 1", intval($importer['importer_uid'])); $datarray['type'] = 'remote-comment'; $datarray['wall'] = 1; $datarray['parent-uri'] = $parent_uri; $datarray['uid'] = $importer['importer_uid']; $datarray['owner-name'] = $own[0]['name']; $datarray['owner-link'] = $own[0]['url']; $datarray['owner-avatar'] = $own[0]['thumb']; $datarray['contact-id'] = $importer['id']; if ($datarray['verb'] === ACTIVITY_LIKE || $datarray['verb'] === ACTIVITY_DISLIKE || $datarray['verb'] === ACTIVITY_ATTEND || $datarray['verb'] === ACTIVITY_ATTENDNO || $datarray['verb'] === ACTIVITY_ATTENDMAYBE) { $is_like = true; $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; $datarray['last-child'] = 0; // only one like or dislike per person // splitted into two queries for performance issues $r = q("select id from item where uid = %d and `contact-id` = %d and verb = '%s' and (`parent-uri` = '%s') and deleted = 0 limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($datarray['parent-uri'])); if ($r && count($r)) { continue; } $r = q("select id from item where uid = %d and `contact-id` = %d and verb = '%s' and (`thr-parent` = '%s') and deleted = 0 limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($datarray['parent-uri'])); if ($r && count($r)) { continue; } } if ($datarray['verb'] === ACTIVITY_TAG && $datarray['object-type'] === ACTIVITY_OBJ_TAGTERM) { $xo = parse_xml_string($datarray['object'], false); $xt = parse_xml_string($datarray['target'], false); if ($xt->type == ACTIVITY_OBJ_NOTE && $xt->id) { // fetch the parent item $tagp = q("select * from item where uri = '%s' and uid = %d limit 1", dbesc($xt->id), intval($importer['importer_uid'])); if (!count($tagp)) { continue; } // extract tag, if not duplicate, and this user allows tags, add to parent item if ($xo->id && $xo->content) { $newtag = '#[url=' . $xo->id . ']' . $xo->content . '[/url]'; if (!stristr($tagp[0]['tag'], $newtag)) { $i = q("SELECT `blocktags` FROM `user` where `uid` = %d LIMIT 1", intval($importer['importer_uid'])); if (count($i) && !intval($i[0]['blocktags'])) { q("UPDATE item SET tag = '%s', `edited` = '%s', `changed` = '%s' WHERE id = %d", dbesc($tagp[0]['tag'] . (strlen($tagp[0]['tag']) ? ',' : '') . $newtag), intval($tagp[0]['id']), dbesc(datetime_convert()), dbesc(datetime_convert())); create_tags_from_item($tagp[0]['id']); } } } } } $posted_id = item_store($datarray); $parent = 0; if ($posted_id) { $datarray["id"] = $posted_id; $r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($posted_id), intval($importer['importer_uid'])); if (count($r)) { $parent = $r[0]['parent']; $parent_uri = $r[0]['parent-uri']; } if (!$is_like) { $r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d", dbesc(datetime_convert()), intval($importer['importer_uid']), intval($r[0]['parent'])); $r2 = q("UPDATE `item` SET `last-child` = 1, `changed` = '%s' WHERE `uid` = %d AND `id` = %d", dbesc(datetime_convert()), intval($importer['importer_uid']), intval($posted_id)); } if ($posted_id && $parent) { proc_run('php', "include/notifier.php", "comment-import", "{$posted_id}"); if (!$is_like && !$importer['self']) { require_once 'include/enotify.php'; notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($posted_id)), 'source_name' => stripslashes($datarray['author-name']), 'source_link' => $datarray['author-link'], 'source_photo' => link_compare($datarray['author-link'], $importer['url']) ? $importer['thumb'] : $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_uri' => $parent_uri)); } } return 0; // NOTREACHED } } else { // regular comment that is part of this total conversation. Have we seen it? If not, import it. $item_id = $item->get_id(); $datarray = get_atom_elements($feed, $item); if ($importer['rel'] == CONTACT_IS_FOLLOWER) { continue; } $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid'])); // Update content if 'updated' changes if (count($r)) { if (edited_timestamp_is_newer($r[0], $datarray)) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc(datetime_convert('UTC', 'UTC', $datarray['edited'])), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); create_tags_from_itemuri($item_id, $importer['importer_uid']); } // update last-child if it changes $allow = $item->get_item_tags(NAMESPACE_DFRN, 'comment-allow'); if ($allow && $allow[0]['data'] != $r[0]['last-child']) { $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", dbesc(datetime_convert()), dbesc($parent_uri), intval($importer['importer_uid'])); $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", intval($allow[0]['data']), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); } continue; } $datarray['parent-uri'] = $parent_uri; $datarray['uid'] = $importer['importer_uid']; $datarray['contact-id'] = $importer['id']; if ($datarray['verb'] === ACTIVITY_LIKE || $datarray['verb'] === ACTIVITY_DISLIKE || $datarray['verb'] === ACTIVITY_ATTEND || $datarray['verb'] === ACTIVITY_ATTENDNO || $datarray['verb'] === ACTIVITY_ATTENDMAYBE) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; // only one like or dislike per person // splitted into two queries for performance issues $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 and (`parent-uri` = '%s') limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($parent_uri)); if ($r && count($r)) { continue; } $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 and (`thr-parent` = '%s') limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), dbesc($parent_uri)); if ($r && count($r)) { continue; } } if ($datarray['verb'] === ACTIVITY_TAG && $datarray['object-type'] === ACTIVITY_OBJ_TAGTERM) { $xo = parse_xml_string($datarray['object'], false); $xt = parse_xml_string($datarray['target'], false); if ($xt->type == ACTIVITY_OBJ_NOTE) { $r = q("select * from item where `uri` = '%s' AND `uid` = %d limit 1", dbesc($xt->id), intval($importer['importer_uid'])); if (!count($r)) { continue; } // extract tag, if not duplicate, add to parent item if ($xo->content) { if (!stristr($r[0]['tag'], trim($xo->content))) { q("UPDATE item SET tag = '%s' WHERE id = %d", dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . '#[url=' . $xo->id . ']' . $xo->content . '[/url]'), intval($r[0]['id'])); create_tags_from_item($r[0]['id']); } } } } $posted_id = item_store($datarray); // find out if our user is involved in this conversation and wants to be notified. if (!x($datarray['type']) || $datarray['type'] != 'activity') { $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0", dbesc($top_uri), intval($importer['importer_uid'])); if (count($myconv)) { $importer_url = $a->get_baseurl() . '/profile/' . $importer['nickname']; // first make sure this isn't our own post coming back to us from a wall-to-wall event if (!link_compare($datarray['author-link'], $importer_url)) { foreach ($myconv as $conv) { // now if we find a match, it means we're in this conversation if (!link_compare($conv['author-link'], $importer_url)) { continue; } require_once 'include/enotify.php'; $conv_parent = $conv['parent']; notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($posted_id)), 'source_name' => stripslashes($datarray['author-name']), 'source_link' => $datarray['author-link'], 'source_photo' => link_compare($datarray['author-link'], $importer['url']) ? $importer['thumb'] : $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $conv_parent, 'parent_uri' => $parent_uri)); // only send one notification break; } } } } continue; } } else { // Head post of a conversation. Have we seen it? If not, import it. $item_id = $item->get_id(); $datarray = get_atom_elements($feed, $item); if (x($datarray, 'object-type') && $datarray['object-type'] === ACTIVITY_OBJ_EVENT) { $ev = bbtoevent($datarray['body']); if ((x($ev, 'desc') || x($ev, 'summary')) && x($ev, 'start')) { $ev['cid'] = $importer['id']; $ev['uid'] = $importer['uid']; $ev['uri'] = $item_id; $ev['edited'] = $datarray['edited']; $ev['private'] = $datarray['private']; $ev['guid'] = $datarray['guid']; $r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['uid'])); if (count($r)) { $ev['id'] = $r[0]['id']; } $xyz = event_store($ev); continue; } } $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid'])); // Update content if 'updated' changes if (count($r)) { if (edited_timestamp_is_newer($r[0], $datarray)) { // do not accept (ignore) an earlier edit than one we currently have. if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) { continue; } $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc(datetime_convert('UTC', 'UTC', $datarray['edited'])), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); create_tags_from_itemuri($item_id, $importer['importer_uid']); update_thread_uri($item_id, $importer['importer_uid']); } // update last-child if it changes $allow = $item->get_item_tags(NAMESPACE_DFRN, 'comment-allow'); if ($allow && $allow[0]['data'] != $r[0]['last-child']) { $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", intval($allow[0]['data']), dbesc(datetime_convert()), dbesc($item_id), intval($importer['importer_uid'])); } continue; } $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['importer_uid']; $datarray['contact-id'] = $importer['id']; if (!link_compare($datarray['owner-link'], $importer['url'])) { // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, // but otherwise there's a possible data mixup on the sender's system. // the tgroup delivery code called from item_store will correct it if it's a forum, // but we're going to unconditionally correct it here so that the post will always be owned by our contact. logger('local_delivery: Correcting item owner.', LOGGER_DEBUG); $datarray['owner-name'] = $importer['senderName']; $datarray['owner-link'] = $importer['url']; $datarray['owner-avatar'] = $importer['thumb']; } if ($importer['rel'] == CONTACT_IS_FOLLOWER && !tgroup_check($importer['importer_uid'], $datarray)) { continue; } // This is my contact on another system, but it's really me. // Turn this into a wall post. $notify = item_is_remote_self($importer, $datarray); $posted_id = item_store($datarray, false, $notify); if (stristr($datarray['verb'], ACTIVITY_POKE)) { $verb = urldecode(substr($datarray['verb'], strpos($datarray['verb'], '#') + 1)); if (!$verb) { continue; } $xo = parse_xml_string($datarray['object'], false); if ($xo->type == ACTIVITY_OBJ_PERSON && $xo->id) { // somebody was poked/prodded. Was it me? $links = parse_xml_string("<links>" . unxmlify($xo->link) . "</links>", false); foreach ($links->link as $l) { $atts = $l->attributes(); switch ($atts['rel']) { case "alternate": $Blink = $atts['href']; break; default: break; } } if ($Blink && link_compare($Blink, $a->get_baseurl() . '/profile/' . $importer['nickname'])) { // send a notification require_once 'include/enotify.php'; notification(array('type' => NOTIFY_POKE, 'notify_flags' => $importer['notify-flags'], 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], 'uid' => $importer['importer_uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($posted_id)), 'source_name' => stripslashes($datarray['author-name']), 'source_link' => $datarray['author-link'], 'source_photo' => link_compare($datarray['author-link'], $importer['url']) ? $importer['thumb'] : $datarray['author-avatar'], 'verb' => $datarray['verb'], 'otype' => 'person', 'activity' => $verb, 'parent' => $datarray['parent'])); } } } continue; } } return 0; // NOTREACHED }
function ostatus_completion($conversation_url, $uid, $item = array()) { $a = get_app(); $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) { //$arr["app"] .= " (OStatus-NoCompletion)"; $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\n\t\t\t(SELECT `parent` FROM `item` WHERE `id` IN\n\t\t\t\t(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) { //$arr["app"] .= " (OStatus-NoConvFetched)"; $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); $r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid)); $importer = $r[0]; foreach ($items as $single_conv) { // Test - remove before flight //$tempfile = tempnam(get_temppath(), "conversation"); //file_put_contents($tempfile, json_encode($single_conv)); $mention = false; 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\n\t\t\t\t\t\t\t(SELECT `parent` FROM `item`\n\t\t\t\t\t\t\t\tWHERE `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; } } $parent_uri = $parent["uri"]; // "context" only seems to exist on older servers if (isset($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($single_conv->context->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); if ($parent_exists) { $parent_uri = $single_conv->context->inReplyTo->id; } } // This is the current way if (isset($single_conv->object->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($single_conv->object->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN)); if ($parent_exists) { $parent_uri = $single_conv->object->inReplyTo->id; } } $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; } if (is_array($single_conv->to)) { foreach ($single_conv->to as $to) { if ($importer["nurl"] == normalise_link($to->id)) { $mention = true; } } } $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 ($mention) { $u = q("SELECT `notify-flags`, `language`, `username`, `email` FROM user WHERE uid = %d LIMIT 1", intval($uid)); $r = q("SELECT `parent` FROM `item` WHERE `id` = %d", intval($newitem)); notification(array('type' => NOTIFY_TAGSELF, 'notify_flags' => $u[0]["notify-flags"], 'language' => $u[0]["language"], 'to_name' => $u[0]["username"], 'to_email' => $u[0]["email"], 'uid' => $uid, 'item' => $arr, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($newitem)), 'source_name' => $arr["author-name"], 'source_link' => $arr["author-link"], 'source_photo' => $arr["author-avatar"], 'verb' => ACTIVITY_TAG, 'otype' => 'item', 'parent' => $r[0]["parent"])); } // 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) { //$arr["app"] .= " (OStatus-NoConvFound)"; $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 appnet_fetchstream($a, $uid) { require_once "addon/appnet/AppDotNet.php"; require_once 'include/items.php'; $token = get_pconfig($uid, 'appnet', 'token'); $clientId = get_pconfig($uid, 'appnet', 'clientid'); $clientSecret = get_pconfig($uid, 'appnet', 'clientsecret'); $app = new AppDotNet($clientId, $clientSecret); $app->setAccessToken($token); $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid)); if (count($r)) { $me = $r[0]; } else { logger("appnet_fetchstream: Own contact not found for user " . $uid, LOGGER_DEBUG); return; } $user = q("SELECT * FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1", intval($uid)); if (count($user)) { $user = $user[0]; } else { logger("appnet_fetchstream: Own user not found for user " . $uid, LOGGER_DEBUG); return; } $ownid = get_pconfig($uid, 'appnet', 'ownid'); // Fetch stream $param = array("count" => 200, "include_deleted" => false, "include_directed_posts" => true, "include_html" => false, "include_post_annotations" => true); $lastid = get_pconfig($uid, 'appnet', 'laststreamid'); if ($lastid != "") { $param["since_id"] = $lastid; } try { $stream = $app->getUserStream($param); } catch (AppDotNetException $e) { logger("appnet_fetchstream: Error fetching stream for user " . $uid . " " . appnet_error($e->getMessage())); return; } if (!is_array($stream)) { $stream = array(); } $stream = array_reverse($stream); foreach ($stream as $post) { $postarray = appnet_createpost($a, $uid, $post, $me, $user, $ownid, true); $item = item_store($postarray); $postarray["id"] = $item; logger('appnet_fetchstream: User ' . $uid . ' posted stream item ' . $item); $lastid = $post["id"]; if ($item != 0 and $postarray['contact-id'] != $me["id"] and !function_exists("check_item_notification")) { $r = q("SELECT `thread`.`iid` AS `parent` FROM `thread`\n\t\t\t\tINNER JOIN `item` ON `thread`.`iid` = `item`.`parent` AND `thread`.`uid` = `item`.`uid`\n\t\t\t\tWHERE `item`.`id` = %d AND `thread`.`mention` LIMIT 1", dbesc($item)); if (count($r)) { require_once 'include/enotify.php'; notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $postarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($item)), 'source_name' => $postarray['author-name'], 'source_link' => $postarray['author-link'], 'source_photo' => $postarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $r[0]["parent"])); } } } set_pconfig($uid, 'appnet', 'laststreamid', $lastid); // Fetch mentions $param = array("count" => 200, "include_deleted" => false, "include_directed_posts" => true, "include_html" => false, "include_post_annotations" => true); $lastid = get_pconfig($uid, 'appnet', 'lastmentionid'); if ($lastid != "") { $param["since_id"] = $lastid; } try { $mentions = $app->getUserMentions("me", $param); } catch (AppDotNetException $e) { logger("appnet_fetchstream: Error fetching mentions for user " . $uid . " " . appnet_error($e->getMessage())); return; } if (!is_array($mentions)) { $mentions = array(); } $mentions = array_reverse($mentions); foreach ($mentions as $post) { $postarray = appnet_createpost($a, $uid, $post, $me, $user, $ownid, false); if (isset($postarray["id"])) { $item = $postarray["id"]; $parent_id = $postarray['parent']; } elseif (isset($postarray["body"])) { $item = item_store($postarray); $postarray["id"] = $item; $parent_id = 0; logger('appnet_fetchstream: User ' . $uid . ' posted mention item ' . $item); if ($item and function_exists("check_item_notification")) { check_item_notification($item, $uid, NOTIFY_TAGSELF); } } else { $item = 0; $parent_id = 0; } // Fetch the parent and id if ($parent_id == 0 and $postarray['uri'] != "") { $r = q("SELECT `id`, `parent` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($postarray['uri']), intval($uid)); if (count($r)) { $item = $r[0]['id']; $parent_id = $r[0]['parent']; } } $lastid = $post["id"]; //if (($item != 0) AND ($postarray['contact-id'] != $me["id"])) { if ($item != 0 and !function_exists("check_item_notification")) { require_once 'include/enotify.php'; notification(array('type' => NOTIFY_TAGSELF, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $postarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($item)), 'source_name' => $postarray['author-name'], 'source_link' => $postarray['author-link'], 'source_photo' => $postarray['author-avatar'], 'verb' => ACTIVITY_TAG, 'otype' => 'item', 'parent' => $parent_id)); } } set_pconfig($uid, 'appnet', 'lastmentionid', $lastid); /* To-Do $param = array("interaction_actions" => "star"); $interactions = $app->getMyInteractions($param); foreach ($interactions AS $interaction) appnet_dolike($a, $uid, $interaction); */ }
function twitter_fetchhometimeline($a, $uid) { $ckey = get_config('twitter', 'consumerkey'); $csecret = get_config('twitter', 'consumersecret'); $otoken = get_pconfig($uid, 'twitter', 'oauthtoken'); $osecret = get_pconfig($uid, 'twitter', 'oauthsecret'); $create_user = get_pconfig($uid, 'twitter', 'create_user'); $mirror_posts = get_pconfig($uid, 'twitter', 'mirror_posts'); logger("twitter_fetchhometimeline: Fetching for user " . $uid, LOGGER_DEBUG); $application_name = get_config('twitter', 'application_name'); if ($application_name == "") { $application_name = $a->get_hostname(); } require_once 'library/twitteroauth.php'; require_once 'include/items.php'; $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); $own_contact = twitter_fetch_own_contact($a, $uid); $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($own_contact), intval($uid)); if (count($r)) { $own_id = $r[0]["nick"]; } else { logger("twitter_fetchhometimeline: Own twitter contact not found for user " . $uid, LOGGER_DEBUG); return; } $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid)); if (count($r)) { $self = $r[0]; } else { logger("twitter_fetchhometimeline: Own contact not found for user " . $uid, LOGGER_DEBUG); return; } $u = q("SELECT * FROM user WHERE uid = %d LIMIT 1", intval($uid)); if (!count($u)) { logger("twitter_fetchhometimeline: Own user not found for user " . $uid, LOGGER_DEBUG); return; } $parameters = array("exclude_replies" => false, "trim_user" => false, "contributor_details" => true, "include_rts" => true); //$parameters["count"] = 200; // Fetching timeline $lastid = get_pconfig($uid, 'twitter', 'lasthometimelineid'); $first_time = $lastid == ""; if ($lastid != "") { $parameters["since_id"] = $lastid; } $items = $connection->get('statuses/home_timeline', $parameters); if (!is_array($items)) { logger("twitter_fetchhometimeline: Error fetching home timeline: " . print_r($items, true), LOGGER_DEBUG); return; } $posts = array_reverse($items); logger("twitter_fetchhometimeline: Fetching timeline for user " . $uid . " " . sizeof($posts) . " items", LOGGER_DEBUG); if (count($posts)) { foreach ($posts as $post) { if ($post->id_str > $lastid) { $lastid = $post->id_str; set_pconfig($uid, 'twitter', 'lasthometimelineid', $lastid); } if ($first_time) { continue; } if (stristr($post->source, $application_name) && $post->user->screen_name == $own_id) { logger("twitter_fetchhometimeline: Skip previously sended post", LOGGER_DEBUG); continue; } if ($mirror_posts && $post->user->screen_name == $own_id && $post->in_reply_to_status_id_str == "") { logger("twitter_fetchhometimeline: Skip post that will be mirrored", LOGGER_DEBUG); continue; } if ($post->in_reply_to_status_id_str != "") { twitter_fetchparentposts($a, $uid, $post, $connection, $self, $own_id); } $postarray = twitter_createpost($a, $uid, $post, $self, $create_user, true); if (trim($postarray['body']) == "") { continue; } $item = item_store($postarray); $postarray["id"] = $item; logger('twitter_fetchhometimeline: User ' . $self["nick"] . ' posted home timeline item ' . $item); if ($item and !function_exists("check_item_notification")) { twitter_checknotification($a, $uid, $own_id, $item, $postarray); } } } set_pconfig($uid, 'twitter', 'lasthometimelineid', $lastid); // Fetching mentions $lastid = get_pconfig($uid, 'twitter', 'lastmentionid'); $first_time = $lastid == ""; if ($lastid != "") { $parameters["since_id"] = $lastid; } $items = $connection->get('statuses/mentions_timeline', $parameters); if (!is_array($items)) { logger("twitter_fetchhometimeline: Error fetching mentions: " . print_r($items, true), LOGGER_DEBUG); return; } $posts = array_reverse($items); logger("twitter_fetchhometimeline: Fetching mentions for user " . $uid . " " . sizeof($posts) . " items", LOGGER_DEBUG); if (count($posts)) { foreach ($posts as $post) { if ($post->id_str > $lastid) { $lastid = $post->id_str; } if ($first_time) { continue; } if ($post->in_reply_to_status_id_str != "") { twitter_fetchparentposts($a, $uid, $post, $connection, $self, $own_id); } $postarray = twitter_createpost($a, $uid, $post, $self, false, false); if (trim($postarray['body']) == "") { continue; } $item = item_store($postarray); $postarray["id"] = $item; if ($item and function_exists("check_item_notification")) { check_item_notification($item, $uid, NOTIFY_TAGSELF); } if (!isset($postarray["parent"]) or $postarray["parent"] == 0) { $postarray["parent"] = $item; } logger('twitter_fetchhometimeline: User ' . $self["nick"] . ' posted mention timeline item ' . $item); if ($item == 0) { $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($postarray['uri']), intval($uid)); if (count($r)) { $item = $r[0]['id']; $parent_id = $r[0]['parent']; } } else { $parent_id = $postarray['parent']; } if ($item != 0 and !function_exists("check_item_notification")) { require_once 'include/enotify.php'; notification(array('type' => NOTIFY_TAGSELF, 'notify_flags' => $u[0]['notify-flags'], 'language' => $u[0]['language'], 'to_name' => $u[0]['username'], 'to_email' => $u[0]['email'], 'uid' => $u[0]['uid'], 'item' => $postarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($item)), 'source_name' => $postarray['author-name'], 'source_link' => $postarray['author-link'], 'source_photo' => $postarray['author-avatar'], 'verb' => ACTIVITY_TAG, 'otype' => 'item', 'parent' => $parent_id)); } } } set_pconfig($uid, 'twitter', 'lastmentionid', $lastid); }
function statusnet_fetchhometimeline($a, $uid, $mode = 1) { $conversations = array(); $ckey = get_pconfig($uid, 'statusnet', 'consumerkey'); $csecret = get_pconfig($uid, 'statusnet', 'consumersecret'); $api = get_pconfig($uid, 'statusnet', 'baseapi'); $otoken = get_pconfig($uid, 'statusnet', 'oauthtoken'); $osecret = get_pconfig($uid, 'statusnet', 'oauthsecret'); $create_user = get_pconfig($uid, 'statusnet', 'create_user'); // "create_user" is deactivated, since currently you cannot add users manually by now $create_user = true; logger("statusnet_fetchhometimeline: Fetching for user " . $uid, LOGGER_DEBUG); require_once 'library/twitteroauth.php'; require_once 'include/items.php'; $connection = new StatusNetOAuth($api, $ckey, $csecret, $otoken, $osecret); $own_contact = statusnet_fetch_own_contact($a, $uid); $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($own_contact), intval($uid)); if (count($r)) { $nick = $r[0]["nick"]; } else { logger("statusnet_fetchhometimeline: Own GNU Social contact not found for user " . $uid, LOGGER_DEBUG); return; } $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid)); if (count($r)) { $self = $r[0]; } else { logger("statusnet_fetchhometimeline: Own contact not found for user " . $uid, LOGGER_DEBUG); return; } $u = q("SELECT * FROM user WHERE uid = %d LIMIT 1", intval($uid)); if (!count($u)) { logger("statusnet_fetchhometimeline: Own user not found for user " . $uid, LOGGER_DEBUG); return; } $parameters = array("exclude_replies" => false, "trim_user" => false, "contributor_details" => true, "include_rts" => true); //$parameters["count"] = 200; if ($mode == 1) { // Fetching timeline $lastid = get_pconfig($uid, 'statusnet', 'lasthometimelineid'); //$lastid = 1; $first_time = $lastid == ""; if ($lastid != "") { $parameters["since_id"] = $lastid; } $items = $connection->get('statuses/home_timeline', $parameters); if (!is_array($items)) { if (is_object($items) and isset($items->error)) { $errormsg = $items->error; } elseif (is_object($items)) { $errormsg = print_r($items, true); } elseif (is_string($items) or is_float($items) or is_int($items)) { $errormsg = $items; } else { $errormsg = "Unknown error"; } logger("statusnet_fetchhometimeline: Error fetching home timeline: " . $errormsg, LOGGER_DEBUG); return; } $posts = array_reverse($items); logger("statusnet_fetchhometimeline: Fetching timeline for user " . $uid . " " . sizeof($posts) . " items", LOGGER_DEBUG); if (count($posts)) { foreach ($posts as $post) { if ($post->id > $lastid) { $lastid = $post->id; } if ($first_time) { continue; } if (isset($post->statusnet_conversation_id)) { if (!isset($conversations[$post->statusnet_conversation_id])) { statusnet_complete_conversation($a, $uid, $self, $create_user, $nick, $post->statusnet_conversation_id); $conversations[$post->statusnet_conversation_id] = $post->statusnet_conversation_id; } } else { $postarray = statusnet_createpost($a, $uid, $post, $self, $create_user, true); if (trim($postarray['body']) == "") { continue; } $item = item_store($postarray); $postarray["id"] = $item; logger('statusnet_fetchhometimeline: User ' . $self["nick"] . ' posted home timeline item ' . $item); if ($item and !function_exists("check_item_notification")) { statusnet_checknotification($a, $uid, $nick, $item, $postarray); } } } } set_pconfig($uid, 'statusnet', 'lasthometimelineid', $lastid); } // Fetching mentions $lastid = get_pconfig($uid, 'statusnet', 'lastmentionid'); $first_time = $lastid == ""; if ($lastid != "") { $parameters["since_id"] = $lastid; } $items = $connection->get('statuses/mentions_timeline', $parameters); if (!is_array($items)) { logger("statusnet_fetchhometimeline: Error fetching mentions: " . print_r($items, true), LOGGER_DEBUG); return; } $posts = array_reverse($items); logger("statusnet_fetchhometimeline: Fetching mentions for user " . $uid . " " . sizeof($posts) . " items", LOGGER_DEBUG); if (count($posts)) { foreach ($posts as $post) { if ($post->id > $lastid) { $lastid = $post->id; } if ($first_time) { continue; } $postarray = statusnet_createpost($a, $uid, $post, $self, false, false); if (isset($post->statusnet_conversation_id)) { if (!isset($conversations[$post->statusnet_conversation_id])) { statusnet_complete_conversation($a, $uid, $self, $create_user, $nick, $post->statusnet_conversation_id); $conversations[$post->statusnet_conversation_id] = $post->statusnet_conversation_id; } } else { if (trim($postarray['body']) != "") { continue; $item = item_store($postarray); $postarray["id"] = $item; logger('statusnet_fetchhometimeline: User ' . $self["nick"] . ' posted mention timeline item ' . $item); if ($item and function_exists("check_item_notification")) { check_item_notification($item, $uid, NOTIFY_TAGSELF); } } } $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($postarray['uri']), intval($uid)); if (count($r)) { $item = $r[0]['id']; $parent_id = $r[0]['parent']; } if ($item != 0 and !function_exists("check_item_notification")) { require_once 'include/enotify.php'; notification(array('type' => NOTIFY_TAGSELF, 'notify_flags' => $u[0]['notify-flags'], 'language' => $u[0]['language'], 'to_name' => $u[0]['username'], 'to_email' => $u[0]['email'], 'uid' => $u[0]['uid'], 'item' => $postarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($item)), 'source_name' => $postarray['author-name'], 'source_link' => $postarray['author-link'], 'source_photo' => $postarray['author-avatar'], 'verb' => ACTIVITY_TAG, 'otype' => 'item', 'parent' => $parent_id)); } } } set_pconfig($uid, 'statusnet', 'lastmentionid', $lastid); }
function fbsync_createcomment($a, $uid, $self_id, $self, $user, $contacts, $applications, $comment) { // check if it was already imported $r = q("SELECT `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' LIMIT 1", intval($uid), dbesc('fb::' . $comment->id)); if (count($r)) { return; } // check if it was an own post (separate posting for performance reasons) $r = q("SELECT `uri` FROM `item` WHERE `uid` = %d AND `extid` = '%s' LIMIT 1", intval($uid), dbesc('fb::' . $comment->id)); if (count($r)) { return; } $parent_uri = ""; $parent_contact = 0; $parent_nick = ""; // Fetch the parent uri (Checking if the parent exists) $r = q("SELECT `uri`, `contact-id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' LIMIT 1", intval($uid), dbesc('fb::' . $comment->post_id)); if (count($r)) { $parent_uri = $r[0]["uri"]; $parent_contact = $r[0]["contact-id"]; } // check if it is a reply to an own post (separate posting for performance reasons) $r = q("SELECT `uri`, `contact-id` FROM `item` WHERE `uid` = %d AND `extid` = '%s' LIMIT 1", intval($uid), dbesc('fb::' . $comment->post_id)); if (count($r)) { $parent_uri = $r[0]["uri"]; $parent_contact = $r[0]["contact-id"]; } // No parent? Then quit if ($parent_uri == "") { return; } //logger("fbsync_createcomment: Checking if parent contact is blocked: ".$parent_contact." - ".$parent_uri, LOGGER_DEBUG); // Check if the contact id was blocked if ($parent_contact > 0) { $r = q("SELECT `blocked`, `readonly`, `nick` FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($uid), intval($parent_contact)); // Should only happen if someone deleted the contact manually if (!count($r)) { logger("fbsync_createcomment: UID " . $uid . " - Contact " . $parent_contact . " doesn't seem to exist.", LOGGER_DEBUG); return; } // Is blocked? Then return if ($r[0]["readonly"] or $r[0]["blocked"]) { logger("fbsync_createcomment: UID " . $uid . " - Contact '" . $r[0]["nick"] . "' is blocked or readonly.", LOGGER_DEBUG); return; } $parent_nick = $r[0]["nick"]; logger("fbsync_createcomment: UID " . $uid . " - Contact '" . $r[0]["nick"] . "' isn't blocked. " . print_r($r, true), LOGGER_DEBUG); } $postarray = array(); $postarray['gravity'] = 0; $postarray['uid'] = $uid; $postarray['wall'] = 0; $postarray['verb'] = ACTIVITY_POST; $postarray['object-type'] = ACTIVITY_OBJ_COMMENT; $postarray['network'] = dbesc(NETWORK_FACEBOOK); $postarray['uri'] = "fb::" . $comment->id; $postarray['thr-parent'] = $parent_uri; $postarray['parent-uri'] = $parent_uri; //$postarray['plink'] = $comment->permalink; $contact_id = fbsync_fetch_contact($uid, $contacts[$comment->fromid], array(), false); $contact_nick = $contacts[$comment->fromid]->name; if ($contact_id == -1) { logger('fbsync_createcomment: Contact was blocked. Comment not imported ' . print_r($comment, true), LOGGER_DEBUG); return; } // If no contact was found, take it from the thread owner if ($contact_id <= 0) { $contact_id = $parent_contact; $contact_nick = $parent_nick; } // This case here should never happen if ($contact_id <= 0) { $contact_id = $self[0]["id"]; $contact_nick = $self[0]["nick"]; } if ($comment->fromid != $self_id) { $postarray['contact-id'] = $contact_id; $postarray['owner-name'] = $contacts[$comment->fromid]->name; $postarray['owner-link'] = $contacts[$comment->fromid]->url; $postarray['owner-avatar'] = $contacts[$comment->fromid]->pic_square; } else { $postarray['contact-id'] = $self[0]["id"]; $postarray['owner-name'] = $self[0]["name"]; $postarray['owner-link'] = $self[0]["url"]; $postarray['owner-avatar'] = $self[0]["photo"]; $contact_nick = $self[0]["nick"]; } $postarray['author-name'] = $postarray['owner-name']; $postarray['author-link'] = $postarray['owner-link']; $postarray['author-avatar'] = $postarray['owner-avatar']; $msgdata = fbsync_convertmsg($a, $comment->text); $postarray["body"] = $msgdata["body"]; $postarray["tag"] = $msgdata["tags"]; $postarray['created'] = datetime_convert('UTC', 'UTC', date("c", $comment->time)); $postarray['edited'] = datetime_convert('UTC', 'UTC', date("c", $comment->time)); $postarray['app'] = $applications[$comment->app_id]->display_name; if ($postarray['app'] == "") { $postarray['app'] = "Facebook"; } if (trim($postarray["body"]) == "") { return; } $item = item_store($postarray); $postarray["id"] = $item; logger('fbsync_createcomment: UID ' . $uid . ' - CID ' . $postarray['contact-id'] . ' - Nick ' . $contact_nick . ' posted comment ' . $item, LOGGER_DEBUG); if ($item == 0) { return; } $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0", dbesc($postarray['parent-uri']), intval($uid)); if (count($myconv)) { $importer_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname']; $own_contact = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1", intval($uid), dbesc("facebook::" . $self_id)); if (!count($own_contact)) { return; } foreach ($myconv as $conv) { // now if we find a match, it means we're in this conversation if (!link_compare($conv['author-link'], $importer_url) and !link_compare($conv['author-link'], $own_contact[0]["url"])) { continue; } require_once 'include/enotify.php'; $conv_parent = $conv['parent']; $notifyarr = array('type' => NOTIFY_COMMENT, 'notify_flags' => $user[0]['notify-flags'], 'language' => $user[0]['language'], 'to_name' => $user[0]['username'], 'to_email' => $user[0]['email'], 'uid' => $user[0]['uid'], 'item' => $postarray, 'link' => $a->get_baseurl() . '/display/' . urlencode(get_item_guid($item)), 'source_name' => $postarray['author-name'], 'source_link' => $postarray['author-link'], 'source_photo' => $postarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $conv_parent); notification($notifyarr); // only send one notification break; } } }