| 
									
										
										
										
											2010-10-04 18:28:54 -07:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * StatusNet, the distributed open-source microblogging tool | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * PHP version 5 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * LICENCE: This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |  * (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @category  Plugin | 
					
						
							|  |  |  |  * @package   StatusNet | 
					
						
							|  |  |  |  * @author    Brion Vibber <brion@status.net> | 
					
						
							|  |  |  |  * @copyright 2010 StatusNet, Inc. | 
					
						
							|  |  |  |  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | 
					
						
							|  |  |  |  * @link      http://status.net/ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $shortoptions = 'n:'; | 
					
						
							| 
									
										
										
										
											2010-11-02 16:26:51 -07:00
										 |  |  | $longoptions = array('nick=','import','all','apiroot='); | 
					
						
							| 
									
										
										
										
											2010-10-04 18:28:54 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | $helptext = <<<ENDOFHELP | 
					
						
							|  |  |  | USAGE: streamtest.php -n <username> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  |   -n --nick=<username> Local user whose Twitter timeline to watch | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |      --import          Experimental: run incoming messages through import | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  |      --all             Experimental: run multiuser; requires nick be the app owner | 
					
						
							| 
									
										
										
										
											2010-11-02 16:26:51 -07:00
										 |  |  |      --apiroot=<url>   Provide alternate streaming API root URL | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-04 18:28:54 -07:00
										 |  |  | Attempts a User Stream connection to Twitter as the given user, dumping | 
					
						
							|  |  |  | data as it comes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ENDOFHELP; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require_once INSTALLDIR.'/scripts/commandline.inc'; | 
					
						
							| 
									
										
										
										
											2013-08-28 15:54:26 +02:00
										 |  |  | require_once dirname(dirname(__FILE__)) . '/lib/jsonstreamreader.php'; | 
					
						
							|  |  |  | require_once dirname(dirname(__FILE__)) . '/lib/twitterstreamreader.php'; | 
					
						
							| 
									
										
										
										
											2010-10-04 18:28:54 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | if (have_option('n')) { | 
					
						
							|  |  |  |     $nickname = get_option_value('n'); | 
					
						
							|  |  |  | } else if (have_option('nick')) { | 
					
						
							|  |  |  |     $nickname = get_option_value('nickname'); | 
					
						
							|  |  |  | } else { | 
					
						
							|  |  |  |     show_help($helptext); | 
					
						
							|  |  |  |     exit(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param User $user  | 
					
						
							|  |  |  |  * @return TwitterOAuthClient | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function twitterAuthForUser(User $user) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     $flink = Foreign_link::getByUserID($user->id, | 
					
						
							|  |  |  |                                        TWITTER_SERVICE); | 
					
						
							|  |  |  |     if (!$flink) { | 
					
						
							|  |  |  |         throw new ServerException("No Twitter config for this user."); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $token = TwitterOAuthClient::unpackToken($flink->credentials); | 
					
						
							|  |  |  |     if (!$token) { | 
					
						
							|  |  |  |         throw new ServerException("No Twitter OAuth credentials for this user."); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return new TwitterOAuthClient($token->key, $token->secret); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function homeStreamForUser(User $user) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     $auth = twitterAuthForUser($user); | 
					
						
							|  |  |  |     return new TwitterUserStream($auth); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | function siteStreamForOwner(User $user) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // The user we auth as must be the owner of the application.
 | 
					
						
							|  |  |  |     $auth = twitterAuthForUser($user); | 
					
						
							| 
									
										
										
										
											2010-11-02 16:26:51 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (have_option('apiroot')) { | 
					
						
							|  |  |  |         $stream = new TwitterSiteStream($auth, get_option_value('apiroot')); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         $stream = new TwitterSiteStream($auth); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Pull Twitter user IDs for all users we want to pull data for
 | 
					
						
							|  |  |  |     $userIds = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $flink = new Foreign_link(); | 
					
						
							|  |  |  |     $flink->service = TWITTER_SERVICE; | 
					
						
							|  |  |  |     $flink->find(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while ($flink->fetch()) { | 
					
						
							|  |  |  |         if (($flink->noticesync & FOREIGN_NOTICE_RECV) == | 
					
						
							|  |  |  |             FOREIGN_NOTICE_RECV) { | 
					
						
							|  |  |  |             $userIds[] = $flink->foreign_id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $stream->followUsers($userIds); | 
					
						
							|  |  |  |     return $stream; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-18 13:04:58 +02:00
										 |  |  | $user = User::getKV('nickname', $nickname); | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  | global $myuser; | 
					
						
							|  |  |  | $myuser = $user; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | if (have_option('all')) { | 
					
						
							|  |  |  |     $stream = siteStreamForOwner($user); | 
					
						
							|  |  |  | } else { | 
					
						
							|  |  |  |     $stream = homeStreamForUser($user); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $stream->hookEvent('raw', function($data, $context) { | 
					
						
							|  |  |  |     common_log(LOG_INFO, json_encode($data) . ' for ' . json_encode($context)); | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('friends', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |     printf("Friend list: %s\n", implode(', ', $data->friends)); | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('favorite', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  |     printf("%s favorited %s's notice: %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->source->screen_name, | 
					
						
							|  |  |  |             $data->target->screen_name, | 
					
						
							|  |  |  |             $data->target_object->text); | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('unfavorite', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 13:25:28 -07:00
										 |  |  |     printf("%s unfavorited %s's notice: %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->source->screen_name, | 
					
						
							|  |  |  |             $data->target->screen_name, | 
					
						
							|  |  |  |             $data->target_object->text); | 
					
						
							| 
									
										
										
										
											2010-10-05 13:25:28 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('follow', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  |     printf("%s friended %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->source->screen_name, | 
					
						
							|  |  |  |             $data->target->screen_name); | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('unfollow', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 13:25:28 -07:00
										 |  |  |     printf("%s unfriended %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->source->screen_name, | 
					
						
							|  |  |  |             $data->target->screen_name); | 
					
						
							| 
									
										
										
										
											2010-10-05 13:25:28 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('delete', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  |     printf("Deleted status notification: %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->status->id); | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('scrub_geo', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  |     printf("Req to scrub geo data for user id %s up to status ID %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->user_id, | 
					
						
							|  |  |  |             $data->up_to_status_id); | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2010-10-05 17:08:04 -07:00
										 |  |  | $stream->hookEvent('status', function($data, $context) { | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  |     printf("Received status update from %s: %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->user->screen_name, | 
					
						
							|  |  |  |             $data->text); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (have_option('import')) { | 
					
						
							|  |  |  |         $importer = new TwitterImport(); | 
					
						
							|  |  |  |         printf("\timporting..."); | 
					
						
							|  |  |  |         $notice = $importer->importStatus($data); | 
					
						
							| 
									
										
										
										
											2014-03-06 04:36:00 +01:00
										 |  |  |         if (!$notice instanceof Notice) { | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             printf(" FAIL\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-10-05 12:42:55 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | $stream->hookEvent('direct_message', function($data) { | 
					
						
							|  |  |  |     printf("Direct message from %s to %s: %s\n", | 
					
						
							| 
									
										
										
										
											2010-10-05 14:26:11 -07:00
										 |  |  |             $data->sender->screen_name, | 
					
						
							|  |  |  |             $data->recipient->screen_name, | 
					
						
							|  |  |  |             $data->text); | 
					
						
							| 
									
										
										
										
											2010-10-04 18:28:54 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TwitterManager extends IoManager | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     function __construct(TwitterStreamReader $stream) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->stream = $stream; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function getSockets() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $this->stream->getSockets(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function handleInput($data) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->stream->handleInput($data); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function start() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->stream->connect(); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function finish() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->stream->close(); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public static function get() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         throw new Exception('not a singleton'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TwitterStreamMaster extends IoMaster | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     function __construct($id, $ioManager) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         parent::__construct($id); | 
					
						
							|  |  |  |         $this->ioManager = $ioManager; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Initialize IoManagers which are appropriate to this instance. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function initManagers() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->instantiate($this->ioManager); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $master = new TwitterStreamMaster('TwitterStream', new TwitterManager($stream)); | 
					
						
							|  |  |  | $master->init(); | 
					
						
							|  |  |  | $master->service(); |