mirror of
https://github.com/sern-handler/handler
synced 2026-06-12 02:42:15 +00:00
chore: prettier reformat
This commit is contained in:
@@ -9,141 +9,140 @@ import type {
|
||||
ReplyMessageOptions,
|
||||
Snowflake,
|
||||
TextBasedChannel,
|
||||
User
|
||||
User,
|
||||
} from 'discord.js';
|
||||
import { None, Option, Some } from 'ts-results';
|
||||
import type { Nullish } from '../../types/handler';
|
||||
|
||||
function firstSome<T>(...args : Option<T>[]) : Nullish<T> {
|
||||
for ( const op of args ) {
|
||||
function firstSome<T>(...args: Option<T>[]): Nullish<T> {
|
||||
for (const op of args) {
|
||||
if (op.some) return op.val;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
//Will need refactoring after applying context in practice
|
||||
//
|
||||
export default class Context {
|
||||
private constructor(
|
||||
private oMsg: Option<Message> = None,
|
||||
private oInterac: Option<ChatInputCommandInteraction> = None
|
||||
private oInterac: Option<ChatInputCommandInteraction> = None,
|
||||
) {
|
||||
this.oMsg = oMsg;
|
||||
this.oInterac = oInterac;
|
||||
}
|
||||
static wrap(
|
||||
wrappable: ChatInputCommandInteraction|Message
|
||||
) : Context {
|
||||
if ( 'token' in wrappable ) {
|
||||
return new Context( None, Some(wrappable));
|
||||
|
||||
static wrap(wrappable: ChatInputCommandInteraction | Message): Context {
|
||||
if ('token' in wrappable) {
|
||||
return new Context(None, Some(wrappable));
|
||||
}
|
||||
return new Context(Some(wrappable), None);
|
||||
}
|
||||
|
||||
public isEmpty() {
|
||||
return this.oMsg.none && this.oInterac.none;
|
||||
}
|
||||
public get message() {
|
||||
|
||||
public get message() {
|
||||
return this.oMsg.unwrap();
|
||||
}
|
||||
|
||||
public get interaction() {
|
||||
return this.oInterac.unwrap();
|
||||
}
|
||||
|
||||
public get id() : Snowflake {
|
||||
return firstSome(
|
||||
this.oInterac.map( i => i.id),
|
||||
this.oMsg.map(m => m.id)
|
||||
)!;
|
||||
}
|
||||
public get channel() : Nullish<TextBasedChannel> {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.channel),
|
||||
this.oInterac.map(i => i.channel)
|
||||
);
|
||||
}
|
||||
public get user(): User {
|
||||
public get id(): Snowflake {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.author),
|
||||
this.oInterac.map(i => i.user)
|
||||
)!;
|
||||
}
|
||||
public get createdTimestamp() : number {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.createdTimestamp),
|
||||
this.oInterac.map(i => i.createdTimestamp)
|
||||
this.oInterac.map(i => i.id),
|
||||
this.oMsg.map(m => m.id),
|
||||
)!;
|
||||
}
|
||||
|
||||
public get guild() : Guild {
|
||||
public get channel(): Nullish<TextBasedChannel> {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.guild),
|
||||
this.oInterac.map(i => i.guild)
|
||||
this.oMsg.map(m => m.channel),
|
||||
this.oInterac.map(i => i.channel),
|
||||
);
|
||||
}
|
||||
|
||||
public get user(): User {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.author),
|
||||
this.oInterac.map(i => i.user),
|
||||
)!;
|
||||
}
|
||||
public get guildId() : Snowflake {
|
||||
|
||||
public get createdTimestamp(): number {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.guildId),
|
||||
this.oInterac.map(i => i.guildId)
|
||||
)!;
|
||||
this.oMsg.map(m => m.createdTimestamp),
|
||||
this.oInterac.map(i => i.createdTimestamp),
|
||||
)!;
|
||||
}
|
||||
|
||||
public get guild(): Guild {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.guild),
|
||||
this.oInterac.map(i => i.guild),
|
||||
)!;
|
||||
}
|
||||
|
||||
public get guildId(): Snowflake {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.guildId),
|
||||
this.oInterac.map(i => i.guildId),
|
||||
)!;
|
||||
}
|
||||
|
||||
/*
|
||||
* interactions can return APIGuildMember if the guild it is emitted from is not cached
|
||||
*/
|
||||
public get member() : Nullish<GuildMember|APIGuildMember> {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.member),
|
||||
this.oInterac.map(i => i.member)
|
||||
);
|
||||
*/
|
||||
public get member(): Nullish<GuildMember | APIGuildMember> {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.member),
|
||||
this.oInterac.map(i => i.member),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the underlying Context but allows for doing other operations
|
||||
*/
|
||||
public onInteraction(
|
||||
onInteraction : ( interaction : ChatInputCommandInteraction ) => Awaitable<void>,
|
||||
): Context {
|
||||
if (this.oInterac.some) {
|
||||
onInteraction(this.oInterac.val);
|
||||
return Context.wrap(this.oInterac.val);
|
||||
}
|
||||
return this;
|
||||
public onInteraction(onInteraction: (interaction: ChatInputCommandInteraction) => Awaitable<void>): Context {
|
||||
if (this.oInterac.some) {
|
||||
onInteraction(this.oInterac.val);
|
||||
return Context.wrap(this.oInterac.val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public onMessage(
|
||||
onMessage : ( message : Message ) => Awaitable<void>
|
||||
): Context {
|
||||
if (this.oMsg.some) {
|
||||
onMessage(this.oMsg.val);
|
||||
return Context.wrap(this.oMsg.val);
|
||||
}
|
||||
return this;
|
||||
|
||||
public onMessage(onMessage: (message: Message) => Awaitable<void>): Context {
|
||||
if (this.oMsg.some) {
|
||||
onMessage(this.oMsg.val);
|
||||
return Context.wrap(this.oMsg.val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public takeInteractionValue<T>(
|
||||
extract : (interaction : ChatInputCommandInteraction) => T
|
||||
): Nullish<T> {
|
||||
if(this.oInterac.none) return null;
|
||||
return extract(this.oInterac.val);
|
||||
}
|
||||
|
||||
public takeMessageValue<T>(
|
||||
extract : (message: Message) => T
|
||||
): Nullish<T> {
|
||||
if(this.oMsg.none) return null;
|
||||
return extract(this.oMsg.val);
|
||||
}
|
||||
public takeInteractionValue<T>(extract: (interaction: ChatInputCommandInteraction) => T): Nullish<T> {
|
||||
if (this.oInterac.none) return null;
|
||||
return extract(this.oInterac.val);
|
||||
}
|
||||
|
||||
public reply(
|
||||
content : Omit<InteractionReplyOptions, 'fetchReply'> | ReplyMessageOptions
|
||||
): Promise<Context> {
|
||||
return firstSome(
|
||||
this.oInterac.map(async i => {
|
||||
await i.reply( content as InteractionReplyOptions);
|
||||
return new Context(Some(await i.fetchReply() as Message), Some(i));
|
||||
}),
|
||||
this.oMsg.map(async m => {
|
||||
const reply = await m.reply( content as ReplyMessageOptions );
|
||||
return new Context(Some(reply), this.oInterac);
|
||||
})
|
||||
)!;
|
||||
}
|
||||
public takeMessageValue<T>(extract: (message: Message) => T): Nullish<T> {
|
||||
if (this.oMsg.none) return null;
|
||||
return extract(this.oMsg.val);
|
||||
}
|
||||
|
||||
public reply(content: Omit<InteractionReplyOptions, 'fetchReply'> | ReplyMessageOptions): Promise<Context> {
|
||||
return firstSome(
|
||||
this.oInterac.map(async i => {
|
||||
await i.reply(content as InteractionReplyOptions);
|
||||
return new Context(Some((await i.fetchReply()) as Message), Some(i));
|
||||
}),
|
||||
this.oMsg.map(async m => {
|
||||
const reply = await m.reply(content as ReplyMessageOptions);
|
||||
return new Context(Some(reply), this.oInterac);
|
||||
}),
|
||||
)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,5 +3,5 @@ export enum SernError {
|
||||
NoAlias = 'You cannot provide an array with elements to a slash command.',
|
||||
NonValidModuleType = 'Detected an unknown module type',
|
||||
UndefinedModule = `A module could not be detected at`,
|
||||
MismatchModule = `A module type mismatched with event emitted!`
|
||||
MismatchModule = `A module type mismatched with event emitted!`,
|
||||
}
|
||||
|
||||
@@ -1,47 +1,50 @@
|
||||
import type { ApplicationCommandOptionData, Awaitable, ButtonInteraction, ContextMenuCommandInteraction, MessageContextMenuCommandInteraction, SelectMenuInteraction } from 'discord.js';
|
||||
import type {
|
||||
ApplicationCommandOptionData,
|
||||
Awaitable,
|
||||
ButtonInteraction,
|
||||
ContextMenuCommandInteraction,
|
||||
MessageContextMenuCommandInteraction,
|
||||
SelectMenuInteraction,
|
||||
} from 'discord.js';
|
||||
import type { Override } from '../../../../types/handler';
|
||||
import type { CommandType } from '../../../sern';
|
||||
import type { BaseModule } from '../module';
|
||||
|
||||
|
||||
|
||||
//possible refactoring to interfaces and not types
|
||||
export type TextCommand = {
|
||||
type : CommandType.Text;
|
||||
alias : string[] | [],
|
||||
type: CommandType.Text;
|
||||
alias: string[] | [];
|
||||
} & BaseModule;
|
||||
|
||||
export type SlashCommand = {
|
||||
type : CommandType.Slash;
|
||||
options : ApplicationCommandOptionData[] | [],
|
||||
} & BaseModule;
|
||||
type: CommandType.Slash;
|
||||
options: ApplicationCommandOptionData[] | [];
|
||||
} & BaseModule;
|
||||
|
||||
export type BothCommand = {
|
||||
type : CommandType.Both;
|
||||
alias : string[] | [];
|
||||
options : ApplicationCommandOptionData[] | [],
|
||||
type: CommandType.Both;
|
||||
alias: string[] | [];
|
||||
options: ApplicationCommandOptionData[] | [];
|
||||
} & BaseModule;
|
||||
|
||||
export type ContextMenuUser = {
|
||||
type : CommandType.MenuUser;
|
||||
} & Override<BaseModule, { execute : ( ctx: ContextMenuCommandInteraction ) => Awaitable<void> }>;
|
||||
type: CommandType.MenuUser;
|
||||
} & Override<BaseModule, { execute: (ctx: ContextMenuCommandInteraction) => Awaitable<void> }>;
|
||||
export type ContextMenuMsg = {
|
||||
type : CommandType.MenuMsg;
|
||||
} & Override<BaseModule, { execute : ( ctx: MessageContextMenuCommandInteraction ) => Awaitable<void> }>;
|
||||
type: CommandType.MenuMsg;
|
||||
} & Override<BaseModule, { execute: (ctx: MessageContextMenuCommandInteraction) => Awaitable<void> }>;
|
||||
export type ButtonCommand = {
|
||||
type : CommandType.Button;
|
||||
} & Override<BaseModule, { execute : (ctx :ButtonInteraction ) => Awaitable<void> }>;
|
||||
type: CommandType.Button;
|
||||
} & Override<BaseModule, { execute: (ctx: ButtonInteraction) => Awaitable<void> }>;
|
||||
export type SelectMenuCommand = {
|
||||
type : CommandType.MenuSelect;
|
||||
} & Override<BaseModule, { execute : (ctx : SelectMenuInteraction ) => Awaitable<void> }>;
|
||||
type: CommandType.MenuSelect;
|
||||
} & Override<BaseModule, { execute: (ctx: SelectMenuInteraction) => Awaitable<void> }>;
|
||||
|
||||
|
||||
export type Module = (
|
||||
TextCommand
|
||||
| SlashCommand
|
||||
export type Module =
|
||||
| TextCommand
|
||||
| SlashCommand
|
||||
| BothCommand
|
||||
| ContextMenuUser
|
||||
| ContextMenuMsg
|
||||
| ButtonCommand
|
||||
| SelectMenuCommand
|
||||
);
|
||||
| SelectMenuCommand;
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
import Context from './context';
|
||||
import type { SlashCommand, TextCommand, BothCommand, Module } from '../structures/modules/commands/module';
|
||||
import type { BothCommand, Module, SlashCommand, TextCommand } from './modules/commands/module';
|
||||
import type Wrapper from './wrapper';
|
||||
|
||||
export {
|
||||
Context,
|
||||
SlashCommand,
|
||||
TextCommand,
|
||||
BothCommand,
|
||||
Module,
|
||||
Wrapper
|
||||
};
|
||||
export { Context, SlashCommand, TextCommand, BothCommand, Module, Wrapper };
|
||||
|
||||
@@ -14,7 +14,7 @@ interface Wrapper {
|
||||
readonly client: Client;
|
||||
readonly defaultPrefix?: string;
|
||||
readonly commands: string;
|
||||
readonly events? : DiscordEvent[];
|
||||
readonly events?: DiscordEvent[];
|
||||
}
|
||||
|
||||
export default Wrapper;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ import type { Message } from 'discord.js';
|
||||
export function isNotFromBot(message: Message) {
|
||||
return !message.author.bot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the message **starts** with the prefix
|
||||
* @param message The message to check
|
||||
@@ -21,6 +22,7 @@ export function isNotFromBot(message: Message) {
|
||||
export function hasPrefix(message: Message, prefix?: string) {
|
||||
return message.content.startsWith(prefix!);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the first character(s) _[depending on prefix length]_ of the message
|
||||
* @param msg
|
||||
|
||||
@@ -1,40 +1,38 @@
|
||||
import { ApplicationCommandType, ComponentType, InteractionType, MessageComponentInteraction, MessageComponentType } from 'discord.js';
|
||||
import { ApplicationCommandType, ComponentType } from 'discord.js';
|
||||
import { readdirSync, statSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { from, Observable } from 'rxjs';
|
||||
import { CommandType } from '../sern';
|
||||
import type { PluggedModule } from '../structures/modules/module';
|
||||
|
||||
|
||||
export const BothCommand = new Map<string, PluggedModule>();
|
||||
export const ApplicationCommandStore = {
|
||||
[ApplicationCommandType.User] : new Map<string, PluggedModule>(),
|
||||
[ApplicationCommandType.Message] : new Map<string, PluggedModule>(),
|
||||
[ApplicationCommandType.ChatInput] : new Map<string, PluggedModule>(),
|
||||
} as {[K in ApplicationCommandType] : Map<string, PluggedModule> };
|
||||
[ApplicationCommandType.User]: new Map<string, PluggedModule>(),
|
||||
[ApplicationCommandType.Message]: new Map<string, PluggedModule>(),
|
||||
[ApplicationCommandType.ChatInput]: new Map<string, PluggedModule>(),
|
||||
} as { [K in ApplicationCommandType]: Map<string, PluggedModule> };
|
||||
|
||||
export const MessageCompCommandStore = {
|
||||
[ComponentType.Button] : new Map<string, PluggedModule>(),
|
||||
[ComponentType.SelectMenu] : new Map<string, PluggedModule>()
|
||||
[ComponentType.Button]: new Map<string, PluggedModule>(),
|
||||
[ComponentType.SelectMenu]: new Map<string, PluggedModule>(),
|
||||
};
|
||||
export const TextCommandStore = {
|
||||
text : new Map<string, PluggedModule>(),
|
||||
aliases : new Map<string, PluggedModule>()
|
||||
text: new Map<string, PluggedModule>(),
|
||||
aliases: new Map<string, PluggedModule>(),
|
||||
};
|
||||
|
||||
// Courtesy @Townsy45
|
||||
function readPath(dir: string, arrayOfFiles: string[] = []): string[] {
|
||||
try {
|
||||
const files = readdirSync(dir);
|
||||
for (const file of files) {
|
||||
if (statSync(dir + '/' + file).isDirectory()) readPath(dir + '/' + file, arrayOfFiles);
|
||||
else arrayOfFiles.push(join(dir, '/', file));
|
||||
try {
|
||||
const files = readdirSync(dir);
|
||||
for (const file of files) {
|
||||
if (statSync(dir + '/' + file).isDirectory()) readPath(dir + '/' + file, arrayOfFiles);
|
||||
else arrayOfFiles.push(join(dir, '/', file));
|
||||
}
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return arrayOfFiles;
|
||||
return arrayOfFiles;
|
||||
}
|
||||
|
||||
export const fmtFileName = (n: string) => n.substring(0, n.length - 3);
|
||||
@@ -45,18 +43,19 @@ export const fmtFileName = (n: string) => n.substring(0, n.length - 3);
|
||||
* @param commandDir
|
||||
*/
|
||||
|
||||
export function buildData(commandDir: string ): Observable<
|
||||
{
|
||||
export function buildData(commandDir: string): Observable<{
|
||||
plugged: PluggedModule;
|
||||
absPath: string;
|
||||
}> {
|
||||
return from(getCommands(commandDir).map(absPath => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const plugged = (<PluggedModule> require(absPath).module);
|
||||
return { plugged, absPath };
|
||||
}));
|
||||
}> {
|
||||
return from(
|
||||
getCommands(commandDir).map(absPath => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const plugged = <PluggedModule>require(absPath).module;
|
||||
return { plugged, absPath };
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function getCommands(dir: string): string[] {
|
||||
return readPath(join(process.cwd(), dir));
|
||||
return readPath(join(process.cwd(), dir));
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
import type {
|
||||
CommandInteractionOptionResolver,
|
||||
MessagePayload,
|
||||
MessageOptions,
|
||||
ClientEvents,
|
||||
Awaitable,
|
||||
ClientEvents,
|
||||
CommandInteractionOptionResolver,
|
||||
MessageOptions,
|
||||
MessagePayload,
|
||||
} from 'discord.js';
|
||||
|
||||
// Anything that can be sent in a `<TextChannel>#send` or `<CommandInteraction>#reply`
|
||||
@@ -15,15 +14,11 @@ export type ParseType<T> = {
|
||||
[K in keyof T]: T[K] extends unknown ? [k: K, args: T[K]] : never;
|
||||
}[keyof T];
|
||||
|
||||
|
||||
export type Args = ParseType<{ text: string[]; slash: SlashOptions }>;
|
||||
|
||||
export type DiscordEvent =
|
||||
ParseType< { [K in keyof ClientEvents ] : (...args : ClientEvents[K]) => Awaitable<void> }>;
|
||||
|
||||
export type DiscordEvent = ParseType<{ [K in keyof ClientEvents]: (...args: ClientEvents[K]) => Awaitable<void> }>;
|
||||
|
||||
export type SlashOptions = Omit<CommandInteractionOptionResolver, 'getMessage' | 'getFocused'>;
|
||||
|
||||
//https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l
|
||||
export type Override<T1, T2> = Omit<T1, keyof T2> & T2;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user