feat: command to login into character.ai
This commit is contained in:
parent
3c04b034f9
commit
18c02e98f3
12 changed files with 199 additions and 71 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
.env
|
.env
|
||||||
|
cai.token
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"dev": "deno run --watch --allow-env --allow-read=. --allow-net --env-file main.ts",
|
"dev": "deno run --watch --allow-env --allow-read=. --allow-net --env-file ./src/main.ts",
|
||||||
"deployCommands": "deno run --env-file --allow-env --allow-net --allow-read=./commands scripts/deployCommands.ts"
|
"deployCommands": "deno run --env-file --allow-env --allow-net --allow-read=./src/ scripts/deployCommands.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
74
deno.lock
generated
74
deno.lock
generated
|
|
@ -1,16 +1,28 @@
|
||||||
{
|
{
|
||||||
"version": "4",
|
"version": "5",
|
||||||
"specifiers": {
|
"specifiers": {
|
||||||
|
"jsr:@std/fs@*": "1.0.18",
|
||||||
"jsr:@std/path@*": "1.1.0",
|
"jsr:@std/path@*": "1.1.0",
|
||||||
|
"jsr:@std/path@^1.1.0": "1.1.0",
|
||||||
"npm:@types/node@*": "22.12.0",
|
"npm:@types/node@*": "22.12.0",
|
||||||
|
"npm:cainode@latest": "1.2.2",
|
||||||
"npm:discord.js@*": "14.20.0"
|
"npm:discord.js@*": "14.20.0"
|
||||||
},
|
},
|
||||||
"jsr": {
|
"jsr": {
|
||||||
|
"@std/fs@1.0.18": {
|
||||||
|
"integrity": "24bcad99eab1af4fde75e05da6e9ed0e0dce5edb71b7e34baacf86ffe3969f3a",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/path@^1.1.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
"@std/path@1.1.0": {
|
"@std/path@1.1.0": {
|
||||||
"integrity": "ddc94f8e3c275627281cbc23341df6b8bcc874d70374f75fec2533521e3d6886"
|
"integrity": "ddc94f8e3c275627281cbc23341df6b8bcc874d70374f75fec2533521e3d6886"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npm": {
|
"npm": {
|
||||||
|
"@bufbuild/protobuf@2.5.2": {
|
||||||
|
"integrity": "sha512-foZ7qr0IsUBjzWIq+SuBLfdQCpJ1j8cTuNNT4owngTHoN5KsJb8L9t65fzz7SCeSWzescoOil/0ldqiL041ABg=="
|
||||||
|
},
|
||||||
"@discordjs/builders@1.11.2": {
|
"@discordjs/builders@1.11.2": {
|
||||||
"integrity": "sha512-F1WTABdd8/R9D1icJzajC4IuLyyS8f3rTOz66JsSI3pKvpCAtsMBweu8cyNYsIyvcrKAVn9EPK+Psoymq+XC0A==",
|
"integrity": "sha512-F1WTABdd8/R9D1icJzajC4IuLyyS8f3rTOz66JsSI3pKvpCAtsMBweu8cyNYsIyvcrKAVn9EPK+Psoymq+XC0A==",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
@ -66,6 +78,52 @@
|
||||||
"ws"
|
"ws"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"@livekit/mutex@1.1.1": {
|
||||||
|
"integrity": "sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw=="
|
||||||
|
},
|
||||||
|
"@livekit/rtc-node-darwin-arm64@0.11.1": {
|
||||||
|
"integrity": "sha512-M+Ui87H06ae19GGI7r937dS6hI84MBBTQAkkNlL7qd+pvdCAk25u0FYa8r4SOElKJ0VR3AbzeDoXTihLgpvjMg==",
|
||||||
|
"os": ["darwin"],
|
||||||
|
"cpu": ["arm64"]
|
||||||
|
},
|
||||||
|
"@livekit/rtc-node-darwin-x64@0.11.1": {
|
||||||
|
"integrity": "sha512-7G92fyuK2p+jdTH2cUJTNeAmtknTGsXuy0xbI727V7VzQvHFDXULCExRlgwn4t9TxvNlIjUpiltiQ6RCSai6zw==",
|
||||||
|
"os": ["darwin"],
|
||||||
|
"cpu": ["x64"]
|
||||||
|
},
|
||||||
|
"@livekit/rtc-node-linux-arm64-gnu@0.11.1": {
|
||||||
|
"integrity": "sha512-vqZN9+87Pvxit7auYVW69M+GvUPnf+EwipIJ92GgCJA3Ir1Tcceu5ud5/Ic+0FzSoV0cotVVlQNm74F0tQvyCg==",
|
||||||
|
"os": ["linux"],
|
||||||
|
"cpu": ["arm64"]
|
||||||
|
},
|
||||||
|
"@livekit/rtc-node-linux-x64-gnu@0.11.1": {
|
||||||
|
"integrity": "sha512-smHZUMfgILQh6/eoauYNe/VlKwQCp4/4jWxiIADHY+mtDtVSvQ9zB6y4GP8FrpohRwFWesKCUpvPBypU0Icrng==",
|
||||||
|
"os": ["linux"],
|
||||||
|
"cpu": ["x64"]
|
||||||
|
},
|
||||||
|
"@livekit/rtc-node-win32-x64-msvc@0.11.1": {
|
||||||
|
"integrity": "sha512-bTWVtb+UiRPFjiuhrqq40gt5vs5mMPTa1e+kd2jGQPTOlKZPLArQ0WgFcep2TAy1zmcpOgfeM1XRPVFhZl7G1A==",
|
||||||
|
"os": ["win32"],
|
||||||
|
"cpu": ["x64"]
|
||||||
|
},
|
||||||
|
"@livekit/rtc-node@0.11.1": {
|
||||||
|
"integrity": "sha512-EFw+giPll12fcXATZpN2zKkE3umYJAdHvfjW+Yu0aBjwfxbUBXu8rz6le2CzDNvGmRwR888DSZXFZfYikwZgiw==",
|
||||||
|
"dependencies": [
|
||||||
|
"@bufbuild/protobuf",
|
||||||
|
"@livekit/mutex",
|
||||||
|
"@livekit/typed-emitter"
|
||||||
|
],
|
||||||
|
"optionalDependencies": [
|
||||||
|
"@livekit/rtc-node-darwin-arm64",
|
||||||
|
"@livekit/rtc-node-darwin-x64",
|
||||||
|
"@livekit/rtc-node-linux-arm64-gnu",
|
||||||
|
"@livekit/rtc-node-linux-x64-gnu",
|
||||||
|
"@livekit/rtc-node-win32-x64-msvc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@livekit/typed-emitter@3.0.0": {
|
||||||
|
"integrity": "sha512-9bl0k4MgBPZu3Qu3R3xy12rmbW17e3bE9yf4YY85gJIQ3ezLEj/uzpKHWBsLaDoL5Mozz8QCgggwIBudYQWeQg=="
|
||||||
|
},
|
||||||
"@sapphire/async-queue@1.5.5": {
|
"@sapphire/async-queue@1.5.5": {
|
||||||
"integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="
|
"integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="
|
||||||
},
|
},
|
||||||
|
|
@ -94,6 +152,14 @@
|
||||||
"@vladfrangu/async_event_emitter@2.4.6": {
|
"@vladfrangu/async_event_emitter@2.4.6": {
|
||||||
"integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="
|
"integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="
|
||||||
},
|
},
|
||||||
|
"cainode@1.2.2": {
|
||||||
|
"integrity": "sha512-x73+JgjAJOjuNJYpRXqbET86sDuEY8pcCmC55oCZWi3Vfh9wxoPWWldTxWhmuYD2A71jGNu20UB8A70nf3Q43A==",
|
||||||
|
"optionalDependencies": [
|
||||||
|
"@livekit/rtc-node",
|
||||||
|
"ws"
|
||||||
|
],
|
||||||
|
"scripts": true
|
||||||
|
},
|
||||||
"discord-api-types@0.38.12": {
|
"discord-api-types@0.38.12": {
|
||||||
"integrity": "sha512-vqkRM50N5Zc6OVckAqtSslbUEoXmpN4bd9xq2jkoK9fgO3KNRIOyMMQ7ipqjwjKuAgzWvU6G8bRIcYWaUe1sCA=="
|
"integrity": "sha512-vqkRM50N5Zc6OVckAqtSslbUEoXmpN4bd9xq2jkoK9fgO3KNRIOyMMQ7ipqjwjKuAgzWvU6G8bRIcYWaUe1sCA=="
|
||||||
},
|
},
|
||||||
|
|
@ -140,7 +206,11 @@
|
||||||
"integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="
|
"integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="
|
||||||
},
|
},
|
||||||
"ws@8.18.2": {
|
"ws@8.18.2": {
|
||||||
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ=="
|
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
||||||
|
"optionalPeers": [
|
||||||
|
"bufferutil@^4.0.1",
|
||||||
|
"utf-8-validate@>=5.0.2"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
main.ts
64
main.ts
|
|
@ -1,64 +0,0 @@
|
||||||
import {
|
|
||||||
Client as _client,
|
|
||||||
ClientOptions,
|
|
||||||
Collection,
|
|
||||||
Events,
|
|
||||||
GatewayIntentBits,
|
|
||||||
MessageFlags,
|
|
||||||
} from "npm:discord.js";
|
|
||||||
const token = Deno.env.get("token");
|
|
||||||
import { Command } from "./types.ts";
|
|
||||||
import { gatherCommandsPaths } from "./commands.ts";
|
|
||||||
|
|
||||||
|
|
||||||
class Client extends _client {
|
|
||||||
commands: Collection<string, Command>;
|
|
||||||
constructor(options: ClientOptions) {
|
|
||||||
super(options);
|
|
||||||
this.commands = new Collection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
|
|
||||||
|
|
||||||
async function register(commandPath: string) {
|
|
||||||
const { default: command }: { default: Command } = await import(commandPath);
|
|
||||||
if ("data" in command && "execute" in command) {
|
|
||||||
client.commands.set(command.data.name, command);
|
|
||||||
console.log(`Registered ${command.data.name}.`);
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
`[WARNING] The command at ${commandPath} is missing a required "data" or "execute" property.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(await gatherCommandsPaths()).forEach(register)
|
|
||||||
|
|
||||||
client.once(Events.ClientReady, (readyClient) => {
|
|
||||||
console.log(`Ready! Logged in as ${readyClient.user.tag}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on(Events.InteractionCreate, async interaction => {
|
|
||||||
if (!interaction.isChatInputCommand()) return;
|
|
||||||
|
|
||||||
const command = client.commands.get(interaction.commandName);
|
|
||||||
|
|
||||||
if (!command) {
|
|
||||||
console.error(`No command matching ${interaction.commandName} was found.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await command.execute(interaction);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
if (interaction.replied || interaction.deferred) {
|
|
||||||
await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
} else {
|
|
||||||
await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.login(token);
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { REST, RESTPostAPIChatInputApplicationCommandsJSONBody, Routes } from "npm:discord.js";
|
import { REST, RESTPostAPIChatInputApplicationCommandsJSONBody, Routes } from "npm:discord.js";
|
||||||
const { clientId, guildId, token } = Deno.env.toObject();
|
const { clientId, guildId, token } = Deno.env.toObject();
|
||||||
import { Command } from "../types.ts";
|
import { Command } from "../src/types.ts";
|
||||||
import { gatherCommandsPaths } from "../commands.ts";
|
import { gatherCommandsPaths } from "../src/commands.ts";
|
||||||
|
|
||||||
const commands: RESTPostAPIChatInputApplicationCommandsJSONBody[] = [];
|
const commands: RESTPostAPIChatInputApplicationCommandsJSONBody[] = [];
|
||||||
async function register(commandPath: string) {
|
async function register(commandPath: string) {
|
||||||
|
|
|
||||||
3
src/cai.ts
Normal file
3
src/cai.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { CAINode } from "npm:cainode@latest";
|
||||||
|
|
||||||
|
export default new CAINode()
|
||||||
42
src/commands/utils/login.ts
Normal file
42
src/commands/utils/login.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import {
|
||||||
|
CacheType,
|
||||||
|
ChatInputCommandInteraction,
|
||||||
|
MessageFlags,
|
||||||
|
SlashCommandBuilder,
|
||||||
|
} from "npm:discord.js";
|
||||||
|
import cai from "../../cai.ts";
|
||||||
|
|
||||||
|
async function getToken() {
|
||||||
|
try {
|
||||||
|
await Deno.stat("./cai.token");
|
||||||
|
return await Deno.readFile("./cai.token");
|
||||||
|
} catch {
|
||||||
|
const token: string = await cai.generate_token("charcord.bot@gmail.com", 0);
|
||||||
|
await Deno.writeTextFile("./cai.token", token);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName("login")
|
||||||
|
.setDescription("Login to character.ai"),
|
||||||
|
async execute(interaction: ChatInputCommandInteraction<CacheType>) {
|
||||||
|
if(cai.logged) {
|
||||||
|
await cai.logout()
|
||||||
|
}
|
||||||
|
await interaction.reply({
|
||||||
|
content: "Logging in...",
|
||||||
|
flags: MessageFlags.Ephemeral,
|
||||||
|
});
|
||||||
|
const token = await getToken();
|
||||||
|
await cai.login(token);
|
||||||
|
console.log(
|
||||||
|
`Logged in character.ai as ${cai.user.info.user.user.username}`
|
||||||
|
);
|
||||||
|
await interaction.followUp({
|
||||||
|
content: `Logged in character.ai as ${cai.user.info.user.user.username}`,
|
||||||
|
flags: MessageFlags.Ephemeral,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
76
src/main.ts
Normal file
76
src/main.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
import {
|
||||||
|
Client as _client,
|
||||||
|
ClientOptions,
|
||||||
|
Collection,
|
||||||
|
Events,
|
||||||
|
GatewayIntentBits,
|
||||||
|
MessageFlags,
|
||||||
|
} from "npm:discord.js";
|
||||||
|
const token = Deno.env.get("token");
|
||||||
|
import { Command } from "./types.ts";
|
||||||
|
import { gatherCommandsPaths } from "./commands.ts";
|
||||||
|
import { exists } from "jsr:@std/fs/exists";
|
||||||
|
import cai from "./cai.ts";
|
||||||
|
|
||||||
|
class Client extends _client {
|
||||||
|
commands: Collection<string, Command>;
|
||||||
|
constructor(options: ClientOptions) {
|
||||||
|
super(options);
|
||||||
|
this.commands = new Collection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
|
||||||
|
|
||||||
|
async function register(commandPath: string) {
|
||||||
|
const { default: command }: { default: Command } = await import(commandPath);
|
||||||
|
if ("data" in command && "execute" in command) {
|
||||||
|
client.commands.set(command.data.name, command);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`[WARNING] The command at ${commandPath} is missing a required "data" or "execute" property.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(await gatherCommandsPaths()).forEach(register);
|
||||||
|
|
||||||
|
client.on(Events.InteractionCreate, async (interaction) => {
|
||||||
|
if (!interaction.isChatInputCommand()) return;
|
||||||
|
|
||||||
|
const command = client.commands.get(interaction.commandName);
|
||||||
|
|
||||||
|
if (!command) {
|
||||||
|
console.error(`No command matching ${interaction.commandName} was found.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await command.execute(interaction);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
if (interaction.replied || interaction.deferred) {
|
||||||
|
await interaction.followUp({
|
||||||
|
content: "There was an error while executing this command!",
|
||||||
|
flags: MessageFlags.Ephemeral,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await interaction.reply({
|
||||||
|
content: "There was an error while executing this command!",
|
||||||
|
flags: MessageFlags.Ephemeral,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.once(Events.ClientReady, (readyClient) => {
|
||||||
|
console.log(`Ready! Logged in as ${readyClient.user.tag}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (await exists("./cai.token", { isFile: true })) {
|
||||||
|
await cai.login(await Deno.readTextFile("./cai.token"));
|
||||||
|
cai.logged = true;
|
||||||
|
console.log(`Logged in character.ai as ${cai.user.info.user.user.username}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.login(token);
|
||||||
0
src/utils.ts
Normal file
0
src/utils.ts
Normal file
Loading…
Add table
Add a link
Reference in a new issue