Jelajahi Sumber

Implement new hook `parseMessageForCommands` for plugins to add custom commands

Dele Olajide 3 tahun lalu
induk
melakukan
c83cc69cef

+ 5 - 0
CHANGES.md

@@ -4,6 +4,11 @@
 
 
 - Updated translations: lt
 - Updated translations: lt
 - #2751: Media not rendered when Converse runs in a browser extension
 - #2751: Media not rendered when Converse runs in a browser extension
+- #2789: Implement new hook parseMessageForCommands for plugins to add custom
+
+### New hooks and events
+
+- New hook: [parseMessageForCommands](https://conversejs.org/docs/html/api/-_converse.html#event:parseMessageForCommands)
 
 
 ## 9.0.0 (2021-11-26)
 ## 9.0.0 (2021-11-26)
 
 

+ 3 - 3
src/plugins/chatview/message-form.js

@@ -162,9 +162,9 @@ export default class MessageForm extends ElementView {
         }
         }
     }
     }
 
 
-    parseMessageForCommands (text) {
+    async parseMessageForCommands (text) {
         // Wrap util so that we can override in the MUC message-form component
         // Wrap util so that we can override in the MUC message-form component
-        return parseMessageForCommands(this.model, text);
+        return await parseMessageForCommands(this.model, text);
     }
     }
 
 
     async onFormSubmitted (ev) {
     async onFormSubmitted (ev) {
@@ -194,7 +194,7 @@ export default class MessageForm extends ElementView {
         textarea.setAttribute('disabled', 'disabled');
         textarea.setAttribute('disabled', 'disabled');
         this.querySelector('converse-emoji-dropdown')?.hideMenu();
         this.querySelector('converse-emoji-dropdown')?.hideMenu();
 
 
-        const is_command = this.parseMessageForCommands(message_text);
+        const is_command = await this.parseMessageForCommands(message_text);
         const message = is_command ? null : await this.model.sendMessage({'body': message_text, spoiler_hint});
         const message = is_command ? null : await this.model.sendMessage({'body': message_text, spoiler_hint});
         if (is_command || message) {
         if (is_command || message) {
             hint_el.value = '';
             hint_el.value = '';

+ 23 - 2
src/plugins/chatview/utils.js

@@ -1,7 +1,7 @@
 import { __ } from 'i18n';
 import { __ } from 'i18n';
 import { _converse } from "@converse/headless/core";
 import { _converse } from "@converse/headless/core";
 import { html } from 'lit';
 import { html } from 'lit';
-
+import { api } from "@converse/headless/core";
 
 
 export function clearHistory (jid) {
 export function clearHistory (jid) {
     if (_converse.router.history.getFragment() === `converse/chat?jid=${jid}`) {
     if (_converse.router.history.getFragment() === `converse/chat?jid=${jid}`) {
@@ -39,9 +39,29 @@ export async function clearMessages (chat) {
 }
 }
 
 
 
 
-export function parseMessageForCommands (chat, text) {
+export async function parseMessageForCommands (chat, text) {
+    /**
+     * *Hook* which allows plugins to add more commands to a chat's textbox.
+     * Data provided is the chatbox model and the text typed - {model, text}.
+     * Check `handled` to see if the hook was already handled.
+     * @event _converse#parseMessageForCommands
+     * @example
+     *  api.listen.on('parseMessageForCommands', (data, handled) {
+     *      if (!handled) {
+     *         const command = (data.text.match(/^\/([a-zA-Z]*) ?/) || ['']).pop().toLowerCase();
+     *         // custom code comes here
+     *      }
+     *      return handled;
+     *  }
+     */
     const match = text.replace(/^\s*/, '').match(/^\/(.*)\s*$/);
     const match = text.replace(/^\s*/, '').match(/^\/(.*)\s*$/);
     if (match) {
     if (match) {
+        let handled = false;
+        handled = await api.hook('parseMessageForCommands', {model: chat, text}, handled);
+        if (handled) {
+            return true;
+        }
+
         if (match[1] === 'clear') {
         if (match[1] === 'clear') {
             clearMessages(chat);
             clearMessages(chat);
             return true;
             return true;
@@ -54,6 +74,7 @@ export function parseMessageForCommands (chat, text) {
             return true;
             return true;
         }
         }
     }
     }
+    return false;
 }
 }
 
 
 export function resetElementHeight (ev) {
 export function resetElementHeight (ev) {

+ 3 - 0
src/plugins/muc-views/message-form.js

@@ -47,6 +47,9 @@ export default class MUCMessageForm extends MessageForm {
         this.mention_auto_complete.on('suggestion-box-selectcomplete', () => (this.auto_completing = false));
         this.mention_auto_complete.on('suggestion-box-selectcomplete', () => (this.auto_completing = false));
     }
     }
 
 
+    /**
+     * @async
+     */
     parseMessageForCommands (text) {
     parseMessageForCommands (text) {
         return parseMessageForMUCCommands(this.model, text);
         return parseMessageForMUCCommands(this.model, text);
     }
     }

+ 7 - 1
src/plugins/muc-views/utils.js

@@ -298,7 +298,7 @@ export function showOccupantModal (ev, occupant) {
 }
 }
 
 
 
 
-export function parseMessageForMUCCommands (muc, text) {
+export async function parseMessageForMUCCommands (muc, text) {
     if (
     if (
         api.settings.get('muc_disable_slash_commands') &&
         api.settings.get('muc_disable_slash_commands') &&
         !Array.isArray(api.settings.get('muc_disable_slash_commands'))
         !Array.isArray(api.settings.get('muc_disable_slash_commands'))
@@ -310,6 +310,12 @@ export function parseMessageForMUCCommands (muc, text) {
     if (!command) {
     if (!command) {
         return false;
         return false;
     }
     }
+
+    const handled = await api.hook('parseMessageForCommands', {model: muc, text}, false);
+    if (handled) {
+        return true;
+    }
+
     const args = text.slice(('/' + command).length + 1).trim();
     const args = text.slice(('/' + command).length + 1).trim();
     if (!muc.getAllowedCommands().includes(command)) {
     if (!muc.getAllowedCommands().includes(command)) {
         return false;
         return false;