summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/createsim.php142
-rwxr-xr-xscripts/getvaliddaemons.php12
-rwxr-xr-xscripts/maildaemon.php52
-rwxr-xr-xscripts/stopdaemons.sh2
-rwxr-xr-xscripts/synctwitterfriends.php277
-rw-r--r--scripts/triminboxes.php40
-rwxr-xr-xscripts/twitterstatusfetcher.php319
-rwxr-xr-xscripts/xmppdaemon.php5
8 files changed, 536 insertions, 313 deletions
diff --git a/scripts/createsim.php b/scripts/createsim.php
new file mode 100644
index 000000000..71827ba5b
--- /dev/null
+++ b/scripts/createsim.php
@@ -0,0 +1,142 @@
+#!/usr/bin/env php
+<?php
+/*
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ *
+ * 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/>.
+ */
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$shortoptions = 'u:n:b:t:x:';
+$longoptions = array('users=', 'notices=', 'subscriptions=', 'tags=', 'prefix=');
+
+$helptext = <<<END_OF_CREATESIM_HELP
+Creates a lot of test users and notices to (loosely) simulate a real server.
+
+ -u --users Number of users (default 100)
+ -n --notices Average notices per user (default 100)
+ -b --subscriptions Average subscriptions per user (default no. users/20)
+ -t --tags Number of distinct hash tags (default 10000)
+ -x --prefix User name prefix (default 'testuser')
+
+END_OF_CREATESIM_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+// XXX: make these command-line options
+
+function newUser($i)
+{
+ global $userprefix;
+ User::register(array('nickname' => sprintf('%s%d', $userprefix, $i),
+ 'password' => sprintf('password%d', $i),
+ 'fullname' => sprintf('Test User %d', $i)));
+}
+
+function newNotice($i, $tagmax)
+{
+ global $userprefix;
+
+ $n = rand(0, $i - 1);
+ $user = User::staticGet('nickname', sprintf('%s%d', $userprefix, $n));
+
+ $is_reply = rand(0, 4);
+
+ $content = 'Test notice content';
+
+ if ($is_reply == 0) {
+ $n = rand(0, $i - 1);
+ $content = "@$userprefix$n " . $content;
+ }
+
+ $has_hash = rand(0, 2);
+
+ if ($has_hash == 0) {
+ $hashcount = rand(0, 2);
+ for ($j = 0; $j < $hashcount; $j++) {
+ $h = rand(0, $tagmax);
+ $content .= " #tag{$h}";
+ }
+ }
+
+ $notice = Notice::saveNew($user->id, $content, 'system');
+}
+
+function newSub($i)
+{
+ global $userprefix;
+ $f = rand(0, $i - 1);
+
+ $fromnick = sprintf('%s%d', $userprefix, $f);
+
+ $from = User::staticGet('nickname', $fromnick);
+
+ if (empty($from)) {
+ throw new Exception("Can't find user '$fromnick'.");
+ }
+
+ $t = rand(0, $i - 1);
+
+ if ($t == $f) {
+ $t++;
+ if ($t > $i - 1) {
+ $t = 0;
+ }
+ }
+
+ $tunic = sprintf('%s%d', $userprefix, $t);
+
+ $to = User::staticGet('nickname', $tunic);
+
+ if (empty($from)) {
+ throw new Exception("Can't find user '$tunic'.");
+ }
+
+ subs_subscribe_to($from, $to);
+}
+
+function main($usercount, $noticeavg, $subsavg, $tagmax)
+{
+ $n = 1;
+
+ newUser(0);
+
+ // # registrations + # notices + # subs
+
+ $events = $usercount + ($usercount * ($noticeavg + $subsavg));
+
+ for ($i = 0; $i < $events; $i++)
+ {
+ $e = rand(0, 1 + $noticeavg + $subsavg);
+
+ if ($e == 0) {
+ newUser($n);
+ $n++;
+ } else if ($e < $noticeavg + 1) {
+ newNotice($n, $tagmax);
+ } else {
+ newSub($n);
+ }
+ }
+}
+
+$usercount = (have_option('u', 'users')) ? get_option_value('u', 'users') : 100;
+$noticeavg = (have_option('n', 'notices')) ? get_option_value('n', 'notices') : 100;
+$subsavg = (have_option('b', 'subscriptions')) ? get_option_value('b', 'subscriptions') : max($usercount/20, 10);
+$tagmax = (have_option('t', 'tags')) ? get_option_value('t', 'tags') : 10000;
+$userprefix = (have_option('x', 'prefix')) ? get_option_value('x', 'prefix') : 'testuser';
+
+main($usercount, $noticeavg, $subsavg, $tagmax);
diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php
index 97c230784..f1d8d8116 100755
--- a/scripts/getvaliddaemons.php
+++ b/scripts/getvaliddaemons.php
@@ -28,7 +28,8 @@
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
$helptext = <<<ENDOFHELP
-getvaliddaemons.php - print out the currently configured PID directory
+getvaliddaemons.php - print out a list of valid daemons that should be started
+by the startdaemons script
ENDOFHELP;
@@ -42,7 +43,12 @@ if(common_config('twitterbridge','enabled')) {
echo "twitterstatusfetcher.php ";
}
echo "ombqueuehandler.php ";
-echo "twitterqueuehandler.php ";
+if (common_config('twitter', 'enabled')) {
+ echo "twitterqueuehandler.php ";
+ echo "synctwitterfriends.php ";
+}
echo "facebookqueuehandler.php ";
echo "pingqueuehandler.php ";
-echo "smsqueuehandler.php ";
+if (common_config('sms', 'enabled')) {
+ echo "smsqueuehandler.php ";
+}
diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php
index 11ddf06b7..91c257adb 100755
--- a/scripts/maildaemon.php
+++ b/scripts/maildaemon.php
@@ -299,25 +299,43 @@ class MailerDaemon
$attachments = array();
+ $this->extract_part($parsed,$msg,$attachments);
+
+ return array($from, $to, $msg, $attachments);
+ }
+
+ function extract_part($parsed,&$msg,&$attachments){
if ($parsed->ctype_primary == 'multipart') {
- foreach ($parsed->parts as $part) {
- if ($part->ctype_primary == 'text' &&
- $part->ctype_secondary == 'plain') {
- $msg = $part->body;
- }else{
- if ($part->body) {
- $attachment = tmpfile();
- fwrite($attachment, $part->body);
- $attachments[] = $attachment;
- }
+ if($parsed->ctype_secondary == 'alternative'){
+ $altmsg = $this->extract_msg_from_multipart_alternative_part($parsed);
+ if(!empty($altmsg)) $msg = $altmsg;
+ }else{
+ foreach($parsed->parts as $part){
+ $this->extract_part($part,$msg,$attachments);
}
}
- } else if ($type == 'text/plain') {
+ } else if ($parsed->ctype_primary == 'text'
+ && $parsed->ctype_secondary=='plain') {
$msg = $parsed->body;
- } else {
- $this->unsupported_type($type);
+ if(strtolower($parsed->ctype_parameters['charset']) != "utf-8"){
+ $msg = utf8_encode($msg);
+ }
+ }else if(!empty($parsed->body)){
+ if(common_config('attachments', 'uploads')){
+ //only save attachments if uploads are enabled
+ $attachment = tmpfile();
+ fwrite($attachment, $parsed->body);
+ $attachments[] = $attachment;
+ }
}
- return array($from, $to, $msg, $attachments);
+ }
+
+ function extract_msg_from_multipart_alternative_part($parsed){
+ foreach ($parsed->parts as $part) {
+ $this->extract_part($part,$msg,$attachments);
+ }
+ //we don't want any attachments that are a result of this parsing
+ return $msg;
}
function unsupported_type($type)
@@ -367,5 +385,7 @@ class MailerDaemon
}
}
-$md = new MailerDaemon();
-$md->handle_message('php://stdin');
+if (common_config('emailpost', 'enabled')) {
+ $md = new MailerDaemon();
+ $md->handle_message('php://stdin');
+}
diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh
index 60ffd83ad..894e5aaff 100755
--- a/scripts/stopdaemons.sh
+++ b/scripts/stopdaemons.sh
@@ -25,7 +25,7 @@ DIR=`php $SDIR/getpiddir.php`
for f in jabberhandler ombhandler publichandler smshandler pinghandler \
xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \
- twitterstatusfetcher; do
+ twitterstatusfetcher synctwitterfriends; do
FILES="$DIR/$f.*.pid"
for ff in "$FILES" ; do
diff --git a/scripts/synctwitterfriends.php b/scripts/synctwitterfriends.php
index fe53ff44d..2de464bcc 100755
--- a/scripts/synctwitterfriends.php
+++ b/scripts/synctwitterfriends.php
@@ -20,85 +20,260 @@
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
-// Uncomment this to get useful console output
+$shortoptions = 'di::';
+$longoptions = array('id::', 'debug');
+
+$helptext = <<<END_OF_TRIM_HELP
+Batch script for synching local friends with Twitter friends.
+ -i --id Identity (default 'generic')
+ -d --debug Debug (lots of log output)
+
+END_OF_TRIM_HELP;
+
+require_once INSTALLDIR . '/scripts/commandline.inc';
+require_once INSTALLDIR . '/lib/parallelizingdaemon.php';
+
+/**
+ * Daemon to sync local friends with Twitter friends
+ *
+ * @category Twitter
+ * @package Laconica
+ * @author Zach Copley <zach@controlyourself.ca>
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
$helptext = <<<END_OF_TWITTER_HELP
Batch script for synching local friends with Twitter friends.
END_OF_TWITTER_HELP;
-require_once INSTALLDIR.'/scripts/commandline.inc';
+require_once INSTALLDIR . '/scripts/commandline.inc';
+require_once INSTALLDIR . '/lib/parallelizingdaemon.php';
-// Make a lockfile
-$lockfilename = lockFilename();
-if (!($lockfile = @fopen($lockfilename, "w"))) {
- print "Already running... exiting.\n";
- exit(1);
-}
+class SyncTwitterFriendsDaemon extends ParallelizingDaemon
+{
+ /**
+ * Constructor
+ *
+ * @param string $id the name/id of this daemon
+ * @param int $interval sleep this long before doing everything again
+ * @param int $max_children maximum number of child processes at a time
+ * @param boolean $debug debug output flag
+ *
+ * @return void
+ *
+ **/
-// Obtain an exlcusive lock on file (will fail if script is already going)
-if (!@flock( $lockfile, LOCK_EX | LOCK_NB, &$wouldblock) || $wouldblock) {
- // Script already running - abort
- @fclose($lockfile);
- print "Already running... exiting.\n";
- exit(1);
-}
+ function __construct($id = null, $interval = 60,
+ $max_children = 2, $debug = null)
+ {
+ parent::__construct($id, $interval, $max_children, $debug);
+ }
-$flink = new Foreign_link();
-$flink->service = 1; // Twitter
-$flink->orderBy('last_friendsync');
-$flink->limit(25); // sync this many users during this run
-$cnt = $flink->find();
+ /**
+ * Name of this daemon
+ *
+ * @return string Name of the daemon.
+ */
-print "Updating Twitter friends subscriptions for $cnt users.\n";
+ function name()
+ {
+ return ('synctwitterfriends.' . $this->_id);
+ }
-while ($flink->fetch()) {
+ /**
+ * Find all the Twitter foreign links for users who have requested
+ * automatically subscribing to their Twitter friends locally.
+ *
+ * @return array flinks an array of Foreign_link objects
+ */
+ function getObjects()
+ {
+ $flinks = array();
+ $flink = new Foreign_link();
- if (($flink->friendsync & FOREIGN_FRIEND_RECV) == FOREIGN_FRIEND_RECV) {
+ $conn = &$flink->getDatabaseConnection();
- $user = User::staticGet($flink->user_id);
+ $flink->service = TWITTER_SERVICE;
+ $flink->orderBy('last_friendsync');
+ $flink->limit(25); // sync this many users during this run
+ $flink->find();
- if (empty($user)) {
- common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id);
- print "Unmatched user for ID $flink->user_id\n";
- continue;
+ while ($flink->fetch()) {
+ if (($flink->friendsync & FOREIGN_FRIEND_RECV) == FOREIGN_FRIEND_RECV) {
+ $flinks[] = clone($flink);
+ }
}
- print "Updating Twitter friends for $user->nickname (Laconica ID: $user->id)... ";
+ $conn->disconnect();
- $fuser = $flink->getForeignUser();
+ global $_DB_DATAOBJECT;
+ unset($_DB_DATAOBJECT['CONNECTIONS']);
- if (empty($fuser)) {
- common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id);
- print "Unmatched user for ID $flink->user_id\n";
- continue;
- }
+ return $flinks;
+ }
+
+ function childTask($flink) {
- save_twitter_friends($user, $fuser->id, $fuser->nickname, $flink->credentials);
+ // Each child ps needs its own DB connection
+
+ // Note: DataObject::getDatabaseConnection() creates
+ // a new connection if there isn't one already
+
+ $conn = &$flink->getDatabaseConnection();
+
+ $this->subscribeTwitterFriends($flink);
$flink->last_friendsync = common_sql_now();
$flink->update();
- if (defined('SCRIPT_DEBUG')) {
- print "\nDONE\n";
- } else {
- print "DONE\n";
+ $conn->disconnect();
+
+ // XXX: Couldn't find a less brutal way to blow
+ // away a cached connection
+
+ global $_DB_DATAOBJECT;
+ unset($_DB_DATAOBJECT['CONNECTIONS']);
+ }
+
+ function fetchTwitterFriends($flink)
+ {
+ $friends = array();
+
+ $token = TwitterOAuthClient::unpackToken($flink->credentials);
+
+ $client = new TwitterOAuthClient($token->key, $token->secret);
+
+ try {
+ $friends_ids = $client->friendsIds();
+ } catch (OAuthCurlException $e) {
+ common_log(LOG_WARNING, $this->name() .
+ ' - cURL error getting friend ids ' .
+ $e->getCode() . ' - ' . $e->getMessage());
+ return $friends;
+ }
+
+ if (empty($friends_ids)) {
+ common_debug($this->name() .
+ " - Twitter user $flink->foreign_id " .
+ 'doesn\'t have any friends!');
+ return $friends;
+ }
+
+ common_debug($this->name() . ' - Twitter\'s API says Twitter user id ' .
+ "$flink->foreign_id has " .
+ count($friends_ids) . ' friends.');
+
+ // Calculate how many pages to get...
+ $pages = ceil(count($friends_ids) / 100);
+
+ if ($pages == 0) {
+ common_debug($this->name() . " - $user seems to have no friends.");
+ }
+
+ for ($i = 1; $i <= $pages; $i++) {
+
+ try {
+ $more_friends = $client->statusesFriends(null, null, null, $i);
+ } catch (OAuthCurlException $e) {
+ common_log(LOG_WARNING, $this->name() .
+ ' - cURL error getting Twitter statuses/friends ' .
+ "page $i - " . $e->getCode() . ' - ' .
+ $e->getMessage());
}
+
+ if (empty($more_friends)) {
+ common_log(LOG_WARNING, $this->name() .
+ " - Couldn't retrieve page $i " .
+ "of Twitter user $flink->foreign_id friends.");
+ continue;
+ } else {
+ $friends = array_merge($friends, $more_friends);
+ }
+ }
+
+ return $friends;
}
-}
-function lockFilename()
-{
- $piddir = common_config('daemon', 'piddir');
- if (!$piddir) {
- $piddir = '/var/run';
+ function subscribeTwitterFriends($flink)
+ {
+ $friends = $this->fetchTwitterFriends($flink);
+
+ if (empty($friends)) {
+ common_debug($this->name() .
+ ' - Couldn\'t get friends from Twitter for ' .
+ "Twitter user $flink->foreign_id.");
+ return false;
+ }
+
+ $user = $flink->getUser();
+
+ foreach ($friends as $friend) {
+
+ $friend_name = $friend->screen_name;
+ $friend_id = (int) $friend->id;
+
+ // Update or create the Foreign_user record for each
+ // Twitter friend
+
+ if (!save_twitter_user($friend_id, $friend_name)) {
+ common_log(LOG_WARNING, $this-name() .
+ " - Couldn't save $screen_name's friend, $friend_name.");
+ continue;
+ }
+
+ // Check to see if there's a related local user
+
+ $friend_flink = Foreign_link::getByForeignID($friend_id,
+ TWITTER_SERVICE);
+
+ if (!empty($friend_flink)) {
+
+ // Get associated user and subscribe her
+
+ $friend_user = User::staticGet('id', $friend_flink->user_id);
+
+ if (!empty($friend_user)) {
+ $result = subs_subscribe_to($user, $friend_user);
+
+ if ($result === true) {
+ common_log(LOG_INFO,
+ $this->name() . ' - Subscribed ' .
+ "$friend_user->nickname to $user->nickname.");
+ } else {
+ common_debug($this->name() .
+ ' - Tried subscribing ' .
+ "$friend_user->nickname to $user->nickname - " .
+ $result);
+ }
+ }
+ }
+ }
+
+ return true;
}
- return $piddir . '/synctwitterfriends.lock';
}
-// Cleanup
-fclose($lockfile);
-unlink($lockfilename);
+$id = null;
+$debug = null;
+
+if (have_option('i')) {
+ $id = get_option_value('i');
+} else if (have_option('--id')) {
+ $id = get_option_value('--id');
+} else if (count($args) > 0) {
+ $id = $args[0];
+} else {
+ $id = null;
+}
+
+if (have_option('d') || have_option('debug')) {
+ $debug = true;
+}
+
+$syncer = new SyncTwitterFriendsDaemon($id, 60, 2, $debug);
+$syncer->runOnce();
-exit(0);
diff --git a/scripts/triminboxes.php b/scripts/triminboxes.php
index b2135d682..27e200fef 100644
--- a/scripts/triminboxes.php
+++ b/scripts/triminboxes.php
@@ -52,43 +52,5 @@ if (!empty($id)) {
$cnt = $user->find();
while ($user->fetch()) {
-
- $inbox_entry = new Notice_inbox();
- $inbox_entry->user_id = $user->id;
- $inbox_entry->orderBy('created DESC');
- $inbox_entry->limit(1000, 1);
-
- $id = null;
-
- if ($inbox_entry->find(true)) {
- $id = $inbox_entry->notice_id;
- }
-
- $inbox_entry->free();
- unset($inbox_entry);
-
- if (is_null($id)) {
- continue;
- }
-
- $start = microtime(true);
-
- $old_inbox = new Notice_inbox();
- $cnt = $old_inbox->query('DELETE from notice_inbox WHERE user_id = ' . $user->id . ' AND notice_id < ' . $id);
- $old_inbox->free();
- unset($old_inbox);
-
- print "Deleted $cnt notices for $user->nickname ($user->id).\n";
-
- $finish = microtime(true);
-
- $delay = 3.0 * ($finish - $start);
-
- print "Delaying $delay seconds...";
-
- // Wait to let slaves catch up
-
- usleep($delay * 1000000);
-
- print "DONE.\n";
+ Notice_inbox::gc($user->id);
}
diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php
index 4a1ed8977..f5289c5f4 100755
--- a/scripts/twitterstatusfetcher.php
+++ b/scripts/twitterstatusfetcher.php
@@ -25,19 +25,18 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
define('MAXCHILDREN', 2);
define('POLL_INTERVAL', 60); // in seconds
-$shortoptions = 'i::';
-$longoptions = array('id::');
+$shortoptions = 'di::';
+$longoptions = array('id::', 'debug');
$helptext = <<<END_OF_TRIM_HELP
Batch script for retrieving Twitter messages from foreign service.
- -i --id Identity (default 'generic')
+ -i --id Identity (default 'generic')
+ -d --debug Debug (lots of log output)
END_OF_TRIM_HELP;
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-require_once INSTALLDIR . '/lib/common.php';
+require_once INSTALLDIR .'/scripts/commandline.inc';
require_once INSTALLDIR . '/lib/daemon.php';
/**
@@ -57,9 +56,24 @@ require_once INSTALLDIR . '/lib/daemon.php';
// NOTE: an Avatar path MUST be set in config.php for this
// script to work: e.g.: $config['avatar']['path'] = '/laconica/avatar';
-class TwitterStatusFetcher extends Daemon
+class TwitterStatusFetcher extends ParallelizingDaemon
{
- private $_children = array();
+ /**
+ * Constructor
+ *
+ * @param string $id the name/id of this daemon
+ * @param int $interval sleep this long before doing everything again
+ * @param int $max_children maximum number of child processes at a time
+ * @param boolean $debug debug output flag
+ *
+ * @return void
+ *
+ **/
+ function __construct($id = null, $interval = 60,
+ $max_children = 2, $debug = null)
+ {
+ parent::__construct($id, $interval, $max_children, $debug);
+ }
/**
* Name of this daemon
@@ -73,121 +87,22 @@ class TwitterStatusFetcher extends Daemon
}
/**
- * Run the daemon
+ * Find all the Twitter foreign links for users who have requested
+ * importing of their friends' timelines
*
- * @return void
+ * @return array flinks an array of Foreign_link objects
*/
- function run()
+ function getObjects()
{
- do {
-
- $flinks = $this->refreshFlinks();
-
- foreach ($flinks as $f) {
-
- // We have to disconnect from the DB before forking so
- // each sub-process will open its own connection and
- // avoid stomping on the others
-
- $conn = &$f->getDatabaseConnection();
- $conn->disconnect();
-
- $pid = pcntl_fork();
-
- if ($pid == -1) {
- die ("Couldn't fork!");
- }
-
- if ($pid) {
-
- // Parent
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Parent: forked new status ".
- " fetcher process " . $pid);
- }
-
- $this->_children[] = $pid;
-
- } else {
-
- // Child
- $this->getTimeline($f);
- exit();
- }
-
- // Remove child from ps list as it finishes
- while (($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) {
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Child $c finished.");
- }
-
- $this->removePs($this->_children, $c);
- }
+ global $_DB_DATAOBJECT;
- // Wait! We have too many damn kids.
- if (sizeof($this->_children) > MAXCHILDREN) {
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Too many children. Waiting...');
- }
-
- if (($c = pcntl_wait($status, WUNTRACED)) > 0) {
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Finished waiting for $c");
- }
-
- $this->removePs($this->_children, $c);
- }
- }
- }
-
- // Remove all children from the process list before restarting
- while (($c = pcntl_wait($status, WUNTRACED)) > 0) {
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Child $c finished.");
- }
-
- $this->removePs($this->_children, $c);
- }
-
- // Rest for a bit before we fetch more statuses
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Waiting ' . POLL_INTERVAL .
- ' secs before hitting Twitter again.');
- }
-
- if (POLL_INTERVAL > 0) {
- sleep(POLL_INTERVAL);
- }
-
- } while (true);
- }
-
- /**
- * Refresh the foreign links for this user
- *
- * @return void
- */
-
- function refreshFlinks()
- {
$flink = new Foreign_link();
+ $conn = &$flink->getDatabaseConnection();
- $flink->service = 1; // Twitter
-
+ $flink->service = TWITTER_SERVICE;
$flink->orderBy('last_noticesync');
-
- $cnt = $flink->find();
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Updating Twitter friends subscriptions' .
- " for $cnt users.");
- }
+ $flink->find();
$flinks = array();
@@ -202,78 +117,81 @@ class TwitterStatusFetcher extends Daemon
$flink->free();
unset($flink);
+ $conn->disconnect();
+ unset($_DB_DATAOBJECT['CONNECTIONS']);
+
return $flinks;
}
- /**
- * Unknown
- *
- * @param array &$plist unknown.
- * @param string $ps unknown.
- *
- * @return unknown
- * @todo document
- */
+ function childTask($flink) {
- function removePs(&$plist, $ps)
- {
- for ($i = 0; $i < sizeof($plist); $i++) {
- if ($plist[$i] == $ps) {
- unset($plist[$i]);
- $plist = array_values($plist);
- break;
- }
- }
+ // Each child ps needs its own DB connection
+
+ // Note: DataObject::getDatabaseConnection() creates
+ // a new connection if there isn't one already
+
+ $conn = &$flink->getDatabaseConnection();
+
+ $this->getTimeline($flink);
+
+ $flink->last_friendsync = common_sql_now();
+ $flink->update();
+
+ $conn->disconnect();
+
+ // XXX: Couldn't find a less brutal way to blow
+ // away a cached connection
+
+ global $_DB_DATAOBJECT;
+ unset($_DB_DATAOBJECT['CONNECTIONS']);
}
function getTimeline($flink)
{
- if (empty($flink)) {
- common_log(LOG_WARNING,
- "Can't retrieve Foreign_link for foreign ID $fid");
+ if (empty($flink)) {
+ common_log(LOG_WARNING, $this->name() .
+ " - Can't retrieve Foreign_link for foreign ID $fid");
return;
}
- $fuser = $flink->getForeignUser();
-
- if (empty($fuser)) {
- common_log(LOG_WARNING, "Unmatched user for ID " .
- $flink->user_id);
- return;
- }
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Trying to get timeline for Twitter user ' .
- "$fuser->nickname ($flink->foreign_id).");
- }
+ common_debug($this->name() . ' - Trying to get timeline for Twitter user ' .
+ $flink->foreign_id);
// XXX: Biggest remaining issue - How do we know at which status
// to start importing? How many statuses? Right now I'm going
// with the default last 20.
- $url = 'http://twitter.com/statuses/friends_timeline.json';
+ $token = TwitterOAuthClient::unpackToken($flink->credentials);
- $timeline_json = get_twitter_data($url, $fuser->nickname,
- $flink->credentials);
+ $client = new TwitterOAuthClient($token->key, $token->secret);
- $timeline = json_decode($timeline_json);
+ $timeline = null;
+
+ try {
+ $timeline = $client->statusesFriendsTimeline();
+ } catch (OAuthClientCurlException $e) {
+ common_log(LOG_WARNING, $this->name() .
+ ' - OAuth client unable to get friends timeline for user ' .
+ $flink->user_id . ' - code: ' .
+ $e->getCode() . 'msg: ' . $e->getMessage());
+ }
if (empty($timeline)) {
- common_log(LOG_WARNING, "Empty timeline.");
+ common_log(LOG_WARNING, $this->name() . " - Empty timeline.");
return;
}
// Reverse to preserve order
+
foreach (array_reverse($timeline) as $status) {
// Hacktastic: filter out stuff coming from this Laconica
+
$source = mb_strtolower(common_config('integration', 'source'));
if (preg_match("/$source/", mb_strtolower($status->source))) {
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Skipping import of status ' . $status->id .
- ' with source ' . $source);
- }
+ common_debug($this->name() . ' - Skipping import of status ' .
+ $status->id . ' with source ' . $source);
continue;
}
@@ -281,6 +199,7 @@ class TwitterStatusFetcher extends Daemon
}
// Okay, record the time we synced with Twitter for posterity
+
$flink->last_noticesync = common_sql_now();
$flink->update();
}
@@ -288,11 +207,12 @@ class TwitterStatusFetcher extends Daemon
function saveStatus($status, $flink)
{
$id = $this->ensureProfile($status->user);
+
$profile = Profile::staticGet($id);
- if (!$profile) {
- common_log(LOG_ERR,
- 'Problem saving notice. No associated Profile.');
+ if (empty($profile)) {
+ common_log(LOG_ERR, $this->name() .
+ ' - Problem saving notice. No associated Profile.');
return null;
}
@@ -305,7 +225,7 @@ class TwitterStatusFetcher extends Daemon
// check to see if we've already imported the status
- if (!$notice) {
+ if (empty($notice)) {
$notice = new Notice();
@@ -316,7 +236,7 @@ class TwitterStatusFetcher extends Daemon
$notice->content = common_shorten_links($status->text); // XXX
$notice->rendered = common_render_content($notice->content, $notice);
$notice->source = 'twitter';
- $notice->reply_to = null; // XXX lookup reply
+ $notice->reply_to = null; // XXX: lookup reply
$notice->is_local = Notice::GATEWAY;
if (Event::handle('StartNoticeSave', array(&$notice))) {
@@ -342,24 +262,22 @@ class TwitterStatusFetcher extends Daemon
function ensureProfile($user)
{
// check to see if there's already a profile for this user
+
$profileurl = 'http://twitter.com/' . $user->screen_name;
$profile = Profile::staticGet('profileurl', $profileurl);
- if ($profile) {
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Profile for $profile->nickname found.");
- }
+ if (!empty($profile)) {
+ common_debug($this->name() .
+ " - Profile for $profile->nickname found.");
// Check to see if the user's Avatar has changed
- $this->checkAvatar($user, $profile);
+ $this->checkAvatar($user, $profile);
return $profile->id;
} else {
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Adding profile and remote profile ' .
- "for Twitter user: $profileurl");
- }
+ common_debug($this->name() . ' - Adding profile and remote profile ' .
+ "for Twitter user: $profileurl.");
$profile = new Profile();
$profile->query("BEGIN");
@@ -381,9 +299,10 @@ class TwitterStatusFetcher extends Daemon
}
// check for remote profile
+
$remote_pro = Remote_profile::staticGet('uri', $profileurl);
- if (!$remote_pro) {
+ if (empty($remote_pro)) {
$remote_pro = new Remote_profile();
@@ -420,23 +339,18 @@ class TwitterStatusFetcher extends Daemon
$oldname = $profile->getAvatar(48)->filename;
if ($newname != $oldname) {
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Avatar for Twitter user ' .
- "$profile->nickname has changed.");
- common_debug("old: $oldname new: $newname");
- }
+ common_debug($this->name() . ' - Avatar for Twitter user ' .
+ "$profile->nickname has changed.");
+ common_debug($this->name() . " - old: $oldname new: $newname");
$this->updateAvatars($twitter_user, $profile);
}
if ($this->missingAvatarFile($profile)) {
-
- if (defined('SCRIPT_DEBUG')) {
- common_debug('Twitter user ' . $profile->nickname .
- ' is missing one or more local avatars.');
- common_debug("old: $oldname new: $newname");
- }
+ common_debug($this->name() . ' - Twitter user ' .
+ $profile->nickname .
+ ' is missing one or more local avatars.');
+ common_debug($this->name() ." - old: $oldname new: $newname");
$this->updateAvatars($twitter_user, $profile);
}
@@ -516,23 +430,20 @@ class TwitterStatusFetcher extends Daemon
if ($this->fetchAvatar($url, $filename)) {
$this->newAvatar($id, $size, $mediatype, $filename);
} else {
- common_log(LOG_WARNING, "Problem fetching Avatar: $url", __FILE__);
+ common_log(LOG_WARNING, $this->id() .
+ " - Problem fetching Avatar: $url");
}
}
}
function updateAvatar($profile_id, $size, $mediatype, $filename) {
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Updating avatar: $size");
- }
+ common_debug($this->name() . " - Updating avatar: $size");
$profile = Profile::staticGet($profile_id);
if (empty($profile)) {
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Couldn't get profile: $profile_id!");
- }
+ common_debug($this->name() . " - Couldn't get profile: $profile_id!");
return;
}
@@ -540,6 +451,7 @@ class TwitterStatusFetcher extends Daemon
$avatar = $profile->getAvatar($sizes[$size]);
// Delete the avatar, if present
+
if ($avatar) {
$avatar->delete();
}
@@ -577,9 +489,7 @@ class TwitterStatusFetcher extends Daemon
$avatar->filename = $filename;
$avatar->url = Avatar::url($filename);
- if (defined('SCRIPT_DEBUG')) {
- common_debug("new filename: $avatar->url");
- }
+ common_debug($this->name() . " - New filename: $avatar->url");
$avatar->created = common_sql_now();
@@ -590,9 +500,8 @@ class TwitterStatusFetcher extends Daemon
return null;
}
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Saved new $size avatar for $profile_id.");
- }
+ common_debug($this->name() .
+ " - Saved new $size avatar for $profile_id.");
return $id;
}
@@ -605,13 +514,12 @@ class TwitterStatusFetcher extends Daemon
$out = fopen($avatarfile, 'wb');
if (!$out) {
- common_log(LOG_WARNING, "Couldn't open file $filename", __FILE__);
+ common_log(LOG_WARNING, $this->name() .
+ " - Couldn't open file $filename");
return false;
}
- if (defined('SCRIPT_DEBUG')) {
- common_debug("Fetching avatar: $url");
- }
+ common_debug($this->name() . " - Fetching Twitter avatar: $url");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
@@ -628,7 +536,8 @@ class TwitterStatusFetcher extends Daemon
}
}
-declare(ticks = 1);
+$id = null;
+$debug = null;
if (have_option('i')) {
$id = get_option_value('i');
@@ -640,6 +549,10 @@ if (have_option('i')) {
$id = null;
}
-$fetcher = new TwitterStatusFetcher($id);
+if (have_option('d') || have_option('debug')) {
+ $debug = true;
+}
+
+$fetcher = new TwitterStatusFetcher($id, 60, 2, $debug);
$fetcher->runOnce();
diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php
index 488b4b514..69512f243 100755
--- a/scripts/xmppdaemon.php
+++ b/scripts/xmppdaemon.php
@@ -175,6 +175,10 @@ class XMPPDaemon extends Daemon
$user = $this->get_user($from);
+ // For common_current_user to work
+ global $_cur;
+ $_cur = $user;
+
if (!$user) {
$this->from_site($from, 'Unknown user; go to ' .
common_local_url('imsettings') .
@@ -211,6 +215,7 @@ class XMPPDaemon extends Daemon
$user->free();
unset($user);
+ unset($_cur);
unset($pl['xml']);
$pl['xml'] = null;