mirror of
https://github.com/SrIzan10/vinci.git
synced 2026-06-06 01:07:00 +00:00
feat: ai and birthday
This commit is contained in:
6
TODO.md
6
TODO.md
@@ -38,7 +38,6 @@
|
||||
|
||||
# Message driven functions
|
||||
- [x] AI chat
|
||||
- [ ] T thread message deletion
|
||||
|
||||
# Utility Systems to Rewrite
|
||||
- [x] Resolver - Role/user resolution utility
|
||||
@@ -46,9 +45,8 @@
|
||||
|
||||
# Background Services
|
||||
- [x] ~YouTube notifications system~ using rss instead
|
||||
- [ ] Birthday checker service
|
||||
- [ ] Minecraft server status checker
|
||||
- [ ] Activity status rotation
|
||||
- [x] Birthday checker service
|
||||
- [x] Activity status rotation
|
||||
|
||||
# Database
|
||||
- [x] Migration to sqlite
|
||||
|
||||
File diff suppressed because one or more lines are too long
1
assets/daysinyear.json
Normal file
1
assets/daysinyear.json
Normal file
@@ -0,0 +1 @@
|
||||
["1-1","2-1","3-1","4-1","5-1","6-1","7-1","8-1","9-1","10-1","11-1","12-1","13-1","14-1","15-1","16-1","17-1","18-1","19-1","20-1","21-1","22-1","23-1","24-1","25-1","26-1","27-1","28-1","29-1","30-1","31-1","1-2","2-2","3-2","4-2","5-2","6-2","7-2","8-2","9-2","10-2","11-2","12-2","13-2","14-2","15-2","16-2","17-2","18-2","19-2","20-2","21-2","22-2","23-2","24-2","25-2","26-2","27-2","28-2","1-3","2-3","3-3","4-3","5-3","6-3","7-3","8-3","9-3","10-3","11-3","12-3","13-3","14-3","15-3","16-3","17-3","18-3","19-3","20-3","21-3","22-3","23-3","24-3","25-3","26-3","27-3","28-3","29-3","30-3","31-3","1-4","2-4","3-4","4-4","5-4","6-4","7-4","8-4","9-4","10-4","11-4","12-4","13-4","14-4","15-4","16-4","17-4","18-4","19-4","20-4","21-4","22-4","23-4","24-4","25-4","26-4","27-4","28-4","29-4","30-4","1-5","2-5","3-5","4-5","5-5","6-5","7-5","8-5","9-5","10-5","11-5","12-5","13-5","14-5","15-5","16-5","17-5","18-5","19-5","20-5","21-5","22-5","23-5","24-5","25-5","26-5","27-5","28-5","29-5","30-5","31-5","1-6","2-6","3-6","4-6","5-6","6-6","7-6","8-6","9-6","10-6","11-6","12-6","13-6","14-6","15-6","16-6","17-6","18-6","19-6","20-6","21-6","22-6","23-6","24-6","25-6","26-6","27-6","28-6","29-6","30-6","1-7","2-7","3-7","4-7","5-7","6-7","7-7","8-7","9-7","10-7","11-7","12-7","13-7","14-7","15-7","16-7","17-7","18-7","19-7","20-7","21-7","22-7","23-7","24-7","25-7","26-7","27-7","28-7","29-7","30-7","31-7","1-8","2-8","3-8","4-8","5-8","6-8","7-8","8-8","9-8","10-8","11-8","12-8","13-8","14-8","15-8","16-8","17-8","18-8","19-8","20-8","21-8","22-8","23-8","24-8","25-8","26-8","27-8","28-8","29-8","30-8","31-8","1-9","2-9","3-9","4-9","5-9","6-9","7-9","8-9","9-9","10-9","11-9","12-9","13-9","14-9","15-9","16-9","17-9","18-9","19-9","20-9","21-9","22-9","23-9","24-9","25-9","26-9","27-9","28-9","29-9","30-9","1-10","2-10","3-10","4-10","5-10","6-10","7-10","8-10","9-10","10-10","11-10","12-10","13-10","14-10","15-10","16-10","17-10","18-10","19-10","20-10","21-10","22-10","23-10","24-10","25-10","26-10","27-10","28-10","29-10","30-10","31-10","1-11","2-11","3-11","4-11","5-11","6-11","7-11","8-11","9-11","10-11","11-11","12-11","13-11","14-11","15-11","16-11","17-11","18-11","19-11","20-11","21-11","22-11","23-11","24-11","25-11","26-11","27-11","28-11","29-11","30-11","1-12","2-12","3-12","4-12","5-12","6-12","7-12","8-12","9-12","10-12","11-12","12-12","13-12","14-12","15-12","16-12","17-12","18-12","19-12","20-12","21-12","22-12","23-12","24-12","25-12","26-12","27-12","28-12","29-12","30-12","31-12"]
|
||||
62
src/commands/misc/cumple.ts
Normal file
62
src/commands/misc/cumple.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { commandModule, CommandType } from '@sern/handler';
|
||||
import { ApplicationCommandOptionType } from 'discord.js';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [],
|
||||
description: 'Añade tu cumpleaños',
|
||||
options: [
|
||||
{
|
||||
name: 'fecha',
|
||||
description: 'La fecha de tu cumple (D-M) (elige en el autocompletado)',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
autocomplete: true,
|
||||
required: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
execute: async (autocomplete) => {
|
||||
const focusedValue = autocomplete.options.getFocused();
|
||||
let choices = JSON.parse(readFileSync('./assets/daysinyear.json').toString()) as string[];
|
||||
choices = choices.filter((choice) => choice.startsWith(focusedValue));
|
||||
choices = choices.slice(0, 25);
|
||||
await autocomplete.respond(
|
||||
choices.map((choice) => ({
|
||||
name: choice,
|
||||
value: choice,
|
||||
}))
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
execute: async (ctx, sdt) => {
|
||||
const date = ctx.interaction.options.getString('fecha', true);
|
||||
|
||||
const existing = await sdt.deps.prisma.birthday.findUnique({
|
||||
where: { userId: ctx.user.id },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
await sdt.deps.prisma.birthday.update({
|
||||
where: { userId: ctx.user.id },
|
||||
data: { date },
|
||||
});
|
||||
await ctx.reply({
|
||||
content: `cumpleaños actualizado a ${date}!`,
|
||||
ephemeral: true,
|
||||
});
|
||||
} else {
|
||||
await sdt.deps.prisma.birthday.create({
|
||||
data: {
|
||||
userId: ctx.user.id,
|
||||
date,
|
||||
},
|
||||
});
|
||||
await ctx.reply({
|
||||
content: `cumpleaños registrado para el ${date}!`,
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,9 +1,9 @@
|
||||
//CONFIG FILE: export only data here and do not cause side effects. Feel free to add your own configuration to this file.
|
||||
|
||||
//commands directory. REQUIRED
|
||||
export const commands = './dist/commands'
|
||||
// events directory.
|
||||
export const events = './dist/events'
|
||||
export const commands = './dist/commands';
|
||||
// events directory.
|
||||
export const events = './dist/events';
|
||||
|
||||
// schedule tasks and declare them here
|
||||
// export const tasks = './dist/tasks'
|
||||
@@ -11,3 +11,4 @@ export const events = './dist/events'
|
||||
// defaultPrefix: if omitted, sern will disable all text/prefix commands
|
||||
// export const defaultPrefix = '?'
|
||||
|
||||
export const tasks = './dist/tasks';
|
||||
|
||||
4
src/dependencies.d.ts
vendored
4
src/dependencies.d.ts
vendored
@@ -7,8 +7,8 @@
|
||||
import type { CoreDependencies } from '@sern/handler';
|
||||
import type { Client } from 'discord.js';
|
||||
import type { Publisher } from '@sern/publisher';
|
||||
import type prisma from './utils/db/index.js';
|
||||
import type { Database } from 'bun:sqlite';
|
||||
import type { PrismaClient } from '@prisma/client';
|
||||
/**
|
||||
* Note: You usually would not need to modify this unless there is an urgent need to break the contracts provided.
|
||||
* You would need to modify this to add your custom Services, however.
|
||||
@@ -17,7 +17,7 @@ declare global {
|
||||
interface Dependencies extends CoreDependencies {
|
||||
'@sern/client': Client;
|
||||
publisher: Publisher;
|
||||
prisma: prisma;
|
||||
prisma: PrismaClient;
|
||||
dict: Database;
|
||||
}
|
||||
}
|
||||
|
||||
43
src/tasks/birthdayCheck.ts
Normal file
43
src/tasks/birthdayCheck.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { scheduledTask } from "@sern/handler";
|
||||
import { ThreadAutoArchiveDuration } from "discord.js";
|
||||
|
||||
export default scheduledTask({
|
||||
trigger: "* * * * *",
|
||||
execute: async (context, sdt) => {
|
||||
const now = new Date();
|
||||
const today = `${now.getDate()}-${now.getMonth() + 1}`;
|
||||
|
||||
// mark all non-today birthdays as not sent
|
||||
await sdt.deps.prisma.birthday.updateMany({
|
||||
where: {
|
||||
date: { not: today },
|
||||
sent: true,
|
||||
},
|
||||
data: { sent: false },
|
||||
});
|
||||
|
||||
const users = await sdt.deps.prisma.birthday.findMany({
|
||||
where: {
|
||||
date: today,
|
||||
sent: false,
|
||||
}
|
||||
});
|
||||
users.forEach(async user => {
|
||||
const channel = await sdt.deps["@sern/client"].channels.fetch(process.env.BIRTHDAY_CHANNEL!);
|
||||
const discordUser = await sdt.deps["@sern/client"].users.fetch(user.userId);
|
||||
if (channel && channel.isSendable() && channel.isTextBased()) {
|
||||
const msg = await channel.send(`<@&1039613683422208020>, hoy es el cumpleaños de <@${discordUser.id}>! 🎉🎂 ¡Muchas felicidades!`);
|
||||
msg.react('🎉');
|
||||
msg.react('<:Pog:1030169609178976346>');
|
||||
msg.startThread({
|
||||
name: `Feliz cumpleaños ${discordUser.username}!`,
|
||||
autoArchiveDuration: ThreadAutoArchiveDuration.OneWeek,
|
||||
});
|
||||
await sdt.deps.prisma.birthday.update({
|
||||
where: { id: user.id },
|
||||
data: { sent: true },
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -35,15 +35,29 @@ export async function aiHandle(msg: OmitPartialGroupDMChannel<Message<boolean>>,
|
||||
messages.push({ role: 'system', content: systemMsg }, { role: 'user', content: msg.content });
|
||||
}
|
||||
|
||||
const sentMsg = await msg.reply(':sparkles: Pensando...');
|
||||
const sentMsg = await msg.reply(':sparkles: Razonando...');
|
||||
const stream = await openai.chat.completions.create({
|
||||
model: 'llama-3.3-70b-versatile',
|
||||
model: 'google/gemini-3-pro-preview',
|
||||
messages,
|
||||
max_tokens: 2000,
|
||||
max_completion_tokens: 2000,
|
||||
temperature: 0.7,
|
||||
stream: true,
|
||||
});
|
||||
const message = stream.choices[0].message.content!
|
||||
|
||||
let message = '';
|
||||
let lastEdit = Date.now();
|
||||
|
||||
for await (const chunk of stream) {
|
||||
const content = chunk.choices[0]?.delta?.content || '';
|
||||
message += content;
|
||||
|
||||
if (Date.now() - lastEdit > 1000 && message.length > 0) {
|
||||
await sentMsg.edit(message.slice(0, 2000));
|
||||
lastEdit = Date.now();
|
||||
}
|
||||
}
|
||||
|
||||
await sentMsg.edit(message.slice(0, 2000));
|
||||
|
||||
messages.push({ role: 'assistant', content: message.replace(/^\n{2}/, '') });
|
||||
@@ -51,7 +65,7 @@ export async function aiHandle(msg: OmitPartialGroupDMChannel<Message<boolean>>,
|
||||
if (!isThread) {
|
||||
const titleMessage = (
|
||||
await openai.chat.completions.create({
|
||||
model: 'llama-3.3-70b-versatile',
|
||||
model: 'google/gemini-3-pro-preview',
|
||||
messages: [
|
||||
{ role: 'system', content: systemMsg },
|
||||
{
|
||||
|
||||
@@ -2,5 +2,5 @@ import OpenAI from "openai";
|
||||
|
||||
export const openai = new OpenAI({
|
||||
apiKey: process.env.AI_KEY,
|
||||
baseURL: "https://api.groq.com/openai/v1"
|
||||
baseURL: "https://ai.hackclub.com/proxy/v1"
|
||||
});
|
||||
Reference in New Issue
Block a user