]> git.mxchange.org Git - friendica-addons.git/blob - twitter/twitter.php
Merge pull request #255 from annando/1502-pledgie-deactivated
[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
510                         if ($result->source)
511                                 set_config("twitter", "application_name", strip_tags($result->source));
512
513                         if ($result->errors OR $result->error) {
514                                 logger('Send to Twitter failed: "' . print_r($result->errors, true) . '"');
515
516                                 // Workaround: Remove the picture link so that the post can be reposted without it
517                                 $msg .= " ".$image;
518                                 $image = "";
519                         } elseif ($iscomment) {
520                                 logger('twitter_post: Update extid '.$result->id_str." for post id ".$b['id']);
521                                 q("UPDATE `item` SET `extid` = '%s', `body` = '%s' WHERE `id` = %d",
522                                         dbesc("twitter::".$result->id_str),
523                                         dbesc($result->text),
524                                         intval($b['id'])
525                                 );
526                         }
527                 }
528
529                 if(strlen($msg) and ($image == "")) {
530                         $url = 'statuses/update';
531                         $post = array('status' => $msg);
532
533                         if ($iscomment)
534                                 $post["in_reply_to_status_id"] = substr($orig_post["uri"], 9);
535
536                         $result = $tweet->post($url, $post);
537                         logger('twitter_post send, result: ' . print_r($result, true), LOGGER_DEBUG);
538
539                         if ($result->source)
540                                 set_config("twitter", "application_name", strip_tags($result->source));
541
542                         if ($result->errors) {
543                                 logger('Send to Twitter failed: "' . print_r($result->errors, true) . '"');
544
545                                 $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($b['uid']));
546                                 if (count($r))
547                                         $a->contact = $r[0]["id"];
548
549                                 $s = serialize(array('url' => $url, 'item' => $b['id'], 'post' => $post));
550                                 require_once('include/queue_fn.php');
551                                 add_to_queue($a->contact,NETWORK_TWITTER,$s);
552                                 notice(t('Twitter post failed. Queued for retry.').EOL);
553                         } elseif ($iscomment) {
554                                 logger('twitter_post: Update extid '.$result->id_str." for post id ".$b['id']);
555                                 q("UPDATE `item` SET `extid` = '%s' WHERE `id` = %d",
556                                         dbesc("twitter::".$result->id_str),
557                                         intval($b['id'])
558                                 );
559                                 //q("UPDATE `item` SET `extid` = '%s', `body` = '%s' WHERE `id` = %d",
560                                 //      dbesc("twitter::".$result->id_str),
561                                 //      dbesc($result->text),
562                                 //      intval($b['id'])
563                                 //);
564                         }
565                 }
566         }
567 }
568
569 function twitter_plugin_admin_post(&$a){
570         $consumerkey    =       ((x($_POST,'consumerkey'))              ? notags(trim($_POST['consumerkey']))   : '');
571         $consumersecret =       ((x($_POST,'consumersecret'))   ? notags(trim($_POST['consumersecret'])): '');
572         $applicationname = ((x($_POST, 'applicationname')) ? notags(trim($_POST['applicationname'])):'');
573         set_config('twitter','consumerkey',$consumerkey);
574         set_config('twitter','consumersecret',$consumersecret);
575         //set_config('twitter','application_name',$applicationname);
576         info( t('Settings updated.'). EOL );
577 }
578 function twitter_plugin_admin(&$a, &$o){
579         $t = get_markup_template( "admin.tpl", "addon/twitter/" );
580
581         $o = replace_macros($t, array(
582                 '$submit' => t('Save Settings'),
583                                                                 // name, label, value, help, [extra values]
584                 '$consumerkey' => array('consumerkey', t('Consumer key'),  get_config('twitter', 'consumerkey' ), ''),
585                 '$consumersecret' => array('consumersecret', t('Consumer secret'),  get_config('twitter', 'consumersecret' ), ''),
586                 //'$applicationname' => array('applicationname', t('Name of the Twitter Application'), get_config('twitter','application_name'),t('Set this to the exact name you gave the app on twitter.com/apps to avoid mirroring postings from ~friendica back to ~friendica'))
587         ));
588 }
589
590 function twitter_cron($a,$b) {
591         $last = get_config('twitter','last_poll');
592
593         $poll_interval = intval(get_config('twitter','poll_interval'));
594         if(! $poll_interval)
595                 $poll_interval = TWITTER_DEFAULT_POLL_INTERVAL;
596
597         if($last) {
598                 $next = $last + ($poll_interval * 60);
599                 if($next > time()) {
600                         logger('twitter: poll intervall not reached');
601                         return;
602                 }
603         }
604         logger('twitter: cron_start');
605
606         $r = q("SELECT * FROM `pconfig` WHERE `cat` = 'twitter' AND `k` = 'mirror_posts' AND `v` = '1' ORDER BY RAND()");
607         if(count($r)) {
608                 foreach($r as $rr) {
609                         logger('twitter: fetching for user '.$rr['uid']);
610                         twitter_fetchtimeline($a, $rr['uid']);
611                 }
612         }
613
614         $abandon_days = intval(get_config('system','account_abandon_days'));
615         if ($abandon_days < 1)
616                 $abandon_days = 0;
617
618         $abandon_limit = date("Y-m-d H:i:s", time() - $abandon_days * 86400);
619
620         $r = q("SELECT * FROM `pconfig` WHERE `cat` = 'twitter' AND `k` = 'import' AND `v` = '1' ORDER BY RAND()");
621         if(count($r)) {
622                 foreach($r as $rr) {
623                         if ($abandon_days != 0) {
624                                 $user = q("SELECT `login_date` FROM `user` WHERE uid=%d AND `login_date` >= '%s'", $rr['uid'], $abandon_limit);
625                                 if (!count($user)) {
626                                         logger('abandoned account: timeline from user '.$rr['uid'].' will not be imported');
627                                         continue;
628                                 }
629                         }
630
631                         logger('twitter: importing timeline from user '.$rr['uid']);
632                         twitter_fetchhometimeline($a, $rr["uid"]);
633
634 /*
635                         // To-Do
636                         // check for new contacts once a day
637                         $last_contact_check = get_pconfig($rr['uid'],'pumpio','contact_check');
638                         if($last_contact_check)
639                                 $next_contact_check = $last_contact_check + 86400;
640                         else
641                                 $next_contact_check = 0;
642
643                         if($next_contact_check <= time()) {
644                                 pumpio_getallusers($a, $rr["uid"]);
645                                 set_pconfig($rr['uid'],'pumpio','contact_check',time());
646                         }
647 */
648
649                 }
650         }
651
652         logger('twitter: cron_end');
653
654         set_config('twitter','last_poll', time());
655 }
656
657 function twitter_expire($a,$b) {
658
659         $days = get_config('twitter', 'expire');
660
661         if ($days == 0)
662                 return;
663
664         $r = q("DELETE FROM `item` WHERE `deleted` AND `network` = '%s'", dbesc(NETWORK_TWITTER));
665
666         require_once("include/items.php");
667
668         logger('twitter_expire: expire_start');
669
670         $r = q("SELECT * FROM `pconfig` WHERE `cat` = 'twitter' AND `k` = 'import' AND `v` = '1' ORDER BY RAND()");
671         if(count($r)) {
672                 foreach($r as $rr) {
673                         logger('twitter_expire: user '.$rr['uid']);
674                         item_expire($rr['uid'], $days, NETWORK_TWITTER, true);
675                 }
676         }
677
678         logger('twitter_expire: expire_end');
679 }
680
681 function twitter_prepare_body(&$a,&$b) {
682         if ($b["item"]["network"] != NETWORK_TWITTER)
683                 return;
684
685         if ($b["preview"]) {
686                 $max_char = 140;
687                 require_once("include/plaintext.php");
688                 $item = $b["item"];
689                 $item["plink"] = $a->get_baseurl()."/display/".$a->user["nickname"]."/".$item["parent"];
690
691                 $r = q("SELECT `author-link` FROM item WHERE item.uri = '%s' AND item.uid = %d LIMIT 1",
692                         dbesc($item["thr-parent"]),
693                         intval(local_user()));
694
695                 if(count($r)) {
696                         $orig_post = $r[0];
697
698                         $nicknameplain = preg_replace("=https?://twitter.com/(.*)=ism", "$1", $orig_post["author-link"]);
699                         $nickname = "@[url=".$orig_post["author-link"]."]".$nicknameplain."[/url]";
700                         $nicknameplain = "@".$nicknameplain;
701
702                         if ((strpos($item["body"], $nickname) === false) AND (strpos($item["body"], $nicknameplain) === false))
703                                 $item["body"] = $nickname." ".$item["body"];
704                 }
705
706
707                 $msgarr = plaintext($a, $item, $max_char, true, 8);
708                 $msg = $msgarr["text"];
709
710                 if (isset($msgarr["url"]))
711                         $msg .= " ".$msgarr["url"];
712
713                 if (isset($msgarr["image"]))
714                         $msg .= " ".$msgarr["image"];
715
716                 $b['html'] = nl2br(htmlspecialchars($msg));
717         }
718 }
719
720 function twitter_fetchtimeline($a, $uid) {
721         $ckey    = get_config('twitter', 'consumerkey');
722         $csecret = get_config('twitter', 'consumersecret');
723         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
724         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
725         $lastid  = get_pconfig($uid, 'twitter', 'lastid');
726
727         $application_name  = get_config('twitter', 'application_name');
728
729         if ($application_name == "")
730                 $application_name = $a->get_hostname();
731
732         $has_picture = false;
733
734         require_once('mod/item.php');
735         require_once('include/items.php');
736
737         require_once('library/twitteroauth.php');
738         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
739
740         $parameters = array("exclude_replies" => true, "trim_user" => false, "contributor_details" => true, "include_rts" => true);
741
742         $first_time = ($lastid == "");
743
744         if ($lastid <> "")
745                 $parameters["since_id"] = $lastid;
746
747         $items = $connection->get('statuses/user_timeline', $parameters);
748
749         if (!is_array($items))
750                 return;
751
752         $posts = array_reverse($items);
753
754         if (count($posts)) {
755             foreach ($posts as $post) {
756                 if ($post->id_str > $lastid)
757                         $lastid = $post->id_str;
758
759                 if ($first_time)
760                         continue;
761
762                 if (!stristr($post->source, $application_name)) {
763                         $_SESSION["authenticated"] = true;
764                         $_SESSION["uid"] = $uid;
765
766                         unset($_REQUEST);
767                         $_REQUEST["type"] = "wall";
768                         $_REQUEST["api_source"] = true;
769                         $_REQUEST["profile_uid"] = $uid;
770                         //$_REQUEST["source"] = "Twitter";
771                         $_REQUEST["source"] = $post->source;
772                         $_REQUEST["extid"] = NETWORK_TWITTER;
773
774                         //$_REQUEST["date"] = $post->created_at;
775
776                         $_REQUEST["title"] = "";
777
778                         if (is_object($post->retweeted_status)) {
779
780                                 $_REQUEST['body'] = $post->retweeted_status->text;
781
782                                 $picture = "";
783
784                                 // media
785                                 if (is_array($post->retweeted_status->entities->media)) {
786                                         foreach($post->retweeted_status->entities->media AS $media) {
787                                                 switch($media->type) {
788                                                         case 'photo':
789                                                                 //$_REQUEST['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $_REQUEST['body']);
790                                                                 //$has_picture = true;
791                                                                 $_REQUEST['body'] = str_replace($media->url, "", $_REQUEST['body']);
792                                                                 $picture = $media->media_url_https;
793                                                                 break;
794                                                 }
795                                         }
796                                 }
797
798                                 $converted = twitter_expand_entities($a, $_REQUEST['body'], $post->retweeted_status, true, $picture);
799                                 $_REQUEST['body'] = $converted["body"];
800
801                                 $_REQUEST['body'] = "[share author='".$post->retweeted_status->user->name.
802                                         "' profile='https://twitter.com/".$post->retweeted_status->user->screen_name.
803                                         "' avatar='".$post->retweeted_status->user->profile_image_url_https.
804                                         "' link='https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str."']".
805                                         $_REQUEST['body'];
806                                 $_REQUEST['body'] .= "[/share]";
807                         } else {
808                                 $_REQUEST["body"] = $post->text;
809
810                                 $picture = "";
811
812                                 if (is_array($post->entities->media)) {
813                                         foreach($post->entities->media AS $media) {
814                                                 switch($media->type) {
815                                                         case 'photo':
816                                                                 //$_REQUEST['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $_REQUEST['body']);
817                                                                 //$has_picture = true;
818                                                                 $_REQUEST['body'] = str_replace($media->url, "", $_REQUEST['body']);
819                                                                 $picture = $media->media_url_https;
820                                                                 break;
821                                                 }
822                                         }
823                                 }
824
825                                 $converted = twitter_expand_entities($a, $_REQUEST["body"], $post, true, $picture);
826                                 $_REQUEST['body'] = $converted["body"];
827                         }
828
829                         if (is_string($post->place->name))
830                                 $_REQUEST["location"] = $post->place->name;
831
832                         if (is_string($post->place->full_name))
833                                 $_REQUEST["location"] = $post->place->full_name;
834
835                         if (is_array($post->geo->coordinates))
836                                 $_REQUEST["coord"] = $post->geo->coordinates[0]." ".$post->geo->coordinates[1];
837
838                         if (is_array($post->coordinates->coordinates))
839                                 $_REQUEST["coord"] = $post->coordinates->coordinates[1]." ".$post->coordinates->coordinates[0];
840
841                         //print_r($_REQUEST);
842                         logger('twitter: posting for user '.$uid);
843
844 //                      require_once('mod/item.php');
845
846                         item_post($a);
847                 }
848             }
849         }
850         set_pconfig($uid, 'twitter', 'lastid', $lastid);
851 }
852
853 function twitter_queue_hook(&$a,&$b) {
854
855         $qi = q("SELECT * FROM `queue` WHERE `network` = '%s'",
856                 dbesc(NETWORK_TWITTER)
857                 );
858         if(! count($qi))
859                 return;
860
861         require_once('include/queue_fn.php');
862
863         foreach($qi as $x) {
864                 if($x['network'] !== NETWORK_TWITTER)
865                         continue;
866
867                 logger('twitter_queue: run');
868
869                 $r = q("SELECT `user`.* FROM `user` LEFT JOIN `contact` on `contact`.`uid` = `user`.`uid` 
870                         WHERE `contact`.`self` = 1 AND `contact`.`id` = %d LIMIT 1",
871                         intval($x['cid'])
872                 );
873                 if(! count($r))
874                         continue;
875
876                 $user = $r[0];
877
878                 $ckey    = get_config('twitter', 'consumerkey');
879                 $csecret = get_config('twitter', 'consumersecret');
880                 $otoken  = get_pconfig($user['uid'], 'twitter', 'oauthtoken');
881                 $osecret = get_pconfig($user['uid'], 'twitter', 'oauthsecret');
882
883                 $success = false;
884
885                 if ($ckey AND $csecret AND $otoken AND $osecret) {
886
887                         logger('twitter_queue: able to post');
888
889                         $z = unserialize($x['content']);
890
891                         require_once("addon/twitter/codebird.php");
892
893                         $cb = \Codebird\Codebird::getInstance();
894                         $cb->setConsumerKey($ckey, $csecret);
895                         $cb->setToken($otoken, $osecret);
896
897                         if ($z['url'] == "statuses/update")
898                                 $result = $cb->statuses_update($z['post']);
899
900                         logger('twitter_queue: post result: ' . print_r($result, true), LOGGER_DEBUG);
901
902                         if ($result->errors)
903                                 logger('twitter_queue: Send to Twitter failed: "' . print_r($result->errors, true) . '"');
904                         else {
905                                 $success = true;
906                                 remove_queue_item($x['id']);
907                         }
908                 } else
909                         logger("twitter_queue: Error getting tokens for user ".$user['uid']);
910
911                 if (!$success) {
912                         logger('twitter_queue: delayed');
913                         update_queue_time($x['id']);
914                 }
915         }
916 }
917
918 function twitter_fetch_contact($uid, $contact, $create_user) {
919         require_once("include/Photo.php");
920
921         if ($contact->id_str == "")
922                 return(-1);
923
924         $avatar = str_replace("_normal.", ".", $contact->profile_image_url_https);
925
926         $info = get_photo_info($avatar);
927         if (!$info)
928                 $avatar = $contact->profile_image_url_https;
929
930         // Check if the unique contact is existing
931         // To-Do: only update once a while
932         $r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1",
933                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)));
934
935         if (count($r) == 0)
936                 q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')",
937                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
938                         dbesc($contact->name),
939                         dbesc($contact->screen_name),
940                         dbesc($avatar));
941         else
942                 q("UPDATE unique_contacts SET name = '%s', nick = '%s', avatar = '%s' WHERE url = '%s'",
943                         dbesc($contact->name),
944                         dbesc($contact->screen_name),
945                         dbesc($avatar),
946                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)));
947
948         if (DB_UPDATE_VERSION >= "1177")
949                 q("UPDATE `unique_contacts` SET `location` = '%s', `about` = '%s' WHERE url = '%s'",
950                         dbesc($contact->location),
951                         dbesc($contact->description),
952                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)));
953
954         $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
955                 intval($uid), dbesc("twitter::".$contact->id_str));
956
957         if(!count($r) AND !$create_user)
958                 return(0);
959
960         if (count($r) AND ($r[0]["readonly"] OR $r[0]["blocked"])) {
961                 logger("twitter_fetch_contact: Contact '".$r[0]["nick"]."' is blocked or readonly.", LOGGER_DEBUG);
962                 return(-1);
963         }
964
965         if(!count($r)) {
966                 // create contact record
967                 q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,
968                                         `name`, `nick`, `photo`, `network`, `rel`, `priority`,
969                                         `writable`, `blocked`, `readonly`, `pending` )
970                                         VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0) ",
971                         intval($uid),
972                         dbesc(datetime_convert()),
973                         dbesc("https://twitter.com/".$contact->screen_name),
974                         dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
975                         dbesc($contact->screen_name."@twitter.com"),
976                         dbesc("twitter::".$contact->id_str),
977                         dbesc(''),
978                         dbesc("twitter::".$contact->id_str),
979                         dbesc($contact->name),
980                         dbesc($contact->screen_name),
981                         dbesc($avatar),
982                         dbesc(NETWORK_TWITTER),
983                         intval(CONTACT_IS_FRIEND),
984                         intval(1),
985                         intval(1)
986                 );
987
988                 $r = q("SELECT * FROM `contact` WHERE `alias` = '%s' AND `uid` = %d LIMIT 1",
989                         dbesc("twitter::".$contact->id_str),
990                         intval($uid)
991                         );
992
993                 if(! count($r))
994                         return(false);
995
996                 $contact_id  = $r[0]['id'];
997
998                 $g = q("SELECT def_gid FROM user WHERE uid = %d LIMIT 1",
999                         intval($uid)
1000                 );
1001
1002                 if($g && intval($g[0]['def_gid'])) {
1003                         require_once('include/group.php');
1004                         group_add_member($uid,'',$contact_id,$g[0]['def_gid']);
1005                 }
1006
1007                 require_once("Photo.php");
1008
1009                 $photos = import_profile_photo($avatar,$uid,$contact_id);
1010
1011                 q("UPDATE `contact` SET `photo` = '%s',
1012                                         `thumb` = '%s',
1013                                         `micro` = '%s',
1014                                         `name-date` = '%s',
1015                                         `uri-date` = '%s',
1016                                         `avatar-date` = '%s'
1017                                 WHERE `id` = %d",
1018                         dbesc($photos[0]),
1019                         dbesc($photos[1]),
1020                         dbesc($photos[2]),
1021                         dbesc(datetime_convert()),
1022                         dbesc(datetime_convert()),
1023                         dbesc(datetime_convert()),
1024                         intval($contact_id)
1025                 );
1026
1027                 if (DB_UPDATE_VERSION >= "1177")
1028                         q("UPDATE `contact` SET `location` = '%s',
1029                                                 `about` = '%s'
1030                                         WHERE `id` = %d",
1031                                 dbesc($contact->location),
1032                                 dbesc($contact->description),
1033                                 intval($contact_id)
1034                         );
1035
1036         } else {
1037                 // update profile photos once every two weeks as we have no notification of when they change.
1038
1039                 //$update_photo = (($r[0]['avatar-date'] < datetime_convert('','','now -2 days')) ? true : false);
1040                 $update_photo = ($r[0]['avatar-date'] < datetime_convert('','','now -12 hours'));
1041
1042                 // check that we have all the photos, this has been known to fail on occasion
1043
1044                 if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro']) || ($update_photo)) {
1045
1046                         logger("twitter_fetch_contact: Updating contact ".$contact->screen_name, LOGGER_DEBUG);
1047
1048                         require_once("Photo.php");
1049
1050                         $photos = import_profile_photo($avatar, $uid, $r[0]['id']);
1051
1052                         q("UPDATE `contact` SET `photo` = '%s',
1053                                                 `thumb` = '%s',
1054                                                 `micro` = '%s',
1055                                                 `name-date` = '%s',
1056                                                 `uri-date` = '%s',
1057                                                 `avatar-date` = '%s',
1058                                                 `url` = '%s',
1059                                                 `nurl` = '%s',
1060                                                 `addr` = '%s',
1061                                                 `name` = '%s',
1062                                                 `nick` = '%s'
1063                                         WHERE `id` = %d",
1064                                 dbesc($photos[0]),
1065                                 dbesc($photos[1]),
1066                                 dbesc($photos[2]),
1067                                 dbesc(datetime_convert()),
1068                                 dbesc(datetime_convert()),
1069                                 dbesc(datetime_convert()),
1070                                 dbesc("https://twitter.com/".$contact->screen_name),
1071                                 dbesc(normalise_link("https://twitter.com/".$contact->screen_name)),
1072                                 dbesc($contact->screen_name."@twitter.com"),
1073                                 dbesc($contact->name),
1074                                 dbesc($contact->screen_name),
1075                                 intval($r[0]['id'])
1076                         );
1077
1078                         if (DB_UPDATE_VERSION >= "1177")
1079                                 q("UPDATE `contact` SET `location` = '%s',
1080                                                         `about` = '%s'
1081                                                 WHERE `id` = %d",
1082                                         dbesc($contact->location),
1083                                         dbesc($contact->description),
1084                                         intval($r[0]['id'])
1085                                 );
1086                 }
1087         }
1088
1089         return($r[0]["id"]);
1090 }
1091
1092 function twitter_fetchuser($a, $uid, $screen_name = "", $user_id = "") {
1093         $ckey    = get_config('twitter', 'consumerkey');
1094         $csecret = get_config('twitter', 'consumersecret');
1095         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1096         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1097
1098         require_once("addon/twitter/codebird.php");
1099
1100         $cb = \Codebird\Codebird::getInstance();
1101         $cb->setConsumerKey($ckey, $csecret);
1102         $cb->setToken($otoken, $osecret);
1103
1104         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1105                 intval($uid));
1106
1107         if(count($r)) {
1108                 $self = $r[0];
1109         } else
1110                 return;
1111
1112         $parameters = array();
1113
1114         if ($screen_name != "")
1115                 $parameters["screen_name"] = $screen_name;
1116
1117         if ($user_id != "")
1118                 $parameters["user_id"] = $user_id;
1119
1120         // Fetching user data
1121         $user = $cb->users_show($parameters);
1122
1123         if (!is_object($user))
1124                 return;
1125
1126         $contact_id = twitter_fetch_contact($uid, $user, true);
1127
1128         return $contact_id;
1129 }
1130
1131 function twitter_expand_entities($a, $body, $item, $no_tags = false, $picture) {
1132         require_once("include/oembed.php");
1133         require_once("include/network.php");
1134
1135         $tags = "";
1136
1137         if (isset($item->entities->urls)) {
1138                 $type = "";
1139                 $footerurl = "";
1140                 $footerlink = "";
1141                 $footer = "";
1142
1143                 foreach ($item->entities->urls AS $url) {
1144                         if ($url->url AND $url->expanded_url AND $url->display_url) {
1145
1146                                 $expanded_url = original_url($url->expanded_url);
1147
1148                                 $oembed_data = oembed_fetch_url($expanded_url);
1149
1150                                 // Quickfix: Workaround for URL with "[" and "]" in it
1151                                 if (strpos($expanded_url, "[") OR strpos($expanded_url, "]"))
1152                                         $expanded_url = $url->url;
1153
1154                                 if ($type == "")
1155                                         $type = $oembed_data->type;
1156
1157                                 if ($oembed_data->type == "video") {
1158                                         //$body = str_replace($url->url,
1159                                         //              "[video]".$expanded_url."[/video]", $body);
1160                                         //$dontincludemedia = true;
1161                                         $type = $oembed_data->type;
1162                                         $footerurl = $expanded_url;
1163                                         $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]";
1164
1165                                         $body = str_replace($url->url, $footerlink, $body);
1166                                 //} elseif (($oembed_data->type == "photo") AND isset($oembed_data->url) AND !$dontincludemedia) {
1167                                 } elseif (($oembed_data->type == "photo") AND isset($oembed_data->url)) {
1168                                         $body = str_replace($url->url,
1169                                                         "[url=".$expanded_url."][img]".$oembed_data->url."[/img][/url]",
1170                                                         $body);
1171                                         //$dontincludemedia = true;
1172                                 } elseif ($oembed_data->type != "link")
1173                                         $body = str_replace($url->url,
1174                                                         "[url=".$expanded_url."]".$expanded_url."[/url]",
1175                                                         $body);
1176                                 else {
1177                                         $img_str = fetch_url($expanded_url, true, $redirects, 4);
1178
1179                                         $tempfile = tempnam(get_temppath(), "cache");
1180                                         file_put_contents($tempfile, $img_str);
1181                                         $mime = image_type_to_mime_type(exif_imagetype($tempfile));
1182                                         unlink($tempfile);
1183
1184                                         if (substr($mime, 0, 6) == "image/") {
1185                                                 $type = "photo";
1186                                                 $body = str_replace($url->url, "[img]".$expanded_url."[/img]", $body);
1187                                                 //$dontincludemedia = true;
1188                                         } else {
1189                                                 $type = $oembed_data->type;
1190                                                 $footerurl = $expanded_url;
1191                                                 $footerlink = "[url=".$expanded_url."]".$expanded_url."[/url]";
1192
1193                                                 $body = str_replace($url->url, $footerlink, $body);
1194                                         }
1195                                 }
1196                         }
1197                 }
1198
1199                 if ($footerurl != "")
1200                         $footer = add_page_info($footerurl, false, $picture);
1201
1202                 if (($footerlink != "") AND (trim($footer) != "")) {
1203                         $removedlink = trim(str_replace($footerlink, "", $body));
1204
1205                         if (($removedlink == "") OR strstr($body, $removedlink))
1206                                 $body = $removedlink;
1207
1208                         $body .= $footer;
1209                 }
1210
1211                 if (($footer == "") AND ($picture != ""))
1212                         $body .= "\n\n[img]".$picture."[/img]\n";
1213
1214                 if ($no_tags)
1215                         return(array("body" => $body, "tags" => ""));
1216
1217                 $tags_arr = array();
1218
1219                 foreach ($item->entities->hashtags AS $hashtag) {
1220                         $url = "#[url=".$a->get_baseurl()."/search?tag=".rawurlencode($hashtag->text)."]".$hashtag->text."[/url]";
1221                         $tags_arr["#".$hashtag->text] = $url;
1222                         $body = str_replace("#".$hashtag->text, $url, $body);
1223                 }
1224
1225                 foreach ($item->entities->user_mentions AS $mention) {
1226                         $url = "@[url=https://twitter.com/".rawurlencode($mention->screen_name)."]".$mention->screen_name."[/url]";
1227                         $tags_arr["@".$mention->screen_name] = $url;
1228                         $body = str_replace("@".$mention->screen_name, $url, $body);
1229                 }
1230
1231                 // it seems as if the entities aren't always covering all mentions. So the rest will be checked here
1232                 $tags = get_tags($body);
1233
1234                 if(count($tags)) {
1235                         foreach($tags as $tag) {
1236                                 if (strstr(trim($tag), " "))
1237                                         continue;
1238
1239                                 if(strpos($tag,'#') === 0) {
1240                                         if(strpos($tag,'[url='))
1241                                                 continue;
1242
1243                                         // don't link tags that are already embedded in links
1244
1245                                         if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body))
1246                                                 continue;
1247                                         if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body))
1248                                                 continue;
1249
1250                                         $basetag = str_replace('_',' ',substr($tag,1));
1251                                         $url = '#[url='.$a->get_baseurl().'/search?tag='.rawurlencode($basetag).']'.$basetag.'[/url]';
1252                                         $body = str_replace($tag,$url,$body);
1253                                         $tags_arr["#".$basetag] = $url;
1254                                         continue;
1255                                 } elseif(strpos($tag,'@') === 0) {
1256                                         if(strpos($tag,'[url='))
1257                                                 continue;
1258
1259                                         $basetag = substr($tag,1);
1260                                         $url = '@[url=https://twitter.com/'.rawurlencode($basetag).']'.$basetag.'[/url]';
1261                                         $body = str_replace($tag,$url,$body);
1262                                         $tags_arr["@".$basetag] = $url;
1263                                 }
1264                         }
1265                 }
1266
1267
1268                 $tags = implode($tags_arr, ",");
1269
1270         }
1271         return(array("body" => $body, "tags" => $tags));
1272 }
1273
1274 function twitter_createpost($a, $uid, $post, $self, $create_user, $only_existing_contact) {
1275
1276         $has_picture = false;
1277
1278         $postarray = array();
1279         $postarray['network'] = NETWORK_TWITTER;
1280         $postarray['gravity'] = 0;
1281         $postarray['uid'] = $uid;
1282         $postarray['wall'] = 0;
1283         $postarray['uri'] = "twitter::".$post->id_str;
1284
1285         $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1",
1286                         dbesc($postarray['uri']),
1287                         intval($uid)
1288                 );
1289
1290         if (count($r))
1291                 return(array());
1292
1293         $contactid = 0;
1294
1295         if ($post->in_reply_to_status_id_str != "") {
1296
1297                 $parent = "twitter::".$post->in_reply_to_status_id_str;
1298
1299                 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
1300                                 dbesc($parent),
1301                                 intval($uid)
1302                         );
1303                 if (count($r)) {
1304                         $postarray['thr-parent'] = $r[0]["uri"];
1305                         $postarray['parent-uri'] = $r[0]["parent-uri"];
1306                         $postarray['parent'] = $r[0]["parent"];
1307                         $postarray['object-type'] = ACTIVITY_OBJ_COMMENT;
1308                 } else {
1309                         $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1",
1310                                         dbesc($parent),
1311                                         intval($uid)
1312                                 );
1313                         if (count($r)) {
1314                                 $postarray['thr-parent'] = $r[0]['uri'];
1315                                 $postarray['parent-uri'] = $r[0]['parent-uri'];
1316                                 $postarray['parent'] = $r[0]['parent'];
1317                                 $postarray['object-type'] = ACTIVITY_OBJ_COMMENT;
1318                         } else {
1319                                 $postarray['thr-parent'] = $postarray['uri'];
1320                                 $postarray['parent-uri'] = $postarray['uri'];
1321                                 $postarray['object-type'] = ACTIVITY_OBJ_NOTE;
1322                         }
1323                 }
1324
1325                 // Is it me?
1326                 $own_id = get_pconfig($uid, 'twitter', 'own_id');
1327
1328                 if ($post->user->id_str == $own_id) {
1329                         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1330                                 intval($uid));
1331
1332                         if(count($r)) {
1333                                 $contactid = $r[0]["id"];
1334
1335                                 $postarray['owner-name'] =  $r[0]["name"];
1336                                 $postarray['owner-link'] = $r[0]["url"];
1337                                 $postarray['owner-avatar'] =  $r[0]["photo"];
1338                         } else
1339                                 return(array());
1340                 }
1341                 // Don't create accounts of people who just comment something
1342                 $create_user = false;
1343         } else {
1344                 $postarray['parent-uri'] = $postarray['uri'];
1345                 $postarray['object-type'] = ACTIVITY_OBJ_NOTE;
1346         }
1347
1348         if ($contactid == 0) {
1349                 $contactid = twitter_fetch_contact($uid, $post->user, $create_user);
1350
1351                 $postarray['owner-name'] = $post->user->name;
1352                 $postarray['owner-link'] = "https://twitter.com/".$post->user->screen_name;
1353                 $postarray['owner-avatar'] = $post->user->profile_image_url_https;
1354         }
1355
1356         if(($contactid == 0) AND !$only_existing_contact)
1357                 $contactid = $self['id'];
1358         elseif ($contactid <= 0)
1359                 return(array());
1360
1361         $postarray['contact-id'] = $contactid;
1362
1363         $postarray['verb'] = ACTIVITY_POST;
1364         $postarray['author-name'] = $postarray['owner-name'];
1365         $postarray['author-link'] = $postarray['owner-link'];
1366         $postarray['author-avatar'] = $postarray['owner-avatar'];
1367         $postarray['plink'] = "https://twitter.com/".$post->user->screen_name."/status/".$post->id_str;
1368         $postarray['app'] = strip_tags($post->source);
1369
1370         if ($post->user->protected) {
1371                 $postarray['private'] = 1;
1372                 $postarray['allow_cid'] = '<' . $self['id'] . '>';
1373         }
1374
1375         $postarray['body'] = $post->text;
1376
1377         $picture = "";
1378
1379         // media
1380         if (is_array($post->entities->media)) {
1381                 foreach($post->entities->media AS $media) {
1382                         switch($media->type) {
1383                                 case 'photo':
1384                                         //$postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']);
1385                                         //$has_picture = true;
1386                                         $postarray['body'] = str_replace($media->url, "", $postarray['body']);
1387                                         $postarray['object-type'] = ACTIVITY_OBJ_IMAGE;
1388                                         $picture = $media->media_url_https;
1389                                         break;
1390                                 default:
1391                                         $postarray['body'] .= print_r($media, true);
1392                         }
1393                 }
1394         }
1395
1396         $converted = twitter_expand_entities($a, $postarray['body'], $post, false, $picture);
1397         $postarray['body'] = $converted["body"];
1398         $postarray['tag'] = $converted["tags"];
1399
1400         $postarray['created'] = datetime_convert('UTC','UTC',$post->created_at);
1401         $postarray['edited'] = datetime_convert('UTC','UTC',$post->created_at);
1402
1403         if (is_string($post->place->name))
1404                 $postarray["location"] = $post->place->name;
1405
1406         if (is_string($post->place->full_name))
1407                 $postarray["location"] = $post->place->full_name;
1408
1409         if (is_array($post->geo->coordinates))
1410                 $postarray["coord"] = $post->geo->coordinates[0]." ".$post->geo->coordinates[1];
1411
1412         if (is_array($post->coordinates->coordinates))
1413                 $postarray["coord"] = $post->coordinates->coordinates[1]." ".$post->coordinates->coordinates[0];
1414
1415         if (is_object($post->retweeted_status)) {
1416
1417                 $postarray['body'] = $post->retweeted_status->text;
1418
1419                 $picture = "";
1420
1421                 // media
1422                 if (is_array($post->retweeted_status->entities->media)) {
1423                         foreach($post->retweeted_status->entities->media AS $media) {
1424                                 switch($media->type) {
1425                                         case 'photo':
1426                                                 //$postarray['body'] = str_replace($media->url, "\n\n[img]".$media->media_url_https."[/img]\n", $postarray['body']);
1427                                                 //$has_picture = true;
1428                                                 $postarray['body'] = str_replace($media->url, "", $postarray['body']);
1429                                                 $postarray['object-type'] = ACTIVITY_OBJ_IMAGE;
1430                                                 $picture = $media->media_url_https;
1431                                                 break;
1432                                         default:
1433                                                 $postarray['body'] .= print_r($media, true);
1434                                 }
1435                         }
1436                 }
1437
1438                 $converted = twitter_expand_entities($a, $postarray['body'], $post->retweeted_status, false, $picture);
1439                 $postarray['body'] = $converted["body"];
1440                 $postarray['tag'] = $converted["tags"];
1441
1442                 twitter_fetch_contact($uid, $post->retweeted_status->user, false);
1443
1444                 // Deactivated at the moment, since there are problems with answers to retweets
1445                 if (false AND !intval(get_config('system','wall-to-wall_share'))) {
1446                         $postarray['body'] = "[share author='".$post->retweeted_status->user->name.
1447                                 "' profile='https://twitter.com/".$post->retweeted_status->user->screen_name.
1448                                 "' avatar='".$post->retweeted_status->user->profile_image_url_https.
1449                                 "' link='https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str."']".
1450                                 $postarray['body'];
1451                         $postarray['body'] .= "[/share]";
1452                 } else {
1453                         // Let retweets look like wall-to-wall posts
1454                         $postarray['author-name'] = $post->retweeted_status->user->name;
1455                         $postarray['author-link'] = "https://twitter.com/".$post->retweeted_status->user->screen_name;
1456                         $postarray['author-avatar'] = $post->retweeted_status->user->profile_image_url_https;
1457                         //if (($post->retweeted_status->user->screen_name != "") AND ($post->retweeted_status->id_str != "")) {
1458                         //      $postarray['plink'] = "https://twitter.com/".$post->retweeted_status->user->screen_name."/status/".$post->retweeted_status->id_str;
1459                         //      $postarray['uri'] = "twitter::".$post->retweeted_status->id_str;
1460                         //}
1461                 }
1462
1463         }
1464         return($postarray);
1465 }
1466
1467 function twitter_checknotification($a, $uid, $own_id, $top_item, $postarray) {
1468
1469         // this whole function doesn't seem to work. Needs complete check
1470
1471         $user = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1",
1472                         intval($uid)
1473                 );
1474
1475         if(!count($user))
1476                 return;
1477
1478         // Is it me?
1479         if (link_compare($user[0]["url"], $postarray['author-link']))
1480                 return;
1481
1482         $own_user = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
1483                         intval($uid),
1484                         dbesc("twitter::".$own_id)
1485                 );
1486
1487         if(!count($own_user))
1488                 return;
1489
1490         // Is it me from twitter?
1491         if (link_compare($own_user[0]["url"], $postarray['author-link']))
1492                 return;
1493
1494         $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0",
1495                         dbesc($postarray['parent-uri']),
1496                         intval($uid)
1497                         );
1498
1499         if(count($myconv)) {
1500
1501                 foreach($myconv as $conv) {
1502                         // now if we find a match, it means we're in this conversation
1503
1504                         if(!link_compare($conv['author-link'],$user[0]["url"]) AND !link_compare($conv['author-link'],$own_user[0]["url"]))
1505                                 continue;
1506
1507                         require_once('include/enotify.php');
1508
1509                         $conv_parent = $conv['parent'];
1510
1511                         notification(array(
1512                                 'type'         => NOTIFY_COMMENT,
1513                                 'notify_flags' => $user[0]['notify-flags'],
1514                                 'language'     => $user[0]['language'],
1515                                 'to_name'      => $user[0]['username'],
1516                                 'to_email'     => $user[0]['email'],
1517                                 'uid'          => $user[0]['uid'],
1518                                 'item'         => $postarray,
1519                                 'link'         => $a->get_baseurl().'/display/'.urlencode(get_item_guid($top_item)),
1520                                 'source_name'  => $postarray['author-name'],
1521                                 'source_link'  => $postarray['author-link'],
1522                                 'source_photo' => $postarray['author-avatar'],
1523                                 'verb'         => ACTIVITY_POST,
1524                                 'otype'        => 'item',
1525                                 'parent'       => $conv_parent,
1526                         ));
1527
1528                         // only send one notification
1529                         break;
1530                 }
1531         }
1532 }
1533
1534 function twitter_fetchhometimeline($a, $uid) {
1535         $ckey    = get_config('twitter', 'consumerkey');
1536         $csecret = get_config('twitter', 'consumersecret');
1537         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1538         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1539         $create_user = get_pconfig($uid, 'twitter', 'create_user');
1540
1541         logger("twitter_fetchhometimeline: Fetching for user ".$uid, LOGGER_DEBUG);
1542
1543         require_once('library/twitteroauth.php');
1544         require_once('include/items.php');
1545
1546         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1547
1548         $own_contact = twitter_fetch_own_contact($a, $uid);
1549
1550         $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
1551                 intval($own_contact),
1552                 intval($uid));
1553
1554         if(count($r)) {
1555                 $own_id = $r[0]["nick"];
1556         } else {
1557                 logger("twitter_fetchhometimeline: Own twitter contact not found for user ".$uid, LOGGER_DEBUG);
1558                 return;
1559         }
1560
1561         $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
1562                 intval($uid));
1563
1564         if(count($r)) {
1565                 $self = $r[0];
1566         } else {
1567                 logger("twitter_fetchhometimeline: Own contact not found for user ".$uid, LOGGER_DEBUG);
1568                 return;
1569         }
1570
1571         $u = q("SELECT * FROM user WHERE uid = %d LIMIT 1",
1572                 intval($uid));
1573         if(!count($u)) {
1574                 logger("twitter_fetchhometimeline: Own user not found for user ".$uid, LOGGER_DEBUG);
1575                 return;
1576         }
1577
1578         $parameters = array("exclude_replies" => false, "trim_user" => false, "contributor_details" => true, "include_rts" => true);
1579         //$parameters["count"] = 200;
1580
1581
1582         // Fetching timeline
1583         $lastid  = get_pconfig($uid, 'twitter', 'lasthometimelineid');
1584
1585         $first_time = ($lastid == "");
1586
1587         if ($lastid <> "")
1588                 $parameters["since_id"] = $lastid;
1589
1590         $items = $connection->get('statuses/home_timeline', $parameters);
1591
1592         if (!is_array($items)) {
1593                 logger("twitter_fetchhometimeline: Error fetching home timeline: ".print_r($items, true), LOGGER_DEBUG);
1594                 return;
1595         }
1596
1597         $posts = array_reverse($items);
1598
1599         logger("twitter_fetchhometimeline: Fetching timeline for user ".$uid." ".sizeof($posts)." items", LOGGER_DEBUG);
1600
1601         if (count($posts)) {
1602                 foreach ($posts as $post) {
1603                         if ($post->id_str > $lastid)
1604                                 $lastid = $post->id_str;
1605
1606                         if ($first_time)
1607                                 continue;
1608
1609                         $postarray = twitter_createpost($a, $uid, $post, $self, $create_user, true);
1610
1611                         if (trim($postarray['body']) == "")
1612                                 continue;
1613
1614                         $item = item_store($postarray);
1615
1616                         logger('twitter_fetchhometimeline: User '.$self["nick"].' posted home timeline item '.$item);
1617
1618                         if ($item != 0)
1619                                 twitter_checknotification($a, $uid, $own_id, $item, $postarray);
1620
1621                 }
1622         }
1623         set_pconfig($uid, 'twitter', 'lasthometimelineid', $lastid);
1624
1625         // Fetching mentions
1626         $lastid  = get_pconfig($uid, 'twitter', 'lastmentionid');
1627
1628         $first_time = ($lastid == "");
1629
1630         if ($lastid <> "")
1631                 $parameters["since_id"] = $lastid;
1632
1633         $items = $connection->get('statuses/mentions_timeline', $parameters);
1634
1635         if (!is_array($items)) {
1636                 logger("twitter_fetchhometimeline: Error fetching mentions: ".print_r($items, true), LOGGER_DEBUG);
1637                 return;
1638         }
1639
1640         $posts = array_reverse($items);
1641
1642         logger("twitter_fetchhometimeline: Fetching mentions for user ".$uid." ".sizeof($posts)." items", LOGGER_DEBUG);
1643
1644         if (count($posts)) {
1645                 foreach ($posts as $post) {
1646                         if ($post->id_str > $lastid)
1647                                 $lastid = $post->id_str;
1648
1649                         if ($first_time)
1650                                 continue;
1651
1652                         $postarray = twitter_createpost($a, $uid, $post, $self, false, false);
1653
1654                         if (trim($postarray['body']) == "")
1655                                 continue;
1656
1657                         $item = item_store($postarray);
1658
1659                         if (!isset($postarray["parent"]) OR ($postarray["parent"] == 0))
1660                                 $postarray["parent"] = $item;
1661
1662                         logger('twitter_fetchhometimeline: User '.$self["nick"].' posted mention timeline item '.$item);
1663
1664                         if ($item == 0) {
1665                                 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
1666                                         dbesc($postarray['uri']),
1667                                         intval($uid)
1668                                 );
1669                                 if (count($r)) {
1670                                         $item = $r[0]['id'];
1671                                         $parent_id = $r[0]['parent'];
1672                                 }
1673                         } else
1674                                 $parent_id = $postarray['parent'];
1675
1676                         if ($item != 0) {
1677                                 require_once('include/enotify.php');
1678                                 notification(array(
1679                                         'type'         => NOTIFY_TAGSELF,
1680                                         'notify_flags' => $u[0]['notify-flags'],
1681                                         'language'     => $u[0]['language'],
1682                                         'to_name'      => $u[0]['username'],
1683                                         'to_email'     => $u[0]['email'],
1684                                         'uid'          => $u[0]['uid'],
1685                                         'item'         => $postarray,
1686                                         'link'         => $a->get_baseurl().'/display/'.urlencode(get_item_guid($item)),
1687                                         'source_name'  => $postarray['author-name'],
1688                                         'source_link'  => $postarray['author-link'],
1689                                         'source_photo' => $postarray['author-avatar'],
1690                                         'verb'         => ACTIVITY_TAG,
1691                                         'otype'        => 'item',
1692                                         'parent'       => $parent_id
1693                                 ));
1694                         }
1695                 }
1696         }
1697
1698         set_pconfig($uid, 'twitter', 'lastmentionid', $lastid);
1699 }
1700
1701 function twitter_fetch_own_contact($a, $uid) {
1702         $ckey    = get_config('twitter', 'consumerkey');
1703         $csecret = get_config('twitter', 'consumersecret');
1704         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1705         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1706
1707         $own_id = get_pconfig($uid, 'twitter', 'own_id');
1708
1709         $contact_id = 0;
1710
1711         if ($own_id == "") {
1712                 require_once('library/twitteroauth.php');
1713
1714                 $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1715
1716                 // Fetching user data
1717                 $user = $connection->get('account/verify_credentials');
1718
1719                 set_pconfig($uid, 'twitter', 'own_id', $user->id_str);
1720
1721                 $contact_id = twitter_fetch_contact($uid, $user, true);
1722
1723         } else {
1724                 $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
1725                         intval($uid), dbesc("twitter::".$own_id));
1726                 if(count($r))
1727                         $contact_id = $r[0]["id"];
1728                 else
1729                         del_pconfig($uid, 'twitter', 'own_id');
1730
1731         }
1732
1733         return($contact_id);
1734 }
1735
1736 function twitter_is_retweet($a, $uid, $body) {
1737         $body = trim($body);
1738
1739         // Skip if it isn't a pure repeated messages
1740         // Does it start with a share?
1741         if (strpos($body, "[share") > 0)
1742                 return(false);
1743
1744         // Does it end with a share?
1745         if (strlen($body) > (strrpos($body, "[/share]") + 8))
1746                 return(false);
1747
1748         $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
1749         // Skip if there is no shared message in there
1750         if ($body == $attributes)
1751                 return(false);
1752
1753         $link = "";
1754         preg_match("/link='(.*?)'/ism", $attributes, $matches);
1755         if ($matches[1] != "")
1756                 $link = $matches[1];
1757
1758         preg_match('/link="(.*?)"/ism', $attributes, $matches);
1759         if ($matches[1] != "")
1760                 $link = $matches[1];
1761
1762         $id = preg_replace("=https?://twitter.com/(.*)/status/(.*)=ism", "$2", $link);
1763         if ($id == $link)
1764                 return(false);
1765
1766         logger('twitter_is_retweet: Retweeting id '.$id.' for user '.$uid, LOGGER_DEBUG);
1767
1768         $ckey    = get_config('twitter', 'consumerkey');
1769         $csecret = get_config('twitter', 'consumersecret');
1770         $otoken  = get_pconfig($uid, 'twitter', 'oauthtoken');
1771         $osecret = get_pconfig($uid, 'twitter', 'oauthsecret');
1772
1773         require_once('library/twitteroauth.php');
1774         $connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
1775
1776         $result = $connection->post('statuses/retweet/'.$id);
1777
1778         logger('twitter_is_retweet: result '.print_r($result, true), LOGGER_DEBUG);
1779
1780         return(!isset($result->errors));
1781 }
1782 ?>