X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Fcommand.php;h=8080fb8bc0071de9f4a4b991d1fb7f6a524ea69b;hb=44caa3a93f452777c795006edb52ef4c5c2c4997;hp=11d40b8e156da190df5b33aa0a45f8aa36a34041;hpb=c012b278f00664470e74a0009791e8b2bca2a5e3;p=quix0rs-gnu-social.git diff --git a/lib/command.php b/lib/command.php index 11d40b8e15..8080fb8bc0 100644 --- a/lib/command.php +++ b/lib/command.php @@ -1,7 +1,7 @@ user = $user; } - function execute($channel) + /** + * Execute the command and send success or error results + * back via the given communications channel. + * + * @param Channel + */ + public function execute($channel) + { + try { + $this->handle($channel); + } catch (CommandException $e) { + $channel->error($this->user, $e->getMessage()); + } catch (Exception $e) { + common_log(LOG_ERR, "Error handling " . get_class($this) . ": " . $e->getMessage()); + $channel->error($this->user, $e->getMessage()); + } + } + + + /** + * Override this with the meat! + * + * An error to send back to the user may be sent by throwing + * a CommandException with a formatted message. + * + * @param Channel + * @throws CommandException + */ + function handle($channel) { return false; } + + /** + * Look up a notice from an argument, by poster's name to get last post + * or notice_id prefixed with #. + * + * @return Notice + * @throws CommandException + */ + function getNotice($arg) + { + $notice = null; + if (Event::handle('StartCommandGetNotice', array($this, $arg, &$notice))) { + if(substr($this->other,0,1)=='#'){ + // A specific notice_id #123 + + $notice = Notice::staticGet(substr($arg,1)); + if (!$notice) { + throw new CommandException(_('Notice with that id does not exist')); + } + } + + if (Validate::uri($this->other)) { + // A specific notice by URI lookup + $notice = Notice::staticGet('uri', $arg); + } + + if (!$notice) { + // Local or remote profile name to get their last notice. + // May throw an exception and report 'no such user' + $recipient = $this->getProfile($arg); + + $notice = $recipient->getCurrentNotice(); + if (!$notice) { + throw new CommandException(_('User has no last notice')); + } + } + } + Event::handle('EndCommandGetNotice', array($this, $arg, &$notice)); + if (!$notice) { + throw new CommandException(_('Notice with that id does not exist')); + } + return $notice; + } + + /** + * Look up a local or remote profile by nickname. + * + * @return Profile + * @throws CommandException + */ + function getProfile($arg) + { + $profile = null; + if (Event::handle('StartCommandGetProfile', array($this, $arg, &$profile))) { + $profile = + common_relative_profile($this->user, common_canonical_nickname($arg)); + } + Event::handle('EndCommandGetProfile', array($this, $arg, &$profile)); + if (!$profile) { + throw new CommandException(sprintf(_('Could not find a user with nickname %s'), $arg)); + } + return $profile; + } + + /** + * Get a local user by name + * @return User + * @throws CommandException + */ + function getUser($arg) + { + $user = null; + if (Event::handle('StartCommandGetUser', array($this, $arg, &$user))) { + $user = User::staticGet('nickname', $arg); + } + Event::handle('EndCommandGetUser', array($this, $arg, &$user)); + if (!$user){ + throw new CommandException(sprintf(_('Could not find a local user with nickname %s'), + $arg)); + } + return $user; + } + + /** + * Get a local or remote group by name. + * @return User_group + * @throws CommandException + */ + function getGroup($arg) + { + $group = null; + if (Event::handle('StartCommandGetGroup', array($this, $arg, &$group))) { + $group = User_group::getForNickname($arg, $this->user->getProfile()); + } + Event::handle('EndCommandGetGroup', array($this, $arg, &$group)); + if (!$group) { + throw new CommandException(_('No such group.')); + } + return $group; + } +} + +class CommandException extends Exception +{ } class UnimplementedCommand extends Command { - function execute($channel) + function handle($channel) { $channel->error($this->user, _("Sorry, this command is not yet implemented.")); } @@ -73,7 +205,7 @@ class UntrackCommand extends UnimplementedCommand } } -class NudgeCommand extends UnimplementedCommand +class NudgeCommand extends Command { var $other = null; function __construct($user, $other) @@ -81,6 +213,22 @@ class NudgeCommand extends UnimplementedCommand parent::__construct($user); $this->other = $other; } + + function handle($channel) + { + $recipient = $this->getUser($this->other); + if ($recipient->id == $this->user->id) { + throw new CommandException(_('It does not make a lot of sense to nudge yourself!')); + } else { + if ($recipient->email && $recipient->emailnotifynudge) { + mail_notify_nudge($this->user, $recipient); + } + // XXX: notify by IM + // XXX: notify by SMS + $channel->output($this->user, sprintf(_('Nudge sent to %s'), + $recipient->nickname)); + } + } } class InviteCommand extends UnimplementedCommand @@ -95,7 +243,7 @@ class InviteCommand extends UnimplementedCommand class StatsCommand extends Command { - function execute($channel) + function handle($channel) { $profile = $this->user->getProfile(); @@ -122,30 +270,20 @@ class FavCommand extends Command $this->other = $other; } - function execute($channel) + function handle($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); + $notice = $this->getNotice($this->other); + $fave = Fave::addNew($this->user->getProfile(), $notice); if (!$fave) { $channel->error($this->user, _('Could not create favorite.')); return; } - $other = User::staticGet('id', $recipient->id); + // @fixme favorite notification should be triggered + // at a lower level + + $other = User::staticGet('id', $notice->profile_id); if ($other && $other->id != $user->id) { if ($other->email && $other->emailnotifyfav) { @@ -159,6 +297,7 @@ class FavCommand extends Command } } + class JoinCommand extends Command { var $other = null; @@ -169,17 +308,10 @@ class JoinCommand extends Command $this->other = $other; } - function execute($channel) + function handle($channel) { - - $nickname = common_canonical_nickname($this->other); - $group = User_group::staticGet('nickname', $nickname); - $cur = $this->user; - - if (!$group) { - $channel->error($cur, _('No such group.')); - return; - } + $group = $this->getGroup($this->other); + $cur = $this->user; if ($cur->isMember($group)) { $channel->error($cur, _('You are already a member of that group')); @@ -190,18 +322,15 @@ class JoinCommand extends Command return; } - $member = new Group_member(); - - $member->group_id = $group->id; - $member->profile_id = $cur->id; - $member->created = common_sql_now(); - - $result = $member->insert(); - if (!$result) { - common_log_db_error($member, 'INSERT', __FILE__); - $channel->error($cur, sprintf(_('Could not join user %s to group %s'), - $cur->nickname, $group->nickname)); - return; + try { + if (Event::handle('StartJoinGroup', array($group, $cur))) { + Group_member::join($group->id, $cur->id); + Event::handle('EndJoinGroup', array($group, $cur)); + } + } catch (Exception $e) { + $channel->error($cur, sprintf(_('Could not join user %s to group %s'), + $cur->nickname, $group->nickname)); + return; } $channel->output($cur, sprintf(_('%s joined group %s'), @@ -220,12 +349,10 @@ class DropCommand extends Command $this->other = $other; } - function execute($channel) + function handle($channel) { - - $nickname = common_canonical_nickname($this->other); - $group = User_group::staticGet('nickname', $nickname); - $cur = $this->user; + $group = $this->getGroup($this->other); + $cur = $this->user; if (!$group) { $channel->error($cur, _('No such group.')); @@ -237,21 +364,15 @@ class DropCommand extends Command return; } - $member = new Group_member(); - - $member->group_id = $group->id; - $member->profile_id = $cur->id; - - if (!$member->find(true)) { - $channel->error($cur,_('Could not find membership record.')); - return; - } - $result = $member->delete(); - if (!$result) { - common_log_db_error($member, 'INSERT', __FILE__); - $channel->error($cur, sprintf(_('Could not remove user %s to group %s'), - $cur->nickname, $group->nickname)); - return; + try { + if (Event::handle('StartLeaveGroup', array($group, $cur))) { + Group_member::leave($group->id, $cur->id); + Event::handle('EndLeaveGroup', array($group, $cur)); + } + } catch (Exception $e) { + $channel->error($cur, sprintf(_('Could not remove user %s to group %s'), + $cur->nickname, $group->nickname)); + return; } $channel->output($cur, sprintf(_('%s left group %s'), @@ -270,15 +391,9 @@ class WhoisCommand extends Command $this->other = $other; } - function execute($channel) + function handle($channel) { - $recipient = - common_relative_profile($this->user, common_canonical_nickname($this->other)); - - if (!$recipient) { - $channel->error($this->user, _('No such user.')); - return; - } + $recipient = $this->getProfile($this->other); $whois = sprintf(_("%1\$s (%2\$s)"), $recipient->nickname, $recipient->profileurl); @@ -309,9 +424,18 @@ class MessageCommand extends Command $this->text = $text; } - function execute($channel) + function handle($channel) { - $other = User::staticGet('nickname', common_canonical_nickname($this->other)); + try { + $other = $this->getUser($this->other); + } catch (CommandException $e) { + try { + $profile = $this->getProfile($this->other); + } catch (CommandException $f) { + throw $e; + } + throw new CommandException(sprintf(_('%s is a remote profile; you can only send direct messages to users on the same server.'), $this->other)); + } $len = mb_strlen($this->text); @@ -340,6 +464,7 @@ class MessageCommand extends Command } $message = Message::saveNew($this->user->id, $other->id, $this->text, $channel->source()); if ($message) { + $message->notify(); $channel->output($this->user, sprintf(_('Direct message to %s sent'), $this->other)); } else { $channel->error($this->user, _('Error sending direct message.')); @@ -347,28 +472,99 @@ class MessageCommand extends Command } } -class GetCommand extends Command +class RepeatCommand extends Command { - var $other = null; - function __construct($user, $other) { parent::__construct($user); $this->other = $other; } - function execute($channel) + function handle($channel) { - $target_nickname = common_canonical_nickname($this->other); + $notice = $this->getNotice($this->other); - $target = - common_relative_profile($this->user, $target_nickname); + if($this->user->id == $notice->profile_id) + { + $channel->error($this->user, _('Cannot repeat your own notice')); + return; + } - if (!$target) { - $channel->error($this->user, _('No such user.')); + if ($this->user->getProfile()->hasRepeated($notice->id)) { + $channel->error($this->user, _('Already repeated that notice')); + return; + } + + $repeat = $notice->repeat($this->user->id, $channel->source); + + if ($repeat) { + + $channel->output($this->user, sprintf(_('Notice from %s repeated'), $recipient->nickname)); + } else { + $channel->error($this->user, _('Error repeating notice.')); + } + } +} + +class ReplyCommand extends Command +{ + var $other = null; + var $text = null; + function __construct($user, $other, $text) + { + parent::__construct($user); + $this->other = $other; + $this->text = $text; + } + + function handle($channel) + { + $notice = $this->getNotice($this->other); + $recipient = $notice->getProfile(); + + $len = mb_strlen($this->text); + + if ($len == 0) { + $channel->error($this->user, _('No content!')); return; } + + $this->text = common_shorten_links($this->text); + + if (Notice::contentTooLong($this->text)) { + $channel->error($this->user, sprintf(_('Notice too long - maximum is %d characters, you sent %d'), + Notice::maxContent(), mb_strlen($this->text))); + return; + } + + $notice = Notice::saveNew($this->user->id, $this->text, $channel->source(), + array('reply_to' => $notice->id)); + + if ($notice) { + $channel->output($this->user, sprintf(_('Reply to %s sent'), $recipient->nickname)); + } else { + $channel->error($this->user, _('Error saving notice.')); + } + + } +} + +class GetCommand extends Command +{ + + var $other = null; + + function __construct($user, $other) + { + parent::__construct($user); + $this->other = $other; + } + + function handle($channel) + { + $target = $this->getProfile($this->other); + $notice = $target->getCurrentNotice(); if (!$notice) { $channel->error($this->user, _('User has no last notice')); @@ -376,7 +572,7 @@ class GetCommand extends Command } $notice_content = $notice->content; - $channel->output($this->user, $target_nickname . ": " . $notice_content); + $channel->output($this->user, $target->nickname . ": " . $notice_content); } } @@ -391,7 +587,7 @@ class SubCommand extends Command $this->other = $other; } - function execute($channel) + function handle($channel) { if (!$this->other) { @@ -399,12 +595,19 @@ class SubCommand extends Command return; } - $result = subs_subscribe_user($this->user, $this->other); + $target = $this->getProfile($this->other); - if ($result == 'true') { + $remote = Remote_profile::staticGet('id', $target->id); + if ($remote) { + throw new CommandException(_("Can't subscribe to OMB profiles by command.")); + } + + try { + Subscription::start($this->user->getProfile(), + $target); $channel->output($this->user, sprintf(_('Subscribed to %s'), $this->other)); - } else { - $channel->error($this->user, $result); + } catch (Exception $e) { + $channel->error($this->user, $e->getMessage()); } } } @@ -420,19 +623,21 @@ class UnsubCommand extends Command $this->other = $other; } - function execute($channel) + function handle($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); + $target = $this->getProfile($this->other); - if ($result) { + try { + Subscription::cancel($this->user->getProfile(), + $target); $channel->output($this->user, sprintf(_('Unsubscribed from %s'), $this->other)); - } else { - $channel->error($this->user, $result); + } catch (Exception $e) { + $channel->error($this->user, $e->getMessage()); } } } @@ -445,7 +650,7 @@ class OffCommand extends Command parent::__construct($user); $this->other = $other; } - function execute($channel) + function handle($channel) { if ($other) { $channel->error($this->user, _("Command not yet implemented.")); @@ -468,7 +673,7 @@ class OnCommand extends Command $this->other = $other; } - function execute($channel) + function handle($channel) { if ($other) { $channel->error($this->user, _("Command not yet implemented.")); @@ -482,9 +687,98 @@ class OnCommand extends Command } } +class LoginCommand extends Command +{ + function handle($channel) + { + $disabled = common_config('logincommand','disabled'); + $disabled = isset($disabled) && $disabled; + if($disabled) { + $channel->error($this->user, _('Login command is disabled')); + return; + } + + try { + $login_token = Login_token::makeNew($this->user); + } catch (Exception $e) { + $channel->error($this->user, $e->getMessage()); + } + + $channel->output($this->user, + sprintf(_('This link is useable only once, and is good for only 2 minutes: %s'), + common_local_url('otp', + array('user_id' => $login_token->user_id, 'token' => $login_token->token)))); + } +} + +class SubscriptionsCommand extends Command +{ + function handle($channel) + { + $profile = $this->user->getSubscriptions(0); + $nicknames=array(); + while ($profile->fetch()) { + $nicknames[]=$profile->nickname; + } + if(count($nicknames)==0){ + $out=_('You are not subscribed to anyone.'); + }else{ + $out = ngettext('You are subscribed to this person:', + 'You are subscribed to these people:', + count($nicknames)); + $out .= ' '; + $out .= implode(', ',$nicknames); + } + $channel->output($this->user,$out); + } +} + +class SubscribersCommand extends Command +{ + function handle($channel) + { + $profile = $this->user->getSubscribers(); + $nicknames=array(); + while ($profile->fetch()) { + $nicknames[]=$profile->nickname; + } + if(count($nicknames)==0){ + $out=_('No one is subscribed to you.'); + }else{ + $out = ngettext('This person is subscribed to you:', + 'These people are subscribed to you:', + count($nicknames)); + $out .= ' '; + $out .= implode(', ',$nicknames); + } + $channel->output($this->user,$out); + } +} + +class GroupsCommand extends Command +{ + function handle($channel) + { + $group = $this->user->getGroups(); + $groups=array(); + while ($group->fetch()) { + $groups[]=$group->nickname; + } + if(count($groups)==0){ + $out=_('You are not a member of any groups.'); + }else{ + $out = ngettext('You are a member of this group:', + 'You are a member of these groups:', + count($nicknames)); + $out.=implode(', ',$groups); + } + $channel->output($this->user,$out); + } +} + class HelpCommand extends Command { - function execute($channel) + function handle($channel) { $channel->output($this->user, _("Commands:\n". @@ -492,12 +786,21 @@ class HelpCommand extends Command "off - turn off notifications\n". "help - show this help\n". "follow - subscribe to user\n". + "groups - lists the groups you have joined\n". + "subscriptions - list the people you follow\n". + "subscribers - list the people that follow you\n". "leave - unsubscribe from user\n". "d - direct message to user\n". "get - get last notice from user\n". "whois - get profile info on user\n". "fav - add user's last notice as a 'fave'\n". + "fav # - add notice with the given id as a 'fave'\n". + "repeat # - repeat a notice with a given id\n". + "repeat - repeat the last notice from user\n". + "reply # - reply to notice with a given id\n". + "reply - reply to the last notice from user\n". "join - join group\n". + "login - Get a link to login to the web interface\n". "drop - leave group\n". "stats - get your stats\n". "stop - same as 'off'\n". @@ -507,7 +810,7 @@ class HelpCommand extends Command "last - same as 'get'\n". "on - not yet implemented.\n". "off - not yet implemented.\n". - "nudge - not yet implemented.\n". + "nudge - remind a user to update.\n". "invite - not yet implemented.\n". "track - not yet implemented.\n". "untrack - not yet implemented.\n".