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