diff --git a/README.md b/README.md index eb06d96..0059ef3 100644 --- a/README.md +++ b/README.md @@ -23,95 +23,3 @@ Commands and Listeners are all stored in named files within the src/commands and Use the following link (replacing DISCORD_CLIENT_ID with your own bot's client ID of course...) to add your bot: https://discord.com/oauth2/authorize?client_id=DISCORD_CLIENT_ID&scope=bot&permissions=8 - -## Commands - -### **ask** - -##### Description - -A command that returns the answer to your prompt for OpenAI's GPT 4.0 turbo model. - -#### Usage - -`/ask prompt:prompt_text` - -### **borf** - -#### Description - -A command that returns a random picture of a dog. - -#### Usage - -`/borf` - -### **dad** - -#### Description - -A command that returns a random dad joke. - -#### Usage - -`/dad` - -### **fancypic** - -#### Description - -A command that return an image using DALL.E with "hd" quality. - -#### Usage - -`/fancypic prompt` - -### **pic** - -#### Description - -A command that return an image using DALL.E with "standard" quality. - -#### Usage - -`/pic prompt` - -### **ping** - -#### Description - -A command that returns the latency for the bot, and the latency for the Discord API. Useful for bot debugging. - -#### Usage - -`/ping` - -### **quack** - -#### Description - -A command that returns a random picture of a duck. - -#### Usage - -`/quack` - -### **support** - -#### Description - -A command that returns a Stripe link that can be used to fund credits for the AI commands. - -#### Usage - -`/support` - -### **hs** - -#### Description - -A command that returns "my nickname in highschool" response given your prompt - -#### Usage - -`/hs nickname:butts` diff --git a/src/commands/fancytts.ts b/src/commands/fancytts.ts new file mode 100644 index 0000000..3e49d8a --- /dev/null +++ b/src/commands/fancytts.ts @@ -0,0 +1,95 @@ +import { ApplyOptions } from '@sapphire/decorators'; +import { Args, BucketScope, Command } from '@sapphire/framework'; +import { AttachmentBuilder, Message, MessageFlags } from 'discord.js'; +import OpenAI from 'openai'; + +const openai = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY +}); + +// @ts-ignore +@ApplyOptions({ + 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 { + // Register Chat Input and Context Menu command + public override registerApplicationCommands(registry: Command.Registry) { + registry.registerChatInputCommand((builder) => + builder + .setName(this.name) + .setDescription(this.description) + .addStringOption((option) => option.setName('prompt').setDescription('The prompt you will use to generate audio!').setRequired(true)) + ); + } + + // 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 }); + + try { + const mp3 = await openai.audio.speech.create({ + model: 'tts-1-hd', + voice: 'shimmer', + input: prompt + }); + const mp3Buffer = Buffer.from(await mp3.arrayBuffer()); + + const mp3Attachment: AttachmentBuilder[] = []; + + mp3Attachment.push( + new AttachmentBuilder(Buffer.from(new Uint8Array(mp3Buffer)), { + name: 'himbot_response.mp3', + description: `An TTS message generated by Himbot using the prompt: ${prompt}` + }) + ); + + const content = `Prompt: ${prompt}:`; + + if (interactionOrMessage instanceof Message) { + return askMessage.edit({ + content, + files: mp3Attachment, + flags: '8192' + }); + } + + return interactionOrMessage.editReply({ + content, + files: mp3Attachment, + options: { + flags: MessageFlags.IsVoiceMessage.valueOf() + } + }); + } 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 + }); + } + } +}