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 # syntax = docker/dockerfile:1
# Adjust NODE_VERSION as desired # Adjust NODE_VERSION as desired
ARG NODE_VERSION=18.14.2 ARG BUN_VERSION=1.0.9
FROM node:${NODE_VERSION}-slim as base FROM oven/bun:${BUN_VERSION} as base
LABEL fly_launch_runtime="Node.js" LABEL fly_launch_runtime="Bun"
# Node.js app lives here # Node.js app lives here
WORKDIR /app WORKDIR /app
@ -12,11 +12,6 @@ WORKDIR /app
# Set production environment # Set production environment
ENV NODE_ENV="production" 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 # Throw-away build stage to reduce size of final image
FROM base as build FROM base as build
@ -25,19 +20,12 @@ RUN apt-get update -qq && \
apt-get install -y build-essential pkg-config python-is-python3 apt-get install -y build-essential pkg-config python-is-python3
# Install node modules # Install node modules
COPY --link .npmrc package.json pnpm-lock.yaml ./ COPY --link .npmrc package.json bun.lockb ./
RUN pnpm install --frozen-lockfile --prod=false RUN bun install --ci
# Copy application code # Copy application code
COPY --link . . COPY --link . .
# Build application
RUN pnpm run build
# Remove development dependencies
RUN pnpm prune --prod
# Final stage for app image # Final stage for app image
FROM base FROM base
@ -46,4 +34,4 @@ COPY --from=build /app /app
# Start the server by default, this can be overwritten at runtime # Start the server by default, this can be overwritten at runtime
EXPOSE 3000 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": { "scripts": {
"sapphire": "sapphire", "sapphire": "sapphire",
"generate": "sapphire generate", "generate": "sapphire generate",
"build": "tsc",
"watch": "tsc -w", "watch": "tsc -w",
"start": "node dist/index.js", "start": "bun run src/index.ts",
"dev": "npm run build && npm run start", "dev": "bun run src/index.ts",
"watch:start": "tsc-watch --onSuccess \"npm run start\"", "watch:start": "tsc-watch --onSuccess \"npm run start\"",
"format": "prettier --write \"src/\"" "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 { Command, container } from '@sapphire/framework';
import { Args, Command } from '@sapphire/framework'; import { AttachmentBuilder, blockQuote, codeBlock } from 'discord.js';
import { AttachmentBuilder, Message, blockQuote, codeBlock } from 'discord.js';
import OpenAI from 'openai'; import OpenAI from 'openai';
const openai = new OpenAI({ const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY apiKey: process.env.OPENAI_API_KEY
}); });
// @ts-ignore export class AskCommand extends Command {
@ApplyOptions<Command.Options>({ public constructor(context: Command.LoaderContext) {
super(context, {
description: 'You can ACTUALLY ask Himbot something! So cool!', description: 'You can ACTUALLY ask Himbot something! So cool!',
options: ['prompt'] options: ['prompt']
}) });
export class UserCommand extends Command { }
// Register Chat Input and Context Menu command
public override registerApplicationCommands(registry: Command.Registry) { public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => registry.registerChatInputCommand((builder) =>
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) { 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) { await interaction.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
const askMessage =
interactionOrMessage instanceof Message
? await interactionOrMessage.channel.send({ content: '🤔 Thinking... 🤔' })
: await interactionOrMessage.reply({ content: '🤔 Thinking... 🤔', fetchReply: true });
const chatCompletion = await openai.chat.completions.create({ const chatCompletion = await openai.chat.completions.create({
model: 'gpt-4-1106-preview', model: 'gpt-4-1106-preview',
@ -64,8 +53,7 @@ export class UserCommand extends Command {
); );
} }
if (interactionOrMessage instanceof Message) { return interaction.editReply({
return askMessage.edit({
content: content:
content.length < 2000 content.length < 2000
? content ? content
@ -73,13 +61,10 @@ export class UserCommand extends Command {
files: messageAttachment files: messageAttachment
}); });
} }
}
return interactionOrMessage.editReply({ void container.stores.loadPiece({
content: store: 'commands',
content.length < 2000 name: 'ask',
? content piece: AskCommand
: `Discord only allows messages with 2000 characters or less. Please see your response in the attached file!`,
files: messageAttachment
}); });
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,14 @@
import './lib/setup'; 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 { LogLevel, SapphireClient, BucketScope } from '@sapphire/framework';
import { ActivityType, GatewayIntentBits } from 'discord.js'; import { ActivityType, GatewayIntentBits } from 'discord.js';
@ -18,7 +28,6 @@ const client = new SapphireClient({
level: LogLevel.Debug level: LogLevel.Debug
}, },
intents: [GatewayIntentBits.DirectMessages, GatewayIntentBits.GuildMessages, GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent], intents: [GatewayIntentBits.DirectMessages, GatewayIntentBits.GuildMessages, GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent],
loadMessageCommandListeners: true,
defaultCooldown: { defaultCooldown: {
// 10s // 10s
delay: 10_000, delay: 10_000,
@ -27,7 +36,8 @@ const client = new SapphireClient({
// Yes... I did hardcode myself. // Yes... I did hardcode myself.
filteredUsers: ['83679718401904640'], filteredUsers: ['83679718401904640'],
scope: BucketScope.User scope: BucketScope.User
} },
baseUserDirectory: null
}); });
const main = async () => { const main = async () => {

View file

@ -1,21 +1,11 @@
import { import { container, type ChatInputCommandSuccessPayload, type Command, type ContextMenuCommandSuccessPayload } from '@sapphire/framework';
container,
type ChatInputCommandSuccessPayload,
type Command,
type ContextMenuCommandSuccessPayload,
type MessageCommandSuccessPayload
} from '@sapphire/framework';
import { cyan } from 'colorette'; import { cyan } from 'colorette';
import type { APIUser, Guild, User } from 'discord.js'; 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>; let successLoggerData: ReturnType<typeof getSuccessLoggerData>;
if ('interaction' in payload) {
successLoggerData = getSuccessLoggerData(payload.interaction.guild, payload.interaction.user, payload.command); successLoggerData = getSuccessLoggerData(payload.interaction.guild, payload.interaction.user, payload.command);
} else {
successLoggerData = getSuccessLoggerData(payload.message.guild, payload.message.author, payload.command);
}
container.logger.debug(`${successLoggerData.shard} - ${successLoggerData.commandName} ${successLoggerData.author} ${successLoggerData.sentAt}`); 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 { 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'; import { blue, gray, green, magenta, magentaBright, white, yellow } from 'colorette';
const dev = process.env.NODE_ENV !== 'production'; 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 stores = [...client.stores.values()];
const last = stores.pop()!; const last = stores.pop()!;
for (const store of stores) logger.info(this.styleStore(store, false)); for (const store of stores) logger.info(this.styleStore(store));
logger.info(this.styleStore(last, true)); logger.info(this.styleStore(last));
} }
private styleStore(store: Store<any>, last: boolean) { private styleStore(store: Store<any>) {
return gray(`${last ? '└─' : '├─'} Loaded ${this.style(store.size.toString().padEnd(3, ' '))} ${store.name}.`); return gray(`${'└─'} Loaded ${this.style(store.size.toString().padEnd(3, ' '))} ${store.name}.`);
} }
} }
void container.stores.loadPiece({
piece: UserEvent,
name: 'ready',
store: 'listeners'
});