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