. /** * GNUsocial implementation of Direct Messages * * @package GNUsocial * @author Mikael Nordfeldth * @author Bruno Casteleiro * @copyright 2019 Free Software Foundation, Inc http://www.fsf.org * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later */ defined('GNUSOCIAL') || die(); // require needed abstractions first require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'messagelist.php'; require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'messagelistitem.php'; // Import plugin libs foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . '*.php') as $filename) { require_once $filename; } // Import plugin models foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'models' . DIRECTORY_SEPARATOR . '*.php') as $filename) { require_once $filename; } /** * @category Plugin * @package GNUsocial * @author Mikael Nordfeldth * @author Bruno Casteleiro * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later */ class DirectMessagePlugin extends Plugin { const PLUGIN_VERSION = '3.0.0'; public function onRouterInitialized(URLMapper $m) { // web front-end actions $m->connect( 'message/new', ['action' => 'newmessage'] ); $m->connect( 'message/new?to=:to', ['action' => 'newmessage'], ['to' => '[0-9]+'] ); $m->connect( 'message/:message', ['action' => 'showmessage'], ['message' => '[0-9]+'] ); // direct messages $m->connect( 'api/direct_messages.:format', ['action' => 'ApiDirectMessage'], ['format' => '(xml|json|rss|atom)'] ); $m->connect( 'api/direct_messages/sent.:format', [ 'action' => 'ApiDirectMessage', 'sent' => true, ], ['format' => '(xml|json|rss|atom)'] ); $m->connect( 'api/direct_messages/new.:format', ['action' => 'ApiDirectMessageNew'], ['format' => '(xml|json)'] ); return true; } /** * Are we allowed to perform a certain command over the API? * * @param Command $cmd * @param bool &$supported * @return bool hook value */ public function onCommandSupportedAPI(Command $cmd, ?bool &$supported) : bool { $supported = $supported || $cmd instanceof MessageCommand; return true; } /** * EndInterpretCommand will handle the 'd' and 'dm' commands. * * @param string $cmd Command being run * @param string $arg Rest of the message (including address) * @param User $user User sending the message * @param MessageCommand|bool &$result The resulting command object to be run. * @return bool hook value */ public function onStartInterpretCommand(string $cmd, ?string $arg, User $user, &$result) : bool { $dm_cmds = ['d', 'dm']; if ($result === false && in_array($cmd, $dm_cmds)) { if (!empty($arg)) { list($other, $extra) = CommandInterpreter::split_arg($arg); if (!empty($extra)) { $result = new MessageCommand($user, $other, $extra); } } return false; } return true; } /** * Show Message button in someone's left-side navigation menu * * @param Menu $menu * @param Profile $target * @param Profile $scoped * @return void * @throws ServerException */ public function onEndPersonalGroupNav(Menu $menu, Profile $target, Profile $scoped = null) { if ($scoped instanceof Profile && $scoped->id == $target->id && !common_config('singleuser', 'enabled')) { $menu->out->menuItem( common_local_url('inbox', ['nickname' => $target->getNickname()]), // TRANS: Menu item in personal group navigation menu. _m('MENU', 'Messages'), // TRANS: Menu item title in personal group navigation menu. _('Your incoming messages'), $scoped->id === $target->id && $menu->actionName =='inbox' ); } } /** * Show Message button in someone's profile page * * @param HTMLOutputter $out * @param Profile $profile * @return bool hook flag */ public function onEndProfilePageActionsElements(HTMLOutputter $out, Profile $profile) : bool { $scoped = Profile::current(); if (!$scoped instanceof Profile || $scoped->getID() === $profile->getID()) { return true; } if (!$profile->isLocal() && Event::handle('DirectMessageProfilePageActions', [$profile])) { // nothing to do if remote profile and no one to validate it return true; } if (!$profile->hasBlocked($scoped)) { $out->elementStart('li', 'entity_send-a-message'); $out->element( 'a', ['href' => common_local_url('newmessage', ['to' => $profile->getID()]), // TRANS: Link title for link on user profile. 'title' => _('Send a direct message to this user.')], // TRANS: Link text for link on user profile. _m('BUTTON', 'Message') ); $out->elementEnd('li'); } return true; } /** * Notice table is used to store private messages in a newer version of the plugin, * this ensures we migrate entries from the old message table. * * @return bool hook flag */ public function onEndUpgrade() : bool { try { $schema = Schema::get(); $schema->getTableDef('message'); } catch (SchemaTableMissingException $e) { return true; } $message = new Message(); $message->selectAdd(); // clears it $message->selectAdd('id'); $message->orderBy('created, id'); if ($message->find()) { while ($message->fetch()) { $msg = Message::getKV('id', $message->id); $act = $msg->asActivity(); Notice::saveActivity( $act, $msg->getFrom(), [ 'source' => 'web', 'scope' => NOTICE::MESSAGE_SCOPE, ] ); } } $message->free(); $message = null; $schema->dropTable('message'); return true; } public function onPluginVersion(array &$versions): bool { $versions[] = [ 'name' => 'Direct Message', 'version' => self::PLUGIN_VERSION, 'author' => 'Mikael Nordfeldth, Bruno Casteleiro', 'homepage' => 'https://gnusocial.rocks/', 'rawdescription' => // TRANS: Plugin description. _m('Direct Message to other local users.') ]; return true; } }