DirectMessagePlugin.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. // This file is part of GNU social - https://www.gnu.org/software/social
  3. //
  4. // GNU social is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // GNU social is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * GNUsocial implementation of Direct Messages
  18. *
  19. * @package GNUsocial
  20. * @author Mikael Nordfeldth <mmn@hethane.se>
  21. * @author Bruno Casteleiro <brunoccast@fc.up.pt>
  22. * @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
  23. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  24. */
  25. defined('GNUSOCIAL') || die();
  26. // require needed abstractions first
  27. require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'messagelist.php';
  28. require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'messagelistitem.php';
  29. // Import plugin libs
  30. foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . '*.php') as $filename) {
  31. require_once $filename;
  32. }
  33. // Import plugin models
  34. foreach (glob(__DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'models' . DIRECTORY_SEPARATOR . '*.php') as $filename) {
  35. require_once $filename;
  36. }
  37. /**
  38. * @category Plugin
  39. * @package GNUsocial
  40. * @author Mikael Nordfeldth <mmn@hethane.se>
  41. * @author Bruno Casteleiro <brunoccast@fc.up.pt>
  42. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  43. */
  44. class DirectMessagePlugin extends Plugin
  45. {
  46. const PLUGIN_VERSION = '3.0.0';
  47. public function onRouterInitialized(URLMapper $m)
  48. {
  49. // web front-end actions
  50. $m->connect(
  51. 'message/new',
  52. ['action' => 'newmessage']
  53. );
  54. $m->connect(
  55. 'message/new?to=:to',
  56. ['action' => 'newmessage'],
  57. ['to' => '[0-9]+']
  58. );
  59. $m->connect(
  60. 'message/:message',
  61. ['action' => 'showmessage'],
  62. ['message' => '[0-9]+']
  63. );
  64. // direct messages
  65. $m->connect(
  66. 'api/direct_messages.:format',
  67. ['action' => 'ApiDirectMessage'],
  68. ['format' => '(xml|json|rss|atom)']
  69. );
  70. $m->connect(
  71. 'api/direct_messages/sent.:format',
  72. ['action' => 'ApiDirectMessage',
  73. 'sent' => true],
  74. ['format' => '(xml|json|rss|atom)']
  75. );
  76. $m->connect(
  77. 'api/direct_messages/new.:format',
  78. ['action' => 'ApiDirectMessageNew'],
  79. ['format' => '(xml|json)']
  80. );
  81. return true;
  82. }
  83. /**
  84. * Are we allowed to perform a certain command over the API?
  85. *
  86. * @param Command $cmd
  87. * @param bool &$supported
  88. * @return bool hook value
  89. */
  90. public function onCommandSupportedAPI(Command $cmd, ?bool &$supported) : bool
  91. {
  92. $supported = $supported || $cmd instanceof MessageCommand;
  93. return true;
  94. }
  95. /**
  96. * EndInterpretCommand will handle the 'd' and 'dm' commands.
  97. *
  98. * @param string $cmd Command being run
  99. * @param string $arg Rest of the message (including address)
  100. * @param User $user User sending the message
  101. * @param MessageCommand|bool &$result The resulting command object to be run.
  102. * @return bool hook value
  103. */
  104. public function onStartInterpretCommand(string $cmd, ?string $arg, User $user, &$result) : bool
  105. {
  106. $dm_cmds = ['d', 'dm'];
  107. if ($result === false && in_array($cmd, $dm_cmds)) {
  108. if (!empty($arg)) {
  109. list($other, $extra) = CommandInterpreter::split_arg($arg);
  110. if (!empty($extra)) {
  111. $result = new MessageCommand($user, $other, $extra);
  112. }
  113. }
  114. return false;
  115. }
  116. return true;
  117. }
  118. /**
  119. * Show Message button in someone's left-side navigation menu
  120. *
  121. * @param Menu $menu
  122. * @param Profile $target
  123. * @param Profile $scoped
  124. * @return void
  125. * @throws ServerException
  126. */
  127. public function onEndPersonalGroupNav(Menu $menu, Profile $target, Profile $scoped = null)
  128. {
  129. if ($scoped instanceof Profile && $scoped->id == $target->id
  130. && !common_config('singleuser', 'enabled')) {
  131. $menu->out->menuItem(
  132. common_local_url('inbox', ['nickname' => $target->getNickname()]),
  133. // TRANS: Menu item in personal group navigation menu.
  134. _m('MENU', 'Messages'),
  135. // TRANS: Menu item title in personal group navigation menu.
  136. _('Your incoming messages'),
  137. $scoped->id === $target->id && $menu->actionName =='inbox'
  138. );
  139. }
  140. }
  141. /**
  142. * Show Message button in someone's profile page
  143. *
  144. * @param HTMLOutputter $out
  145. * @param Profile $profile
  146. * @return bool hook flag
  147. */
  148. public function onEndProfilePageActionsElements(HTMLOutputter $out, Profile $profile) : bool
  149. {
  150. $scoped = Profile::current();
  151. if (!$scoped instanceof Profile || $scoped->getID() === $profile->getID()) {
  152. return true;
  153. }
  154. if (!$profile->isLocal() && Event::handle('DirectMessageProfilePageActions', [$profile])) {
  155. // nothing to do if remote profile and no one to validate it
  156. return true;
  157. }
  158. if (!$profile->hasBlocked($scoped)) {
  159. $out->elementStart('li', 'entity_send-a-message');
  160. $out->element(
  161. 'a',
  162. ['href' => common_local_url('newmessage', ['to' => $profile->getID()]),
  163. // TRANS: Link title for link on user profile.
  164. 'title' => _('Send a direct message to this user.')],
  165. // TRANS: Link text for link on user profile.
  166. _m('BUTTON', 'Message')
  167. );
  168. $out->elementEnd('li');
  169. }
  170. return true;
  171. }
  172. /**
  173. * Notice table is used to store private messages in a newer version of the plugin,
  174. * this ensures we migrate entries from the old message table.
  175. *
  176. * @return bool hook flag
  177. */
  178. public function onEndUpgrade() : bool
  179. {
  180. try {
  181. $schema = Schema::get();
  182. $schema->getTableDef('message');
  183. } catch (SchemaTableMissingException $e) {
  184. return true;
  185. }
  186. $message = new Message();
  187. $message->selectAdd(); // clears it
  188. $message->selectAdd('id');
  189. $message->orderBy('created ASC');
  190. if ($message->find()) {
  191. while ($message->fetch()) {
  192. $msg = Message::getKV('id', $message->id);
  193. $act = $msg->asActivity();
  194. Notice::saveActivity(
  195. $act,
  196. $msg->getFrom(),
  197. ['source' => 'web',
  198. 'scope' => NOTICE::MESSAGE_SCOPE]
  199. );
  200. }
  201. }
  202. $message->free();
  203. $message = null;
  204. $schema->dropTable('message');
  205. return true;
  206. }
  207. public function onPluginVersion(array &$versions): bool
  208. {
  209. $versions[] = [
  210. 'name' => 'Direct Message',
  211. 'version' => self::PLUGIN_VERSION,
  212. 'author' => 'Mikael Nordfeldth, Bruno Casteleiro',
  213. 'homepage' => 'https://gnu.social/',
  214. 'rawdescription' =>
  215. // TRANS: Plugin description.
  216. _m('Direct Message to other local users.')
  217. ];
  218. return true;
  219. }
  220. }