Changed the buntime!

This commit is contained in:
Atridad Lahiji 2023-12-03 17:30:36 -07:00
parent 2d0e8ab106
commit 6b53e17c49
No known key found for this signature in database
20 changed files with 210 additions and 1548 deletions

View file

@ -1,10 +1,10 @@
# syntax = docker/dockerfile:1
# Adjust NODE_VERSION as desired
ARG NODE_VERSION=18.14.2
FROM node:${NODE_VERSION}-slim as base
ARG BUN_VERSION=1.0.9
FROM oven/bun:${BUN_VERSION} as base
LABEL fly_launch_runtime="Node.js"
LABEL fly_launch_runtime="Bun"
# Node.js app lives here
WORKDIR /app
@ -12,11 +12,6 @@ WORKDIR /app
# Set production environment
ENV NODE_ENV="production"
# Install pnpm
ARG PNPM_VERSION=8.9.0
RUN npm install -g pnpm@$PNPM_VERSION
# Throw-away build stage to reduce size of final image
FROM base as build
@ -25,19 +20,12 @@ RUN apt-get update -qq && \
apt-get install -y build-essential pkg-config python-is-python3
# Install node modules
COPY --link .npmrc package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod=false
COPY --link .npmrc package.json bun.lockb ./
RUN bun install --ci
# Copy application code
COPY --link . .
# Build application
RUN pnpm run build
# Remove development dependencies
RUN pnpm prune --prod
# Final stage for app image
FROM base
@ -46,4 +34,4 @@ COPY --from=build /app /app
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD [ "pnpm", "run", "start" ]
CMD [ "bun", "start" ]

BIN
bun.lockb Executable file

Binary file not shown.

View file

@ -34,10 +34,9 @@
"scripts": {
"sapphire": "sapphire",
"generate": "sapphire generate",
"build": "tsc",
"watch": "tsc -w",
"start": "node dist/index.js",
"dev": "npm run build && npm run start",
"start": "bun run src/index.ts",
"dev": "bun run src/index.ts",
"watch:start": "tsc-watch --onSuccess \"npm run start\"",
"format": "prettier --write \"src/\""
},

1082
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,19 +1,19 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Args, Command } from '@sapphire/framework';
import { AttachmentBuilder, Message, blockQuote, codeBlock } from 'discord.js';
import { Command, container } from '@sapphire/framework';
import { AttachmentBuilder, blockQuote, codeBlock } from 'discord.js';
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'You can ACTUALLY ask Himbot something! So cool!',
options: ['prompt']
})
export class UserCommand extends Command {
// Register Chat Input and Context Menu command
export class AskCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'You can ACTUALLY ask Himbot something! So cool!',
options: ['prompt']
});
}
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) =>
builder
@ -25,21 +25,10 @@ export class UserCommand extends Command {
);
}
// Message command
public async messageRun(message: Message, args: Args) {
return this.ask(message, args.getOption('prompt') || message.content.split('!ask ')[1]);
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.ask(interaction, interaction.options.getString('prompt') || 'NOTHING');
}
const prompt = interaction.options.getString('prompt');
private async ask(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction, prompt: string) {
const askMessage =
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({ content: '🤔 Thinking... 🤔' })
: await interactionOrMessage.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
await interaction.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
const chatCompletion = await openai.chat.completions.create({
model: 'gpt-4-1106-preview',
@ -64,17 +53,7 @@ export class UserCommand extends Command {
);
}
if (interactionOrMessage instanceof Message) {
return askMessage.edit({
content:
content.length < 2000
? content
: `Discord only allows messages with 2000 characters or less. Please see your response in the attached file!`,
files: messageAttachment
});
}
return interactionOrMessage.editReply({
return interaction.editReply({
content:
content.length < 2000
? content
@ -83,3 +62,9 @@ export class UserCommand extends Command {
});
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'ask',
piece: AskCommand
});

View file

@ -1,12 +1,12 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Command } from '@sapphire/framework';
import { Message } from 'discord.js';
import { Command, container } from '@sapphire/framework';
export class BorfCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'Borf! Borf!'
});
}
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'Borf! Borf!'
})
export class UserCommand extends Command {
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
// Register Chat Input command
@ -16,27 +16,20 @@ export class UserCommand extends Command {
});
}
// Message command
public async messageRun(message: Message) {
return this.sendBorf(message);
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.sendBorf(interaction);
}
private async sendBorf(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction) {
const dogResponse = await fetch('https://dog.ceo/api/breeds/image/random');
const dogData = (await dogResponse.json()) as { message: string; status: string };
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({
content: dogData?.status === 'success' ? dogData.message : 'Error: I had troubles fetching perfect puppies for you... :('
})
: await interactionOrMessage.reply({
content: dogData.status === 'success' ? dogData.message : 'Error: I had troubles fetching perfect puppies for you... :(',
fetchReply: true
});
await interaction.reply({
content: dogData.status === 'success' ? dogData.message : 'Error: I had troubles fetching perfect puppies for you... :(',
fetchReply: true
});
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'borf',
piece: BorfCommand
});

