use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\ItemContent;
+use Friendica\Model\ItemURI;
+use Friendica\Model\Tag;
use Friendica\Model\User;
use Friendica\Protocol\Activity;
use Friendica\Util\ConfigFileLoader;
Hook::register('expire' , __FILE__, 'twitter_expire');
Hook::register('prepare_body' , __FILE__, 'twitter_prepare_body');
Hook::register('check_item_notification', __FILE__, 'twitter_check_item_notification');
+ Hook::register('probe_detect' , __FILE__, 'twitter_probe_detect');
Logger::info("installed twitter");
}
-function twitter_uninstall()
-{
- Hook::unregister('load_config' , __FILE__, 'twitter_load_config');
- Hook::unregister('connector_settings' , __FILE__, 'twitter_settings');
- Hook::unregister('connector_settings_post', __FILE__, 'twitter_settings_post');
- Hook::unregister('hook_fork' , __FILE__, 'twitter_hook_fork');
- Hook::unregister('post_local' , __FILE__, 'twitter_post_local');
- Hook::unregister('notifier_normal' , __FILE__, 'twitter_post_hook');
- Hook::unregister('jot_networks' , __FILE__, 'twitter_jot_nets');
- Hook::unregister('cron' , __FILE__, 'twitter_cron');
- Hook::unregister('follow' , __FILE__, 'twitter_follow');
- Hook::unregister('expire' , __FILE__, 'twitter_expire');
- Hook::unregister('prepare_body' , __FILE__, 'twitter_prepare_body');
- Hook::unregister('check_item_notification', __FILE__, 'twitter_check_item_notification');
-
- // old setting - remove only
- Hook::unregister('post_local_end' , __FILE__, 'twitter_post_hook');
- Hook::unregister('addon_settings' , __FILE__, 'twitter_settings');
- Hook::unregister('addon_settings_post', __FILE__, 'twitter_settings_post');
-}
+// Hook functions
function twitter_load_config(App $a, ConfigFileLoader $loader)
{
$connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret);
$connection->post('friendships/create', ['screen_name' => $nickname]);
- twitter_fetchuser($a, $uid, $nickname);
+ $user = twitter_fetchuser($nickname);
- $r = q("SELECT name,nick,url,addr,batch,notify,poll,request,confirm,poco,photo,priority,network,alias,pubkey
- FROM `contact` WHERE `uid` = %d AND `nick` = '%s'",
- intval($uid),
- DBA::escape($nickname));
- if (DBA::isResult($r)) {
- $contact["contact"] = $r[0];
+ $contact_id = twitter_fetch_contact($uid, $user, true);
+
+ $contact = Contact::getById($contact_id, ['name', 'nick', 'url', 'addr', 'batch', 'notify', 'poll', 'request', 'confirm', 'poco', 'photo', 'priority', 'network', 'alias', 'pubkey']);
+
+ if (DBA::isResult($contact)) {
+ $contact["contact"] = $contact;
}
}
$b['postopts'] .= 'twitter';
}
+function twitter_probe_detect(App $a, array &$hookData)
+{
+ // Don't overwrite an existing result
+ if ($hookData['result']) {
+ return;
+ }
+
+ // Avoid a lookup for the wrong network
+ if (!in_array($hookData['network'], ['', Protocol::TWITTER])) {
+ return;
+ }
+
+ if (preg_match('=(.*)@twitter.com=i', $hookData['uri'], $matches)) {
+ $nick = $matches[1];
+ } elseif (preg_match('=https?://(?:mobile\.)?twitter.com/(.*)=i', $hookData['uri'], $matches)) {
+ $nick = $matches[1];
+ } else {
+ return;
+ }
+
+ $user = twitter_fetchuser($nick);
+
+ if ($user) {
+ $hookData['result'] = twitter_user_to_contact($user);
+ }
+}
+
function twitter_action(App $a, $uid, $pid, $action)
{
$ckey = DI::config()->get('twitter', 'consumerkey');
$post = ['id' => $pid];
- Logger::log("twitter_action '" . $action . "' ID: " . $pid . " data: " . print_r($post, true), Logger::DATA);
+ Logger::debug('before action', ['action' => $action, 'pid' => $pid, 'data' => $post]);
switch ($action) {
- case "delete":
+ case 'delete':
// To-Do: $result = $connection->post('statuses/destroy', $post);
$result = [];
break;
- case "like":
+ case 'like':
$result = $connection->post('favorites/create', $post);
+ if ($connection->getLastHttpCode() != 200) {
+ Logger::error('Unable to create favorite', ['result' => $result]);
+ }
break;
- case "unlike":
+ case 'unlike':
$result = $connection->post('favorites/destroy', $post);
+ if ($connection->getLastHttpCode() != 200) {
+ Logger::error('Unable to destroy favorite', ['result' => $result]);
+ }
break;
default:
- Logger::log('Unhandled action ' . $action, Logger::DEBUG);
+ Logger::warning('Unhandled action', ['action' => $action]);
$result = [];
}
- Logger::log("twitter_action '" . $action . "' send, result: " . print_r($result, true), Logger::DEBUG);
+
+ Logger::info('after action', ['action' => $action, 'result' => $result]);
}
function twitter_post_hook(App $a, array &$b)
$b['body'] = twitter_update_mentions($b['body']);
- $msgarr = ItemContent::getPlaintextPost($b, $max_char, true, 8);
+ $msgarr = ItemContent::getPlaintextPost($b, $max_char, true, BBCode::TWITTER);
Logger::info('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]);
$msg = $msgarr["text"];
}
}
- $msgarr = ItemContent::getPlaintextPost($item, $max_char, true, 8);
+ $msgarr = ItemContent::getPlaintextPost($item, $max_char, true, BBCode::TWITTER);
$msg = $msgarr["text"];
if (isset($msgarr["url"]) && ($msgarr["type"] != "photo")) {
if (!empty($post->retweeted_status)) {
// We don't support nested shares, so we mustn't show quotes as shares on retweets
- $item = twitter_createpost($a, $uid, $post->retweeted_status, ['id' => 0], false, false, true);
+ $item = twitter_createpost($a, $uid, $post->retweeted_status, ['id' => 0], false, false, true, -1);
if (empty($item['body'])) {
return [];
}
- $datarray['body'] = "\n" . share_header(
+ $datarray['body'] = "\n" . BBCode::getShareOpeningTag(
$item['author-name'],
$item['author-link'],
$item['author-avatar'],
- '',
- $item['created'],
- $item['plink']
+ $item['plink'],
+ $item['created']
);
$datarray['body'] .= $item['body'] . '[/share]';
} else {
- $item = twitter_createpost($a, $uid, $post, ['id' => 0], false, false, false);
+ $item = twitter_createpost($a, $uid, $post, ['id' => 0], false, false, false, -1);
if (empty($item['body'])) {
return [];
try {
$status = $connection->get('friendships/show', $parameters);
- } catch (TwitterOAuthException $e) {
- Logger::info('Error fetching friendship status', ['user' => $uid, 'target' => $target, 'message' => $e->getMessage()]);
- return $relation;
- }
+ if ($connection->getLastHttpCode() !== 200) {
+ throw new Exception($status->errors[0]->message ?? 'HTTP response code ' . $connection->getLastHttpCode(), $status->errors[0]->code ?? $connection->getLastHttpCode());
+ }
- $following = $status->relationship->source->following;
- $followed = $status->relationship->source->followed_by;
+ $following = $status->relationship->source->following;
+ $followed = $status->relationship->source->followed_by;
+
+ if ($following && !$followed) {
+ $relation = Contact::SHARING;
+ } elseif (!$following && $followed) {
+ $relation = Contact::FOLLOWER;
+ } elseif ($following && $followed) {
+ $relation = Contact::FRIEND;
+ } elseif (!$following && !$followed) {
+ $relation = 0;
+ }
- if ($following && !$followed) {
- $relation = Contact::SHARING;
- } elseif (!$following && $followed) {
- $relation = Contact::FOLLOWER;
- } elseif ($following && $followed) {
- $relation = Contact::FRIEND;
- } elseif (!$following && !$followed) {
- $relation = 0;
+ Logger::info('Fetched friendship relation', ['user' => $uid, 'target' => $target, 'relation' => $relation]);
+ } catch (Throwable $e) {
+ Logger::error('Error fetching friendship status', ['user' => $uid, 'target' => $target, 'message' => $e->getMessage()]);
}
- Logger::info('Fetched friendship relation', ['user' => $uid, 'target' => $target, 'relation' => $relation]);
-
return $relation;
}
-function twitter_fetch_contact($uid, $data, $create_user)
+/**
+ * @param $data
+ * @return array
+ */
+function twitter_user_to_contact($data)
{
if (empty($data->id_str)) {
- return -1;
+ return [];
}
- $avatar = twitter_fix_avatar($data->profile_image_url_https);
- $url = "https://twitter.com/" . $data->screen_name;
- $addr = $data->screen_name . "@twitter.com";
+ $baseurl = 'https://twitter.com';
+ $url = $baseurl . '/' . $data->screen_name;
+ $addr = $data->screen_name . '@twitter.com';
+
+ $fields = [
+ 'url' => $url,
+ 'network' => Protocol::TWITTER,
+ 'alias' => 'twitter::' . $data->id_str,
+ 'baseurl' => $baseurl,
+ 'name' => $data->name,
+ 'nick' => $data->screen_name,
+ 'addr' => $addr,
+ 'location' => $data->location,
+ 'about' => $data->description,
+ 'photo' => twitter_fix_avatar($data->profile_image_url_https),
+ ];
+
+ return $fields;
+}
- $fields = ['url' => $url, 'network' => Protocol::TWITTER,
- 'alias' => 'twitter::' . $data->id_str,
- 'name' => $data->name, 'nick' => $data->screen_name, 'addr' => $addr,
- 'location' => $data->location, 'about' => $data->description];
+function twitter_fetch_contact($uid, $data, $create_user)
+{
+ $fields = twitter_user_to_contact($data);
+
+ if (empty($fields)) {
+ return -1;
+ }
+
+ // photo comes from twitter_user_to_contact but shouldn't be saved directly in the contact row
+ $avatar = $fields['photo'];
+ unset($fields['photo']);
// Update the public contact
$pcontact = DBA::selectFirst('contact', ['id'], ['uid' => 0, 'alias' => "twitter::" . $data->id_str]);
if (DBA::isResult($pcontact)) {
$cid = $pcontact['id'];
} else {
- $cid = Contact::getIdForURL($url, 0, true, $fields);
+ $cid = Contact::getIdForURL($fields['url'], 0, true, $fields);
}
if (!empty($cid)) {
// create contact record
$fields['uid'] = $uid;
$fields['created'] = DateTimeFormat::utcNow();
- $fields['nurl'] = Strings::normaliseLink($url);
+ $fields['nurl'] = Strings::normaliseLink($fields['url']);
$fields['poll'] = 'twitter::' . $data->id_str;
$fields['rel'] = $relation;
$fields['priority'] = 1;
return $contact_id;
}
-function twitter_fetchuser(App $a, $uid, $screen_name = "", $user_id = "")
+/**
+ * @param string $screen_name
+ * @return stdClass|null
+ * @throws Exception
+ */
+function twitter_fetchuser($screen_name)
{
$ckey = DI::config()->get('twitter', 'consumerkey');
$csecret = DI::config()->get('twitter', 'consumersecret');
- $otoken = DI::pConfig()->get($uid, 'twitter', 'oauthtoken');
- $osecret = DI::pConfig()->get($uid, 'twitter', 'oauthsecret');
-
- $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
- intval($uid));
-
- if (DBA::isResult($r)) {
- $self = $r[0];
- } else {
- return;
- }
-
- $parameters = [];
-
- if ($screen_name != "") {
- $parameters["screen_name"] = $screen_name;
- }
-
- if ($user_id != "") {
- $parameters["user_id"] = $user_id;
- }
- // Fetching user data
- $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret);
try {
+ // Fetching user data
+ $connection = new TwitterOAuth($ckey, $csecret);
+ $parameters = ['screen_name' => $screen_name];
$user = $connection->get('users/show', $parameters);
} catch (TwitterOAuthException $e) {
- Logger::log('twitter_fetchuser: Error fetching user ' . $uid . ': ' . $e->getMessage());
- return;
+ Logger::log('twitter_fetchuser: Error fetching user ' . $screen_name . ': ' . $e->getMessage());
+ return null;
}
if (!is_object($user)) {
- return;
+ return null;
}
- $contact_id = twitter_fetch_contact($uid, $user, true);
-
- return $contact_id;
+ return $user;
}
-function twitter_expand_entities(App $a, $body, $item, $picture)
+/**
+ * Replaces Twitter entities with Friendica-friendly links.
+ *
+ * The Twitter API gives indices for each entity, which allows for fine-grained replacement.
+ *
+ * First, we need to collect everything that needs to be replaced, what we will replace it with, and the start index.
+ * Then we sort the indices decreasingly, and we replace from the end of the body to the start in order for the next
+ * index to be correct even after the last replacement.
+ *
+ * @param string $body
+ * @param stdClass $status
+ * @param string $picture
+ * @return array
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ */
+function twitter_expand_entities($body, stdClass $status, $picture)
{
$plain = $body;
- $tags_arr = [];
-
- foreach ($item->entities->hashtags AS $hashtag) {
- $url = '#[url=' . DI::baseUrl()->get() . '/search?tag=' . $hashtag->text . ']' . $hashtag->text . '[/url]';
- $tags_arr['#' . $hashtag->text] = $url;
- $body = str_replace('#' . $hashtag->text, $url, $body);
- }
+ $taglist = [];
- foreach ($item->entities->user_mentions AS $mention) {
- $url = '@[url=https://twitter.com/' . rawurlencode($mention->screen_name) . ']' . $mention->screen_name . '[/url]';
- $tags_arr['@' . $mention->screen_name] = $url;
- $body = str_replace('@' . $mention->screen_name, $url, $body);
- }
+ $replacementList = [];
- if (isset($item->entities->urls)) {
- $type = '';
- $footerurl = '';
- $footerlink = '';
- $footer = '';
+ foreach ($status->entities->hashtags AS $hashtag) {
+ $replace = '#[url=' . DI::baseUrl()->get() . '/search?tag=' . $hashtag->text . ']' . $hashtag->text . '[/url]';
+ $taglist['#' . $hashtag->text] = ['#', $hashtag->text, ''];
- foreach ($item->entities->urls as $url) {
- $plain = str_replace($url->url, '', $plain);
+ $replacementList[$hashtag->indices[0]] = [
+ 'replace' => $replace,
+ 'length' => $hashtag->indices[1] - $hashtag->indices[0],
+ ];
+ }
- if ($url->url && $url->expanded_url && $url->display_url) {
- // Quote tweet, we just remove the quoted tweet URL from the body, the share block will be added later.
- if (!empty($item->quoted_status) && isset($item->quoted_status_id_str)
- && substr($url->expanded_url, -strlen($item->quoted_status_id_str)) == $item->quoted_status_id_str ) {
- $body = str_replace($url->url, '', $body);
- continue;
- }
+ foreach ($status->entities->user_mentions AS $mention) {
+ $replace = '@[url=https://twitter.com/' . rawurlencode($mention->screen_name) . ']' . $mention->screen_name . '[/url]';
+ $taglist['@' . $mention->screen_name] = ['@', $mention->screen_name, 'https://twitter.com/' . rawurlencode($mention->screen_name)];
- $expanded_url = $url->expanded_url;
+ $replacementList[$mention->indices[0]] = [
+ 'replace' => $replace,
+ 'length' => $mention->indices[1] - $mention->indices[0],
+ ];
+ }
- $final_url = Network::finalUrl($url->expanded_url);
+ // This URL if set will be used to add an attachment at the bottom of the post
+ $attachmentUrl = '';
- $oembed_data = OEmbed::fetchURL($final_url);
+ foreach ($status->entities->urls ?? [] as $url) {
+ $plain = str_replace($url->url, '', $plain);
- if (empty($oembed_data) || empty($oembed_data->type)) {
- continue;
- }
+ if ($url->url && $url->expanded_url && $url->display_url) {
- // Quickfix: Workaround for URL with '[' and ']' in it
- if (strpos($expanded_url, '[') || strpos($expanded_url, ']')) {
- $expanded_url = $url->url;
- }
+ // Quote tweet, we just remove the quoted tweet URL from the body, the share block will be added later.
+ if (!empty($status->quoted_status) && isset($status->quoted_status_id_str)
+ && substr($url->expanded_url, -strlen($status->quoted_status_id_str)) == $status->quoted_status_id_str
+ ) {
+ $replacementList[$url->indices[0]] = [
+ 'replace' => '',
+ 'length' => $url->indices[1] - $url->indices[0],
+ ];
+ continue;
+ }
- if ($type == '') {
- $type = $oembed_data->type;
- }
+ $expanded_url = $url->expanded_url;
- if ($oembed_data->type == 'video') {
- $type = $oembed_data->type;
- $footerurl = $expanded_url;
- $footerlink = '[url=' . $expanded_url . ']' . $url->display_url . '[/url]';
+ $final_url = Network::finalUrl($url->expanded_url);
- $body = str_replace($url->url, $footerlink, $body);
- } elseif (($oembed_data->type == 'photo') && isset($oembed_data->url)) {
- $body = str_replace($url->url, '[url=' . $expanded_url . '][img]' . $oembed_data->url . '[/img][/url]', $body);
- } elseif ($oembed_data->type != 'link') {
- $body = str_replace($url->url, '[url=' . $expanded_url . ']' . $url->display_url . '[/url]', $body);
- } else {
- $img_str = Network::fetchUrl($final_url, true, 4);
+ $oembed_data = OEmbed::fetchURL($final_url);
- $tempfile = tempnam(get_temppath(), 'cache');
- file_put_contents($tempfile, $img_str);
+ if (empty($oembed_data) || empty($oembed_data->type)) {
+ continue;
+ }
- // See http://php.net/manual/en/function.exif-imagetype.php#79283
- if (filesize($tempfile) > 11) {
- $mime = image_type_to_mime_type(exif_imagetype($tempfile));
- } else {
- $mime = false;
- }
+ // Quickfix: Workaround for URL with '[' and ']' in it
+ if (strpos($expanded_url, '[') || strpos($expanded_url, ']')) {
+ $expanded_url = $url->url;
+ }
- unlink($tempfile);
+ if ($oembed_data->type == 'video') {
+ $attachmentUrl = $expanded_url;
+ $replace = '';
+ } elseif (($oembed_data->type == 'photo') && isset($oembed_data->url)) {
+ $replace = '[url=' . $expanded_url . '][img]' . $oembed_data->url . '[/img][/url]';
+ } elseif ($oembed_data->type != 'link') {
+ $replace = '[url=' . $expanded_url . ']' . $url->display_url . '[/url]';
+ } else {
+ $img_str = Network::fetchUrl($final_url, true, 4);
- if (substr($mime, 0, 6) == 'image/') {
- $type = 'photo';
- $body = str_replace($url->url, '[img]' . $final_url . '[/img]', $body);
- } else {
- $type = $oembed_data->type;
- $footerurl = $expanded_url;
- $footerlink = '[url=' . $expanded_url . ']' . $url->display_url . '[/url]';
+ $tempfile = tempnam(get_temppath(), 'cache');
+ file_put_contents($tempfile, $img_str);
- $body = str_replace($url->url, $footerlink, $body);
- }
+ // See http://php.net/manual/en/function.exif-imagetype.php#79283
+ if (filesize($tempfile) > 11) {
+ $mime = image_type_to_mime_type(exif_imagetype($tempfile));
+ } else {
+ $mime = false;
}
- }
- }
- // Footer will be taken care of with a share block in the case of a quote
- if (empty($item->quoted_status)) {
- if ($footerurl != '') {
- $footer = add_page_info($footerurl, false, $picture);
- }
-
- if (($footerlink != '') && (trim($footer) != '')) {
- $removedlink = trim(str_replace($footerlink, '', $body));
+ unlink($tempfile);
- if (($removedlink == '') || strstr($body, $removedlink)) {
- $body = $removedlink;
+ if (substr($mime, 0, 6) == 'image/') {
+ $replace = '[img]' . $final_url . '[/img]';
+ } else {
+ $attachmentUrl = $expanded_url;
+ $replace = '';
}
-
- $body .= $footer;
}
- if ($footer == '' && $picture != '') {
- $body .= "\n\n[img]" . $picture . "[/img]\n";
- } elseif ($footer == '' && $picture == '') {
- $body = add_page_info_to_body($body);
- }
+ $replacementList[$url->indices[0]] = [
+ 'replace' => $replace,
+ 'length' => $url->indices[1] - $url->indices[0],
+ ];
}
}
- // it seems as if the entities aren't always covering all mentions. So the rest will be checked here
- $tags = BBCode::getTags($body);
+ krsort($replacementList);
- if (count($tags)) {
- foreach ($tags as $tag) {
- if (strstr(trim($tag), ' ')) {
- continue;
- }
-
- if (strpos($tag, '#') === 0) {
- if (strpos($tag, '[url=')) {
- continue;
- }
-
- // don't link tags that are already embedded in links
- if (preg_match('/\[(.*?)' . preg_quote($tag, '/') . '(.*?)\]/', $body)) {
- continue;
- }
- if (preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag, '/') . '(.*?)\)/', $body)) {
- continue;
- }
+ foreach ($replacementList as $startIndex => $parameters) {
+ $body = Strings::substringReplace($body, $parameters['replace'], $startIndex, $parameters['length']);
+ }
- $basetag = str_replace('_', ' ', substr($tag, 1));
- $url = '#[url=' . DI::baseUrl()->get() . '/search?tag=' . $basetag . ']' . $basetag . '[/url]';
- $body = str_replace($tag, $url, $body);
- $tags_arr['#' . $basetag] = $url;
- } elseif (strpos($tag, '@') === 0) {
- if (strpos($tag, '[url=')) {
- continue;
- }
+ // Footer will be taken care of with a share block in the case of a quote
+ if (empty($status->quoted_status)) {
+ $footer = '';
+ if ($attachmentUrl) {
+ $footer = add_page_info($attachmentUrl, false, $picture);
+ }
- $basetag = substr($tag, 1);
- $url = '@[url=https://twitter.com/' . rawurlencode($basetag) . ']' . $basetag . '[/url]';
- $body = str_replace($tag, $url, $body);
- $tags_arr['@' . $basetag] = $url;
- }
+ if (trim($footer)) {
+ $body .= $footer;
+ } elseif ($picture) {
+ $body .= "\n\n[img]" . $picture . "[/img]\n";
+ } else {
+ $body = add_page_info_to_body($body);
}
}
- $tags = implode($tags_arr, ',');
-
- return ['body' => $body, 'tags' => $tags, 'plain' => $plain];
+ return ['body' => $body, 'plain' => $plain, 'taglist' => $taglist];
}
/**
return '';
}
-function twitter_createpost(App $a, $uid, $post, array $self, $create_user, $only_existing_contact, $noquote)
+/**
+ * Undocumented function
+ *
+ * @param App $a
+ * @param integer $uid User ID
+ * @param object $post Incoming Twitter post
+ * @param array $self
+ * @param bool $create_user Should users be created?
+ * @param bool $only_existing_contact Only import existing contacts if set to "true"
+ * @param bool $noquote
+ * @param integer $uriid URI Id used to store tags. 0 = create a new one; -1 = don't store tags for this post.
+ * @return array item array
+ */
+function twitter_createpost(App $a, $uid, $post, array $self, $create_user, $only_existing_contact, $noquote, int $uriid = 0)
{
$postarray = [];
$postarray['network'] = Protocol::TWITTER;
$postarray['protocol'] = Conversation::PARCEL_TWITTER;
$postarray['source'] = json_encode($post);
+ if (empty($uriid)) {
+ $uriid = $postarray['uri-id'] = ItemURI::insert(['uri' => $postarray['uri']]);
+ }
+
// Don't import our own comments
if (Item::exists(['extid' => $postarray['uri'], 'uid' => $uid])) {
Logger::log("Item with extid " . $postarray['uri'] . " found.", Logger::DEBUG);
// Search for media links
$picture = twitter_media_entities($post, $postarray);
- $converted = twitter_expand_entities($a, $postarray['body'], $post, $picture);
- $postarray['body'] = $converted["body"];
- $postarray['tag'] = $converted["tags"];
+ $converted = twitter_expand_entities($postarray['body'], $post, $picture);
+ $postarray['body'] = $converted['body'];
$postarray['created'] = DateTimeFormat::utc($post->created_at);
$postarray['edited'] = DateTimeFormat::utc($post->created_at);
+ if ($uriid > 0) {
+ twitter_store_tags($uriid, $converted['taglist']);
+ }
+
$statustext = $converted["plain"];
if (!empty($post->place->name)) {
}
}
- if (!empty($post->quoted_status) && !$noquote) {
- $quoted = twitter_createpost($a, $uid, $post->quoted_status, $self, false, false, true);
-
- if (!empty($quoted['body'])) {
- $postarray['body'] .= "\n" . share_header(
- $quoted['author-name'],
- $quoted['author-link'],
- $quoted['author-avatar'],
- "",
- $quoted['created'],
- $quoted['plink']
- );
-
- $postarray['body'] .= $quoted['body'] . '[/share]';
- } else {
- // Quoted post author is blocked/ignored, so we just provide the link to avoid removing quote context.
+ if (!empty($post->quoted_status)) {
+ if ($noquote) {
+ // To avoid recursive share blocks we just provide the link to avoid removing quote context.
$postarray['body'] .= "\n\nhttps://twitter.com/" . $post->quoted_status->user->screen_name . "/status/" . $post->quoted_status->id_str;
+ } else {
+ $quoted = twitter_createpost($a, $uid, $post->quoted_status, $self, false, false, true, $uriid);
+ if (!empty($quoted['body'])) {
+ $postarray['body'] .= "\n" . BBCode::getShareOpeningTag(
+ $quoted['author-name'],
+ $quoted['author-link'],
+ $quoted['author-avatar'],
+ $quoted['plink'],
+ $quoted['created']
+ );
+
+ $postarray['body'] .= $quoted['body'] . '[/share]';
+ } else {
+ // Quoted post author is blocked/ignored, so we just provide the link to avoid removing quote context.
+ $postarray['body'] .= "\n\nhttps://twitter.com/" . $post->quoted_status->user->screen_name . "/status/" . $post->quoted_status->id_str;
+ }
}
}
return $postarray;
}
+/**
+ * Store tags and mentions
+ *
+ * @param integer $uriid
+ * @param array $taglist
+ */
+function twitter_store_tags(int $uriid, array $taglist)
+{
+ foreach ($taglist as $tag) {
+ Tag::storeByHash($uriid, $tag[0], $tag[1], $tag[2]);
+ }
+}
+
function twitter_fetchparentposts(App $a, $uid, $post, TwitterOAuth $connection, array $self)
{
Logger::log("twitter_fetchparentposts: Fetching for user " . $uid . " and post " . $post->id_str, Logger::DEBUG);
}
}
- $item = Item::insert($postarray, false, $notify);
+ $item = Item::insert($postarray, $notify);
$postarray["id"] = $item;
Logger::log('User ' . $uid . ' posted home timeline item ' . $item);
// Fetching user data
// get() may throw TwitterOAuthException, but we will catch it later
$user = $connection->get('account/verify_credentials');
- if (empty($user) || empty($user->id_str)) {
+ if (empty($user->id_str)) {
return false;
}
function twitter_convert_share(array $attributes, array $author_contact, $content, $is_quote_share)
{
- if ($author_contact['network'] == Protocol::TWITTER) {
+ if (empty($author_contact)) {
+ return $content . "\n\n" . $attributes['link'];
+ }
+
+ if (!empty($author_contact['network']) && ($author_contact['network'] == Protocol::TWITTER)) {
$mention = '@' . $author_contact['nick'];
} else {
$mention = $author_contact['addr'];