]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Move Commands stuff out of classes
authorEvan Prodromou <evan@controlyourself.ca>
Wed, 11 Feb 2009 20:46:29 +0000 (15:46 -0500)
committerEvan Prodromou <evan@controlyourself.ca>
Wed, 11 Feb 2009 20:46:29 +0000 (15:46 -0500)
The classes/ subdir is primarily for the DB_DataObject classes. Stuff
in there can get stomped by various generation scripts.

I've moved the lurkers there -- related to command-handling -- to
lib/. Since auto-loading works fine with lib/, there shouldn't be much
of a visible change here.

classes/Channel.php [deleted file]
classes/Command.php [deleted file]
classes/CommandInterpreter.php [deleted file]
lib/channel.php [new file with mode: 0644]
lib/command.php [new file with mode: 0644]
lib/commandinterpreter.php [new file with mode: 0644]

diff --git a/classes/Channel.php b/classes/Channel.php
deleted file mode 100644 (file)
index fdeff21..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-<?php
-/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('LACONICA')) { exit(1); }
-
-class Channel
-{
-
-    function on($user)
-    {
-        return false;
-    }
-
-    function off($user)
-    {
-        return false;
-    }
-
-    function output($user, $text)
-    {
-        return false;
-    }
-
-    function error($user, $text)
-    {
-        return false;
-    }
-
-    function source()
-    {
-        return null;
-    }
-}
-
-class XMPPChannel extends Channel
-{
-
-    var $conn = null;
-
-    function source()
-    {
-        return 'xmpp';
-    }
-
-    function __construct($conn)
-    {
-        $this->conn = $conn;
-    }
-
-    function on($user)
-    {
-        return $this->set_notify($user, 1);
-    }
-
-    function off($user)
-    {
-        return $this->set_notify($user, 0);
-    }
-
-    function output($user, $text)
-    {
-        $text = '['.common_config('site', 'name') . '] ' . $text;
-        jabber_send_message($user->jabber, $text);
-    }
-
-    function error($user, $text)
-    {
-        $text = '['.common_config('site', 'name') . '] ' . $text;
-        jabber_send_message($user->jabber, $text);
-    }
-
-    function set_notify(&$user, $notify)
-    {
-        $orig = clone($user);
-        $user->jabbernotify = $notify;
-        $result = $user->update($orig);
-        if (!$result) {
-            $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
-            common_log(LOG_ERR,
-                       'Could not set notify flag to ' . $notify .
-                       ' for user ' . common_log_objstring($user) .
-                       ': ' . $last_error->message);
-            return false;
-        } else {
-            common_log(LOG_INFO,
-                       'User ' . $user->nickname . ' set notify flag to ' . $notify);
-            return true;
-        }
-    }
-}
-
-class WebChannel extends Channel
-{
-    var $out = null;
-
-    function __construct($out=null)
-    {
-        $this->out = $out;
-    }
-
-    function source()
-    {
-        return 'web';
-    }
-
-    function on($user)
-    {
-        return false;
-    }
-
-    function off($user)
-    {
-        return false;
-    }
-
-    function output($user, $text)
-    {
-        # XXX: buffer all output and send it at the end
-        # XXX: even better, redirect to appropriate page
-        #      depending on what command was run
-        $this->out->startHTML();
-        $this->out->elementStart('head');
-        $this->out->element('title', null, _('Command results'));
-        $this->out->elementEnd('head');
-        $this->out->elementStart('body');
-        $this->out->element('p', array('id' => 'command_result'), $text);
-        $this->out->elementEnd('body');
-        $this->out->endHTML();
-    }
-
-    function error($user, $text)
-    {
-        common_user_error($text);
-    }
-}
-
-class AjaxWebChannel extends WebChannel
-{
-    function output($user, $text)
-    {
-        $this->out->startHTML('text/xml;charset=utf-8');
-        $this->out->elementStart('head');
-        $this->out->element('title', null, _('Command results'));
-        $this->out->elementEnd('head');
-        $this->out->elementStart('body');
-        $this->out->element('p', array('id' => 'command_result'), $text);
-        $this->out->elementEnd('body');
-        $this->out->endHTML();
-    }
-
-    function error($user, $text)
-    {
-        $this->out->startHTML('text/xml;charset=utf-8');
-        $this->out->elementStart('head');
-        $this->out->element('title', null, _('Ajax Error'));
-        $this->out->elementEnd('head');
-        $this->out->elementStart('body');
-        $this->out->element('p', array('id' => 'error'), $text);
-        $this->out->elementEnd('body');
-        $this->out->endHTML();
-    }
-}
-
-class MailChannel extends Channel
-{
-
-    var $addr = null;
-
-    function source()
-    {
-        return 'mail';
-    }
-
-    function __construct($addr=null)
-    {
-        $this->addr = $addr;
-    }
-
-    function on($user)
-    {
-        return $this->set_notify($user, 1);
-    }
-
-    function off($user)
-    {
-        return $this->set_notify($user, 0);
-    }
-
-    function output($user, $text)
-    {
-
-        $headers['From'] = $user->incomingemail;
-        $headers['To'] = $this->addr;
-
-        $headers['Subject'] = _('Command complete');
-
-        return mail_send(array($this->addr), $headers, $text);
-    }
-
-    function error($user, $text)
-    {
-
-        $headers['From'] = $user->incomingemail;
-        $headers['To'] = $this->addr;
-
-        $headers['Subject'] = _('Command failed');
-
-        return mail_send(array($this->addr), $headers, $text);
-    }
-
-    function set_notify($user, $value)
-    {
-        $orig = clone($user);
-        $user->smsnotify = $value;
-        $result = $user->update($orig);
-        if (!$result) {
-            common_log_db_error($user, 'UPDATE', __FILE__);
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/classes/Command.php b/classes/Command.php
deleted file mode 100644 (file)
index eacbdac..0000000
+++ /dev/null
@@ -1,419 +0,0 @@
-<?php
-/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('LACONICA')) { exit(1); }
-
-require_once(INSTALLDIR.'/classes/Channel.php');
-
-class Command
-{
-    
-    var $user = null;
-    
-    function __construct($user=null)
-    {
-        $this->user = $user;
-    }
-    
-    function execute($channel)
-    {
-        return false;
-    }
-}
-
-class UnimplementedCommand extends Command
-{
-    function execute($channel)
-    {
-        $channel->error($this->user, _("Sorry, this command is not yet implemented."));
-    }
-}
-
-class TrackingCommand extends UnimplementedCommand
-{
-}
-
-class TrackOffCommand extends UnimplementedCommand
-{
-}
-
-class TrackCommand extends UnimplementedCommand
-{
-    var $word = null;
-    function __construct($user, $word)
-    {
-        parent::__construct($user);
-        $this->word = $word;
-    }
-}
-
-class UntrackCommand extends UnimplementedCommand
-{
-    var $word = null;
-    function __construct($user, $word)
-    {
-        parent::__construct($user);
-        $this->word = $word;
-    }
-}
-
-class NudgeCommand extends UnimplementedCommand
-{
-    var $other = null;
-    function __construct($user, $other)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-}
-
-class InviteCommand extends UnimplementedCommand
-{
-    var $other = null;
-    function __construct($user, $other)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-}
-
-class StatsCommand extends Command
-{
-    function execute($channel)
-    {
-
-        $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();
-        
-        $channel->output($this->user, sprintf(_("Subscriptions: %1\$s\n".
-                                   "Subscribers: %2\$s\n".
-                                   "Notices: %3\$s"),
-                                 $subs_count,
-                                 $subbed_count,
-                                 $notice_count));
-    }
-}
-
-class FavCommand extends Command
-{
-    
-    var $other = null;
-    
-    function __construct($user, $other)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-    
-    function execute($channel)
-    {
-        
-        $recipient = 
-          common_relative_profile($this->user, common_canonical_nickname($this->other));
-        
-        if (!$recipient) {
-            $channel->error($this->user, _('No such user.'));
-            return;
-        }
-        $notice = $recipient->getCurrentNotice();
-        if (!$notice) {
-            $channel->error($this->user, _('User has no last notice'));
-            return;
-        }
-        
-        $fave = Fave::addNew($this->user, $notice);
-
-        if (!$fave) {
-            $channel->error($this->user, _('Could not create favorite.'));
-            return;
-        }
-
-        $other = User::staticGet('id', $recipient->id);
-        
-        if ($other && $other->id != $user->id) {
-            if ($other->email && $other->emailnotifyfav) {
-                mail_notify_fave($other, $this->user, $notice);
-            }
-        }
-        
-        $this->user->blowFavesCache();
-        
-        $channel->output($this->user, _('Notice marked as fave.'));
-    }
-}
-
-class WhoisCommand extends Command
-{
-    var $other = null;
-    function __construct($user, $other)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-    
-    function execute($channel)
-    {
-        $recipient = 
-          common_relative_profile($this->user, common_canonical_nickname($this->other));
-        
-        if (!$recipient) {
-            $channel->error($this->user, _('No such user.'));
-            return;
-        }
-        
-        $whois = sprintf(_("%1\$s (%2\$s)"), $recipient->nickname,
-                         $recipient->profileurl);
-        if ($recipient->fullname) {
-            $whois .= "\n" . sprintf(_('Fullname: %s'), $recipient->fullname);
-        }
-        if ($recipient->location) {
-            $whois .= "\n" . sprintf(_('Location: %s'), $recipient->location);
-        }
-        if ($recipient->homepage) {
-            $whois .= "\n" . sprintf(_('Homepage: %s'), $recipient->homepage);
-        }
-        if ($recipient->bio) {
-            $whois .= "\n" . sprintf(_('About: %s'), $recipient->bio);
-        }
-        $channel->output($this->user, $whois);
-    }
-}
-
-class MessageCommand extends Command
-{
-    var $other = null;
-    var $text = null;
-    function __construct($user, $other, $text)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-        $this->text = $text;
-    }
-    
-    function execute($channel)
-    {
-        $other = User::staticGet('nickname', common_canonical_nickname($this->other));
-        $len = mb_strlen($this->text);
-        if ($len == 0) {
-            $channel->error($this->user, _('No content!'));
-            return;
-        } else if ($len > 140) {
-            $content = common_shorten_links($content);
-            if (mb_strlen($content) > 140) {
-                $channel->error($this->user, sprintf(_('Message too long - maximum is 140 characters, you sent %d'), $len));
-                return;
-            }
-        }
-        
-        if (!$other) {
-            $channel->error($this->user, _('No such user.'));
-            return;
-        } else if (!$this->user->mutuallySubscribed($other)) {
-            $channel->error($this->user, _('You can\'t send a message to this user.'));
-            return;
-        } else if ($this->user->id == $other->id) {
-            $channel->error($this->user, _('Don\'t send a message to yourself; just say it to yourself quietly instead.'));
-            return;
-        }
-        $message = Message::saveNew($this->user->id, $other->id, $this->text, $channel->source());
-        if ($message) {
-            $channel->output($this->user, sprintf(_('Direct message to %s sent'), $this->other));
-        } else {
-            $channel->error($this->user, _('Error sending direct message.'));
-        }
-    }
-}
-
-class GetCommand extends Command
-{
-    
-    var $other = null;
-    
-    function __construct($user, $other)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-    
-    function execute($channel)
-    {
-        $target_nickname = common_canonical_nickname($this->other);
-        
-        $target =
-          common_relative_profile($this->user, $target_nickname);
-
-        if (!$target) {
-            $channel->error($this->user, _('No such user.'));
-            return;
-        }
-        $notice = $target->getCurrentNotice();
-        if (!$notice) {
-            $channel->error($this->user, _('User has no last notice'));
-            return;
-        }
-        $notice_content = $notice->content;
-        
-        $channel->output($this->user, $target_nickname . ": " . $notice_content);
-    }
-}
-
-class SubCommand extends Command
-{
-    
-    var $other = null;
-    
-    function __construct($user, $other)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-    
-    function execute($channel)
-    {
-        
-        if (!$this->other) {
-            $channel->error($this->user, _('Specify the name of the user to subscribe to'));
-            return;
-        }
-        
-        $result = subs_subscribe_user($this->user, $this->other);
-        
-        if ($result == 'true') {
-            $channel->output($this->user, sprintf(_('Subscribed to %s'), $this->other));
-        } else {
-            $channel->error($this->user, $result);
-        }
-    }
-}
-
-class UnsubCommand extends Command
-{
-
-    var $other = null;
-    
-    function __construct($user, $other)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-
-    function execute($channel)
-    {
-        if(!$this->other) {
-            $channel->error($this->user, _('Specify the name of the user to unsubscribe from'));
-            return;
-        }
-        
-        $result=subs_unsubscribe_user($this->user, $this->other);
-        
-        if ($result) {
-            $channel->output($this->user, sprintf(_('Unsubscribed from %s'), $this->other));
-        } else {
-            $channel->error($this->user, $result);
-        }
-    }
-}
-
-class OffCommand extends Command
-{
-    var $other = null;
-    function __construct($user, $other=null)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-    function execute($channel)
-    {
-        if ($other) {
-            $channel->error($this->user, _("Command not yet implemented."));
-        } else {
-            if ($channel->off($this->user)) {
-                $channel->output($this->user, _('Notification off.'));
-            } else {
-                $channel->error($this->user, _('Can\'t turn off notification.'));
-            }
-        }
-    }
-}
-
-class OnCommand extends Command
-{
-    var $other = null;
-    function __construct($user, $other=null)
-    {
-        parent::__construct($user);
-        $this->other = $other;
-    }
-    
-    function execute($channel)
-    {
-        if ($other) {
-            $channel->error($this->user, _("Command not yet implemented."));
-        } else {
-            if ($channel->on($this->user)) {
-                $channel->output($this->user, _('Notification on.'));
-            } else {
-                $channel->error($this->user, _('Can\'t turn on notification.'));
-            }
-        }
-    }
-}
-
-class HelpCommand extends Command
-{
-    function execute($channel)
-    {
-        $channel->output($this->user,
-                         _("Commands:\n".
-                           "on - turn on notifications\n".
-                           "off - turn off notifications\n".
-                           "help - show this help\n".
-                           "follow <nickname> - subscribe to user\n".
-                           "leave <nickname> - unsubscribe from user\n".
-                           "d <nickname> <text> - direct message to user\n".
-                           "get <nickname> - get last notice from user\n".
-                           "whois <nickname> - get profile info on user\n".
-                           "fav <nickname> - add user's last notice as a 'fave'\n".
-                           "stats - get your stats\n".
-                           "stop - same as 'off'\n".
-                           "quit - same as 'off'\n".
-                           "sub <nickname> - same as 'follow'\n".
-                           "unsub <nickname> - same as 'leave'\n".
-                           "last <nickname> - same as 'get'\n".
-                           "on <nickname> - not yet implemented.\n".
-                           "off <nickname> - not yet implemented.\n".                           
-                           "nudge <nickname> - not yet implemented.\n".
-                           "invite <phone number> - not yet implemented.\n".
-                           "track <word> - not yet implemented.\n".
-                           "untrack <word> - not yet implemented.\n".
-                           "track off - not yet implemented.\n".
-                           "untrack all - not yet implemented.\n".
-                           "tracks - not yet implemented.\n".
-                           "tracking - not yet implemented.\n"));
-    }
-}
diff --git a/classes/CommandInterpreter.php b/classes/CommandInterpreter.php
deleted file mode 100644 (file)
index 0679f54..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-<?php
-/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('LACONICA')) { exit(1); }
-
-require_once(INSTALLDIR.'/classes/Command.php');
-
-class CommandInterpreter
-{
-
-    function handle_command($user, $text)
-    {
-        # XXX: localise
-
-        $text = preg_replace('/\s+/', ' ', trim($text));
-        list($cmd, $arg) = explode(' ', $text, 2);
-
-        # We try to support all the same commands as Twitter, see
-        # http://getsatisfaction.com/twitter/topics/what_are_the_twitter_commands
-        # There are a few compatibility commands from earlier versions of
-        # Laconica
-
-        switch(strtolower($cmd)) {
-         case 'help':
-            if ($arg) {
-                return null;
-            }
-            return new HelpCommand($user);
-         case 'on':
-            if ($arg) {
-                list($other, $extra) = explode(' ', $arg, 2);
-                if ($extra) {
-                    return null;
-                } else {
-                    return new OnCommand($user, $other);
-                }
-            } else {
-                return new OnCommand($user);
-            }
-         case 'off':
-            if ($arg) {
-                list($other, $extra) = explode(' ', $arg, 2);
-                if ($extra) {
-                    return null;
-                } else {
-                    return new OffCommand($user, $other);
-                }
-            } else {
-                return new OffCommand($user);
-            }
-         case 'stop':
-         case 'quit':
-            if ($arg) {
-                return null;
-            } else {
-                return new OffCommand($user);
-            }
-         case 'follow':
-         case 'sub':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else {
-                return new SubCommand($user, $other);
-            }
-         case 'leave':
-         case 'unsub':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else {
-                return new UnsubCommand($user, $other);
-            }
-         case 'get':
-         case 'last':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else {
-                return new GetCommand($user, $other);
-            }
-         case 'd':
-         case 'dm':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if (!$extra) {
-                return null;
-            } else {
-                return new MessageCommand($user, $other, $extra);
-            }
-         case 'whois':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else {
-                return new WhoisCommand($user, $other);
-            }
-         case 'fav':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else {
-                return new FavCommand($user, $other);
-            }
-         case 'nudge':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else {
-                return new NudgeCommand($user, $other);
-            }
-         case 'stats':
-            if ($arg) {
-                return null;
-            }
-            return new StatsCommand($user);
-         case 'invite':
-            if (!$arg) {
-                return null;
-            }
-            list($other, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else {
-                return new InviteCommand($user, $other);
-            }
-         case 'track':
-            if (!$arg) {
-                return null;
-            }
-            list($word, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else if ($word == 'off') {
-                return new TrackOffCommand($user);
-            } else {
-                return new TrackCommand($user, $word);
-            }
-         case 'untrack':
-            if (!$arg) {
-                return null;
-            }
-            list($word, $extra) = explode(' ', $arg, 2);
-            if ($extra) {
-                return null;
-            } else if ($word == 'all') {
-                return new TrackOffCommand($user);
-            } else {
-                return new UntrackCommand($user, $word);
-            }
-         case 'tracks':
-         case 'tracking':
-            if ($arg) {
-                return null;
-            }
-            return new TrackingCommand($user);
-         default:
-            return false;
-        }
-    }
-}
-
diff --git a/lib/channel.php b/lib/channel.php
new file mode 100644 (file)
index 0000000..fdeff21
--- /dev/null
@@ -0,0 +1,238 @@
+<?php
+/*
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, Controlez-Vous, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('LACONICA')) { exit(1); }
+
+class Channel
+{
+
+    function on($user)
+    {
+        return false;
+    }
+
+    function off($user)
+    {
+        return false;
+    }
+
+    function output($user, $text)
+    {
+        return false;
+    }
+
+    function error($user, $text)
+    {
+        return false;
+    }
+
+    function source()
+    {
+        return null;
+    }
+}
+
+class XMPPChannel extends Channel
+{
+
+    var $conn = null;
+
+    function source()
+    {
+        return 'xmpp';
+    }
+
+    function __construct($conn)
+    {
+        $this->conn = $conn;
+    }
+
+    function on($user)
+    {
+        return $this->set_notify($user, 1);
+    }
+
+    function off($user)
+    {
+        return $this->set_notify($user, 0);
+    }
+
+    function output($user, $text)
+    {
+        $text = '['.common_config('site', 'name') . '] ' . $text;
+        jabber_send_message($user->jabber, $text);
+    }
+
+    function error($user, $text)
+    {
+        $text = '['.common_config('site', 'name') . '] ' . $text;
+        jabber_send_message($user->jabber, $text);
+    }
+
+    function set_notify(&$user, $notify)
+    {
+        $orig = clone($user);
+        $user->jabbernotify = $notify;
+        $result = $user->update($orig);
+        if (!$result) {
+            $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
+            common_log(LOG_ERR,
+                       'Could not set notify flag to ' . $notify .
+                       ' for user ' . common_log_objstring($user) .
+                       ': ' . $last_error->message);
+            return false;
+        } else {
+            common_log(LOG_INFO,
+                       'User ' . $user->nickname . ' set notify flag to ' . $notify);
+            return true;
+        }
+    }
+}
+
+class WebChannel extends Channel
+{
+    var $out = null;
+
+    function __construct($out=null)
+    {
+        $this->out = $out;
+    }
+
+    function source()
+    {
+        return 'web';
+    }
+
+    function on($user)
+    {
+        return false;
+    }
+
+    function off($user)
+    {
+        return false;
+    }
+
+    function output($user, $text)
+    {
+        # XXX: buffer all output and send it at the end
+        # XXX: even better, redirect to appropriate page
+        #      depending on what command was run
+        $this->out->startHTML();
+        $this->out->elementStart('head');
+        $this->out->element('title', null, _('Command results'));
+        $this->out->elementEnd('head');
+        $this->out->elementStart('body');
+        $this->out->element('p', array('id' => 'command_result'), $text);
+        $this->out->elementEnd('body');
+        $this->out->endHTML();
+    }
+
+    function error($user, $text)
+    {
+        common_user_error($text);
+    }
+}
+
+class AjaxWebChannel extends WebChannel
+{
+    function output($user, $text)
+    {
+        $this->out->startHTML('text/xml;charset=utf-8');
+        $this->out->elementStart('head');
+        $this->out->element('title', null, _('Command results'));
+        $this->out->elementEnd('head');
+        $this->out->elementStart('body');
+        $this->out->element('p', array('id' => 'command_result'), $text);
+        $this->out->elementEnd('body');
+        $this->out->endHTML();
+    }
+
+    function error($user, $text)
+    {
+        $this->out->startHTML('text/xml;charset=utf-8');
+        $this->out->elementStart('head');
+        $this->out->element('title', null, _('Ajax Error'));
+        $this->out->elementEnd('head');
+        $this->out->elementStart('body');
+        $this->out->element('p', array('id' => 'error'), $text);
+        $this->out->elementEnd('body');
+        $this->out->endHTML();
+    }
+}
+
+class MailChannel extends Channel
+{
+
+    var $addr = null;
+
+    function source()
+    {
+        return 'mail';
+    }
+
+    function __construct($addr=null)
+    {
+        $this->addr = $addr;
+    }
+
+    function on($user)
+    {
+        return $this->set_notify($user, 1);
+    }
+
+    function off($user)
+    {
+        return $this->set_notify($user, 0);
+    }
+
+    function output($user, $text)
+    {
+
+        $headers['From'] = $user->incomingemail;
+        $headers['To'] = $this->addr;
+
+        $headers['Subject'] = _('Command complete');
+
+        return mail_send(array($this->addr), $headers, $text);
+    }
+
+    function error($user, $text)
+    {
+
+        $headers['From'] = $user->incomingemail;
+        $headers['To'] = $this->addr;
+
+        $headers['Subject'] = _('Command failed');
+
+        return mail_send(array($this->addr), $headers, $text);
+    }
+
+    function set_notify($user, $value)
+    {
+        $orig = clone($user);
+        $user->smsnotify = $value;
+        $result = $user->update($orig);
+        if (!$result) {
+            common_log_db_error($user, 'UPDATE', __FILE__);
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/lib/command.php b/lib/command.php
new file mode 100644 (file)
index 0000000..eacbdac
--- /dev/null
@@ -0,0 +1,419 @@
+<?php
+/*
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, Controlez-Vous, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('LACONICA')) { exit(1); }
+
+require_once(INSTALLDIR.'/classes/Channel.php');
+
+class Command
+{
+    
+    var $user = null;
+    
+    function __construct($user=null)
+    {
+        $this->user = $user;
+    }
+    
+    function execute($channel)
+    {
+        return false;
+    }
+}
+
+class UnimplementedCommand extends Command
+{
+    function execute($channel)
+    {
+        $channel->error($this->user, _("Sorry, this command is not yet implemented."));
+    }
+}
+
+class TrackingCommand extends UnimplementedCommand
+{
+}
+
+class TrackOffCommand extends UnimplementedCommand
+{
+}
+
+class TrackCommand extends UnimplementedCommand
+{
+    var $word = null;
+    function __construct($user, $word)
+    {
+        parent::__construct($user);
+        $this->word = $word;
+    }
+}
+
+class UntrackCommand extends UnimplementedCommand
+{
+    var $word = null;
+    function __construct($user, $word)
+    {
+        parent::__construct($user);
+        $this->word = $word;
+    }
+}
+
+class NudgeCommand extends UnimplementedCommand
+{
+    var $other = null;
+    function __construct($user, $other)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+}
+
+class InviteCommand extends UnimplementedCommand
+{
+    var $other = null;
+    function __construct($user, $other)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+}
+
+class StatsCommand extends Command
+{
+    function execute($channel)
+    {
+
+        $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();
+        
+        $channel->output($this->user, sprintf(_("Subscriptions: %1\$s\n".
+                                   "Subscribers: %2\$s\n".
+                                   "Notices: %3\$s"),
+                                 $subs_count,
+                                 $subbed_count,
+                                 $notice_count));
+    }
+}
+
+class FavCommand extends Command
+{
+    
+    var $other = null;
+    
+    function __construct($user, $other)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+    
+    function execute($channel)
+    {
+        
+        $recipient = 
+          common_relative_profile($this->user, common_canonical_nickname($this->other));
+        
+        if (!$recipient) {
+            $channel->error($this->user, _('No such user.'));
+            return;
+        }
+        $notice = $recipient->getCurrentNotice();
+        if (!$notice) {
+            $channel->error($this->user, _('User has no last notice'));
+            return;
+        }
+        
+        $fave = Fave::addNew($this->user, $notice);
+
+        if (!$fave) {
+            $channel->error($this->user, _('Could not create favorite.'));
+            return;
+        }
+
+        $other = User::staticGet('id', $recipient->id);
+        
+        if ($other && $other->id != $user->id) {
+            if ($other->email && $other->emailnotifyfav) {
+                mail_notify_fave($other, $this->user, $notice);
+            }
+        }
+        
+        $this->user->blowFavesCache();
+        
+        $channel->output($this->user, _('Notice marked as fave.'));
+    }
+}
+
+class WhoisCommand extends Command
+{
+    var $other = null;
+    function __construct($user, $other)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+    
+    function execute($channel)
+    {
+        $recipient = 
+          common_relative_profile($this->user, common_canonical_nickname($this->other));
+        
+        if (!$recipient) {
+            $channel->error($this->user, _('No such user.'));
+            return;
+        }
+        
+        $whois = sprintf(_("%1\$s (%2\$s)"), $recipient->nickname,
+                         $recipient->profileurl);
+        if ($recipient->fullname) {
+            $whois .= "\n" . sprintf(_('Fullname: %s'), $recipient->fullname);
+        }
+        if ($recipient->location) {
+            $whois .= "\n" . sprintf(_('Location: %s'), $recipient->location);
+        }
+        if ($recipient->homepage) {
+            $whois .= "\n" . sprintf(_('Homepage: %s'), $recipient->homepage);
+        }
+        if ($recipient->bio) {
+            $whois .= "\n" . sprintf(_('About: %s'), $recipient->bio);
+        }
+        $channel->output($this->user, $whois);
+    }
+}
+
+class MessageCommand extends Command
+{
+    var $other = null;
+    var $text = null;
+    function __construct($user, $other, $text)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+        $this->text = $text;
+    }
+    
+    function execute($channel)
+    {
+        $other = User::staticGet('nickname', common_canonical_nickname($this->other));
+        $len = mb_strlen($this->text);
+        if ($len == 0) {
+            $channel->error($this->user, _('No content!'));
+            return;
+        } else if ($len > 140) {
+            $content = common_shorten_links($content);
+            if (mb_strlen($content) > 140) {
+                $channel->error($this->user, sprintf(_('Message too long - maximum is 140 characters, you sent %d'), $len));
+                return;
+            }
+        }
+        
+        if (!$other) {
+            $channel->error($this->user, _('No such user.'));
+            return;
+        } else if (!$this->user->mutuallySubscribed($other)) {
+            $channel->error($this->user, _('You can\'t send a message to this user.'));
+            return;
+        } else if ($this->user->id == $other->id) {
+            $channel->error($this->user, _('Don\'t send a message to yourself; just say it to yourself quietly instead.'));
+            return;
+        }
+        $message = Message::saveNew($this->user->id, $other->id, $this->text, $channel->source());
+        if ($message) {
+            $channel->output($this->user, sprintf(_('Direct message to %s sent'), $this->other));
+        } else {
+            $channel->error($this->user, _('Error sending direct message.'));
+        }
+    }
+}
+
+class GetCommand extends Command
+{
+    
+    var $other = null;
+    
+    function __construct($user, $other)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+    
+    function execute($channel)
+    {
+        $target_nickname = common_canonical_nickname($this->other);
+        
+        $target =
+          common_relative_profile($this->user, $target_nickname);
+
+        if (!$target) {
+            $channel->error($this->user, _('No such user.'));
+            return;
+        }
+        $notice = $target->getCurrentNotice();
+        if (!$notice) {
+            $channel->error($this->user, _('User has no last notice'));
+            return;
+        }
+        $notice_content = $notice->content;
+        
+        $channel->output($this->user, $target_nickname . ": " . $notice_content);
+    }
+}
+
+class SubCommand extends Command
+{
+    
+    var $other = null;
+    
+    function __construct($user, $other)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+    
+    function execute($channel)
+    {
+        
+        if (!$this->other) {
+            $channel->error($this->user, _('Specify the name of the user to subscribe to'));
+            return;
+        }
+        
+        $result = subs_subscribe_user($this->user, $this->other);
+        
+        if ($result == 'true') {
+            $channel->output($this->user, sprintf(_('Subscribed to %s'), $this->other));
+        } else {
+            $channel->error($this->user, $result);
+        }
+    }
+}
+
+class UnsubCommand extends Command
+{
+
+    var $other = null;
+    
+    function __construct($user, $other)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+
+    function execute($channel)
+    {
+        if(!$this->other) {
+            $channel->error($this->user, _('Specify the name of the user to unsubscribe from'));
+            return;
+        }
+        
+        $result=subs_unsubscribe_user($this->user, $this->other);
+        
+        if ($result) {
+            $channel->output($this->user, sprintf(_('Unsubscribed from %s'), $this->other));
+        } else {
+            $channel->error($this->user, $result);
+        }
+    }
+}
+
+class OffCommand extends Command
+{
+    var $other = null;
+    function __construct($user, $other=null)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+    function execute($channel)
+    {
+        if ($other) {
+            $channel->error($this->user, _("Command not yet implemented."));
+        } else {
+            if ($channel->off($this->user)) {
+                $channel->output($this->user, _('Notification off.'));
+            } else {
+                $channel->error($this->user, _('Can\'t turn off notification.'));
+            }
+        }
+    }
+}
+
+class OnCommand extends Command
+{
+    var $other = null;
+    function __construct($user, $other=null)
+    {
+        parent::__construct($user);
+        $this->other = $other;
+    }
+    
+    function execute($channel)
+    {
+        if ($other) {
+            $channel->error($this->user, _("Command not yet implemented."));
+        } else {
+            if ($channel->on($this->user)) {
+                $channel->output($this->user, _('Notification on.'));
+            } else {
+                $channel->error($this->user, _('Can\'t turn on notification.'));
+            }
+        }
+    }
+}
+
+class HelpCommand extends Command
+{
+    function execute($channel)
+    {
+        $channel->output($this->user,
+                         _("Commands:\n".
+                           "on - turn on notifications\n".
+                           "off - turn off notifications\n".
+                           "help - show this help\n".
+                           "follow <nickname> - subscribe to user\n".
+                           "leave <nickname> - unsubscribe from user\n".
+                           "d <nickname> <text> - direct message to user\n".
+                           "get <nickname> - get last notice from user\n".
+                           "whois <nickname> - get profile info on user\n".
+                           "fav <nickname> - add user's last notice as a 'fave'\n".
+                           "stats - get your stats\n".
+                           "stop - same as 'off'\n".
+                           "quit - same as 'off'\n".
+                           "sub <nickname> - same as 'follow'\n".
+                           "unsub <nickname> - same as 'leave'\n".
+                           "last <nickname> - same as 'get'\n".
+                           "on <nickname> - not yet implemented.\n".
+                           "off <nickname> - not yet implemented.\n".                           
+                           "nudge <nickname> - not yet implemented.\n".
+                           "invite <phone number> - not yet implemented.\n".
+                           "track <word> - not yet implemented.\n".
+                           "untrack <word> - not yet implemented.\n".
+                           "track off - not yet implemented.\n".
+                           "untrack all - not yet implemented.\n".
+                           "tracks - not yet implemented.\n".
+                           "tracking - not yet implemented.\n"));
+    }
+}
diff --git a/lib/commandinterpreter.php b/lib/commandinterpreter.php
new file mode 100644 (file)
index 0000000..0679f54
--- /dev/null
@@ -0,0 +1,198 @@
+<?php
+/*
+ * Laconica - a distributed open-source microblogging tool
+ * Copyright (C) 2008, Controlez-Vous, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('LACONICA')) { exit(1); }
+
+require_once(INSTALLDIR.'/classes/Command.php');
+
+class CommandInterpreter
+{
+
+    function handle_command($user, $text)
+    {
+        # XXX: localise
+
+        $text = preg_replace('/\s+/', ' ', trim($text));
+        list($cmd, $arg) = explode(' ', $text, 2);
+
+        # We try to support all the same commands as Twitter, see
+        # http://getsatisfaction.com/twitter/topics/what_are_the_twitter_commands
+        # There are a few compatibility commands from earlier versions of
+        # Laconica
+
+        switch(strtolower($cmd)) {
+         case 'help':
+            if ($arg) {
+                return null;
+            }
+            return new HelpCommand($user);
+         case 'on':
+            if ($arg) {
+                list($other, $extra) = explode(' ', $arg, 2);
+                if ($extra) {
+                    return null;
+                } else {
+                    return new OnCommand($user, $other);
+                }
+            } else {
+                return new OnCommand($user);
+            }
+         case 'off':
+            if ($arg) {
+                list($other, $extra) = explode(' ', $arg, 2);
+                if ($extra) {
+                    return null;
+                } else {
+                    return new OffCommand($user, $other);
+                }
+            } else {
+                return new OffCommand($user);
+            }
+         case 'stop':
+         case 'quit':
+            if ($arg) {
+                return null;
+            } else {
+                return new OffCommand($user);
+            }
+         case 'follow':
+         case 'sub':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else {
+                return new SubCommand($user, $other);
+            }
+         case 'leave':
+         case 'unsub':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else {
+                return new UnsubCommand($user, $other);
+            }
+         case 'get':
+         case 'last':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else {
+                return new GetCommand($user, $other);
+            }
+         case 'd':
+         case 'dm':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if (!$extra) {
+                return null;
+            } else {
+                return new MessageCommand($user, $other, $extra);
+            }
+         case 'whois':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else {
+                return new WhoisCommand($user, $other);
+            }
+         case 'fav':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else {
+                return new FavCommand($user, $other);
+            }
+         case 'nudge':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else {
+                return new NudgeCommand($user, $other);
+            }
+         case 'stats':
+            if ($arg) {
+                return null;
+            }
+            return new StatsCommand($user);
+         case 'invite':
+            if (!$arg) {
+                return null;
+            }
+            list($other, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else {
+                return new InviteCommand($user, $other);
+            }
+         case 'track':
+            if (!$arg) {
+                return null;
+            }
+            list($word, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else if ($word == 'off') {
+                return new TrackOffCommand($user);
+            } else {
+                return new TrackCommand($user, $word);
+            }
+         case 'untrack':
+            if (!$arg) {
+                return null;
+            }
+            list($word, $extra) = explode(' ', $arg, 2);
+            if ($extra) {
+                return null;
+            } else if ($word == 'all') {
+                return new TrackOffCommand($user);
+            } else {
+                return new UntrackCommand($user, $word);
+            }
+         case 'tracks':
+         case 'tracking':
+            if ($arg) {
+                return null;
+            }
+            return new TrackingCommand($user);
+         default:
+            return false;
+        }
+    }
+}
+