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