X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=twitter%2Ftwitter.php;h=aeae1c2f5a7ded918c647029fab562c3d23059df;hb=7fb604f0ff544faa567aa93212649413ef727811;hp=e90f36df191c0de4ddfaed9e8078306ee6c8aec4;hpb=e89bab99add903f3a9c32b98a3c5c6749d37baf7;p=friendica-addons.git diff --git a/twitter/twitter.php b/twitter/twitter.php index e90f36df..aeae1c2f 100755 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -169,6 +169,7 @@ function twitter_settings_post ($a,$post) { del_pconfig(local_user(), 'twitter', 'intelligent_shortening'); del_pconfig(local_user(), 'twitter', 'import'); del_pconfig(local_user(), 'twitter', 'create_user'); + del_pconfig(local_user(), 'twitter', 'own_id'); } else { if (isset($_POST['twitter-pin'])) { // if the user supplied us with a PIN from Twitter, let the magic of OAuth happen @@ -229,8 +230,13 @@ function twitter_settings(&$a,&$s) { $create_userenabled = get_pconfig(local_user(),'twitter','create_user'); $create_userchecked = (($create_userenabled) ? ' checked="checked" ' : ''); - $s .= '
'; - $s .= '

'. t('Twitter Posting Settings') .'

'; + $s .= ''; + $s .= '

'. t('Twitter') .'

'; + $s .= '
'; + $s .= '
'; - $s .= '
'; + $s .= '
'; } else { /*** * we have an OAuth key / secret pair for the user @@ -310,7 +316,7 @@ function twitter_settings(&$a,&$s) { $s .= ''; $s .= ''; $s .= '
'; - $s .= '
'; + $s .= '
'; } } $s .= '
'; @@ -366,21 +372,25 @@ function short_link ($url) { } }; function twitter_shortenmsg($b, $shortlink = false) { + require_once("include/api.php"); require_once("include/bbcode.php"); require_once("include/html2plain.php"); $max_char = 140; + $b['body'] = bb_CleanPictureLinks($b['body']); + // Looking for the first image + $cleaned_body = api_clean_plain_items($b['body']); $image = ''; - if(preg_match("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/is",$b['body'],$matches)) + if(preg_match("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/is",$cleaned_body,$matches)) $image = $matches[3]; if ($image == '') - if(preg_match("/\[img\](.*?)\[\/img\]/is",$b['body'],$matches)) + if(preg_match("/\[img\](.*?)\[\/img\]/is",$cleaned_body,$matches)) $image = $matches[1]; - $multipleimages = (strpos($b['body'], "[img") != strrpos($b['body'], "[img")); + $multipleimages = (strpos($cleaned_body, "[img") != strrpos($cleaned_body, "[img")); // When saved into the database the content is sent through htmlspecialchars // That means that we have to decode all image-urls @@ -420,7 +430,7 @@ function twitter_shortenmsg($b, $shortlink = false) { //$body = preg_replace("/\[share(.*?)\](.*?)\[\/share\]/ism","\n\n$2\n\n",$body); // At first convert the text to html - $html = bbcode($body, false, false, 2); + $html = bbcode(api_clean_plain_items($body), false, false, 2); // Then convert it to plain text $msg = trim(html2plain($html, 0, true)); @@ -627,8 +637,12 @@ function twitter_post_hook(&$a,&$b) { $orig_post = $r[0]; } - // To-Do: Ab dem letzten / nehmen - $b["body"] = "@".substr($orig_post["author-link"], 20)." ".$b["body"]; + $nickname = preg_replace("=https?://twitter.com/(.*)=ism", "$1", $orig_post["author-link"]); + $nickname = "@[url=".$orig_post["author-link"]."]".$nickname."[/url]"; + + logger("twitter_post_hook: comparing ".$nickname." with ".$b["body"], LOGGER_DEBUG); + if (strpos($b["body"], $nickname) === false) + $b["body"] = $nickname." ".$b["body"]; logger("twitter_post_hook: parent found ".print_r($orig_post, true), LOGGER_DATA); } else { @@ -675,9 +689,14 @@ function twitter_post_hook(&$a,&$b) { if($ckey && $csecret && $otoken && $osecret) { logger('twitter: we have customer key and oauth stuff, going to send.', LOGGER_DEBUG); + // If it's a repeated message from twitter then do a native retweet and exit + if (twitter_is_retweet($a, $b['uid'], $b['body'])) + return; + require_once('library/twitteroauth.php'); require_once('include/bbcode.php'); $tweet = new TwitterOAuth($ckey,$csecret,$otoken,$osecret); + // in theory max char is 140 but T. uses t.co to make links // longer so we give them 10 characters extra if (!$intelligent_shortening) { @@ -762,6 +781,7 @@ function twitter_post_hook(&$a,&$b) { $msg = $msgarr["msg"]; $image = $msgarr["image"]; } + // and now tweet it :-) if(strlen($msg) and ($image != "")) { $img_str = fetch_url($image); @@ -787,16 +807,6 @@ function twitter_post_hook(&$a,&$b) { $result = $cb->statuses_updateWithMedia($post); unlink($tempfile); - /* - // Old Code - $mime = image_type_to_mime_type(exif_imagetype($tempfile)); - unlink($tempfile); - - $filename = "upload"; - - $result = $tweet->post('statuses/update_with_media', array('media[]' => "{$img_str};type=".$mime.";filename={$filename}" , 'status' => $msg)); - */ - logger('twitter_post_with_media send, result: ' . print_r($result, true), LOGGER_DEBUG); if ($result->errors OR $result->error) { logger('Send to Twitter failed: "' . print_r($result->errors, true) . '"'); @@ -863,7 +873,7 @@ function twitter_plugin_admin(&$a, &$o){ $t = get_markup_template( "admin.tpl", "addon/twitter/" ); $o = replace_macros($t, array( - '$submit' => t('Submit'), + '$submit' => t('Save Settings'), // name, label, value, help, [extra values] '$consumerkey' => array('consumerkey', t('Consumer key'), get_config('twitter', 'consumerkey' ), ''), '$consumersecret' => array('consumersecret', t('Consumer secret'), get_config('twitter', 'consumersecret' ), ''), @@ -937,6 +947,8 @@ function twitter_fetchtimeline($a, $uid) { if ($application_name == "") $application_name = $a->get_hostname(); + $has_picture = false; + require_once('mod/item.php'); require_once('library/twitteroauth.php'); @@ -988,12 +1000,14 @@ function twitter_fetchtimeline($a, $uid) { switch($media->type) { case 'photo': $_REQUEST['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $_REQUEST['body']); + $has_picture = true; break; } } } - $converted = twitter_convertmsg($a, $_REQUEST['body'], true); + //$converted = twitter_convertmsg($a, $_REQUEST['body'], true, $has_picture); + $converted = twitter_expand_entities($a, $_REQUEST['body'], $post->retweeted_status, true, $has_picture); $_REQUEST['body'] = $converted["body"]; $_REQUEST['body'] = "[share author='".$post->retweeted_status->user->name. @@ -1010,12 +1024,14 @@ function twitter_fetchtimeline($a, $uid) { switch($media->type) { case 'photo': $_REQUEST['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $_REQUEST['body']); + $has_picture = true; break; } } } - $converted = twitter_convertmsg($a, $_REQUEST["body"], true); + //$converted = twitter_convertmsg($a, $_REQUEST["body"], true, $has_picture); + $converted = twitter_expand_entities($a, $_REQUEST["body"], $post, true, $has_picture); $_REQUEST['body'] = $converted["body"]; } @@ -1110,6 +1126,24 @@ function twitter_queue_hook(&$a,&$b) { function twitter_fetch_contact($uid, $contact, $create_user) { + // Check if the unique contact is existing + // To-Do: only update once a while + $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", + dbesc(normalise_link("https://twitter.com/".$contact->screen_name))); + + if (count($r) == 0) + q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')", + dbesc(normalise_link("https://twitter.com/".$contact->screen_name)), + dbesc($contact->name), + dbesc($contact->screen_name), + dbesc($contact->profile_image_url_https)); + else + q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'", + dbesc($contact->name), + dbesc($contact->screen_name), + dbesc($contact->profile_image_url_https), + dbesc(normalise_link("https://twitter.com/".$contact->screen_name))); + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1", intval($uid), dbesc("twitter::".$contact->id_str)); @@ -1182,6 +1216,7 @@ function twitter_fetch_contact($uid, $contact, $create_user) { dbesc(datetime_convert()), intval($contact_id) ); + } else { // update profile photos once every two weeks as we have no notification of when they change. @@ -1268,8 +1303,147 @@ function twitter_fetchuser($a, $uid, $screen_name = "", $user_id = "") { return $contact_id; } +function twitter_expand_entities($a, $body, $item, $no_tags = false, $dontincludemedia) { + require_once("include/oembed.php"); + + $tags = ""; + + if (isset($item->entities->urls)) { + $type = ""; + $footerurl = ""; + $footerlink = ""; + $footer = ""; + + foreach ($item->entities->urls AS $url) { + if ($url->url AND $url->expanded_url AND $url->display_url) { + + $expanded_url = twitter_original_url($url->expanded_url); + + $oembed_data = oembed_fetch_url($expanded_url); + + // Quickfix: Workaround for URL with "[" and "]" in it + if (strpos($expanded_url, "[") OR strpos($expanded_url, "]")) + $expanded_url = $url->url; + + if ($type == "") + $type = $oembed_data->type; + + if ($oembed_data->type == "video") { + $body = str_replace($url->url, + "[video]".$expanded_url."[/video]", $body); + $dontincludemedia = true; + } elseif (($oembed_data->type == "photo") AND isset($oembed_data->url) AND !$dontincludemedia) { + $body = str_replace($url->url, + "[url=".$expanded_url."][img]".$oembed_data->url."[/img][/url]", + $body); + $dontincludemedia = true; + } elseif ($oembed_data->type != "link") + $body = str_replace($url->url, + "[url=".$expanded_url."]".$expanded_url."[/url]", + $body); + //"[url=".$expanded_url."]".$url->display_url."[/url]", + else { + $img_str = fetch_url($expanded_url, true, $redirects, 4); + + $tempfile = tempnam(get_config("system","temppath"), "cache"); + file_put_contents($tempfile, $img_str); + $mime = image_type_to_mime_type(exif_imagetype($tempfile)); + unlink($tempfile); + + if (substr($mime, 0, 6) == "image/") { + $type = "photo"; + $body = str_replace($url->url, "[img]".$expanded_url."[/img]", $body); + $dontincludemedia = true; + } else { + $type = $oembed_data->type; + $footerurl = $expanded_url; + $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]"; + //$footerlink = "[url=".$expanded_url."]".$url->display_url."[/url]"; + + $body = str_replace($url->url, $footerlink, $body); + } + } + } + } + + if ($footerurl != "") + $footer = twitter_siteinfo($footerurl, $dontincludemedia); + + if (($footerlink != "") AND (trim($footer) != "")) { + $removedlink = trim(str_replace($footerlink, "", $body)); + + if (strstr($body, $removedlink)) + $body = $removedlink; + + $body .= "\n\n[class=type-".$type."]".$footer."[/class]"; + } + + if ($no_tags) + return(array("body" => $body, "tags" => "")); + + $tags_arr = array(); + + foreach ($item->entities->hashtags AS $hashtag) { + $url = "#[url=".$a->get_baseurl()."/search?tag=".rawurlencode($hashtag->text)."]".$hashtag->text."[/url]"; + $tags_arr["#".$hashtag->text] = $url; + $body = str_replace("#".$hashtag->text, $url, $body); + } + + 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); + } + + // it seems as if the entities aren't always covering all mentions. So the rest will be checked here + $tags = get_tags($body); + + 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; + + $basetag = str_replace('_',' ',substr($tag,1)); + $url = '#[url='.$a->get_baseurl().'/search?tag='.rawurlencode($basetag).']'.$basetag.'[/url]'; + $body = str_replace($tag,$url,$body); + $tags_arr["#".$basetag] = $url; + continue; + } elseif(strpos($tag,'@') === 0) { + if(strpos($tag,'[url=')) + continue; + + $basetag = substr($tag,1); + $url = '@[url=https://twitter.com/'.rawurlencode($basetag).']'.$basetag.'[/url]'; + $body = str_replace($tag,$url,$body); + $tags_arr["@".$basetag] = $url; + } + } + } + + + $tags = implode($tags_arr, ","); + + } + return(array("body" => $body, "tags" => $tags)); +} + function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing_contact) { + + $has_picture = false; + $postarray = array(); + $postarray['network'] = NETWORK_TWITTER; $postarray['gravity'] = 0; $postarray['uid'] = $uid; $postarray['wall'] = 0; @@ -1364,6 +1538,7 @@ function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing switch($media->type) { case 'photo': $postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']); + $has_picture = true; break; default: $postarray['body'] .= print_r($media, true); @@ -1371,7 +1546,8 @@ function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing } } - $converted = twitter_convertmsg($a, $postarray['body']); + //$converted = twitter_convertmsg($a, $postarray['body'], false, $has_picture); + $converted = twitter_expand_entities($a, $postarray['body'], $post, false, $has_picture); $postarray['body'] = $converted["body"]; $postarray['tag'] = $converted["tags"]; @@ -1400,6 +1576,7 @@ function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing switch($media->type) { case 'photo': $postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']); + $has_picture = true; break; default: $postarray['body'] .= print_r($media, true); @@ -1407,10 +1584,12 @@ function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing } } - $converted = twitter_convertmsg($a, $postarray['body']); + //$converted = twitter_convertmsg($a, $postarray['body'], false, $has_picture); + $converted = twitter_expand_entities($a, $postarray['body'], $post->retweeted_status, false, $has_picture); $postarray['body'] = $converted["body"]; $postarray['tag'] = $converted["tags"]; + twitter_fetch_contact($uid, $post->retweeted_status->user, false); // Deactivated at the moment, since there are problems with answers to retweets if (false AND !intval(get_config('system','wall-to-wall_share'))) { @@ -1425,6 +1604,10 @@ function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing $postarray['author-name'] = $post->retweeted_status->user->name; $postarray['author-link'] = "https://twitter.com/".$post->retweeted_status->user->screen_name; $postarray['author-avatar'] = $post->retweeted_status->user->profile_image_url_https; + //if (($post->retweeted_status->user->screen_name != "") AND ($post->retweeted_status->id_str != "")) { + // $postarray['plink'] = "https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str; + // $postarray['uri'] = "twitter::".$post->retweeted_status->id_str; + //} } } @@ -1722,10 +1905,14 @@ function twitter_original_url($url, $depth=1, $fetchbody = false) { return($url); } -function twitter_siteinfo($url) { +function twitter_siteinfo($url, $dontincludemedia) { require_once("mod/parse_url.php"); - $data = parseurl_getsiteinfo($url); + // Fetch site infos - but only from the meta data + $data = parseurl_getsiteinfo($url, true); + + if ($dontincludemedia) + unset($data["images"]); if (!is_string($data["text"]) AND (sizeof($data["images"]) == 0) AND ($data["title"] == $url)) return(""); @@ -1733,36 +1920,46 @@ function twitter_siteinfo($url) { if (is_string($data["title"])) $text .= "[bookmark=".$url."]".trim($data["title"])."[/bookmark]\n"; + // Add a spoiler to the extra information + //if ((sizeof($data["images"]) > 0) OR is_string($data["text"])) + // $text .= "[spoiler]"; + if (sizeof($data["images"]) > 0) { $imagedata = $data["images"][0]; - $text .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]' . "\n"; + //$text .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]' . "\n"; + $text .= '[img]'.$imagedata["src"].'[/img]'."\n"; } if (is_string($data["text"])) $text .= "[quote]".$data["text"]."[/quote]"; + //if ((sizeof($data["images"]) > 0) OR is_string($data["text"])) + // $text .= "[/spoiler]"; + return($text); } -function twitter_convertmsg($a, $body, $no_tags = false) { +function twitter_convertmsg($a, $body, $no_tags = false, $dontincludemedia) { + + require_once("include/oembed.php"); $links = preg_match_all("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", $body,$matches,PREG_SET_ORDER); $footer = ""; + $footerurl = ""; + $type = ""; if ($links) { foreach ($matches AS $match) { $expanded_url = twitter_original_url($match[2]); - // To-Do: - // Twitlonger + $oembed_data = oembed_fetch_url($expanded_url); + + if ($type == "") + $type = $oembed_data->type; - if (strstr($expanded_url, "//www.youtube.com/")) - $body = str_replace($match[2], "\n[youtube]".$expanded_url."[/youtube]\n", $body); - elseif (strstr($expanded_url, "//player.vimeo.com/")) - $body = str_replace($match[2], "\n[vimeo]".$expanded_url."[/vimeo]\n", $body); - elseif (strstr($expanded_url, "//instagram.com")) + if ($oembed_data->type != "link") $body = str_replace($match[2], "\n[url]".$expanded_url."[/url]\n", $body); else { $img_str = fetch_url($expanded_url, true, $redirects, 4); @@ -1772,12 +1969,13 @@ function twitter_convertmsg($a, $body, $no_tags = false) { $mime = image_type_to_mime_type(exif_imagetype($tempfile)); unlink($tempfile); - if (substr($mime, 0, 6) == "image/") + if (substr($mime, 0, 6) == "image/") { + $type = "photo"; $body = str_replace($match[2], "[img]".$expanded_url."[/img]", $body); - else { - - //if ($footer == "") - $footer = "\n\n".twitter_siteinfo($expanded_url); + $dontincludemedia = true; + } else { + $type = $oembed_data->type; + $footerurl = $expanded_url; $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]"; $body = str_replace($match[2], $footerlink, $body); @@ -1785,18 +1983,21 @@ function twitter_convertmsg($a, $body, $no_tags = false) { } } + if ($footerurl != "") + $footer = twitter_siteinfo($footerurl, $dontincludemedia); + if (($footerlink != "") AND (trim($footer) != "")) { $removedlink = trim(str_replace($footerlink, "", $body)); if (strstr($body, $removedlink)) $body = $removedlink; - $body .= $footer; + $body .= "\n\n[class=type-".$type."]".$footer."[/class]"; } } if ($no_tags) - return(array("body" => $body, $tags => "")); + return(array("body" => $body, "tags" => "")); $str_tags = ''; @@ -1872,8 +2073,59 @@ function twitter_fetch_own_contact($a, $uid) { intval($uid), dbesc("twitter::".$own_id)); if(count($r)) $contact_id = $r[0]["id"]; + else + del_pconfig($uid, 'twitter', 'own_id'); + } return($contact_id); } + +function twitter_is_retweet($a, $uid, $body) { + $body = trim($body); + + // Skip if it isn't a pure repeated messages + // Does it start with a share? + if (strpos($body, "[share") > 0) + return(false); + + // Does it end with a share? + if (strlen($body) > (strrpos($body, "[/share]") + 8)) + return(false); + + $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body); + // Skip if there is no shared message in there + if ($body == $attributes) + return(false); + + $link = ""; + preg_match("/link='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + preg_match('/link="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + $id = preg_replace("=https?://twitter.com/(.*)/status/(.*)=ism", "$2", $link); + if ($id == $link) + return(false); + + logger('twitter_is_retweet: Retweeting id '.$id.' for user '.$uid, LOGGER_DEBUG); + + $ckey = get_config('twitter', 'consumerkey'); + $csecret = get_config('twitter', 'consumersecret'); + $otoken = get_pconfig($uid, 'twitter', 'oauthtoken'); + $osecret = get_pconfig($uid, 'twitter', 'oauthsecret'); + + require_once('library/twitteroauth.php'); + $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret); + + $result = $connection->post('statuses/retweet/'.$id); + + logger('twitter_is_retweet: result '.print_r($result, true), LOGGER_DEBUG); + + return(!isset($result->errors)); +} + ?>