diff --git a/package.json b/package.json index 294fb9d8c..daace453e 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "jsdom": "^22.1.0", "libsodium-wrappers": "^0.7.13", "mathjs": "^12.1.0", + "openai": "^4.20.1", "play-dl": "^1.9.7", "r6api.js": "^4.4.1", "undici": "^5.27.2", diff --git a/settings.example.yaml b/settings.example.yaml index 41c0a537e..adac2bef7 100644 --- a/settings.example.yaml +++ b/settings.example.yaml @@ -79,6 +79,16 @@ auth: "" coinMarketCapApiKey: "" # Required for `apod` command. nasaApiKey: "DEMO_KEY" +# Required for `chat` command to use the OpenAI's ChatGPT APIs. +# API pricing depends on these values. +# For more details, check https://openai.com/pricing +openai: + apiKey: "" + # If you want to use GPT-4, set `model` to `gpt-4`. + model: "gpt-3.5-turbo" + # Change the `maxTokens` value to set the length of ChatGPT's responses. + # https://platform.openai.com/tokenizer + maxTokens: 100 # Required for `weather` command. openWeatherMapApiKey: "" # Required for `movie` and `tv` commands. diff --git a/src/commands/chat.ts b/src/commands/chat.ts new file mode 100644 index 000000000..8fd4d7bd3 --- /dev/null +++ b/src/commands/chat.ts @@ -0,0 +1,55 @@ +/*! + * @author TRACTION (iamtraction) + * @copyright 2023 + */ +import { ApplicationCommandOptionType, ChatInputCommandInteraction } from "discord.js"; +import { Client, Command } from "@bastion/tesseract"; +import OpenAI from "openai"; + +import Settings from "../utils/settings.js"; + +class ChatCommand extends Command { + constructor() { + super({ + name: "chat", + description: "Ask questions or chat with ChatGPT from OpenAI.", + owner: true, + options: [ + { + type: ApplicationCommandOptionType.String, + name: "message", + description: "Your message.", + required: true, + }, + ], + }); + } + + public async exec(interaction: ChatInputCommandInteraction<"cached">): Promise<void> { + await interaction.deferReply(); + + const message = interaction.options.getString("message"); + + const openai = new OpenAI({ + apiKey: ((interaction.client as Client).settings as Settings).get("openai").apiKey, + }); + + const response = await openai.chat.completions.create({ + model: ((interaction.client as Client).settings as Settings).get("openai").model || "gpt-3.5-turbo", + messages: [ + { + role: "user", + content: message, + }, + ], + max_tokens: ((interaction.client as Client).settings as Settings).get("openai").maxTokens || 100, + user: interaction.member.id, + }); + + await interaction.editReply({ + content: response.choices[0].message.content, + }); + } +} + +export { ChatCommand as Command }; diff --git a/src/types.ts b/src/types.ts index 6c15aff6e..9390513d4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -12,6 +12,11 @@ export namespace bastion { auth?: string; coinMarketCapApiKey?: string; nasaApiKey?: string; + openai?: { + apiKey?: string; + model?: string; + maxTokens?: number; + }; openWeatherMapApiKey?: string; tmdbApiKey?: string; trackerNetworkApiKey?: string;