From e8d502983429909a6e198dee34362720b6a40736 Mon Sep 17 00:00:00 2001 From: SrIzan10 <66965250+SrIzan10@users.noreply.github.com> Date: Fri, 5 Jan 2024 20:46:38 +0100 Subject: [PATCH 1/9] chore: update fortnite file --- fortnite | 1 + 1 file changed, 1 insertion(+) diff --git a/fortnite b/fortnite index e69de29b..6a2188d7 100644 --- a/fortnite +++ b/fortnite @@ -0,0 +1 @@ +this adds fortnite, it speeds up the software, makes it way faster, adds way more features to sern, and clearly should make me the top developer in sern. because im just BETTER From 655bb8d35815fe0ce9797d8b169310a07b284ae0 Mon Sep 17 00:00:00 2001 From: SrIzan10 <66965250+SrIzan10@users.noreply.github.com> Date: Fri, 5 Jan 2024 20:47:25 +0100 Subject: [PATCH 2/9] revert: the last commit --- fortnite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fortnite b/fortnite index 6a2188d7..d3f5a12f 100644 --- a/fortnite +++ b/fortnite @@ -1 +1 @@ -this adds fortnite, it speeds up the software, makes it way faster, adds way more features to sern, and clearly should make me the top developer in sern. because im just BETTER + From a359f73fa24127a4964d411c8c1c0dfea5edc0f1 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 7 Jan 2024 15:26:08 -0600 Subject: [PATCH 3/9] fix: crashing when slash command is used as text command (#349) * progress on fix * fix: ids --- src/core/id.ts | 54 +++++++++++-------- .../structures/services/module-manager.ts | 5 +- src/handlers/dispatchers.ts | 4 +- src/handlers/event-utils.ts | 33 +++++++----- src/handlers/ready-event.ts | 8 ++- test/handlers/id.test.ts | 29 +--------- 6 files changed, 66 insertions(+), 67 deletions(-) diff --git a/src/core/id.ts b/src/core/id.ts index fa4a33ba..28032c54 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -4,20 +4,20 @@ import { CommandType, EventType } from './structures'; /** * Construct unique ID for a given interaction object. * @param event The interaction object for which to create an ID. - * @returns A unique string ID based on the type and properties of the interaction object. + * @returns An array of unique string IDs based on the type and properties of the interaction object. */ export function reconstruct(event: T) { switch (event.type) { case InteractionType.MessageComponent: { - return `${event.customId}_C${event.componentType}`; + return [`${event.customId}_C${event.componentType}`]; } case InteractionType.ApplicationCommand: case InteractionType.ApplicationCommandAutocomplete: { - return `${event.commandName}_A${event.commandType}`; + return [`${event.commandName}_A${event.commandType}`, `${event.commandName}_B`]; } //Modal interactions are classified as components for sern case InteractionType.ModalSubmit: { - return `${event.customId}_C1`; + return [`${event.customId}_M`]; } } } @@ -27,21 +27,20 @@ export function reconstruct(event: T) { */ const appBitField = 0b000000001111; -// Each index represents the exponent of a CommandType. -// Every CommandType is a power of two. -export const CommandTypeDiscordApi = [ - 1, // CommandType.Text - ApplicationCommandType.ChatInput, - ApplicationCommandType.User, - ApplicationCommandType.Message, - ComponentType.Button, - ComponentType.StringSelect, - 1, // CommandType.Modal - ComponentType.UserSelect, - ComponentType.RoleSelect, - ComponentType.MentionableSelect, - ComponentType.ChannelSelect, -]; + +const TypeMap = new Map([ + [CommandType.Text, 0], + [CommandType.Both, 0], + [CommandType.Slash, ApplicationCommandType.ChatInput], + [CommandType.CtxUser, ApplicationCommandType.User], + [CommandType.CtxMsg, ApplicationCommandType.Message], + [CommandType.Button, ComponentType.Button], + [CommandType.Modal, InteractionType.ModalSubmit], + [CommandType.StringSelect, ComponentType.StringSelect], + [CommandType.UserSelect, ComponentType.UserSelect], + [CommandType.MentionableSelect, ComponentType.MentionableSelect], + [CommandType.RoleSelect, ComponentType.RoleSelect], + [CommandType.ChannelSelect, ComponentType.ChannelSelect]]); /* * Generates a number based on CommandType. @@ -49,8 +48,7 @@ export const CommandTypeDiscordApi = [ * TextCommands are 0 as they aren't either or. */ function apiType(t: CommandType | EventType) { - if (t === CommandType.Both || t === CommandType.Modal) return 1; - return CommandTypeDiscordApi[Math.log2(t)]; + return TypeMap.get(t)!; } /* @@ -59,6 +57,18 @@ function apiType(t: CommandType | EventType) { * Then, another number generated by apiType function is appended */ export function create(name: string, type: CommandType | EventType) { + if(type == CommandType.Text) { + return `${name}_T`; + } + if(type == CommandType.Both) { + return `${name}_B`; + } + if(type == CommandType.Modal) { + return `${name}_M`; + } const am = (appBitField & type) !== 0 ? 'A' : 'C'; - return name + '_' + am + apiType(type); + return `${name}_${am}${apiType(type)}` } + + + diff --git a/src/core/structures/services/module-manager.ts b/src/core/structures/services/module-manager.ts index 63154802..356936bf 100644 --- a/src/core/structures/services/module-manager.ts +++ b/src/core/structures/services/module-manager.ts @@ -44,7 +44,10 @@ export class DefaultModuleManager implements ModuleManager { const publishable = 0b000000110; return Promise.all( Array.from(entries) - .filter(([id]) => !(Number.parseInt(id.at(-1)!) & publishable)) + .filter(([id]) => { + const last_entry = id.at(-1); + return last_entry == 'B' || !(publishable & Number.parseInt(last_entry!)); + }) .map(([, path]) => Files.importModule(path)), ); } diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts index ad9549c8..5162e1ee 100644 --- a/src/handlers/dispatchers.ts +++ b/src/handlers/dispatchers.ts @@ -11,7 +11,7 @@ import { import { createResultResolver } from './event-utils'; import { BaseInteraction, Message } from 'discord.js'; import { CommandType, Context } from '../core'; -import type { AnyFunction, Args } from '../types/utility'; +import type { Args } from '../types/utility'; import { inspect } from 'node:util' import type { CommandModule, Module, Processed } from '../types/core-modules'; @@ -77,7 +77,7 @@ export function createDispatcher(payload: { if (isAutocomplete(payload.event)) { const option = treeSearch(payload.event, payload.module.options); assert.ok(option, SernError.NotSupportedInteraction + ` There is no autocomplete tag for ` + inspect(payload.module)); - const { command, name, parent } = option; + const { command } = option; return { ...payload, diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index ad75f520..6182aee3 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -71,18 +71,23 @@ export function createInteractionHandler( return createGenericHandler, void>>( source, async event => { - const fullPath = mg.get(Id.reconstruct(event)); - if(!fullPath) { - return Err.EMPTY + const possibleIds = Id.reconstruct(event); + let fullPaths= possibleIds + .map(id => mg.get(id)) + .filter((id): id is string => id !== undefined); + + if(fullPaths.length == 0) { + return Err.EMPTY; } + const [ path ] = fullPaths; return Files - .defaultModuleLoader>(fullPath) - .then(payload => Ok(createDispatcher({ - module: payload.module, - event, - }))); - }, - ); + .defaultModuleLoader>(path) + .then(payload => Ok(createDispatcher({ + module: payload.module, + event, + }))); + }, +); } export function createMessageHandler( @@ -92,10 +97,12 @@ export function createMessageHandler( ) { return createGenericHandler(source, async event => { const [prefix, ...rest] = fmt(event.content, defaultPrefix); - const fullPath = mg.get(`${prefix}_A1`); - + let fullPath = mg.get(`${prefix}_T`); if(!fullPath) { - return Err('Possibly undefined behavior: could not find a static id to resolve') + fullPath = mg.get(`${prefix}_B`); + if(!fullPath) { + return Err('Possibly undefined behavior: could not find a static id to resolve'); + } } return Files .defaultModuleLoader>(fullPath) diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index 9e6753df..b4e811bd 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -39,8 +39,12 @@ function register>( validModuleType, `Found ${module.name} at ${fullPath}, which does not have a valid type`, ); - if (module.type === CommandType.Both || module.type === CommandType.Text) { - module.alias?.forEach(a => manager.set(`${a}_A1`, fullPath)); + if (module.type === CommandType.Both) { + module.alias?.forEach(a => manager.set(`${a}_B`, fullPath)); + } else { + if(module.type === CommandType.Text){ + module.alias?.forEach(a => manager.set(`${a}_T`, fullPath)); + } } return Result.wrap(() => manager.set(id, fullPath)); } diff --git a/test/handlers/id.test.ts b/test/handlers/id.test.ts index a472742b..d8306900 100644 --- a/test/handlers/id.test.ts +++ b/test/handlers/id.test.ts @@ -2,7 +2,6 @@ import { describe, expect, it, vi } from 'vitest'; import * as Id from '../../src/core/id'; import { faker } from '@faker-js/faker'; import { CommandModule, CommandType, commandModule } from '../../src'; -import { CommandTypeDiscordApi } from '../../src/core/id'; function createRandomCommandModules() { const randomCommandType = [ @@ -41,32 +40,8 @@ describe('id resolution', () => { const metadata = modules.map(createMetadata); metadata.forEach((meta, idx) => { const associatedModule = modules[idx]; - const am = (appBitField & associatedModule.type) !== 0 ? 'A' : 'C'; - let uid = 0; - if ( - associatedModule.type === CommandType.Both || - associatedModule.type === CommandType.Modal - ) { - uid = 1; - } else { - uid = CommandTypeDiscordApi[Math.log2(associatedModule.type)]; - } - expect(meta.id).toBe(associatedModule.name + '_' + am + uid); + const uid = Id.create(associatedModule.name!, associatedModule.type!); + expect(meta.id).toBe(uid); }); }); - - it('maps commands type to discord components or application commands', () => { - expect(CommandTypeDiscordApi[Math.log2(CommandType.Text)]).toBe(1); - - expect(CommandTypeDiscordApi[1]).toBe(1); - expect(CommandTypeDiscordApi[Math.log2(CommandType.CtxUser)]).toBe(2); - expect(CommandTypeDiscordApi[Math.log2(CommandType.CtxMsg)]).toBe(3); - expect(CommandTypeDiscordApi[Math.log2(CommandType.Button)]).toBe(2); - expect(CommandTypeDiscordApi[Math.log2(CommandType.StringSelect)]).toBe(3); - expect(CommandTypeDiscordApi[Math.log2(CommandType.UserSelect)]).toBe(5); - expect(CommandTypeDiscordApi[Math.log2(CommandType.RoleSelect)]).toBe(6); - expect(CommandTypeDiscordApi[Math.log2(CommandType.MentionableSelect)]).toBe(7); - expect(CommandTypeDiscordApi[Math.log2(CommandType.ChannelSelect)]).toBe(8); - expect(CommandTypeDiscordApi[6]).toBe(1); - }); }); From c281832db2c674d7aa0545d2ad5753e41609a505 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 7 Jan 2024 15:27:43 -0600 Subject: [PATCH 4/9] chore(main): release 3.3.1 (#350) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9b1f0b2..f661fbe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [3.3.1](https://github.com/sern-handler/handler/compare/v3.3.0...v3.3.1) (2024-01-07) + + +### Bug Fixes + +* crashing when slash command is used as text command ([#349](https://github.com/sern-handler/handler/issues/349)) ([a359f73](https://github.com/sern-handler/handler/commit/a359f73fa24127a4964d411c8c1c0dfea5edc0f1)) + + +### Reverts + +* the last commit ([655bb8d](https://github.com/sern-handler/handler/commit/655bb8d35815fe0ce9797d8b169310a07b284ae0)) + ## [3.3.0](https://github.com/sern-handler/handler/compare/v3.2.1...v3.3.0) (2023-12-27) diff --git a/package.json b/package.json index 1aae54ae..044dbace 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@sern/handler", "packageManager": "yarn@3.5.0", - "version": "3.3.0", + "version": "3.3.1", "description": "A complete, customizable, typesafe, & reactive framework for discord bots.", "main": "./dist/index.js", "module": "./dist/index.mjs", From a6fa4e3dcb95f6544ca2aa683204ce56fb2ae1c4 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 7 Jan 2024 15:38:22 -0600 Subject: [PATCH 5/9] fix docs build --- src/core/presences.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/presences.ts b/src/core/presences.ts index 1fdf5e9f..c587575e 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -22,7 +22,7 @@ export type Config = /** * A small wrapper to provide type inference. - * Create a Presence module which **MUST** be put in a file called presence. + * Create a Presence module which **MUST** be put in a file called presence.(language-extension) * adjacent to the file where **Sern.init** is CALLED. */ export function module From 4f2387119acfde036d0d1626553e9050f55627d1 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:11:27 -0600 Subject: [PATCH 6/9] fix: presence feature not workign on cjs applications (#351) * start fix * fix on unix * better solution --- src/core/module-loading.ts | 29 ++++++++++++----------------- src/sern.ts | 1 + 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index a7c6d36d..7bf406c9 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,20 +1,19 @@ import { Result } from 'ts-results-es'; import { type Observable, from, mergeMap, ObservableInput } from 'rxjs'; import { readdir, stat } from 'fs/promises'; -import { basename, extname, join, resolve, parse } from 'path'; +import { basename, extname, join, resolve, parse, dirname } from 'path'; import assert from 'assert'; import { createRequire } from 'node:module'; import type { ImportPayload, Wrapper } from '../types/core'; import type { Module } from '../types/core-modules'; import { existsSync } from 'fs'; -import { fileURLToPath } from 'node:url'; export const shouldHandle = (path: string, fpath: string) => { - const newPath = new URL(fpath+extname(path), path).href; - return { - exists: existsSync(fileURLToPath(newPath)), - path: newPath - } + const file_name = fpath+extname(path); + let newPath = join(dirname(path), file_name) + .replace(/file:\\?/, ""); + return { exists: existsSync(newPath), + path: 'file:///'+newPath }; } @@ -79,11 +78,9 @@ const isSkippable = (filename: string) => { async function deriveFileInfo(dir: string, file: string) { const fullPath = join(dir, file); - return { - fullPath, - fileStats: await stat(fullPath), - base: basename(file), - }; + return { fullPath, + fileStats: await stat(fullPath), + base: basename(file) }; } async function* readPaths(dir: string): AsyncGenerator { @@ -131,10 +128,8 @@ export function loadConfig(wrapper: Wrapper | 'file'): Wrapper { console.log('Events path is set to', eventsPath); } - return { - defaultPrefix: config.defaultPrefix, - commands: commandsPath, - events: eventsPath, - }; + return { defaultPrefix: config.defaultPrefix, + commands: commandsPath, + events: eventsPath }; } diff --git a/src/sern.ts b/src/sern.ts index d6fe0d59..495e331c 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -34,6 +34,7 @@ export function init(maybeWrapper: Wrapper | 'file') { if (wrapper.events !== undefined) { eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); } + const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); //Ready event: load all modules and when finished, time should be taken and logged From 9d5c6c714fabef5341bf6df2a1bcea83403efa0a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:16:52 -0600 Subject: [PATCH 7/9] chore(main): release 3.3.2 (#352) * chore(main): release 3.3.2 * Update CHANGELOG.md --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f661fbe2..e3904561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [3.3.2](https://github.com/sern-handler/handler/compare/v3.3.1...v3.3.2) (2024-01-08) + + +### Bug Fixes + +* presence feature not working on cjs applications ([#351](https://github.com/sern-handler/handler/issues/351)) ([4f23871](https://github.com/sern-handler/handler/commit/4f2387119acfde036d0d1626553e9050f55627d1)) + ## [3.3.1](https://github.com/sern-handler/handler/compare/v3.3.0...v3.3.1) (2024-01-07) diff --git a/package.json b/package.json index 044dbace..3ba82869 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@sern/handler", "packageManager": "yarn@3.5.0", - "version": "3.3.1", + "version": "3.3.2", "description": "A complete, customizable, typesafe, & reactive framework for discord bots.", "main": "./dist/index.js", "module": "./dist/index.mjs", From 044a10dace2facb0de285f05b0ab5948aadd87fb Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:29:49 -0600 Subject: [PATCH 8/9] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8bbda84b..586f4b3c 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ export default commandModule({ - [Murayama](https://github.com/murayamabot/murayama), :pepega: - [Protector (WIP)](https://github.com/needhamgary/Protector), Just a simple bot to help enhance a private minecraft server. - [SmokinWeed 💨](https://github.com/Peter-MJ-Parker/sern-bud), A fun bot for a small - but growing - server. +- [Man Nomic](https://github.com/jacoobes/man-nomic), A simple information bot to provide information to the nomic-ai discord community. ## 💻 CLI From 5cad43258914aa96a7328d505a33bce3a68a4157 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:31:49 -0600 Subject: [PATCH 9/9] Update README.md --- README.md | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/README.md b/README.md index 586f4b3c..590f64c3 100644 --- a/README.md +++ b/README.md @@ -42,26 +42,6 @@ export default commandModule({ }); ``` -
modal.ts - -```ts -export default commandModule({ - type: CommandType.Modal, - //Installed a plugin to make sure modal fields pass a validation. - plugins : [ - assertFields({ - fields: { - name: /^([^0-9]*)$/ - }, - failure: (errors, modal) => modal.reply('your submission did not pass the validations') - }) - ], - execute : (modal) => { - modal.reply('thanks for the submission!'); - } -}) -``` -
## 🤖 Bots Using sern @@ -73,7 +53,7 @@ export default commandModule({ - [Protector (WIP)](https://github.com/needhamgary/Protector), Just a simple bot to help enhance a private minecraft server. - [SmokinWeed 💨](https://github.com/Peter-MJ-Parker/sern-bud), A fun bot for a small - but growing - server. - [Man Nomic](https://github.com/jacoobes/man-nomic), A simple information bot to provide information to the nomic-ai discord community. - +- [Linear-Discord](https://github.com/sern-handler/linear-discord) Display and manage a linear dashboard. ## 💻 CLI It is **highly encouraged** to use the [command line interface](https://github.com/sern-handler/cli) for your project. Don't forget to view it.