Send a private group message with a d command

This commit is contained in:
Evan Prodromou 2011-02-04 15:51:59 -05:00
parent d7b2b141be
commit 842bc5708e
4 changed files with 302 additions and 1 deletions

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
@ -290,6 +298,45 @@ 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',

View File

@ -0,0 +1,85 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Command object for messages to groups
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Command
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Command object for messages to groups
*
* @category General
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class 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;
}
}