First working prototype, but it has alzheimer's
This commit is contained in:
21
package-lock.json
generated
21
package-lock.json
generated
@@ -10,9 +10,15 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@google/genai": "^1.10.0",
|
||||
"@types/dateformat": "^5.0.3",
|
||||
"axios": "^1.10.0",
|
||||
"dateformat": "^5.0.3",
|
||||
"discord-api-types": "^0.38.16",
|
||||
"discord.js": "^14.21.0",
|
||||
"dotenv": "^17.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders": {
|
||||
@@ -196,6 +202,12 @@
|
||||
"npm": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/dateformat": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/dateformat/-/dateformat-5.0.3.tgz",
|
||||
"integrity": "sha512-hvskLa9ObgUwJe0rtfkyBbU+VIK8Ia3BACsxRsp4CPnyPBAOyIHbqImfBGFfaVVxn82wGx5SD8Twll6jMc/BaQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.15.tgz",
|
||||
@@ -310,6 +322,15 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/dateformat": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.3.tgz",
|
||||
"integrity": "sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"version": "0.0.0",
|
||||
"description": "ai bot thingy",
|
||||
"main": "app.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
@@ -10,8 +11,14 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@google/genai": "^1.10.0",
|
||||
"@types/dateformat": "^5.0.3",
|
||||
"axios": "^1.10.0",
|
||||
"dateformat": "^5.0.3",
|
||||
"discord-api-types": "^0.38.16",
|
||||
"discord.js": "^14.21.0",
|
||||
"dotenv": "^17.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
14
src/index.ts
14
src/index.ts
@@ -0,0 +1,14 @@
|
||||
import * as Discord from "discord.js";
|
||||
import dotenv from "dotenv";
|
||||
import axios from "axios";
|
||||
import { GoogleGenAI } from "@google/genai";
|
||||
import { createShardManager } from "./utils.ts";
|
||||
import path from "path";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const shardManager = createShardManager("src/shard.ts", process.env.BOT_TOKEN, "auto", false);
|
||||
|
||||
shardManager.on("shardCreate", shard => console.log(`[ShardManager] Launched shard ${shard.id}`));
|
||||
|
||||
shardManager.spawn().catch(console.error);
|
||||
|
||||
98
src/shard.ts
Normal file
98
src/shard.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import * as Discord from "discord.js";
|
||||
import * as Utils from "@discordjs/util"
|
||||
import * as Formatters from "@discordjs/formatters"
|
||||
import * as Builders from "@discordjs/builders"
|
||||
import * as Types from "discord-api-types/v10"
|
||||
import * as fs from "node:fs"
|
||||
import dateFormat, { masks } from "dateformat";
|
||||
|
||||
|
||||
import { GoogleGenAI } from "@google/genai";
|
||||
import EventEmitter from "events";
|
||||
|
||||
const Client:Discord.Client = new Discord.Client({
|
||||
intents: ["MessageContent", "Guilds", "GuildMessages", "GuildMembers","GuildMessageReactions","GuildPresences","GuildVoiceStates","GuildIntegrations","GuildEmojisAndStickers","GuildInvites","GuildExpressions","GuildScheduledEvents","GuildMessageTyping","GuildMessagePolls"],
|
||||
ws: { properties: { $browser: "Discord iOS" }},
|
||||
presence: {status: "online", activities:
|
||||
[{
|
||||
name: "something",
|
||||
state: "who am i?",
|
||||
type: Discord.ActivityType.Custom
|
||||
}]
|
||||
},
|
||||
shards: "auto",
|
||||
allowedMentions: {parse: ["users", "roles"], repliedUser: true},
|
||||
})
|
||||
|
||||
const ai = new GoogleGenAI({
|
||||
apiKey: process.env.GEMINI_KEY,
|
||||
project: process.env.GCP_PROJECT_ID||undefined,
|
||||
});
|
||||
|
||||
const shardCacheMap = new Map<string,string|undefined>();
|
||||
|
||||
function logPrefix():string {return `[${dateFormat(new Date(), masks.isoTime)}] [Shard-${Client.shard?.ids[0]}]: `}
|
||||
|
||||
Client.on("ready", async () => {
|
||||
console.log(logPrefix()+"Client is ready.")
|
||||
//await createCaches();
|
||||
})
|
||||
|
||||
function sevenDays():string {
|
||||
const nextWeek = new Date();
|
||||
nextWeek.setDate(nextWeek.getDate() + 7);
|
||||
return nextWeek.toISOString();
|
||||
}
|
||||
async function createCaches() {
|
||||
console.log(logPrefix()+"Creating caches...")
|
||||
const guildList:string[] = Client.guilds.cache.map(guild => guild.id)
|
||||
var cacheList = new Set<string>();
|
||||
const caches = await ai.caches.list({config: {pageSize: 100}})
|
||||
|
||||
for await (const cache of caches) {
|
||||
if (cache.displayName) {
|
||||
cacheList.add(cache.displayName);
|
||||
shardCacheMap.set(cache.displayName, cache.name);
|
||||
}
|
||||
}
|
||||
|
||||
for (const guildId of guildList) {
|
||||
if (!cacheList.has(guildId)) {
|
||||
console.log(logPrefix()+`Guild ${guildId} does not have a cache, creating one now.`)
|
||||
const newCache = await ai.caches.create({
|
||||
model: "gemini-2.5-flash",
|
||||
config: {
|
||||
displayName: guildId,
|
||||
expireTime: sevenDays(), // im not gonna bother trying to fit all this in one value
|
||||
systemInstruction: fs.readFileSync("systemprompt.txt").toString().replace("<GUILD>",Client.guilds.cache.get(guildId)?.name||"undefined"),
|
||||
}
|
||||
})
|
||||
shardCacheMap.set(guildId, newCache.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function embedMessageInfo(message:Discord.Message) {
|
||||
return `Message Author Username: ${message.author.username}
|
||||
Message Author Name: ${message.author.displayName}
|
||||
Message Content: ${message.cleanContent}`
|
||||
}
|
||||
|
||||
|
||||
|
||||
Client.on("messageCreate", async message => {
|
||||
if (message.content.includes("<@1396892425548730601>")) {
|
||||
const genContent = await ai.models.generateContent({
|
||||
model: "gemini-2.5-flash",
|
||||
contents: embedMessageInfo(message),
|
||||
config: {
|
||||
//cachedContent: shardCacheMap.get(message.guildId || ""),
|
||||
systemInstruction: fs.readFileSync("systemprompt.txt").toString().replace("<GUILD>",Client.guilds.cache.get(message.guildId||"")?.name||"undefined"),
|
||||
}
|
||||
})
|
||||
const resContent:string = genContent.text?.toString()||" ";
|
||||
message.reply(resContent);
|
||||
}
|
||||
})
|
||||
|
||||
Client.login(process.env.TOKEN);
|
||||
13
src/utils.ts
Normal file
13
src/utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as Discord from "discord.js";
|
||||
|
||||
function createShardManager(file:string, token:string|undefined, shards:number|"auto", silent?:boolean):Discord.ShardingManager {
|
||||
const manager = new Discord.ShardingManager(file,{
|
||||
token: token,
|
||||
totalShards: shards,
|
||||
mode: "process",
|
||||
silent: silent||false
|
||||
})
|
||||
return manager;
|
||||
}
|
||||
|
||||
export {createShardManager};
|
||||
1
systemprompt.txt
Normal file
1
systemprompt.txt
Normal file
@@ -0,0 +1 @@
|
||||
you are aisha, a human user on the messaging platform Discord. your job is to act like a human user of this platform and talk with people that interact with you. The server you are in is called <GUILD>. Users can talk to you by "mentioning" you with the mention sign @Aisha.
|
||||
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"target": "es6",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
Reference in New Issue
Block a user