Finished autocomplete & context menu interactions

Autocomplete & context menu interactions have been fully implemented in the Open Discord framework. They have not yet been implemented in the Open Ticket bot code though.
This commit is contained in:
DJj123dj
2025-06-24 08:43:57 +02:00
parent 8116d4d8dd
commit 6df3498cb5
7 changed files with 432 additions and 7 deletions
+1 -1
View File
@@ -160,7 +160,7 @@ export class ODTextCommandManager_Default extends ODTextCommandManager {
* It's used to generate typescript declarations for this class.
*/
export interface ODContextMenuManagerIds_Default {
"opendiscord:test-menu":ODContextMenu
//"opendiscord:test-menu":ODContextMenu
}
/**## ODContextMenuManager_Default `default_class`
+5 -1
View File
@@ -21,7 +21,7 @@ import { ODLanguageManager_Default } from "./language"
import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./checker"
import { ODClientManager_Default, ODContextMenuManager_Default, ODSlashCommandManager_Default, ODTextCommandManager_Default } from "./client"
import { ODBuilderManager_Default, ODButtonManager_Default, ODDropdownManager_Default, ODEmbedManager_Default, ODFileManager_Default, ODMessageManager_Default, ODModalManager_Default } from "./builder"
import { ODButtonResponderManager_Default, ODCommandResponderManager_Default, ODDropdownResponderManager_Default, ODModalResponderManager_Default, ODResponderManager_Default } from "./responder"
import { ODAutocompleteResponderManager_Default, ODButtonResponderManager_Default, ODCommandResponderManager_Default, ODContextMenuResponderManager_Default, ODDropdownResponderManager_Default, ODModalResponderManager_Default, ODResponderManager_Default } from "./responder"
import { ODActionManager_Default } from "./action"
import { ODPermissionManager_Default } from "./permission"
import { ODHelpMenuManager_Default } from "./helpmenu"
@@ -255,6 +255,10 @@ export interface ODEventIds_Default {
"afterDropdownRespondersLoaded": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onModalResponderLoad": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterModalRespondersLoaded": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onContextMenuResponderLoad": ODEvent_Default<(menus:ODContextMenuResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterContextMenuRespondersLoaded": ODEvent_Default<(menus:ODContextMenuResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onAutocompleteResponderLoad": ODEvent_Default<(autocomplete:ODAutocompleteResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterAutocompleteRespondersLoaded": ODEvent_Default<(autocomplete:ODAutocompleteResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
//plugin loading before finalizations
"onPluginBeforeFinalizationLoad": ODEvent_Default<() => ODPromiseVoid>,
+97 -1
View File
@@ -2,7 +2,7 @@
//DEFAULT RESPONDER MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODButtonResponder, ODButtonResponderInstance, ODButtonResponderManager, ODCommandResponder, ODCommandResponderInstance, ODCommandResponderManager, ODDropdownResponder, ODDropdownResponderInstance, ODDropdownResponderManager, ODModalResponder, ODModalResponderInstance, ODModalResponderManager, ODResponderManager } from "../modules/responder"
import { ODAutocompleteResponder, ODAutocompleteResponderInstance, ODAutocompleteResponderManager, ODButtonResponder, ODButtonResponderInstance, ODButtonResponderManager, ODCommandResponder, ODCommandResponderInstance, ODCommandResponderManager, ODContextMenuResponder, ODContextMenuResponderInstance, ODContextMenuResponderManager, ODDropdownResponder, ODDropdownResponderInstance, ODDropdownResponderManager, ODModalResponder, ODModalResponderInstance, ODModalResponderManager, ODResponderManager } from "../modules/responder"
import { ODWorkerManager_Default } from "./worker"
/**## ODResponderManager_Default `default_class`
@@ -16,6 +16,8 @@ export class ODResponderManager_Default extends ODResponderManager {
declare buttons: ODButtonResponderManager_Default
declare dropdowns: ODDropdownResponderManager_Default
declare modals: ODModalResponderManager_Default
declare contextMenus: ODContextMenuResponderManager_Default
declare autocomplete: ODAutocompleteResponderManager_Default
}
/**## ODCommandResponderManagerIds_Default `interface`
@@ -252,4 +254,98 @@ export class ODModalResponderManager_Default extends ODModalResponderManager {
*/
export class ODModalResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODModalResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODModalResponderInstance,Source,Params,WorkerIds>
}
/**## ODContextMenuResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODContextMenuResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODContextMenuResponderManagerIds_Default {
//"opendiscord:example":{source:"context-menu",params:{},workers:"opendiscord:example"},
}
/**## ODContextMenuResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODContextMenuResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.contextMenus`!
*/
export class ODContextMenuResponderManager_Default extends ODContextMenuResponderManager {
get<ModalResponderId extends keyof ODContextMenuResponderManagerIds_Default>(id:ModalResponderId): ODContextMenuResponder_Default<ODContextMenuResponderManagerIds_Default[ModalResponderId]["source"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["params"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["workers"]>
get(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null
get(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null {
return super.get(id)
}
remove<ModalResponderId extends keyof ODContextMenuResponderManagerIds_Default>(id:ModalResponderId): ODContextMenuResponder_Default<ODContextMenuResponderManagerIds_Default[ModalResponderId]["source"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["params"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["workers"]>
remove(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null
remove(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null {
return super.remove(id)
}
exists(id:keyof ODContextMenuResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODContextMenuResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODContextMenuResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODContextMenuResponder`'s!
*/
export class ODContextMenuResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODContextMenuResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODContextMenuResponderInstance,Source,Params,WorkerIds>
}
/**## ODAutocompleteResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODAutocompleteResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODAutocompleteResponderManagerIds_Default {
//"opendiscord:example":{source:"autocomplete",params:{},workers:"opendiscord:example"},
}
/**## ODAutocompleteResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODAutocompleteResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.autocomplete`!
*/
export class ODAutocompleteResponderManager_Default extends ODAutocompleteResponderManager {
get<ModalResponderId extends keyof ODAutocompleteResponderManagerIds_Default>(id:ModalResponderId): ODAutocompleteResponder_Default<ODAutocompleteResponderManagerIds_Default[ModalResponderId]["source"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["params"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["workers"]>
get(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null
get(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null {
return super.get(id)
}
remove<ModalResponderId extends keyof ODAutocompleteResponderManagerIds_Default>(id:ModalResponderId): ODAutocompleteResponder_Default<ODAutocompleteResponderManagerIds_Default[ModalResponderId]["source"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["params"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["workers"]>
remove(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null
remove(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null {
return super.remove(id)
}
exists(id:keyof ODAutocompleteResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODAutocompleteResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODAutocompleteResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODAutocompleteResponder`'s!
*/
export class ODAutocompleteResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODAutocompleteResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODAutocompleteResponderInstance,Source,Params,WorkerIds>
}
+6
View File
@@ -140,6 +140,10 @@ export interface ODDefaults {
dropdownRespondersLoading:boolean,
/**Load the default Open Ticket modal responders. */
modalRespondersLoading:boolean,
/**Load the default Open Ticket context menu responders. */
contextMenuRespondersLoading:boolean,
/**Load the default Open Ticket autocomplete responders. */
autocompleteRespondersLoading:boolean,
/**Set the time (in ms) before Open Ticket sends an error message when no reply is sent in a responder. */
responderTimeoutMs:number,
@@ -311,6 +315,8 @@ export class ODDefaultsManager {
buttonRespondersLoading:true,
dropdownRespondersLoading:true,
modalRespondersLoading:true,
contextMenuRespondersLoading:true,
autocompleteRespondersLoading:true,
responderTimeoutMs:2500,
actionsLoading:true,
+302 -3
View File
@@ -5,7 +5,7 @@ import { ODId, ODManager, ODValidId, ODSystemError, ODManagerData } from "./base
import * as discord from "discord.js"
import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker"
import { ODDebugger } from "./console"
import { ODClientManager, ODSlashCommand, ODTextCommand, ODTextCommandInteractionOption } from "./client"
import { ODClientManager, ODContextMenu, ODSlashCommand, ODTextCommand, ODTextCommandInteractionOption } from "./client"
import { ODDropdownData, ODMessageBuildResult, ODMessageBuildSentResult, ODModalBuildResult } from "./builder"
/**## ODResponderImplementation `class`
@@ -36,7 +36,7 @@ export class ODResponderImplementation<Instance,Source extends string,Params> ex
/**## ODResponderTimeoutErrorCallback `type`
* This is the callback for the responder timeout function. It will be executed when something went wrong or the action takes too much time.
*/
export type ODResponderTimeoutErrorCallback<Instance, Source extends "slash"|"text"|"button"|"dropdown"|"modal"|"other"> = (instance:Instance, source:Source) => void|Promise<void>
export type ODResponderTimeoutErrorCallback<Instance, Source extends "slash"|"text"|"button"|"dropdown"|"modal"|"other"|"context-menu"|"autocomplete"> = (instance:Instance, source:Source) => void|Promise<void>
/**## ODResponderManager `class`
* This is an Open Ticket responder manager.
@@ -61,12 +61,18 @@ export class ODResponderManager {
dropdowns: ODDropdownResponderManager
/**A manager for all modal responders. */
modals: ODModalResponderManager
/**A manager for all context menu responders. */
contextMenus: ODContextMenuResponderManager
/**A manager for all autocomplete responders. */
autocomplete: ODAutocompleteResponderManager
constructor(debug:ODDebugger, client:ODClientManager){
this.commands = new ODCommandResponderManager(debug,"command responder",client)
this.buttons = new ODButtonResponderManager(debug,"button responder",client)
this.dropdowns = new ODDropdownResponderManager(debug,"dropdown responder",client)
this.modals = new ODModalResponderManager(debug,"modal responder",client)
this.contextMenus = new ODContextMenuResponderManager(debug,"context menu responder",client)
this.autocomplete = new ODAutocompleteResponderManager(debug,"autocomplete responder",client)
}
}
@@ -1083,7 +1089,7 @@ export class ODModalResponderInstance {
const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}else throw new ODSystemError()
}else throw new ODSystemError("Unable to update modal interaction!")
}catch{
return {success:false,message:null}
}
@@ -1113,4 +1119,297 @@ export class ODModalResponder<Source extends string,Params> extends ODResponderI
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
}
}
/**## ODContextMenuResponderManager `class`
* This is an Open Ticket context menu responder manager.
*
* It contains all Open Ticket context menu responders. These can respond to user/message context menu interactions.
*
* Using the Open Ticket responder system has a few advantages compared to vanilla discord.js:
* - plugins can extend/edit replies
* - automatically reply on error
* - independent workers (with priority)
* - fail-safe design using try-catch
* - know where the request came from!
* - And so much more!
*/
export class ODContextMenuResponderManager extends ODManager<ODContextMenuResponder<"context-menu",any>> {
/**An alias to the Open Ticket client manager. */
#client: ODClientManager
/**The callback executed when the default workers take too much time to reply. */
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODContextMenuResponderInstance,"context-menu">|null = null
/**The amount of milliseconds before the timeout error callback is executed. */
#timeoutMs: number|null = null
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
super(debug,debugname)
this.#client = client
}
/**Set the message to send when the response times out! */
setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback<ODContextMenuResponderInstance,"context-menu">|null, ms:number|null){
this.#timeoutErrorCallback = callback
this.#timeoutMs = ms
}
add(data:ODContextMenuResponder<"context-menu",any>, overwrite?:boolean){
const res = super.add(data,overwrite)
this.#client.contextMenus.onInteraction(data.match,(interaction,cmd) => {
const newData = this.get(data.id)
if (!newData) return
newData.respond(new ODContextMenuResponderInstance(interaction,cmd,this.#timeoutErrorCallback,this.#timeoutMs),"context-menu",{})
})
return res
}
}
/**## ODContextMenuResponderInstance `class`
* This is an Open Ticket context menu responder instance.
*
* An instance is an active context menu interaction. You can reply to the context menu using `reply()`.
*/
export class ODContextMenuResponderInstance {
/**The interaction which is the source of this instance. */
interaction: discord.ContextMenuCommandInteraction
/**Did a worker already reply to this instance/interaction? */
didReply: boolean = false
/**The context menu wich is the source of this instance. */
menu:ODContextMenu
/**The user who triggered this context menu. */
user: discord.User
/**The guild member who triggered this context menu. */
member: discord.GuildMember|null
/**The guild where this context menu was triggered. */
guild: discord.Guild|null
/**The channel where this context menu was triggered. */
channel: discord.TextBasedChannel
/**The target of this context menu (user or message). */
target: discord.Message|discord.User
constructor(interaction:discord.ContextMenuCommandInteraction, menu:ODContextMenu, errorCallback:ODResponderTimeoutErrorCallback<ODContextMenuResponderInstance,"context-menu">|null, timeoutMs:number|null){
if (!interaction.channel) throw new ODSystemError("ODContextMenuResponderInstance: Unable to find interaction channel!")
this.interaction = interaction
this.menu = menu
this.user = interaction.user
this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null
this.guild = interaction.guild
this.channel = interaction.channel
if (interaction.isMessageContextMenuCommand()) this.target = interaction.targetMessage
else if (interaction.isUserContextMenuCommand()) this.target = interaction.targetUser
else throw new ODSystemError("ODContextMenuResponderInstance: Invalid context menu type. Should be of the type User/Message!")
setTimeout(async () => {
if (!this.didReply){
try {
if (!errorCallback){
this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{
content:":x: **Something went wrong while replying to this context menu!**"
}})
}else{
await errorCallback(this,"context-menu")
}
}catch(err){
process.emit("uncaughtException",err)
}
}
},timeoutMs ?? 2500)
}
/**Reply to this context menu. */
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags}))
this.didReply = true
return {success:true,message:sent}
}else{
const sent = await this.interaction.reply(Object.assign(msg.message,{flags:msgFlags}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}
}catch{
return {success:false,message:null}
}
}
/**Update the message of this context menu. */
async update(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}else throw new ODSystemError("Unable to update context menu interaction!")
}catch{
return {success:false,message:null}
}
}
/**Defer this context menu. */
async defer(type:"reply", ephemeral:boolean){
if (this.interaction.deferred) return false
if (type == "reply"){
const msgFlags: number[] = ephemeral ? [discord.MessageFlags.Ephemeral] : []
await this.interaction.deferReply({flags:msgFlags})
}
this.didReply = true
return true
}
/**Show a modal as reply to this context menu. */
async modal(modal:ODModalBuildResult){
this.interaction.showModal(modal.modal)
this.didReply = true
return true
}
}
/**## ODContextMenuResponder `class`
* This is an Open Ticket context menu responder.
*
* This class manages all workers which are executed when the related context menu is triggered.
*/
export class ODContextMenuResponder<Source extends string,Params> extends ODResponderImplementation<ODContextMenuResponderInstance,Source,Params> {
/**Respond to this button */
async respond(instance:ODContextMenuResponderInstance, source:Source, params:Params){
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
}
}
/**## ODAutocompleteResponderManager `class`
* This is an Open Ticket autocomplete responder manager.
*
* It contains all Open Ticket autocomplete responders. These can respond to autocomplete interactions.
*
* Using the Open Ticket responder system has a few advantages compared to vanilla discord.js:
* - plugins can extend/edit replies
* - automatically reply on error
* - independent workers (with priority)
* - fail-safe design using try-catch
* - know where the request came from!
* - And so much more!
*/
export class ODAutocompleteResponderManager extends ODManager<ODAutocompleteResponder<"autocomplete",any>> {
/**An alias to the Open Ticket client manager. */
#client: ODClientManager
/**The callback executed when the default workers take too much time to reply. */
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODAutocompleteResponderInstance,"autocomplete">|null = null
/**The amount of milliseconds before the timeout error callback is executed. */
#timeoutMs: number|null = null
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
super(debug,debugname)
this.#client = client
}
/**Set the message to send when the response times out! */
setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback<ODAutocompleteResponderInstance,"autocomplete">|null, ms:number|null){
this.#timeoutErrorCallback = callback
this.#timeoutMs = ms
}
add(data:ODAutocompleteResponder<"autocomplete",any>, overwrite?:boolean){
const res = super.add(data,overwrite)
this.#client.autocompletes.onInteraction(data.cmdMatch,data.match,(interaction) => {
const newData = this.get(data.id)
if (!newData) return
newData.respond(new ODAutocompleteResponderInstance(interaction,this.#timeoutErrorCallback,this.#timeoutMs),"autocomplete",{})
})
return res
}
}
/**## ODAutocompleteResponderInstance `class`
* This is an Open Ticket autocomplete responder instance.
*
* An instance is an active autocomplete interaction. You can reply to the autocomplete using `reply()`.
*/
export class ODAutocompleteResponderInstance {
/**The interaction which is the source of this instance. */
interaction: discord.AutocompleteInteraction
/**Did a worker already reply to this instance/interaction? */
didReply: boolean = false
/**The user who triggered this autocomplete. */
user: discord.User
/**The guild member who triggered this autocomplete. */
member: discord.GuildMember|null
/**The guild where this autocomplete was triggered. */
guild: discord.Guild|null
/**The channel where this autocomplete was triggered. */
channel: discord.TextBasedChannel
/**The target slash command option of this autocomplete. */
target: discord.AutocompleteFocusedOption
constructor(interaction:discord.AutocompleteInteraction, errorCallback:ODResponderTimeoutErrorCallback<ODAutocompleteResponderInstance,"autocomplete">|null, timeoutMs:number|null){
if (!interaction.channel) throw new ODSystemError("ODAutocompleteResponderInstance: Unable to find interaction channel!")
this.interaction = interaction
this.user = interaction.user
this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null
this.guild = interaction.guild
this.channel = interaction.channel
this.target = interaction.options.getFocused(true)
setTimeout(async () => {
if (!this.didReply){
process.emit("uncaughtException",new ODSystemError("Autocomplete responder instance failed to respond widthin 2.5sec!"))
}
},timeoutMs ?? 2500)
}
/**Reply to this autocomplete. */
async autocomplete(choices:(string|discord.ApplicationCommandOptionChoiceData)[]): Promise<{success:boolean}> {
const newChoices: (discord.ApplicationCommandOptionChoiceData)[] = choices.map((raw) => {
if (typeof raw == "string") return {name:raw,value:raw}
else return raw
})
try{
if (this.interaction.responded){
return {success:false}
}else{
await this.interaction.respond(newChoices)
return {success:true}
}
}catch(err){
process.emit("uncaughtException",err)
return {success:false}
}
}
/**Reply to this autocomplete, but filter choices based on the input of the user. */
async filteredAutocomplete(choices:(string|discord.ApplicationCommandOptionChoiceData)[]): Promise<{success:boolean}> {
const newChoices: (discord.ApplicationCommandOptionChoiceData)[] = choices.map((raw) => {
if (typeof raw == "string") return {name:raw,value:raw}
else return raw
})
const filteredChoices = newChoices.filter((choice) => choice.name.startsWith(this.target.value) || choice.value.toString().startsWith(this.target.value))
return await this.autocomplete(filteredChoices)
}
}
/**## ODAutocompleteResponder `class`
* This is an Open Ticket autocomplete responder.
*
* This class manages all workers which are executed when the related autocomplete is triggered.
*/
export class ODAutocompleteResponder<Source extends string,Params> extends ODResponderImplementation<ODAutocompleteResponderInstance,Source,Params> {
/**The slash command of the autocomplete should match the following regex. */
cmdMatch: string|RegExp
constructor(id:ODValidId,cmdMatch:string|RegExp,match:string|RegExp,callback?:ODWorkerCallback<ODAutocompleteResponderInstance,Source,Params>,priority?:number,callbackId?:ODValidId){
super(id,match,callback,priority,callbackId)
this.cmdMatch = cmdMatch
}
/**Respond to this autocomplete interaction. */
async respond(instance:ODAutocompleteResponderInstance, source:Source, params:Params){
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
}
}
+4
View File
@@ -209,6 +209,10 @@ export const loadAllEvents = () => {
"afterDropdownRespondersLoaded",
"onModalResponderLoad",
"afterModalRespondersLoaded",
"onContextMenuResponderLoad",
"afterContextMenuRespondersLoaded",
"onAutocompleteResponderLoad",
"afterAutocompleteRespondersLoaded",
//plugin loading before finalizations
"onPluginBeforeFinalizationLoad",
+17 -1
View File
@@ -710,6 +710,22 @@ const main = async () => {
await opendiscord.events.get("onModalResponderLoad").emit([opendiscord.responders.modals,opendiscord.responders,opendiscord.actions])
await opendiscord.events.get("afterModalRespondersLoaded").emit([opendiscord.responders.modals,opendiscord.responders,opendiscord.actions])
//load context menu responders
opendiscord.log("Loading context menu responders...","system")
if (opendiscord.defaults.getDefault("contextMenuRespondersLoading")){
//TODO!!
}
await opendiscord.events.get("onContextMenuResponderLoad").emit([opendiscord.responders.contextMenus,opendiscord.responders,opendiscord.actions])
await opendiscord.events.get("afterContextMenuRespondersLoaded").emit([opendiscord.responders.contextMenus,opendiscord.responders,opendiscord.actions])
//load autocomplete responders
opendiscord.log("Loading autocomplete responders...","system")
if (opendiscord.defaults.getDefault("autocompleteRespondersLoading")){
//TODO!!
}
await opendiscord.events.get("onAutocompleteResponderLoad").emit([opendiscord.responders.autocomplete,opendiscord.responders,opendiscord.actions])
await opendiscord.events.get("afterAutocompleteRespondersLoaded").emit([opendiscord.responders.autocomplete,opendiscord.responders,opendiscord.actions])
//plugin loading before finalizations
await opendiscord.events.get("onPluginBeforeFinalizationLoad").emit([])
await opendiscord.events.get("afterPluginBeforeFinalizationLoaded").emit([])
@@ -871,7 +887,7 @@ const main = async () => {
await opendiscord.startscreen.renderAllComponents()
if (opendiscord.languages.getLanguageMetadata(false)?.automated){
console.log("===================")
opendiscord.log("You are currently using a language which has been translated by Google Translate!","warning")
opendiscord.log("You are using a language which has been translated using Google Translate or AI!","warning")
opendiscord.log("Please help us improve the translation by contributing to our project!","warning")
console.log("===================")
}