summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/DiskCachePlugin.php168
-rw-r--r--plugins/Enjit/README5
-rw-r--r--plugins/Enjit/enjitqueuehandler.php91
-rw-r--r--plugins/Facebook/FacebookPlugin.php46
-rw-r--r--[-rwxr-xr-x]plugins/Facebook/facebookqueuehandler.php52
-rw-r--r--plugins/Imap/ImapPlugin.php36
-rwxr-xr-xplugins/Imap/imapdaemon.php147
-rw-r--r--plugins/Imap/imapmailhandler.php32
-rw-r--r--plugins/Imap/imapmanager.php129
-rw-r--r--plugins/LinkbackPlugin.php1
-rw-r--r--plugins/MemcachePlugin.php17
-rw-r--r--plugins/PubSubHubBub/PubSubHubBubPlugin.php16
-rw-r--r--plugins/Realtime/RealtimePlugin.php11
-rw-r--r--plugins/SubscriptionThrottlePlugin.php175
-rw-r--r--plugins/TwitterBridge/TwitterBridgePlugin.php50
-rwxr-xr-xplugins/TwitterBridge/daemons/twitterstatusfetcher.php14
-rw-r--r--plugins/TwitterBridge/twitter.php14
-rw-r--r--[-rwxr-xr-x]plugins/TwitterBridge/twitterqueuehandler.php (renamed from plugins/TwitterBridge/daemons/twitterqueuehandler.php)40
18 files changed, 702 insertions, 342 deletions
diff --git a/plugins/DiskCachePlugin.php b/plugins/DiskCachePlugin.php
new file mode 100644
index 000000000..b709ea3b3
--- /dev/null
+++ b/plugins/DiskCachePlugin.php
@@ -0,0 +1,168 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2009, StatusNet, Inc.
+ *
+ * Plugin to implement cache interface with disk files
+ *
+ * PHP version 5
+ *
+ * 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 Cache
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2009 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/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * A plugin to cache data on local disk
+ *
+ * @category Cache
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2009 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/
+ */
+
+class DiskCachePlugin extends Plugin
+{
+ var $root = '/tmp';
+
+ function keyToFilename($key)
+ {
+ return $this->root . '/' . str_replace(':', '/', $key);
+ }
+
+ /**
+ * Get a value associated with a key
+ *
+ * The value should have been set previously.
+ *
+ * @param string &$key in; Lookup key
+ * @param mixed &$value out; value associated with key
+ *
+ * @return boolean hook success
+ */
+
+ function onStartCacheGet(&$key, &$value)
+ {
+ $filename = $this->keyToFilename($key);
+
+ if (file_exists($filename)) {
+ $data = file_get_contents($filename);
+ if ($data !== false) {
+ $value = unserialize($data);
+ }
+ }
+
+ Event::handle('EndCacheGet', array($key, &$value));
+ return false;
+ }
+
+ /**
+ * Associate a value with a key
+ *
+ * @param string &$key in; Key to use for lookups
+ * @param mixed &$value in; Value to associate
+ * @param integer &$flag in; Flag (passed through to Memcache)
+ * @param integer &$expiry in; Expiry (passed through to Memcache)
+ * @param boolean &$success out; Whether the set was successful
+ *
+ * @return boolean hook success
+ */
+
+ function onStartCacheSet(&$key, &$value, &$flag, &$expiry, &$success)
+ {
+ $filename = $this->keyToFilename($key);
+ $parent = dirname($filename);
+
+ $sofar = '';
+
+ foreach (explode('/', $parent) as $part) {
+ if (empty($part)) {
+ continue;
+ }
+ $sofar .= '/' . $part;
+ if (!is_dir($sofar)) {
+ $this->debug("Creating new directory '$sofar'");
+ $success = mkdir($sofar, 0750);
+ if (!$success) {
+ $this->log(LOG_ERR, "Can't create directory '$sofar'");
+ return false;
+ }
+ }
+ }
+
+ if (is_dir($filename)) {
+ $success = false;
+ return false;
+ }
+
+ // Write to a temp file and move to destination
+
+ $tempname = tempnam(null, 'statusnetdiskcache');
+
+ $result = file_put_contents($tempname, serialize($value));
+
+ if ($result === false) {
+ $this->log(LOG_ERR, "Couldn't write '$key' to temp file '$tempname'");
+ return false;
+ }
+
+ $result = rename($tempname, $filename);
+
+ if (!$result) {
+ $this->log(LOG_ERR, "Couldn't move temp file '$tempname' to path '$filename' for key '$key'");
+ @unlink($tempname);
+ return false;
+ }
+
+ Event::handle('EndCacheSet', array($key, $value, $flag,
+ $expiry));
+
+ return false;
+ }
+
+ /**
+ * Delete a value associated with a key
+ *
+ * @param string &$key in; Key to lookup
+ * @param boolean &$success out; whether it worked
+ *
+ * @return boolean hook success
+ */
+
+ function onStartCacheDelete(&$key, &$success)
+ {
+ $filename = $this->keyToFilename($key);
+
+ if (file_exists($filename) && !is_dir($filename)) {
+ unlink($filename);
+ }
+
+ Event::handle('EndCacheDelete', array($key));
+ return false;
+ }
+}
+
diff --git a/plugins/Enjit/README b/plugins/Enjit/README
new file mode 100644
index 000000000..03f989490
--- /dev/null
+++ b/plugins/Enjit/README
@@ -0,0 +1,5 @@
+This doesn't seem to have been functional for a while; can't find other references
+to the enjit configuration or transport enqueuing. Keeping it in case someone
+wants to bring it up to date.
+
+-- brion vibber <brion@status.net> 2009-12-03
diff --git a/plugins/Enjit/enjitqueuehandler.php b/plugins/Enjit/enjitqueuehandler.php
new file mode 100644
index 000000000..f0e706b92
--- /dev/null
+++ b/plugins/Enjit/enjitqueuehandler.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, 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/>.
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Queue handler for watching new notices and posting to enjit.
+ * @fixme is this actually being used/functional atm?
+ */
+class EnjitQueueHandler extends QueueHandler
+{
+ function transport()
+ {
+ return 'enjit';
+ }
+
+ function start()
+ {
+ $this->log(LOG_INFO, "Starting EnjitQueueHandler");
+ $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl'));
+ return true;
+ }
+
+ function handle_notice($notice)
+ {
+
+ $profile = Profile::staticGet($notice->profile_id);
+
+ $this->log(LOG_INFO, "Posting Notice ".$notice->id." from ".$profile->nickname);
+
+ if ( ! $notice->is_local ) {
+ $this->log(LOG_INFO, "Skipping remote notice");
+ return "skipped";
+ }
+
+ #
+ # Build an Atom message from the notice
+ #
+ $noticeurl = common_local_url('shownotice', array('notice' => $notice->id));
+ $msg = $profile->nickname . ': ' . $notice->content;
+
+ $atom = "<entry xmlns='http://www.w3.org/2005/Atom'>\n";
+ $atom .= "<apisource>".common_config('enjit','source')."</apisource>\n";
+ $atom .= "<source>\n";
+ $atom .= "<title>" . $profile->nickname . " - " . common_config('site', 'name') . "</title>\n";
+ $atom .= "<link href='" . $profile->profileurl . "'/>\n";
+ $atom .= "<link rel='self' type='application/rss+xml' href='" . common_local_url('userrss', array('nickname' => $profile->nickname)) . "'/>\n";
+ $atom .= "<author><name>" . $profile->nickname . "</name></author>\n";
+ $atom .= "<icon>" . $profile->avatarUrl(AVATAR_PROFILE_SIZE) . "</icon>\n";
+ $atom .= "</source>\n";
+ $atom .= "<title>" . htmlspecialchars($msg) . "</title>\n";
+ $atom .= "<summary>" . htmlspecialchars($msg) . "</summary>\n";
+ $atom .= "<link rel='alternate' href='" . $noticeurl . "' />\n";
+ $atom .= "<id>". $notice->uri . "</id>\n";
+ $atom .= "<published>".common_date_w3dtf($notice->created)."</published>\n";
+ $atom .= "<updated>".common_date_w3dtf($notice->modified)."</updated>\n";
+ $atom .= "</entry>\n";
+
+ $url = common_config('enjit', 'apiurl') . "/submit/". common_config('enjit','apikey');
+ $data = array(
+ 'msg' => $atom,
+ );
+
+ #
+ # POST the message to $config['enjit']['apiurl']
+ #
+ $request = HTTPClient::start();
+ $response = $request->post($url, null, $data);
+
+ return $response->isOk();
+ }
+
+}
diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php
index de91bf24a..4266b886d 100644
--- a/plugins/Facebook/FacebookPlugin.php
+++ b/plugins/Facebook/FacebookPlugin.php
@@ -114,6 +114,9 @@ class FacebookPlugin extends Plugin
case 'FBCSettingsNav':
include_once INSTALLDIR . '/plugins/Facebook/FBCSettingsNav.php';
return false;
+ case 'FacebookQueueHandler':
+ include_once INSTALLDIR . '/plugins/Facebook/facebookqueuehandler.php';
+ return false;
default:
return true;
}
@@ -508,50 +511,15 @@ class FacebookPlugin extends Plugin
}
/**
- * broadcast the message when not using queuehandler
+ * Register Facebook notice queue handler
*
- * @param Notice &$notice the notice
- * @param array $queue destination queue
+ * @param QueueManager $manager
*
* @return boolean hook return
*/
-
- function onUnqueueHandleNotice(&$notice, $queue)
- {
- if (($queue == 'facebook') && ($this->_isLocal($notice))) {
- facebookBroadcastNotice($notice);
- return false;
- }
- return true;
- }
-
- /**
- * Determine whether the notice was locally created
- *
- * @param Notice $notice the notice
- *
- * @return boolean locality
- */
-
- function _isLocal($notice)
- {
- return ($notice->is_local == Notice::LOCAL_PUBLIC ||
- $notice->is_local == Notice::LOCAL_NONPUBLIC);
- }
-
- /**
- * Add Facebook queuehandler to the list of daemons to start
- *
- * @param array $daemons the list fo daemons to run
- *
- * @return boolean hook return
- *
- */
-
- function onGetValidDaemons($daemons)
+ function onEndInitializeQueueManager($manager)
{
- array_push($daemons, INSTALLDIR .
- '/plugins/Facebook/facebookqueuehandler.php');
+ $manager->connect('facebook', 'FacebookQueueHandler');
return true;
}
diff --git a/plugins/Facebook/facebookqueuehandler.php b/plugins/Facebook/facebookqueuehandler.php
index e4ae7d4ee..1778690e5 100755..100644
--- a/plugins/Facebook/facebookqueuehandler.php
+++ b/plugins/Facebook/facebookqueuehandler.php
@@ -1,4 +1,3 @@
-#!/usr/bin/env php
<?php
/*
* StatusNet - the distributed open-source microblogging tool
@@ -18,21 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-define('INSTALLDIR', realpath(dirname(__FILE__) . '/../..'));
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-$shortoptions = 'i::';
-$longoptions = array('id::');
-
-$helptext = <<<END_OF_FACEBOOK_HELP
-Daemon script for pushing new notices to Facebook.
-
- -i --id Identity (default none)
-
-END_OF_FACEBOOK_HELP;
-
-require_once INSTALLDIR . '/scripts/commandline.inc';
require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
-require_once INSTALLDIR . '/lib/queuehandler.php';
class FacebookQueueHandler extends QueueHandler
{
@@ -41,33 +28,24 @@ class FacebookQueueHandler extends QueueHandler
return 'facebook';
}
- function start()
- {
- $this->log(LOG_INFO, "INITIALIZE");
- return true;
- }
-
function handle_notice($notice)
{
- return facebookBroadcastNotice($notice);
+ if ($this->_isLocal($notice)) {
+ return facebookBroadcastNotice($notice);
+ }
+ return true;
}
- function finish()
+ /**
+ * Determine whether the notice was locally created
+ *
+ * @param Notice $notice the notice
+ *
+ * @return boolean locality
+ */
+ function _isLocal($notice)
{
+ return ($notice->is_local == Notice::LOCAL_PUBLIC ||
+ $notice->is_local == Notice::LOCAL_NONPUBLIC);
}
-
}
-
-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;
-}
-
-$handler = new FacebookQueueHandler($id);
-
-$handler->runOnce();
diff --git a/plugins/Imap/ImapPlugin.php b/plugins/Imap/ImapPlugin.php
index d9768b680..89a775a16 100644
--- a/plugins/Imap/ImapPlugin.php
+++ b/plugins/Imap/ImapPlugin.php
@@ -46,8 +46,6 @@ class ImapPlugin extends Plugin
public $user;
public $password;
public $poll_frequency = 60;
- public static $instances = array();
- public static $daemon_added = array();
function initialize(){
if(!isset($this->mailbox)){
@@ -63,24 +61,34 @@ class ImapPlugin extends Plugin
throw new Exception("must specify a poll_frequency");
}
- self::$instances[] = $this;
return true;
}
- function cleanup(){
- $index = array_search($this, self::$instances);
- unset(self::$instances[$index]);
- return true;
+ /**
+ * Load related modules when needed
+ *
+ * @param string $cls Name of the class to be loaded
+ *
+ * @return boolean hook value; true means continue processing, false means stop.
+ */
+ function onAutoload($cls)
+ {
+ $dir = dirname(__FILE__);
+
+ switch ($cls)
+ {
+ case 'ImapManager':
+ case 'IMAPMailHandler':
+ include_once $dir . '/'.strtolower($cls).'.php';
+ return false;
+ default:
+ return true;
+ }
}
- function onGetValidDaemons($daemons)
+ function onStartIoManagerClasses(&$classes)
{
- if(! self::$daemon_added){
- array_push($daemons, INSTALLDIR .
- '/plugins/Imap/imapdaemon.php');
- self::$daemon_added = true;
- }
- return true;
+ $classes[] = new ImapManager($this);
}
function onPluginVersion(&$versions)
diff --git a/plugins/Imap/imapdaemon.php b/plugins/Imap/imapdaemon.php
deleted file mode 100755
index 7e60e1376..000000000
--- a/plugins/Imap/imapdaemon.php
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/env php
-<?php
-/*
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, StatusNet, 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 = 'fi::';
-$longoptions = array('id::', 'foreground');
-
-$helptext = <<<END_OF_IMAP_HELP
-Daemon script for receiving new notices from users via a mail box (IMAP, POP3, etc)
-
- -i --id Identity (default none)
- -f --foreground Stay in the foreground (default background)
-
-END_OF_IMAP_HELP;
-
-require_once INSTALLDIR.'/scripts/commandline.inc';
-
-require_once INSTALLDIR . '/lib/common.php';
-require_once INSTALLDIR . '/lib/daemon.php';
-require_once INSTALLDIR.'/lib/mailhandler.php';
-
-class IMAPDaemon extends Daemon
-{
- function __construct($resource=null, $daemonize=true, $attrs)
- {
- parent::__construct($daemonize);
-
- foreach ($attrs as $attr=>$value)
- {
- $this->$attr = $value;
- }
-
- $this->log(LOG_INFO, "INITIALIZE IMAPDaemon {" . $this->name() . "}");
- }
-
- function name()
- {
- return strtolower('imapdaemon.'.$this->user.'.'.crc32($this->mailbox));
- }
-
- function run()
- {
- $this->connect();
- while(true)
- {
- if(imap_ping($this->conn) || $this->connect())
- {
- $this->check_mailbox();
- }
- sleep($this->poll_frequency);
- }
- }
-
- function check_mailbox()
- {
- $count = imap_num_msg($this->conn);
- $this->log(LOG_INFO, "Found $count messages");
- if($count > 0){
- $handler = new IMAPMailHandler();
- for($i=1; $i <= $count; $i++)
- {
- $rawmessage = imap_fetchheader($this->conn, $count, FT_PREFETCHTEXT) . imap_body($this->conn, $i);
- $handler->handle_message($rawmessage);
- imap_delete($this->conn, $i);
- }
- imap_expunge($this->conn);
- $this->log(LOG_INFO, "Finished processing messages");
- }
- }
-
- function log($level, $msg)
- {
- $text = $this->name() . ': '.$msg;
- common_log($level, $text);
- if (!$this->daemonize)
- {
- $line = common_log_line($level, $text);
- echo $line;
- echo "\n";
- }
- }
-
- function connect()
- {
- $this->conn = imap_open($this->mailbox, $this->user, $this->password);
- if($this->conn){
- $this->log(LOG_INFO, "Connected");
- return true;
- }else{
- $this->log(LOG_INFO, "Failed to connect: " . imap_last_error());
- return false;
- }
- }
-}
-
-class IMAPMailHandler extends MailHandler
-{
- function error($from, $msg)
- {
- $this->log(LOG_INFO, "Error: $from $msg");
- $headers['To'] = $from;
- $headers['Subject'] = _m('Error');
-
- return mail_send(array($from), $headers, $msg);
- }
-}
-
-if (have_option('i', 'id')) {
- $id = get_option_value('i', 'id');
-} else if (count($args) > 0) {
- $id = $args[0];
-} else {
- $id = null;
-}
-
-$foreground = have_option('f', 'foreground');
-
-foreach(ImapPlugin::$instances as $pluginInstance){
-
- $daemon = new IMAPDaemon($id, !$foreground, array(
- 'mailbox' => $pluginInstance->mailbox,
- 'user' => $pluginInstance->user,
- 'password' => $pluginInstance->password,
- 'poll_frequency' => $pluginInstance->poll_frequency
- ));
-
- $daemon->runOnce();
-
-}
diff --git a/plugins/Imap/imapmailhandler.php b/plugins/Imap/imapmailhandler.php
new file mode 100644
index 000000000..3d4b6113a
--- /dev/null
+++ b/plugins/Imap/imapmailhandler.php
@@ -0,0 +1,32 @@
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, 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/>.
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+
+class IMAPMailHandler extends MailHandler
+{
+ function error($from, $msg)
+ {
+ $this->log(LOG_INFO, "Error: $from $msg");
+ $headers['To'] = $from;
+ $headers['Subject'] = _m('Error');
+
+ return mail_send(array($from), $headers, $msg);
+ }
+}
diff --git a/plugins/Imap/imapmanager.php b/plugins/Imap/imapmanager.php
new file mode 100644
index 000000000..e4fda5809
--- /dev/null
+++ b/plugins/Imap/imapmanager.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * IMAP IO Manager
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @copyright 2009-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/
+ */
+
+class ImapManager extends IoManager
+{
+ protected $conn = null;
+
+ function __construct($plugin)
+ {
+ $this->plugin = $plugin;
+ }
+
+ /**
+ * Fetch the singleton manager for the current site.
+ * @return mixed ImapManager, or false if unneeded
+ */
+ public static function get()
+ {
+ throw new Exception('ImapManager should be created using it\'s constructor, not the static get method');
+ }
+
+ /**
+ * Lists the IM connection socket to allow i/o master to wake
+ * when input comes in here as well as from the queue source.
+ *
+ * @return array of resources
+ */
+ public function getSockets()
+ {
+ return array();
+ }
+
+ /**
+ * Tell the i/o master we need one instance for each supporting site
+ * being handled in this process.
+ */
+ public static function multiSite()
+ {
+ return IoManager::INSTANCE_PER_SITE;
+ }
+
+ /**
+ * Initialize connection to server.
+ * @return boolean true on success
+ */
+ public function start($master)
+ {
+ if(parent::start($master))
+ {
+ $this->conn = $this->connect();
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ public function handleInput($socket)
+ {
+ $this->check_mailbox();
+ return true;
+ }
+
+ public function poll()
+ {
+ return $this->check_mailbox() > 0;
+ }
+
+ function pollInterval()
+ {
+ return $this->plugin->poll_frequency;
+ }
+
+ protected function connect()
+ {
+ $this->conn = imap_open($this->plugin->mailbox, $this->plugin->user, $this->plugin->password);
+ if($this->conn){
+ common_log(LOG_INFO, "Connected");
+ return $this->conn;
+ }else{
+ common_log(LOG_INFO, "Failed to connect: " . imap_last_error());
+ return $this->conn;
+ }
+ }
+
+ protected function check_mailbox()
+ {
+ imap_ping($this->conn);
+ $count = imap_num_msg($this->conn);
+ common_log(LOG_INFO, "Found $count messages");
+ if($count > 0){
+ $handler = new IMAPMailHandler();
+ for($i=1; $i <= $count; $i++)
+ {
+ $rawmessage = imap_fetchheader($this->conn, $count, FT_PREFETCHTEXT) . imap_body($this->conn, $i);
+ $handler->handle_message($rawmessage);
+ imap_delete($this->conn, $i);
+ }
+ imap_expunge($this->conn);
+ common_log(LOG_INFO, "Finished processing messages");
+ }
+ return $count;
+ }
+}
diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php
index 15e57ab0e..8e44beae1 100644
--- a/plugins/LinkbackPlugin.php
+++ b/plugins/LinkbackPlugin.php
@@ -126,6 +126,7 @@ class LinkbackPlugin extends Plugin
if (!extension_loaded('xmlrpc')) {
if (!dl('xmlrpc.so')) {
common_log(LOG_ERR, "Can't pingback; xmlrpc extension not available.");
+ return;
}
}
diff --git a/plugins/MemcachePlugin.php b/plugins/MemcachePlugin.php
index 5f93e9a83..fbc2802f7 100644
--- a/plugins/MemcachePlugin.php
+++ b/plugins/MemcachePlugin.php
@@ -133,6 +133,23 @@ class MemcachePlugin extends Plugin
return false;
}
+ function onStartCacheReconnect(&$success)
+ {
+ if (empty($this->_conn)) {
+ // nothing to do
+ return true;
+ }
+ if ($this->persistent) {
+ common_log(LOG_ERR, "Cannot close persistent memcached connection");
+ $success = false;
+ } else {
+ common_log(LOG_INFO, "Closing memcached connection");
+ $success = $this->_conn->close();
+ $this->_conn = null;
+ }
+ return false;
+ }
+
/**
* Ensure that a connection exists
*
diff --git a/plugins/PubSubHubBub/PubSubHubBubPlugin.php b/plugins/PubSubHubBub/PubSubHubBubPlugin.php
index c40d906a5..367b35403 100644
--- a/plugins/PubSubHubBub/PubSubHubBubPlugin.php
+++ b/plugins/PubSubHubBub/PubSubHubBubPlugin.php
@@ -95,14 +95,16 @@ class PubSubHubBubPlugin extends Plugin
}
//feed of each user that subscribes to the notice's author
- $notice_inbox = new Notice_inbox();
- $notice_inbox->notice_id = $notice->id;
- if ($notice_inbox->find()) {
- while ($notice_inbox->fetch()) {
- $user = User::staticGet('id',$notice_inbox->user_id);
- $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'rss'));
- $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'atom'));
+
+ $ni = $notice->whoGets();
+
+ foreach (array_keys($ni) as $user_id) {
+ $user = User::staticGet('id', $user_id);
+ if (empty($user)) {
+ continue;
}
+ $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'rss'));
+ $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'atom'));
}
//feed of user replied to
diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php
index 21e465b53..89640f5be 100644
--- a/plugins/Realtime/RealtimePlugin.php
+++ b/plugins/Realtime/RealtimePlugin.php
@@ -154,14 +154,11 @@ class RealtimePlugin extends Plugin
// Add to inbox timelines
// XXX: do a join
- $inbox = new Notice_inbox();
- $inbox->notice_id = $notice->id;
+ $ni = $notice->whoGets();
- if ($inbox->find()) {
- while ($inbox->fetch()) {
- $user = User::staticGet('id', $inbox->user_id);
- $paths[] = array('all', $user->nickname);
- }
+ foreach (array_keys($ni) as $user_id) {
+ $user = User::staticGet('id', $user_id);
+ $paths[] = array('all', $user->nickname);
}
// Add to the replies timeline
diff --git a/plugins/SubscriptionThrottlePlugin.php b/plugins/SubscriptionThrottlePlugin.php
new file mode 100644
index 000000000..114113360
--- /dev/null
+++ b/plugins/SubscriptionThrottlePlugin.php
@@ -0,0 +1,175 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * Plugin to throttle subscriptions by a user
+ *
+ * PHP version 5
+ *
+ * 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 Throttle
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * Subscription throttle
+ *
+ * @category Throttle
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+class SubscriptionThrottlePlugin extends Plugin
+{
+ public $subLimits = array(86400 => 100,
+ 3600 => 50);
+
+ public $groupLimits = array(86400 => 50,
+ 3600 => 25);
+
+ /**
+ * Filter subscriptions to see if they're coming too fast.
+ *
+ * @param User $user The user subscribing
+ * @param User $other The user being subscribed to
+ *
+ * @return boolean hook value
+ */
+
+ function onStartSubscribe($user, $other)
+ {
+ foreach ($this->subLimits as $seconds => $limit) {
+ $sub = $this->_getNthSub($user, $limit);
+
+ if (!empty($sub)) {
+ $subtime = strtotime($sub->created);
+ $now = time();
+ if ($now - $subtime < $seconds) {
+ throw new Exception(_("Too many subscriptions. Take a break and try again later."));
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Filter group joins to see if they're coming too fast.
+ *
+ * @param Group $group The group being joined
+ * @param User $user The user joining
+ *
+ * @return boolean hook value
+ */
+
+ function onStartJoinGroup($group, $user)
+ {
+ foreach ($this->groupLimits as $seconds => $limit) {
+ $mem = $this->_getNthMem($user, $limit);
+ if (!empty($mem)) {
+
+ $jointime = strtotime($mem->created);
+ $now = time();
+ if ($now - $jointime < $seconds) {
+ throw new Exception(_("Too many memberships. Take a break and try again later."));
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the Nth most recent subscription for this user
+ *
+ * @param User $user The user to get subscriptions for
+ * @param integer $n How far to count back
+ *
+ * @return Subscription a subscription or null
+ */
+
+ private function _getNthSub($user, $n)
+ {
+ $sub = new Subscription();
+
+ $sub->subscriber = $user->id;
+ $sub->orderBy('created DESC');
+ $sub->limit($n - 1, 1);
+
+ if ($sub->find(true)) {
+ return $sub;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the Nth most recent group membership for this user
+ *
+ * @param User $user The user to get memberships for
+ * @param integer $n How far to count back
+ *
+ * @return Group_member a membership or null
+ */
+
+ private function _getNthMem($user, $n)
+ {
+ $mem = new Group_member();
+
+ $mem->profile_id = $user->id;
+ $mem->orderBy('created DESC');
+ $mem->limit($n - 1, 1);
+
+ if ($mem->find(true)) {
+ return $mem;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return plugin version data for display
+ *
+ * @param array &$versions Array of version arrays
+ *
+ * @return boolean hook value
+ */
+
+ function onPluginVersion(&$versions)
+ {
+ $versions[] = array('name' => 'SubscriptionThrottle',
+ 'version' => STATUSNET_VERSION,
+ 'author' => 'Evan Prodromou',
+ 'homepage' => 'http://status.net/wiki/Plugin:SubscriptionThrottle',
+ 'rawdescription' =>
+ _m('Configurable limits for subscriptions and group memberships.'));
+ return true;
+ }
+}
+
diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php
index a87ee2894..57b3c1c99 100644
--- a/plugins/TwitterBridge/TwitterBridgePlugin.php
+++ b/plugins/TwitterBridge/TwitterBridgePlugin.php
@@ -112,7 +112,9 @@ class TwitterBridgePlugin extends Plugin
strtolower(mb_substr($cls, 0, -6)) . '.php';
return false;
case 'TwitterOAuthClient':
- include_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php';
+ case 'TwitterQueueHandler':
+ include_once INSTALLDIR . '/plugins/TwitterBridge/' .
+ strtolower($cls) . '.php';
return false;
default:
return true;
@@ -139,48 +141,15 @@ class TwitterBridgePlugin extends Plugin
}
/**
- * broadcast the message when not using queuehandler
- *
- * @param Notice &$notice the notice
- * @param array $queue destination queue
- *
- * @return boolean hook return
- */
- function onUnqueueHandleNotice(&$notice, $queue)
- {
- if (($queue == 'twitter') && ($this->_isLocal($notice))) {
- broadcast_twitter($notice);
- return false;
- }
- return true;
- }
-
- /**
- * Determine whether the notice was locally created
- *
- * @param Notice $notice
- *
- * @return boolean locality
- */
- function _isLocal($notice)
- {
- return ($notice->is_local == Notice::LOCAL_PUBLIC ||
- $notice->is_local == Notice::LOCAL_NONPUBLIC);
- }
-
- /**
* Add Twitter bridge daemons to the list of daemons to start
*
* @param array $daemons the list fo daemons to run
*
* @return boolean hook return
- *
*/
function onGetValidDaemons($daemons)
{
array_push($daemons, INSTALLDIR .
- '/plugins/TwitterBridge/daemons/twitterqueuehandler.php');
- array_push($daemons, INSTALLDIR .
'/plugins/TwitterBridge/daemons/synctwitterfriends.php');
if (common_config('twitterimport', 'enabled')) {
@@ -191,6 +160,19 @@ class TwitterBridgePlugin extends Plugin
return true;
}
+ /**
+ * Register Twitter notice queue handler
+ *
+ * @param QueueManager $manager
+ *
+ * @return boolean hook return
+ */
+ function onEndInitializeQueueManager($manager)
+ {
+ $manager->connect('twitter', 'TwitterQueueHandler');
+ return true;
+ }
+
function onPluginVersion(&$versions)
{
$versions[] = array('name' => 'TwitterBridge',
diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php
index b4ca12be2..36732ce46 100755
--- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php
+++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php
@@ -268,19 +268,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon
}
- if (!Notice_inbox::pkeyGet(array('notice_id' => $notice->id,
- 'user_id' => $flink->user_id))) {
- // Add to inbox
- $inbox = new Notice_inbox();
-
- $inbox->user_id = $flink->user_id;
- $inbox->notice_id = $notice->id;
- $inbox->created = $notice->created;
- $inbox->source = NOTICE_INBOX_SOURCE_GATEWAY; // From a private source
-
- $inbox->insert();
-
- }
+ Inbox::insertNotice($flink->user_id, $notice->id);
$notice->blowCaches();
diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php
index e133ce6f7..33dfb788b 100644
--- a/plugins/TwitterBridge/twitter.php
+++ b/plugins/TwitterBridge/twitter.php
@@ -269,19 +269,23 @@ function process_error($e, $flink, $notice)
common_log(LOG_WARNING, $logmsg);
- if ($code == 401) {
-
+ switch($code) {
+ case 401:
// Probably a revoked or otherwise bad access token - nuke!
-
remove_twitter_link($flink);
return true;
-
- } else {
+ break;
+ case 403:
+ // User has exceeder her rate limit -- toss the notice
+ return true;
+ break;
+ default:
// For every other case, it's probably some flakiness so try
// sending the notice again later (requeue).
return false;
+ break;
}
}
diff --git a/plugins/TwitterBridge/daemons/twitterqueuehandler.php b/plugins/TwitterBridge/twitterqueuehandler.php
index f0e76bb74..5089ca7b7 100755..100644
--- a/plugins/TwitterBridge/daemons/twitterqueuehandler.php
+++ b/plugins/TwitterBridge/twitterqueuehandler.php
@@ -1,4 +1,3 @@
-#!/usr/bin/env php
<?php
/*
* StatusNet - the distributed open-source microblogging tool
@@ -18,20 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-$shortoptions = 'i::';
-$longoptions = array('id::');
-
-$helptext = <<<END_OF_ENJIT_HELP
-Daemon script for pushing new notices to Twitter.
-
- -i --id Identity (default none)
-
-END_OF_ENJIT_HELP;
-
-require_once INSTALLDIR . '/scripts/commandline.inc';
-require_once INSTALLDIR . '/lib/queuehandler.php';
require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php';
class TwitterQueueHandler extends QueueHandler
@@ -41,33 +28,8 @@ class TwitterQueueHandler extends QueueHandler
return 'twitter';
}
- function start()
- {
- $this->log(LOG_INFO, "INITIALIZE");
- return true;
- }
-
function handle_notice($notice)
{
return broadcast_twitter($notice);
}
-
- function finish()
- {
- }
-
}
-
-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;
-}
-
-$handler = new TwitterQueueHandler($id);
-
-$handler->runOnce();