View file

@ -1,23 +1,23 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Args, BucketScope, Command } from '@sapphire/framework';
import { AttachmentBuilder, Message } from 'discord.js';
import { BucketScope, Command, container } from '@sapphire/framework';
import { AttachmentBuilder } from 'discord.js';
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'Generate an image using OpenAI! Cooldown of 10 Minutes due to cost!',
options: ['prompt'],
cooldownDelay: 480_000,
cooldownLimit: 1,
// Yes... I did hardcode myself.
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
})
export class UserCommand extends Command {
export class HDPicCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'Generate an image using OpenAI! Cooldown of 10 Minutes due to cost!',
options: ['prompt'],
cooldownDelay: 480_000,
cooldownLimit: 1,
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
});
}
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) =>
@ -30,21 +30,11 @@ export class UserCommand extends Command {
);
}
// Message command
public async messageRun(message: Message, args: Args) {
return this.pic(message, args.getOption('prompt') || 'NOTHING');
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.pic(interaction, interaction.options.getString('prompt') || 'NOTHING');
}
const prompt = interaction.options.getString('prompt') || '';
private async pic(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction, prompt: string) {
const askMessage =
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({ content: '🤔 Thinking... 🤔' })
: await interactionOrMessage.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
await interaction.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
try {
const response = await openai.images.generate({
@ -70,22 +60,20 @@ export class UserCommand extends Command {
const content = `Prompt: ${prompt}:`;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({ content, files: imageAttachment });
}
return interactionOrMessage.editReply({
return interaction.editReply({
content,
files: imageAttachment
});
} catch (error) {
const content = "Sorry, I can't complete the prompt for: " + prompt + '\n' + error;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({ content });
}
return interactionOrMessage.editReply({ content });
return interaction.editReply({ content });
}
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'hdpic',
piece: HDPicCommand
});

View file

@ -1,23 +1,24 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Args, BucketScope, Command } from '@sapphire/framework';
import { AttachmentBuilder, Message, MessageFlags } from 'discord.js';
import { BucketScope, Command, container } from '@sapphire/framework';
import { AttachmentBuilder, MessageFlags } from 'discord.js';
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'Generate "HD" TTS every 2 minutes!',
options: ['prompt'],
cooldownDelay: 200_000,
cooldownLimit: 1,
// Yes... I did hardcode myself.
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
})
export class UserCommand extends Command {
export class HDTTSCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'Generate "HD" TTS every 2 minutes!',
options: ['prompt'],
cooldownDelay: 200_000,
cooldownLimit: 1,
// Yes... I did hardcode myself.
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
});
}
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) =>
@ -28,22 +29,11 @@ export class UserCommand extends Command {
);
}
// Message command
public async messageRun(message: Message, args: Args) {
return this.tts(message, args.getOption('prompt') || 'NOTHING');
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.tts(interaction, interaction.options.getString('prompt') || 'NOTHING');
}
private async tts(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction, prompt: string) {
const askMessage =
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({ content: '🤔 Thinking... 🤔' })
: await interactionOrMessage.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
const prompt = interaction.options.getString('prompt') || 'NOTHING';
await interaction.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
try {
enum voice {
alloy = 'alloy',
@ -73,15 +63,7 @@ export class UserCommand extends Command {
const content = `Prompt: ${prompt}:`;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({
content,
files: mp3Attachment,
flags: '8192'
});
}
return interactionOrMessage.editReply({
return interaction.editReply({
content,
files: mp3Attachment,
options: {
@ -91,15 +73,15 @@ export class UserCommand extends Command {
} catch (error) {
const content = "Sorry, I can't complete the prompt for: " + prompt + '\n' + error;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({
content
});
}
return interactionOrMessage.editReply({
return interaction.editReply({
content
});
}
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'hdtts',
piece: HDTTSCommand
});

View file

@ -1,13 +1,13 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Args, Command } from '@sapphire/framework';
import { Message } from 'discord.js';
import { Command, container } from '@sapphire/framework';
export class HighSchoolCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'This command was your nickname in highschool!',
options: ['nickname']
});
}
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'This command was your nickname in highschool!',
options: ['nickname']
})
export class UserCommand extends Command {
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) =>
@ -18,27 +18,18 @@ export class UserCommand extends Command {
);
}
// Message command
public async messageRun(message: Message, args: Args) {
return this.sendPing(message, args.getOption('nickname') || message.content.split('!wryna ')[1]);
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.sendPing(interaction, interaction.options.getString('nickname') || 'NOTHING');
}
private async sendPing(
interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction,
nickname: string
) {
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({
content: `${nickname} was ${interactionOrMessage.author.username}'s nickname in highschool!`
})
: await interactionOrMessage.reply({
content: `${nickname} was ${interactionOrMessage.user.username}'s nickname in highschool!`,
fetchReply: true
});
const nickname = interaction.options.getString('nickname') || 'NOTHING';
await interaction.reply({
content: `${nickname} was ${interaction.user.username}'s nickname in highschool!`,
fetchReply: true
});
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'hs',
piece: HighSchoolCommand
});

