]> git.mxchange.org Git - friendica-addons.git/blob - twitter/twitter.php
Merge pull request #210 from annando/master
[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, 8);
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, 8);
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         require_once("include/Photo.php");
894
895         $avatar = str_replace("_normal.", ".", $contact->profile_image_url_https);
896
897         $info = get_photo_info($avatar);
898         if (!$info)
899                 $avatar = $contact->profile_image_url_https;
900
901         // Check if the unique contact is existing
902         // To-Do: only update once a while
903         $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1",
904                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)));
905
906         if (count($r) == 0)
907                 q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')",
908                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
909                         dbesc($contact->name),
910                         dbesc($contact->screen_name),
911                         dbesc($avatar));
912         else
913                 q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'",
914                         dbesc($contact->name),
915                         dbesc($contact->screen_name),
916                         dbesc($avatar),
917                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)));
918
919         $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
920                 intval($uid), dbesc("twitter::".$contact->id_str));
921
922         if(!count($r) AND !$create_user)
923                 return(0);
924
925         if (count($r) AND ($r[0]["readonly"] OR $r[0]["blocked"])) {
926                 logger("twitter_fetch_contact: Contact '".$r[0]["nick"]."' is blocked or readonly.", LOGGER_DEBUG);
927                 return(-1);
928         }
929
930         if(!count($r)) {
931                 // create contact record
932                 q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,
933                                         `name`, `nick`, `photo`, `network`, `rel`, `priority`,
934                                         `writable`, `blocked`, `readonly`, `pending` )
935                                         VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
936                         intval($uid),
937                         dbesc(datetime_convert()),
938                         dbesc("https://twitter.com/".$contact->screen_name),
939                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
940                         dbesc($contact->screen_name."@twitter.com"),
941                         dbesc("twitter::".$contact->id_str),
942                         dbesc(''),
943                         dbesc("twitter::".$contact->id_str),
944                         dbesc($contact->name),
945                         dbesc($contact->screen_name),
946                         dbesc($avatar),
947                         dbesc(NETWORK_TWITTER),
948                         intval(CONTACT_IS_FRIEND),
949                         intval(1),
950                         intval(1)
951                 );
952
953                 $r = q("SELECT * FROM `contact` WHERE `alias` = '%s' AND `uid` = %d LIMIT 1",
954                         dbesc("twitter::".$contact->id_str),
955                         intval($uid)
956                         );
957
958                 if(! count($r))
959                         return(false);
960
961                 $contact_id  = $r[0]['id'];
962
963                 $g = q("SELECT def_gid FROM user WHERE uid = %d LIMIT 1",
964                         intval($uid)
965                 );
966
967                 if($g && intval($g[0]['def_gid'])) {
968                         require_once('include/group.php');
969                         group_add_member($uid,'',$contact_id,$g[0]['def_gid']);
970                 }
971
972                 require_once("Photo.php");
973
974                 $photos = import_profile_photo($avatar,$uid,$contact_id);
975
976                 q("UPDATE `contact` SET `photo` = '%s',
977                                         `thumb` = '%s',
978                                         `micro` = '%s',
979                                         `name-date` = '%s',
980                                         `uri-date` = '%s',
981                                         `avatar-date` = '%s'
982                                 WHERE `id` = %d",
983                         dbesc($photos[0]),
984                         dbesc($photos[1]),
985                         dbesc($photos[2]),
986                         dbesc(datetime_convert()),
987                         dbesc(datetime_convert()),
988                         dbesc(datetime_convert()),
989                         intval($contact_id)
990                 );
991
992         } else {
993                 // update profile photos once every two weeks as we have no notification of when they change.
994
995                 //$update_photo = (($r[0]['avatar-date'] < datetime_convert('','','now -2 days')) ? true : false);
996                 $update_photo = ($r[0]['avatar-date'] < datetime_convert('','','now -12 hours'));
997
998                 // check that we have all the photos, this has been known to fail on occasion
999
1000                 if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro']) || ($update_photo)) {
1001
1002                         logger("twitter_fetch_contact: Updating contact ".$contact->screen_name, LOGGER_DEBUG);
1003
1004                         require_once("Photo.php");
1005
1006                         $photos = import_profile_photo($avatar, $uid, $r[0]['id']);
1007
1008                         q("UPDATE `contact` SET `photo` = '%s',
1009                                                 `thumb` = '%s',
1010                                                 `micro` = '%s',
1011                                                 `name-date` = '%s',
1012                                                 `uri-date` = '%s',
1013                                                 `avatar-date` = '%s',
1014                                                 `url` = '%s',
1015                                                 `nurl` = '%s',
1016                                                 `addr` = '%s',
1017                                                 `name` = '%s',
1018                                                 `nick` = '%s'
1019                                         WHERE `id` = %d",
1020                                 dbesc($photos[0]),
1021                                 dbesc($photos[1]),
1022                                 dbesc($photos[2]),
1023                                 dbesc(datetime_convert()),
1024                                 dbesc(datetime_convert()),
1025                                 dbesc(datetime_convert()),
1026                                 dbesc("https://twitter.com/".$contact->screen_name),
1027                                 dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
1028                                 dbesc($contact->screen_name."@twitter.com"),
1029                                 dbesc($contact->name),
1030                                 dbesc($contact->screen_name),
1031                                 intval($r[0]['id'])
1032                         );
1033                 }
1034         }
1035
1036         return($r[0]["id"]);
1037 }
1038
1039 function twitter_fetchuser($a, $uid, $screen_name = "", $user_id = "") {
1040         $ckey    = get_config('twitter', 'consumerkey');
1041         $csecret = get_config('twitter', 'consumersecret');
1042         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1043         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1044
1045         require_once("addon/twitter/codebird.php");
1046
1047         $cb = \Codebird\Codebird::getInstance();
1048         $cb->setConsumerKey($ckey, $csecret);
1049         $cb->setToken($otoken, $osecret);
1050
1051         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1052                 intval($uid));
1053
1054         if(count($r)) {
1055                 $self = $r[0];
1056         } else
1057                 return;
1058
1059         $parameters = array();
1060
1061         if ($screen_name != "")
1062                 $parameters["screen_name"] = $screen_name;
1063
1064         if ($user_id != "")
1065                 $parameters["user_id"] = $user_id;
1066
1067         // Fetching user data
1068         $user = $cb->users_show($parameters);
1069
1070         if (!is_object($user))
1071                 return;
1072
1073         $contact_id = twitter_fetch_contact($uid, $user, true);
1074
1075         return $contact_id;
1076 }
1077
1078 function twitter_expand_entities($a, $body, $item, $no_tags = false, $picture) {
1079         require_once("include/oembed.php");
1080         require_once("include/network.php");
1081
1082         $tags = "";
1083
1084         if (isset($item->entities->urls)) {
1085                 $type = "";
1086                 $footerurl = "";
1087                 $footerlink = "";
1088                 $footer = "";
1089
1090                 foreach ($item->entities->urls AS $url) {
1091                         if ($url->url AND $url->expanded_url AND $url->display_url) {
1092
1093                                 $expanded_url = original_url($url->expanded_url);
1094
1095                                 $oembed_data = oembed_fetch_url($expanded_url);
1096
1097                                 // Quickfix: Workaround for URL with "[" and "]" in it
1098                                 if (strpos($expanded_url, "[") OR strpos($expanded_url, "]"))
1099                                         $expanded_url = $url->url;
1100
1101                                 if ($type == "")
1102                                         $type = $oembed_data->type;
1103
1104                                 if ($oembed_data->type == "video") {
1105                                         //$body = str_replace($url->url,
1106                                         //              "[video]".$expanded_url."[/video]", $body);
1107                                         //$dontincludemedia = true;
1108                                         $type = $oembed_data->type;
1109                                         $footerurl = $expanded_url;
1110                                         $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]";
1111
1112                                         $body = str_replace($url->url, $footerlink, $body);
1113                                 //} elseif (($oembed_data->type == "photo") AND isset($oembed_data->url) AND !$dontincludemedia) {
1114                                 } elseif (($oembed_data->type == "photo") AND isset($oembed_data->url)) {
1115                                         $body = str_replace($url->url,
1116                                                         "[url=".$expanded_url."][img]".$oembed_data->url."[/img][/url]",
1117                                                         $body);
1118                                         //$dontincludemedia = true;
1119                                 } elseif ($oembed_data->type != "link")
1120                                         $body = str_replace($url->url,
1121                                                         "[url=".$expanded_url."]".$expanded_url."[/url]",
1122                                                         $body);
1123                                 else {
1124                                         $img_str = fetch_url($expanded_url, true, $redirects, 4);
1125
1126                                         $tempfile = tempnam(get_temppath(), "cache");
1127                                         file_put_contents($tempfile, $img_str);
1128                                         $mime = image_type_to_mime_type(exif_imagetype($tempfile));
1129                                         unlink($tempfile);
1130
1131                                         if (substr($mime, 0, 6) == "image/") {
1132                                                 $type = "photo";
1133                                                 $body = str_replace($url->url, "[img]".$expanded_url."[/img]", $body);
1134                                                 //$dontincludemedia = true;
1135                                         } else {
1136                                                 $type = $oembed_data->type;
1137                                                 $footerurl = $expanded_url;
1138                                                 $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]";
1139
1140                                                 $body = str_replace($url->url, $footerlink, $body);
1141                                         }
1142                                 }
1143                         }
1144                 }
1145
1146                 if ($footerurl != "")
1147                         $footer = add_page_info($footerurl, false, $picture);
1148
1149                 if (($footerlink != "") AND (trim($footer) != "")) {
1150                         $removedlink = trim(str_replace($footerlink, "", $body));
1151
1152                         if (($removedlink == "") OR strstr($body, $removedlink))
1153                                 $body = $removedlink;
1154
1155                         $body .= $footer;
1156                 }
1157
1158                 if (($footer == "") AND ($picture != ""))
1159                         $body .= "\n\n[img]".$picture."[/img]\n";
1160
1161                 if ($no_tags)
1162                         return(array("body" => $body, "tags" => ""));
1163
1164                 $tags_arr = array();
1165
1166                 foreach ($item->entities->hashtags AS $hashtag) {
1167                         $url = "#[url=".$a->get_baseurl()."/search?tag=".rawurlencode($hashtag->text)."]".$hashtag->text."[/url]";
1168                         $tags_arr["#".$hashtag->text] = $url;
1169                         $body = str_replace("#".$hashtag->text, $url, $body);
1170                 }
1171
1172                 foreach ($item->entities->user_mentions AS $mention) {
1173                         $url = "@[url=https://twitter.com/".rawurlencode($mention->screen_name)."]".$mention->screen_name."[/url]";
1174                         $tags_arr["@".$mention->screen_name] = $url;
1175                         $body = str_replace("@".$mention->screen_name, $url, $body);
1176                 }
1177
1178                 // it seems as if the entities aren't always covering all mentions. So the rest will be checked here
1179                 $tags = get_tags($body);
1180
1181                 if(count($tags)) {
1182                         foreach($tags as $tag) {
1183                                 if (strstr(trim($tag), " "))
1184                                         continue;
1185
1186                                 if(strpos($tag,'#') === 0) {
1187                                         if(strpos($tag,'[url='))
1188                                                 continue;
1189
1190                                         // don't link tags that are already embedded in links
1191
1192                                         if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body))
1193                                                 continue;
1194                                         if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body))
1195                                                 continue;
1196
1197                                         $basetag = str_replace('_',' ',substr($tag,1));
1198                                         $url = '#[url='.$a->get_baseurl().'/search?tag='.rawurlencode($basetag).']'.$basetag.'[/url]';
1199                                         $body = str_replace($tag,$url,$body);
1200                                         $tags_arr["#".$basetag] = $url;
1201                                         continue;
1202                                 } elseif(strpos($tag,'@') === 0) {
1203                                         if(strpos($tag,'[url='))
1204                                                 continue;
1205
1206                                         $basetag = substr($tag,1);
1207                                         $url = '@[url=https://twitter.com/'.rawurlencode($basetag).']'.$basetag.'[/url]';
1208                                         $body = str_replace($tag,$url,$body);
1209                                         $tags_arr["@".$basetag] = $url;
1210                                 }
1211                         }
1212                 }
1213
1214
1215                 $tags = implode($tags_arr, ",");
1216
1217         }
1218         return(array("body" => $body, "tags" => $tags));
1219 }
1220
1221 function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing_contact) {
1222
1223         $has_picture = false;
1224
1225         $postarray = array();
1226         $postarray['network'] = NETWORK_TWITTER;
1227         $postarray['gravity'] = 0;
1228         $postarray['uid'] = $uid;
1229         $postarray['wall'] = 0;
1230         $postarray['uri'] = "twitter::".$post->id_str;
1231
1232         $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1",
1233                         dbesc($postarray['uri']),
1234                         intval($uid)
1235                 );
1236
1237         if (count($r))
1238                 return(array());
1239
1240         $contactid = 0;
1241
1242         if ($post->in_reply_to_status_id_str != "") {
1243
1244                 $parent = "twitter::".$post->in_reply_to_status_id_str;
1245
1246                 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
1247                                 dbesc($parent),
1248                                 intval($uid)
1249                         );
1250                 if (count($r)) {
1251                         $postarray['thr-parent'] = $r[0]["uri"];
1252                         $postarray['parent-uri'] = $r[0]["parent-uri"];
1253                         $postarray['parent'] = $r[0]["parent"];
1254                         $postarray['object-type'] = ACTIVITY_OBJ_COMMENT;
1255                 } else {
1256                         $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1",
1257                                         dbesc($parent),
1258                                         intval($uid)
1259                                 );
1260                         if (count($r)) {
1261                                 $postarray['thr-parent'] = $r[0]['uri'];
1262                                 $postarray['parent-uri'] = $r[0]['parent-uri'];
1263                                 $postarray['parent'] = $r[0]['parent'];
1264                                 $postarray['object-type'] = ACTIVITY_OBJ_COMMENT;
1265                         } else {
1266                                 $postarray['thr-parent'] = $postarray['uri'];
1267                                 $postarray['parent-uri'] = $postarray['uri'];
1268                                 $postarray['object-type'] = ACTIVITY_OBJ_NOTE;
1269                         }
1270                 }
1271
1272                 // Is it me?
1273                 $own_id = get_pconfig($uid, 'twitter', 'own_id');
1274
1275                 if ($post->user->id_str == $own_id) {
1276                         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1277                                 intval($uid));
1278
1279                         if(count($r)) {
1280                                 $contactid = $r[0]["id"];
1281
1282                                 $postarray['owner-name'] =  $r[0]["name"];
1283                                 $postarray['owner-link'] = $r[0]["url"];
1284                                 $postarray['owner-avatar'] =  $r[0]["photo"];
1285                         } else
1286                                 return(array());
1287                 }
1288                 // Don't create accounts of people who just comment something
1289                 $create_user = false;
1290         } else {
1291                 $postarray['parent-uri'] = $postarray['uri'];
1292                 $postarray['object-type'] = ACTIVITY_OBJ_NOTE;
1293         }
1294
1295         if ($contactid == 0) {
1296                 $contactid = twitter_fetch_contact($uid, $post->user, $create_user);
1297
1298                 $postarray['owner-name'] = $post->user->name;
1299                 $postarray['owner-link'] = "https://twitter.com/".$post->user->screen_name;
1300                 $postarray['owner-avatar'] = $post->user->profile_image_url_https;
1301         }
1302
1303         if(($contactid == 0) AND !$only_existing_contact)
1304                 $contactid = $self['id'];
1305         elseif ($contactid <= 0)
1306                 return(array());
1307
1308         $postarray['contact-id'] = $contactid;
1309
1310         $postarray['verb'] = ACTIVITY_POST;
1311         $postarray['author-name'] = $postarray['owner-name'];
1312         $postarray['author-link'] = $postarray['owner-link'];
1313         $postarray['author-avatar'] = $postarray['owner-avatar'];
1314         $postarray['plink'] = "https://twitter.com/".$post->user->screen_name."/status/".$post->id_str;
1315         $postarray['app'] = strip_tags($post->source);
1316
1317         if ($post->user->protected) {
1318                 $postarray['private'] = 1;
1319                 $postarray['allow_cid'] = '<' . $self['id'] . '>';
1320         }
1321
1322         $postarray['body'] = $post->text;
1323
1324         $picture = "";
1325
1326         // media
1327         if (is_array($post->entities->media)) {
1328                 foreach($post->entities->media AS $media) {
1329                         switch($media->type) {
1330                                 case 'photo':
1331                                         //$postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']);
1332                                         //$has_picture = true;
1333                                         $postarray['body'] = str_replace($media->url, "", $postarray['body']);
1334                                         $postarray['object-type'] = ACTIVITY_OBJ_IMAGE;
1335                                         $picture = $media->media_url_https;
1336                                         break;
1337                                 default:
1338                                         $postarray['body'] .= print_r($media, true);
1339                         }
1340                 }
1341         }
1342
1343         $converted = twitter_expand_entities($a, $postarray['body'], $post, false, $picture);
1344         $postarray['body'] = $converted["body"];
1345         $postarray['tag'] = $converted["tags"];
1346
1347         $postarray['created'] = datetime_convert('UTC','UTC',$post->created_at);
1348         $postarray['edited'] = datetime_convert('UTC','UTC',$post->created_at);
1349
1350         if (is_string($post->place->name))
1351                 $postarray["location"] = $post->place->name;
1352
1353         if (is_string($post->place->full_name))
1354                 $postarray["location"] = $post->place->full_name;
1355
1356         if (is_array($post->geo->coordinates))
1357                 $postarray["coord"] = $post->geo->coordinates[0]." ".$post->geo->coordinates[1];
1358
1359         if (is_array($post->coordinates->coordinates))
1360                 $postarray["coord"] = $post->coordinates->coordinates[1]." ".$post->coordinates->coordinates[0];
1361
1362         if (is_object($post->retweeted_status)) {
1363
1364                 $postarray['body'] = $post->retweeted_status->text;
1365
1366                 $picture = "";
1367
1368                 // media
1369                 if (is_array($post->retweeted_status->entities->media)) {
1370                         foreach($post->retweeted_status->entities->media AS $media) {
1371                                 switch($media->type) {
1372                                         case 'photo':
1373                                                 //$postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']);
1374                                                 //$has_picture = true;
1375                                                 $postarray['body'] = str_replace($media->url, "", $postarray['body']);
1376                                                 $postarray['object-type'] = ACTIVITY_OBJ_IMAGE;
1377                                                 $picture = $media->media_url_https;
1378                                                 break;
1379                                         default:
1380                                                 $postarray['body'] .= print_r($media, true);
1381                                 }
1382                         }
1383                 }
1384
1385                 $converted = twitter_expand_entities($a, $postarray['body'], $post->retweeted_status, false, $picture);
1386                 $postarray['body'] = $converted["body"];
1387                 $postarray['tag'] = $converted["tags"];
1388
1389                 twitter_fetch_contact($uid, $post->retweeted_status->user, false);
1390
1391                 // Deactivated at the moment, since there are problems with answers to retweets
1392                 if (false AND !intval(get_config('system','wall-to-wall_share'))) {
1393                         $postarray['body'] = "[share author='".$post->retweeted_status->user->name.
1394                                 "' profile='https://twitter.com/".$post->retweeted_status->user->screen_name.
1395                                 "' avatar='".$post->retweeted_status->user->profile_image_url_https.
1396                                 "' link='https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str."']".
1397                                 $postarray['body'];
1398                         $postarray['body'] .= "[/share]";
1399                 } else {
1400                         // Let retweets look like wall-to-wall posts
1401                         $postarray['author-name'] = $post->retweeted_status->user->name;
1402                         $postarray['author-link'] = "https://twitter.com/".$post->retweeted_status->user->screen_name;
1403                         $postarray['author-avatar'] = $post->retweeted_status->user->profile_image_url_https;
1404                         //if (($post->retweeted_status->user->screen_name != "") AND ($post->retweeted_status->id_str != "")) {
1405                         //      $postarray['plink'] = "https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str;
1406                         //      $postarray['uri'] = "twitter::".$post->retweeted_status->id_str;
1407                         //}
1408                 }
1409
1410         }
1411         return($postarray);
1412 }
1413
1414 function twitter_checknotification($a, $uid, $own_id, $top_item, $postarray) {
1415
1416         // this whole function doesn't seem to work. Needs complete check
1417
1418         $user = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1",
1419                         intval($uid)
1420                 );
1421
1422         if(!count($user))
1423                 return;
1424
1425         // Is it me?
1426         if (link_compare($user[0]["url"], $postarray['author-link']))
1427                 return;
1428
1429         $own_user = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
1430                         intval($uid),
1431                         dbesc("twitter::".$own_id)
1432                 );
1433
1434         if(!count($own_user))
1435                 return;
1436
1437         // Is it me from twitter?
1438         if (link_compare($own_user[0]["url"], $postarray['author-link']))
1439                 return;
1440
1441         $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0",
1442                         dbesc($postarray['parent-uri']),
1443                         intval($uid)
1444                         );
1445
1446         if(count($myconv)) {
1447
1448                 foreach($myconv as $conv) {
1449                         // now if we find a match, it means we're in this conversation
1450
1451                         if(!link_compare($conv['author-link'],$user[0]["url"]) AND !link_compare($conv['author-link'],$own_user[0]["url"]))
1452                                 continue;
1453
1454                         require_once('include/enotify.php');
1455
1456                         $conv_parent = $conv['parent'];
1457
1458                         notification(array(
1459                                 'type'         => NOTIFY_COMMENT,
1460                                 'notify_flags' => $user[0]['notify-flags'],
1461                                 'language'     => $user[0]['language'],
1462                                 'to_name'      => $user[0]['username'],
1463                                 'to_email'     => $user[0]['email'],
1464                                 'uid'          => $user[0]['uid'],
1465                                 'item'         => $postarray,
1466                                 'link'         => $a->get_baseurl().'/display/'.urlencode(get_item_guid($top_item)),
1467                                 'source_name'  => $postarray['author-name'],
1468                                 'source_link'  => $postarray['author-link'],
1469                                 'source_photo' => $postarray['author-avatar'],
1470                                 'verb'         => ACTIVITY_POST,
1471                                 'otype'        => 'item',
1472                                 'parent'       => $conv_parent,
1473                         ));
1474
1475                         // only send one notification
1476                         break;
1477                 }
1478         }
1479 }
1480
1481 function twitter_fetchhometimeline($a, $uid) {
1482         $ckey    = get_config('twitter', 'consumerkey');
1483         $csecret = get_config('twitter', 'consumersecret');
1484         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1485         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1486         $create_user = get_pconfig($uid, 'twitter', 'create_user');
1487
1488         logger("twitter_fetchhometimeline: Fetching for user ".$uid, LOGGER_DEBUG);
1489
1490         require_once('library/twitteroauth.php');
1491         require_once('include/items.php');
1492
1493         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1494
1495         $own_contact = twitter_fetch_own_contact($a, $uid);
1496
1497         $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
1498                 intval($own_contact),
1499                 intval($uid));
1500
1501         if(count($r)) {
1502                 $own_id = $r[0]["nick"];
1503         } else {
1504                 logger("twitter_fetchhometimeline: Own twitter contact not found for user ".$uid, LOGGER_DEBUG);
1505                 return;
1506         }
1507
1508         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1509                 intval($uid));
1510
1511         if(count($r)) {
1512                 $self = $r[0];
1513         } else {
1514                 logger("twitter_fetchhometimeline: Own contact not found for user ".$uid, LOGGER_DEBUG);
1515                 return;
1516         }
1517
1518         $u = q("SELECT * FROM user WHERE uid = %d LIMIT 1",
1519                 intval($uid));
1520         if(!count($u)) {
1521                 logger("twitter_fetchhometimeline: Own user not found for user ".$uid, LOGGER_DEBUG);
1522                 return;
1523         }
1524
1525         $parameters = array("exclude_replies" => false, "trim_user" => false, "contributor_details" => true, "include_rts" => true);
1526         //$parameters["count"] = 200;
1527
1528
1529         // Fetching timeline
1530         $lastid  = get_pconfig($uid, 'twitter', 'lasthometimelineid');
1531
1532         $first_time = ($lastid == "");
1533
1534         if ($lastid <> "")
1535                 $parameters["since_id"] = $lastid;
1536
1537         $items = $connection->get('statuses/home_timeline', $parameters);
1538
1539         if (!is_array($items)) {
1540                 logger("twitter_fetchhometimeline: Error fetching home timeline: ".print_r($items, true), LOGGER_DEBUG);
1541                 return;
1542         }
1543
1544         $posts = array_reverse($items);
1545
1546         logger("twitter_fetchhometimeline: Fetching timeline for user ".$uid." ".sizeof($posts)." items", LOGGER_DEBUG);
1547
1548         if (count($posts)) {
1549                 foreach ($posts as $post) {
1550                         if ($post->id_str > $lastid)
1551                                 $lastid = $post->id_str;
1552
1553                         if ($first_time)
1554                                 continue;
1555
1556                         $postarray = twitter_createpost($a, $uid, $post, $self, $create_user, true);
1557
1558                         if (trim($postarray['body']) == "")
1559                                 continue;
1560
1561                         $item = item_store($postarray);
1562
1563                         logger('twitter_fetchhometimeline: User '.$self["nick"].' posted home timeline item '.$item);
1564
1565                         if ($item != 0)
1566                                 twitter_checknotification($a, $uid, $own_id, $item, $postarray);
1567
1568                 }
1569         }
1570         set_pconfig($uid, 'twitter', 'lasthometimelineid', $lastid);
1571
1572         // Fetching mentions
1573         $lastid  = get_pconfig($uid, 'twitter', 'lastmentionid');
1574
1575         $first_time = ($lastid == "");
1576
1577         if ($lastid <> "")
1578                 $parameters["since_id"] = $lastid;
1579
1580         $items = $connection->get('statuses/mentions_timeline', $parameters);
1581
1582         if (!is_array($items)) {
1583                 logger("twitter_fetchhometimeline: Error fetching mentions: ".print_r($items, true), LOGGER_DEBUG);
1584                 return;
1585         }
1586
1587         $posts = array_reverse($items);
1588
1589         logger("twitter_fetchhometimeline: Fetching mentions for user ".$uid." ".sizeof($posts)." items", LOGGER_DEBUG);
1590
1591         if (count($posts)) {
1592                 foreach ($posts as $post) {
1593                         if ($post->id_str > $lastid)
1594                                 $lastid = $post->id_str;
1595
1596                         if ($first_time)
1597                                 continue;
1598
1599                         $postarray = twitter_createpost($a, $uid, $post, $self, false, false);
1600
1601                         if (trim($postarray['body']) == "")
1602                                 continue;
1603
1604                         $item = item_store($postarray);
1605
1606                         if (!isset($postarray["parent"]) OR ($postarray["parent"] == 0))
1607                                 $postarray["parent"] = $item;
1608
1609                         logger('twitter_fetchhometimeline: User '.$self["nick"].' posted mention timeline item '.$item);
1610
1611                         if ($item == 0) {
1612                                 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
1613                                         dbesc($postarray['uri']),
1614                                         intval($uid)
1615                                 );
1616                                 if (count($r)) {
1617                                         $item = $r[0]['id'];
1618                                         $parent_id = $r[0]['parent'];
1619                                 }
1620                         } else
1621                                 $parent_id = $postarray['parent'];
1622
1623                         if ($item != 0) {
1624                                 require_once('include/enotify.php');
1625                                 notification(array(
1626                                         'type'         => NOTIFY_TAGSELF,
1627                                         'notify_flags' => $u[0]['notify-flags'],
1628                                         'language'     => $u[0]['language'],
1629                                         'to_name'      => $u[0]['username'],
1630                                         'to_email'     => $u[0]['email'],
1631                                         'uid'          => $u[0]['uid'],
1632                                         'item'         => $postarray,
1633                                         'link'         => $a->get_baseurl().'/display/'.urlencode(get_item_guid($item)),
1634                                         'source_name'  => $postarray['author-name'],
1635                                         'source_link'  => $postarray['author-link'],
1636                                         'source_photo' => $postarray['author-avatar'],
1637                                         'verb'         => ACTIVITY_TAG,
1638                                         'otype'        => 'item',
1639                                         'parent'       => $parent_id
1640                                 ));
1641                         }
1642                 }
1643         }
1644
1645         set_pconfig($uid, 'twitter', 'lastmentionid', $lastid);
1646 }
1647
1648 function twitter_fetch_own_contact($a, $uid) {
1649         $ckey    = get_config('twitter', 'consumerkey');
1650         $csecret = get_config('twitter', 'consumersecret');
1651         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1652         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1653
1654         $own_id = get_pconfig($uid, 'twitter', 'own_id');
1655
1656         $contact_id = 0;
1657
1658         if ($own_id == "") {
1659                 require_once('library/twitteroauth.php');
1660
1661                 $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1662
1663                 // Fetching user data
1664                 $user = $connection->get('account/verify_credentials');
1665
1666                 set_pconfig($uid, 'twitter', 'own_id', $user->id_str);
1667
1668                 $contact_id = twitter_fetch_contact($uid, $user, true);
1669
1670         } else {
1671                 $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
1672                         intval($uid), dbesc("twitter::".$own_id));
1673                 if(count($r))
1674                         $contact_id = $r[0]["id"];
1675                 else
1676                         del_pconfig($uid, 'twitter', 'own_id');
1677
1678         }
1679
1680         return($contact_id);
1681 }
1682
1683 function twitter_is_retweet($a, $uid, $body) {
1684         $body = trim($body);
1685
1686         // Skip if it isn't a pure repeated messages
1687         // Does it start with a share?
1688         if (strpos($body, "[share") > 0)
1689                 return(false);
1690
1691         // Does it end with a share?
1692         if (strlen($body) > (strrpos($body, "[/share]") + 8))
1693                 return(false);
1694
1695         $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
1696         // Skip if there is no shared message in there
1697         if ($body == $attributes)
1698                 return(false);
1699
1700         $link = "";
1701         preg_match("/link='(.*?)'/ism", $attributes, $matches);
1702         if ($matches[1] != "")
1703                 $link = $matches[1];
1704
1705         preg_match('/link="(.*?)"/ism', $attributes, $matches);
1706         if ($matches[1] != "")
1707                 $link = $matches[1];
1708
1709         $id = preg_replace("=https?://twitter.com/(.*)/status/(.*)=ism", "$2", $link);
1710         if ($id == $link)
1711                 return(false);
1712
1713         logger('twitter_is_retweet: Retweeting id '.$id.' for user '.$uid, LOGGER_DEBUG);
1714
1715         $ckey    = get_config('twitter', 'consumerkey');
1716         $csecret = get_config('twitter', 'consumersecret');
1717         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1718         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1719
1720         require_once('library/twitteroauth.php');
1721         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1722
1723         $result = $connection->post('statuses/retweet/'.$id);
1724
1725         logger('twitter_is_retweet: result '.print_r($result, true), LOGGER_DEBUG);
1726
1727         return(!isset($result->errors));
1728 }
1729 ?>