From de0335fbe946d94a47247d8118b1f57f0f4843aa Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 20 Jun 2009 22:36:56 -0700 Subject: add TOS to footer menu if brought-by available --- lib/action.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index 89a8c8f4d..77a8ee391 100644 --- a/lib/action.php +++ b/lib/action.php @@ -247,7 +247,6 @@ class Action extends HTMLOutputter // lawsuit 'src' => common_path('js/jquery.joverlay.min.js')), ' '); - Event::handle('EndShowJQueryScripts', array($this)); } if (Event::handle('StartShowLaconicaScripts', array($this))) { @@ -704,6 +703,11 @@ class Action extends HTMLOutputter // lawsuit _('About')); $this->menuItem(common_local_url('doc', array('title' => 'faq')), _('FAQ')); + $bb = common_config('site', 'broughtby'); + if (!empty($bb)) { + $this->menuItem(common_local_url('doc', array('title' => 'tos')), + _('TOS')); + } $this->menuItem(common_local_url('doc', array('title' => 'privacy')), _('Privacy')); $this->menuItem(common_local_url('doc', array('title' => 'source')), -- cgit v1.2.3-54-g00ecf From 56496a2cb56263fed1eb53313057686f9fd55b63 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 24 Jun 2009 21:31:10 +1200 Subject: add missing group by item, to make database that aren't mysql happy --- lib/popularnoticesection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/popularnoticesection.php b/lib/popularnoticesection.php index 375d5538b..e47c9b385 100644 --- a/lib/popularnoticesection.php +++ b/lib/popularnoticesection.php @@ -68,7 +68,7 @@ class PopularNoticeSection extends NoticeSection } $qry .= ' GROUP BY notice.id,notice.profile_id,notice.content,notice.uri,' . 'notice.rendered,notice.url,notice.created,notice.modified,' . - 'notice.reply_to,notice.is_local,notice.source ' . + 'notice.reply_to,notice.is_local,notice.source,notice.conversation ' . 'ORDER BY weight DESC'; $offset = 0; -- cgit v1.2.3-54-g00ecf From e5b758dbbef6774943abf453a43114a2c3371b4a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 28 Jun 2009 14:38:31 -0400 Subject: start of queuemanager code --- lib/dbqueuemanager.php | 106 ++++++++++++++++++++++++++++++++++++++++ lib/queuemanager.php | 78 +++++++++++++++++++++++++++++ lib/stompqueuemanager.php | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 lib/dbqueuemanager.php create mode 100644 lib/queuemanager.php create mode 100644 lib/stompqueuemanager.php (limited to 'lib') diff --git a/lib/dbqueuemanager.php b/lib/dbqueuemanager.php new file mode 100644 index 000000000..c0d4dcd29 --- /dev/null +++ b/lib/dbqueuemanager.php @@ -0,0 +1,106 @@ +. + * + * @category QueueManager + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class DBQueueManager extends QueueManager +{ + var $qis = array(); + + function enqueue($object, $queue) + { + $notice = (Notice)$object; + + $qi = new Queue_item(); + + $qi->notice_id = $notice->id; + $qi->transport = $queue; + $qi->created = $notice->created; + $result = $qi->insert(); + + if (!$result) { + common_log_db_error($qi, 'INSERT', __FILE__); + throw new ServerException('DB error inserting queue item'); + } + + return true; + } + + function nextItem($queue, $timeout=null) + { + $start = time(); + $result = null; + + do { + $qi = Queue_item::top($queue); + if (!empty($qi)) { + $notice = Notice::staticGet('id', $qi->notice_id); + if (!empty($notice)) { + $result = $notice; + } else { + $this->_log(LOG_INFO, 'dequeued non-existent notice ' . $notice->id); + $qi->delete(); + $qi->free(); + $qi = null; + } + } + } while (empty($result) && (is_null($timeout) || (time() - $start) < $timeout)); + + return $result; + } + + function done($object, $queue) + { + $notice = (Notice)$object; + + $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, + 'transport' => $queue)); + + if (empty($qi)) { + $this->log(LOG_INFO, 'Cannot find queue item for notice '.$notice->id.', queue '.$queue); + } else { + if (empty($qi->claimed)) { + $this->log(LOG_WARNING, 'Reluctantly releasing unclaimed queue item '. + 'for '.$notice->id.', queue '.$queue); + } + $qi->delete(); + $qi->free(); + $qi = null; + } + + $this->log(LOG_INFO, 'done with notice ID = ' . $notice->id); + + $notice->free(); + $notice = null; + } + + function _log($level, $msg) + { + common_log($level, 'DBQueueManager: '.$msg); + } +} diff --git a/lib/queuemanager.php b/lib/queuemanager.php new file mode 100644 index 000000000..64aca1bc1 --- /dev/null +++ b/lib/queuemanager.php @@ -0,0 +1,78 @@ +. + * + * @category QueueManager + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class QueueManager +{ + static $qm = null; + + static function get() + { + if (empty(self::$qm)) { + + if (Event::handle('StartNewQueueManager', self::$qm)) { + + $type = common_config('queue', 'sub'); + + switch ($type) { + case 'db': + self::$qm = new DBQueueManager(); + break; + case 'stomp': + self::$qm = new StompQueueManager(); + break; + default: + throw new ServerException("No queue manager class for type '$type'"); + } + } + + return self::$qm; + } + } + + function enqueue($object, $queue) + { + throw ServerException("Unimplemented function 'enqueue' called"); + } + + function peek($queue) + { + throw ServerException("Unimplemented function 'peek' called"); + } + + function nextItem($queue, $timeout=null) + { + throw ServerException("Unimplemented function 'nextItem' called"); + } + + function done($object, $queue) + { + throw ServerException("Unimplemented function 'done' called"); + } +} diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php new file mode 100644 index 000000000..20c6e7a34 --- /dev/null +++ b/lib/stompqueuemanager.php @@ -0,0 +1,122 @@ +. + * + * @category QueueManager + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +require_once 'Stomp.php'; + +class QueueManager +{ + var $server = null; + var $username = null; + var $password = null; + var $base = null; + var $con = null; + var $frames = array(); + + function __construct() + { + $this->server = common_config('queue', 'stomp_server'); + $this->username = common_config('queue', 'stomp_username'); + $this->password = common_config('queue', 'stomp_password'); + $this->base = common_config('queue', 'queue_basename'); + } + + function _connect() + { + if (empty($this->con)) { + $this->con = new Stomp($this->server); + + if (!$this->con->connect($this->username, $this->password)) { + $this->_log(LOG_ERR, 'Failed to connect to queue server'); + throw new ServerException('Failed to connect to queue server'); + } + } + } + + function enqueue($object, $queue) + { + $notice = (Notice)$object; + + $this->_connect(); + + $result = $this->con->send($this->_queueName($queue), + $notice->id, // BODY of the message + array ('created' => $notice->created)); + + if (!$result) { + common_log(LOG_ERR, 'Error sending to '.$transport.' queue'); + return false; + } + + common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' + . $notice->id . ' for ' . $transport); + } + + function nextItem($queue, $timeout=null) + { + $result = null; + + $this->_connect(); + + $frame = $this->con->readFrame(); + + if ($frame) { + $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($frame->headers['created'])); + + // XXX: Now the queue handler receives only the ID of the + // notice, and it has to get it from the DB + // A massive improvement would be avoid DB query by transmitting + // all the notice details via queue server... + $notice = Notice::staticGet($frame->body); + + if ($notice) { + } else { + $this->log(LOG_WARNING, 'queue item for notice that does not exist'); + } + } + } + + function done($object, $queue) + { + $notice = (Notice)$object; + + $this->_connect(); + + $frame = $this->_getFrame($notice, $queue); + + if (empty($frame)) { + $this->log(LOG_ERR, 'Cannot find frame for notice '.$notice->id.' in queue '.$queue); + } else { + // if the msg has been handled positively, ack it + // and the queue server will remove it from the queue + $this->con->ack($frame); + $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); + } + } +} -- cgit v1.2.3-54-g00ecf From 854c82cfd53cb071afa39259fb467b4730bd6494 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 28 Jun 2009 14:38:34 -0400 Subject: start of queuemanager code --- classes/Queue_item.php | 11 ++++++-- lib/util.php | 75 -------------------------------------------------- 2 files changed, 8 insertions(+), 78 deletions(-) (limited to 'lib') diff --git a/classes/Queue_item.php b/classes/Queue_item.php index 9b909ec22..295c321b5 100644 --- a/classes/Queue_item.php +++ b/classes/Queue_item.php @@ -4,7 +4,7 @@ */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -class Queue_item extends Memcached_DataObject +class Queue_item extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -13,7 +13,7 @@ class Queue_item extends Memcached_DataObject public $notice_id; // int(4) primary_key not_null public $transport; // varchar(8) primary_key not_null public $created; // datetime() not_null - public $claimed; // datetime() + public $claimed; // datetime() /* Static get */ function staticGet($k,$v=null) @@ -24,7 +24,7 @@ class Queue_item extends Memcached_DataObject function sequenceKey() { return array(false, false); } - + static function top($transport) { $qi = new Queue_item(); @@ -54,4 +54,9 @@ class Queue_item extends Memcached_DataObject $qi = null; return null; } + + function &pkeyGet($kv) + { + return Memcached_DataObject::pkeyGet('Queue_item', $kv); + } } diff --git a/lib/util.php b/lib/util.php index 9c1af7a0d..3f924c8de 100644 --- a/lib/util.php +++ b/lib/util.php @@ -889,69 +889,6 @@ function common_enqueue_notice($notice) return $result; } -function common_enqueue_notice_stomp($notice, $transports) -{ - // use an external message queue system via STOMP - require_once("Stomp.php"); - - $server = common_config('queue','stomp_server'); - $username = common_config('queue', 'stomp_username'); - $password = common_config('queue', 'stomp_password'); - - $con = new Stomp($server); - - if (!$con->connect($username, $password)) { - common_log(LOG_ERR, 'Failed to connect to queue server'); - return false; - } - - $queue_basename = common_config('queue','queue_basename'); - - foreach ($transports as $transport) { - $result = $con->send('/queue/'.$queue_basename.'-'.$transport, // QUEUE - $notice->id, // BODY of the message - array ('created' => $notice->created)); - if (!$result) { - common_log(LOG_ERR, 'Error sending to '.$transport.' queue'); - return false; - } - common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' . $notice->id . ' for ' . $transport); - } - - //send tags as headers, so they can be used as JMS selectors - common_log(LOG_DEBUG, 'searching for tags ' . $notice->id); - $tags = array(); - $tag = new Notice_tag(); - $tag->notice_id = $notice->id; - if ($tag->find()) { - while ($tag->fetch()) { - common_log(LOG_DEBUG, 'tag found = ' . $tag->tag); - array_push($tags,$tag->tag); - } - } - $tag->free(); - - $con->send('/topic/laconica.'.$notice->profile_id, - $notice->content, - array( - 'profile_id' => $notice->profile_id, - 'created' => $notice->created, - 'tags' => implode($tags,' - ') - ) - ); - common_log(LOG_DEBUG, 'sent to personal topic ' . $notice->id); - $con->send('/topic/laconica.allusers', - $notice->content, - array( - 'profile_id' => $notice->profile_id, - 'created' => $notice->created, - 'tags' => implode($tags,' - ') - ) - ); - common_log(LOG_DEBUG, 'sent to catch-all topic ' . $notice->id); - $result = true; -} - function common_enqueue_notice_db($notice, $transports) { // in any other case, 'internal' @@ -962,18 +899,6 @@ function common_enqueue_notice_db($notice, $transports) function common_enqueue_notice_transport($notice, $transport) { - $qi = new Queue_item(); - $qi->notice_id = $notice->id; - $qi->transport = $transport; - $qi->created = $notice->created; - $result = $qi->insert(); - if (!$result) { - $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError'); - common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message); - throw new ServerException('DB error inserting queue item: ' . $last_error->message); - } - common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport); - return true; } function common_real_broadcast($notice, $remote=false) -- cgit v1.2.3-54-g00ecf From 58b427869a001a91d66cff497f1563b8277f1a67 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 11:09:42 -0400 Subject: compile errors in DBQueueManager --- lib/dbqueuemanager.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/dbqueuemanager.php b/lib/dbqueuemanager.php index c0d4dcd29..46be54b30 100644 --- a/lib/dbqueuemanager.php +++ b/lib/dbqueuemanager.php @@ -34,7 +34,7 @@ class DBQueueManager extends QueueManager function enqueue($object, $queue) { - $notice = (Notice)$object; + $notice = $object; $qi = new Queue_item(); @@ -76,7 +76,9 @@ class DBQueueManager extends QueueManager function done($object, $queue) { - $notice = (Notice)$object; + // XXX: right now, we only handle notices + + $notice = $object; $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, 'transport' => $queue)); -- cgit v1.2.3-54-g00ecf From 4c256a6d7ee287def5c26f401c8caa6bfe0b8dff Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 11:09:58 -0400 Subject: better hook variables for StartQueueManager --- lib/queuemanager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/queuemanager.php b/lib/queuemanager.php index 64aca1bc1..92f0e10de 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -36,9 +36,9 @@ class QueueManager { if (empty(self::$qm)) { - if (Event::handle('StartNewQueueManager', self::$qm)) { + $type = common_config('queue', 'sub'); - $type = common_config('queue', 'sub'); + if (Event::handle('StartNewQueueManager', array($type, &self::$qm))) { switch ($type) { case 'db': -- cgit v1.2.3-54-g00ecf From 7b66a129139d8c2f03677f6a5b71412a111f655d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 11:10:23 -0400 Subject: save frames for StompQueueManager --- lib/stompqueuemanager.php | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 20c6e7a34..1b4a26f2e 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -30,7 +30,7 @@ require_once 'Stomp.php'; -class QueueManager +class StompQueueManager { var $server = null; var $username = null; @@ -61,10 +61,12 @@ class QueueManager function enqueue($object, $queue) { - $notice = (Notice)$object; + $notice = $object; $this->_connect(); + // XXX: serialize and send entire notice + $result = $this->con->send($this->_queueName($queue), $notice->id, // BODY of the message array ('created' => $notice->created)); @@ -93,9 +95,11 @@ class QueueManager // notice, and it has to get it from the DB // A massive improvement would be avoid DB query by transmitting // all the notice details via queue server... + $notice = Notice::staticGet($frame->body); if ($notice) { + $this->_saveFrame($notice, $queue, $frame); } else { $this->log(LOG_WARNING, 'queue item for notice that does not exist'); } @@ -104,7 +108,7 @@ class QueueManager function done($object, $queue) { - $notice = (Notice)$object; + $notice = $object; $this->_connect(); @@ -116,7 +120,33 @@ class QueueManager // if the msg has been handled positively, ack it // and the queue server will remove it from the queue $this->con->ack($frame); + $this->_clearFrame($notice, $queue); + $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); } } + + function _frameKey($notice, $queue) + { + return ((string)$notice->id) . '-' . $queue; + } + + function _saveFrame($notice, $queue, $frame) + { + $k = $this->_frameKey($notice, $queue); + $this->_frames[$k] = $frame; + return true; + } + + function _getFrame($notice, $queue) + { + $k = $this->_frameKey($notice, $queue); + return $this->_frames[$k]; + } + + function _clearFrame($notice, $queue) + { + $k = $this->_frameKey($notice, $queue); + unset($this->_frames[$k]); + } } -- cgit v1.2.3-54-g00ecf From e0bf8ad95b2d2ddc7b988c25e9cffa20075a5d8c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 11:34:12 -0400 Subject: Add UnQueueManager for immediate handling Perhaps it's a little precious, but I took out the switches in util.php to determine what's supposed to be sent when, and made a queuemanager class that will just do things when they're supposed to be done. --- lib/queuemanager.php | 10 ++++-- lib/unqueuemanager.php | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/util.php | 85 ++++++++++---------------------------------------- 3 files changed, 109 insertions(+), 71 deletions(-) create mode 100644 lib/unqueuemanager.php (limited to 'lib') diff --git a/lib/queuemanager.php b/lib/queuemanager.php index 92f0e10de..6bb21de9b 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -36,9 +36,15 @@ class QueueManager { if (empty(self::$qm)) { - $type = common_config('queue', 'sub'); + if (Event::handle('StartNewQueueManager', array(&self::$qm))) { - if (Event::handle('StartNewQueueManager', array($type, &self::$qm))) { + $enabled = common_config('queue', 'enabled'); + $type = common_config('queue', 'sub'); + + if (!$enabled) { + // does everything immediately + return new UnQueueManager(); + } switch ($type) { case 'db': diff --git a/lib/unqueuemanager.php b/lib/unqueuemanager.php new file mode 100644 index 000000000..515461072 --- /dev/null +++ b/lib/unqueuemanager.php @@ -0,0 +1,85 @@ +. + * + * @category QueueManager + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class UnQueueManager +{ + function enqueue($object, $queue) + { + $notice = $object; + + switch ($queue) + { + case 'omb': + if ($this->_isLocal($notice)) { + require_once(INSTALLDIR.'/lib/omb.php'); + omb_broadcast_remote_subscribers($notice); + } + break; + case 'public': + if ($this->_isLocal($notice)) { + require_once(INSTALLDIR.'/lib/jabber.php'); + jabber_public_notice($notice); + } + break; + case 'twitter': + if ($this->_isLocal($notice)) { + broadcast_twitter($notice); + } + break; + case 'facebook': + if ($this->_isLocal($notice)) { + require_once INSTALLDIR . '/lib/facebookutil.php'; + return facebookBroadcastNotice($notice); + } + break; + case 'ping': + if ($this->_isLocal($notice)) { + require_once INSTALLDIR . '/lib/ping.php'; + return ping_broadcast_notice($notice); + } + case 'sms': + require_once(INSTALLDIR.'/lib/mail.php'); + mail_broadcast_notice_sms($notice); + break; + case 'jabber': + require_once(INSTALLDIR.'/lib/jabber.php'); + jabber_broadcast_notice($notice); + break; + default: + throw ServerException("UnQueueManager: Unknown queue: $type"); + } + } + + function _isLocal($notice) + { + return ($notice->is_local == NOTICE_LOCAL_PUBLIC || + $notice->is_local == NOTICE_LOCAL_NONPUBLIC); + } +} \ No newline at end of file diff --git a/lib/util.php b/lib/util.php index 3f924c8de..b1b4faa7e 100644 --- a/lib/util.php +++ b/lib/util.php @@ -861,88 +861,35 @@ function common_redirect($url, $code=307) function common_broadcast_notice($notice, $remote=false) { - if (common_config('queue', 'enabled')) { - // Do it later! - return common_enqueue_notice($notice); - } else { - return common_real_broadcast($notice, $remote); - } + return common_enqueue_notice($notice); } // Stick the notice on the queue function common_enqueue_notice($notice) { - $transports = array('omb', 'sms', 'public', 'twitter', 'facebook', 'ping'); + static $localTransports = array('omb', + 'public', + 'twitter', + 'facebook', + 'ping'); + static $allTransports = array('sms', 'jabber'); - if (common_config('xmpp', 'enabled')) - { - $transports[] = 'jabber'; - } + $transports = $allTransports; - if (common_config('queue','subsystem') == 'stomp') { - common_enqueue_notice_stomp($notice, $transports); + if ($notice->is_local == NOTICE_LOCAL_PUBLIC || + $notice->is_local == NOTICE_LOCAL_NONPUBLIC) { + $transports = array_merge($transports, $localTransports); } - else { - common_enqueue_notice_db($notice, $transports); - } - return $result; -} -function common_enqueue_notice_db($notice, $transports) -{ - // in any other case, 'internal' - foreach ($transports as $transport) { - common_enqueue_notice_transport($notice, $transport); - } -} - -function common_enqueue_notice_transport($notice, $transport) -{ -} + $qm = QueueManager::get(); -function common_real_broadcast($notice, $remote=false) -{ - $success = true; - if (!$remote) { - // Make sure we have the OMB stuff - require_once(INSTALLDIR.'/lib/omb.php'); - $success = omb_broadcast_remote_subscribers($notice); - if (!$success) { - common_log(LOG_ERR, 'Error in OMB broadcast for notice ' . $notice->id); - } - } - if ($success) { - require_once(INSTALLDIR.'/lib/jabber.php'); - $success = jabber_broadcast_notice($notice); - if (!$success) { - common_log(LOG_ERR, 'Error in jabber broadcast for notice ' . $notice->id); - } - } - if ($success) { - require_once(INSTALLDIR.'/lib/mail.php'); - $success = mail_broadcast_notice_sms($notice); - if (!$success) { - common_log(LOG_ERR, 'Error in sms broadcast for notice ' . $notice->id); - } - } - if ($success) { - $success = jabber_public_notice($notice); - if (!$success) { - common_log(LOG_ERR, 'Error in public broadcast for notice ' . $notice->id); - } - } - if ($success) { - $success = broadcast_twitter($notice); - if (!$success) { - common_log(LOG_ERR, 'Error in Twitter broadcast for notice ' . $notice->id); - } + foreach ($transports as $transport) + { + $qm->enqueue($notice, $transport); } - // XXX: Do a real-time FB broadcast here? - - // XXX: broadcast notices to other IM - return $success; + return true; } function common_broadcast_profile($profile) -- cgit v1.2.3-54-g00ecf From 887d35cfc8c1d42e5af67d0161b244545cda464a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 12:09:18 -0400 Subject: better queue manager detection, new method fail() --- lib/queuemanager.php | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/queuemanager.php b/lib/queuemanager.php index 6bb21de9b..1bf4d4dec 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -39,22 +39,22 @@ class QueueManager if (Event::handle('StartNewQueueManager', array(&self::$qm))) { $enabled = common_config('queue', 'enabled'); - $type = common_config('queue', 'sub'); + $type = common_config('queue', 'subsystem'); if (!$enabled) { // does everything immediately - return new UnQueueManager(); - } - - switch ($type) { - case 'db': - self::$qm = new DBQueueManager(); - break; - case 'stomp': - self::$qm = new StompQueueManager(); - break; - default: - throw new ServerException("No queue manager class for type '$type'"); + self::$qm = new UnQueueManager(); + } else { + switch ($type) { + case 'db': + self::$qm = new DBQueueManager(); + break; + case 'stomp': + self::$qm = new StompQueueManager(); + break; + default: + throw new ServerException("No queue manager class for type '$type'"); + } } } @@ -81,4 +81,9 @@ class QueueManager { throw ServerException("Unimplemented function 'done' called"); } + + function fail($object, $queue) + { + throw ServerException("Unimplemented function 'fail' called"); + } } -- cgit v1.2.3-54-g00ecf From 557418bc1e4e9d8a06025910ad7be5f60557f71e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 12:09:41 -0400 Subject: better transport choices when xmpp is disabled --- lib/util.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/util.php b/lib/util.php index b1b4faa7e..656374516 100644 --- a/lib/util.php +++ b/lib/util.php @@ -869,17 +869,25 @@ function common_broadcast_notice($notice, $remote=false) function common_enqueue_notice($notice) { static $localTransports = array('omb', - 'public', 'twitter', 'facebook', 'ping'); - static $allTransports = array('sms', 'jabber'); + static $allTransports = array('sms'); $transports = $allTransports; + $xmpp = common_config('xmpp', 'enabled'); + + if ($xmpp) { + $transports[] = 'jabber'; + } + if ($notice->is_local == NOTICE_LOCAL_PUBLIC || $notice->is_local == NOTICE_LOCAL_NONPUBLIC) { $transports = array_merge($transports, $localTransports); + if ($xmpp) { + $transports[] = 'public'; + } } $qm = QueueManager::get(); -- cgit v1.2.3-54-g00ecf From 2325d934a8abfc611f455d4f0b816e2dd62c5ec4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 12:10:11 -0400 Subject: add fail() method to stompqueuemanager --- lib/stompqueuemanager.php | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 1b4a26f2e..badcd4abb 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -126,6 +126,17 @@ class StompQueueManager } } + function fail($object, $queue) + { + $notice = $object; + + // STOMP server will requeue it after a while anyways, + // so no need to notify. Just get it out of our little + // array + + $this->_clearFrame($notice, $queue); + } + function _frameKey($notice, $queue) { return ((string)$notice->id) . '-' . $queue; -- cgit v1.2.3-54-g00ecf From a35138b2684ec5275a1ffd7badfe7826cf2173b1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 12:10:25 -0400 Subject: add fail() method to dbqueuemanager and fix logging --- lib/dbqueuemanager.php | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/dbqueuemanager.php b/lib/dbqueuemanager.php index 46be54b30..c9e5ef243 100644 --- a/lib/dbqueuemanager.php +++ b/lib/dbqueuemanager.php @@ -84,10 +84,10 @@ class DBQueueManager extends QueueManager 'transport' => $queue)); if (empty($qi)) { - $this->log(LOG_INFO, 'Cannot find queue item for notice '.$notice->id.', queue '.$queue); + $this->_log(LOG_INFO, 'Cannot find queue item for notice '.$notice->id.', queue '.$queue); } else { if (empty($qi->claimed)) { - $this->log(LOG_WARNING, 'Reluctantly releasing unclaimed queue item '. + $this->_log(LOG_WARNING, 'Reluctantly releasing unclaimed queue item '. 'for '.$notice->id.', queue '.$queue); } $qi->delete(); @@ -95,7 +95,36 @@ class DBQueueManager extends QueueManager $qi = null; } - $this->log(LOG_INFO, 'done with notice ID = ' . $notice->id); + $this->_log(LOG_INFO, 'done with notice ID = ' . $notice->id); + + $notice->free(); + $notice = null; + } + + function fail($object, $queue) + { + // XXX: right now, we only handle notices + + $notice = $object; + + $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, + 'transport' => $queue)); + + if (empty($qi)) { + $this->_log(LOG_INFO, 'Cannot find queue item for notice '.$notice->id.', queue '.$queue); + } else { + if (empty($qi->claimed)) { + $this->_log(LOG_WARNING, 'Ignoring failure for unclaimed queue item '. + 'for '.$notice->id.', queue '.$queue); + } else { + $orig = clone($qi); + $qi->claimed = null; + $qi->update($orig); + $qi = null; + } + } + + $this->_log(LOG_INFO, 'done with notice ID = ' . $notice->id); $notice->free(); $notice = null; -- cgit v1.2.3-54-g00ecf From e52997e52fe02960908eb6a9637a3349a2c74dad Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Jul 2009 12:11:02 -0400 Subject: change queuehandler class to use queuemanager interface --- lib/queuehandler.php | 151 ++++++++++++++------------------------------------- 1 file changed, 41 insertions(+), 110 deletions(-) (limited to 'lib') diff --git a/lib/queuehandler.php b/lib/queuehandler.php index ae403c65e..045432ae5 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -17,17 +17,18 @@ * along with this program. If not, see . */ -define('CLAIM_TIMEOUT', 1200); - if (!defined('LACONICA')) { exit(1); } require_once(INSTALLDIR.'/lib/daemon.php'); require_once(INSTALLDIR.'/classes/Queue_item.php'); require_once(INSTALLDIR.'/classes/Notice.php'); +define('CLAIM_TIMEOUT', 1200); +define('QUEUE_HANDLER_MISS_IDLE', 10); +define('QUEUE_HANDLER_HIT_IDLE', 10); + class QueueHandler extends Daemon { - var $_id = 'generic'; function QueueHandler($id=null) @@ -37,6 +38,11 @@ class QueueHandler extends Daemon } } + function timeout() + { + return null; + } + function class_name() { return ucfirst($this->transport()) . 'Handler'; @@ -75,110 +81,45 @@ class QueueHandler extends Daemon return true; } - function db_dispatch() { - do { - $qi = Queue_item::top($this->transport()); - if ($qi) { - $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($qi->created)); - $notice = Notice::staticGet($qi->notice_id); - if ($notice) { - $this->log(LOG_INFO, 'broadcasting notice ID = ' . $notice->id); - # XXX: what to do if broadcast fails? - $result = $this->handle_notice($notice); - if (!$result) { - $this->log(LOG_WARNING, 'Failed broadcast for notice ID = ' . $notice->id); - $orig = $qi; - $qi->claimed = null; - $qi->update($orig); - $this->log(LOG_WARNING, 'Abandoned claim for notice ID = ' . $notice->id); - continue; - } - $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); - $notice->free(); - unset($notice); - $notice = null; - } else { - $this->log(LOG_WARNING, 'queue item for notice that does not exist'); - } - $qi->delete(); - $qi->free(); - unset($qi); - $this->idle(0); - } else { - $this->clear_old_claims(); - $this->idle(5); - } - } while (true); - } - - function stomp_dispatch() { - - // use an external message queue system via STOMP - require_once("Stomp.php"); + function run() + { + if (!$this->start()) { + return false; + } - $server = common_config('queue','stomp_server'); - $username = common_config('queue', 'stomp_username'); - $password = common_config('queue', 'stomp_password'); + $this->log(LOG_INFO, 'checking for queued notices'); - $con = new Stomp($server); + $queue = $this->transport(); + $timeout = $this->timeout(); - if (!$con->connect($username, $password)) { - $this->log(LOG_ERR, 'Failed to connect to queue server'); - return false; - } + $qm = QueueManager::get(); - $queue_basename = common_config('queue','queue_basename'); - // subscribe to the relevant queue (format: basename-transport) - $con->subscribe('/queue/'.$queue_basename.'-'.$this->transport()); - - do { - $frame = $con->readFrame(); - if ($frame) { - $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($frame->headers['created'])); - - // XXX: Now the queue handler receives only the ID of the - // notice, and it has to get it from the DB - // A massive improvement would be avoid DB query by transmitting - // all the notice details via queue server... - $notice = Notice::staticGet($frame->body); - - if ($notice) { - $this->log(LOG_INFO, 'broadcasting notice ID = ' . $notice->id); - $result = $this->handle_notice($notice); - if ($result) { - // if the msg has been handled positively, ack it - // and the queue server will remove it from the queue - $con->ack($frame); - $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); - } - else { - // no ack - $this->log(LOG_WARNING, 'Failed broadcast for notice ID = ' . $notice->id); - } - $notice->free(); - unset($notice); - $notice = null; + while (true) { + $this->log(LOG_DEBUG, 'Checking for notices...'); + $notice = $qm->nextItem($queue, $timeout); + if (empty($notice)) { + $this->log(LOG_DEBUG, 'No notices waiting; idling.'); + // Nothing in the queue. Do you + // have other tasks, like servicing your + // XMPP connection, to do? + $this->idle(QUEUE_HANDLER_MISS_IDLE); + } else { + $this->log(LOG_INFO, 'Got notice '. $notice->id); + // Yay! Got one! + if ($this->handle_notice($notice)) { + $this->log(LOG_INFO, 'Successfully handled notice '. $notice->id); + $qm->done($notice, $queue); } else { - $this->log(LOG_WARNING, 'queue item for notice that does not exist'); + $this->log(LOG_INFO, 'Failed to handle notice '. $notice->id); + $qm->fail($notice, $queue); } + // Chance to e.g. service your XMPP connection + $this->log(LOG_DEBUG, 'Idling after success.'); + $this->idle(QUEUE_HANDLER_HIT_IDLE); } - } while (true); - - $con->disconnect(); - } - - function run() - { - if (!$this->start()) { - return false; - } - $this->log(LOG_INFO, 'checking for queued notices'); - if (common_config('queue','subsystem') == 'stomp') { - $this->stomp_dispatch(); - } - else { - $this->db_dispatch(); + // XXX: when do we give up? } + if (!$this->finish()) { return false; } @@ -187,21 +128,11 @@ class QueueHandler extends Daemon function idle($timeout=0) { - if ($timeout>0) { + if ($timeout > 0) { sleep($timeout); } } - function clear_old_claims() - { - $qi = new Queue_item(); - $qi->transport = $this->transport(); - $qi->whereAdd('now() - claimed > '.CLAIM_TIMEOUT); - $qi->update(DB_DATAOBJECT_WHEREADD_ONLY); - $qi->free(); - unset($qi); - } - function log($level, $msg) { common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); -- cgit v1.2.3-54-g00ecf From e8f27025ba7869057d86fe37a5264e1c742969f5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 2 Jul 2009 12:43:09 -0400 Subject: more logging in stompqueuemanager --- lib/stompqueuemanager.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index badcd4abb..08a5790d4 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -49,10 +49,14 @@ class StompQueueManager function _connect() { + $this->_log(LOG_DEBUG, "Connecting to $this->server..."); if (empty($this->con)) { + $this->_log(LOG_INFO, "Connecting to '$this->server' as '$this->username'..."); $this->con = new Stomp($this->server); - if (!$this->con->connect($this->username, $this->password)) { + if ($this->con->connect($this->username, $this->password)) { + $this->_log(LOG_INFO, "Connected."); + } else { $this->_log(LOG_ERR, 'Failed to connect to queue server'); throw new ServerException('Failed to connect to queue server'); } @@ -160,4 +164,9 @@ class StompQueueManager $k = $this->_frameKey($notice, $queue); unset($this->_frames[$k]); } + + function _log($level, $msg) + { + common_log($level, 'StompQueueManager: '.$msg); + } } -- cgit v1.2.3-54-g00ecf From 3e4be98ff6de7a1044f0d7b0deef4f6054e64464 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Jul 2009 10:05:07 -0400 Subject: add _queueName function --- lib/stompqueuemanager.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 08a5790d4..1ad687036 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -165,6 +165,11 @@ class StompQueueManager unset($this->_frames[$k]); } + function _queueName($queue) + { + return common_config('queue', 'queue_basename') . $queue; + } + function _log($level, $msg) { common_log($level, 'StompQueueManager: '.$msg); -- cgit v1.2.3-54-g00ecf From 49c5c6f92bc1d06e6464eade81eead891d86f10d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 4 Jul 2009 00:31:28 -0400 Subject: move handling code into queuemanager --- lib/dbqueuemanager.php | 35 +++++++++++++++++++-- lib/queuehandler.php | 30 ++---------------- lib/queuemanager.php | 19 ++--------- lib/stompqueuemanager.php | 80 +++++++++-------------------------------------- 4 files changed, 51 insertions(+), 113 deletions(-) (limited to 'lib') diff --git a/lib/dbqueuemanager.php b/lib/dbqueuemanager.php index c9e5ef243..6e7172de0 100644 --- a/lib/dbqueuemanager.php +++ b/lib/dbqueuemanager.php @@ -51,7 +51,36 @@ class DBQueueManager extends QueueManager return true; } - function nextItem($queue, $timeout=null) + function service($queue, $handler) + { + while (true) { + $this->_log(LOG_DEBUG, 'Checking for notices...'); + $notice = $this->_nextItem($queue, null); + if (empty($notice)) { + $this->_log(LOG_DEBUG, 'No notices waiting; idling.'); + // Nothing in the queue. Do you + // have other tasks, like servicing your + // XMPP connection, to do? + $handler->idle(QUEUE_HANDLER_MISS_IDLE); + } else { + $this->_log(LOG_INFO, 'Got notice '. $notice->id); + // Yay! Got one! + if ($handler->handle_notice($notice)) { + $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id); + $this->_done($notice, $queue); + } else { + $this->_log(LOG_INFO, 'Failed to handle notice '. $notice->id); + $this->_fail($notice, $queue); + } + // Chance to e.g. service your XMPP connection + $this->_log(LOG_DEBUG, 'Idling after success.'); + $handler->idle(QUEUE_HANDLER_HIT_IDLE); + } + // XXX: when do we give up? + } + } + + function _nextItem($queue, $timeout=null) { $start = time(); $result = null; @@ -74,7 +103,7 @@ class DBQueueManager extends QueueManager return $result; } - function done($object, $queue) + function _done($object, $queue) { // XXX: right now, we only handle notices @@ -101,7 +130,7 @@ class DBQueueManager extends QueueManager $notice = null; } - function fail($object, $queue) + function _fail($object, $queue) { // XXX: right now, we only handle notices diff --git a/lib/queuehandler.php b/lib/queuehandler.php index ddb47a28e..c0f38f4e3 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -25,7 +25,7 @@ require_once(INSTALLDIR.'/classes/Notice.php'); define('CLAIM_TIMEOUT', 1200); define('QUEUE_HANDLER_MISS_IDLE', 10); -define('QUEUE_HANDLER_HIT_IDLE', 10); +define('QUEUE_HANDLER_HIT_IDLE', 0); class QueueHandler extends Daemon { @@ -42,7 +42,7 @@ class QueueHandler extends Daemon function timeout() { - return null; + return 60; } function class_name() @@ -96,31 +96,7 @@ class QueueHandler extends Daemon $qm = QueueManager::get(); - while (true) { - $this->log(LOG_DEBUG, 'Checking for notices...'); - $notice = $qm->nextItem($queue, $timeout); - if (empty($notice)) { - $this->log(LOG_DEBUG, 'No notices waiting; idling.'); - // Nothing in the queue. Do you - // have other tasks, like servicing your - // XMPP connection, to do? - $this->idle(QUEUE_HANDLER_MISS_IDLE); - } else { - $this->log(LOG_INFO, 'Got notice '. $notice->id); - // Yay! Got one! - if ($this->handle_notice($notice)) { - $this->log(LOG_INFO, 'Successfully handled notice '. $notice->id); - $qm->done($notice, $queue); - } else { - $this->log(LOG_INFO, 'Failed to handle notice '. $notice->id); - $qm->fail($notice, $queue); - } - // Chance to e.g. service your XMPP connection - $this->log(LOG_DEBUG, 'Idling after success.'); - $this->idle(QUEUE_HANDLER_HIT_IDLE); - } - // XXX: when do we give up? - } + $qm->service($queue, $this); if (!$this->finish()) { return false; diff --git a/lib/queuemanager.php b/lib/queuemanager.php index 1bf4d4dec..f36e99d16 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -67,23 +67,8 @@ class QueueManager throw ServerException("Unimplemented function 'enqueue' called"); } - function peek($queue) + function service($queue, $handler) { - throw ServerException("Unimplemented function 'peek' called"); - } - - function nextItem($queue, $timeout=null) - { - throw ServerException("Unimplemented function 'nextItem' called"); - } - - function done($object, $queue) - { - throw ServerException("Unimplemented function 'done' called"); - } - - function fail($object, $queue) - { - throw ServerException("Unimplemented function 'fail' called"); + throw ServerException("Unimplemented function 'service' called"); } } diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 1ad687036..b8731d543 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -84,85 +84,33 @@ class StompQueueManager . $notice->id . ' for ' . $transport); } - function nextItem($queue, $timeout=null) + function service($queue, $handler) { $result = null; $this->_connect(); - $frame = $this->con->readFrame(); + $this->con->setReadTimeout($handler->timeout()); - if ($frame) { - $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($frame->headers['created'])); + $this->con->subscribe($this->_queueName($queue)); - // XXX: Now the queue handler receives only the ID of the - // notice, and it has to get it from the DB - // A massive improvement would be avoid DB query by transmitting - // all the notice details via queue server... + while (true) { - $notice = Notice::staticGet($frame->body); + $frame = $this->con->readFrame(); - if ($notice) { - $this->_saveFrame($notice, $queue, $frame); - } else { - $this->log(LOG_WARNING, 'queue item for notice that does not exist'); - } - } - } - - function done($object, $queue) - { - $notice = $object; + if ($frame) { + $notice = Notice::staticGet($frame->body); - $this->_connect(); - - $frame = $this->_getFrame($notice, $queue); - - if (empty($frame)) { - $this->log(LOG_ERR, 'Cannot find frame for notice '.$notice->id.' in queue '.$queue); - } else { - // if the msg has been handled positively, ack it - // and the queue server will remove it from the queue - $this->con->ack($frame); - $this->_clearFrame($notice, $queue); + if ($handler->handle_notice($notice)) { + $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id); + $this->con->ack($frame); + } + } - $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); + $handler->idle(0); } - } - - function fail($object, $queue) - { - $notice = $object; - - // STOMP server will requeue it after a while anyways, - // so no need to notify. Just get it out of our little - // array - - $this->_clearFrame($notice, $queue); - } - - function _frameKey($notice, $queue) - { - return ((string)$notice->id) . '-' . $queue; - } - function _saveFrame($notice, $queue, $frame) - { - $k = $this->_frameKey($notice, $queue); - $this->_frames[$k] = $frame; - return true; - } - - function _getFrame($notice, $queue) - { - $k = $this->_frameKey($notice, $queue); - return $this->_frames[$k]; - } - - function _clearFrame($notice, $queue) - { - $k = $this->_frameKey($notice, $queue); - unset($this->_frames[$k]); + $this->con->unsubscribe($this->_queueName($queue)); } function _queueName($queue) -- cgit v1.2.3-54-g00ecf From f63702579a672d35c5db262873a4a22835301074 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 4 Jul 2009 01:16:58 -0400 Subject: don't say we're connecting if we're not --- lib/stompqueuemanager.php | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index b8731d543..a6bac861b 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -49,7 +49,6 @@ class StompQueueManager function _connect() { - $this->_log(LOG_DEBUG, "Connecting to $this->server..."); if (empty($this->con)) { $this->_log(LOG_INFO, "Connecting to '$this->server' as '$this->username'..."); $this->con = new Stomp($this->server); -- cgit v1.2.3-54-g00ecf From 6d72864618b73271a83aa566f35838bb1a5c57c7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 4 Jul 2009 01:17:37 -0400 Subject: don't try to show non-object --- lib/util.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/util.php b/lib/util.php index a40cd3d54..9e8ec41d2 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1028,6 +1028,9 @@ function common_log_objstring(&$object) if (is_null($object)) { return "null"; } + if (!($object instanceof DB_DataObject)) { + return "(unknown)"; + } $arr = $object->toArray(); $fields = array(); foreach ($arr as $k => $v) { -- cgit v1.2.3-54-g00ecf From 9dee9e1612ebe6d6f28c21bce8c426658d60f171 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 4 Jul 2009 01:20:39 -0400 Subject: new default daemon jid --- lib/xmppqueuehandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index 986e09c25..c8b5ad1fb 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -91,7 +91,7 @@ class XmppQueueHandler extends QueueHandler if (common_config('xmpp', 'listener')) { return common_config('xmpp', 'listener'); } else { - return jabber_daemon_address() . '/' . common_config('xmpp','resource') . '-listener'; + return jabber_daemon_address() . '/' . common_config('xmpp','resource') . 'daemon'; } } } -- cgit v1.2.3-54-g00ecf From 49eaa04b508f6e27533f494dedd4997416670bef Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 4 Jul 2009 01:42:42 -0400 Subject: return singleton if initialized --- lib/queuemanager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/queuemanager.php b/lib/queuemanager.php index f36e99d16..582c24790 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -57,9 +57,9 @@ class QueueManager } } } - - return self::$qm; } + + return self::$qm; } function enqueue($object, $queue) -- cgit v1.2.3-54-g00ecf From 66a4a60e0bb67ba9094cd94be5992c70e5352e54 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 4 Jul 2009 01:43:18 -0400 Subject: better debug logging in stomp queue manager --- lib/stompqueuemanager.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index a6bac861b..5f0b88d8a 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -75,12 +75,12 @@ class StompQueueManager array ('created' => $notice->created)); if (!$result) { - common_log(LOG_ERR, 'Error sending to '.$transport.' queue'); + common_log(LOG_ERR, 'Error sending to '.$queue.' queue'); return false; } common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' - . $notice->id . ' for ' . $transport); + . $notice->id . ' for ' . $queue); } function service($queue, $handler) @@ -101,7 +101,7 @@ class StompQueueManager $notice = Notice::staticGet($frame->body); if ($handler->handle_notice($notice)) { - $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id); + $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created']); $this->con->ack($frame); } } -- cgit v1.2.3-54-g00ecf From 23e6dafff6d82492aa7ab2addc2fae99bd609b57 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 5 Jul 2009 11:01:07 -0400 Subject: better handling of frames and notices --- lib/stompqueuemanager.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 5f0b88d8a..e7e1e00dd 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -37,7 +37,6 @@ class StompQueueManager var $password = null; var $base = null; var $con = null; - var $frames = array(); function __construct() { @@ -97,13 +96,19 @@ class StompQueueManager $frame = $this->con->readFrame(); - if ($frame) { - $notice = Notice::staticGet($frame->body); + if (!empty($frame)) { + $notice = Notice::staticGet('id', $frame->body); - if ($handler->handle_notice($notice)) { + if (empty($notice)) { + $this->_log(LOG_WARNING, 'Got ID '. $frame->body .' for non-existent notice'); + $this->con->ack($frame); + } else if ($handler->handle_notice($notice)) { $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created']); $this->con->ack($frame); + unset($notice); } + + unset($frame); } $handler->idle(0); -- cgit v1.2.3-54-g00ecf From e6c54a59e140c9ee3b6244dbcb92f9ca9d065887 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 5 Jul 2009 14:33:12 -0400 Subject: set/get viewdesigns flag and use it --- actions/othersettings.php | 11 ++++++++--- lib/groupdesignaction.php | 16 +++++++++------- lib/ownerdesignaction.php | 12 ++++++++---- 3 files changed, 25 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/actions/othersettings.php b/actions/othersettings.php index b542233ca..1277f8052 100644 --- a/actions/othersettings.php +++ b/actions/othersettings.php @@ -83,14 +83,12 @@ class OthersettingsAction extends AccountSettingsAction { $user = common_current_user(); - $this->elementStart('form', array('method' => 'post', 'id' => 'form_settings_other', 'class' => 'form_settings', 'action' => common_local_url('othersettings'))); $this->elementStart('fieldset'); - $this->element('legend', null, _('URL Auto-shortening')); $this->hidden('token', common_session_token()); // I18N @@ -109,10 +107,14 @@ class OthersettingsAction extends AccountSettingsAction $this->elementStart('ul', 'form_data'); $this->elementStart('li'); - $this->dropdown('urlshorteningservice', _('Service'), + $this->dropdown('urlshorteningservice', _('Shorten URLs with'), $services, _('Automatic shortening service to use.'), false, $user->urlshorteningservice); $this->elementEnd('li'); + $this->elementStart('li'); + $this->checkbox('viewdesigns', _('View profile designs'), + $user->viewdesigns, _('Show or hide profile designs.')); + $this->elementEnd('li'); $this->elementEnd('ul'); $this->submit('save', _('Save')); $this->elementEnd('fieldset'); @@ -145,6 +147,8 @@ class OthersettingsAction extends AccountSettingsAction return; } + $viewdesigns = $this->boolean('viewdesigns'); + $user = common_current_user(); assert(!is_null($user)); // should already be checked @@ -154,6 +158,7 @@ class OthersettingsAction extends AccountSettingsAction $original = clone($user); $user->urlshorteningservice = $urlshorteningservice; + $user->viewdesigns = $viewdesigns; $result = $user->update($original); diff --git a/lib/groupdesignaction.php b/lib/groupdesignaction.php index bc95921f1..58777c283 100644 --- a/lib/groupdesignaction.php +++ b/lib/groupdesignaction.php @@ -34,7 +34,7 @@ if (!defined('LACONICA')) { /** * Base class for actions that use a group's design * - * Pages related to groups can be themed with a design. + * Pages related to groups can be themed with a design. * This superclass returns that design. * * @category Action @@ -48,7 +48,7 @@ class GroupDesignAction extends Action { /** The group in question */ var $group = null; - + /** * Show the groups's design stylesheet * @@ -58,10 +58,14 @@ class GroupDesignAction extends Action { { parent::showStylesheets(); - $design = $this->getDesign(); + $user = common_current_user(); + + if (empty($user) || $user->viewdesigns) { + $design = $this->getDesign(); - if (!empty($design)) { - $design->showCSS($this); + if (!empty($design)) { + $design->showCSS($this); + } } } @@ -76,12 +80,10 @@ class GroupDesignAction extends Action { function getDesign() { - if (empty($this->group)) { return null; } return $this->group->getDesign(); } - } diff --git a/lib/ownerdesignaction.php b/lib/ownerdesignaction.php index 424474f42..785b8a93d 100644 --- a/lib/ownerdesignaction.php +++ b/lib/ownerdesignaction.php @@ -61,11 +61,15 @@ class OwnerDesignAction extends Action { { parent::showStylesheets(); - $design = $this->getDesign(); + $user = common_current_user(); - if (!empty($design)) { - $design->showCSS($this); - } + if (empty($user) || $user->viewdesigns) { + $design = $this->getDesign(); + + if (!empty($design)) { + $design->showCSS($this); + } + } } /** -- cgit v1.2.3-54-g00ecf From 5875c02cbba9c595e6fb73f788776d23905694d5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 5 Jul 2009 14:37:37 -0400 Subject: also hide your own design --- lib/currentuserdesignaction.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/currentuserdesignaction.php b/lib/currentuserdesignaction.php index 7c2520cf6..4c7e15a8b 100644 --- a/lib/currentuserdesignaction.php +++ b/lib/currentuserdesignaction.php @@ -53,14 +53,19 @@ class CurrentUserDesignAction extends Action * * @return nothing */ + function showStylesheets() { parent::showStylesheets(); - $design = $this->getDesign(); + $user = common_current_user(); + + if (empty($user) || $user->viewdesigns) { + $design = $this->getDesign(); - if (!empty($design)) { - $design->showCSS($this); + if (!empty($design)) { + $design->showCSS($this); + } } } @@ -84,5 +89,4 @@ class CurrentUserDesignAction extends Action return $cur->getDesign(); } - } -- cgit v1.2.3-54-g00ecf From d40075ae9c7c2b920a5e9a7cd436aff96f94d8f8 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 6 Jul 2009 11:57:21 -0700 Subject: Support undocumented 'id' parameter in /statuses/show API method --- actions/twitapistatuses.php | 15 ++++++++++++--- lib/router.php | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 555c746cb..c9943698d 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -373,9 +373,19 @@ class TwitapistatusesAction extends TwitterapiAction return; } + // 'id' is an undocumented parameter in Twitter's API. Several + // clients make use of it, so we support it too. + + // show.json?id=12345 takes precedence over /show/12345.json + $this->auth_user = $apidata['user']; - $notice_id = $apidata['api_arg']; - $notice = Notice::staticGet($notice_id); + $notice_id = $this->trimmed('id'); + + if (empty($notice_id)) { + $notice_id = $apidata['api_arg']; + } + + $notice = Notice::staticGet((int)$notice_id); if ($notice) { if ($apidata['content-type'] == 'xml') { @@ -389,7 +399,6 @@ class TwitapistatusesAction extends TwitterapiAction $this->clientError(_('No status with that ID found.'), 404, $apidata['content-type']); } - } function destroy($args, $apidata) diff --git a/lib/router.php b/lib/router.php index 50b733453..75e72f932 100644 --- a/lib/router.php +++ b/lib/router.php @@ -261,7 +261,7 @@ class Router $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|mentions|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|mentions|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', -- cgit v1.2.3-54-g00ecf From 79b06ade27666a10cdfb54ba46af7a26b9a593d2 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 8 Jul 2009 00:42:14 +0000 Subject: Removed OpenID link from the primary global navigation in order to keep a single Login idea because we have several ways to login already: regular login, OpenID and Facebook (and probably LDAP, Open Social in the future) --- lib/action.php | 2 -- plugins/FBConnect/FBConnectPlugin.php | 2 -- 2 files changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index 928eb48c0..da5b48858 100644 --- a/lib/action.php +++ b/lib/action.php @@ -439,8 +439,6 @@ class Action extends HTMLOutputter // lawsuit $this->menuItem(common_local_url('register'), _('Register'), _('Create an account'), false, 'nav_register'); } - $this->menuItem(common_local_url('openidlogin'), - _('OpenID'), _('Login with OpenID'), false, 'nav_openid'); $this->menuItem(common_local_url('login'), _('Login'), _('Login to the site'), false, 'nav_login'); } diff --git a/plugins/FBConnect/FBConnectPlugin.php b/plugins/FBConnect/FBConnectPlugin.php index d8af1a4e8..65870a187 100644 --- a/plugins/FBConnect/FBConnectPlugin.php +++ b/plugins/FBConnect/FBConnectPlugin.php @@ -313,8 +313,6 @@ class FBConnectPlugin extends Plugin $action->menuItem(common_local_url('register'), _('Register'), _('Create an account'), false, 'nav_register'); } - $action->menuItem(common_local_url('openidlogin'), - _('OpenID'), _('Login with OpenID'), false, 'nav_openid'); $action->menuItem(common_local_url('login'), _('Login'), _('Login to the site'), false, 'nav_login'); } -- cgit v1.2.3-54-g00ecf From b25e6139e8d6b3dcb9ca76ac8c43729dc17eedb4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 7 Jul 2009 21:15:39 -0400 Subject: check for array before checking xmlrpc fault --- lib/ping.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ping.php b/lib/ping.php index 3de541e9a..d26c73417 100644 --- a/lib/ping.php +++ b/lib/ping.php @@ -59,7 +59,7 @@ function ping_broadcast_notice($notice) { $response = xmlrpc_decode($file); - if (xmlrpc_is_fault($response)) { + if (is_array($response) && xmlrpc_is_fault($response)) { common_log(LOG_WARNING, "XML-RPC error for ping ($notify_url, $notice->id) ". "$response[faultString] ($response[faultCode])"); -- cgit v1.2.3-54-g00ecf From a626f32d8e01faa620a11e1f8370a35cc660a579 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 8 Jul 2009 01:36:12 -0400 Subject: log errors in handling notices --- lib/stompqueuemanager.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index e7e1e00dd..06be2ba85 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -100,11 +100,16 @@ class StompQueueManager $notice = Notice::staticGet('id', $frame->body); if (empty($notice)) { - $this->_log(LOG_WARNING, 'Got ID '. $frame->body .' for non-existent notice'); - $this->con->ack($frame); - } else if ($handler->handle_notice($notice)) { - $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created']); + $this->_log(LOG_WARNING, 'Got ID '. $frame->body .' for non-existent notice in queue '. $queue); $this->con->ack($frame); + } else { + if ($handler->handle_notice($notice)) { + $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); + $this->con->ack($frame); + } else { + $this->_log(LOG_WARNING, 'Failed handling notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); + // Don't ack; it'll get re-sent + } unset($notice); } -- cgit v1.2.3-54-g00ecf From 2ed9d2dac5c2eb0d44c1168cdd861c925f184fb6 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 8 Jul 2009 00:30:18 -0700 Subject: Get rid of error ('Trying to get property of non-object') --- lib/facebookutil.php | 2 +- lib/twitter.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/facebookutil.php b/lib/facebookutil.php index 4d0df797b..5eb9534b1 100644 --- a/lib/facebookutil.php +++ b/lib/facebookutil.php @@ -108,11 +108,11 @@ function facebookBroadcastNotice($notice) { $facebook = getFacebook(); $flink = Foreign_link::getByUserID($notice->profile_id, FACEBOOK_SERVICE); - $fbuid = $flink->foreign_id; if (isFacebookBound($notice, $flink)) { $status = null; + $fbuid = $flink->foreign_id; // Get the status 'verb' (prefix) the user has set try { diff --git a/lib/twitter.php b/lib/twitter.php index 3ec082686..d5eba084b 100644 --- a/lib/twitter.php +++ b/lib/twitter.php @@ -367,7 +367,7 @@ function broadcast_twitter($notice) // XXX: Not sure WHERE to check whether a notice should go to // Twitter. Should we even put in the queue if it shouldn't? --Zach - if (!is_null($flink) && is_twitter_bound($notice, $flink)) { + if (is_twitter_bound($notice, $flink)) { $fuser = $flink->getForeignUser(); $twitter_user = $fuser->nickname; -- cgit v1.2.3-54-g00ecf From 06bf2e2413446fe30b9b4b63bccb47d47786cde2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 8 Jul 2009 01:02:12 -0700 Subject: Get rid of the other error trying to property on a non-obj --- lib/facebookutil.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/facebookutil.php b/lib/facebookutil.php index 5eb9534b1..762d17bff 100644 --- a/lib/facebookutil.php +++ b/lib/facebookutil.php @@ -51,6 +51,10 @@ function updateProfileBox($facebook, $flink, $notice) { function isFacebookBound($notice, $flink) { + if (empty($flink)) { + return false; + } + // If the user does not want to broadcast to Facebook, move along if (!($flink->noticesync & FOREIGN_NOTICE_SEND == FOREIGN_NOTICE_SEND)) { common_log(LOG_INFO, "Skipping notice $notice->id " . -- cgit v1.2.3-54-g00ecf From 8aef0e4271dda4210901de635b4227e6dbefca18 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 8 Jul 2009 17:55:43 -0400 Subject: manually re-enqueue failed notices --- lib/stompqueuemanager.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 06be2ba85..4cefba113 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -108,7 +108,10 @@ class StompQueueManager $this->con->ack($frame); } else { $this->_log(LOG_WARNING, 'Failed handling notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); - // Don't ack; it'll get re-sent + // FIXME we probably shouldn't have to do + // this kind of queue management ourselves + $this->con->ack($frame); + $this->enqueue($notice, $queue); } unset($notice); } -- cgit v1.2.3-54-g00ecf From 616d68cf9481f08eae75095e2188fb7fea6d822c Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 9 Jul 2009 00:40:12 +0000 Subject: Better error handling for TwitterQueueHandler --- lib/mail.php | 36 +++++++++++++++++++++ lib/twitter.php | 97 +++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 116 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/mail.php b/lib/mail.php index 4e1f1dbb1..c948f83ca 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -625,3 +625,39 @@ function mail_notify_attn($user, $notice) common_init_locale(); mail_to_user($user, $subject, $body); } + +/** + * Send a mail message to notify a user that her Twitter bridge link + * has stopped working, and therefore has been removed. This can + * happen when the user changes her Twitter password, or otherwise + * revokes access. + * + * @param User $user user whose Twitter bridge link has been removed + * + * @return boolean success flag + */ + +function mail_twitter_bridge_removed($user) +{ + common_init_locale($user->language); + + $profile = $user->getProfile(); + + $subject = sprintf(_('Your Twitter bridge has been disabled.')); + + $body = sprintf(_("Hi, %1\$s. We're sorry to inform you that your " . + 'link to Twitter has been disabled. Your Twitter credentials ' . + 'have either changed (did you recently change your Twitter ' . + 'password?) or you have otherwise revoked our access to your ' . + "Twitter account.\n\n" . + 'You can re-enable your Twitter bridge by visiting your ' . + "Twitter settings page:\n\n\t%2\$s\n\n" . + "Regards,\n%3\$s\n"), + $profile->getBestName(), + common_local_url('twittersettings'), + common_config('site', 'name')); + + common_init_locale(); + return mail_to_user($user, $subject, $body); +} + diff --git a/lib/twitter.php b/lib/twitter.php index d5eba084b..47af32e61 100644 --- a/lib/twitter.php +++ b/lib/twitter.php @@ -360,13 +360,10 @@ function is_twitter_bound($notice, $flink) { function broadcast_twitter($notice) { - $success = true; $flink = Foreign_link::getByUserID($notice->profile_id, TWITTER_SERVICE); - // XXX: Not sure WHERE to check whether a notice should go to - // Twitter. Should we even put in the queue if it shouldn't? --Zach if (is_twitter_bound($notice, $flink)) { $fuser = $flink->getForeignUser(); @@ -401,33 +398,99 @@ function broadcast_twitter($notice) curl_setopt_array($ch, $options); $data = curl_exec($ch); $errmsg = curl_error($ch); + $errno = curl_errno($ch); - if ($errmsg) { - common_debug("cURL error: $errmsg - " . + if (!empty($errmsg)) { + common_debug("cURL error ($errno): $errmsg - " . "trying to send notice for $twitter_user.", __FILE__); - $success = false; + + $user = $flink->getUser(); + + if ($errmsg == 'The requested URL returned error: 401') { + common_debug(sprintf('User %s (user id: %s) ' . + 'has bad Twitter credentials!', + $user->nickname, $user->id)); + + // Bad credentials we need to delete the foreign_link + // to Twitter and inform the user. + + remove_twitter_link($flink); + + return true; + + } else { + + // Some other error happened, so we should try to + // send again later + + return false; + } + } curl_close($ch); - if (!$data) { + if (empty($data)) { common_debug("No data returned by Twitter's " . "API trying to send update for $twitter_user", __FILE__); - $success = false; - } - // Twitter should return a status - $status = json_decode($data); + // XXX: Not sure this represents a failure to send, but it + // probably does - if (!$status->id) { - common_debug("Unexpected data returned by Twitter " . - " API trying to send update for $twitter_user", - __FILE__); - $success = false; + return false; + + } else { + + // Twitter should return a status + $status = json_decode($data); + + if (empty($status)) { + common_debug("Unexpected data returned by Twitter " . + " API trying to send update for $twitter_user", + __FILE__); + + // XXX: Again, this could represent a failure posting + // or the Twitter API might just be behaving flakey. + // We're treating it as a failure to post. + + return false; + } } } - return $success; + return true; +} + +function remove_twitter_link($flink) +{ + $user = $flink->getUser(); + + common_log(LOG_INFO, 'Removing Twitter bridge Foreign link for ' . + "user $user->nickname (user id: $user->id)."); + + $result = $flink->delete(); + + if (empty($result)) { + common_log(LOG_ERR, 'Could not remove Twitter bridge ' . + "Foreign_link for $user->nickname (user id: $user->id)!"); + common_log_db_error($flink, 'DELETE', __FILE__); + } + + // Notify the user that her Twitter bridge is down + + $result = mail_twitter_bridge_removed($user); + + if (!$result) { + + $msg = 'Unable to send email to notify ' . + "$user->nickname (user id: $user->id) " . + 'that their Twitter bridge link was ' . + 'removed!'; + + common_log(LOG_WARNING, $msg); + } + } + -- cgit v1.2.3-54-g00ecf From bbb25e2153c3c58053155c7258644738fc9e6ab6 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 9 Jul 2009 02:04:38 +0000 Subject: Better error handling for FacebookQueueHandler --- lib/facebookutil.php | 75 ++++++++++++++++++++++++++++++++++++++++++++++------ lib/mail.php | 36 +++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/facebookutil.php b/lib/facebookutil.php index 762d17bff..632ec4bad 100644 --- a/lib/facebookutil.php +++ b/lib/facebookutil.php @@ -90,10 +90,10 @@ function isFacebookBound($notice, $flink) { if ($result != 1) { $user = $flink->getUser(); - $msg = "Can't send notice $notice->id to Facebook " . + $msg = "Not sending notice $notice->id to Facebook " . "because user $user->nickname hasn't given the " . 'Facebook app \'status_update\' permission.'; - common_log(LOG_INFO, $msg); + common_debug($msg); $success = false; } @@ -118,7 +118,10 @@ function facebookBroadcastNotice($notice) $status = null; $fbuid = $flink->foreign_id; + $user = $flink->getUser(); + // Get the status 'verb' (prefix) the user has set + try { $prefix = $facebook->api_client-> data_getUserPreference(FACEBOOK_NOTICE_PREFIX, $fbuid); @@ -126,23 +129,79 @@ function facebookBroadcastNotice($notice) $status = "$prefix $notice->content"; } catch(FacebookRestClientException $e) { - common_log(LOG_ERR, $e->getMessage()); - return false; + common_log(LOG_WARNING, $e->getMessage()); + common_log(LOG_WARNING, + 'Unable to get the status verb setting from Facebook ' . + "for $user->nickname (user id: $user->id)."); } - // Okay, we're good to go! + // Okay, we're good to go, update the FB status try { $facebook->api_client->users_setStatus($status, $fbuid, false, true); - updateProfileBox($facebook, $flink, $notice); } catch(FacebookRestClientException $e) { common_log(LOG_ERR, $e->getMessage()); - return false; + common_log(LOG_ERR, + 'Unable to update Facebook status for ' . + "$user->nickname (user id: $user->id)!"); - // Should we remove flink if this fails? + $code = $e->getCode(); + + if ($code >= 200) { + + // 200 The application does not have permission to operate on the passed in uid parameter. + // 250 Updating status requires the extended permission status_update. + // see: http://wiki.developers.facebook.com/index.php/Users.setStatus#Example_Return_XML + + remove_facebook_app($flink); + } + + } + + // Now try to update the profile box + + try { + updateProfileBox($facebook, $flink, $notice); + } catch(FacebookRestClientException $e) { + common_log(LOG_WARNING, $e->getMessage()); + common_log(LOG_WARNING, + 'Unable to update Facebook profile box for ' . + "$user->nickname (user id: $user->id)."); } } return true; } + +function remove_facebook_app($flink) +{ + + $user = $flink->getUser(); + + common_log(LOG_INFO, 'Removing Facebook App Foreign link for ' . + "user $user->nickname (user id: $user->id)."); + + $result = $flink->delete(); + + if (empty($result)) { + common_log(LOG_ERR, 'Could not remove Facebook App ' . + "Foreign_link for $user->nickname (user id: $user->id)!"); + common_log_db_error($flink, 'DELETE', __FILE__); + } + + // Notify the user that we are removing their FB app access + + $result = mail_facebook_app_removed($user); + + if (!$result) { + + $msg = 'Unable to send email to notify ' . + "$user->nickname (user id: $user->id) " . + 'that their Facebook app link was ' . + 'removed!'; + + common_log(LOG_WARNING, $msg); + } + +} diff --git a/lib/mail.php b/lib/mail.php index c948f83ca..90ee3c992 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -661,3 +661,39 @@ function mail_twitter_bridge_removed($user) return mail_to_user($user, $subject, $body); } +/** + * Send a mail message to notify a user that her Facebook Application + * access has been removed. + * + * @param User $user user whose Facebook app link has been removed + * + * @return boolean success flag + */ + +function mail_facebook_app_removed($user) +{ + common_init_locale($user->language); + + $profile = $user->getProfile(); + + $site_name = common_config('site', 'name'); + + $subject = sprintf( + _('Your %s Facebook application access has been disabled.', + $site_name)); + + $body = sprintf(_("Hi, %1\$s. We're sorry to inform you that we are " . + 'unable to update your Facebook status from %s, and have disabled ' . + 'the Facebook application for your account. This may be because ' . + 'you have removed the Facebook application\'s authorization, or ' . + 'have deleted your Facebook account. You can re-enable the ' . + 'Facebook application and automatic status updating by ' . + "re-installing the %1\$s Facebook application.\n\nRegards,\n\n%1\$s"), + $site_name); + + common_init_locale(); + return mail_to_user($user, $subject, $body); + +} + + -- cgit v1.2.3-54-g00ecf From a5212dd6e32433bac4c5085e8ffb3c8c27a01936 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 10:11:13 -0400 Subject: timeouts and pings for xmppqueuehandlers --- lib/xmppqueuehandler.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'lib') diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index c8b5ad1fb..9b1a6989e 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -30,6 +30,8 @@ require_once(INSTALLDIR.'/lib/queuehandler.php'); class XmppQueueHandler extends QueueHandler { + var $pingid = 0; + function start() { # Low priority; we don't want to receive messages @@ -44,6 +46,11 @@ class XmppQueueHandler extends QueueHandler return !is_null($this->conn); } + function timeout() + { + return 10; + } + function handle_reconnect(&$pl) { $this->conn->processUntil('session_start'); @@ -55,7 +62,9 @@ class XmppQueueHandler extends QueueHandler # Process the queue for as long as needed try { if ($this->conn) { + $this->log(LOG_DEBUG, "Servicing the XMPP queue."); $this->conn->processTime($timeout); + $this->sendPing(); } } catch (XMPPHP_Exception $e) { $this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage()); @@ -63,6 +72,22 @@ class XmppQueueHandler extends QueueHandler } } + function sendPing() + { + $jid = jabber_daemon_address().'/'.$this->_id.$this->transport(); + $server = common_config('xmpp', 'server'); + + if (!isset($this->pingid)) { + $this->pingid = 0; + } else { + $this->pingid++; + } + + $this->log(LOG_DEBUG, "Sending ping #{$this->pingid}"); + + $this->conn->send(""); + } + function forward_message(&$pl) { if ($pl['type'] != 'chat') { -- cgit v1.2.3-54-g00ecf From d2e83b6a67fec311f9bc36a7d886f40169d9de15 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 10:40:24 -0400 Subject: give processtime a minimum of 1s --- lib/xmppqueuehandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index 9b1a6989e..7d14422c6 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -63,7 +63,7 @@ class XmppQueueHandler extends QueueHandler try { if ($this->conn) { $this->log(LOG_DEBUG, "Servicing the XMPP queue."); - $this->conn->processTime($timeout); + $this->conn->processTime(max($timeout, 1)); $this->sendPing(); } } catch (XMPPHP_Exception $e) { -- cgit v1.2.3-54-g00ecf From d7611009b11c489abbc7c52d51ec859fd9fa5600 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 11:16:50 -0400 Subject: Revert "give processtime a minimum of 1s" This reverts commit d2e83b6a67fec311f9bc36a7d886f40169d9de15. --- lib/xmppqueuehandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index 7d14422c6..9b1a6989e 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -63,7 +63,7 @@ class XmppQueueHandler extends QueueHandler try { if ($this->conn) { $this->log(LOG_DEBUG, "Servicing the XMPP queue."); - $this->conn->processTime(max($timeout, 1)); + $this->conn->processTime($timeout); $this->sendPing(); } } catch (XMPPHP_Exception $e) { -- cgit v1.2.3-54-g00ecf From 1daad01f362d72e6ed89f415546220016c32404a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 11:40:01 -0400 Subject: slightly better timing --- lib/stompqueuemanager.php | 7 +++++-- lib/xmppqueuehandler.php | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 4cefba113..4d89806f8 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -117,9 +117,12 @@ class StompQueueManager } unset($frame); - } - $handler->idle(0); + $handler->idle(QUEUE_HANDLER_HIT_IDLE); + + } else { + $handler->idle(QUEUE_HANDLER_MISS_IDLE); + } } $this->con->unsubscribe($this->_queueName($queue)); diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index 9b1a6989e..cbcfe5e1c 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -21,6 +21,8 @@ if (!defined('LACONICA')) { exit(1); } require_once(INSTALLDIR.'/lib/queuehandler.php'); +define('PING_INTERVAL', 120); + /** * Common superclass for all XMPP-using queue handlers. They all need to * service their message queues on idle, and forward any incoming messages @@ -31,6 +33,7 @@ require_once(INSTALLDIR.'/lib/queuehandler.php'); class XmppQueueHandler extends QueueHandler { var $pingid = 0; + var $lastping = null; function start() { @@ -64,7 +67,11 @@ class XmppQueueHandler extends QueueHandler if ($this->conn) { $this->log(LOG_DEBUG, "Servicing the XMPP queue."); $this->conn->processTime($timeout); - $this->sendPing(); + $now = time(); + if (empty($this->lastping) || $now - $this->lastping > PING_INTERVAL) { + $this->sendPing(); + $this->lastping = $now; + } } } catch (XMPPHP_Exception $e) { $this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage()); -- cgit v1.2.3-54-g00ecf From 03200235b1a1bba56c24e1bb659023ba24265eb3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 12:09:20 -0400 Subject: use select() to bring down xmpp latency --- lib/jabber.php | 10 ++++++- lib/queuehandler.php | 5 ++++ lib/stompqueuemanager.php | 73 +++++++++++++++++++++++++++++++++-------------- lib/xmppqueuehandler.php | 5 ++++ 4 files changed, 71 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/jabber.php b/lib/jabber.php index 7d584ad01..e15076160 100644 --- a/lib/jabber.php +++ b/lib/jabber.php @@ -77,6 +77,14 @@ function jabber_daemon_address() return common_config('xmpp', 'user') . '@' . common_config('xmpp', 'server'); } +class Sharing_XMPP extends XMPPHP_XMPP +{ + function getSocket() + { + return $this->socket; + } +} + /** * connect the configured Jabber account to the configured server * @@ -89,7 +97,7 @@ function jabber_connect($resource=null) { static $conn = null; if (!$conn) { - $conn = new XMPPHP_XMPP(common_config('xmpp', 'host') ? + $conn = new Sharing_XMPP(common_config('xmpp', 'host') ? common_config('xmpp', 'host') : common_config('xmpp', 'server'), common_config('xmpp', 'port'), diff --git a/lib/queuehandler.php b/lib/queuehandler.php index c0f38f4e3..c2ff10f32 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -115,5 +115,10 @@ class QueueHandler extends Daemon { common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); } + + function getSockets() + { + return array(); + } } diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 4d89806f8..7da7c0011 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -30,6 +30,14 @@ require_once 'Stomp.php'; +class LiberalStomp extends Stomp +{ + function getSocket() + { + return $this->_socket; + } +} + class StompQueueManager { var $server = null; @@ -50,7 +58,7 @@ class StompQueueManager { if (empty($this->con)) { $this->_log(LOG_INFO, "Connecting to '$this->server' as '$this->username'..."); - $this->con = new Stomp($this->server); + $this->con = new LiberalStomp($this->server); if ($this->con->connect($this->username, $this->password)) { $this->_log(LOG_INFO, "Connected."); @@ -94,34 +102,57 @@ class StompQueueManager while (true) { - $frame = $this->con->readFrame(); + // Wait for something on one of our sockets - if (!empty($frame)) { - $notice = Notice::staticGet('id', $frame->body); + $stompsock = $this->con->getSocket(); - if (empty($notice)) { - $this->_log(LOG_WARNING, 'Got ID '. $frame->body .' for non-existent notice in queue '. $queue); - $this->con->ack($frame); - } else { - if ($handler->handle_notice($notice)) { - $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); + $handsocks = $handler->getSockets(); + + $this->_log(LOG_DEBUG, "Got ".count($handsocks)." sockets from handler."); + $this->_log(LOG_DEBUG, print_r($handsocks, true)); + + $socks = array_merge(array($stompsock), $handsocks); + + $read = $socks; + $write = array(); + $except = array(); + + $this->_log(LOG_DEBUG, "Starting select"); + $ready = stream_select($read, $write, $except, $handler->timeout(), 0); + $this->_log(LOG_DEBUG, "Finished select with value '$ready'"); + + if (!$ready || $read[0] !== $stompsock) { + $handler->idle(QUEUE_HANDLER_MISS_IDLE); + } else { + $frame = $this->con->readFrame(); + + if (!empty($frame)) { + $notice = Notice::staticGet('id', $frame->body); + + if (empty($notice)) { + $this->_log(LOG_WARNING, 'Got ID '. $frame->body .' for non-existent notice in queue '. $queue); $this->con->ack($frame); } else { - $this->_log(LOG_WARNING, 'Failed handling notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); - // FIXME we probably shouldn't have to do - // this kind of queue management ourselves - $this->con->ack($frame); - $this->enqueue($notice, $queue); + if ($handler->handle_notice($notice)) { + $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); + $this->con->ack($frame); + } else { + $this->_log(LOG_WARNING, 'Failed handling notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); + // FIXME we probably shouldn't have to do + // this kind of queue management ourselves + $this->con->ack($frame); + $this->enqueue($notice, $queue); + } + unset($notice); } - unset($notice); - } - unset($frame); + unset($frame); - $handler->idle(QUEUE_HANDLER_HIT_IDLE); + $handler->idle(QUEUE_HANDLER_HIT_IDLE); - } else { - $handler->idle(QUEUE_HANDLER_MISS_IDLE); + } else { + $handler->idle(QUEUE_HANDLER_MISS_IDLE); + } } } diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index cbcfe5e1c..77d476c30 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -126,4 +126,9 @@ class XmppQueueHandler extends QueueHandler return jabber_daemon_address() . '/' . common_config('xmpp','resource') . 'daemon'; } } + + function getSockets() + { + return array($this->conn->getSocket()); + } } -- cgit v1.2.3-54-g00ecf From eccab870444463734b8fcd7ec0f1cf149a0f6a57 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 12:33:38 -0400 Subject: slightly more robust select() logic --- lib/stompqueuemanager.php | 70 +++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 7da7c0011..ac55f9733 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -108,55 +108,55 @@ class StompQueueManager $handsocks = $handler->getSockets(); - $this->_log(LOG_DEBUG, "Got ".count($handsocks)." sockets from handler."); - $this->_log(LOG_DEBUG, print_r($handsocks, true)); - $socks = array_merge(array($stompsock), $handsocks); $read = $socks; $write = array(); $except = array(); - $this->_log(LOG_DEBUG, "Starting select"); $ready = stream_select($read, $write, $except, $handler->timeout(), 0); - $this->_log(LOG_DEBUG, "Finished select with value '$ready'"); - if (!$ready || $read[0] !== $stompsock) { + if ($ready === false) { + $this->_log(LOG_ERR, "Error selecting on sockets"); + } else if ($ready > 0) { + if (in_array($stompsock, $read)) { + $this->_handleNotice($queue, $handler); + } + $handler->idle(QUEUE_HANDLER_HIT_IDLE); + } else { // timeout $handler->idle(QUEUE_HANDLER_MISS_IDLE); - } else { - $frame = $this->con->readFrame(); - - if (!empty($frame)) { - $notice = Notice::staticGet('id', $frame->body); - - if (empty($notice)) { - $this->_log(LOG_WARNING, 'Got ID '. $frame->body .' for non-existent notice in queue '. $queue); - $this->con->ack($frame); - } else { - if ($handler->handle_notice($notice)) { - $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); - $this->con->ack($frame); - } else { - $this->_log(LOG_WARNING, 'Failed handling notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); - // FIXME we probably shouldn't have to do - // this kind of queue management ourselves - $this->con->ack($frame); - $this->enqueue($notice, $queue); - } - unset($notice); - } - - unset($frame); - - $handler->idle(QUEUE_HANDLER_HIT_IDLE); + } + } + + $this->con->unsubscribe($this->_queueName($queue)); + } + function _handleNotice($queue, $handler) + { + $frame = $this->con->readFrame(); + + if (!empty($frame)) { + $notice = Notice::staticGet('id', $frame->body); + + if (empty($notice)) { + $this->_log(LOG_WARNING, 'Got ID '. $frame->body .' for non-existent notice in queue '. $queue); + $this->con->ack($frame); + } else { + if ($handler->handle_notice($notice)) { + $this->_log(LOG_INFO, 'Successfully handled notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); + $this->con->ack($frame); } else { - $handler->idle(QUEUE_HANDLER_MISS_IDLE); + $this->_log(LOG_WARNING, 'Failed handling notice '. $notice->id .' posted at ' . $frame->headers['created'] . ' in queue '. $queue); + // FIXME we probably shouldn't have to do + // this kind of queue management ourselves + $this->con->ack($frame); + $this->enqueue($notice, $queue); } + unset($notice); } - } - $this->con->unsubscribe($this->_queueName($queue)); + unset($frame); + } } function _queueName($queue) -- cgit v1.2.3-54-g00ecf From 031146f4c757ca00fb9f528abf69ef4b229bdc18 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 12:49:37 -0400 Subject: yet another select() refinement --- lib/stompqueuemanager.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index ac55f9733..d13af3fa5 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -122,9 +122,12 @@ class StompQueueManager if (in_array($stompsock, $read)) { $this->_handleNotice($queue, $handler); } - $handler->idle(QUEUE_HANDLER_HIT_IDLE); - } else { // timeout - $handler->idle(QUEUE_HANDLER_MISS_IDLE); + foreach ($handsocks as $sock) { + if (in_array($sock, $read)) { + $handler->idle(QUEUE_HANDLER_HIT_IDLE); + break; + } + } } } -- cgit v1.2.3-54-g00ecf From 69574591d0ac429475b1099e8d9f3e46f7a004ea Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Thu, 9 Jul 2009 13:18:57 -0400 Subject: Notice attachments are enclosures in feeds (Atom, RSS 1.0/RDF, and RSS 2.0). http://laconi.ca/trac/ticket/1690 --- classes/Notice.php | 12 ++++++++++++ lib/rssaction.php | 9 +++++++++ lib/twitterapi.php | 21 ++++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/classes/Notice.php b/classes/Notice.php index 5ec0692d9..e975cab93 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1164,6 +1164,18 @@ class Notice extends Memcached_DataObject } $tag->free(); + # Enclosures + $attachments = $this->attachments(); + if($attachments){ + foreach($attachments as $attachment){ + $attributes = array('rel'=>'enclosure','href'=>$attachment->url,'type'=>$attachment->mimetype,'length'=>$attachment->size); + if($attachment->title){ + $attributes['title']=$attachment->title; + } + $xs->element('link', $attributes, null); + } + } + $xs->elementEnd('entry'); return $xs->getString(); diff --git a/lib/rssaction.php b/lib/rssaction.php index 0c8188e88..fe3fd6f4a 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -216,6 +216,13 @@ class Rss10Action extends Action $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to)); $this->element('sioc:reply_of', array('rdf:resource' => $replyurl)); } + $attachments = $notice->attachments(); + if($attachments){ + foreach($attachments as $attachment){ + $this->element('enc:enclosure', array('rdf:resource'=>$attachment->url,'enc:type'=>$attachment->mimetype,'enc:length'=>$attachment->size), null); + } + } + $this->elementEnd('item'); $this->creators[$creator_uri] = $profile; } @@ -251,6 +258,8 @@ class Rss10Action extends Action 'http://creativecommons.org/ns#', 'xmlns:content' => 'http://purl.org/rss/1.0/modules/content/', + 'xmlns:enc' => + 'http://purl.oclc.org/net/rss_2.0/enc#', 'xmlns:foaf' => 'http://xmlns.com/foaf/0.1/', 'xmlns:sioc' => diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 40e5b5067..8f902cbca 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -207,7 +207,6 @@ class TwitterapiAction extends Action function twitter_rss_entry_array($notice) { - $profile = $notice->getProfile(); $entry = array(); @@ -224,6 +223,19 @@ class TwitterapiAction extends Action $entry['updated'] = $entry['published']; $entry['author'] = $profile->getBestName(); + # Enclosure + $attachments = $notice->attachments(); + if($attachments){ + $entry['enclosures']=array(); + foreach($attachments as $attachment){ + $enclosure=array(); + $enclosure['url']=$attachment->url; + $enclosure['mimetype']=$attachment->mimetype; + $enclosure['size']=$attachment->size; + $entry['enclosures'][]=$enclosure; + } + } + # RSS Item specific $entry['description'] = $entry['content']; $entry['pubDate'] = common_date_rfc2822($notice->created); @@ -378,6 +390,13 @@ class TwitterapiAction extends Action $this->element('pubDate', null, $entry['pubDate']); $this->element('guid', null, $entry['guid']); $this->element('link', null, $entry['link']); + + # RSS only supports 1 enclosure per item + if($entry['enclosures']){ + $enclosure = $entry['enclosures'][0]; + $this->element('enclosure', array('url'=>$enclosure['url'],'type'=>$enclosure['mimetype'],'length'=>$enclosure['size']), null); + } + $this->elementEnd('item'); } -- cgit v1.2.3-54-g00ecf From fc3442a041a43f2df29deedc0ad96fbd6ba92385 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 13:26:09 -0400 Subject: Let the queue handlers drain their xmpp queues --- lib/stompqueuemanager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index d13af3fa5..359f6d9d8 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -124,7 +124,8 @@ class StompQueueManager } foreach ($handsocks as $sock) { if (in_array($sock, $read)) { - $handler->idle(QUEUE_HANDLER_HIT_IDLE); + // let it really handle this stuff + $handler->idle(QUEUE_HANDLER_MISS_IDLE); break; } } -- cgit v1.2.3-54-g00ecf From 43e0b308fdb32ed434d25b54b4a84b88d329d1bf Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 13:39:22 -0400 Subject: Revert "Let the queue handlers drain their xmpp queues" This reverts commit fc3442a041a43f2df29deedc0ad96fbd6ba92385. --- lib/stompqueuemanager.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 359f6d9d8..d13af3fa5 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -124,8 +124,7 @@ class StompQueueManager } foreach ($handsocks as $sock) { if (in_array($sock, $read)) { - // let it really handle this stuff - $handler->idle(QUEUE_HANDLER_MISS_IDLE); + $handler->idle(QUEUE_HANDLER_HIT_IDLE); break; } } -- cgit v1.2.3-54-g00ecf From 2197d0bacf44d0f2d0ab1a58446c9f4c6bd14190 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 9 Jul 2009 19:12:50 +0000 Subject: Added width/height attribute and values for the creative commons image --- lib/action.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index da5b48858..95ee10c64 100644 --- a/lib/action.php +++ b/lib/action.php @@ -772,7 +772,9 @@ class Action extends HTMLOutputter // lawsuit $this->elementStart('p'); $this->element('img', array('id' => 'license_cc', 'src' => common_config('license', 'image'), - 'alt' => common_config('license', 'title'))); + 'alt' => common_config('license', 'title'), + 'width' => '80', + 'height' => '15')); //TODO: This is dirty: i18n $this->text(_('All '.common_config('site', 'name').' content and data are available under the ')); $this->element('a', array('class' => 'license', -- cgit v1.2.3-54-g00ecf From 0828fde51ccb1a5629ab33dd23834070b95c0f37 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 15:25:59 -0400 Subject: one more shot at servicing queues --- lib/stompqueuemanager.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index d13af3fa5..46baeb5c7 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -122,12 +122,7 @@ class StompQueueManager if (in_array($stompsock, $read)) { $this->_handleNotice($queue, $handler); } - foreach ($handsocks as $sock) { - if (in_array($sock, $read)) { - $handler->idle(QUEUE_HANDLER_HIT_IDLE); - break; - } - } + $handler->idle(QUEUE_HANDLER_HIT_IDLE); } } -- cgit v1.2.3-54-g00ecf From b78801becbd963a57e3a5b5db9c2f71c0f078e14 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 18:19:13 -0400 Subject: correct the newuser default setting in common.php --- lib/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index 14be747bc..5bfb35583 100644 --- a/lib/common.php +++ b/lib/common.php @@ -206,7 +206,7 @@ $config = 'inboxes' => array('enabled' => true), # on by default for new sites 'newuser' => - array('subscribe' => null, + array('default' => null, 'welcome' => null), 'snapshot' => array('run' => 'web', -- cgit v1.2.3-54-g00ecf From efd94b4e5423c72a65cdd6acd252e5d00ec98967 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 18:22:10 -0400 Subject: change version number to 0.8.0 --- lib/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index 5bfb35583..832667d81 100644 --- a/lib/common.php +++ b/lib/common.php @@ -19,7 +19,7 @@ if (!defined('LACONICA')) { exit(1); } -define('LACONICA_VERSION', '0.8.0dev'); +define('LACONICA_VERSION', '0.8.0'); define('AVATAR_PROFILE_SIZE', 96); define('AVATAR_STREAM_SIZE', 48); -- cgit v1.2.3-54-g00ecf From 8250006fbfdc120a4766f85ff5d6ee79798d626d Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Thu, 9 Jul 2009 18:42:19 -0400 Subject: When a notice is posted with an attachment, the facebook stream update has media displayed inline, or as links. http://laconi.ca/trac/ticket/1685 --- actions/facebookhome.php | 4 +-- actions/facebooklogin.php | 4 +-- actions/facebooksettings.php | 4 +-- lib/facebookaction.php | 15 ++--------- lib/facebookutil.php | 61 +++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 65 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/actions/facebookhome.php b/actions/facebookhome.php index 34989c978..6d8d0745d 100644 --- a/actions/facebookhome.php +++ b/actions/facebookhome.php @@ -57,7 +57,7 @@ class FacebookhomeAction extends FacebookAction // If this is the first time the user has started the app // prompt for Facebook status update permission - if (!$this->facebook->api_client->users_hasAppPermission('status_update')) { + if (!$this->facebook->api_client->users_hasAppPermission('publish_stream')) { if ($this->facebook->api_client->data_getUserPreference( FACEBOOK_PROMPTED_UPDATE_PREF) != 'true') { @@ -203,7 +203,7 @@ class FacebookhomeAction extends FacebookAction $api_key = common_config('facebook', 'apikey'); $auth_url = 'http://www.facebook.com/authorize.php?api_key=' . - $api_key . '&v=1.0&ext_perm=status_update&next=' . $next . + $api_key . '&v=1.0&ext_perm=publish_stream&next=' . $next . '&next_cancel=' . $next . '&submit=skip'; $this->elementStart('span', array('class' => 'facebook-button')); diff --git a/actions/facebooklogin.php b/actions/facebooklogin.php index 22007da4f..aa86cfbc0 100644 --- a/actions/facebooklogin.php +++ b/actions/facebooklogin.php @@ -31,7 +31,7 @@ class FacebookinviteAction extends FacebookAction $this->error = $error; if ($this->flink) { - if (!$this->facebook->api_client->users_hasAppPermission('status_update') && + if (!$this->facebook->api_client->users_hasAppPermission('publish_stream') && $this->facebook->api_client->data_getUserPreference( FACEBOOK_PROMPTED_UPDATE_PREF) == 'true') { @@ -60,7 +60,7 @@ class FacebookinviteAction extends FacebookAction // If this is the first time the user has started the app // prompt for Facebook status update permission - if (!$this->facebook->api_client->users_hasAppPermission('status_update')) { + if (!$this->facebook->api_client->users_hasAppPermission('publish_stream')) { if ($this->facebook->api_client->data_getUserPreference( FACEBOOK_PROMPTED_UPDATE_PREF) != 'true') { diff --git a/actions/facebooksettings.php b/actions/facebooksettings.php index ee2c279ab..c3b364743 100644 --- a/actions/facebooksettings.php +++ b/actions/facebooksettings.php @@ -78,7 +78,7 @@ class FacebooksettingsAction extends FacebookAction } } - if ($this->facebook->api_client->users_hasAppPermission('status_update')) { + if ($this->facebook->api_client->users_hasAppPermission('publish_stream')) { $this->elementStart('form', array('method' => 'post', 'id' => 'facebook_settings')); @@ -131,7 +131,7 @@ class FacebooksettingsAction extends FacebookAction $this->elementStart('ul', array('id' => 'fb-permissions-list')); $this->elementStart('li', array('id' => 'fb-permissions-item')); - $this->elementStart('fb:prompt-permission', array('perms' => 'status_update', + $this->elementStart('fb:prompt-permission', array('perms' => 'publish_stream', 'next_fbjs' => 'document.setLocation(\'' . "$this->app_uri/settings.php" . '\')')); $this->element('span', array('class' => 'facebook-button'), sprintf(_('Allow %s to update my Facebook status'), common_config('site', 'name'))); diff --git a/lib/facebookaction.php b/lib/facebookaction.php index 1ae90d53b..5be2f2fe6 100644 --- a/lib/facebookaction.php +++ b/lib/facebookaction.php @@ -460,16 +460,6 @@ class FacebookAction extends Action } } - function updateFacebookStatus($notice) - { - $prefix = $this->facebook->api_client->data_getUserPreference(FACEBOOK_NOTICE_PREFIX, $this->fbuid); - $content = "$prefix $notice->content"; - - if ($this->facebook->api_client->users_hasAppPermission('status_update', $this->fbuid)) { - $this->facebook->api_client->users_setStatus($content, $this->fbuid, false, true); - } - } - function saveNewNotice() { @@ -504,7 +494,7 @@ class FacebookAction extends Action $replyto = $this->trimmed('inreplyto'); $notice = Notice::saveNew($user->id, $content, - 'Facebook', 1, ($replyto == 'false') ? null : $replyto); + 'web', 1, ($replyto == 'false') ? null : $replyto); if (is_string($notice)) { $this->showPage($notice); @@ -514,8 +504,7 @@ class FacebookAction extends Action common_broadcast_notice($notice); // Also update the user's Facebook status - $this->updateFacebookStatus($notice); - $this->updateProfileBox($notice); + facebookBroadcastNotice($notice); } diff --git a/lib/facebookutil.php b/lib/facebookutil.php index 632ec4bad..85077c254 100644 --- a/lib/facebookutil.php +++ b/lib/facebookutil.php @@ -86,13 +86,17 @@ function isFacebookBound($notice, $flink) { // Check to see if the user has given the FB app status update perms $result = $facebook->api_client-> - users_hasAppPermission('status_update', $fbuid); + users_hasAppPermission('publish_stream', $fbuid); + if ($result != 1) { + $result = $facebook->api_client-> + users_hasAppPermission('status_update', $fbuid); + } if ($result != 1) { $user = $flink->getUser(); $msg = "Not sending notice $notice->id to Facebook " . "because user $user->nickname hasn't given the " . - 'Facebook app \'status_update\' permission.'; + 'Facebook app \'status_update\' or \'publish_stream\' permission.'; common_debug($msg); $success = false; } @@ -138,7 +142,56 @@ function facebookBroadcastNotice($notice) // Okay, we're good to go, update the FB status try { - $facebook->api_client->users_setStatus($status, $fbuid, false, true); + $result = $facebook->api_client-> + users_hasAppPermission('publish_stream', $fbuid); + if($result == 1){ + // authorized to use the stream api, so use it + $fbattachment = null; + $attachments = $notice->attachments(); + if($attachments){ + $fbattachment=array(); + $fbattachment['media']=array(); + //facebook only supports one attachment per item + $attachment = $attachments[0]; + $fbmedia=array(); + if(strncmp($attachment->mimetype,'image/',strlen('image/'))==0){ + $fbmedia['type']='image'; + $fbmedia['src']=$attachment->url; + $fbmedia['href']=$attachment->url; + $fbattachment['media'][]=$fbmedia; +/* Video doesn't seem to work. The notice never makes it to facebook, and no error is reported. + }else if(strncmp($attachment->mimetype,'video/',strlen('image/'))==0 || $attachment->mimetype="application/ogg"){ + $fbmedia['type']='video'; + $fbmedia['video_src']=$attachment->url; + // http://wiki.developers.facebook.com/index.php/Attachment_%28Streams%29 + // says that preview_img is required... but we have no value to put in it + // $fbmedia['preview_img']=$attachment->url; + if($attachment->title){ + $fbmedia['video_title']=$attachment->title; + } + $fbmedia['video_type']=$attachment->mimetype; + $fbattachment['media'][]=$fbmedia; +*/ + }else if($attachment->mimetype=='audio/mpeg'){ + $fbmedia['type']='mp3'; + $fbmedia['src']=$attachment->url; + $fbattachment['media'][]=$fbmedia; + }else if($attachment->mimetype=='application/x-shockwave-flash'){ + $fbmedia['type']='flash'; + // http://wiki.developers.facebook.com/index.php/Attachment_%28Streams%29 + // says that imgsrc is required... but we have no value to put in it + // $fbmedia['imgsrc']=''; + $fbmedia['swfsrc']=$attachment->url; + $fbattachment['media'][]=$fbmedia; + }else{ + $fbattachment['name']=($attachment->title?$attachment->title:$attachment->url); + $fbattachment['href']=$attachment->url; + } + } + $facebook->api_client->stream_publish($status, $fbattachment, null, null, $fbuid); + }else{ + $facebook->api_client->users_setStatus($status, $fbuid, false, true); + } } catch(FacebookRestClientException $e) { common_log(LOG_ERR, $e->getMessage()); common_log(LOG_ERR, @@ -150,7 +203,7 @@ function facebookBroadcastNotice($notice) if ($code >= 200) { // 200 The application does not have permission to operate on the passed in uid parameter. - // 250 Updating status requires the extended permission status_update. + // 250 Updating status requires the extended permission status_update or publish_stream. // see: http://wiki.developers.facebook.com/index.php/Users.setStatus#Example_Return_XML remove_facebook_app($flink); -- cgit v1.2.3-54-g00ecf From 8b65883f9ddf1cb1b7bdec323722da351fa0cb69 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 17:28:38 -0700 Subject: cache frequently-used subscriber, subscription, notice and fave count values --- classes/Notice.php | 2 + classes/Profile.php | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++ classes/User.php | 2 + lib/command.php | 15 ++---- lib/profileaction.php | 21 +++------ lib/subs.php | 13 +++-- lib/twitterapi.php | 20 ++------ 7 files changed, 157 insertions(+), 44 deletions(-) (limited to 'lib') diff --git a/classes/Notice.php b/classes/Notice.php index e975cab93..75044cf63 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -356,6 +356,8 @@ class Notice extends Memcached_DataObject $this->blowTagCache($blowLast); $this->blowGroupCache($blowLast); $this->blowConversationCache($blowLast); + $profile = Profile::staticGet($this->profile_id); + $profile->blowNoticeCount(); } function blowConversationCache($blowLast=false) diff --git a/classes/Profile.php b/classes/Profile.php index a0ed6b3ca..224b61bd2 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -337,4 +337,132 @@ class Profile extends Memcached_DataObject return $profile; } + + function subscriptionCount() + { + $c = common_memcache(); + + if (!empty($c)) { + $cnt = $c->get(common_cache_key('profile:subscription_count:'.$this->id)); + if (is_integer($cnt)) { + return (int) $cnt; + } + } + + $sub = new Subscription(); + $sub->subscriber = $this->id; + + $cnt = (int) $sub->count('distinct subscribed'); + + $cnt = ($cnt > 0) ? $cnt - 1 : $cnt; + + if (!empty($c)) { + $c->set(common_cache_key('profile:subscription_count:'.$this->id), $cnt); + } + + common_debug("subscriptionCount == $cnt"); + return $cnt; + } + + function subscriberCount() + { + $c = common_memcache(); + if (!empty($c)) { + $cnt = $c->get(common_cache_key('profile:subscriber_count:'.$this->id)); + if (is_integer($cnt)) { + return (int) $cnt; + } + } + + $sub = new Subscription(); + $sub->subscribed = $this->id; + + $cnt = (int) $sub->count('distinct subscriber'); + + $cnt = ($cnt > 0) ? $cnt - 1 : $cnt; + + if (!empty($c)) { + $c->set(common_cache_key('profile:subscriber_count:'.$this->id), $cnt); + } + + common_debug("subscriberCount == $cnt"); + return $cnt; + } + + function faveCount() + { + $c = common_memcache(); + if (!empty($c)) { + $cnt = $c->get(common_cache_key('profile:fave_count:'.$this->id)); + if (is_integer($cnt)) { + return (int) $cnt; + } + } + + $faves = new Fave(); + $faves->user_id = $this->id; + $cnt = (int) $faves->count('distinct notice_id'); + + if (!empty($c)) { + $c->set(common_cache_key('profile:fave_count:'.$this->id), $cnt); + } + + common_debug("faveCount == $cnt"); + return $cnt; + } + + function noticeCount() + { + $c = common_memcache(); + + if (!empty($c)) { + $cnt = $c->get(common_cache_key('profile:notice_count:'.$this->id)); + if (is_integer($cnt)) { + return (int) $cnt; + } + } + + $notices = new Notice(); + $notices->profile_id = $this->id; + $cnt = (int) $notices->count('distinct id'); + + if (!empty($c)) { + $c->set(common_cache_key('profile:notice_count:'.$this->id), $cnt); + } + + common_debug("noticeCount == $cnt"); + return $cnt; + } + + function blowSubscriberCount() + { + $c = common_memcache(); + if (!empty($c)) { + $c->delete(common_cache_key('profile:subscriber_count:'.$this->id)); + } + } + + function blowSubscriptionCount() + { + $c = common_memcache(); + if (!empty($c)) { + $c->delete(common_cache_key('profile:subscription_count:'.$this->id)); + } + } + + function blowFaveCount() + { + $c = common_memcache(); + if (!empty($c)) { + $c->delete(common_cache_key('profile:fave_count:'.$this->id)); + } + } + + function blowNoticeCount() + { + $c = common_memcache(); + if (!empty($c)) { + $c->delete(common_cache_key('profile:notice_count:'.$this->id)); + } + } } diff --git a/classes/User.php b/classes/User.php index 04b38a0d2..6c1f149e4 100644 --- a/classes/User.php +++ b/classes/User.php @@ -494,6 +494,8 @@ class User extends Memcached_DataObject $cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id)); $cache->delete(common_cache_key('fave:ids_by_user_own:'.$this->id.';last')); } + $profile = $this->getProfile(); + $profile->blowFaveCount(); } function getSelfTags() diff --git a/lib/command.php b/lib/command.php index 564661382..4e2280bc8 100644 --- a/lib/command.php +++ b/lib/command.php @@ -97,18 +97,11 @@ class StatsCommand extends Command { function execute($channel) { + $profile = $this->user->getProfile(); - $subs = new Subscription(); - $subs->subscriber = $this->user->id; - $subs_count = (int) $subs->count() - 1; - - $subbed = new Subscription(); - $subbed->subscribed = $this->user->id; - $subbed_count = (int) $subbed->count() - 1; - - $notices = new Notice(); - $notices->profile_id = $this->user->id; - $notice_count = (int) $notices->count(); + $subs_count = $profile->subscriptionCount(); + $subbed_count = $profile->subscriberCount(); + $notice_count = $profile->noticeCount(); $channel->output($this->user, sprintf(_("Subscriptions: %1\$s\n". "Subscribers: %2\$s\n". diff --git a/lib/profileaction.php b/lib/profileaction.php index eeb5dbe48..9e9c79c78 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -163,18 +163,9 @@ class ProfileAction extends OwnerDesignAction function showStatistics() { - // XXX: WORM cache this - $subs = new Subscription(); - $subs->subscriber = $this->profile->id; - $subs_count = (int) $subs->count() - 1; - - $subbed = new Subscription(); - $subbed->subscribed = $this->profile->id; - $subbed_count = (int) $subbed->count() - 1; - - $notices = new Notice(); - $notices->profile_id = $this->profile->id; - $notice_count = (int) $notices->count(); + $subs_count = $this->profile->subscriptionCount(); + $subbed_count = $this->profile->subscriberCount(); + $notice_count = $this->profile->noticeCount(); $this->elementStart('div', array('id' => 'entity_statistics', 'class' => 'section')); @@ -199,7 +190,7 @@ class ProfileAction extends OwnerDesignAction array('nickname' => $this->profile->nickname))), _('Subscriptions')); $this->elementEnd('dt'); - $this->element('dd', null, (is_int($subs_count)) ? $subs_count : '0'); + $this->element('dd', null, $subs_count); $this->elementEnd('dl'); $this->elementStart('dl', 'entity_subscribers'); @@ -208,12 +199,12 @@ class ProfileAction extends OwnerDesignAction array('nickname' => $this->profile->nickname))), _('Subscribers')); $this->elementEnd('dt'); - $this->element('dd', 'subscribers', (is_int($subbed_count)) ? $subbed_count : '0'); + $this->element('dd', 'subscribers', $subbed_count); $this->elementEnd('dl'); $this->elementStart('dl', 'entity_notices'); $this->element('dt', null, _('Notices')); - $this->element('dd', null, (is_int($notice_count)) ? $notice_count : '0'); + $this->element('dd', null, $notice_count); $this->elementEnd('dl'); $this->elementEnd('div'); diff --git a/lib/subs.php b/lib/subs.php index 3bd67b39c..e76023752 100644 --- a/lib/subs.php +++ b/lib/subs.php @@ -44,7 +44,6 @@ function subs_subscribe_user($user, $other_nickname) function subs_subscribe_to($user, $other) { - if ($user->isSubscribed($other)) { return _('Already subscribed!.'); } @@ -60,12 +59,16 @@ function subs_subscribe_to($user, $other) subs_notify($other, $user); - $cache = common_memcache(); + $cache = common_memcache(); if ($cache) { $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); } + $profile = $user->getProfile(); + + $profile->blowSubscriptionsCount(); + $other->blowSubscribersCount(); if ($other->autosubscribe && !$other->isSubscribed($user) && !$user->hasBlocked($other)) { if (!$other->subscribeTo($user)) { @@ -117,7 +120,6 @@ function subs_unsubscribe_user($user, $other_nickname) function subs_unsubscribe_to($user, $other) { - if (!$user->isSubscribed($other)) return _('Not subscribed!.'); @@ -139,6 +141,11 @@ function subs_unsubscribe_to($user, $other) $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); } + $profile = $user->getProfile(); + + $profile->blowSubscriptionsCount(); + $other->blowSubscribersCount(); + return true; } diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 8f902cbca..f48513e67 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -89,7 +89,7 @@ class TwitterapiAction extends Action $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null; $twitter_user['protected'] = false; # not supported by Laconica yet - $twitter_user['followers_count'] = $this->count_subscriptions($profile); + $twitter_user['followers_count'] = $profile->subscriberCount(); // To be supported soon... $twitter_user['profile_background_color'] = ''; @@ -98,17 +98,11 @@ class TwitterapiAction extends Action $twitter_user['profile_sidebar_fill_color'] = ''; $twitter_user['profile_sidebar_border_color'] = ''; - $subbed = DB_DataObject::factory('subscription'); - $subbed->subscriber = $profile->id; - $subbed_count = (int) $subbed->count() - 1; - $twitter_user['friends_count'] = (is_int($subbed_count)) ? $subbed_count : 0; + $twitter_user['friends_count'] = $profile->subscriptionCount(); $twitter_user['created_at'] = $this->date_twitter($profile->created); - $faves = DB_DataObject::factory('fave'); - $faves->user_id = $user->id; - $faves_count = (int) $faves->count(); - $twitter_user['favourites_count'] = $faves_count; // British spelling! + $twitter_user['favourites_count'] = $profile->faveCount(); // British spelling! // Need to pull up the user for some of this $user = User::staticGet($profile->id); @@ -129,11 +123,7 @@ class TwitterapiAction extends Action $twitter_user['profile_background_image_url'] = ''; $twitter_user['profile_background_tile'] = false; - $notices = DB_DataObject::factory('notice'); - $notices->profile_id = $profile->id; - $notice_count = (int) $notices->count(); - - $twitter_user['statuses_count'] = (is_int($notice_count)) ? $notice_count : 0; + $twitter_user['statuses_count'] = $profile->noticeCount(); // Is the requesting user following this user? $twitter_user['following'] = false; @@ -396,7 +386,7 @@ class TwitterapiAction extends Action $enclosure = $entry['enclosures'][0]; $this->element('enclosure', array('url'=>$enclosure['url'],'type'=>$enclosure['mimetype'],'length'=>$enclosure['size']), null); } - + $this->elementEnd('item'); } -- cgit v1.2.3-54-g00ecf From f527b8a8d7cf38e21c0ceb8d54cfae2d679e1564 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 17:40:11 -0700 Subject: wrong order for span and a in profilesection --- lib/profilesection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/profilesection.php b/lib/profilesection.php index 8ed290e03..9ff243fb5 100644 --- a/lib/profilesection.php +++ b/lib/profilesection.php @@ -94,8 +94,8 @@ class ProfileSection extends Section $profile->fullname : $profile->nickname)); $this->out->element('span', 'fn nickname', $profile->nickname); - $this->out->elementEnd('span'); $this->out->elementEnd('a'); + $this->out->elementEnd('span'); $this->out->elementEnd('td'); if ($profile->value) { $this->out->element('td', 'value', $profile->value); -- cgit v1.2.3-54-g00ecf From 15f6309deacf64e6b408d45a4eb19852d36f9f72 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 9 Jul 2009 23:12:53 -0700 Subject: add a little syntactical sugar for adding plugins --- lib/common.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index 832667d81..c47702779 100644 --- a/lib/common.php +++ b/lib/common.php @@ -282,6 +282,39 @@ if (function_exists('date_default_timezone_set')) { date_default_timezone_set('UTC'); } +function addPlugin($name, $attrs = null) +{ + $name = ucfirst($name); + $pluginclass = "{$name}Plugin"; + + if (!class_exists($pluginclass)) { + + $files = array("local/plugins/{$pluginclass}.php", + "local/plugins/{$name}/{$pluginclass}.php", + "local/{$pluginclass}.php", + "local/{$name}/{$pluginclass}.php", + "plugins/{$pluginclass}.php", + "plugins/{$name}/{$pluginclass}.php"); + + foreach ($files as $file) { + $fullpath = INSTALLDIR.'/'.$file; + if (@file_exists($fullpath)) { + include_once($fullpath); + break; + } + } + } + + $inst = new $pluginclass(); + + if (!empty($attrs)) { + foreach ($attrs as $aname => $avalue) { + $inst->$aname = $avalue; + } + } + return $inst; +} + // From most general to most specific: // server-wide, then vhost-wide, then for a path, // finally for a dir (usually only need one of the last two). -- cgit v1.2.3-54-g00ecf From 08d50655f3a220b1fe970b0917a6ecbcae019b04 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 10 Jul 2009 17:00:27 -0400 Subject: added group status api, located at /api/statuses/group_timeline/ID.rss http://laconi.ca/trac/ticket/1702 --- actions/showgroup.php | 23 +++++++++++++++--- actions/twitapistatuses.php | 58 +++++++++++++++++++++++++++++++++++++++++++++ lib/router.php | 2 +- lib/twitterapi.php | 28 ++++++++++++++++++++++ 4 files changed, 107 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/actions/showgroup.php b/actions/showgroup.php index ce11d574e..f803840ff 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -317,8 +317,25 @@ class ShowgroupAction extends GroupDesignAction common_local_url('grouprss', array('nickname' => $this->group->nickname)); - return array(new Feed(Feed::RSS1, $url, sprintf(_('Notice feed for %s group'), - $this->group->nickname))); + return array(new Feed(Feed::RSS1, + common_local_url('grouprss', + array('nickname' => $this->group->nickname)), + sprintf(_('Notice feed for %s group (RSS 1.0)'), + $this->group->nickname)), + new Feed(Feed::RSS2, + common_local_url('api', + array('apiaction' => 'statuses', + 'method' => 'group_timeline', + 'argument' => $this->group->nickname.'.rss')), + sprintf(_('Notice feed for %s group (RSS 2.0)'), + $this->group->nickname)), + new Feed(Feed::ATOM, + common_local_url('api', + array('apiaction' => 'statuses', + 'method' => 'group_timeline', + 'argument' => $this->group->nickname.'.atom')), + sprintf(_('Notice feed for %s group (Atom)'), + $this->group->nickname))); } /** @@ -466,4 +483,4 @@ class GroupAdminSection extends ProfileSection { return null; } -} \ No newline at end of file +} diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index c9943698d..ec5d378f0 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -136,6 +136,64 @@ class TwitapistatusesAction extends TwitterapiAction } + function group_timeline($args, $apidata) + { + parent::handle($args); + + $this->auth_user = $apidata['user']; + $group = $this->get_group($apidata['api_arg'], $apidata); + + if (empty($group)) { + $this->clientError('Not Found', 404, $apidata['content-type']); + return; + } + + $sitename = common_config('site', 'name'); + $title = sprintf(_("%s timeline"), $group->nickname); + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:GroupTimeline:".$group->id; + $link = common_local_url('showstream', + array('nickname' => $group->nickname)); + $subtitle = sprintf(_('Updates from %1$s on %2$s!'), + $group->nickname, $sitename); + + $page = (int)$this->arg('page', 1); + $count = (int)$this->arg('count', 20); + $max_id = (int)$this->arg('max_id', 0); + $since_id = (int)$this->arg('since_id', 0); + $since = $this->arg('since'); + + $notice = $group->getNotices(($page-1)*$count, + $count, $since_id, $max_id, $since); + + switch($apidata['content-type']) { + case 'xml': + $this->show_xml_timeline($notice); + break; + case 'rss': + $this->show_rss_timeline($notice, $title, $link, + $subtitle, $suplink); + break; + case 'atom': + if (isset($apidata['api_arg'])) { + $selfuri = common_root_url() . + 'api/statuses/group_timeline/' . + $apidata['api_arg'] . '.atom'; + } else { + $selfuri = common_root_url() . + 'api/statuses/group_timeline.atom'; + } + $this->show_atom_timeline($notice, $title, $id, $link, + $subtitle, $suplink, $selfuri); + break; + case 'json': + $this->show_json_timeline($notice); + break; + default: + $this->clientError(_('API method not found!'), $code = 404); + } + } + function user_timeline($args, $apidata) { parent::handle($args); diff --git a/lib/router.php b/lib/router.php index 75e72f932..bc063038f 100644 --- a/lib/router.php +++ b/lib/router.php @@ -266,7 +266,7 @@ class Router $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); + array('method' => '(group_timeline|user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); // users diff --git a/lib/twitterapi.php b/lib/twitterapi.php index f48513e67..d2515070d 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -774,6 +774,34 @@ class TwitterapiAction extends Action } } + function get_group($id, $apidata=null) + { + if (empty($id)) { + + if (is_numeric($this->arg('id'))) { + return User::staticGet($this->arg('id')); + } else if ($this->arg('id')) { + $nickname = common_canonical_nickname($this->arg('id')); + return User_group::staticGet('nickname', $nickname); + } else if ($this->arg('user_id')) { + // This is to ensure that a non-numeric user_id still + // overrides screen_name even if it doesn't get used + if (is_numeric($this->arg('user_id'))) { + return User_group::staticGet('id', $this->arg('user_id')); + } + } else if ($this->arg('screen_name')) { + $nickname = common_canonical_nickname($this->arg('screen_name')); + return User::staticGet('nickname', $nickname); + } + + } else if (is_numeric($id)) { + return User_group::staticGet($id); + } else { + $nickname = common_canonical_nickname($id); + return User_group::staticGet('nickname', $nickname); + } + } + function get_profile($id) { if (is_numeric($id)) { -- cgit v1.2.3-54-g00ecf From 544a14d290cc6c08950b2d4a6faf324704e90c6c Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 10 Jul 2009 17:56:01 -0700 Subject: Move groups timeline API method into groups API action --- actions/twitapigroups.php | 114 ++++++++++++++++++++++++++++++++++++++++++++ actions/twitapistatuses.php | 58 ---------------------- lib/router.php | 7 ++- 3 files changed, 120 insertions(+), 59 deletions(-) create mode 100644 actions/twitapigroups.php (limited to 'lib') diff --git a/actions/twitapigroups.php b/actions/twitapigroups.php new file mode 100644 index 000000000..c8aae173f --- /dev/null +++ b/actions/twitapigroups.php @@ -0,0 +1,114 @@ +. + * + * @category Twitter + * @package Laconica + * @author Craig Andrews + * @author Zach Copley + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/twitterapi.php'; + +/** + * Group-specific API methods + * + * This class handles Laconica group API methods. + * + * @category Twitter + * @package Laconica + * @author Craig Andrews + * @author Zach Copley + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + + class TwitapigroupsAction extends TwitterapiAction + { + + function timeline($args, $apidata) + { + parent::handle($args); + + common_debug("in groups api action"); + + $this->auth_user = $apidata['user']; + $group = $this->get_group($apidata['api_arg'], $apidata); + + if (empty($group)) { + $this->clientError('Not Found', 404, $apidata['content-type']); + return; + } + + $sitename = common_config('site', 'name'); + $title = sprintf(_("%s timeline"), $group->nickname); + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:GroupTimeline:".$group->id; + $link = common_local_url('showstream', + array('nickname' => $group->nickname)); + $subtitle = sprintf(_('Updates from %1$s on %2$s!'), + $group->nickname, $sitename); + + $page = (int)$this->arg('page', 1); + $count = (int)$this->arg('count', 20); + $max_id = (int)$this->arg('max_id', 0); + $since_id = (int)$this->arg('since_id', 0); + $since = $this->arg('since'); + + $notice = $group->getNotices(($page-1)*$count, + $count, $since_id, $max_id, $since); + + switch($apidata['content-type']) { + case 'xml': + $this->show_xml_timeline($notice); + break; + case 'rss': + $this->show_rss_timeline($notice, $title, $link, + $subtitle, $suplink); + break; + case 'atom': + if (isset($apidata['api_arg'])) { + $selfuri = common_root_url() . + 'api/statuses/group_timeline/' . + $apidata['api_arg'] . '.atom'; + } else { + $selfuri = common_root_url() . + 'api/statuses/group_timeline.atom'; + } + $this->show_atom_timeline($notice, $title, $id, $link, + $subtitle, $suplink, $selfuri); + break; + case 'json': + $this->show_json_timeline($notice); + break; + default: + $this->clientError(_('API method not found!'), $code = 404); + } + } + +} \ No newline at end of file diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index ec5d378f0..c9943698d 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -136,64 +136,6 @@ class TwitapistatusesAction extends TwitterapiAction } - function group_timeline($args, $apidata) - { - parent::handle($args); - - $this->auth_user = $apidata['user']; - $group = $this->get_group($apidata['api_arg'], $apidata); - - if (empty($group)) { - $this->clientError('Not Found', 404, $apidata['content-type']); - return; - } - - $sitename = common_config('site', 'name'); - $title = sprintf(_("%s timeline"), $group->nickname); - $taguribase = common_config('integration', 'taguri'); - $id = "tag:$taguribase:GroupTimeline:".$group->id; - $link = common_local_url('showstream', - array('nickname' => $group->nickname)); - $subtitle = sprintf(_('Updates from %1$s on %2$s!'), - $group->nickname, $sitename); - - $page = (int)$this->arg('page', 1); - $count = (int)$this->arg('count', 20); - $max_id = (int)$this->arg('max_id', 0); - $since_id = (int)$this->arg('since_id', 0); - $since = $this->arg('since'); - - $notice = $group->getNotices(($page-1)*$count, - $count, $since_id, $max_id, $since); - - switch($apidata['content-type']) { - case 'xml': - $this->show_xml_timeline($notice); - break; - case 'rss': - $this->show_rss_timeline($notice, $title, $link, - $subtitle, $suplink); - break; - case 'atom': - if (isset($apidata['api_arg'])) { - $selfuri = common_root_url() . - 'api/statuses/group_timeline/' . - $apidata['api_arg'] . '.atom'; - } else { - $selfuri = common_root_url() . - 'api/statuses/group_timeline.atom'; - } - $this->show_atom_timeline($notice, $title, $id, $link, - $subtitle, $suplink, $selfuri); - break; - case 'json': - $this->show_json_timeline($notice); - break; - default: - $this->clientError(_('API method not found!'), $code = 404); - } - } - function user_timeline($args, $apidata) { parent::handle($args); diff --git a/lib/router.php b/lib/router.php index bc063038f..cd2143d13 100644 --- a/lib/router.php +++ b/lib/router.php @@ -266,7 +266,7 @@ class Router $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(group_timeline|user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); + array('method' => '(|user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); // users @@ -394,6 +394,11 @@ class Router array('action' => 'api', 'apiaction' => 'laconica')); + // Groups + $m->connect('api/laconica/groups/:method/:argument', + array('action' => 'api', + 'apiaction' => 'groups')); + // search $m->connect('api/search.atom', array('action' => 'twitapisearchatom')); $m->connect('api/search.json', array('action' => 'twitapisearchjson')); -- cgit v1.2.3-54-g00ecf From 0ac08c1fb3a930af420cb9c4252bc6f499ba1141 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 10 Jul 2009 18:22:19 -0700 Subject: Make get_group() behave more like get_user() --- lib/router.php | 4 ++++ lib/twitterapi.php | 14 +++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/router.php b/lib/router.php index cd2143d13..8104d7818 100644 --- a/lib/router.php +++ b/lib/router.php @@ -399,6 +399,10 @@ class Router array('action' => 'api', 'apiaction' => 'groups')); + $m->connect('api/laconica/groups/:method', + array('action' => 'api', + 'apiaction' => 'groups')); + // search $m->connect('api/search.atom', array('action' => 'twitapisearchatom')); $m->connect('api/search.json', array('action' => 'twitapisearchjson')); diff --git a/lib/twitterapi.php b/lib/twitterapi.php index d2515070d..4f3a5c0b6 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -779,19 +779,19 @@ class TwitterapiAction extends Action if (empty($id)) { if (is_numeric($this->arg('id'))) { - return User::staticGet($this->arg('id')); + return User_group::staticGet($this->arg('id')); } else if ($this->arg('id')) { $nickname = common_canonical_nickname($this->arg('id')); return User_group::staticGet('nickname', $nickname); - } else if ($this->arg('user_id')) { + } else if ($this->arg('group_id')) { // This is to ensure that a non-numeric user_id still // overrides screen_name even if it doesn't get used - if (is_numeric($this->arg('user_id'))) { - return User_group::staticGet('id', $this->arg('user_id')); + if (is_numeric($this->arg('group_id'))) { + return User_group::staticGet('id', $this->arg('group_id')); } - } else if ($this->arg('screen_name')) { - $nickname = common_canonical_nickname($this->arg('screen_name')); - return User::staticGet('nickname', $nickname); + } else if ($this->arg('group_name')) { + $nickname = common_canonical_nickname($this->arg('group_name')); + return User_group::staticGet('nickname', $nickname); } } else if (is_numeric($id)) { -- cgit v1.2.3-54-g00ecf