Rocket.Chat Canned Responses App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
8.6 KiB

5 years ago
  1. //
  2. // Copyright (c) 2019, Mr. Gecko's Media (James Coleman)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // 1. Redistributions of source code must retain the above copyright notice, this
  9. // list of conditions and the following disclaimer.
  10. //
  11. // 2. Redistributions in binary form must reproduce the above copyright notice,
  12. // this list of conditions and the following disclaimer in the documentation
  13. // and/or other materials provided with the distribution.
  14. //
  15. // 3. Neither the name of the copyright holder nor the names of its contributors
  16. // may be used to endorse or promote products derived from this software without
  17. // specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  23. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  25. // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  26. // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. // POSSIBILITY OF SUCH DAMAGE.
  29. //
  30. import { ISlashCommand, ISlashCommandPreview, ISlashCommandPreviewItem, SlashCommandContext, SlashCommandPreviewItemType } from '@rocket.chat/apps-engine/definition/slashcommands';
  31. import { IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors';
  32. import { App } from '@rocket.chat/apps-engine/definition/App';
  33. export class CannedResponsesSlashCommand implements ISlashCommand {
  34. public command = 'can';
  35. public i18nParamsExample = 'can_command_params_example';
  36. public i18nDescription = 'can_command_description';
  37. public providesPreview = true;
  38. constructor(private readonly app: App) { }
  39. public async executor(context: SlashCommandContext, read: IRead, modify: IModify, http: IHttp, persis: IPersistence): Promise<void> {
  40. const settingsReader = read.getEnvironmentReader().getSettings();
  41. const apiURL = await settingsReader.getValueById('canned_responses_api_url');
  42. const command = context.getArguments();
  43. if (command.length === 0 || command[0] === 'help') {
  44. return this.processHelpCommand(context, read, modify);
  45. }
  46. if (command[0] === 'list') {
  47. return this.processListCommand(context, read, modify, http);
  48. }
  49. const message = await modify.getCreator().startMessage();
  50. const sender = await read.getUserReader().getByUsername(context.getSender().username);
  51. const room = await read.getRoomReader().getById(context.getRoom().id);
  52. const roomEph = context.getRoom();
  53. if (!room) {
  54. throw Error('No room is configured for the message');
  55. }
  56. message.setRoom(room);
  57. message.setSender(sender);
  58. const key = command.join(' ');
  59. try {
  60. const result = await http.get(`${apiURL}response/get?key=${key}`);
  61. if (result.data.type === 'success') {
  62. const response = result.data.results[0];
  63. if (!response) {
  64. throw new Error('No response found.');
  65. }
  66. message.setText(response.message);
  67. modify.getCreator().finish(message);
  68. } else {
  69. throw new Error('Could not get a response.');
  70. }
  71. } catch (error) {
  72. const rocketSender = await read.getUserReader().getById('rocket.cat');
  73. message.setSender(rocketSender);
  74. message.setRoom(roomEph);
  75. message.setText(error.message);
  76. modify.getNotifier().notifyRoom(roomEph, message.getMessage());
  77. }
  78. }
  79. public async previewer(context: SlashCommandContext, read: IRead, modify: IModify, http: IHttp, persis: IPersistence): Promise<ISlashCommandPreview> {
  80. const settingsReader = read.getEnvironmentReader().getSettings();
  81. const apiURL = await settingsReader.getValueById('canned_responses_api_url');
  82. const command = context.getArguments();
  83. if (command[0] === 'help') {
  84. return {
  85. i18nTitle: 'can_command_preview',
  86. items: [{
  87. id: 'help',
  88. type: SlashCommandPreviewItemType.TEXT,
  89. value: 'Print help.',
  90. }],
  91. };
  92. }
  93. if (command[0] === 'list') {
  94. return {
  95. i18nTitle: 'can_command_preview',
  96. items: [{
  97. id: 'list',
  98. type: SlashCommandPreviewItemType.TEXT,
  99. value: 'List all keys.',
  100. }],
  101. };
  102. }
  103. const key = command.join(' ');
  104. try {
  105. const result = await http.get(`${apiURL}response/find?key=${key}`);
  106. if (result.data.type === 'success') {
  107. return {
  108. i18nTitle: 'can_command_preview',
  109. items: result.data.results.map((response) => {
  110. return {
  111. id: response.docid,
  112. type: SlashCommandPreviewItemType.TEXT,
  113. value: response.message,
  114. };
  115. }),
  116. };
  117. } else {
  118. throw new Error('Could not get a response.');
  119. }
  120. } catch (error) {
  121. console.log(error.message);
  122. }
  123. return {
  124. i18nTitle: 'can_command_preview',
  125. items: [],
  126. };
  127. }
  128. // tslint:disable-next-line:max-line-length
  129. public async executePreviewItem(item: ISlashCommandPreviewItem, context: SlashCommandContext, read: IRead, modify: IModify, http: IHttp, persis: IPersistence): Promise<void> {
  130. if (item.id === 'help') {
  131. return this.processHelpCommand(context, read, modify);
  132. }
  133. if (item.id === 'list') {
  134. return this.processListCommand(context, read, modify, http);
  135. }
  136. const message = await modify.getCreator().startMessage();
  137. const sender = await read.getUserReader().getByUsername(context.getSender().username);
  138. const room = await read.getRoomReader().getById(context.getRoom().id);
  139. if (!room) {
  140. throw Error('No room is configured for the message');
  141. }
  142. message.setRoom(room);
  143. message.setSender(sender);
  144. message.setText(item.value);
  145. modify.getCreator().finish(message);
  146. }
  147. private async processHelpCommand(context: SlashCommandContext, read: IRead, modify: IModify): Promise<void> {
  148. const message = await modify.getCreator().startMessage();
  149. const sender = await read.getUserReader().getById('rocket.cat');
  150. const roomEph = context.getRoom();
  151. message.setSender(sender);
  152. message.setRoom(roomEph);
  153. const text =
  154. `These are the commands I can understand:
  155. \`/can help\` Get this help.
  156. \`/can list\` List all available keys.
  157. \`/can key\` Provide a canned response.`;
  158. message.setText(text);
  159. modify.getNotifier().notifyRoom(roomEph, message.getMessage());
  160. }
  161. private async processListCommand(context: SlashCommandContext, read: IRead, modify: IModify, http: IHttp): Promise<void> {
  162. const settingsReader = read.getEnvironmentReader().getSettings();
  163. const apiURL = await settingsReader.getValueById('canned_responses_api_url');
  164. const message = await modify.getCreator().startMessage();
  165. const sender = await read.getUserReader().getById('rocket.cat');
  166. const roomEph = context.getRoom();
  167. message.setSender(sender);
  168. message.setRoom(roomEph);
  169. let text = 'These are the keys available:\n';
  170. const result = await http.get(`${apiURL}response/get-all`);
  171. if (result.data.type === 'success') {
  172. let count = 0;
  173. result.data.results.forEach((response) => {
  174. if (count !== 0) {
  175. text += ', ';
  176. }
  177. text += response.key;
  178. count++;
  179. });
  180. }
  181. message.setText(text);
  182. modify.getNotifier().notifyRoom(roomEph, message.getMessage());
  183. }
  184. }