From 842bc5708e4aed14d8e10a559234bd5fdce9d2a8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 4 Feb 2011 15:51:59 -0500 Subject: [PATCH] Send a private group message with a d command --- plugins/PrivateGroup/Group_message.php | 94 +++++++++++++++++++ .../PrivateGroup/Group_message_profile.php | 75 +++++++++++++++ plugins/PrivateGroup/PrivateGroupPlugin.php | 49 +++++++++- plugins/PrivateGroup/groupmessagecommand.php | 85 +++++++++++++++++ 4 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 plugins/PrivateGroup/groupmessagecommand.php diff --git a/plugins/PrivateGroup/Group_message.php b/plugins/PrivateGroup/Group_message.php index 27f4cff0ed..b3d34cf287 100644 --- a/plugins/PrivateGroup/Group_message.php +++ b/plugins/PrivateGroup/Group_message.php @@ -118,4 +118,98 @@ class Group_message extends Memcached_DataObject { return array('id' => 'K', 'uri' => 'U'); } + + static function send($user, $group, $text) + { + if (!$user->hasRight(Right::NEWMESSAGE)) { + // XXX: maybe break this out into a separate right + throw new Exception(sprintf(_('User %s not allowed to send private messages.'), + $user->nickname)); + } + + $gps = Group_privacy_settings::staticGet('group_id', $group->id); + + if (empty($gps)) { + // make a fake one with defaults + $gps = new Group_privacy_settings(); + $gps->allow_privacy = Group_privacy_settings::SOMETIMES; + $gps->allow_sender = Group_privacy_settings::MEMBER; + } + + if ($gps->allow_privacy == Group_privacy_settings::NEVER) { + throw new Exception(sprintf(_('Group %s does not allow private messages.'), + $group->nickname)); + } + + switch ($gps->allow_sender) { + case Group_privacy_settings::EVERYONE: + $profile = $user->getProfile(); + if (Group_block::isBlocked($group, $profile)) { + throw new Exception(sprintf(_('User %s is blocked from group %s.'), + $user->nickname, + $group->nickname)); + } + break; + case Group_privacy_settings::MEMBER: + if (!$user->isMember($group)) { + throw new Exception(sprintf(_('User %s is not a member of group %s.'), + $user->nickname, + $group->nickname)); + } + break; + case Group_privacy_settings::ADMIN: + if (!$user->isAdmin($group)) { + throw new Exception(sprintf(_('User %s is not an administrator of group %s.'), + $user->nickname, + $group->nickname)); + } + break; + default: + throw new Exception(sprintf(_('Unknown privacy settings for group %s.'), + $group->nickname)); + } + + $text = $user->shortenLinks($text); + + // We use the same limits as for 'regular' private messages. + + if (Message::contentTooLong($text)) { + throw new Exception(sprintf(_m('That\'s too long. Maximum message size is %d character.', + 'That\'s too long. Maximum message size is %d characters.', + Message::maxContent()), + Message::maxContent())); + } + + // Valid! Let's do this thing! + + $gm = new Group_message(); + + $gm->id = UUID::gen(); + $gm->uri = common_local_url('showgroupmessage', array('id' => $gm->id)); + $gm->from_profile = $user->id; + $gm->to_group = $group->id; + $gm->content = $text; // XXX: is this cool?! + $gm->rendered = common_render_text($text); + $gm->url = $gm->uri; + $gm->created = common_sql_now(); + + // This throws a conniption if there's a problem + + $gm->insert(); + + $gm->distribute(); + + return $gm; + } + + function distribute() + { + $group = User_group::staticGet('id', $this->to_group); + + $member = $group->getMembers(); + + while ($member->fetch()) { + Group_message_profile::send($this, $member); + } + } } diff --git a/plugins/PrivateGroup/Group_message_profile.php b/plugins/PrivateGroup/Group_message_profile.php index b32341ca77..fc1ff1bceb 100644 --- a/plugins/PrivateGroup/Group_message_profile.php +++ b/plugins/PrivateGroup/Group_message_profile.php @@ -108,4 +108,79 @@ class Group_message_profile extends Memcached_DataObject { return array('to_profile' => 'K', 'group_message_id' => 'K'); } + + /** + * No sequence keys in this table. + */ + function sequenceKey() + { + return array(false, false, false); + } + + function send($gm, $profile) + { + $gmp = new Group_message_profile(); + + $gmp->group_message_id = $gm->id; + $gmp->to_profile = $profile->id; + $gmp->created = common_sql_now(); + + $gmp->insert(); + + $gmp->notify(); + + return $gmp; + } + + function notify() + { + // XXX: add more here + $this->notifyByMail(); + } + + function notifyByMail() + { + $to = User::staticGet('id', $this->to_profile); + + if (empty($to) || is_null($to->email) || !$to->emailnotifymsg) { + return true; + } + + $gm = Group_message::staticGet('id', $this->group_message_id); + + $from_profile = Profile::staticGet('id', $gm->from_profile); + + common_switch_locale($to->language); + + // TRANS: Subject for direct-message notification email. + // TRANS: %s is the sending user's nickname. + $subject = sprintf(_('New private message from %s'), $from->nickname); + + $from_profile = $from->getProfile(); + + // TRANS: Body for direct-message notification email. + // TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname, + // TRANS: %3$s is the message content, %4$s a URL to the message, + // TRANS: %5$s is the StatusNet sitename. + $body = sprintf(_("%1\$s (%2\$s) sent you a private message:\n\n". + "------------------------------------------------------\n". + "%3\$s\n". + "------------------------------------------------------\n\n". + "You can reply to their message here:\n\n". + "%4\$s\n\n". + "Don't reply to this email; it won't get to them.\n\n". + "With kind regards,\n". + "%5\$s\n"), + $from_profile->getBestName(), + $from->nickname, + $this->content, + common_local_url('newmessage', array('to' => $from->id)), + common_config('site', 'name')); + + $headers = _mail_prepare_headers('message', $to->nickname, $from->nickname); + + common_switch_locale(); + + return mail_to_user($to, $subject, $body, $headers); + } } diff --git a/plugins/PrivateGroup/PrivateGroupPlugin.php b/plugins/PrivateGroup/PrivateGroupPlugin.php index 67e1cfb65e..4d8f2b370b 100644 --- a/plugins/PrivateGroup/PrivateGroupPlugin.php +++ b/plugins/PrivateGroup/PrivateGroupPlugin.php @@ -144,6 +144,7 @@ class PrivateGroupPlugin extends Plugin switch ($cls) { case 'GroupinboxAction': + case 'ShowgroupmessageAction': include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; case 'Group_privacy_settings': @@ -151,6 +152,9 @@ class PrivateGroupPlugin extends Plugin case 'Group_message_profile': include_once $dir . '/'.$cls.'.php'; return false; + case 'GroupMessageCommand': + include_once $dir . '/'.strtolower($cls).'.php'; + return false; default: return true; } @@ -170,6 +174,10 @@ class PrivateGroupPlugin extends Plugin array('action' => 'groupinbox'), array('nickname' => Nickname::DISPLAY_FMT)); + $m->connect('group/message/:id', + array('action' => 'showgroupmessage'), + array('id' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')); + return true; } @@ -289,7 +297,46 @@ class PrivateGroupPlugin extends Plugin return true; } - + + /** + * Overload 'd' command to send private messages to groups. + * + * 'd !group word word word' will send the private message + * 'word word word' to the group 'group'. + * + * @param string $cmd Command being run + * @param string $arg Rest of the message (including address) + * @param User $user User sending the message + * @param Command &$result The resulting command object to be run. + * + * @return boolean hook value + */ + function onStartIntepretCommand($cmd, $arg, $user, &$result) + { + if ($cmd == 'd' || $cmd == 'dm') { + + $this->debug('Got a d command'); + + // Break off the first word as the address + + $pieces = explode(' ', $arg, 2); + + if (count($pieces) == 1) { + $pieces[] = null; + } + + list($addr, $msg) = $pieces; + + if (!empty($addr) && $addr[0] == '!') { + $result = new GroupMessageCommand($user, substr($addr, 1), $msg); + Event::handle('EndInterpretCommand', array($cmd, $arg, $user, $result)); + return false; + } + } + + return true; + } + function onPluginVersion(&$versions) { $versions[] = array('name' => 'PrivateGroup', diff --git a/plugins/PrivateGroup/groupmessagecommand.php b/plugins/PrivateGroup/groupmessagecommand.php new file mode 100644 index 0000000000..19136f1318 --- /dev/null +++ b/plugins/PrivateGroup/groupmessagecommand.php @@ -0,0 +1,85 @@ +. + * + * @category Command + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Command object for messages to groups + * + * @category General + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class GroupMessageCommand extends Command +{ + /** User sending the message. */ + var $user; + /** Nickname of the group they're sending to. */ + var $nickname; + /** Text of the message. */ + var $text; + + /** + * Constructor + * + * @param User $user User sending the message + * @param string $nickname Nickname of the group + * @param string $text Text of message + */ + + function __construct($user, $nickname, $text) + { + $this->user = $user; + $this->nickname = $nickname; + $this->text = $text; + } + + function handle($channel) + { + // Throws a command exception if group not found + $group = $this->getGroup($this->nickname); + + $gm = Group_message::send($this->user, $group, $this->text); + + $channel->output($this->user, + sprintf(_('Direct message to group %s sent.'), + $group->nickname)); + + return true; + } +}