mirror of
https://github.com/sern-handler/sern-community
synced 2026-06-06 01:16:57 +00:00
fix compile errors
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/rest": "19.0.7",
|
||||
"@sern/handler": "^3.3.2",
|
||||
"@sern/handler": "^4.0.0",
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "16.0.3",
|
||||
"jsdoc-parse-plus": "1.3.0",
|
||||
|
||||
@@ -44,7 +44,7 @@ export default commandModule({
|
||||
},
|
||||
],
|
||||
execute: async (context, options) => {
|
||||
const option = options[1].getString("search", true);
|
||||
const option = context.options.getString("search", true);
|
||||
const result = docHandler.DocTrie.search(option);
|
||||
|
||||
if (!result.length) {
|
||||
|
||||
@@ -44,15 +44,15 @@ export default slashCommand({
|
||||
],
|
||||
},
|
||||
],
|
||||
execute: async (ctx, [, args]) => {
|
||||
const command = args.getSubcommand();
|
||||
execute: async (ctx) => {
|
||||
const command = ctx.options.getSubcommand();
|
||||
|
||||
await ctx.interaction.deferReply();
|
||||
switch (command) {
|
||||
case "submit": {
|
||||
const attachment = args.getAttachment("attachment");
|
||||
const urlString = args.getString("url");
|
||||
const name = args.getString("name", true);
|
||||
const attachment = ctx.options.getAttachment("attachment");
|
||||
const urlString = ctx.options.getString("url");
|
||||
const name = ctx.options.getString("name", true);
|
||||
const send = sendTo("1014582281907753080", ctx.member as GuildMember, name);
|
||||
|
||||
if (attachment) {
|
||||
|
||||
@@ -6,11 +6,10 @@ import { Evo, Seren, Mina } from "#constants";
|
||||
export default commandModule({
|
||||
type: CommandType.Text,
|
||||
description: "Eval something",
|
||||
alias: ["ev"],
|
||||
execute: async (ctx, args) => {
|
||||
execute: async (ctx) => {
|
||||
if (![Evo, Seren, Mina].includes(ctx.user.id)) return;
|
||||
|
||||
let code: string[] | string = args[1];
|
||||
let code: string[] | string = ctx.options;
|
||||
|
||||
code = code.join(" ") as string;
|
||||
if (code.includes("await")) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ApplicationCommandOptionType } from "discord.js";
|
||||
import { Timestamp } from "#utils";
|
||||
import { Emojis } from "#constants";
|
||||
const prefix = (t: unknown) => (t ? "$" : "#");
|
||||
const octokit = Service("octokit");
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
description: "Get info about a PR or issue",
|
||||
@@ -18,7 +18,7 @@ export default commandModule({
|
||||
autocomplete: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
async execute(ctx) {
|
||||
async execute(ctx, { deps: { octokit } }) {
|
||||
const text = ctx.options.getFocused();
|
||||
const org = await octokit.repos.listForOrg({
|
||||
org: "sern-handler",
|
||||
@@ -60,7 +60,7 @@ export default commandModule({
|
||||
autocomplete: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
async execute(ctx) {
|
||||
async execute(ctx, { deps }) {
|
||||
const text = ctx.options.getFocused();
|
||||
const repo = ctx.options.getString("repo");
|
||||
if (!repo) return ctx.respond([]);
|
||||
@@ -68,7 +68,7 @@ export default commandModule({
|
||||
let search;
|
||||
|
||||
if (text.length) {
|
||||
search = await octokit.search
|
||||
search = await deps.octokit.search
|
||||
.issuesAndPullRequests({
|
||||
q: `repo:sern-handler/${repo} ${text} in:title`,
|
||||
})
|
||||
@@ -76,7 +76,7 @@ export default commandModule({
|
||||
}
|
||||
|
||||
if (!text.length) {
|
||||
const issues = await octokit.issues
|
||||
const issues = await deps.octokit.issues
|
||||
.listForRepo({
|
||||
owner: "sern-handler",
|
||||
repo,
|
||||
@@ -120,10 +120,10 @@ export default commandModule({
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
async execute(ctx, [, options]) {
|
||||
const repo = options.getString("repo", true);
|
||||
const number = options.getInteger("number", true);
|
||||
const target = options.getUser("target");
|
||||
async execute(ctx, { deps: { octokit }}) {
|
||||
const repo = ctx.options.getString("repo", true);
|
||||
const number = ctx.options.getInteger("number", true);
|
||||
const target = ctx.options.getUser("target");
|
||||
|
||||
const issue = await octokit.issues
|
||||
.get({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ownerIDs } from "#constants";
|
||||
import { commandModule, CommandType } from "@sern/handler";
|
||||
import { ActionRowBuilder, ButtonBuilder, EmbedBuilder } from "discord.js";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonComponentData, EmbedBuilder } from "discord.js";
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Button,
|
||||
@@ -17,7 +17,7 @@ export default commandModule({
|
||||
const components = [
|
||||
new ActionRowBuilder<ButtonBuilder>().setComponents(
|
||||
ctx.message!.components[0].components.map((c) =>
|
||||
new ButtonBuilder(c.data).setDisabled(),
|
||||
new ButtonBuilder(c.data as ButtonComponentData).setDisabled(),
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { commandModule, CommandType } from "@sern/handler";
|
||||
import { ActionRowBuilder, ButtonBuilder, EmbedBuilder } from "discord.js";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonComponentData, EmbedBuilder } from "discord.js";
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Modal,
|
||||
@@ -33,9 +33,7 @@ export default commandModule({
|
||||
const components = [
|
||||
new ActionRowBuilder<ButtonBuilder>().setComponents(
|
||||
ctx.message!.components[0].components.map((c) =>
|
||||
new ButtonBuilder(c.data).setDisabled(),
|
||||
),
|
||||
),
|
||||
new ButtonBuilder(c.data as Readonly<ButtonComponentData>).setDisabled())),
|
||||
];
|
||||
|
||||
const embed = new EmbedBuilder(ctx.message?.embeds[0]?.data) //
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { slashCommand } from "#utils";
|
||||
import { readFile } from "fs/promises";
|
||||
import path from "path";
|
||||
import type { Context, ReplyOptions } from "@sern/handler";
|
||||
import { ownerOnly, publish } from "#plugins";
|
||||
import * as fs from "fs";
|
||||
import { AttachmentBuilder } from "discord.js";
|
||||
|
||||
async function ephemeral(ctx: Context, options: ReplyOptions) {
|
||||
const resolvedOptions = typeof options == "string" ? { content: options } : options;
|
||||
await ctx.interaction.editReply({ ...resolvedOptions });
|
||||
}
|
||||
|
||||
export default slashCommand({
|
||||
description: "Fetch logs",
|
||||
plugins: [publish(), ownerOnly()],
|
||||
execute: async (ctx, args) => {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const logPath = path.join(process.cwd(), "error.log");
|
||||
const readHandle = readFile(logPath, { signal: controller.signal });
|
||||
await ctx.interaction.deferReply({ ephemeral: true });
|
||||
if (!fs.existsSync(logPath)) {
|
||||
controller.abort();
|
||||
}
|
||||
const log = await readHandle;
|
||||
await ephemeral(ctx, {
|
||||
files: [new AttachmentBuilder(log).setName("error.log")],
|
||||
});
|
||||
} catch (e) {
|
||||
await ephemeral(ctx, "Couldn't find log. In dev mode?");
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -19,7 +19,7 @@ export default slashCommand({
|
||||
name: "channel",
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
description: "The channel to send the message to",
|
||||
channelTypes: [ChannelType.GuildText],
|
||||
channel_types: [ChannelType.GuildText],
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
@@ -35,7 +35,8 @@ export default slashCommand({
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
async execute(ctx, [, options]) {
|
||||
async execute(ctx) {
|
||||
const options = ctx.options;
|
||||
const channel = options.getChannel("channel", true) as TextChannel;
|
||||
const role = new Resolver(options.getString("role", true), ctx.interaction).roles;
|
||||
const message = options.getString("message", true);
|
||||
|
||||
@@ -14,8 +14,7 @@ export default slashCommand({
|
||||
required: true,
|
||||
autocomplete: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
async execute(ctx) {
|
||||
async execute(ctx, deps) {
|
||||
const plugins = require(PluginList) as Plugin[];
|
||||
|
||||
const focus = ctx.options.getFocused();
|
||||
@@ -45,7 +44,8 @@ export default slashCommand({
|
||||
}),
|
||||
),
|
||||
],
|
||||
async execute(ctx, [, options]) {
|
||||
async execute(ctx) {
|
||||
const { options } = ctx;
|
||||
const plugins = require(PluginList) as Plugin[];
|
||||
|
||||
if (!plugins.length) return ctx.reply("Plugins are uncached, contact Evo!");
|
||||
|
||||
@@ -6,10 +6,8 @@ import type { Plugin } from "typings";
|
||||
|
||||
export default slashCommand({
|
||||
plugins: [
|
||||
publish({
|
||||
dmPermission: false,
|
||||
defaultMemberPermissions: ["Administrator"],
|
||||
}),
|
||||
publish({ dmPermission: false,
|
||||
defaultMemberPermissions: ["Administrator"], }),
|
||||
ownerOnly([Evo]),
|
||||
],
|
||||
description: "refresh plugins cache",
|
||||
|
||||
@@ -57,7 +57,7 @@ export default slashCommand({
|
||||
},
|
||||
],
|
||||
execute(ctx, args) {
|
||||
const [, options] = args;
|
||||
const options = ctx.options;
|
||||
const subCmd = options.getSubcommand();
|
||||
switch (subCmd) {
|
||||
case "list": {
|
||||
|
||||
@@ -96,7 +96,7 @@ export default slashCommand({
|
||||
},
|
||||
],
|
||||
execute: async (context, args) => {
|
||||
const [, options] = args;
|
||||
const { options } = context;
|
||||
const subcmd = options.getSubcommand();
|
||||
|
||||
const file: TagData[] = require(TagList);
|
||||
|
||||
@@ -49,7 +49,8 @@ export default slashCommand({
|
||||
type: ApplicationCommandOptionType.Subcommand,
|
||||
},
|
||||
],
|
||||
execute: async (ctx, [, options]) => {
|
||||
execute: async (ctx) => {
|
||||
const { options } = ctx;
|
||||
switch (options.getSubcommand()) {
|
||||
case "create": {
|
||||
const reqData = {
|
||||
|
||||
12
src/dependencies.d.ts
vendored
12
src/dependencies.d.ts
vendored
@@ -6,21 +6,17 @@
|
||||
|
||||
import type {
|
||||
SernEmitter,
|
||||
Logging,
|
||||
CoreModuleStore,
|
||||
ModuleManager,
|
||||
ErrorHandling,
|
||||
CoreDependencies,
|
||||
Singleton,
|
||||
} from "@sern/handler";
|
||||
import type { Client } from "discord.js";
|
||||
import type { SernLogger } from "./utils/Logger";
|
||||
import type { Octokit } from "@octokit/rest";
|
||||
declare global {
|
||||
interface Dependencies extends Dependencies {
|
||||
"@sern/client": Singleton<Client>;
|
||||
"@sern/logger": Singleton<SernLogger>;
|
||||
octokit: Singleton<Octokit>;
|
||||
"@sern/client": Client;
|
||||
"@sern/logger": SernLogger;
|
||||
octokit: Octokit;
|
||||
process: NodeJS.Process
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
import { eventModule, EventType } from "@sern/handler";
|
||||
import { AnyThreadChannel, EmbedBuilder } from "discord.js";
|
||||
import { onCorrectThread } from "../plugins/onCorrectThread.js";
|
||||
import { AnyThreadChannel, ChannelType, EmbedBuilder } from "discord.js";
|
||||
import { forumID } from "#constants";
|
||||
|
||||
function onCorrectThread(thread: AnyThreadChannel, parentId: string, newlyMade: boolean) {
|
||||
const isBadThread =
|
||||
!thread.parent ||
|
||||
thread.parentId !== parentId ||
|
||||
thread.parent.type !== ChannelType.GuildForum ||
|
||||
!newlyMade;
|
||||
if (!isBadThread) {
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
}
|
||||
export default eventModule({
|
||||
type: EventType.Discord,
|
||||
plugins: [onCorrectThread(forumID)],
|
||||
name: "threadCreate",
|
||||
async execute(thread: AnyThreadChannel, _: boolean) {
|
||||
async execute(thread: AnyThreadChannel, newlyMade: boolean) {
|
||||
if(!onCorrectThread(thread, forumID, newlyMade)) {
|
||||
return;
|
||||
}
|
||||
if (thread.appliedTags.length > 3)
|
||||
await thread.setAppliedTags(thread.appliedTags.slice(0, 3));
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
controller,
|
||||
EventControlPlugin,
|
||||
eventModule,
|
||||
EventType,
|
||||
Payload,
|
||||
@@ -11,8 +10,7 @@ import {
|
||||
export default eventModule({
|
||||
name: "module.activate",
|
||||
type: EventType.Sern,
|
||||
plugins: [filterFailedActivation()],
|
||||
execute(payload: Payload & { type: PayloadType.Failure }) {
|
||||
execute(payload: Payload & { type: 'failure' }) {
|
||||
const logger = Service("@sern/logger");
|
||||
logger.warning({
|
||||
message: `A module (${payload.module?.name} failed to execute: ${payload.reason}`,
|
||||
@@ -20,12 +18,3 @@ export default eventModule({
|
||||
},
|
||||
});
|
||||
|
||||
function filterFailedActivation() {
|
||||
return EventControlPlugin<EventType.Sern>((payload) => {
|
||||
if (payload.type == PayloadType.Failure) {
|
||||
return controller.next();
|
||||
} else {
|
||||
return controller.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
15
src/index.ts
15
src/index.ts
@@ -1,6 +1,6 @@
|
||||
import "dotenv/config";
|
||||
import { Client, GatewayIntentBits, Partials } from "discord.js";
|
||||
import { Sern, single, makeDependencies, Service } from "@sern/handler";
|
||||
import { Sern, makeDependencies, Service } from "@sern/handler";
|
||||
import { SernLogger } from "#utils";
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import { cp } from "./commands/refresh.js";
|
||||
@@ -21,15 +21,10 @@ const client = new Client({
|
||||
},
|
||||
});
|
||||
|
||||
await makeDependencies({
|
||||
build: (root) =>
|
||||
root
|
||||
.add({ "@sern/client": () => client })
|
||||
.upsert({ "@sern/logger": () => new SernLogger("info") })
|
||||
.add({
|
||||
process: () => process,
|
||||
octokit: () => new Octokit({ auth: process.env.GITHUB_TOKEN }),
|
||||
}),
|
||||
await makeDependencies(root => {
|
||||
root.add("@sern/client", client);
|
||||
root.swap("@sern/logger", new SernLogger("info"))
|
||||
root.add('octokit', new Octokit({ auth: process.env.GITHUB_TOKEN }))
|
||||
});
|
||||
|
||||
Sern.init({
|
||||
|
||||
@@ -1,147 +1,180 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* Allows you to set cooldowns (or "ratelimits") for commands
|
||||
* limits user/channel/guild actions,
|
||||
* @plugin
|
||||
* Allows you to set cooldowns (or "ratelimits") for commands, limits user/channel/guild actions.
|
||||
* An extra function cooldown2 is exported if you want your cooldown to be local to the command.
|
||||
* @author @trueharuu [<@504698587221852172>]
|
||||
* @version 1.0.0
|
||||
* @example
|
||||
* ```ts
|
||||
* import { cooldown } from "../plugins/cooldown";
|
||||
* import { cooldown, cooldown2 } from "../plugins/cooldown";
|
||||
* import { commandModule } from "@sern/handler";
|
||||
* //IF you want this cooldown to be local to this command:
|
||||
* const localCooldown = cooldown2()
|
||||
* export default commandModule({
|
||||
* plugins: [cooldown.add( [ ['channel', '1/4'] ] )], // limit to 1 action every 4 seconds per channel
|
||||
* execute: (ctx) => {
|
||||
* //your code here
|
||||
* }
|
||||
* plugins: [cooldown.add([['channel', '1/4']]), // limit to 1 action every 4 seconds per channel
|
||||
* localCooldown.add([["user", "1/10"]])], // limit to 1 action every 10 seconds, local to command
|
||||
* execute: (ctx) => { //your code here }
|
||||
* })
|
||||
* ```
|
||||
* @end
|
||||
*/
|
||||
|
||||
import { CommandControlPlugin, CommandType, Context, controller } from "@sern/handler";
|
||||
import {
|
||||
CommandControlPlugin,
|
||||
CommandType,
|
||||
Context,
|
||||
controller,
|
||||
} from "@sern/handler";
|
||||
import { GuildMember } from "discord.js";
|
||||
/**
|
||||
* actions/seconds
|
||||
*/
|
||||
export type CooldownString = `${number}/${number}`;
|
||||
export interface Cooldown {
|
||||
location: CooldownLocation;
|
||||
seconds: number;
|
||||
actions: number;
|
||||
location: CooldownLocation;
|
||||
seconds: number;
|
||||
actions: number;
|
||||
}
|
||||
export enum CooldownLocation {
|
||||
channel = "channel",
|
||||
user = "user",
|
||||
guild = "guild",
|
||||
channel = "channel",
|
||||
user = "user",
|
||||
guild = "guild",
|
||||
}
|
||||
|
||||
export class ExpiryMap<K, V> extends Map<K, V> {
|
||||
public readonly expiry: number;
|
||||
constructor(expiry: number = Infinity, iterable: [K, V][] | ReadonlyMap<K, V> = []) {
|
||||
super(iterable);
|
||||
this.expiry = expiry;
|
||||
}
|
||||
public readonly expiry: number;
|
||||
constructor(
|
||||
expiry: number = Infinity,
|
||||
iterable: [K, V][] | ReadonlyMap<K, V> = [],
|
||||
) {
|
||||
super(iterable);
|
||||
this.expiry = expiry;
|
||||
}
|
||||
|
||||
public set(key: K, value: V, expiry: number = this.expiry): this {
|
||||
super.set(key, value);
|
||||
if (expiry !== Infinity)
|
||||
setTimeout(() => {
|
||||
super.delete(key);
|
||||
}, expiry);
|
||||
return this;
|
||||
}
|
||||
public set(key: K, value: V, expiry: number = this.expiry): this {
|
||||
super.set(key, value);
|
||||
if (expiry !== Infinity)
|
||||
setTimeout(() => {
|
||||
super.delete(key);
|
||||
}, expiry);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export const map = new ExpiryMap<string, number>();
|
||||
|
||||
function parseCooldown(location: CooldownLocation, cooldown: CooldownString): Cooldown {
|
||||
const [actions, seconds] = cooldown.split("/").map((s) => Number(s));
|
||||
function parseCooldown(
|
||||
location: CooldownLocation,
|
||||
cooldown: CooldownString,
|
||||
): Cooldown {
|
||||
const [actions, seconds] = cooldown.split("/").map((s) => Number(s));
|
||||
|
||||
if (
|
||||
!Number.isSafeInteger(actions) ||
|
||||
!Number.isSafeInteger(seconds) ||
|
||||
actions === undefined ||
|
||||
seconds === undefined
|
||||
) {
|
||||
throw new Error(`Invalid cooldown string: ${cooldown}`);
|
||||
}
|
||||
if (
|
||||
!Number.isSafeInteger(actions) ||
|
||||
!Number.isSafeInteger(seconds) ||
|
||||
actions === undefined ||
|
||||
seconds === undefined
|
||||
) {
|
||||
throw new Error(`Invalid cooldown string: ${cooldown}`);
|
||||
}
|
||||
|
||||
return {
|
||||
actions,
|
||||
seconds,
|
||||
location,
|
||||
};
|
||||
return {
|
||||
actions,
|
||||
seconds,
|
||||
location,
|
||||
};
|
||||
}
|
||||
|
||||
function getPropertyForLocation(context: Context, location: CooldownLocation) {
|
||||
switch (location) {
|
||||
case CooldownLocation.channel:
|
||||
return context.channel!.id;
|
||||
case CooldownLocation.user:
|
||||
if (!context.member || !(context.member instanceof GuildMember)) {
|
||||
throw new Error("context.member is not a GuildMember");
|
||||
}
|
||||
return context.member.id;
|
||||
case CooldownLocation.guild:
|
||||
return context.guildId;
|
||||
}
|
||||
switch (location) {
|
||||
case CooldownLocation.channel:
|
||||
return context.channel!.id;
|
||||
case CooldownLocation.user:
|
||||
if (!context.member || !(context.member instanceof GuildMember)) {
|
||||
throw new Error("context.member is not a GuildMember");
|
||||
}
|
||||
return context.member.id;
|
||||
case CooldownLocation.guild:
|
||||
return context.guildId;
|
||||
}
|
||||
}
|
||||
|
||||
export interface RecievedCooldown {
|
||||
location: CooldownLocation;
|
||||
actions: number;
|
||||
maxActions: number;
|
||||
seconds: number;
|
||||
context: Context;
|
||||
location: CooldownLocation;
|
||||
actions: number;
|
||||
maxActions: number;
|
||||
seconds: number;
|
||||
context: Context;
|
||||
}
|
||||
type CooldownResponse = (cooldown: RecievedCooldown) => any;
|
||||
|
||||
function add(
|
||||
items: Array<[CooldownLocation | keyof typeof CooldownLocation, CooldownString] | Cooldown>,
|
||||
message?: CooldownResponse,
|
||||
) {
|
||||
const raw = items.map((c) => {
|
||||
if (!Array.isArray(c)) return c;
|
||||
return parseCooldown(c[0] as CooldownLocation, c[1]);
|
||||
}) as Array<Cooldown>;
|
||||
return CommandControlPlugin<CommandType.Both>(async (context, args) => {
|
||||
for (const { location, actions, seconds } of raw) {
|
||||
const id = getPropertyForLocation(context, location);
|
||||
const cooldown = map.get(id!);
|
||||
function __add(map : ExpiryMap<string, number>,
|
||||
items: Array<| [CooldownLocation
|
||||
| keyof typeof CooldownLocation, CooldownString]
|
||||
| Cooldown>,
|
||||
message?: CooldownResponse) {
|
||||
const raw = items.map((c) => {
|
||||
if (!Array.isArray(c)) return c;
|
||||
return parseCooldown(c[0] as CooldownLocation, c[1]);
|
||||
}) as Array<Cooldown>;
|
||||
|
||||
if (!cooldown) {
|
||||
map.set(id!, 1, seconds * 1000);
|
||||
continue;
|
||||
}
|
||||
return CommandControlPlugin<CommandType.Both>(async (context, args) => {
|
||||
for (const { location, actions, seconds } of raw) {
|
||||
const id = getPropertyForLocation(context, location);
|
||||
const cooldown = map.get(id!);
|
||||
|
||||
if (cooldown >= actions) {
|
||||
if (message) {
|
||||
await message({
|
||||
location,
|
||||
actions: cooldown,
|
||||
maxActions: actions,
|
||||
seconds,
|
||||
context,
|
||||
});
|
||||
}
|
||||
return controller.stop();
|
||||
}
|
||||
if (!cooldown) {
|
||||
map.set(id!, 1, seconds * 1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
map.set(id!, cooldown + 1, seconds * 1000);
|
||||
}
|
||||
return controller.next();
|
||||
});
|
||||
if (cooldown >= actions) {
|
||||
if (message) {
|
||||
await message({
|
||||
location,
|
||||
actions: cooldown,
|
||||
maxActions: actions,
|
||||
seconds,
|
||||
context,
|
||||
});
|
||||
}
|
||||
return controller.stop();
|
||||
}
|
||||
|
||||
map.set(id!, cooldown + 1, seconds * 1000);
|
||||
}
|
||||
return controller.next();
|
||||
});
|
||||
}
|
||||
|
||||
type Location = (value: CooldownString) => ReturnType<typeof add>;
|
||||
type Location = (value: CooldownString) => ReturnType<typeof __add>;
|
||||
|
||||
const locations: Record<CooldownLocation, Location> = {
|
||||
[CooldownLocation.channel]: (value) => add([[CooldownLocation.channel, value]]),
|
||||
[CooldownLocation.user]: (value) => add([[CooldownLocation.user, value]]),
|
||||
[CooldownLocation.guild]: (value) => add([[CooldownLocation.guild, value]]),
|
||||
const locationsFn = (map: ExpiryMap<string, number>)=> ({
|
||||
[CooldownLocation.channel]: (value) => __add(map, [[CooldownLocation.channel, value]]),
|
||||
[CooldownLocation.user]: (value) => __add(map, [[CooldownLocation.user, value]]),
|
||||
[CooldownLocation.guild]: (value) => __add(map, [[CooldownLocation.guild, value]]),
|
||||
} as Record<CooldownLocation, Location>);
|
||||
|
||||
|
||||
|
||||
export const cooldown2 = () => {
|
||||
const cooldownMap = new ExpiryMap<string, number>();
|
||||
return {
|
||||
add:(items: Array<| [CooldownLocation
|
||||
| keyof typeof CooldownLocation, CooldownString]
|
||||
| Cooldown>,
|
||||
message?: CooldownResponse) => __add(cooldownMap, items, message),
|
||||
locations: locationsFn(cooldownMap),
|
||||
map: cooldownMap
|
||||
}
|
||||
};
|
||||
|
||||
const map = new ExpiryMap<string, number>();
|
||||
export const cooldown = {
|
||||
add,
|
||||
locations,
|
||||
map,
|
||||
};
|
||||
locations: locationsFn(map),
|
||||
add: (items: Array<| [CooldownLocation
|
||||
| keyof typeof CooldownLocation, CooldownString]
|
||||
| Cooldown>,
|
||||
message?: CooldownResponse) => __add(map, items, message)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { controller, DiscordEventControlPlugin } from "@sern/handler";
|
||||
import { ChannelType } from "discord.js";
|
||||
|
||||
export function onCorrectThread(parentId: string) {
|
||||
return DiscordEventControlPlugin("threadCreate", (thread, newlyMade) => {
|
||||
const isBadThread =
|
||||
!thread.parent ||
|
||||
thread.parentId !== parentId ||
|
||||
thread.parent.type !== ChannelType.GuildForum ||
|
||||
!newlyMade;
|
||||
if (!isBadThread) {
|
||||
return controller.next();
|
||||
}
|
||||
return controller.stop();
|
||||
});
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
controller,
|
||||
SernOptionsData,
|
||||
SlashCommand,
|
||||
Service,
|
||||
} from "@sern/handler";
|
||||
import {
|
||||
ApplicationCommandData,
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// import type { SernLogger } from "./Logger";
|
||||
// import { readdir } from "fs/promises";
|
||||
// import path from "path";
|
||||
// import type { Client } from "discord.js";
|
||||
// import { ApplicationCommandType, basename } from "discord.js";
|
||||
// import type { BothCommand, CommandModule, ContextMenuMsg, ContextMenuUser, SlashCommand } from "@sern/handler";
|
||||
// import { CommandType } from "@sern/handler";
|
||||
//
|
||||
// async function* getFiles(dir: string): AsyncGenerator<string> {
|
||||
// const dirents = await readdir(dir, { withFileTypes: true });
|
||||
// for (const dirent of dirents) {
|
||||
// const res = path.resolve(dir, dirent.name);
|
||||
// if (dirent.isDirectory()) {
|
||||
// yield* getFiles(res);
|
||||
// } else {
|
||||
// yield res;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// export class CommandSyncer {
|
||||
// private commandsPath = "dist/src/commands";
|
||||
//
|
||||
// constructor(
|
||||
// private logger: SernLogger,
|
||||
// private client: Client,
|
||||
// private scopedGuilds : string[] = []
|
||||
// ) {
|
||||
// setTimeout(() => {
|
||||
// this
|
||||
// .sync()
|
||||
// .catch((e) => logger.error({ message: e ?? "Something went wrong with syncing" }));
|
||||
// }, 20_000)
|
||||
// }
|
||||
// private publishable(module: CommandModule) {
|
||||
// const publishableTypes = (CommandType.Both | CommandType.CtxUser | CommandType.CtxMsg | CommandType.Slash)
|
||||
// return ((publishableTypes & ~CommandType.Text) & module.type) != 0
|
||||
// }
|
||||
// private async handleSlashCommand(module: SlashCommand | BothCommand, resolvedName: string) {
|
||||
// this.logger.debug({ message: `Checking if ${resolvedName} is already registered` });
|
||||
// if (this.scopedGuilds.length) {
|
||||
// for (const guildId of this.scopedGuilds) {
|
||||
// const guild = await this.client.guilds.fetch(guildId).catch(() => null);
|
||||
//
|
||||
// if (!guild) throw new Error(`Found no Guild with id ${guildId}!`);
|
||||
// console.log(guild.name)
|
||||
// console.log(await guild.commands.fetch())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// private handleContextMenus(module: ContextMenuUser | ContextMenuMsg, resolvedName: string) {
|
||||
//
|
||||
// }
|
||||
// private async sync() {
|
||||
// this.logger.info({ message: "Syncing commands" });
|
||||
// for await(const path of getFiles(this.commandsPath)) {
|
||||
// const module = await import("file:///"+path).then(imp => imp.default) as CommandModule; //i would retrieve from the module store, but its a little bugged since
|
||||
// if(this.publishable(module)) {
|
||||
// const resolvedName = module.name ?? basename(path).slice(0, -3)
|
||||
// switch(module.type) {
|
||||
// case CommandType.Both:
|
||||
// case CommandType.Slash: {
|
||||
// await this.handleSlashCommand(module, resolvedName)
|
||||
// } break;
|
||||
// case CommandType.CtxMsg:
|
||||
// case CommandType.CtxUser: {
|
||||
// this.handleContextMenus(module, resolvedName)
|
||||
// } break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,22 +1,25 @@
|
||||
import {
|
||||
AnyCommandPlugin,
|
||||
BaseOptions,
|
||||
commandModule,
|
||||
CommandType,
|
||||
Context,
|
||||
SernSubCommandData,
|
||||
SernSubCommandGroupData,
|
||||
SlashOptions,
|
||||
Plugin,
|
||||
SDT,
|
||||
SlashCommand
|
||||
} from "@sern/handler";
|
||||
import { ChatInputCommandInteraction } from "discord.js";
|
||||
|
||||
export function slashCommand(data: {
|
||||
name?: string;
|
||||
description: string;
|
||||
plugins?: AnyCommandPlugin[];
|
||||
options?: (SernSubCommandData | SernSubCommandGroupData | BaseOptions)[] | undefined;
|
||||
execute: (ctx: Context, args: ["slash", SlashOptions]) => any;
|
||||
plugins?: Plugin[];
|
||||
options?: SlashCommand['options'];
|
||||
execute: (ctx: Context & { get options(): ChatInputCommandInteraction['options'] }, args: SDT) => any;
|
||||
|
||||
}) {
|
||||
//Weird fix for explicit undefined fields in an object
|
||||
const resolvedData = { type: CommandType.Slash, ...data } as const;
|
||||
return commandModule(resolvedData);
|
||||
}
|
||||
|
||||
|
||||
78
yarn.lock
78
yarn.lock
@@ -479,15 +479,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sern/handler@npm:^3.3.2":
|
||||
version: 3.3.2
|
||||
resolution: "@sern/handler@npm:3.3.2"
|
||||
"@sern/handler@npm:^4.0.0":
|
||||
version: 4.0.1
|
||||
resolution: "@sern/handler@npm:4.0.1"
|
||||
dependencies:
|
||||
"@sern/ioc": ^1.1.0
|
||||
callsites: ^3.1.0
|
||||
iti: ^0.6.0
|
||||
cron: ^3.1.7
|
||||
deepmerge: ^4.3.1
|
||||
rxjs: ^7.8.0
|
||||
ts-results-es: ^4.0.0
|
||||
checksum: a405f9f4e914245dc0c0a9091508871a2cdbb50947a71797ec4faa64ba0ec775dc8b9aa0f116c4699752520ca4b5f54b624898d7da0f53375e4534a698d0c3d4
|
||||
ts-results-es: ^4.1.0
|
||||
checksum: ab461fa953f2086b5b8ebc089078a55535d0cccd6f5b3210c45bde33022d3be1f3b47bb3ab251b129c7ed33bfe08b873416c70aace50c101ac03d0097206552a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sern/ioc@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@sern/ioc@npm:1.1.0"
|
||||
checksum: 0882ef51c3fcd28e7fe803762f2a8d7eb3dca4e494d3475ef7d4a43158d3b24243bda3679c3d58485c89bdc820719d22351007503e44b5cf8e6f2d0efe342921
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -498,6 +507,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/luxon@npm:~3.4.0":
|
||||
version: 3.4.2
|
||||
resolution: "@types/luxon@npm:3.4.2"
|
||||
checksum: 6f92d5bd02e89f310395753506bcd9cef3a56f5940f7a50db2a2b9822bce753553ac767d143cb5b4f9ed5ddd4a84e64f89ff538082ceb4d18739af7781b56925
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:*":
|
||||
version: 18.11.18
|
||||
resolution: "@types/node@npm:18.11.18"
|
||||
@@ -868,6 +884,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cron@npm:^3.1.7":
|
||||
version: 3.1.7
|
||||
resolution: "cron@npm:3.1.7"
|
||||
dependencies:
|
||||
"@types/luxon": ~3.4.0
|
||||
luxon: ~3.4.0
|
||||
checksum: d98ee5297543c138221d96dd49270bf6576db80134e6041f4ce4a3c0cb6060863d76910209b34fee66fbf134461449ec3bd283d6a76d1c50da220cde7fc10c65
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cross-spawn@npm:^7.0.3":
|
||||
version: 7.0.3
|
||||
resolution: "cross-spawn@npm:7.0.3"
|
||||
@@ -891,6 +917,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"deepmerge@npm:^4.3.1":
|
||||
version: 4.3.1
|
||||
resolution: "deepmerge@npm:4.3.1"
|
||||
checksum: 2024c6a980a1b7128084170c4cf56b0fd58a63f2da1660dcfe977415f27b17dbe5888668b59d0b063753f3220719d5e400b7f113609489c90160bb9a5518d052
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"delegates@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "delegates@npm:1.0.0"
|
||||
@@ -1485,15 +1518,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"iti@npm:^0.6.0":
|
||||
version: 0.6.0
|
||||
resolution: "iti@npm:0.6.0"
|
||||
dependencies:
|
||||
utility-types: ^3.10.0
|
||||
checksum: 19e484aa8b00bf57642c73c56b658d06d70d7b5acf5725a6aca9948c6b3c8d1fab18d71fb25f482a13d8c6acac137799fa80e7dbdc97cc24ed5afc94f03811e3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jclass@npm:^1.0.1":
|
||||
version: 1.2.1
|
||||
resolution: "jclass@npm:1.2.1"
|
||||
@@ -1593,6 +1617,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"luxon@npm:~3.4.0":
|
||||
version: 3.4.4
|
||||
resolution: "luxon@npm:3.4.4"
|
||||
checksum: 36c1f99c4796ee4bfddf7dc94fa87815add43ebc44c8934c924946260a58512f0fd2743a629302885df7f35ccbd2d13f178c15df046d0e3b6eb71db178f1c60c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"magic-bytes.js@npm:^1.5.0":
|
||||
version: 1.8.0
|
||||
resolution: "magic-bytes.js@npm:1.8.0"
|
||||
@@ -2135,7 +2166,7 @@ __metadata:
|
||||
resolution: "sern-community@workspace:."
|
||||
dependencies:
|
||||
"@octokit/rest": 19.0.7
|
||||
"@sern/handler": ^3.3.2
|
||||
"@sern/handler": ^4.0.0
|
||||
"@types/node": 18.16.3
|
||||
"@types/string-similarity": 4.0.0
|
||||
discord.js: ^14.14.1
|
||||
@@ -2445,10 +2476,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-results-es@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "ts-results-es@npm:4.0.0"
|
||||
checksum: 32a7059491e36d06c5a1084fe9be8021a0beb2d94a94b0c3fa85dc3e96561bf34fb8fd60ebe661064c9fc2bafcf437b6b65f119e8d7497af7f76cda9d9a2a945
|
||||
"ts-results-es@npm:^4.1.0":
|
||||
version: 4.2.0
|
||||
resolution: "ts-results-es@npm:4.2.0"
|
||||
checksum: ff475c2f6d44377e0204211e6eafdbcabddf3ad09d40540ad5dee3d817eefbd48c07a21f5ad86864ef82cd8a5542a266af9dd8dd4d58d4766fdd6e79370519bb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2572,13 +2603,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"utility-types@npm:^3.10.0":
|
||||
version: 3.10.0
|
||||
resolution: "utility-types@npm:3.10.0"
|
||||
checksum: 8f274415c6196ab62883b8bd98c9d2f8829b58016e4269aaa1ebd84184ac5dda7dc2ca45800c0d5e0e0650966ba063bf9a412aaeaea6850ca4440a391283d5c8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"wasm-feature-detect@npm:^1.2.11":
|
||||
version: 1.6.1
|
||||
resolution: "wasm-feature-detect@npm:1.6.1"
|
||||
|
||||
Reference in New Issue
Block a user