DirectMessagePlugin.php 8.1 KB

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