]> git.mxchange.org Git - friendica-addons.git/blob - twitter/twitter.php
app.net, facebook, twitter and statusnet: Preview now shows the post like it will...
[friendica-addons.git] / twitter / twitter.php
1 <?php
2 /**
3  * Name: Twitter Connector
4  * Description: Relay public postings to a connected Twitter account
5  * Version: 1.0.4
6  * Author: Tobias Diekershoff <https://f.diekershoff.de/profile/tobias>
7  * Author: Michael Vogel <https://pirati.ca/profile/heluecht>
8  *
9  * Copyright (c) 2011-2013 Tobias Diekershoff, Michael Vogel
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *    * Redistributions of source code must retain the above copyright notice,
15  *     this list of conditions and the following disclaimer.
16  *    * Redistributions in binary form must reproduce the above
17  *    * copyright notice, this list of conditions and the following disclaimer in
18  *      the documentation and/or other materials provided with the distribution.
19  *    * Neither the name of the <organization> nor the names of its contributors
20  *      may be used to endorse or promote products derived from this software
21  *      without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  */
35  
36 /*   Twitter Plugin for Friendica
37  *
38  *   Author: Tobias Diekershoff
39  *           tobias.diekershoff@gmx.net
40  *
41  *   License:3-clause BSD license
42  *
43  *   Configuration:
44  *     To use this plugin you need a OAuth Consumer key pair (key & secret)
45  *     you can get it from Twitter at https://twitter.com/apps
46  *
47  *     Register your Friendica site as "Client" application with "Read & Write" access
48  *     we do not need "Twitter as login". When you've registered the app you get the
49  *     OAuth Consumer key and secret pair for your application/site.
50  *
51  *     Add this key pair to your global .htconfig.php or use the admin panel.
52  *
53  *     $a->config['twitter']['consumerkey'] = 'your consumer_key here';
54  *     $a->config['twitter']['consumersecret'] = 'your consumer_secret here';
55  *
56  *     To activate the plugin itself add it to the $a->config['system']['addon']
57  *     setting. After this, your user can configure their Twitter account settings
58  *     from "Settings -> Plugin Settings".
59  *
60  *     Requirements: PHP5, curl [Slinky library]
61  */
62
63 define('TWITTER_DEFAULT_POLL_INTERVAL', 5); // given in minutes
64
65 function twitter_install() {
66         //  we need some hooks, for the configuration and for sending tweets
67         register_hook('connector_settings', 'addon/twitter/twitter.php', 'twitter_settings');
68         register_hook('connector_settings_post', 'addon/twitter/twitter.php', 'twitter_settings_post');
69         register_hook('post_local', 'addon/twitter/twitter.php', 'twitter_post_local');
70         register_hook('notifier_normal', 'addon/twitter/twitter.php', 'twitter_post_hook');
71         register_hook('jot_networks', 'addon/twitter/twitter.php', 'twitter_jot_nets');
72         register_hook('cron', 'addon/twitter/twitter.php', 'twitter_cron');
73         register_hook('queue_predeliver', 'addon/twitter/twitter.php', 'twitter_queue_hook');
74         register_hook('follow', 'addon/twitter/twitter.php', 'twitter_follow');
75         register_hook('expire', 'addon/twitter/twitter.php', 'twitter_expire');
76         register_hook('prepare_body', 'addon/twitter/twitter.php', 'twitter_prepare_body');
77         logger("installed twitter");
78 }
79
80
81 function twitter_uninstall() {
82         unregister_hook('connector_settings', 'addon/twitter/twitter.php', 'twitter_settings');
83         unregister_hook('connector_settings_post', 'addon/twitter/twitter.php', 'twitter_settings_post');
84         unregister_hook('post_local', 'addon/twitter/twitter.php', 'twitter_post_local');
85         unregister_hook('notifier_normal', 'addon/twitter/twitter.php', 'twitter_post_hook');
86         unregister_hook('jot_networks', 'addon/twitter/twitter.php', 'twitter_jot_nets');
87         unregister_hook('cron', 'addon/twitter/twitter.php', 'twitter_cron');
88         unregister_hook('queue_predeliver', 'addon/twitter/twitter.php', 'twitter_queue_hook');
89         unregister_hook('follow', 'addon/twitter/twitter.php', 'twitter_follow');
90         unregister_hook('expire', 'addon/twitter/twitter.php', 'twitter_expire');
91         unregister_hook('prepare_body', 'addon/twitter/twitter.php', 'twitter_prepare_body');
92
93         // old setting - remove only
94         unregister_hook('post_local_end', 'addon/twitter/twitter.php', 'twitter_post_hook');
95         unregister_hook('plugin_settings', 'addon/twitter/twitter.php', 'twitter_settings');
96         unregister_hook('plugin_settings_post', 'addon/twitter/twitter.php', 'twitter_settings_post');
97
98 }
99
100 function twitter_follow($a, &$contact) {
101
102         logger("twitter_follow: Check if contact is twitter contact. ".$contact["url"], LOGGER_DEBUG);
103
104         if (!strstr($contact["url"], "://twitter.com") AND !strstr($contact["url"], "@twitter.com"))
105                 return;
106
107         // contact seems to be a twitter contact, so continue
108         $nickname = preg_replace("=https?://twitter.com/(.*)=ism", "$1", $contact["url"]);
109         $nickname = str_replace("@twitter.com", "", $nickname);
110
111         $uid = $a->user["uid"];
112
113         $ckey    = get_config('twitter', 'consumerkey');
114         $csecret = get_config('twitter', 'consumersecret');
115         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
116         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
117
118         require_once("addon/twitter/codebird.php");
119
120         $cb = \Codebird\Codebird::getInstance();
121         $cb->setConsumerKey($ckey, $csecret);
122         $cb->setToken($otoken, $osecret);
123
124         $parameters = array();
125         $parameters["screen_name"] = $nickname;
126
127         $user = $cb->friendships_create($parameters);
128
129         twitter_fetchuser($a, $uid, $nickname);
130
131         $r = q("SELECT name,nick,url,addr,batch,notify,poll,request,confirm,poco,photo,priority,network,alias,pubkey
132                 FROM `contact` WHERE `uid` = %d AND `nick` = '%s'",
133                                 intval($uid),
134                                 dbesc($nickname));
135         if (count($r))
136                 $contact["contact"] = $r[0];
137 }
138
139 function twitter_jot_nets(&$a,&$b) {
140         if(! local_user())
141                 return;
142
143         $tw_post = get_pconfig(local_user(),'twitter','post');
144         if(intval($tw_post) == 1) {
145                 $tw_defpost = get_pconfig(local_user(),'twitter','post_by_default');
146                 $selected = ((intval($tw_defpost) == 1) ? ' checked="checked" ' : '');
147                 $b .= '<div class="profile-jot-net"><input type="checkbox" name="twitter_enable"' . $selected . ' value="1" /> ' 
148                         . t('Post to Twitter') . '</div>';
149         }
150 }
151
152 function twitter_settings_post ($a,$post) {
153         if(! local_user())
154                 return;
155         // don't check twitter settings if twitter submit button is not clicked
156         if (!x($_POST,'twitter-submit'))
157                 return;
158
159         if (isset($_POST['twitter-disconnect'])) {
160                 /***
161                  * if the twitter-disconnect checkbox is set, clear the OAuth key/secret pair
162                  * from the user configuration
163                  */
164                 del_pconfig(local_user(), 'twitter', 'consumerkey');
165                 del_pconfig(local_user(), 'twitter', 'consumersecret');
166                 del_pconfig(local_user(), 'twitter', 'oauthtoken');
167                 del_pconfig(local_user(), 'twitter', 'oauthsecret');
168                 del_pconfig(local_user(), 'twitter', 'post');
169                 del_pconfig(local_user(), 'twitter', 'post_by_default');
170                 del_pconfig(local_user(), 'twitter', 'lastid');
171                 del_pconfig(local_user(), 'twitter', 'mirror_posts');
172                 del_pconfig(local_user(), 'twitter', 'import');
173                 del_pconfig(local_user(), 'twitter', 'create_user');
174                 del_pconfig(local_user(), 'twitter', 'own_id');
175         } else {
176         if (isset($_POST['twitter-pin'])) {
177                 //  if the user supplied us with a PIN from Twitter, let the magic of OAuth happen
178                 logger('got a Twitter PIN');
179                 require_once('library/twitteroauth.php');
180                 $ckey    = get_config('twitter', 'consumerkey');
181                 $csecret = get_config('twitter', 'consumersecret');
182                 //  the token and secret for which the PIN was generated were hidden in the settings
183                 //  form as token and token2, we need a new connection to Twitter using these token
184                 //  and secret to request a Access Token with the PIN
185                 $connection = new TwitterOAuth($ckey, $csecret, $_POST['twitter-token'], $_POST['twitter-token2']);
186                 $token   = $connection->getAccessToken( $_POST['twitter-pin'] );
187                 //  ok, now that we have the Access Token, save them in the user config
188                 set_pconfig(local_user(),'twitter', 'oauthtoken',  $token['oauth_token']);
189                 set_pconfig(local_user(),'twitter', 'oauthsecret', $token['oauth_token_secret']);
190                 set_pconfig(local_user(),'twitter', 'post', 1);
191                 //  reload the Addon Settings page, if we don't do it see Bug #42
192                 goaway($a->get_baseurl().'/settings/connectors');
193         } else {
194                 //  if no PIN is supplied in the POST variables, the user has changed the setting
195                 //  to post a tweet for every new __public__ posting to the wall
196                 set_pconfig(local_user(),'twitter','post',intval($_POST['twitter-enable']));
197                 set_pconfig(local_user(),'twitter','post_by_default',intval($_POST['twitter-default']));
198                 set_pconfig(local_user(), 'twitter', 'mirror_posts', intval($_POST['twitter-mirror']));
199                 set_pconfig(local_user(), 'twitter', 'import', intval($_POST['twitter-import']));
200                 set_pconfig(local_user(), 'twitter', 'create_user', intval($_POST['twitter-create_user']));
201
202                 if (!intval($_POST['twitter-mirror']))
203                         del_pconfig(local_user(),'twitter','lastid');
204
205                 info(t('Twitter settings updated.') . EOL);
206         }}
207 }
208 function twitter_settings(&$a,&$s) {
209         if(! local_user())
210                 return;
211         $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/twitter/twitter.css' . '" media="all" />' . "\r\n";
212         /***
213          * 1) Check that we have global consumer key & secret
214          * 2) If no OAuthtoken & stuff is present, generate button to get some
215          * 3) Checkbox for "Send public notices (140 chars only)
216          */
217         $ckey    = get_config('twitter', 'consumerkey' );
218         $csecret = get_config('twitter', 'consumersecret' );
219         $otoken  = get_pconfig(local_user(), 'twitter', 'oauthtoken'  );
220         $osecret = get_pconfig(local_user(), 'twitter', 'oauthsecret' );
221         $enabled = get_pconfig(local_user(), 'twitter', 'post');
222         $checked = (($enabled) ? ' checked="checked" ' : '');
223         $defenabled = get_pconfig(local_user(),'twitter','post_by_default');
224         $defchecked = (($defenabled) ? ' checked="checked" ' : '');
225         $mirrorenabled = get_pconfig(local_user(),'twitter','mirror_posts');
226         $mirrorchecked = (($mirrorenabled) ? ' checked="checked" ' : '');
227         $importenabled = get_pconfig(local_user(),'twitter','import');
228         $importchecked = (($importenabled) ? ' checked="checked" ' : '');
229         $create_userenabled = get_pconfig(local_user(),'twitter','create_user');
230         $create_userchecked = (($create_userenabled) ? ' checked="checked" ' : '');
231
232         $css = (($enabled) ? '' : '-disabled');
233
234         $s .= '<span id="settings_twitter_inflated" class="settings-block fakelink" style="display: block;" onclick="openClose(\'settings_twitter_expanded\'); openClose(\'settings_twitter_inflated\');">';
235         $s .= '<img class="connector'.$css.'" src="images/twitter.png" /><h3 class="connector">'. t('Twitter Import/Export/Mirror').'</h3>';
236         $s .= '</span>';
237         $s .= '<div id="settings_twitter_expanded" class="settings-block" style="display: none;">';
238         $s .= '<span class="fakelink" onclick="openClose(\'settings_twitter_expanded\'); openClose(\'settings_twitter_inflated\');">';
239         $s .= '<img class="connector'.$css.'" src="images/twitter.png" /><h3 class="connector">'. t('Twitter Import/Export/Mirror').'</h3>';
240         $s .= '</span>';
241
242         if ( (!$ckey) && (!$csecret) ) {
243                 /***
244                  * no global consumer keys
245                  * display warning and skip personal config
246                  */
247                 $s .= '<p>'. t('No consumer key pair for Twitter found. Please contact your site administrator.') .'</p>';
248         } else {
249                 /***
250                  * ok we have a consumer key pair now look into the OAuth stuff
251                  */
252                 if ( (!$otoken) && (!$osecret) ) {
253                         /***
254                          * the user has not yet connected the account to twitter...
255                          * get a temporary OAuth key/secret pair and display a button with
256                          * which the user can request a PIN to connect the account to a
257                          * account at Twitter.
258                          */
259                         require_once('library/twitteroauth.php');
260                         $connection = new TwitterOAuth($ckey, $csecret);
261                         $request_token = $connection->getRequestToken();
262                         $token = $request_token['oauth_token'];
263                         /***
264                          *  make some nice form
265                          */
266                         $s .= '<p>'. t('At this Friendica 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.') .'</p>';
267                         $s .= '<a href="'.$connection->getAuthorizeURL($token).'" target="_twitter"><img src="addon/twitter/lighter.png" alt="'.t('Log in with Twitter').'"></a>';
268                         $s .= '<div id="twitter-pin-wrapper">';
269                         $s .= '<label id="twitter-pin-label" for="twitter-pin">'. t('Copy the PIN from Twitter here') .'</label>';
270                         $s .= '<input id="twitter-pin" type="text" name="twitter-pin" />';
271                         $s .= '<input id="twitter-token" type="hidden" name="twitter-token" value="'.$token.'" />';
272                         $s .= '<input id="twitter-token2" type="hidden" name="twitter-token2" value="'.$request_token['oauth_token_secret'].'" />';
273             $s .= '</div><div class="clear"></div>';
274             $s .= '<div class="settings-submit-wrapper" ><input type="submit" name="twitter-submit" class="settings-submit" value="' . t('Save Settings') . '" /></div>';
275                 } else {
276                         /***
277                          *  we have an OAuth key / secret pair for the user
278                          *  so let's give a chance to disable the postings to Twitter
279                          */
280                         require_once('library/twitteroauth.php');
281                         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
282                         $details = $connection->get('account/verify_credentials');
283                         $s .= '<div id="twitter-info" ><img id="twitter-avatar" src="'.$details->profile_image_url.'" /><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>';
284                         $s .= '<p>'. t('If enabled all your <strong>public</strong> postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.') .'</p>';
285                         if ($a->user['hidewall']) {
286                             $s .= '<p>'. 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.') .'</p>';
287                         }
288                         $s .= '<div id="twitter-enable-wrapper">';
289                         $s .= '<label id="twitter-enable-label" for="twitter-checkbox">'. t('Allow posting to Twitter'). '</label>';
290                         $s .= '<input id="twitter-checkbox" type="checkbox" name="twitter-enable" value="1" ' . $checked . '/>';
291                         $s .= '<div class="clear"></div>';
292                         $s .= '<label id="twitter-default-label" for="twitter-default">'. t('Send public postings to Twitter by default') .'</label>';
293                         $s .= '<input id="twitter-default" type="checkbox" name="twitter-default" value="1" ' . $defchecked . '/>';
294                         $s .= '<div class="clear"></div>';
295
296                         $s .= '<label id="twitter-mirror-label" for="twitter-mirror">'.t('Mirror all posts from twitter that are no replies').'</label>';
297                         $s .= '<input id="twitter-mirror" type="checkbox" name="twitter-mirror" value="1" '. $mirrorchecked . '/>';
298                         $s .= '<div class="clear"></div>';
299                         $s .= '</div>';
300
301                         $s .= '<label id="twitter-import-label" for="twitter-import">'.t('Import the remote timeline').'</label>';
302                         $s .= '<input id="twitter-import" type="checkbox" name="twitter-import" value="1" '. $importchecked . '/>';
303                         $s .= '<div class="clear"></div>';
304
305                         $s .= '<label id="twitter-create_user-label" for="twitter-create_user">'.t('Automatically create contacts').'</label>';
306                         $s .= '<input id="twitter-create_user" type="checkbox" name="twitter-create_user" value="1" '. $create_userchecked . '/>';
307                         $s .= '<div class="clear"></div>';
308
309                         $s .= '<div id="twitter-disconnect-wrapper">';
310                         $s .= '<label id="twitter-disconnect-label" for="twitter-disconnect">'. t('Clear OAuth configuration') .'</label>';
311                         $s .= '<input id="twitter-disconnect" type="checkbox" name="twitter-disconnect" value="1" />';
312                         $s .= '</div><div class="clear"></div>';
313                         $s .= '<div class="settings-submit-wrapper" ><input type="submit" name="twitter-submit" class="settings-submit" value="' . t('Save Settings') . '" /></div>'; 
314                 }
315         }
316         $s .= '</div><div class="clear"></div>';
317 }
318
319
320 function twitter_post_local(&$a,&$b) {
321
322         if($b['edit'])
323                 return;
324
325         if((local_user()) && (local_user() == $b['uid']) && (! $b['private']) && (! $b['parent']) ) {
326
327                 $twitter_post = intval(get_pconfig(local_user(),'twitter','post'));
328                 $twitter_enable = (($twitter_post && x($_REQUEST,'twitter_enable')) ? intval($_REQUEST['twitter_enable']) : 0);
329
330                 // if API is used, default to the chosen settings
331                 if($_REQUEST['api_source'] && intval(get_pconfig(local_user(),'twitter','post_by_default')))
332                         $twitter_enable = 1;
333
334         if(! $twitter_enable)
335                 return;
336
337         if(strlen($b['postopts']))
338                 $b['postopts'] .= ',';
339                 $b['postopts'] .= 'twitter';
340         }
341 }
342
343 function twitter_action($a, $uid, $pid, $action) {
344
345         $ckey    = get_config('twitter', 'consumerkey');
346         $csecret = get_config('twitter', 'consumersecret');
347         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
348         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
349
350         require_once("addon/twitter/codebird.php");
351
352         $cb = \Codebird\Codebird::getInstance();
353         $cb->setConsumerKey($ckey, $csecret);
354         $cb->setToken($otoken, $osecret);
355
356         $post = array('id' => $pid);
357
358         logger("twitter_action '".$action."' ID: ".$pid." data: " . print_r($post, true), LOGGER_DATA);
359
360         switch ($action) {
361                 case "delete":
362                         $result = $cb->statuses_destroy($post);
363                         break;
364                 case "like":
365                         $result = $cb->favorites_create($post);
366                         break;
367                 case "unlike":
368                         $result = $cb->favorites_destroy($post);
369                         break;
370         }
371         logger("twitter_action '".$action."' send, result: " . print_r($result, true), LOGGER_DEBUG);
372 }
373
374 function twitter_post_hook(&$a,&$b) {
375
376         /**
377          * Post to Twitter
378          */
379
380         require_once("include/network.php");
381
382         if (!get_pconfig($b["uid"],'twitter','import')) {
383                 if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited']))
384                         return;
385         }
386
387         if($b['parent'] != $b['id']) {
388                 logger("twitter_post_hook: parameter ".print_r($b, true), LOGGER_DATA);
389
390                 // Looking if its a reply to a twitter post
391                 if ((substr($b["parent-uri"], 0, 9) != "twitter::") AND (substr($b["extid"], 0, 9) != "twitter::") AND (substr($b["thr-parent"], 0, 9) != "twitter::")) {
392                         logger("twitter_post_hook: no twitter post ".$b["parent"]);
393                         return;
394                 }
395
396                 $r = q("SELECT * FROM item WHERE item.uri = '%s' AND item.uid = %d LIMIT 1",
397                         dbesc($b["thr-parent"]),
398                         intval($b["uid"]));
399
400                 if(!count($r)) {
401                         logger("twitter_post_hook: no parent found ".$b["thr-parent"]);
402                         return;
403                 } else {
404                         $iscomment = true;
405                         $orig_post = $r[0];
406                 }
407
408
409                 $nicknameplain = preg_replace("=https?://twitter.com/(.*)=ism", "$1", $orig_post["author-link"]);
410                 $nickname = "@[url=".$orig_post["author-link"]."]".$nicknameplain."[/url]";
411                 $nicknameplain = "@".$nicknameplain;
412
413                 logger("twitter_post_hook: comparing ".$nickname." and ".$nicknameplain." with ".$b["body"], LOGGER_DEBUG);
414                 if ((strpos($b["body"], $nickname) === false) AND (strpos($b["body"], $nicknameplain) === false))
415                         $b["body"] = $nickname." ".$b["body"];
416
417                 logger("twitter_post_hook: parent found ".print_r($orig_post, true), LOGGER_DATA);
418         } else {
419                 $iscomment = false;
420
421                 if($b['private'] OR !strstr($b['postopts'],'twitter'))
422                         return;
423         }
424
425         if (($b['verb'] == ACTIVITY_POST) AND $b['deleted'])
426                 twitter_action($a, $b["uid"], substr($orig_post["uri"], 9), "delete");
427
428         if($b['verb'] == ACTIVITY_LIKE) {
429                 logger("twitter_post_hook: parameter 2 ".substr($b["thr-parent"], 9), LOGGER_DEBUG);
430                 if ($b['deleted'])
431                         twitter_action($a, $b["uid"], substr($b["thr-parent"], 9), "unlike");
432                 else
433                         twitter_action($a, $b["uid"], substr($b["thr-parent"], 9), "like");
434                 return;
435         }
436
437         if($b['deleted'] || ($b['created'] !== $b['edited']))
438                 return;
439
440         // if post comes from twitter don't send it back
441         if($b['app'] == "Twitter")
442                 return;
443
444         logger('twitter post invoked');
445
446
447         load_pconfig($b['uid'], 'twitter');
448
449         $ckey    = get_config('twitter', 'consumerkey');
450         $csecret = get_config('twitter', 'consumersecret');
451         $otoken  = get_pconfig($b['uid'], 'twitter', 'oauthtoken');
452         $osecret = get_pconfig($b['uid'], 'twitter', 'oauthsecret');
453
454         if($ckey && $csecret && $otoken && $osecret) {
455                 logger('twitter: we have customer key and oauth stuff, going to send.', LOGGER_DEBUG);
456
457                 // If it's a repeated message from twitter then do a native retweet and exit
458                 if (twitter_is_retweet($a, $b['uid'], $b['body']))
459                         return;
460
461                 require_once('library/twitteroauth.php');
462                 require_once('include/bbcode.php');
463                 $tweet = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
464
465                 $max_char = 140;
466                 require_once("include/plaintext.php");
467                 $msgarr = plaintext($a, $b, $max_char, true);
468                 $msg = $msgarr["text"];
469
470                 if (($msg == "") AND isset($msgarr["title"]))
471                         $msg = shortenmsg($msgarr["title"], $max_char - 50);
472
473                 $image = "";
474
475                 if (isset($msgarr["url"]))
476                         $msg .= "\n".$msgarr["url"];
477                 elseif (isset($msgarr["image"]) AND ($msgarr["type"] != "video"))
478                         $image = $msgarr["image"];
479
480                 // and now tweet it :-)
481                 if(strlen($msg) and ($image != "")) {
482                         $img_str = fetch_url($image);
483
484                         $tempfile = tempnam(get_temppath(), "cache");
485                         file_put_contents($tempfile, $img_str);
486
487                         // Twitter had changed something so that the old library doesn't work anymore
488                         // so we are using a new library for twitter
489                         // To-Do:
490                         // Switching completely to this library with all functions
491                         require_once("addon/twitter/codebird.php");
492
493                         $cb = \Codebird\Codebird::getInstance();
494                         $cb->setConsumerKey($ckey, $csecret);
495                         $cb->setToken($otoken, $osecret);
496
497                         $post = array('status' => $msg, 'media[]' => $tempfile);
498
499                         if ($iscomment)
500                                 $post["in_reply_to_status_id"] = substr($orig_post["uri"], 9);
501
502                         $result = $cb->statuses_updateWithMedia($post);
503                         unlink($tempfile);
504
505                         logger('twitter_post_with_media send, result: ' . print_r($result, true), LOGGER_DEBUG);
506                         if ($result->errors OR $result->error) {
507                                 logger('Send to Twitter failed: "' . print_r($result->errors, true) . '"');
508
509                                 // Workaround: Remove the picture link so that the post can be reposted without it
510                                 $msg .= " ".$image;
511                                 $image = "";
512                         } elseif ($iscomment) {
513                                 logger('twitter_post: Update extid '.$result->id_str." for post id ".$b['id']);
514                                 q("UPDATE `item` SET `extid` = '%s', `body` = '%s' WHERE `id` = %d",
515                                         dbesc("twitter::".$result->id_str),
516                                         dbesc($result->text),
517                                         intval($b['id'])
518                                 );
519                         }
520                 }
521
522                 if(strlen($msg) and ($image == "")) {
523                         $url = 'statuses/update';
524                         $post = array('status' => $msg);
525
526                         if ($iscomment)
527                                 $post["in_reply_to_status_id"] = substr($orig_post["uri"], 9);
528
529                         $result = $tweet->post($url, $post);
530                         logger('twitter_post send, result: ' . print_r($result, true), LOGGER_DEBUG);
531                         if ($result->errors) {
532                                 logger('Send to Twitter failed: "' . print_r($result->errors, true) . '"');
533
534                                 $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($b['uid']));
535                                 if (count($r))
536                                         $a->contact = $r[0]["id"];
537
538                                 $s = serialize(array('url' => $url, 'item' => $b['id'], 'post' => $post));
539                                 require_once('include/queue_fn.php');
540                                 add_to_queue($a->contact,NETWORK_TWITTER,$s);
541                                 notice(t('Twitter post failed. Queued for retry.').EOL);
542                         } elseif ($iscomment) {
543                                 logger('twitter_post: Update extid '.$result->id_str." for post id ".$b['id']);
544                                 q("UPDATE `item` SET `extid` = '%s' WHERE `id` = %d",
545                                         dbesc("twitter::".$result->id_str),
546                                         intval($b['id'])
547                                 );
548                                 //q("UPDATE `item` SET `extid` = '%s', `body` = '%s' WHERE `id` = %d",
549                                 //      dbesc("twitter::".$result->id_str),
550                                 //      dbesc($result->text),
551                                 //      intval($b['id'])
552                                 //);
553                         }
554                 }
555         }
556 }
557
558 function twitter_plugin_admin_post(&$a){
559         $consumerkey    =       ((x($_POST,'consumerkey'))              ? notags(trim($_POST['consumerkey']))   : '');
560         $consumersecret =       ((x($_POST,'consumersecret'))   ? notags(trim($_POST['consumersecret'])): '');
561         $applicationname = ((x($_POST, 'applicationname')) ? notags(trim($_POST['applicationname'])):'');
562         set_config('twitter','consumerkey',$consumerkey);
563         set_config('twitter','consumersecret',$consumersecret);
564         set_config('twitter','application_name',$applicationname);
565         info( t('Settings updated.'). EOL );
566 }
567 function twitter_plugin_admin(&$a, &$o){
568         $t = get_markup_template( "admin.tpl", "addon/twitter/" );
569
570         $o = replace_macros($t, array(
571                 '$submit' => t('Save Settings'),
572                                                                 // name, label, value, help, [extra values]
573                 '$consumerkey' => array('consumerkey', t('Consumer key'),  get_config('twitter', 'consumerkey' ), ''),
574                 '$consumersecret' => array('consumersecret', t('Consumer secret'),  get_config('twitter', 'consumersecret' ), ''),
575                 '$applicationname' => array('applicationname', t('Name of the Twitter Application'), get_config('twitter','application_name'),t('set this to avoid mirroring postings from ~friendica back to ~friendica'))
576         ));
577 }
578
579 function twitter_cron($a,$b) {
580         $last = get_config('twitter','last_poll');
581
582         $poll_interval = intval(get_config('twitter','poll_interval'));
583         if(! $poll_interval)
584                 $poll_interval = TWITTER_DEFAULT_POLL_INTERVAL;
585
586         if($last) {
587                 $next = $last + ($poll_interval * 60);
588                 if($next > time()) {
589                         logger('twitter: poll intervall not reached');
590                         return;
591                 }
592         }
593         logger('twitter: cron_start');
594
595         $r = q("SELECT * FROM `pconfig` WHERE `cat` = 'twitter' AND `k` = 'mirror_posts' AND `v` = '1' ORDER BY RAND()");
596         if(count($r)) {
597                 foreach($r as $rr) {
598                         logger('twitter: fetching for user '.$rr['uid']);
599                         twitter_fetchtimeline($a, $rr['uid']);
600                 }
601         }
602
603
604         $r = q("SELECT * FROM `pconfig` WHERE `cat` = 'twitter' AND `k` = 'import' AND `v` = '1' ORDER BY RAND()");
605         if(count($r)) {
606                 foreach($r as $rr) {
607                         logger('twitter: importing timeline from user '.$rr['uid']);
608                         twitter_fetchhometimeline($a, $rr["uid"]);
609
610 /*
611                         // To-Do
612                         // check for new contacts once a day
613                         $last_contact_check = get_pconfig($rr['uid'],'pumpio','contact_check');
614                         if($last_contact_check)
615                                 $next_contact_check = $last_contact_check + 86400;
616                         else
617                                 $next_contact_check = 0;
618
619                         if($next_contact_check <= time()) {
620                                 pumpio_getallusers($a, $rr["uid"]);
621                                 set_pconfig($rr['uid'],'pumpio','contact_check',time());
622                         }
623 */
624
625                 }
626         }
627
628         logger('twitter: cron_end');
629
630         set_config('twitter','last_poll', time());
631 }
632
633 function twitter_expire($a,$b) {
634
635         $days = get_config('twitter', 'expire');
636
637         if ($days == 0)
638                 return;
639
640         $r = q("DELETE FROM `item` WHERE `deleted` AND `network` = '%s'", dbesc(NETWORK_TWITTER));
641
642         require_once("include/items.php");
643
644         logger('twitter_expire: expire_start');
645
646         $r = q("SELECT * FROM `pconfig` WHERE `cat` = 'twitter' AND `k` = 'import' AND `v` = '1' ORDER BY RAND()");
647         if(count($r)) {
648                 foreach($r as $rr) {
649                         logger('twitter_expire: user '.$rr['uid']);
650                         item_expire($rr['uid'], $days, NETWORK_TWITTER, true);
651                 }
652         }
653
654         logger('twitter_expire: expire_end');
655 }
656
657 function twitter_prepare_body(&$a,&$b) {
658         if ($b["item"]["network"] != NETWORK_TWITTER)
659                 return;
660
661         if ($b["preview"]) {
662                 $max_char = 140;
663                 require_once("include/plaintext.php");
664                 $item = $b["item"];
665                 $item["plink"] = $a->get_baseurl()."/display/".$a->user["nickname"]."/".$item["parent"];
666
667                 $r = q("SELECT `author-link` FROM item WHERE item.uri = '%s' AND item.uid = %d LIMIT 1",
668                         dbesc($item["thr-parent"]),
669                         intval(local_user()));
670
671                 if(count($r)) {
672                         $orig_post = $r[0];
673
674                         $nicknameplain = preg_replace("=https?://twitter.com/(.*)=ism", "$1", $orig_post["author-link"]);
675                         $nickname = "@[url=".$orig_post["author-link"]."]".$nicknameplain."[/url]";
676                         $nicknameplain = "@".$nicknameplain;
677
678                         if ((strpos($item["body"], $nickname) === false) AND (strpos($item["body"], $nicknameplain) === false))
679                                 $item["body"] = $nickname." ".$item["body"];
680                 }
681
682
683                 $msgarr = plaintext($a, $item, $max_char, true);
684                 $msg = $msgarr["text"];
685
686                 if (isset($msgarr["url"]))
687                         $msg .= " ".$msgarr["url"];
688
689                 if (isset($msgarr["image"]))
690                         $msg .= " ".$msgarr["image"];
691
692                 $b['html'] = nl2br(htmlspecialchars($msg));
693         }
694 }
695
696 function twitter_fetchtimeline($a, $uid) {
697         $ckey    = get_config('twitter', 'consumerkey');
698         $csecret = get_config('twitter', 'consumersecret');
699         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
700         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
701         $lastid  = get_pconfig($uid, 'twitter', 'lastid');
702
703         $application_name  = get_config('twitter', 'application_name');
704
705         if ($application_name == "")
706                 $application_name = $a->get_hostname();
707
708         $has_picture = false;
709
710         require_once('mod/item.php');
711         require_once('include/items.php');
712
713         require_once('library/twitteroauth.php');
714         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
715
716         $parameters = array("exclude_replies" => true, "trim_user" => false, "contributor_details" => true, "include_rts" => true);
717
718         $first_time = ($lastid == "");
719
720         if ($lastid <> "")
721                 $parameters["since_id"] = $lastid;
722
723         $items = $connection->get('statuses/user_timeline', $parameters);
724
725         if (!is_array($items))
726                 return;
727
728         $posts = array_reverse($items);
729
730         if (count($posts)) {
731             foreach ($posts as $post) {
732                 if ($post->id_str > $lastid)
733                         $lastid = $post->id_str;
734
735                 if ($first_time)
736                         continue;
737
738                 if (!strpos($post->source, $application_name)) {
739                         $_SESSION["authenticated"] = true;
740                         $_SESSION["uid"] = $uid;
741
742                         unset($_REQUEST);
743                         $_REQUEST["type"] = "wall";
744                         $_REQUEST["api_source"] = true;
745                         $_REQUEST["profile_uid"] = $uid;
746                         $_REQUEST["source"] = "Twitter";
747
748                         //$_REQUEST["date"] = $post->created_at;
749
750                         $_REQUEST["title"] = "";
751
752                         if (is_object($post->retweeted_status)) {
753
754                                 $_REQUEST['body'] = $post->retweeted_status->text;
755
756                                 $picture = "";
757
758                                 // media
759                                 if (is_array($post->retweeted_status->entities->media)) {
760                                         foreach($post->retweeted_status->entities->media AS $media) {
761                                                 switch($media->type) {
762                                                         case 'photo':
763                                                                 //$_REQUEST['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $_REQUEST['body']);
764                                                                 //$has_picture = true;
765                                                                 $_REQUEST['body'] = str_replace($media->url, "", $_REQUEST['body']);
766                                                                 $picture = $media->media_url_https;
767                                                                 break;
768                                                 }
769                                         }
770                                 }
771
772                                 $converted = twitter_expand_entities($a, $_REQUEST['body'], $post->retweeted_status, true, $picture);
773                                 $_REQUEST['body'] = $converted["body"];
774
775                                 $_REQUEST['body'] = "[share author='".$post->retweeted_status->user->name.
776                                         "' profile='https://twitter.com/".$post->retweeted_status->user->screen_name.
777                                         "' avatar='".$post->retweeted_status->user->profile_image_url_https.
778                                         "' link='https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str."']".
779                                         $_REQUEST['body'];
780                                 $_REQUEST['body'] .= "[/share]";
781                         } else {
782                                 $_REQUEST["body"] = $post->text;
783
784                                 $picture = "";
785
786                                 if (is_array($post->entities->media)) {
787                                         foreach($post->entities->media AS $media) {
788                                                 switch($media->type) {
789                                                         case 'photo':
790                                                                 //$_REQUEST['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $_REQUEST['body']);
791                                                                 //$has_picture = true;
792                                                                 $_REQUEST['body'] = str_replace($media->url, "", $_REQUEST['body']);
793                                                                 $picture = $media->media_url_https;
794                                                                 break;
795                                                 }
796                                         }
797                                 }
798
799                                 $converted = twitter_expand_entities($a, $_REQUEST["body"], $post, true, $picture);
800                                 $_REQUEST['body'] = $converted["body"];
801                         }
802
803                         if (is_string($post->place->name))
804                                 $_REQUEST["location"] = $post->place->name;
805
806                         if (is_string($post->place->full_name))
807                                 $_REQUEST["location"] = $post->place->full_name;
808
809                         if (is_array($post->geo->coordinates))
810                                 $_REQUEST["coord"] = $post->geo->coordinates[0]." ".$post->geo->coordinates[1];
811
812                         if (is_array($post->coordinates->coordinates))
813                                 $_REQUEST["coord"] = $post->coordinates->coordinates[1]." ".$post->coordinates->coordinates[0];
814
815                         //print_r($_REQUEST);
816                         logger('twitter: posting for user '.$uid);
817
818 //                      require_once('mod/item.php');
819
820                         item_post($a);
821                 }
822             }
823         }
824         set_pconfig($uid, 'twitter', 'lastid', $lastid);
825 }
826
827 function twitter_queue_hook(&$a,&$b) {
828
829         $qi = q("SELECT * FROM `queue` WHERE `network` = '%s'",
830                 dbesc(NETWORK_TWITTER)
831                 );
832         if(! count($qi))
833                 return;
834
835         require_once('include/queue_fn.php');
836
837         foreach($qi as $x) {
838                 if($x['network'] !== NETWORK_TWITTER)
839                         continue;
840
841                 logger('twitter_queue: run');
842
843                 $r = q("SELECT `user`.* FROM `user` LEFT JOIN `contact` on `contact`.`uid` = `user`.`uid` 
844                         WHERE `contact`.`self` = 1 AND `contact`.`id` = %d LIMIT 1",
845                         intval($x['cid'])
846                 );
847                 if(! count($r))
848                         continue;
849
850                 $user = $r[0];
851
852                 $ckey    = get_config('twitter', 'consumerkey');
853                 $csecret = get_config('twitter', 'consumersecret');
854                 $otoken  = get_pconfig($user['uid'], 'twitter', 'oauthtoken');
855                 $osecret = get_pconfig($user['uid'], 'twitter', 'oauthsecret');
856
857                 $success = false;
858
859                 if ($ckey AND $csecret AND $otoken AND $osecret) {
860
861                         logger('twitter_queue: able to post');
862
863                         $z = unserialize($x['content']);
864
865                         require_once("addon/twitter/codebird.php");
866
867                         $cb = \Codebird\Codebird::getInstance();
868                         $cb->setConsumerKey($ckey, $csecret);
869                         $cb->setToken($otoken, $osecret);
870
871                         if ($z['url'] == "statuses/update")
872                                 $result = $cb->statuses_update($z['post']);
873
874                         logger('twitter_queue: post result: ' . print_r($result, true), LOGGER_DEBUG);
875
876                         if ($result->errors)
877                                 logger('twitter_queue: Send to Twitter failed: "' . print_r($result->errors, true) . '"');
878                         else {
879                                 $success = true;
880                                 remove_queue_item($x['id']);
881                         }
882                 } else
883                         logger("twitter_queue: Error getting tokens for user ".$user['uid']);
884
885                 if (!$success) {
886                         logger('twitter_queue: delayed');
887                         update_queue_time($x['id']);
888                 }
889         }
890 }
891
892 function twitter_fetch_contact($uid, $contact, $create_user) {
893
894         // Check if the unique contact is existing
895         // To-Do: only update once a while
896         $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1",
897                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)));
898
899         if (count($r) == 0)
900                 q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')",
901                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
902                         dbesc($contact->name),
903                         dbesc($contact->screen_name),
904                         dbesc($contact->profile_image_url_https));
905         else
906                 q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'",
907                         dbesc($contact->name),
908                         dbesc($contact->screen_name),
909                         dbesc($contact->profile_image_url_https),
910                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)));
911
912         $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
913                 intval($uid), dbesc("twitter::".$contact->id_str));
914
915         if(!count($r) AND !$create_user)
916                 return(0);
917
918         if (count($r) AND ($r[0]["readonly"] OR $r[0]["blocked"])) {
919                 logger("twitter_fetch_contact: Contact '".$r[0]["nick"]."' is blocked or readonly.", LOGGER_DEBUG);
920                 return(-1);
921         }
922
923         if(!count($r)) {
924                 // create contact record
925                 q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,
926                                         `name`, `nick`, `photo`, `network`, `rel`, `priority`,
927                                         `writable`, `blocked`, `readonly`, `pending` )
928                                         VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
929                         intval($uid),
930                         dbesc(datetime_convert()),
931                         dbesc("https://twitter.com/".$contact->screen_name),
932                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
933                         dbesc($contact->screen_name."@twitter.com"),
934                         dbesc("twitter::".$contact->id_str),
935                         dbesc(''),
936                         dbesc("twitter::".$contact->id_str),
937                         dbesc($contact->name),
938                         dbesc($contact->screen_name),
939                         dbesc($contact->profile_image_url_https),
940                         dbesc(NETWORK_TWITTER),
941                         intval(CONTACT_IS_FRIEND),
942                         intval(1),
943                         intval(1)
944                 );
945
946                 $r = q("SELECT * FROM `contact` WHERE `alias` = '%s' AND `uid` = %d LIMIT 1",
947                         dbesc("twitter::".$contact->id_str),
948                         intval($uid)
949                         );
950
951                 if(! count($r))
952                         return(false);
953
954                 $contact_id  = $r[0]['id'];
955
956                 $g = q("SELECT def_gid FROM user WHERE uid = %d LIMIT 1",
957                         intval($uid)
958                 );
959
960                 if($g && intval($g[0]['def_gid'])) {
961                         require_once('include/group.php');
962                         group_add_member($uid,'',$contact_id,$g[0]['def_gid']);
963                 }
964
965                 require_once("Photo.php");
966
967                 $photos = import_profile_photo($contact->profile_image_url_https,$uid,$contact_id);
968
969                 q("UPDATE `contact` SET `photo` = '%s',
970                                         `thumb` = '%s',
971                                         `micro` = '%s',
972                                         `name-date` = '%s',
973                                         `uri-date` = '%s',
974                                         `avatar-date` = '%s'
975                                 WHERE `id` = %d",
976                         dbesc($photos[0]),
977                         dbesc($photos[1]),
978                         dbesc($photos[2]),
979                         dbesc(datetime_convert()),
980                         dbesc(datetime_convert()),
981                         dbesc(datetime_convert()),
982                         intval($contact_id)
983                 );
984
985         } else {
986                 // update profile photos once every two weeks as we have no notification of when they change.
987
988                 //$update_photo = (($r[0]['avatar-date'] < datetime_convert('','','now -2 days')) ? true : false);
989                 $update_photo = ($r[0]['avatar-date'] < datetime_convert('','','now -12 hours'));
990
991                 // check that we have all the photos, this has been known to fail on occasion
992
993                 if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro']) || ($update_photo)) {
994
995                         logger("twitter_fetch_contact: Updating contact ".$contact->screen_name, LOGGER_DEBUG);
996
997                         require_once("Photo.php");
998
999                         $photos = import_profile_photo($contact->profile_image_url_https, $uid, $r[0]['id']);
1000
1001                         q("UPDATE `contact` SET `photo` = '%s',
1002                                                 `thumb` = '%s',
1003                                                 `micro` = '%s',
1004                                                 `name-date` = '%s',
1005                                                 `uri-date` = '%s',
1006                                                 `avatar-date` = '%s',
1007                                                 `url` = '%s',
1008                                                 `nurl` = '%s',
1009                                                 `addr` = '%s',
1010                                                 `name` = '%s',
1011                                                 `nick` = '%s'
1012                                         WHERE `id` = %d",
1013                                 dbesc($photos[0]),
1014                                 dbesc($photos[1]),
1015                                 dbesc($photos[2]),
1016                                 dbesc(datetime_convert()),
1017                                 dbesc(datetime_convert()),
1018                                 dbesc(datetime_convert()),
1019                                 dbesc("https://twitter.com/".$contact->screen_name),
1020                                 dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
1021                                 dbesc($contact->screen_name."@twitter.com"),
1022                                 dbesc($contact->name),
1023                                 dbesc($contact->screen_name),
1024                                 intval($r[0]['id'])
1025                         );
1026                 }
1027         }
1028
1029         return($r[0]["id"]);
1030 }
1031
1032 function twitter_fetchuser($a, $uid, $screen_name = "", $user_id = "") {
1033         $ckey    = get_config('twitter', 'consumerkey');
1034         $csecret = get_config('twitter', 'consumersecret');
1035         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1036         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1037
1038         require_once("addon/twitter/codebird.php");
1039
1040         $cb = \Codebird\Codebird::getInstance();
1041         $cb->setConsumerKey($ckey, $csecret);
1042         $cb->setToken($otoken, $osecret);
1043
1044         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1045                 intval($uid));
1046
1047         if(count($r)) {
1048                 $self = $r[0];
1049         } else
1050                 return;
1051
1052         $parameters = array();
1053
1054         if ($screen_name != "")
1055                 $parameters["screen_name"] = $screen_name;
1056
1057         if ($user_id != "")
1058                 $parameters["user_id"] = $user_id;
1059
1060         // Fetching user data
1061         $user = $cb->users_show($parameters);
1062
1063         if (!is_object($user))
1064                 return;
1065
1066         $contact_id = twitter_fetch_contact($uid, $user, true);
1067
1068         return $contact_id;
1069 }
1070
1071 function twitter_expand_entities($a, $body, $item, $no_tags = false, $picture) {
1072         require_once("include/oembed.php");
1073         require_once("include/network.php");
1074
1075         $tags = "";
1076
1077         if (isset($item->entities->urls)) {
1078                 $type = "";
1079                 $footerurl = "";
1080                 $footerlink = "";
1081                 $footer = "";
1082
1083                 foreach ($item->entities->urls AS $url) {
1084                         if ($url->url AND $url->expanded_url AND $url->display_url) {
1085
1086                                 $expanded_url = original_url($url->expanded_url);
1087
1088                                 $oembed_data = oembed_fetch_url($expanded_url);
1089
1090                                 // Quickfix: Workaround for URL with "[" and "]" in it
1091                                 if (strpos($expanded_url, "[") OR strpos($expanded_url, "]"))
1092                                         $expanded_url = $url->url;
1093
1094                                 if ($type == "")
1095                                         $type = $oembed_data->type;
1096
1097                                 if ($oembed_data->type == "video") {
1098                                         //$body = str_replace($url->url,
1099                                         //              "[video]".$expanded_url."[/video]", $body);
1100                                         //$dontincludemedia = true;
1101                                         $type = $oembed_data->type;
1102                                         $footerurl = $expanded_url;
1103                                         $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]";
1104
1105                                         $body = str_replace($url->url, $footerlink, $body);
1106                                 //} elseif (($oembed_data->type == "photo") AND isset($oembed_data->url) AND !$dontincludemedia) {
1107                                 } elseif (($oembed_data->type == "photo") AND isset($oembed_data->url)) {
1108                                         $body = str_replace($url->url,
1109                                                         "[url=".$expanded_url."][img]".$oembed_data->url."[/img][/url]",
1110                                                         $body);
1111                                         //$dontincludemedia = true;
1112                                 } elseif ($oembed_data->type != "link")
1113                                         $body = str_replace($url->url,
1114                                                         "[url=".$expanded_url."]".$expanded_url."[/url]",
1115                                                         $body);
1116                                 else {
1117                                         $img_str = fetch_url($expanded_url, true, $redirects, 4);
1118
1119                                         $tempfile = tempnam(get_temppath(), "cache");
1120                                         file_put_contents($tempfile, $img_str);
1121                                         $mime = image_type_to_mime_type(exif_imagetype($tempfile));
1122                                         unlink($tempfile);
1123
1124                                         if (substr($mime, 0, 6) == "image/") {
1125                                                 $type = "photo";
1126                                                 $body = str_replace($url->url, "[img]".$expanded_url."[/img]", $body);
1127                                                 //$dontincludemedia = true;
1128                                         } else {
1129                                                 $type = $oembed_data->type;
1130                                                 $footerurl = $expanded_url;
1131                                                 $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]";
1132
1133                                                 $body = str_replace($url->url, $footerlink, $body);
1134                                         }
1135                                 }
1136                         }
1137                 }
1138
1139                 if ($footerurl != "")
1140                         $footer = add_page_info($footerurl, false, $picture);
1141
1142                 if (($footerlink != "") AND (trim($footer) != "")) {
1143                         $removedlink = trim(str_replace($footerlink, "", $body));
1144
1145                         if (strstr($body, $removedlink))
1146                                 $body = $removedlink;
1147
1148                         $body .= $footer;
1149                 }
1150
1151                 if (($footer == "") AND ($picture != ""))
1152                         $body .= "\n\n[img]".$picture."[/img]\n";
1153
1154                 if ($no_tags)
1155                         return(array("body" => $body, "tags" => ""));
1156
1157                 $tags_arr = array();
1158
1159                 foreach ($item->entities->hashtags AS $hashtag) {
1160                         $url = "#[url=".$a->get_baseurl()."/search?tag=".rawurlencode($hashtag->text)."]".$hashtag->text."[/url]";
1161                         $tags_arr["#".$hashtag->text] = $url;
1162                         $body = str_replace("#".$hashtag->text, $url, $body);
1163                 }
1164
1165                 foreach ($item->entities->user_mentions AS $mention) {
1166                         $url = "@[url=https://twitter.com/".rawurlencode($mention->screen_name)."]".$mention->screen_name."[/url]";
1167                         $tags_arr["@".$mention->screen_name] = $url;
1168                         $body = str_replace("@".$mention->screen_name, $url, $body);
1169                 }
1170
1171                 // it seems as if the entities aren't always covering all mentions. So the rest will be checked here
1172                 $tags = get_tags($body);
1173
1174                 if(count($tags)) {
1175                         foreach($tags as $tag) {
1176                                 if (strstr(trim($tag), " "))
1177                                         continue;
1178
1179                                 if(strpos($tag,'#') === 0) {
1180                                         if(strpos($tag,'[url='))
1181                                                 continue;
1182
1183                                         // don't link tags that are already embedded in links
1184
1185                                         if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body))
1186                                                 continue;
1187                                         if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body))
1188                                                 continue;
1189
1190                                         $basetag = str_replace('_',' ',substr($tag,1));
1191                                         $url = '#[url='.$a->get_baseurl().'/search?tag='.rawurlencode($basetag).']'.$basetag.'[/url]';
1192                                         $body = str_replace($tag,$url,$body);
1193                                         $tags_arr["#".$basetag] = $url;
1194                                         continue;
1195                                 } elseif(strpos($tag,'@') === 0) {
1196                                         if(strpos($tag,'[url='))
1197                                                 continue;
1198
1199                                         $basetag = substr($tag,1);
1200                                         $url = '@[url=https://twitter.com/'.rawurlencode($basetag).']'.$basetag.'[/url]';
1201                                         $body = str_replace($tag,$url,$body);
1202                                         $tags_arr["@".$basetag] = $url;
1203                                 }
1204                         }
1205                 }
1206
1207
1208                 $tags = implode($tags_arr, ",");
1209
1210         }
1211         return(array("body" => $body, "tags" => $tags));
1212 }
1213
1214 function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing_contact) {
1215
1216         $has_picture = false;
1217
1218         $postarray = array();
1219         $postarray['network'] = NETWORK_TWITTER;
1220         $postarray['gravity'] = 0;
1221         $postarray['uid'] = $uid;
1222         $postarray['wall'] = 0;
1223         $postarray['uri'] = "twitter::".$post->id_str;
1224
1225         $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1",
1226                         dbesc($postarray['uri']),
1227                         intval($uid)
1228                 );
1229
1230         if (count($r))
1231                 return(array());
1232
1233         $contactid = 0;
1234
1235         if ($post->in_reply_to_status_id_str != "") {
1236
1237                 $parent = "twitter::".$post->in_reply_to_status_id_str;
1238
1239                 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
1240                                 dbesc($parent),
1241                                 intval($uid)
1242                         );
1243                 if (count($r)) {
1244                         $postarray['thr-parent'] = $r[0]["uri"];
1245                         $postarray['parent-uri'] = $r[0]["parent-uri"];
1246                 } else {
1247                         $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1",
1248                                         dbesc($parent),
1249                                         intval($uid)
1250                                 );
1251                         if (count($r)) {
1252                                 $postarray['thr-parent'] = $r[0]['uri'];
1253                                 $postarray['parent-uri'] = $r[0]['parent-uri'];
1254                         } else {
1255                                 $postarray['thr-parent'] = $postarray['uri'];
1256                                 $postarray['parent-uri'] = $postarray['uri'];
1257                         }
1258                 }
1259
1260                 // Is it me?
1261                 $own_id = get_pconfig($uid, 'twitter', 'own_id');
1262
1263                 if ($post->user->id_str == $own_id) {
1264                         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1265                                 intval($uid));
1266
1267                         if(count($r)) {
1268                                 $contactid = $r[0]["id"];
1269
1270                                 $postarray['owner-name'] =  $r[0]["name"];
1271                                 $postarray['owner-link'] = $r[0]["url"];
1272                                 $postarray['owner-avatar'] =  $r[0]["photo"];
1273                         } else
1274                                 return(array());
1275                 }
1276                 // Don't create accounts of people who just comment something
1277                 $create_user = false;
1278         } else
1279                 $postarray['parent-uri'] = $postarray['uri'];
1280
1281         if ($contactid == 0) {
1282                 $contactid = twitter_fetch_contact($uid, $post->user, $create_user);
1283
1284                 $postarray['owner-name'] = $post->user->name;
1285                 $postarray['owner-link'] = "https://twitter.com/".$post->user->screen_name;
1286                 $postarray['owner-avatar'] = $post->user->profile_image_url_https;
1287         }
1288
1289         if(($contactid == 0) AND !$only_existing_contact)
1290                 $contactid = $self['id'];
1291         elseif ($contactid <= 0)
1292                 return(array());
1293
1294         $postarray['contact-id'] = $contactid;
1295
1296         $postarray['verb'] = ACTIVITY_POST;
1297         $postarray['author-name'] = $postarray['owner-name'];
1298         $postarray['author-link'] = $postarray['owner-link'];
1299         $postarray['author-avatar'] = $postarray['owner-avatar'];
1300         $postarray['plink'] = "https://twitter.com/".$post->user->screen_name."/status/".$post->id_str;
1301         $postarray['app'] = strip_tags($post->source);
1302
1303         if ($post->user->protected) {
1304                 $postarray['private'] = 1;
1305                 $postarray['allow_cid'] = '<' . $self['id'] . '>';
1306         }
1307
1308         $postarray['body'] = $post->text;
1309
1310         $picture = "";
1311
1312         // media
1313         if (is_array($post->entities->media)) {
1314                 foreach($post->entities->media AS $media) {
1315                         switch($media->type) {
1316                                 case 'photo':
1317                                         //$postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']);
1318                                         //$has_picture = true;
1319                                         $postarray['body'] = str_replace($media->url, "", $postarray['body']);
1320                                         $picture = $media->media_url_https;
1321                                         break;
1322                                 default:
1323                                         $postarray['body'] .= print_r($media, true);
1324                         }
1325                 }
1326         }
1327
1328         $converted = twitter_expand_entities($a, $postarray['body'], $post, false, $picture);
1329         $postarray['body'] = $converted["body"];
1330         $postarray['tag'] = $converted["tags"];
1331
1332         $postarray['created'] = datetime_convert('UTC','UTC',$post->created_at);
1333         $postarray['edited'] = datetime_convert('UTC','UTC',$post->created_at);
1334
1335         if (is_string($post->place->name))
1336                 $postarray["location"] = $post->place->name;
1337
1338         if (is_string($post->place->full_name))
1339                 $postarray["location"] = $post->place->full_name;
1340
1341         if (is_array($post->geo->coordinates))
1342                 $postarray["coord"] = $post->geo->coordinates[0]." ".$post->geo->coordinates[1];
1343
1344         if (is_array($post->coordinates->coordinates))
1345                 $postarray["coord"] = $post->coordinates->coordinates[1]." ".$post->coordinates->coordinates[0];
1346
1347         if (is_object($post->retweeted_status)) {
1348
1349                 $postarray['body'] = $post->retweeted_status->text;
1350
1351                 $picture = "";
1352
1353                 // media
1354                 if (is_array($post->retweeted_status->entities->media)) {
1355                         foreach($post->retweeted_status->entities->media AS $media) {
1356                                 switch($media->type) {
1357                                         case 'photo':
1358                                                 //$postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']);
1359                                                 //$has_picture = true;
1360                                                 $postarray['body'] = str_replace($media->url, "", $postarray['body']);
1361                                                 $picture = $media->media_url_https;
1362                                                 break;
1363                                         default:
1364                                                 $postarray['body'] .= print_r($media, true);
1365                                 }
1366                         }
1367                 }
1368
1369                 $converted = twitter_expand_entities($a, $postarray['body'], $post->retweeted_status, false, $picture);
1370                 $postarray['body'] = $converted["body"];
1371                 $postarray['tag'] = $converted["tags"];
1372
1373                 twitter_fetch_contact($uid, $post->retweeted_status->user, false);
1374
1375                 // Deactivated at the moment, since there are problems with answers to retweets
1376                 if (false AND !intval(get_config('system','wall-to-wall_share'))) {
1377                         $postarray['body'] = "[share author='".$post->retweeted_status->user->name.
1378                                 "' profile='https://twitter.com/".$post->retweeted_status->user->screen_name.
1379                                 "' avatar='".$post->retweeted_status->user->profile_image_url_https.
1380                                 "' link='https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str."']".
1381                                 $postarray['body'];
1382                         $postarray['body'] .= "[/share]";
1383                 } else {
1384                         // Let retweets look like wall-to-wall posts
1385                         $postarray['author-name'] = $post->retweeted_status->user->name;
1386                         $postarray['author-link'] = "https://twitter.com/".$post->retweeted_status->user->screen_name;
1387                         $postarray['author-avatar'] = $post->retweeted_status->user->profile_image_url_https;
1388                         //if (($post->retweeted_status->user->screen_name != "") AND ($post->retweeted_status->id_str != "")) {
1389                         //      $postarray['plink'] = "https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str;
1390                         //      $postarray['uri'] = "twitter::".$post->retweeted_status->id_str;
1391                         //}
1392                 }
1393
1394         }
1395         return($postarray);
1396 }
1397
1398 function twitter_checknotification($a, $uid, $own_id, $top_item, $postarray) {
1399
1400         $user = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1",
1401                         intval($uid)
1402                 );
1403
1404         if(!count($user))
1405                 return;
1406
1407         // Is it me?
1408         if (link_compare($user[0]["url"], $postarray['author-link']))
1409                 return;
1410
1411         $own_user = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
1412                         intval($uid),
1413                         dbesc("twitter::".$own_id)
1414                 );
1415
1416         if(!count($own_user))
1417                 return;
1418
1419         // Is it me from twitter?
1420         if (link_compare($own_user[0]["url"], $postarray['author-link']))
1421                 return;
1422
1423         $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0",
1424                         dbesc($postarray['parent-uri']),
1425                         intval($uid)
1426                         );
1427
1428         if(count($myconv)) {
1429
1430                 foreach($myconv as $conv) {
1431                         // now if we find a match, it means we're in this conversation
1432
1433                         if(!link_compare($conv['author-link'],$user[0]["url"]) AND !link_compare($conv['author-link'],$own_user[0]["url"]))
1434                                 continue;
1435
1436                         require_once('include/enotify.php');
1437
1438                         $conv_parent = $conv['parent'];
1439
1440                         notification(array(
1441                                 'type'         => NOTIFY_COMMENT,
1442                                 'notify_flags' => $user[0]['notify-flags'],
1443                                 'language'     => $user[0]['language'],
1444                                 'to_name'      => $user[0]['username'],
1445                                 'to_email'     => $user[0]['email'],
1446                                 'uid'          => $user[0]['uid'],
1447                                 'item'         => $postarray,
1448                                 'link'             => $a->get_baseurl() . '/display/' . $user[0]['nickname'] . '/' . $top_item,
1449                                 'source_name'  => $postarray['author-name'],
1450                                 'source_link'  => $postarray['author-link'],
1451                                 'source_photo' => $postarray['author-avatar'],
1452                                 'verb'         => ACTIVITY_POST,
1453                                 'otype'        => 'item',
1454                                 'parent'       => $conv_parent,
1455                         ));
1456
1457                         // only send one notification
1458                         break;
1459                 }
1460         }
1461 }
1462
1463 function twitter_fetchhometimeline($a, $uid) {
1464         $ckey    = get_config('twitter', 'consumerkey');
1465         $csecret = get_config('twitter', 'consumersecret');
1466         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1467         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1468         $create_user = get_pconfig($uid, 'twitter', 'create_user');
1469
1470         logger("twitter_fetchhometimeline: Fetching for user ".$uid, LOGGER_DEBUG);
1471
1472         require_once('library/twitteroauth.php');
1473         require_once('include/items.php');
1474
1475         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1476
1477         $own_contact = twitter_fetch_own_contact($a, $uid);
1478
1479         $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
1480                 intval($own_contact),
1481                 intval($uid));
1482
1483         if(count($r)) {
1484                 $own_id = $r[0]["nick"];
1485         } else {
1486                 logger("twitter_fetchhometimeline: Own twitter contact not found for user ".$uid, LOGGER_DEBUG);
1487                 return;
1488         }
1489
1490         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1491                 intval($uid));
1492
1493         if(count($r)) {
1494                 $self = $r[0];
1495         } else {
1496                 logger("twitter_fetchhometimeline: Own contact not found for user ".$uid, LOGGER_DEBUG);
1497                 return;
1498         }
1499
1500         $u = q("SELECT * FROM user WHERE uid = %d LIMIT 1",
1501                 intval($uid));
1502         if(!count($u)) {
1503                 logger("twitter_fetchhometimeline: Own user not found for user ".$uid, LOGGER_DEBUG);
1504                 return;
1505         }
1506
1507         $parameters = array("exclude_replies" => false, "trim_user" => false, "contributor_details" => true, "include_rts" => true);
1508         //$parameters["count"] = 200;
1509
1510
1511         // Fetching timeline
1512         $lastid  = get_pconfig($uid, 'twitter', 'lasthometimelineid');
1513
1514         $first_time = ($lastid == "");
1515
1516         if ($lastid <> "")
1517                 $parameters["since_id"] = $lastid;
1518
1519         $items = $connection->get('statuses/home_timeline', $parameters);
1520
1521         if (!is_array($items)) {
1522                 logger("twitter_fetchhometimeline: Error fetching home timeline: ".print_r($items, true), LOGGER_DEBUG);
1523                 return;
1524         }
1525
1526         $posts = array_reverse($items);
1527
1528         logger("twitter_fetchhometimeline: Fetching timeline for user ".$uid." ".sizeof($posts)." items", LOGGER_DEBUG);
1529
1530         if (count($posts)) {
1531                 foreach ($posts as $post) {
1532                         if ($post->id_str > $lastid)
1533                                 $lastid = $post->id_str;
1534
1535                         if ($first_time)
1536                                 continue;
1537
1538                         $postarray = twitter_createpost($a, $uid, $post, $self, $create_user, true);
1539
1540                         if (trim($postarray['body']) == "")
1541                                 continue;
1542
1543                         $item = item_store($postarray);
1544
1545                         logger('twitter_fetchhometimeline: User '.$self["nick"].' posted home timeline item '.$item);
1546
1547                         if ($item != 0)
1548                                 twitter_checknotification($a, $uid, $own_id, $item, $postarray);
1549
1550                 }
1551         }
1552         set_pconfig($uid, 'twitter', 'lasthometimelineid', $lastid);
1553
1554         // Fetching mentions
1555         $lastid  = get_pconfig($uid, 'twitter', 'lastmentionid');
1556
1557         $first_time = ($lastid == "");
1558
1559         if ($lastid <> "")
1560                 $parameters["since_id"] = $lastid;
1561
1562         $items = $connection->get('statuses/mentions_timeline', $parameters);
1563
1564         if (!is_array($items)) {
1565                 logger("twitter_fetchhometimeline: Error fetching mentions: ".print_r($items, true), LOGGER_DEBUG);
1566                 return;
1567         }
1568
1569         $posts = array_reverse($items);
1570
1571         logger("twitter_fetchhometimeline: Fetching mentions for user ".$uid." ".sizeof($posts)." items", LOGGER_DEBUG);
1572
1573         if (count($posts)) {
1574                 foreach ($posts as $post) {
1575                         if ($post->id_str > $lastid)
1576                                 $lastid = $post->id_str;
1577
1578                         if ($first_time)
1579                                 continue;
1580
1581                         $postarray = twitter_createpost($a, $uid, $post, $self, false, false);
1582
1583                         if (trim($postarray['body']) == "")
1584                                 continue;
1585
1586                         $item = item_store($postarray);
1587
1588                         logger('twitter_fetchhometimeline: User '.$self["nick"].' posted mention timeline item '.$item);
1589
1590                         if ($item == 0) {
1591                                 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
1592                                         dbesc($postarray['uri']),
1593                                         intval($uid)
1594                                 );
1595                                 if (count($r))
1596                                         $item = $r[0]['id'];
1597                         }
1598
1599                         if ($item != 0) {
1600                                 require_once('include/enotify.php');
1601                                 notification(array(
1602                                         'type'         => NOTIFY_TAGSELF,
1603                                         'notify_flags' => $u[0]['notify-flags'],
1604                                         'language'     => $u[0]['language'],
1605                                         'to_name'      => $u[0]['username'],
1606                                         'to_email'     => $u[0]['email'],
1607                                         'uid'          => $u[0]['uid'],
1608                                         'item'         => $postarray,
1609                                         'link'         => $a->get_baseurl() . '/display/' . $u[0]['nickname'] . '/' . $item,
1610                                         'source_name'  => $postarray['author-name'],
1611                                         'source_link'  => $postarray['author-link'],
1612                                         'source_photo' => $postarray['author-avatar'],
1613                                         'verb'         => ACTIVITY_TAG,
1614                                         'otype'        => 'item'
1615                                 ));
1616                         }
1617                 }
1618         }
1619
1620         set_pconfig($uid, 'twitter', 'lastmentionid', $lastid);
1621 }
1622
1623 function twitter_fetch_own_contact($a, $uid) {
1624         $ckey    = get_config('twitter', 'consumerkey');
1625         $csecret = get_config('twitter', 'consumersecret');
1626         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1627         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1628
1629         $own_id = get_pconfig($uid, 'twitter', 'own_id');
1630
1631         $contact_id = 0;
1632
1633         if ($own_id == "") {
1634                 require_once('library/twitteroauth.php');
1635
1636                 $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1637
1638                 // Fetching user data
1639                 $user = $connection->get('account/verify_credentials');
1640
1641                 set_pconfig($uid, 'twitter', 'own_id', $user->id_str);
1642
1643                 $contact_id = twitter_fetch_contact($uid, $user, true);
1644
1645         } else {
1646                 $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
1647                         intval($uid), dbesc("twitter::".$own_id));
1648                 if(count($r))
1649                         $contact_id = $r[0]["id"];
1650                 else
1651                         del_pconfig($uid, 'twitter', 'own_id');
1652
1653         }
1654
1655         return($contact_id);
1656 }
1657
1658 function twitter_is_retweet($a, $uid, $body) {
1659         $body = trim($body);
1660
1661         // Skip if it isn't a pure repeated messages
1662         // Does it start with a share?
1663         if (strpos($body, "[share") > 0)
1664                 return(false);
1665
1666         // Does it end with a share?
1667         if (strlen($body) > (strrpos($body, "[/share]") + 8))
1668                 return(false);
1669
1670         $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
1671         // Skip if there is no shared message in there
1672         if ($body == $attributes)
1673                 return(false);
1674
1675         $link = "";
1676         preg_match("/link='(.*?)'/ism", $attributes, $matches);
1677         if ($matches[1] != "")
1678                 $link = $matches[1];
1679
1680         preg_match('/link="(.*?)"/ism', $attributes, $matches);
1681         if ($matches[1] != "")
1682                 $link = $matches[1];
1683
1684         $id = preg_replace("=https?://twitter.com/(.*)/status/(.*)=ism", "$2", $link);
1685         if ($id == $link)
1686                 return(false);
1687
1688         logger('twitter_is_retweet: Retweeting id '.$id.' for user '.$uid, LOGGER_DEBUG);
1689
1690         $ckey    = get_config('twitter', 'consumerkey');
1691         $csecret = get_config('twitter', 'consumersecret');
1692         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1693         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1694
1695         require_once('library/twitteroauth.php');
1696         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1697
1698         $result = $connection->post('statuses/retweet/'.$id);
1699
1700         logger('twitter_is_retweet: result '.print_r($result, true), LOGGER_DEBUG);
1701
1702         return(!isset($result->errors));
1703 }
1704 ?>