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