View file

@ -1,24 +1,24 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Args, BucketScope, Command } from '@sapphire/framework';
import { AttachmentBuilder, Message } from 'discord.js';
import { BucketScope, Command, container } from '@sapphire/framework';
import { AttachmentBuilder } from 'discord.js';
import Replicate from 'replicate';
const replicate = new Replicate({
auth: process.env.REPLICATE_API_TOKEN
});
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'Generate an image using Stability AI! Cooldown 1 Minute to prevent spam!',
options: ['prompt'],
// 10mins
cooldownDelay: 100_000,
cooldownLimit: 1,
// Yes... I did hardcode myself.
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
})
export class UserCommand extends Command {
export class PicCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'Generate an image using Stability AI! Cooldown 1 Minute to prevent spam!',
options: ['prompt'],
cooldownDelay: 100_000,
cooldownLimit: 1,
// Yes... I did hardcode myself.
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
});
}
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) =>
@ -31,21 +31,11 @@ export class UserCommand extends Command {
);
}
// Message command
public async messageRun(message: Message, args: Args) {
return this.picHr(message, args.getOption('prompt') || 'Scold me for not passing any prompt in.');
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.picHr(interaction, interaction.options.getString('prompt') || 'NOTHING');
}
const prompt = interaction.options.getString('prompt') || 'NOTHING';
private async picHr(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction, prompt: string) {
const askMessage =
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({ content: '🤔 Thinking... 🤔' })
: await interactionOrMessage.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
await interaction.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
let result = (await replicate.run('stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b', {
input: {
@ -66,11 +56,7 @@ export class UserCommand extends Command {
if (result.length <= 0) {
const content = `Sorry, I can't complete the prompt for: ${prompt}`;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({ content });
}
return interactionOrMessage.editReply({
return interaction.editReply({
content: content
});
} else {
@ -89,14 +75,16 @@ export class UserCommand extends Command {
const content = `Prompt: ${prompt}`;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({ content, files: imageAttachment });
}
return interactionOrMessage.editReply({
return interaction.editReply({
content,
files: imageAttachment
});
}
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'pic',
piece: PicCommand
});

View file

@ -1,47 +0,0 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Command } from '@sapphire/framework';
import { Message } from 'discord.js';
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'Pong!'
})
export class UserCommand extends Command {
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
// Register Chat Input command
registry.registerChatInputCommand({
name: this.name,
description: this.description
});
}
// Message command
public async messageRun(message: Message) {
return this.sendPing(message);
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.sendPing(interaction);
}
private async sendPing(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction) {
const pingMessage =
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({ content: 'Ping?' })
: await interactionOrMessage.reply({ content: 'Ping?', fetchReply: true });
const content = `Pong! Bot Latency ${Math.round(this.container.client.ws.ping)}ms. API Latency ${
pingMessage.createdTimestamp - interactionOrMessage.createdTimestamp
}ms.`;
if (interactionOrMessage instanceof Message) {
return pingMessage.edit({ content });
}
return interactionOrMessage.editReply({
content: content
});
}
}

View file

@ -1,42 +0,0 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Command } from '@sapphire/framework';
import { Message } from 'discord.js';
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'Quack!'
})
export class UserCommand extends Command {
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
// Register Chat Input command
registry.registerChatInputCommand({
name: this.name,
description: this.description
});
}
// Message command
public async messageRun(message: Message) {
return this.sendQuack(message);
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.sendQuack(interaction);
}
private async sendQuack(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction) {
const duckResponse = await fetch('https://random-d.uk/api/v2/quack');
const duckData = (await duckResponse.json()) as { url: string };
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({
content: duckData.url
})
: await interactionOrMessage.reply({
content: duckData.url,
fetchReply: true
});
}
}

