mirror of
https://github.com/YunoHost-Apps/hubzilla_ynh.git
synced 2024-09-03 19:26:21 +02:00
916 lines
36 KiB
PHP
Executable file
916 lines
36 KiB
PHP
Executable file
<?php
|
|
/**
|
|
* Name: Twitter Connector
|
|
* Description: Relay public postings to a connected Twitter account
|
|
* Version: 1.2
|
|
* Author: Tobias Diekershoff <https://f.diekershoff.de/profile/tobias>
|
|
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
|
|
* Author: Mike Macgirvin <https://zothub.com/channel/mike>
|
|
* Maintainer: none
|
|
*
|
|
* Copyright (c) 2011-2013 Tobias Diekershoff, Michael Vogel
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* * copyright notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of the <organization> nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
/* Twitter Plugin for Hubzilla
|
|
*
|
|
* Author: Tobias Diekershoff
|
|
* tobias.diekershoff@gmx.net
|
|
*
|
|
* License:3-clause BSD license
|
|
*
|
|
* Configuration:
|
|
* To use this plugin you need a OAuth Consumer key pair (key & secret)
|
|
* you can get it from Twitter at https://twitter.com/apps
|
|
*
|
|
* Register your Hubzilla site as "Client" application with "Read & Write" access
|
|
* we do not need "Twitter as login". When you've registered the app you get the
|
|
* OAuth Consumer key and secret pair for your application/site.
|
|
*
|
|
* Activate the plugin from the plugins section of your admin panel. When you have
|
|
* done so, add your consumer key and consumer secret in the Plugin Features section
|
|
* of the admin page. A link to this section will appear on the sidebar of the admin page
|
|
* called 'twitter'.
|
|
*
|
|
* Alternatively: (old way - may not work any more)
|
|
* Add this key pair to your global .htconfig.php or use the admin panel.
|
|
*
|
|
* $a->config['twitter']['consumerkey'] = 'your consumer_key here';
|
|
* $a->config['twitter']['consumersecret'] = 'your consumer_secret here';
|
|
*
|
|
* Requirements: PHP5, curl [Slinky library]
|
|
*/
|
|
|
|
define('TWITTER_DEFAULT_POLL_INTERVAL', 5); // given in minutes
|
|
|
|
function twitter_load() {
|
|
// we need some hooks, for the configuration and for sending tweets
|
|
register_hook('feature_settings', 'addon/twitter/twitter.php', 'twitter_settings');
|
|
register_hook('feature_settings_post', 'addon/twitter/twitter.php', 'twitter_settings_post');
|
|
register_hook('post_local', 'addon/twitter/twitter.php', 'twitter_post_local');
|
|
register_hook('notifier_normal', 'addon/twitter/twitter.php', 'twitter_post_hook');
|
|
register_hook('jot_networks', 'addon/twitter/twitter.php', 'twitter_jot_nets');
|
|
|
|
logger("installed twitter");
|
|
}
|
|
|
|
|
|
function twitter_unload() {
|
|
unregister_hook('feature_settings', 'addon/twitter/twitter.php', 'twitter_settings');
|
|
unregister_hook('feature_settings_post', 'addon/twitter/twitter.php', 'twitter_settings_post');
|
|
unregister_hook('post_local', 'addon/twitter/twitter.php', 'twitter_post_local');
|
|
unregister_hook('notifier_normal', 'addon/twitter/twitter.php', 'twitter_post_hook');
|
|
unregister_hook('jot_networks', 'addon/twitter/twitter.php', 'twitter_jot_nets');
|
|
|
|
logger("uninstalled twitter");
|
|
}
|
|
|
|
function twitter_jot_nets(&$a,&$b) {
|
|
if(! local_channel())
|
|
return;
|
|
|
|
$tw_post = get_pconfig(local_channel(),'twitter','post');
|
|
if(intval($tw_post) == 1) {
|
|
$tw_defpost = get_pconfig(local_channel(),'twitter','post_by_default');
|
|
$selected = ((intval($tw_defpost) == 1) ? ' checked="checked" ' : '');
|
|
$b .= '<div class="profile-jot-net"><input type="checkbox" name="twitter_enable"' . $selected . ' value="1" /> <img src="addon/twitter/twitter.png" /> ' . t('Post to Twitter') . '</div>';
|
|
}
|
|
}
|
|
|
|
function twitter_settings_post ($a,$post) {
|
|
if(! local_channel())
|
|
return;
|
|
// don't check twitter settings if twitter submit button is not clicked
|
|
if (!x($_POST,'twitter-submit'))
|
|
return;
|
|
|
|
if (isset($_POST['twitter-disconnect'])) {
|
|
/***
|
|
* if the twitter-disconnect checkbox is set, clear the OAuth key/secret pair
|
|
* from the user configuration
|
|
*/
|
|
del_pconfig(local_channel(), 'twitter', 'consumerkey');
|
|
del_pconfig(local_channel(), 'twitter', 'consumersecret');
|
|
del_pconfig(local_channel(), 'twitter', 'oauthtoken');
|
|
del_pconfig(local_channel(), 'twitter', 'oauthsecret');
|
|
del_pconfig(local_channel(), 'twitter', 'post');
|
|
del_pconfig(local_channel(), 'twitter', 'post_by_default');
|
|
del_pconfig(local_channel(), 'twitter', 'post_taglinks');
|
|
del_pconfig(local_channel(), 'twitter', 'lastid');
|
|
del_pconfig(local_channel(), 'twitter', 'intelligent_shortening');
|
|
del_pconfig(local_channel(), '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
|
|
logger('got a Twitter PIN');
|
|
require_once('library/twitteroauth.php');
|
|
$ckey = get_config('twitter', 'consumerkey');
|
|
$csecret = get_config('twitter', 'consumersecret');
|
|
// the token and secret for which the PIN was generated were hidden in the settings
|
|
// form as token and token2, we need a new connection to Twitter using these token
|
|
// and secret to request a Access Token with the PIN
|
|
$connection = new TwitterOAuth($ckey, $csecret, $_POST['twitter-token'], $_POST['twitter-token2']);
|
|
$token = $connection->getAccessToken( $_POST['twitter-pin'] );
|
|
// ok, now that we have the Access Token, save them in the user config
|
|
set_pconfig(local_channel(),'twitter', 'oauthtoken', $token['oauth_token']);
|
|
set_pconfig(local_channel(),'twitter', 'oauthsecret', $token['oauth_token_secret']);
|
|
set_pconfig(local_channel(),'twitter', 'post', 1);
|
|
set_pconfig(local_channel(),'twitter', 'post_taglinks', 1);
|
|
// reload the Addon Settings page, if we don't do it see Friendica Bug #42
|
|
goaway($a->get_baseurl().'/settings/featured');
|
|
} else {
|
|
// if no PIN is supplied in the POST variables, the user has changed the setting
|
|
// to post a tweet for every new __public__ posting to the wall
|
|
set_pconfig(local_channel(),'twitter','post',intval($_POST['twitter-enable']));
|
|
set_pconfig(local_channel(),'twitter','post_by_default',intval($_POST['twitter-default']));
|
|
set_pconfig(local_channel(),'twitter','post_taglinks',intval($_POST['twitter-sendtaglinks']));
|
|
set_pconfig(local_channel(),'twitter', 'mirror_posts', intval($_POST['twitter-mirror']));
|
|
set_pconfig(local_channel(),'twitter', 'intelligent_shortening', intval($_POST['twitter-shortening']));
|
|
set_pconfig(local_channel(),'twitter', 'import', intval($_POST['twitter-import']));
|
|
set_pconfig(local_channel(),'twitter', 'create_user', intval($_POST['twitter-create_user']));
|
|
info( t('Twitter settings updated.') . EOL);
|
|
}}
|
|
}
|
|
function twitter_settings(&$a,&$s) {
|
|
if(! local_channel())
|
|
return;
|
|
$a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="' . $a->get_baseurl() . '/addon/twitter/twitter.css' . '" media="all" />' . "\r\n";
|
|
/***
|
|
* 1) Check that we have global consumer key & secret
|
|
* 2) If no OAuthtoken & stuff is present, generate button to get some
|
|
* 3) Checkbox for "Send public notices (140 chars only)
|
|
*/
|
|
$ckey = get_config('twitter', 'consumerkey' );
|
|
$csecret = get_config('twitter', 'consumersecret' );
|
|
$otoken = get_pconfig(local_channel(), 'twitter', 'oauthtoken' );
|
|
$osecret = get_pconfig(local_channel(), 'twitter', 'oauthsecret' );
|
|
$enabled = get_pconfig(local_channel(), 'twitter', 'post');
|
|
$checked = (($enabled) ? 1 : false);
|
|
$defenabled = get_pconfig(local_channel(),'twitter','post_by_default');
|
|
$defchecked = (($defenabled) ? 1 : false);
|
|
//$shorteningenabled = get_pconfig(local_channel(),'twitter','intelligent_shortening');
|
|
//$shorteningchecked = (($shorteningenabled) ? 1 : false);
|
|
|
|
if ( (!$ckey) && (!$csecret) ) {
|
|
/***
|
|
* no global consumer keys
|
|
* display warning and skip personal config
|
|
*/
|
|
$sc .= '<div class="section-content-danger-wrapper">';
|
|
$sc .= t('No consumer key pair for Twitter found. Please contact your site administrator.');
|
|
$sc .= '</div>';
|
|
} else {
|
|
/***
|
|
* ok we have a consumer key pair now look into the OAuth stuff
|
|
*/
|
|
if ( (!$otoken) && (!$osecret) ) {
|
|
/***
|
|
* the user has not yet connected the account to twitter...
|
|
* get a temporary OAuth key/secret pair and display a button with
|
|
* which the user can request a PIN to connect the account to a
|
|
* account at Twitter.
|
|
*/
|
|
require_once('library/twitteroauth.php');
|
|
$connection = new TwitterOAuth($ckey, $csecret);
|
|
$request_token = $connection->getRequestToken();
|
|
$token = $request_token['oauth_token'];
|
|
/***
|
|
* make some nice form
|
|
*/
|
|
|
|
$sc .= '<div class="section-content-info-wrapper">';
|
|
$sc .= t('At this Hubzilla instance the Twitter plugin was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your <strong>public</strong> posts will be posted to Twitter.');
|
|
$sc .= '</div>';
|
|
$sc .= '<a href="'.$connection->getAuthorizeURL($token).'" target="_twitter"><img src="addon/twitter/lighter.png" class="form-group" alt="'.t('Log in with Twitter').'"></a>';
|
|
|
|
$sc .= replace_macros(get_markup_template('field_input.tpl'), array(
|
|
'$field' => array('twitter-pin', t('Copy the PIN from Twitter here'), '', '')
|
|
));
|
|
|
|
$sc .= '<input id="twitter-token" type="hidden" name="twitter-token" value="'.$token.'" />';
|
|
$sc .= '<input id="twitter-token2" type="hidden" name="twitter-token2" value="'.$request_token['oauth_token_secret'].'" />';
|
|
|
|
$sc .= '<div class=" settings-submit-wrapper">';
|
|
$sc .= '<button type="submit" name="twitter-submit" class="btn btn-primary" value="' . t('Submit') . '">' . t('Submit') . '</button>';
|
|
$sc .= '</div>';
|
|
|
|
} else {
|
|
/***
|
|
* we have an OAuth key / secret pair for the user
|
|
* so let's give a chance to disable the postings to Twitter
|
|
*/
|
|
require_once('library/twitteroauth.php');
|
|
$connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
|
|
$details = $connection->get('account/verify_credentials');
|
|
$twitpic = $details->profile_image_url;
|
|
if((strstr(z_root(),'https')) && (! strstr($twitpic,'https')))
|
|
$twitpic = str_replace('http:','https:',$twitpic);
|
|
|
|
$sc .= '<div id="twitter-info" ><img id="twitter-avatar" src="'.$twitpic.'" /><p id="twitter-info-block">'. t('Currently connected to: ') .'<a href="https://twitter.com/'.$details->screen_name.'" target="_twitter">'.$details->screen_name.'</a><br /><em>'.$details->description.'</em></p></div>';
|
|
$sc .= '<div class="clear"></div>';
|
|
//FIXME no hidewall in Red
|
|
if ($a->user['hidewall']) {
|
|
$sc .= '<div class="section-content-info-wrapper">';
|
|
$sc .= t('<strong>Note:</strong> Due your privacy settings (<em>Hide your profile details from unknown viewers?</em>) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.');
|
|
$sc .= '</div>';
|
|
}
|
|
|
|
$sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array(
|
|
'$field' => array('twitter-enable', t('Allow posting to Twitter'), $checked, t('If enabled your public postings can be posted to the associated Twitter account'), array(t('No'),t('Yes')))
|
|
));
|
|
|
|
$sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array(
|
|
'$field' => array('twitter-default', t('Send public postings to Twitter by default'), $defchecked, t('If enabled your public postings will be posted to the associated Twitter account by default'), array(t('No'),t('Yes')))
|
|
));
|
|
|
|
//FIXME: Doesn't seem to work. But maybe we don't want this at all.
|
|
//$sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array(
|
|
// '$field' => array('twitter-shortening', t('Shortening method that optimizes the tweet'), $shorteningchecked, '', array(t('No'),t('Yes')))
|
|
//));
|
|
|
|
$sc .= replace_macros(get_markup_template('field_checkbox.tpl'), array(
|
|
'$field' => array('twitter-disconnect', t('Clear OAuth configuration'), '', '', array(t('No'),t('Yes')))
|
|
));
|
|
|
|
$sc .= '<div class=" settings-submit-wrapper">';
|
|
$sc .= '<button type="submit" name="twitter-submit" class="btn btn-primary" value="' . t('Submit') . '">' . t('Submit') . '</button>';
|
|
$sc .= '</div>';
|
|
}
|
|
}
|
|
$s .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array(
|
|
'$addon' => array('', '<img src="addon/twitter/twitter.png" style="width:auto; height:1em; margin:-3px 5px 0px 0px;">' . t('Twitter Post Settings'), '', ''),
|
|
'$content' => $sc
|
|
));
|
|
|
|
}
|
|
|
|
|
|
function twitter_post_local(&$a,&$b) {
|
|
|
|
if($b['edit'])
|
|
return;
|
|
|
|
if((! local_channel()) || (local_channel() != $b['uid']))
|
|
return;
|
|
|
|
if($b['item_private'] || ($b['mid'] != $b['parent_mid']))
|
|
return;
|
|
|
|
|
|
$twitter_post = intval(get_pconfig(local_channel(),'twitter','post'));
|
|
$twitter_enable = (($twitter_post && x($_REQUEST,'twitter_enable')) ? intval($_REQUEST['twitter_enable']) : 0);
|
|
|
|
// if API is used, default to the chosen settings
|
|
if($_REQUEST['api_source'] && intval(get_pconfig(local_channel(),'twitter','post_by_default')))
|
|
$twitter_enable = 1;
|
|
|
|
if(! $twitter_enable)
|
|
return;
|
|
|
|
if(strlen($b['postopts']))
|
|
$b['postopts'] .= ',';
|
|
$b['postopts'] .= 'twitter';
|
|
|
|
}
|
|
|
|
if (! function_exists('short_link')) {
|
|
function short_link ($url) {
|
|
require_once('library/slinky.php');
|
|
$slinky = new Slinky( $url );
|
|
$yourls_url = get_config('yourls','url1');
|
|
if ($yourls_url) {
|
|
$yourls_username = get_config('yourls','username1');
|
|
$yourls_password = get_config('yourls', 'password1');
|
|
$yourls_ssl = get_config('yourls', 'ssl1');
|
|
$yourls = new Slinky_YourLS();
|
|
$yourls->set( 'username', $yourls_username );
|
|
$yourls->set( 'password', $yourls_password );
|
|
$yourls->set( 'ssl', $yourls_ssl );
|
|
$yourls->set( 'yourls-url', $yourls_url );
|
|
$slinky->set_cascade( array( $yourls, new Slinky_UR1ca(), new Slinky_Trim(), new Slinky_IsGd(), new Slinky_TinyURL() ) );
|
|
}
|
|
else {
|
|
// setup a cascade of shortening services
|
|
// try to get a short link from these services
|
|
// in the order ur1.ca, trim, id.gd, tinyurl
|
|
$slinky->set_cascade( array( new Slinky_UR1ca(), new Slinky_Trim(), new Slinky_IsGd(), new Slinky_TinyURL() ) );
|
|
}
|
|
return $slinky->short();
|
|
} };
|
|
|
|
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']);
|
|
$cleaned_body = $b['body'];
|
|
$image = '';
|
|
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",$cleaned_body,$matches))
|
|
$image = $matches[1];
|
|
|
|
$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
|
|
$image = htmlspecialchars_decode($image);
|
|
|
|
$body = $b["body"];
|
|
if ($b["title"] != "")
|
|
$body = $b["title"]."\n\n".$body;
|
|
|
|
if (strpos($body, "[bookmark") !== false) {
|
|
// splitting the text in two parts:
|
|
// before and after the bookmark
|
|
$pos = strpos($body, "[bookmark");
|
|
$body1 = substr($body, 0, $pos);
|
|
$body2 = substr($body, $pos);
|
|
|
|
// Removing all quotes after the bookmark
|
|
// they are mostly only the content after the bookmark.
|
|
$body2 = preg_replace("/\[quote\=([^\]]*)\](.*?)\[\/quote\]/ism",'',$body2);
|
|
$body2 = preg_replace("/\[quote\](.*?)\[\/quote\]/ism",'',$body2);
|
|
$body = $body1.$body2;
|
|
}
|
|
|
|
// Add some newlines so that the message could be cut better
|
|
$body = str_replace(array("[quote", "[bookmark", "[/bookmark]", "[/quote]"),
|
|
array("\n[quote", "\n[bookmark", "[/bookmark]\n", "[/quote]\n"), $body);
|
|
|
|
// remove the recycle signs and the names since they aren't helpful on twitter
|
|
// recycle 1
|
|
$recycle = html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8');
|
|
$body = preg_replace( '/'.$recycle.'\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', "\n", $body);
|
|
// recycle 2 (Test)
|
|
$recycle = html_entity_decode("◌ ", ENT_QUOTES, 'UTF-8');
|
|
$body = preg_replace( '/'.$recycle.'\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', "\n", $body);
|
|
|
|
// remove the share element
|
|
//$body = preg_replace("/\[share(.*?)\](.*?)\[\/share\]/ism","\n\n$2\n\n",$body);
|
|
|
|
// At first convert the text to html
|
|
$html = bbcode($body, false, false);
|
|
|
|
// Then convert it to plain text
|
|
$msg = trim(html2plain($html, 0, true));
|
|
$msg = html_entity_decode($msg,ENT_QUOTES,'UTF-8');
|
|
|
|
// Removing multiple newlines
|
|
while (strpos($msg, "\n\n\n") !== false)
|
|
$msg = str_replace("\n\n\n", "\n\n", $msg);
|
|
|
|
// Removing multiple spaces
|
|
while (strpos($msg, " ") !== false)
|
|
$msg = str_replace(" ", " ", $msg);
|
|
|
|
$origmsg = trim($msg);
|
|
|
|
// Removing URLs
|
|
$msg = preg_replace('/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/i', "", $msg);
|
|
|
|
$msg = trim($msg);
|
|
|
|
$link = '';
|
|
// look for bookmark-bbcode and handle it with priority
|
|
if(preg_match("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/is",$b['body'],$matches))
|
|
$link = $matches[1];
|
|
|
|
$multiplelinks = (strpos($b['body'], "[bookmark") != strrpos($b['body'], "[bookmark"));
|
|
|
|
// If there is no bookmark element then take the first link
|
|
// if ($link == '') {
|
|
// $links = collecturls($html);
|
|
|
|
// foreach($links AS $singlelink) {
|
|
// $img_str = fetch_url($singlelink);
|
|
|
|
// $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/") {
|
|
// $image = $singlelink;
|
|
// unset($links[$singlelink]);
|
|
// }
|
|
// }
|
|
|
|
// if (sizeof($links) > 0) {
|
|
// reset($links);
|
|
// $link = current($links);
|
|
// }
|
|
// $multiplelinks = (sizeof($links) > 1);
|
|
// }
|
|
|
|
$msglink = "";
|
|
if ($multiplelinks)
|
|
$msglink = $b["plink"];
|
|
else if ($link != "")
|
|
$msglink = $link;
|
|
else if ($multipleimages)
|
|
$msglink = $b["plink"];
|
|
else if ($image != "")
|
|
$msglink = $image;
|
|
|
|
if (($msglink == "") and strlen($msg) > $max_char)
|
|
$msglink = $b["plink"];
|
|
|
|
// If the message is short enough then don't modify it.
|
|
if ((strlen($origmsg) <= $max_char) AND ($msglink == ""))
|
|
return(array("msg"=>$origmsg, "image"=>""));
|
|
|
|
// If the message is short enough and contains a picture then post the picture as well
|
|
if ((strlen($origmsg) <= ($max_char - 23)) AND strpos($origmsg, $msglink))
|
|
return(array("msg"=>$origmsg, "image"=>$image));
|
|
|
|
// If the message is short enough and the link exists in the original message don't modify it as well
|
|
// -3 because of the bad shortener of twitter
|
|
if ((strlen($origmsg) <= ($max_char - 3)) AND strpos($origmsg, $msglink))
|
|
return(array("msg"=>$origmsg, "image"=>""));
|
|
|
|
// Preserve the unshortened link
|
|
$orig_link = $msglink;
|
|
|
|
// Just replace the message link with a 22 character long string
|
|
// Twitter calculates with this length
|
|
if (trim($msglink) <> '')
|
|
$msglink = "1234567890123456789012";
|
|
|
|
if (strlen(trim($msg." ".$msglink)) > ($max_char)) {
|
|
$msg = substr($msg, 0, ($max_char) - (strlen($msglink)));
|
|
$lastchar = substr($msg, -1);
|
|
$msg = substr($msg, 0, -1);
|
|
$pos = strrpos($msg, "\n");
|
|
if ($pos > 0)
|
|
$msg = substr($msg, 0, $pos);
|
|
else if ($lastchar != "\n")
|
|
$msg = substr($msg, 0, -3)."...";
|
|
|
|
// if the post contains a picture and a link then the system tries to cut the post earlier.
|
|
// So the link and the picture can be posted.
|
|
if (($image != "") AND ($orig_link != $image)) {
|
|
$msg2 = substr($msg, 0, ($max_char - 20) - (strlen($msglink)));
|
|
$lastchar = substr($msg2, -1);
|
|
$msg2 = substr($msg2, 0, -1);
|
|
$pos = strrpos($msg2, "\n");
|
|
if ($pos > 0)
|
|
$msg = substr($msg2, 0, $pos);
|
|
else if ($lastchar == "\n")
|
|
$msg = trim($msg2);
|
|
}
|
|
|
|
}
|
|
// Removing multiple spaces - again
|
|
while (strpos($msg, " ") !== false)
|
|
$msg = str_replace(" ", " ", $msg);
|
|
|
|
$msg = trim($msg);
|
|
|
|
// Removing multiple newlines
|
|
//while (strpos($msg, "\n\n") !== false)
|
|
// $msg = str_replace("\n\n", "\n", $msg);
|
|
|
|
// Looking if the link points to an image
|
|
$img_str = fetch_url($orig_link);
|
|
|
|
// $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 (($image == $orig_link) OR (substr($mime, 0, 6) == "image/"))
|
|
return(array("msg"=>$msg, "image"=>$orig_link));
|
|
else if (($image != $orig_link) AND ($image != "") AND (strlen($msg." ".$msglink) <= ($max_char - 23))) {
|
|
if ($shortlink)
|
|
$orig_link = short_link($orig_link);
|
|
|
|
return(array("msg"=>$msg." ".$orig_link, "image"=>$image));
|
|
} else {
|
|
if ($shortlink)
|
|
$orig_link = short_link($orig_link);
|
|
|
|
return(array("msg"=>$msg." ".$orig_link, "image"=>""));
|
|
}
|
|
}
|
|
|
|
function twitter_action($a, $uid, $pid, $action) {
|
|
|
|
$ckey = get_config('twitter', 'consumerkey');
|
|
$csecret = get_config('twitter', 'consumersecret');
|
|
$otoken = get_pconfig($uid, 'twitter', 'oauthtoken');
|
|
$osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
|
|
|
|
require_once("addon/twitter/codebird.php");
|
|
|
|
$cb = \Codebird\Codebird::getInstance();
|
|
$cb->setConsumerKey($ckey, $csecret);
|
|
$cb->setToken($otoken, $osecret);
|
|
|
|
$post = array('id' => $pid);
|
|
|
|
logger("twitter_action '".$action."' ID: ".$pid." data: " . print_r($post, true), LOGGER_DATA);
|
|
|
|
switch ($action) {
|
|
case "delete":
|
|
$result = $cb->statuses_destroy($post);
|
|
break;
|
|
case "like":
|
|
$result = $cb->favorites_create($post);
|
|
break;
|
|
case "unlike":
|
|
$result = $cb->favorites_destroy($post);
|
|
break;
|
|
}
|
|
logger("twitter_action '".$action."' send, result: " . print_r($result, true), LOGGER_DEBUG);
|
|
}
|
|
|
|
function twitter_post_hook(&$a,&$b) {
|
|
|
|
/**
|
|
* Post to Twitter
|
|
*/
|
|
|
|
if((! is_item_normal($b)) || $b['item_private'] || ($b['created'] !== $b['edited']))
|
|
return;
|
|
|
|
if(! perm_is_allowed($b['uid'],'','view_stream'))
|
|
return;
|
|
|
|
if(! strstr($b['postopts'],'twitter'))
|
|
return;
|
|
|
|
if($b['parent'] != $b['id'])
|
|
return;
|
|
|
|
|
|
logger('twitter post invoked');
|
|
|
|
|
|
load_pconfig($b['uid'], 'twitter');
|
|
|
|
$ckey = get_config('twitter', 'consumerkey');
|
|
$csecret = get_config('twitter', 'consumersecret');
|
|
$otoken = get_pconfig($b['uid'], 'twitter', 'oauthtoken');
|
|
$osecret = get_pconfig($b['uid'], 'twitter', 'oauthsecret');
|
|
$intelligent_shortening = get_pconfig($b['uid'], 'twitter', 'intelligent_shortening');
|
|
|
|
// Global setting overrides this
|
|
if (get_config('twitter','intelligent_shortening'))
|
|
$intelligent_shortening = get_config('twitter','intelligent_shortening');
|
|
|
|
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) {
|
|
$max_char = 130; // max. length for a tweet
|
|
// we will only work with up to two times the length of the dent
|
|
// we can later send to Twitter. This way we can "gain" some
|
|
// information during shortening of potential links but do not
|
|
// shorten all the links in a 200000 character long essay.
|
|
if (! $b['title']=='') {
|
|
$tmp = $b['title'] . ' : '. $b['body'];
|
|
// $tmp = substr($tmp, 0, 4*$max_char);
|
|
} else {
|
|
$tmp = $b['body']; // substr($b['body'], 0, 3*$max_char);
|
|
}
|
|
// if [url=bla][img]blub.png[/img][/url] get blub.png
|
|
$tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[img\](\\w+.*?)\\[\\/img\]\\[\\/url\]/i', '$2', $tmp);
|
|
$tmp = preg_replace( '/\[zrl\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[zmg\](\\w+.*?)\\[\\/zmg\]\\[\\/zrl\]/i', '$2', $tmp);
|
|
// preserve links to images, videos and audios
|
|
$tmp = preg_replace( '/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism', '$3', $tmp);
|
|
$tmp = preg_replace( '/\[\\/?img(\\s+.*?\]|\])/i', '', $tmp);
|
|
$tmp = preg_replace( '/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism', '$3', $tmp);
|
|
$tmp = preg_replace( '/\[\\/?zmg(\\s+.*?\]|\])/i', '', $tmp);
|
|
$tmp = preg_replace( '/\[\\/?video(\\s+.*?\]|\])/i', '', $tmp);
|
|
$tmp = preg_replace( '/\[\\/?youtube(\\s+.*?\]|\])/i', '', $tmp);
|
|
$tmp = preg_replace( '/\[\\/?vimeo(\\s+.*?\]|\])/i', '', $tmp);
|
|
$tmp = preg_replace( '/\[\\/?audio(\\s+.*?\]|\])/i', '', $tmp);
|
|
$linksenabled = get_pconfig($b['uid'],'twitter','post_taglinks');
|
|
// if a #tag is linked, don't send the [url] over to SN
|
|
// that is, don't send if the option is not set in the
|
|
// connector settings
|
|
if ($linksenabled=='0') {
|
|
// #-tags
|
|
$tmp = preg_replace( '/#\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '#$2', $tmp);
|
|
// @-mentions
|
|
$tmp = preg_replace( '/@\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '@$2', $tmp);
|
|
$tmp = preg_replace( '/#\[zrl\=(\w+.*?)\](\w+.*?)\[\/zrl\]/i', '#$2', $tmp);
|
|
// @-mentions
|
|
$tmp = preg_replace( '/@\[zrl\=(\w+.*?)\](\w+.*?)\[\/zrl\]/i', '@$2', $tmp);
|
|
// recycle 1
|
|
}
|
|
$tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\](\w+.*?)\[\/url\]/i', '$2 $1', $tmp);
|
|
|
|
// find all http or https links in the body of the entry and
|
|
// apply the shortener if the link is longer then 20 characters
|
|
if (( strlen($tmp)>$max_char ) && ( $max_char > 0 )) {
|
|
preg_match_all ( '/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/i', $tmp, $allurls );
|
|
foreach ($allurls as $url) {
|
|
foreach ($url as $u) {
|
|
if (strlen($u)>20) {
|
|
$sl = short_link($u);
|
|
$tmp = str_replace( $u, $sl, $tmp );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// ok, all the links we want to send out are save, now strip
|
|
// away the remaining bbcode
|
|
//$msg = strip_tags(bbcode($tmp, false, false));
|
|
$msg = bbcode($tmp, false, false);
|
|
$msg = str_replace(array('<br>','<br />'),"\n",$msg);
|
|
$msg = strip_tags($msg);
|
|
|
|
// quotes not working - let's try this
|
|
$msg = html_entity_decode($msg);
|
|
if (( strlen($msg) > $max_char) && $max_char > 0) {
|
|
$shortlink = short_link( $b['plink'] );
|
|
// the new message will be shortened such that "... $shortlink"
|
|
// will fit into the character limit
|
|
$msg = nl2br(substr($msg, 0, $max_char-strlen($shortlink)-4));
|
|
$msg = str_replace(array('<br>','<br />'),' ',$msg);
|
|
$e = explode(' ', $msg);
|
|
// remove the last word from the cut down message to
|
|
// avoid sending cut words to the MicroBlog
|
|
array_pop($e);
|
|
$msg = implode(' ', $e);
|
|
$msg .= '... ' . $shortlink;
|
|
}
|
|
|
|
$msg = trim($msg);
|
|
$image = "";
|
|
} else {
|
|
$msgarr = twitter_shortenmsg($b);
|
|
$msg = $msgarr["msg"];
|
|
$image = $msgarr["image"];
|
|
}
|
|
|
|
// and now tweet it :-)
|
|
// if(strlen($msg) and ($image != "")) {
|
|
// $img_str = z_fetch_url($image);
|
|
|
|
// $tempfile = tempnam(get_config("system","temppath"), "cache");
|
|
// file_put_contents($tempfile, $img_str);
|
|
|
|
// Twitter had changed something so that the old library doesn't work anymore
|
|
// so we are using a new library for twitter
|
|
// To-Do:
|
|
// Switching completely to this library with all functions
|
|
require_once("addon/twitter/codebird.php");
|
|
|
|
// $cb = \Codebird\Codebird::getInstance();
|
|
// $cb->setConsumerKey($ckey, $csecret);
|
|
// $cb->setToken($otoken, $osecret);
|
|
|
|
// $post = array('status' => $msg, 'media[]' => $tempfile);
|
|
|
|
// if ($iscomment)
|
|
// $post["in_reply_to_status_id"] = substr($orig_post["uri"], 9);
|
|
|
|
// $result = $cb->statuses_updateWithMedia($post);
|
|
// unlink($tempfile);
|
|
|
|
// 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) . '"');
|
|
|
|
// Workaround: Remove the picture link so that the post can be reposted without it
|
|
// $msg .= " ".$image;
|
|
// $image = "";
|
|
// } elseif ($iscomment) {
|
|
// logger('twitter_post: Update extid '.$result->id_str." for post id ".$b['id']);
|
|
// q("UPDATE `item` SET `extid` = '%s', `body` = '%s' WHERE `id` = %d",
|
|
// dbesc("twitter::".$result->id_str),
|
|
// dbesc($result->text),
|
|
// intval($b['id'])
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
if(strlen($msg) and ($image == "")) {
|
|
$url = 'statuses/update';
|
|
$post = array('status' => $msg);
|
|
|
|
if ($iscomment)
|
|
$post["in_reply_to_status_id"] = substr($orig_post["uri"], 9);
|
|
|
|
$result = $tweet->post($url, $post);
|
|
logger('twitter_post send, result: ' . print_r($result, true), LOGGER_DEBUG);
|
|
if ($result->errors) {
|
|
logger('Send to Twitter failed: "' . print_r($result->errors, true) . '"');
|
|
|
|
}
|
|
// elseif ($iscomment) {
|
|
// logger('twitter_post: Update extid '.$result->id_str." for post id ".$b['id']);
|
|
// q("UPDATE `item` SET `extid` = '%s' WHERE `id` = %d",
|
|
// dbesc("twitter::".$result->id_str),
|
|
// intval($b['id'])
|
|
// );
|
|
//q("UPDATE `item` SET `extid` = '%s', `body` = '%s' WHERE `id` = %d",
|
|
// dbesc("twitter::".$result->id_str),
|
|
// dbesc($result->text),
|
|
// intval($b['id'])
|
|
//);
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
function twitter_plugin_admin_post(&$a){
|
|
$consumerkey = ((x($_POST,'consumerkey')) ? notags(trim($_POST['consumerkey'])) : '');
|
|
$consumersecret = ((x($_POST,'consumersecret')) ? notags(trim($_POST['consumersecret'])): '');
|
|
set_config('twitter','consumerkey',$consumerkey);
|
|
set_config('twitter','consumersecret',$consumersecret);
|
|
info( t('Settings updated.'). EOL );
|
|
}
|
|
function twitter_plugin_admin(&$a, &$o){
|
|
logger('Twitter admin');
|
|
$t = get_markup_template( "admin.tpl", "addon/twitter/" );
|
|
|
|
$o = replace_macros($t, array(
|
|
'$submit' => t('Submit 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' ), '')
|
|
));
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
}
|
|
|