View file

@ -1,35 +0,0 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Command } from '@sapphire/framework';
import { Message } from 'discord.js';
// @ts-ignore
@ApplyOptions<Command.Options>({
description: "Help support HimBot's AI features."
})
export class UserCommand extends Command {
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => builder.setName(this.name).setDescription(this.description));
}
// Message command
public async messageRun(message: Message) {
return this.sendSupport(message);
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.sendSupport(interaction);
}
private async sendSupport(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction) {
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({
content: 'Thanks! The link to donate is here: https://buy.stripe.com/eVa6p95ho0Kn33a8wx'
})
: await interactionOrMessage.reply({
content: 'Thanks! The link to donate is here: https://buy.stripe.com/eVa6p95ho0Kn33a8wx',
fetchReply: true
});
}
}

View file

@ -1,13 +1,13 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Args, Command } from '@sapphire/framework';
import { Message } from 'discord.js';
import { Command, container } from '@sapphire/framework';
export class TitleCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'This command is the title of your sextape.',
options: ['title']
});
}
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'This command is the title of your sextape.',
options: ['title']
})
export class UserCommand extends Command {
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) =>
@ -18,27 +18,19 @@ export class UserCommand extends Command {
);
}
// Message command
public async messageRun(message: Message, args: Args) {
return this.titleHandler(message, args.getOption('title') || message.content.split('!title ')[1]);
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.titleHandler(interaction, interaction.options.getString('title') || 'NOTHING');
}
const title = interaction.options.getString('title') || 'NOTHING';
private async titleHandler(
interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction,
title: string
) {
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({
content: `${title}: Title of ${interactionOrMessage.author.username}'s sex tape!`
})
: await interactionOrMessage.reply({
content: `${title}: Title of ${interactionOrMessage.user.username}'s sex tape!`,
fetchReply: true
});
await interaction.reply({
content: `${title}: Title of ${interaction.user.username}'s sex tape!`,
fetchReply: true
});
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'title',
piece: TitleCommand
});

View file

@ -1,23 +1,24 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Args, BucketScope, Command } from '@sapphire/framework';
import { AttachmentBuilder, Message, MessageFlags } from 'discord.js';
import { BucketScope, Command, container } from '@sapphire/framework';
import { AttachmentBuilder, MessageFlags } from 'discord.js';
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
// @ts-ignore
@ApplyOptions<Command.Options>({
description: 'Generate TTS every minute!',
options: ['prompt'],
cooldownDelay: 100_000,
cooldownLimit: 1,
// Yes... I did hardcode myself.
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
})
export class UserCommand extends Command {
export class TTSCommand extends Command {
public constructor(context: Command.LoaderContext) {
super(context, {
description: 'Generate TTS every minute!',
options: ['prompt'],
cooldownDelay: 100_000,
cooldownLimit: 1,
// Yes... I did hardcode myself.
cooldownFilteredUsers: ['83679718401904640'],
cooldownScope: BucketScope.User
});
}
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) =>
@ -28,21 +29,11 @@ export class UserCommand extends Command {
);
}
// Message command
public async messageRun(message: Message, args: Args) {
return this.tts(message, args.getOption('prompt') || 'NOTHING');
}
// Chat Input (slash) command
public async chatInputRun(interaction: Command.ChatInputCommandInteraction) {
return this.tts(interaction, interaction.options.getString('prompt') || 'NOTHING');
}
const prompt = interaction.options.getString('prompt') || 'NOTHING';
private async tts(interactionOrMessage: Message | Command.ChatInputCommandInteraction | Command.ContextMenuCommandInteraction, prompt: string) {
const askMessage =
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({ content: '🤔 Thinking... 🤔' })
: await interactionOrMessage.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
await interaction.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
try {
enum voice {
@ -73,15 +64,7 @@ export class UserCommand extends Command {
const content = `Prompt: ${prompt}:`;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({
content,
files: mp3Attachment,
flags: '8192'
});
}
return interactionOrMessage.editReply({
return interaction.editReply({
content,
files: mp3Attachment,
options: {
@ -91,15 +74,15 @@ export class UserCommand extends Command {
} catch (error) {
const content = "Sorry, I can't complete the prompt for: " + prompt + '\n' + error;
if (interactionOrMessage instanceof Message) {
return askMessage.edit({
content
});
}
return interactionOrMessage.editReply({
return interaction.editReply({
content
});
}
}
}
void container.stores.loadPiece({
store: 'commands',
name: 'tts',
piece: TTSCommand
});

View file

@ -1,4 +1,14 @@
import './lib/setup';
import './listeners/ready';
import './commands/ask';
import './commands/borf';
import './commands/hdpic';
import './commands/hdtts';
import './commands/hs';
import './commands/pic';
import './commands/title';
import './commands/tts';
import './listeners/commands/chatInputCommands/chatInputCommandSuccess';
import { LogLevel, SapphireClient, BucketScope } from '@sapphire/framework';
import { ActivityType, GatewayIntentBits } from 'discord.js';
@ -18,7 +28,6 @@ const client = new SapphireClient({
level: LogLevel.Debug
},
intents: [GatewayIntentBits.DirectMessages, GatewayIntentBits.GuildMessages, GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent],
loadMessageCommandListeners: true,
defaultCooldown: {
// 10s
delay: 10_000,
@ -27,7 +36,8 @@ const client = new SapphireClient({
// Yes... I did hardcode myself.
filteredUsers: ['83679718401904640'],
scope: BucketScope.User
}
},
baseUserDirectory: null
});
const main = async () => {

View file

@ -1,21 +1,11 @@
import {
container,
type ChatInputCommandSuccessPayload,
type Command,
type ContextMenuCommandSuccessPayload,
type MessageCommandSuccessPayload
} from '@sapphire/framework';
import { container, type ChatInputCommandSuccessPayload, type Command, type ContextMenuCommandSuccessPayload } from '@sapphire/framework';
import { cyan } from 'colorette';
import type { APIUser, Guild, User } from 'discord.js';
export function logSuccessCommand(payload: ContextMenuCommandSuccessPayload | ChatInputCommandSuccessPayload | MessageCommandSuccessPayload): void {
export function logSuccessCommand(payload: ContextMenuCommandSuccessPayload | ChatInputCommandSuccessPayload): void {
let successLoggerData: ReturnType<typeof getSuccessLoggerData>;
if ('interaction' in payload) {
successLoggerData = getSuccessLoggerData(payload.interaction.guild, payload.interaction.user, payload.command);
} else {
successLoggerData = getSuccessLoggerData(payload.message.guild, payload.message.author, payload.command);
}
successLoggerData = getSuccessLoggerData(payload.interaction.guild, payload.interaction.user, payload.command);
container.logger.debug(`${successLoggerData.shard} - ${successLoggerData.commandName} ${successLoggerData.author} ${successLoggerData.sentAt}`);
}

View file

@ -1,12 +0,0 @@
import type { Events, MessageCommandDeniedPayload } from '@sapphire/framework';
import { Listener, type UserError } from '@sapphire/framework';
export class UserEvent extends Listener<typeof Events.MessageCommandDenied> {
public async run({ context, message: content }: UserError, { message }: MessageCommandDeniedPayload) {
// `context: { silent: true }` should make UserError silent:
// Use cases for this are for example permissions error when running the `eval` command.
if (Reflect.get(Object(context), 'silent')) return;
return message.reply({ content, allowedMentions: { users: [message.author.id], roles: [] } });
}
}

View file

@ -1,15 +0,0 @@
import type { MessageCommandSuccessPayload } from '@sapphire/framework';
import { Listener, LogLevel } from '@sapphire/framework';
import type { Logger } from '@sapphire/plugin-logger';
import { logSuccessCommand } from '../../../lib/utils';
export class UserEvent extends Listener {
public run(payload: MessageCommandSuccessPayload) {
logSuccessCommand(payload);
}
public onLoad() {
this.enabled = (this.container.logger as Logger).level <= LogLevel.Debug;
return super.onLoad();
}
}

View file

@ -1,5 +1,5 @@
import { ApplyOptions } from '@sapphire/decorators';
import { Listener, Store } from '@sapphire/framework';
import { Listener, Store, container } from '@sapphire/framework';
import { blue, gray, green, magenta, magentaBright, white, yellow } from 'colorette';
const dev = process.env.NODE_ENV !== 'production';
@ -41,11 +41,17 @@ ${line03}${dev ? ` ${pad}${blc('<')}${llc('/')}${blc('>')} ${llc('DEVELOPMENT MO
const stores = [...client.stores.values()];
const last = stores.pop()!;
for (const store of stores) logger.info(this.styleStore(store, false));
logger.info(this.styleStore(last, true));
for (const store of stores) logger.info(this.styleStore(store));
logger.info(this.styleStore(last));
}
private styleStore(store: Store<any>, last: boolean) {
return gray(`${last ? '└─' : '├─'} Loaded ${this.style(store.size.toString().padEnd(3, ' '))} ${store.name}.`);
private styleStore(store: Store<any>) {
return gray(`${'└─'} Loaded ${this.style(store.size.toString().padEnd(3, ' '))} ${store.name}.`);
}
}
void container.stores.loadPiece({
piece: UserEvent,
name: 'ready',
store: 'listeners'
});