mirror of
https://github.com/SrIzan10/vinci.git
synced 2026-06-08 16:12:31 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b82784608f | |||
| ea1d086fd0 | |||
| b84260901d | |||
| 8ac9c16945 | |||
| 8aeebb1164 | |||
| fa23042c99 | |||
| 2aafce2429 | |||
| 8d5c962049 | |||
| 37d983e150 | |||
| 3b9acf6f29 | |||
| 51ea593bcd | |||
| 8112f232e3 | |||
| 214c35a7e6 | |||
| d208f6b8c7 | |||
| 0b8f23cefd | |||
| c95ceb1539 | |||
| 0654ce2bfd | |||
| b84bd0a250 | |||
| 8005ac0699 | |||
| ecada7600e | |||
| 73e397be5b | |||
| 0f08d35876 | |||
| 116f0be0b2 | |||
| 43c0b40703 | |||
|
|
10aa847aba |
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
images
|
||||
.env*
|
||||
dist
|
||||
12
.github/workflows/docker.yml
vendored
12
.github/workflows/docker.yml
vendored
@@ -22,10 +22,12 @@ jobs:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Log in to Sr Izan's container registry
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
|
||||
with:
|
||||
registry: containers.srizan.dev
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
@@ -33,7 +35,7 @@ jobs:
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: containers.srizan.dev/vinci
|
||||
images: srizan10/vinci
|
||||
tags: latest
|
||||
|
||||
- name: Build and push Docker image
|
||||
@@ -50,5 +52,5 @@ jobs:
|
||||
AUTH_HEADER: ${{ secrets.WHSERVER_TOKEN }}
|
||||
run: |
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer $AUTH_HEADER" \
|
||||
https://webhooks.srizan.dev/hooks/vinci
|
||||
-H "Authorization: $AUTH_HEADER" \
|
||||
https://webhooks.srizan.dev/hooks/vinci
|
||||
|
||||
124
.sern/ambient.d.ts
vendored
Normal file
124
.sern/ambient.d.ts
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
declare var __DEV__: boolean
|
||||
declare var __PROD__: boolean
|
||||
declare var __VERSION__: string
|
||||
declare namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
SHELL:string
|
||||
SESSION_MANAGER:string
|
||||
COLORTERM:string
|
||||
XDG_CONFIG_DIRS:string
|
||||
XDG_SESSION_PATH:string
|
||||
COREPACK_ENABLE_DOWNLOAD_PROMPT:string
|
||||
NVM_INC:string
|
||||
XDG_MENU_PREFIX:string
|
||||
TERM_PROGRAM_VERSION:string
|
||||
ICEAUTHORITY:string
|
||||
NODE_OPTIONS:string
|
||||
LC_ADDRESS:string
|
||||
LC_NAME:string
|
||||
MEMORY_PRESSURE_WRITE:string
|
||||
DESKTOP_SESSION:string
|
||||
LC_MONETARY:string
|
||||
GTK_RC_FILES:string
|
||||
NO_AT_BRIDGE:string
|
||||
EDITOR:string
|
||||
XDG_SEAT:string
|
||||
PWD:string
|
||||
LOGNAME:string
|
||||
XDG_SESSION_DESKTOP:string
|
||||
XDG_SESSION_TYPE:string
|
||||
SYSTEMD_EXEC_PID:string
|
||||
_:string
|
||||
XAUTHORITY:string
|
||||
VSCODE_GIT_ASKPASS_NODE:string
|
||||
MOTD_SHOWN:string
|
||||
GTK2_RC_FILES:string
|
||||
HOME:string
|
||||
COREPACK_ROOT:string
|
||||
LANG:string
|
||||
LC_PAPER:string
|
||||
XDG_CURRENT_DESKTOP:string
|
||||
npm_package_version:string
|
||||
MEMORY_PRESSURE_WATCH:string
|
||||
STARSHIP_SHELL:string
|
||||
WAYLAND_DISPLAY:string
|
||||
GIT_ASKPASS:string
|
||||
XDG_SEAT_PATH:string
|
||||
INVOCATION_ID:string
|
||||
MANAGERPID:string
|
||||
INIT_CWD:string
|
||||
CHROME_DESKTOP:string
|
||||
STARSHIP_SESSION_KEY:string
|
||||
KDE_SESSION_UID:string
|
||||
NVM_DIR:string
|
||||
VSCODE_GIT_ASKPASS_EXTRA_ARGS:string
|
||||
XKB_DEFAULT_LAYOUT:string
|
||||
XDG_ACTIVATION_TOKEN:string
|
||||
XDG_SESSION_CLASS:string
|
||||
LC_IDENTIFICATION:string
|
||||
TERM:string
|
||||
npm_package_name:string
|
||||
PROJECT_CWD:string
|
||||
USER:string
|
||||
VSCODE_GIT_IPC_HANDLE:string
|
||||
QT_WAYLAND_RECONNECT:string
|
||||
KDE_SESSION_VERSION:string
|
||||
PAM_KWALLET5_LOGIN:string
|
||||
DISPLAY:string
|
||||
npm_lifecycle_event:string
|
||||
SHLVL:string
|
||||
NVM_CD_FLAGS:string
|
||||
LC_TELEPHONE:string
|
||||
LC_MEASUREMENT:string
|
||||
XDG_VTNR:string
|
||||
XDG_SESSION_ID:string
|
||||
npm_config_user_agent:string
|
||||
npm_execpath:string
|
||||
XDG_RUNTIME_DIR:string
|
||||
DEBUGINFOD_URLS:string
|
||||
npm_package_json:string
|
||||
LC_TIME:string
|
||||
BUN_INSTALL:string
|
||||
BERRY_BIN_FOLDER:string
|
||||
XKB_DEFAULT_VARIANT:string
|
||||
VSCODE_GIT_ASKPASS_MAIN:string
|
||||
QT_AUTO_SCREEN_SCALE_FACTOR:string
|
||||
JOURNAL_STREAM:string
|
||||
XDG_DATA_DIRS:string
|
||||
KDE_FULL_SESSION:string
|
||||
GDK_BACKEND:string
|
||||
BROWSER:string
|
||||
PATH:string
|
||||
ORIGINAL_XDG_CURRENT_DESKTOP:string
|
||||
DBUS_SESSION_BUS_ADDRESS:string
|
||||
KDE_APPLICATIONS_AS_SCOPE:string
|
||||
MAIL:string
|
||||
NVM_BIN:string
|
||||
npm_node_execpath:string
|
||||
LC_NUMERIC:string
|
||||
OLDPWD:string
|
||||
TERM_PROGRAM:string
|
||||
TOKEN:string
|
||||
PREFIX:string
|
||||
MONGODB:string
|
||||
YOURLS_KEY:string
|
||||
CATAPI:string
|
||||
DOGAPI:string
|
||||
TWITTER:string
|
||||
MAKESWEET:string
|
||||
GENIUS:string
|
||||
SPOTIFY_CLIENT:string
|
||||
SPOTIFY_SECRET:string
|
||||
CF_AI_TOKEN:string
|
||||
CF_AI_ACC:string
|
||||
GUILDID:string
|
||||
SUGGESTIONS_CHANNEL:string
|
||||
MODLOGS_CHANNEL:string
|
||||
JOINSANDLEAVES_CHANNEL:string
|
||||
SOCIALS_CHANNEL:string
|
||||
BIRTHDAYS_CHANNEL:string
|
||||
MCFORM_CHANNEL:string
|
||||
CHATGPT_CHANNEL:string
|
||||
T_CHANNEL:string
|
||||
}
|
||||
}
|
||||
1273
.sern/command-data-remote.json
Normal file
1273
.sern/command-data-remote.json
Normal file
File diff suppressed because it is too large
Load Diff
17
.sern/tsconfig.json
Normal file
17
.sern/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node16",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"target": "esnext",
|
||||
"rootDirs": [
|
||||
"./generated",
|
||||
"../src"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./ambient.d.ts",
|
||||
"../src"
|
||||
]
|
||||
}
|
||||
BIN
.yarn/install-state.gz
Normal file
BIN
.yarn/install-state.gz
Normal file
Binary file not shown.
1
.yarnrc.yml
Normal file
1
.yarnrc.yml
Normal file
@@ -0,0 +1 @@
|
||||
nodeLinker: node-modules
|
||||
11
Dockerfile
11
Dockerfile
@@ -7,12 +7,11 @@ WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache --virtual .gyp python3 make g++
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
COPY . .
|
||||
RUN corepack enable yarn
|
||||
RUN yarn
|
||||
|
||||
COPY . .
|
||||
RUN yarn build
|
||||
RUN yarn cache clean
|
||||
|
||||
# Final stage
|
||||
FROM node:lts-alpine AS final
|
||||
@@ -20,9 +19,9 @@ FROM node:lts-alpine AS final
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=build /app/dist ./dist
|
||||
COPY --from=build /app/schemas ./schemas
|
||||
COPY --from=build /app/util ./
|
||||
COPY --from=build /app/images ./images
|
||||
COPY --from=build /app/src ./src
|
||||
COPY --from=build /app/.sern ./.sern
|
||||
COPY --from=build /app/assets ./assets
|
||||
COPY --from=build /app/node_modules ./node_modules
|
||||
COPY --from=build /app/package.json ./package.json
|
||||
RUN apk add --no-cache ffmpeg msttcorefonts-installer fontconfig && \
|
||||
|
||||
@@ -26,10 +26,5 @@ the code is here for transparency purposes and it's not made to be hosted by thi
|
||||
- ~~socials notification system~~ DONE!
|
||||
- chatbot using IBM's AI (thanks @gosevil for the idea)
|
||||
- ~~joke command~~
|
||||
|
||||
<!--<img src="https://srizan.s-ul.eu/RddzT2f9">-->
|
||||
|
||||
<img src="https://cdn.discordapp.com/attachments/928230817673641995/1036390945945559140/makesweet-hbt4h3.gif">
|
||||
by @Oliverlg8
|
||||
|
||||
10 stars! tysm!
|
||||
|
||||
1059783
assets/icRecipes.json
Normal file
1059783
assets/icRecipes.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
||||
import { commandModule, CommandType } from '@sern/handler';
|
||||
import axios from 'axios';
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Button,
|
||||
plugins: [],
|
||||
execute: async (ctx) => {
|
||||
await ctx.deferReply({ ephemeral: true })
|
||||
const request = await axios.get('https://api.minetools.eu/query/minecraft.maraturing.com/25565').then(res => res.data)
|
||||
|
||||
await ctx.editReply({
|
||||
content: ``
|
||||
})
|
||||
},
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ApplicationCommandOptionType } from "discord.js";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: 'askjavi',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
description: 'DESACTIVADO: Pregunta a Javi LO QUE SEA!',
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
await ctx.reply({content: `Este comando ha sido desactivado ya que era para un evento que ya ha ocurrido.\nGracias por haber participado!`, ephemeral: true})
|
||||
},
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";;
|
||||
import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, TextChannel } from 'discord.js'
|
||||
|
||||
export default commandModule({
|
||||
name: 'ban',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
description: 'ADMIN: Banea usuarios.',
|
||||
options: [{
|
||||
name: 'usuario',
|
||||
description: 'Escribe un usuario.',
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: 'razon',
|
||||
description: 'Escribe la razón.',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true
|
||||
}],
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
try {
|
||||
const userToBan = options[1].getMember('usuario') as GuildMember
|
||||
const reason = options[1].getString('razon') as string
|
||||
userToBan.ban({reason: reason})
|
||||
const sendToMods = ctx.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.MODLOGS_CHANNEL!) as TextChannel
|
||||
await sendToMods.send({content: `Se ha baneado a ${userToBan}.\nBan efectuado por ${ctx.user} con razón "${reason}."`})
|
||||
await ctx.reply({content: 'Baneado correctamente!', ephemeral: true})
|
||||
} catch {
|
||||
await ctx.reply({content: `ERROR: No puedo hacer este comando porque a lo mejor soy inferior que el rol de esa persona o estoy usándolo contra admins.`})
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,42 +0,0 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "../../plugins/index.js";
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ApplicationCommandOptionType, TextChannel } from "discord.js";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: 'eliminarmensaje',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
description: 'ADMIN: Elimina comandos por su ID.',
|
||||
//alias : [],
|
||||
options: [
|
||||
{
|
||||
name: 'canal',
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
description: 'El canal de texto.',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: 'id',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
description: 'El ID del mensaje.',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
try {
|
||||
const idMensaje = options[1].getString('id', true);
|
||||
const guildId = ctx.guild!.id
|
||||
const guild = await ctx.client.guilds.fetch(guildId);
|
||||
const channel = await guild.channels.fetch(ctx.channel!.id);
|
||||
(await (channel as TextChannel).messages.fetch(idMensaje)).delete();
|
||||
await ctx.reply({content: 'Mensaje eliminado correctamente.', ephemeral: true});
|
||||
} catch {
|
||||
await ctx.reply({content: `ERROR: No se ha podido eliminar el mensaje, asegúrate que estás usando el ID y el canal correcto.`})
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";;
|
||||
import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, TextChannel } from 'discord.js'
|
||||
|
||||
export default commandModule({
|
||||
name: 'kick',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
description: 'ADMIN: Expulsa usuarios.',
|
||||
options: [
|
||||
{
|
||||
name: 'usuario',
|
||||
description: 'Escribe un usuario.',
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: 'razon',
|
||||
description: 'Escribe la razón.',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true
|
||||
}
|
||||
],
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
try {
|
||||
const userToKick = options[1].getMember('usuario');
|
||||
const reason = options[1].getString('razon') as string;
|
||||
(userToKick as GuildMember).kick(reason)
|
||||
const sendToMods = ctx.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.MODLOGS_CHANNEL!) as TextChannel
|
||||
await sendToMods!.send({content: `Se ha expulsado a ${userToKick}.\nKick efectuado por ${ctx.user} con razón "${reason}."`})
|
||||
await ctx.reply({content: 'Expulsado correctamente!'})
|
||||
} catch {
|
||||
await ctx.reply({content: `ERROR: No puedo hacer este comando porque a lo mejor soy inferior que el rol de esa persona o estoy usándolo contra admins.`})
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ApplicationCommandOptionType, GuildMember, TextChannel } from "discord.js";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: 'timeout',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
description: 'ADMIN: Silencia a usuarios.',
|
||||
options: [
|
||||
{
|
||||
name: "usuario",
|
||||
description: "Escribe el usuario que silenciar.",
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: "razon",
|
||||
description: "Escribe el razon que vas a silenciar.",
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: "minutos",
|
||||
description: "Escribe los minutos que estará silenciado.",
|
||||
type: ApplicationCommandOptionType.Number,
|
||||
min_value: 0,
|
||||
required: true
|
||||
}
|
||||
],
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
try {
|
||||
const usuario = options[1].getMember('usuario') as GuildMember
|
||||
const minutos = options[1].getNumber('minutos') as number
|
||||
const razon = options[1].getString('razon', true);
|
||||
const minutosToMilisegundos = minutos * 60 * 1000
|
||||
usuario.timeout(minutosToMilisegundos, razon).then(() => {ctx.reply({content: `Se ha silenciado a ${usuario} correctamente.`, ephemeral: true})})
|
||||
const sendToMods = ctx.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.MODLOGS_CHANNEL!) as TextChannel
|
||||
await sendToMods.send({content: `Se ha silenciado a ${usuario}.\nSlencio efectuado por ${ctx.user} con ${minutos} minutos de duración.\nRazón: ${razon}`})
|
||||
} catch {
|
||||
await ctx.reply({content: `ERROR: No puedo hacer este comando porque a lo mejor soy inferior que el rol de esa persona o estoy usándolo contra admins.`})
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,212 +0,0 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";;
|
||||
import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonInteraction, ButtonStyle, ComponentType, EmbedBuilder, GuildMember } from "discord.js";
|
||||
import db from '../../schemas/warn.js';
|
||||
|
||||
export default commandModule({
|
||||
name: 'warn',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
description: 'ADMIN: Avisa a usuarios.',
|
||||
//alias : [],
|
||||
options: [
|
||||
{
|
||||
name: 'leve',
|
||||
description: 'Aviso leve.',
|
||||
type: ApplicationCommandOptionType.Subcommand,
|
||||
options: [
|
||||
{
|
||||
name: 'usuario',
|
||||
description: 'el usuario al que avisar.',
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: 'razon',
|
||||
description: 'la razón aviso.',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'grave',
|
||||
description: 'Aviso grave.',
|
||||
type: ApplicationCommandOptionType.Subcommand,
|
||||
options: [
|
||||
{
|
||||
name: 'usuario',
|
||||
description: 'el usuario al que avisar.',
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: 'razon',
|
||||
description: 'la razón del aviso.',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'clear',
|
||||
description: 'Elimina los avisos de una persona.',
|
||||
type: ApplicationCommandOptionType.Subcommand,
|
||||
options: [
|
||||
{
|
||||
name: 'usuario',
|
||||
description: 'el usuario al que quitar el aviso.',
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
const subcommand = options[1].getSubcommand()
|
||||
const user = (options[1].getMember('usuario') as GuildMember).id
|
||||
const usermember = options[1].getMember('usuario') as GuildMember
|
||||
const reason = options[1].getString('razon', true) as string
|
||||
const times = await db.findOne({id: `${user}`}) as any
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId('1hour')
|
||||
.setLabel('1 hora')
|
||||
.setStyle(ButtonStyle.Danger),
|
||||
new ButtonBuilder()
|
||||
.setCustomId('30mins')
|
||||
.setLabel('30 minutos')
|
||||
.setStyle(ButtonStyle.Danger),
|
||||
new ButtonBuilder()
|
||||
.setCustomId('15mins')
|
||||
.setLabel('15 minutos')
|
||||
.setStyle(ButtonStyle.Danger),
|
||||
new ButtonBuilder()
|
||||
.setCustomId('pardon')
|
||||
.setLabel('Perdonar')
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
);
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setAuthor({name: `${ctx.user.username}`, iconURL: `${ctx.user.displayAvatarURL()}`})
|
||||
.setColor('Red')
|
||||
.setTitle('Tienes un aviso.')
|
||||
.setDescription(`Has sido avisado en el servidor de Discord.\nRazón: ${reason}.`)
|
||||
const dmEmbedTimeout = new EmbedBuilder()
|
||||
.setAuthor({name: `${ctx.user.username}`, iconURL: `${ctx.user.displayAvatarURL()}`})
|
||||
.setColor('Red')
|
||||
.setTitle('Acabas de ser muteado del servidor.')
|
||||
.setDescription(`Ve al servidor de Discord para ver el tiempo que estarás bloqueado.\nRazón: ${reason}.\n**Puede durar hasta una hora.**`)
|
||||
|
||||
switch (subcommand) {
|
||||
case "leve": {
|
||||
return db.exists({id: `${user}`}, async function (err, doc) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
} else {
|
||||
if (doc === null) {
|
||||
const warn = new db({id: `${user}`, times: 1})
|
||||
warn.save()
|
||||
ctx.reply({content: `Se ha avisado a ${usermember} correctamente y añadido a la base de datos.`, ephemeral: true})
|
||||
ctx.client.users.fetch(user).then((user) => {
|
||||
user.send({embeds: [dmEmbed]})
|
||||
}).catch(() => console.log(`couldn't send a DM to user ID ${user}.`));
|
||||
} else {
|
||||
if (times.times > 2) {
|
||||
const msg = await ctx.reply({content: `El usuario ha excedido 3 avisos, ¿qué hacer?`, ephemeral: true, components: [buttons]})
|
||||
const collector = msg.createMessageComponentCollector({ time: 15000, max: 1, componentType: ComponentType.Button });
|
||||
collector.on('collect', async (i) => {
|
||||
await i.deferReply({ephemeral: true})
|
||||
if (i.customId === '1hour') {
|
||||
await i.editReply({content: `Se ha silenciado a ${usermember} durante 1 hora correctamente. ;-;`})
|
||||
usermember.timeout(60 * 60 * 1000, reason)
|
||||
times.times = 0
|
||||
times.save()
|
||||
} else if (i.customId === '30mins') {
|
||||
await i.editReply({content: `Se ha silenciado a ${usermember} durante 30 minutos correctamente. ;-;`})
|
||||
usermember.timeout(30 * 60 * 1000, reason)
|
||||
times.times = 0
|
||||
times.save()
|
||||
} else if (i.customId === '15mins') {
|
||||
await i.editReply({content: `Se ha silenciado a ${usermember} durante 15 minutos correctamente. ;-;`})
|
||||
usermember.timeout(15 * 60 * 1000, reason)
|
||||
times.times = 0
|
||||
times.save()
|
||||
} else if (i.customId === 'pardon') {
|
||||
await i.editReply({content: `Se ha perdonado a ${usermember} correctamente.\nSeguro que la persona te lo agradecerá! :'D`})
|
||||
times.times = 0
|
||||
times.save()
|
||||
}
|
||||
ctx.client.users.fetch(user).then((user) => {
|
||||
user.send({embeds: [dmEmbedTimeout]})
|
||||
}).catch(() => console.log(`couldn't send a DM to user ID ${user}.`));
|
||||
});
|
||||
} else {
|
||||
ctx.reply({content: `se ha añadido un aviso con el motivo ${reason}.\navisos que tiene ahora: ${times.times + 1}`, ephemeral: true})
|
||||
times.times = times.times + 1
|
||||
times.save()
|
||||
ctx.client.users.fetch(user).then((user) => {
|
||||
user.send({embeds: [dmEmbed]});
|
||||
}).catch(() => console.log(`couldn't send a DM to user ID ${user}.`))
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
case "grave": {
|
||||
return db.exists({id: `${user}`}, async function (err, doc) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
} else {
|
||||
if (doc === null) {
|
||||
const warn = new db({id: `${user}`, times: 2})
|
||||
warn.save()
|
||||
ctx.reply({content: `Se ha avisado a ${usermember} correctamente y añadido a la base de datos.`, ephemeral: true})
|
||||
ctx.client.users.fetch(user).then((user) => {
|
||||
user.send({embeds: [dmEmbed]});
|
||||
}).catch(() => console.log(`couldn't send a DM to user ID ${user}.`))
|
||||
} else {
|
||||
if (times.times >= 4) {
|
||||
const msg = await ctx.reply({content: `El usuario ha excedido 3 avisos, ¿qué hacer?`, ephemeral: true, components: [buttons]})
|
||||
const collector = msg.createMessageComponentCollector({ time: 1000, max: 1, componentType: ComponentType.Button });
|
||||
collector.on('collect', async (i: any) => {
|
||||
if (i.customId === '1hour') {
|
||||
await i.channel!.send({content: `Se ha silenciado a ${usermember} durante 1 hora correctamente. ;-;`})
|
||||
usermember.timeout(60 * 60 * 1000, reason)
|
||||
times.times = 0
|
||||
times.save()
|
||||
} else if (i.customId === '30mins') {
|
||||
await i.channel!.send({content: `Se ha silenciado a ${usermember} durante 30 minutos correctamente. ;-;`})
|
||||
usermember.timeout(30 * 60 * 1000, reason)
|
||||
times.times = 0
|
||||
times.save()
|
||||
} else if (i.customId === '15mins') {
|
||||
await i.channel!.send({content: `Se ha silenciado a ${usermember} durante 15 minutos correctamente. ;-;`})
|
||||
usermember.timeout(15 * 60 * 1000, reason)
|
||||
times.times = 0
|
||||
times.save()
|
||||
} else if (i.customId === 'pardon') {
|
||||
await i.channel!.send({content: `Se ha perdonado a ${usermember} correctamente.\nSeguro que la persona te lo agradecerá! :'D`})
|
||||
times.times = 0
|
||||
times.save()
|
||||
}
|
||||
ctx.client.users.fetch(user).then((user) => {
|
||||
user.send({embeds: [dmEmbedTimeout]})
|
||||
}).catch(() => console.log(`couldn't send a DM to user ID ${user}.`));
|
||||
});
|
||||
} else {
|
||||
ctx.reply({content: `se ha añadido un aviso con el motivo ${reason}.\navisos que tiene ahora: ${times.times + 2}`, ephemeral: true})
|
||||
times.times = times.times + 2
|
||||
times.save()
|
||||
ctx.client.users.fetch(user).then((user) => {
|
||||
user.send({embeds: [dmEmbed]});
|
||||
}).catch(() => console.log(`couldn't send a DM to user ID ${user}.`))
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
2
dependencies.d.ts
vendored
2
dependencies.d.ts
vendored
@@ -1,9 +1,11 @@
|
||||
import { SernEmitter, Logging, CoreModuleStore, ModuleManager, ErrorHandling, CoreDependencies, Singleton } from '@sern/handler'
|
||||
import { Client } from 'discord.js'
|
||||
import Spotify from 'spotify-api.js'
|
||||
|
||||
declare global {
|
||||
interface Dependencies extends CoreDependencies {
|
||||
'@sern/client': Singleton<Client>
|
||||
'spotify-api-client': Singleton<Spotify.Client>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
10
deploy.sh
10
deploy.sh
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
git pull
|
||||
|
||||
docker build . -t srizan10/vinci
|
||||
|
||||
docker stop vinci
|
||||
|
||||
docker rm vinci
|
||||
|
||||
docker run -d -t --name vinci -p 7272:7272 --restart unless-stopped srizan10/vinci
|
||||
@@ -1,41 +0,0 @@
|
||||
import { discordEvent } from '@sern/handler';
|
||||
import axios from 'axios';
|
||||
import { TextChannel } from 'discord.js';
|
||||
import db from '../schemas/chatgpt.js';
|
||||
|
||||
export default discordEvent({
|
||||
name: 'messageCreate',
|
||||
async execute(message) {
|
||||
if (message.channel.id !== process.env.CHATGPT_CHANNEL) return;
|
||||
if (message.author.bot) return;
|
||||
if (message.content.includes('ig')) return;
|
||||
|
||||
try {
|
||||
await (message.channel as TextChannel).sendTyping()
|
||||
const response = await axios.post('https://chatgpt-api.shn.hk/v1/', {
|
||||
"model": "gpt-3.5-turbo",
|
||||
"messages": [{ "role": "user", "content": message.content }]
|
||||
}).then(res => res.data)
|
||||
const titleResponse = await axios.post('https://chatgpt-api.shn.hk/v1/', {
|
||||
"model": "gpt-3.5-turbo",
|
||||
"messages": [{ "role": "user", "content": `Generate a title in less than 6 words for the following message, also remove the quotes if you are going to add them AND don't put Title in the beginning:\nUser: ${message.content}\nAssistant: ${response.choices[0].message.content}` }]
|
||||
}).then(res => res.data.choices[0].message.content.replaceAll('"', '') as string)
|
||||
|
||||
const botMsg = await message.reply({ content: response.choices[0].message.content.slice(0, 2000) })
|
||||
const thread = await botMsg.startThread({ name: titleResponse })
|
||||
|
||||
const dbData = new db({
|
||||
messageid: message.id,
|
||||
threadid: thread.id,
|
||||
messages: [
|
||||
{ role: 'user', content: message.content },
|
||||
{ role: 'assistant', content: response.choices[0].message.content.replace(/^\n{2}/, '') }
|
||||
]
|
||||
})
|
||||
await dbData.save()
|
||||
} catch (e) {
|
||||
await message.reply({ content: 'Algo ha ido mal.' }).catch(() => {})
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,53 +0,0 @@
|
||||
import { discordEvent } from '@sern/handler';
|
||||
import axios from 'axios';
|
||||
import { ThreadChannel } from 'discord.js';
|
||||
import database from '../schemas/chatgpt.js';
|
||||
|
||||
export default discordEvent({
|
||||
name: 'messageCreate',
|
||||
async execute(message) {
|
||||
const thread = message.channel as ThreadChannel
|
||||
if (thread.parentId !== process.env.CHATGPT_CHANNEL) return;
|
||||
if (message.author.bot) return;
|
||||
if (message.content.includes('ig')) return;
|
||||
|
||||
try {
|
||||
await thread.sendTyping()
|
||||
let newObj = { role: 'user', content: message.content }
|
||||
let db = await database.findOneAndUpdate({ threadid: thread.id }, {
|
||||
$push: {
|
||||
messages: newObj
|
||||
}
|
||||
})
|
||||
const messages = db!.messages.map((message) => {
|
||||
const { _id, ...rest } = message.toObject(); // Convert Mongoose document to plain object and remove _id field
|
||||
return rest
|
||||
})
|
||||
|
||||
const response = await axios.post('https://chatgpt-api.shn.hk/v1/', {
|
||||
"model": "gpt-3.5-turbo",
|
||||
"messages": messages
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(res => res.data.choices[0].message.content as string)
|
||||
|
||||
newObj = { role: 'assistant', content: response }
|
||||
db = await database.findOneAndUpdate({ threadid: thread.id }, {
|
||||
$push: {
|
||||
messages: newObj
|
||||
}
|
||||
})
|
||||
|
||||
await message.reply({ content: response.slice(0, 2000) })
|
||||
} catch (e) {
|
||||
await message.reply('Algo ha ido mal.')
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function replacer(key, value) {
|
||||
return value.replace(/[^\w\s]/gi, '');
|
||||
}
|
||||
34
package.json
34
package.json
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"name": "vinci",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "Vinci Discord Bot for Mara Turing",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "tsc-watch -p \"./tsconfig.json\" --onSuccess \"node ./dist/index.js --dev\"",
|
||||
"dev": "sern build && node ./dist/index.js --dev",
|
||||
"prod": "tsc-watch -p \"./tsconfig.json\" --onSuccess \"node ./dist/index.js\"",
|
||||
"compile": "tsc --build",
|
||||
"build": "tsc --build",
|
||||
"build": "sern build",
|
||||
"web": "node webserver.js",
|
||||
"watch": "tsc --watch",
|
||||
"start": "nodemon dist/index.js"
|
||||
@@ -32,21 +33,25 @@
|
||||
},
|
||||
"homepage": "https://github.com/SrIzan10/vinci#readme",
|
||||
"dependencies": {
|
||||
"@consumet/extensions": "1.3.5",
|
||||
"@ai-zen/node-fetch-event-source": "^2.1.4",
|
||||
"@consumet/extensions": "^1.7.0",
|
||||
"@discordjs/opus": "^0.9.0",
|
||||
"@discordjs/voice": "^0.15.0",
|
||||
"@napi-rs/canvas": "^0.1.30",
|
||||
"@sern/handler": "^3.0.3",
|
||||
"axios": "^1.1.3",
|
||||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"@napi-rs/canvas": "^0.1.52",
|
||||
"@sern/handler": "^4.0.2",
|
||||
"@sern/publisher": "^1.1.2",
|
||||
"axios": "^1.6.8",
|
||||
"dayjs": "^1.11.6",
|
||||
"discord-tictactoe": "^4.0.0",
|
||||
"discord.js": "^14.13.0",
|
||||
"discord.js": "^14.16.2",
|
||||
"dotenv": "^16.0.1",
|
||||
"execa": "^6.1.0",
|
||||
"express": "^4.18.1",
|
||||
"extended-eventsource": "^1.4.6",
|
||||
"form-data": "^4.0.0",
|
||||
"genius-lyrics": "^4.4.3",
|
||||
"googlethis": "^1.7.1",
|
||||
"googlethis": "^1.8.0",
|
||||
"got": "^12.5.3",
|
||||
"libsodium-wrappers": "^0.7.10",
|
||||
"mongoose": "^6.11.3",
|
||||
@@ -54,13 +59,18 @@
|
||||
"pretty-seconds-spanish": "^2.1.1",
|
||||
"rockpaperscissors-checker": "^1.2.0",
|
||||
"set-interval-async": "^3.0.2",
|
||||
"sharp": "^0.33.3",
|
||||
"spotify-api.js": "^9.2.5",
|
||||
"stringify-safe": "^1.0.3",
|
||||
"systeminformation": "^5.12.6"
|
||||
"systeminformation": "^5.21.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sern/cli": "^1.3.3",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/node": "^20.12.7",
|
||||
"ts-node": "10.9.1",
|
||||
"tsc-watch": "^5.0.3",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"packageManager": "yarn@4.1.1"
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const schema = new mongoose.Schema({
|
||||
number: {type: Number, required: true}
|
||||
})
|
||||
|
||||
const db = new mongoose.Model('counting', schema)
|
||||
|
||||
module.exports = db;
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"language": "typescript",
|
||||
"paths": {
|
||||
"base": ".",
|
||||
"base": "src",
|
||||
"commands": "commands"
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,10 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ApplicationCommandOptionType } from "discord.js";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: '8ball',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Preguntale a la 8-ball cosas.',
|
||||
//alias : [],
|
||||
options: [{
|
||||
@@ -19,8 +13,8 @@ export default commandModule({
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true
|
||||
}],
|
||||
execute: async (ctx, options) => {
|
||||
// yes, the question argument is never used. There is no reason to use it in the code.
|
||||
execute: async (ctx) => {
|
||||
// yes, the question argument is never used. There is no reason to use it.
|
||||
var eightballwords = [
|
||||
'Probablemente',
|
||||
'Sí',
|
||||
@@ -2,10 +2,8 @@ import { commandModule, CommandType } from '@sern/handler';
|
||||
import {
|
||||
ApplicationCommandOptionType,
|
||||
AttachmentBuilder,
|
||||
AutocompleteInteraction,
|
||||
EmbedBuilder,
|
||||
} from 'discord.js';
|
||||
import { publish } from '#plugins';
|
||||
const choices = [
|
||||
'XaviXE',
|
||||
'Paula',
|
||||
@@ -28,9 +26,8 @@ const choices = [
|
||||
export default commandModule({
|
||||
name: 'a',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'A',
|
||||
//alias : [],
|
||||
options: [
|
||||
{
|
||||
name: 'usuario',
|
||||
@@ -39,7 +36,7 @@ export default commandModule({
|
||||
autocomplete: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
async execute(ctx: AutocompleteInteraction) {
|
||||
async execute(ctx) {
|
||||
const focusedValue = ctx.options.getFocused();
|
||||
const filtered = choices.filter((choice) =>
|
||||
choice.startsWith(focusedValue)
|
||||
@@ -48,10 +45,10 @@ export default commandModule({
|
||||
filtered.map((choice) => ({ name: choice, value: choice }))
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
const option = ctx.interaction.options.getString('usuario');
|
||||
if (!option) {
|
||||
const imagesArray = [
|
||||
@@ -77,9 +74,9 @@ export default commandModule({
|
||||
|
||||
await ctx.reply({ content: 'A', files: [images] });
|
||||
} else {
|
||||
if (choices.indexOf(options[1].getString('usuario', true)) > -1) {
|
||||
if (choices.indexOf(option) > -1) {
|
||||
const attachmentbuilder = new AttachmentBuilder(
|
||||
`./images/a/${options[1].getString('usuario', true)}.png`
|
||||
`./images/a/${option}.png`
|
||||
);
|
||||
await ctx.reply({ content: 'A', files: [attachmentbuilder] });
|
||||
} else {
|
||||
@@ -1,16 +1,11 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import axios from "axios";
|
||||
import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ComponentType, EmbedBuilder } from "discord.js";
|
||||
import { publish } from "#plugins";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: 'animal',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Enseña un animal',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -40,8 +35,8 @@ export default commandModule({
|
||||
type: ApplicationCommandOptionType.Subcommand
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
switch (options[1].getSubcommand()) {
|
||||
execute: async (ctx) => {
|
||||
switch (ctx.options.getSubcommand()) {
|
||||
case 'gato': {
|
||||
const request = await axios.get(`https://api.thecatapi.com/v1/images/search?api_key=${process.env.CATAPI}`).then(res => res.data)
|
||||
const embed = new EmbedBuilder()
|
||||
@@ -92,7 +87,7 @@ export default commandModule({
|
||||
"sub_id": i.user.id,
|
||||
"value": -1
|
||||
})
|
||||
i.editReply({content: "Has votado negativamente al gato con ID " + "`" + request[0].id + "`"})
|
||||
i.editReply({content: `Has votado negativamente al gato con ID \`${request[0].id}\``})
|
||||
}
|
||||
})
|
||||
collector.on('end', async (i) => {
|
||||
@@ -100,15 +95,11 @@ export default commandModule({
|
||||
})
|
||||
}
|
||||
case 'capybara': {
|
||||
const request = await axios('https://api.capybara-api.xyz/v1/image/random').then(res => res.data)
|
||||
const requestfacts = await axios('https://api.capybara-api.xyz/v1/facts/random').then(res => res.data)
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
|
||||
.setTitle('Capybara')
|
||||
.setDescription(`Fun fact: ${requestfacts.fact}`)
|
||||
.setColor('Random')
|
||||
.setImage(request.image_urls.medium)
|
||||
.setFooter({text: `ID: ${request.id}`})
|
||||
.setImage('https://api.capy.lol/v1/capybara');
|
||||
await ctx.interaction.reply({embeds: [embed]})
|
||||
}
|
||||
case 'zorro': {
|
||||
@@ -178,7 +169,7 @@ export default commandModule({
|
||||
})
|
||||
}
|
||||
case 'mapache': {
|
||||
const request = await axios('https://some-random-api.ml/animal/raccoon').then(res => res.data)
|
||||
const request = await axios('https://some-random-api.com/animal/raccoon').then(res => res.data)
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
|
||||
.setTitle('Mapache')
|
||||
@@ -1,14 +1,9 @@
|
||||
import { commandModule, CommandType } from '@sern/handler';
|
||||
import { publish } from '#plugins';
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: 'cursivify',
|
||||
type: CommandType.CtxMsg,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
execute: async (ctx) => {
|
||||
await ctx.deferReply()
|
||||
const trimmedstring = ctx.targetMessage.content.replaceAll('*', '');
|
||||
@@ -10,13 +10,13 @@ import {
|
||||
EmbedBuilder,
|
||||
} from 'discord.js';
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'busca cosas en gogoanime',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -91,10 +91,10 @@ export default commandModule({
|
||||
execute: async (ctx, options) => {
|
||||
const gogoanime = new ANIME.Gogoanime();
|
||||
const doubleslashregex = new RegExp('(?<!:)\/\/+')
|
||||
switch (options[1].getSubcommand()) {
|
||||
switch (ctx.options.getSubcommand()) {
|
||||
case 'buscar': {
|
||||
await ctx.interaction.deferReply()
|
||||
const option = options[1].getString('palabra-clave', true);
|
||||
const option = ctx.options.getString('palabra-clave', true);
|
||||
const search = await gogoanime.search(option);
|
||||
const editedarray = await Promise.all(
|
||||
search.results
|
||||
@@ -132,7 +132,7 @@ export default commandModule({
|
||||
})
|
||||
} break;
|
||||
case 'capitulo': {
|
||||
const selepisode = options[1].getString('id-capitulo', true)
|
||||
const selepisode = ctx.options.getString('id-capitulo', true)
|
||||
try {
|
||||
const search = await gogoanime.fetchEpisodeServers(selepisode)
|
||||
const arrayed = await Promise.all(search.map((server) => `[${server.name}](<${server.url!.replace(doubleslashregex, '/')}>)`))
|
||||
@@ -143,7 +143,7 @@ export default commandModule({
|
||||
} break;
|
||||
case 'info': {
|
||||
try {
|
||||
const option = options[1].getString('id', true)
|
||||
const option = ctx.options.getString('id', true)
|
||||
const info = await gogoanime.fetchAnimeInfo(option)
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor('Random')
|
||||
@@ -1,13 +1,13 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import axios from "axios";
|
||||
import { publish } from "#plugins";
|
||||
|
||||
|
||||
export default commandModule({
|
||||
name: 'chiste',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Enseña un chiste en inglés.',
|
||||
execute: async (ctx, args) => {
|
||||
execute: async (ctx) => {
|
||||
const jokeJSON = await axios(
|
||||
'https://v2.jokeapi.dev/joke/Programming,Miscellaneous,Spooky,Christmas?blacklistFlags=nsfw,religious,racist,sexist,explicit'
|
||||
).then((res) => res.data);
|
||||
@@ -11,13 +11,13 @@ import {
|
||||
import axios from 'axios';
|
||||
import https from 'node:https'
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
//alias : [],
|
||||
description: 'no one will read this (i hope)',
|
||||
options: [
|
||||
@@ -40,15 +40,15 @@ export default commandModule({
|
||||
],
|
||||
},
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
await ctx.interaction.deferReply();
|
||||
switch (options[1].getSubcommand()) {
|
||||
switch (ctx.options.getSubcommand()) {
|
||||
case 'heartlocket':
|
||||
{
|
||||
try {
|
||||
// get all options
|
||||
const text = options[1].getString('texto');
|
||||
const image = options[1].getAttachment('imagen', true);
|
||||
const text = ctx.options.getString('texto', true);
|
||||
const image = ctx.options.getAttachment('imagen', true);
|
||||
|
||||
// check file extension of attachment
|
||||
if (
|
||||
@@ -110,6 +110,7 @@ export default commandModule({
|
||||
Authorization: process.env.MAKESWEET!,
|
||||
},
|
||||
responseType: 'arraybuffer',
|
||||
httpsAgent: new https.Agent({ rejectUnauthorized: false })
|
||||
}
|
||||
)
|
||||
.then((res) => res.data);
|
||||
@@ -120,6 +121,7 @@ export default commandModule({
|
||||
Authorization: process.env.MAKESWEET!,
|
||||
},
|
||||
responseType: 'arraybuffer',
|
||||
httpsAgent: new https.Agent({ rejectUnauthorized: false })
|
||||
})
|
||||
.then((res) => res.data);
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins";
|
||||
import Canvas from '@napi-rs/canvas';
|
||||
import { ApplicationCommandOptionType, AttachmentBuilder } from 'discord.js';
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
// , '928018226330337280'
|
||||
description: 'Añade a una imagen de megamind "No ...?"',
|
||||
//alias : [],
|
||||
@@ -22,8 +22,8 @@ export default commandModule({
|
||||
required: true
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
const option = options[1].getString('texto', true)
|
||||
execute: async (ctx) => {
|
||||
const option = ctx.options.getString('texto', true)
|
||||
|
||||
await ctx.reply({content: 'Cargando...'})
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ComponentType, EmbedBuilder, GuildMember } from "discord.js";
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import rockpaperscissors from "rockpaperscissors-checker";
|
||||
|
||||
export default commandModule({
|
||||
name: 'rps',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Juega piedra papel tijeras con los panas',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -17,10 +17,10 @@ export default commandModule({
|
||||
required: true
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
// also the code is mine, I didn't steal from anyone
|
||||
let player1, player2, winner, bothResponded
|
||||
const option = options[1].getMember('usuario') as GuildMember
|
||||
let player1: number, player2: number, winner, bothResponded: boolean
|
||||
const option = ctx.options.getMember('usuario') as unknown as GuildMember
|
||||
if (ctx.user.id === option.id) {
|
||||
return await ctx.reply({content: `no puedes jugar contigo mismo 💀`, ephemeral: true})
|
||||
} else if (option.user.bot) {
|
||||
@@ -1,14 +1,13 @@
|
||||
import TicTacToe from 'discord-tictactoe';
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ApplicationCommandOptionType, ChatInputCommandInteraction, CommandInteraction, Interaction } from "discord.js";
|
||||
|
||||
import { ApplicationCommandOptionType } from "discord.js";
|
||||
const game = new TicTacToe({language: 'en'})
|
||||
|
||||
export default commandModule({
|
||||
name: 'tictactoe',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'tres en raya',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -8,7 +8,7 @@ import { execa } from 'execa';
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.CtxMsg,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
execute: async (ctx) => {
|
||||
await ctx.deferReply({ fetchReply: true })
|
||||
|
||||
@@ -22,11 +22,11 @@ export default commandModule({
|
||||
const randomnumber = random(5)
|
||||
const randomnumber_wav = `bonzi-wav-${randomnumber}.wav`
|
||||
const randomnumber_mp3 = `bonzi-mp3-${randomnumber}.mp3`
|
||||
fs.writeFileSync(`./util/bonzi_temp/${randomnumber_wav}`, new Uint8Array(request))
|
||||
fs.writeFileSync(`./src/util/bonzi_temp/${randomnumber_wav}`, new Uint8Array(request))
|
||||
const command = execa('ffmpeg', [
|
||||
'-i', `./util/bonzi_temp/${randomnumber_wav}`,
|
||||
'-i', `./src/util/bonzi_temp/${randomnumber_wav}`,
|
||||
'-vn',
|
||||
`./util/bonzi_temp/${randomnumber_mp3}`
|
||||
`./src/util/bonzi_temp/${randomnumber_mp3}`
|
||||
], { shell: true })
|
||||
await new Promise((resolve) => {
|
||||
command.on('close', resolve)
|
||||
@@ -34,12 +34,12 @@ export default commandModule({
|
||||
|
||||
const stream = new Readable();
|
||||
stream._read = () => {};
|
||||
stream.push(Buffer.from(new Uint8Array(fs.readFileSync(`./util/bonzi_temp/${randomnumber_mp3}`))));
|
||||
stream.push(Buffer.from(new Uint8Array(fs.readFileSync(`./src/util/bonzi_temp/${randomnumber_mp3}`))));
|
||||
stream.push(null)
|
||||
|
||||
const attachment = new AttachmentBuilder(stream, { name: 'bonzied.mp3' })
|
||||
fs.unlinkSync(`./util/bonzi_temp/${randomnumber_mp3}`)
|
||||
fs.unlinkSync(`./util/bonzi_temp/${randomnumber_wav}`)
|
||||
fs.unlinkSync(`./src/util/bonzi_temp/${randomnumber_mp3}`)
|
||||
fs.unlinkSync(`./src/util/bonzi_temp/${randomnumber_wav}`)
|
||||
|
||||
await ctx.editReply({ files: [attachment] })
|
||||
},
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
EmbedBuilder,
|
||||
TextChannel,
|
||||
} from 'discord.js';
|
||||
|
||||
export default commandModule({
|
||||
@@ -53,11 +52,14 @@ export default commandModule({
|
||||
.setLabel('Añadido a la whitelist!')
|
||||
.setStyle(ButtonStyle.Success)
|
||||
);
|
||||
(
|
||||
(await (
|
||||
await modal.client.guilds.fetch(process.env.GUILDID!)
|
||||
).channels.fetch(process.env.MCFORM_CHANNEL!)) as TextChannel
|
||||
).send({ embeds: [embed], components: [button] });
|
||||
const guild = await modal.client.guilds.fetch(process.env.GUILDID!);
|
||||
const channel = await guild.channels.fetch(process.env.MCFORM_CHANNEL!);
|
||||
if (channel && channel.isTextBased()) {
|
||||
await channel.send({
|
||||
embeds: [embed],
|
||||
components: [button],
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
await modal.reply({
|
||||
content:
|
||||
@@ -15,7 +15,7 @@ export default commandModule({
|
||||
// @ts-ignore
|
||||
).options.map((o: { label: string; value: string }) => o.value);
|
||||
|
||||
const member = interaction.member as GuildMember;
|
||||
const member = interaction.member! as unknown as GuildMember;
|
||||
if (!member) return;
|
||||
|
||||
let content = `Los roles han sido actualizados. Te he dado estos:\n${roles
|
||||
@@ -1,7 +1,6 @@
|
||||
import { commandModule, CommandType } from '@sern/handler';
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from 'discord.js';
|
||||
import {
|
||||
TextChannel,
|
||||
ThreadAutoArchiveDuration,
|
||||
} from 'discord.js';
|
||||
|
||||
@@ -52,10 +51,17 @@ export default commandModule({
|
||||
.setStyle(ButtonStyle.Secondary),
|
||||
)
|
||||
|
||||
const message1 = await (await modal.client.guilds.fetch(process.env.GUILDID!))
|
||||
.channels.fetch(process.env.SUGGESTIONS_CHANNEL!) as TextChannel;
|
||||
const message2 = await message1.send({ embeds: [embed], components: [row, row2] });
|
||||
message2.startThread({
|
||||
const guild = await modal.client.guilds.fetch(process.env.GUILDID!);
|
||||
const channel = await guild.channels.fetch(process.env.SUGGESTIONS_CHANNEL!);
|
||||
if (!channel || !channel.isTextBased()) {
|
||||
return await modal.reply({
|
||||
content: 'ERROR: Canal de sugerencias no encontrado.',
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
||||
const msg = await channel.send({ embeds: [embed], components: [row, row2] });
|
||||
msg.startThread({
|
||||
name: `Sugerencia de ${modal.user.username}`,
|
||||
autoArchiveDuration: ThreadAutoArchiveDuration.ThreeDays,
|
||||
reason: 'AUTOMATIZADO: Hilo para discutir sobre la sugerencia.',
|
||||
@@ -1,11 +1,11 @@
|
||||
import { commandModule, CommandType } from "@sern/handler";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonComponentData, ButtonInteraction, ButtonStyle, ComponentType } from "discord.js";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonComponent, ButtonComponentData, ButtonStyle } from "discord.js";
|
||||
import db from "../../schemas/suggestions.js";
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Button,
|
||||
async execute(interaction) {
|
||||
const convertToNumber = Number(interaction.component.label!)
|
||||
const convertToNumber = Number((interaction.component as ButtonComponent).label!)
|
||||
const row2 = new ActionRowBuilder<ButtonBuilder>().setComponents(
|
||||
new ButtonBuilder(interaction.message!.components[1].components[0].data as ButtonComponentData),
|
||||
new ButtonBuilder(interaction.message!.components[1].components[1].data as ButtonComponentData)
|
||||
@@ -1,5 +1,4 @@
|
||||
import { commandModule, CommandType } from "@sern/handler";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, ComponentType } from "discord.js";
|
||||
import db from "../../schemas/suggestions.js";
|
||||
|
||||
export default commandModule({
|
||||
@@ -1,11 +1,11 @@
|
||||
import { commandModule, CommandType } from "@sern/handler";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonComponentData, ButtonInteraction, ButtonStyle, ComponentType } from "discord.js";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonComponent, ButtonComponentData, ButtonStyle } from "discord.js";
|
||||
import db from "../../schemas/suggestions.js";
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Button,
|
||||
async execute(interaction) {
|
||||
const convertToNumber = Number(interaction.component.label!)
|
||||
const convertToNumber = Number((interaction.component as ButtonComponent).label!)
|
||||
const row2 = new ActionRowBuilder<ButtonBuilder>().setComponents(
|
||||
new ButtonBuilder(interaction.message!.components[1].components[0].data as ButtonComponentData),
|
||||
new ButtonBuilder(interaction.message!.components[1].components[1].data as ButtonComponentData)
|
||||
@@ -1,16 +1,10 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ApplicationCommandOptionType } from "discord.js";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: 'ip',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
//
|
||||
description: 'La IP del servidor de Minecraft',
|
||||
options: [
|
||||
@@ -22,7 +16,7 @@ export default commandModule({
|
||||
],
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
const usuario = options[1].getMember('usuario');
|
||||
const usuario = ctx.options.getMember('usuario');
|
||||
|
||||
if (!usuario) {
|
||||
await ctx.reply({content: "La IP del servidor de Minecraft es `minecraft.maraturing.com`,\nPide acceso con el comando </mcform:1000747672690499594>.", ephemeral: true})
|
||||
@@ -6,13 +6,11 @@ import {
|
||||
TextInputStyle,
|
||||
ModalActionRowComponentBuilder,
|
||||
} from 'discord.js';
|
||||
import { publish } from '#plugins';
|
||||
import { ownerOnly } from '#plugins';
|
||||
|
||||
export default commandModule({
|
||||
name: 'mcform',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Envia el formulario para entrar al servidor.',
|
||||
//alias : [],
|
||||
execute: async (ctx) => {
|
||||
@@ -1,16 +1,10 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
import db from '../../schemas/afk.js';
|
||||
import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js';
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'afk command',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -38,11 +32,11 @@ export default commandModule({
|
||||
type: ApplicationCommandOptionType.Subcommand
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
switch (options[1].getSubcommand()) {
|
||||
execute: async (ctx) => {
|
||||
switch (ctx.options.getSubcommand()) {
|
||||
case 'añadir': {
|
||||
if (await db.exists({ id: ctx.user.id })) return ctx.reply({ content: 'Ya existes en la base de datos!', ephemeral: true })
|
||||
const reason = options[1].getString('motivo', true);
|
||||
const reason = ctx.options.getString('motivo');
|
||||
|
||||
await (new db({ id: ctx.user.id, reason: reason })).save()
|
||||
const embed = new EmbedBuilder()
|
||||
@@ -11,16 +11,15 @@ import {
|
||||
ModalSubmitInteraction,
|
||||
ApplicationCommandOptionType,
|
||||
} from 'discord.js';
|
||||
import { publish } from '#plugins';
|
||||
import { ownerOnly } from '#plugins';
|
||||
import padyama from '../../schemas/padyama.js';
|
||||
import { random } from '../../util/randomstring.js';
|
||||
import { disable } from '#plugins';
|
||||
|
||||
export default commandModule({
|
||||
name: 'askjavi',
|
||||
type: CommandType.Slash,
|
||||
plugins: [
|
||||
// publish(),
|
||||
disable()
|
||||
],
|
||||
description: 'TEMP: Pregunta a Javi LO QUE SEA!',
|
||||
//alias : [],
|
||||
@@ -63,7 +62,7 @@ export default commandModule({
|
||||
],
|
||||
},
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
switch (ctx.interaction.options.getSubcommand()) {
|
||||
case 'new': {
|
||||
const modal = new ModalBuilder()
|
||||
@@ -110,7 +109,7 @@ export default commandModule({
|
||||
time: 180000,
|
||||
filter: (i) => i.user.id === ctx.user.id,
|
||||
})
|
||||
.catch((error) => {})) as ModalSubmitInteraction;
|
||||
.catch((error) => {})) as unknown as ModalSubmitInteraction;
|
||||
const db = new padyama({
|
||||
id: i.user.id,
|
||||
user: i.user.username,
|
||||
@@ -132,7 +131,7 @@ export default commandModule({
|
||||
});
|
||||
}
|
||||
case 'get': {
|
||||
const option = options[1].getString('id');
|
||||
const option = ctx.options.getString('id');
|
||||
const db = await padyama.findOne({ suggestionid: option });
|
||||
if (db?.suggestion !== undefined)
|
||||
return await ctx.reply({
|
||||
@@ -160,7 +159,7 @@ export default commandModule({
|
||||
content: `No puedes usar este comando.`,
|
||||
ephemeral: true,
|
||||
});
|
||||
const option = options[1].getString('id');
|
||||
const option = ctx.options.getString('id');
|
||||
const db = await padyama.findOne({ suggestionid: option });
|
||||
if (db?.user !== undefined) {
|
||||
try {
|
||||
@@ -1,16 +1,14 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { Context, SlashOptions } from "@sern/handler";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
|
||||
import { publish } from "#plugins";
|
||||
|
||||
export default commandModule({
|
||||
name: 'creditos',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Créditos del bot (en inglés)',
|
||||
//alias : [],
|
||||
options: [],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
const baseEmbed = new EmbedBuilder()
|
||||
.setColor('Blurple')
|
||||
.setTitle(`Without these people, the bot wouldn't exist!`)
|
||||
@@ -1,18 +1,13 @@
|
||||
import { commandModule, CommandType } from "@sern/handler";
|
||||
import { publish } from "#plugins";
|
||||
import { ApplicationCommandOptionType } from "discord.js";
|
||||
import { readFileSync } from "node:fs";
|
||||
import birthdays from "../../schemas/birthdays.js";
|
||||
import { acceptingBirthday } from "#plugins";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
name: "cumple",
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), acceptingBirthday()],
|
||||
plugins: [acceptingBirthday()],
|
||||
description: "Pon tu cumpleaños en la base de datos para ser felicitado!",
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -43,7 +38,7 @@ export default commandModule({
|
||||
},
|
||||
},
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
const option = ctx.interaction.options.getString("fecha")
|
||||
const array = JSON.parse(
|
||||
String(readFileSync("./util/daysinyear.txt"))
|
||||
@@ -1,12 +1,10 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { ApplicationCommandOptionType, ColorResolvable, EmbedBuilder } from 'discord.js';
|
||||
import { publish } from "#plugins";
|
||||
import fs from 'node:fs';
|
||||
import mctags from '../../util/tags/minecraft.json' assert { type: 'json' }
|
||||
import mctags from '../../../assets/mcTags.json' with { type: "json" };
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Preguntas normalmente preguntadas :pepega:',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -40,11 +38,11 @@ export default commandModule({
|
||||
]
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
switch (options[1].getSubcommand()) {
|
||||
execute: async (ctx) => {
|
||||
switch (ctx.options.getSubcommand()) {
|
||||
case 'minecraft': {
|
||||
const option = options[1].getString('pregunta', true)
|
||||
const forusr = options[1].getMember('para')
|
||||
const option = ctx.options.getString('pregunta', true)
|
||||
const forusr = ctx.options.getMember('para')
|
||||
const filter = mctags.filter(obj => obj.title.includes(option))[0]
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
@@ -1,15 +1,10 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import google from 'googlethis'
|
||||
import { ApplicationCommandOptionType } from 'discord.js';
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Busca cosas en Google.',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -20,9 +15,9 @@ export default commandModule({
|
||||
required: true,
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
await ctx.interaction.deferReply()
|
||||
const prompt = options[1].getString('busqueda', true)
|
||||
const prompt = ctx.options.getString('busqueda', true)
|
||||
|
||||
const search = await Promise.all((await google.search(prompt)).results.map(res => {
|
||||
return `[${res.title}](<${res.url}>)`
|
||||
56
src/commands/misc/imageClassification.ts
Normal file
56
src/commands/misc/imageClassification.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { commandModule, CommandType } from '@sern/handler';
|
||||
import { publish } from '#plugins';
|
||||
import { AttachmentBuilder, codeBlock } from 'discord.js';
|
||||
import { createCanvas, loadImage } from '@napi-rs/canvas';
|
||||
import sharp from 'sharp';
|
||||
|
||||
export default commandModule({
|
||||
name: 'Clasifica una imagen',
|
||||
type: CommandType.CtxMsg,
|
||||
plugins: [],
|
||||
execute: async (ctx) => {
|
||||
await ctx.deferReply()
|
||||
|
||||
if (ctx.targetMessage.attachments.size === 0) return ctx.editReply('No hay ninguna imagen para clasificar!');
|
||||
const image = ctx.targetMessage.attachments.first()!;
|
||||
if (!image.contentType!.startsWith('image/') && image.contentType !== 'image/gif') return ctx.editReply('El archivo no es una imagen!');
|
||||
|
||||
const imageBuffer = await fetch(image.url).then(async res => await res.arrayBuffer());
|
||||
const compressed = sharp(imageBuffer)
|
||||
.png({quality: 70})
|
||||
.jpeg({quality: 70})
|
||||
.webp({quality: 70})
|
||||
.tiff({quality: 70});
|
||||
const metadata = await compressed.metadata();
|
||||
const imageUint8Array = new Uint8Array(await compressed.toBuffer());
|
||||
|
||||
const request = await fetch(`https://api.cloudflare.com/client/v4/accounts/${process.env.CF_AI_ACC}/ai/run/@cf/facebook/detr-resnet-50`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.CF_AI_TOKEN}`,
|
||||
},
|
||||
body: imageUint8Array,
|
||||
}).then(async res => await res.json());
|
||||
if (request.errors.length > 0) return ctx.editReply(`Hubo un error! ${codeBlock(JSON.stringify(request.errors))}`);
|
||||
|
||||
// all canvas stuff, this was fun to make
|
||||
const canvas = createCanvas(metadata.width!, metadata.height!);
|
||||
const ctxCanvas = canvas.getContext('2d');
|
||||
const img = await loadImage(image.url);
|
||||
ctxCanvas.drawImage(img, 0, 0, metadata.width!, metadata.height!);
|
||||
ctxCanvas.font = '40px sans-serif';
|
||||
ctxCanvas.fillStyle = 'red';
|
||||
ctxCanvas.strokeStyle = 'red';
|
||||
ctxCanvas.lineWidth = 3;
|
||||
for (const result of request.result) {
|
||||
if (result.score < 0.5) continue;
|
||||
const box = result.box;
|
||||
ctxCanvas.strokeRect(box.xmin, box.ymin, box.xmax - box.xmin, box.ymax - box.ymin);
|
||||
ctxCanvas.fillText(result.label, box.xmin, box.ymin - 5);
|
||||
}
|
||||
const canvasBuffer = canvas.toBuffer('image/png');
|
||||
const attachment = new AttachmentBuilder(canvasBuffer, { name: 'generatedImage.png' });
|
||||
|
||||
await ctx.editReply({ files: [attachment] })
|
||||
},
|
||||
});
|
||||
97
src/commands/misc/infinitecraft.ts
Normal file
97
src/commands/misc/infinitecraft.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { commandModule, CommandType } from '@sern/handler';
|
||||
import { ApplicationCommandOptionType, bold, codeBlock, EmbedBuilder, inlineCode } from 'discord.js';
|
||||
import fs from 'node:fs/promises'
|
||||
import { ICFile } from '../../util/infinitecraft/decompress.js';
|
||||
import Finder from '../../util/infinitecraft/finder.js';
|
||||
|
||||
const recipeFile = JSON.parse(await fs.readFile('./assets/icRecipes.json', 'utf-8')) as ICFile;
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [],
|
||||
description: 'Descifra con un algoritmo cómo llegar a la receta de un objeto en InfiniteCraft',
|
||||
options: [
|
||||
{
|
||||
name: 'objeto',
|
||||
description: 'El objeto que quieres descifrar',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true,
|
||||
autocomplete: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
async execute(ctx) {
|
||||
const input = ctx.options.getFocused();
|
||||
const choices = recipeFile.items
|
||||
.filter(item => item.toLowerCase().includes(input.toLowerCase()))
|
||||
.slice(0, 25)
|
||||
if (choices.length === 0) return ctx.respond([{ name: 'No se encontraron resultados', value: 'SSError' }]);
|
||||
if (input.length === 0) return ctx.respond([{ name: 'Empieza a escribir', value: 'SSError' }]);
|
||||
await ctx.respond(
|
||||
choices.map(choice => {
|
||||
return ({ name: choice, value: choice })
|
||||
})
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
execute: async (ctx) => {
|
||||
await ctx.interaction.deferReply()
|
||||
const object = ctx.options.getString('objeto', true)
|
||||
if (object === 'SSError') return ctx.reply({
|
||||
content: 'Has escogido el mensaje de error 💀',
|
||||
ephemeral: true
|
||||
});
|
||||
if (!recipeFile.items.includes(ctx.options.getString('objeto', true))) return ctx.reply({
|
||||
content: 'No se encontró el objeto. Asegúrate de escogerlo del autocompletado.',
|
||||
ephemeral: true
|
||||
});
|
||||
|
||||
let processed = 0
|
||||
let timesBacked = 0
|
||||
const infinitePath = new Finder((progress) => {
|
||||
switch (progress.phase) {
|
||||
case 0:
|
||||
processed = progress.current
|
||||
break;
|
||||
case 1:
|
||||
timesBacked = timesBacked + 1
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
||||
const interval = setInterval(() => {
|
||||
ctx.interaction.editReply({
|
||||
content: `Procesando...\n${inlineCode(processed.toString())} recetas procesadas, ${inlineCode(timesBacked.toString())} veces retrocedido.`,
|
||||
})
|
||||
}, 1250)
|
||||
ctx.interaction.editReply({
|
||||
content: `Procesando...\n${inlineCode(processed.toString())} recetas procesadas, ${inlineCode(timesBacked.toString())} veces retrocedido.`,
|
||||
})
|
||||
const initialTime = performance.now()
|
||||
const path = await infinitePath.findItem(object)
|
||||
const finalTime = performance.now()
|
||||
clearInterval(interval)
|
||||
if (path.length === 0) return ctx.interaction.editReply({
|
||||
content: 'No se encontró la receta de este objeto.'
|
||||
});
|
||||
|
||||
const recipe = path.map(({ first, second, result }) => `${first} + ${second} = ${result}`).join('\n')
|
||||
let paste: string | undefined;
|
||||
if (recipe.length >= 1500) {
|
||||
paste = await fetch('https://fb.srizan.dev/paste', {
|
||||
method: 'POST',
|
||||
body: recipe
|
||||
}).then(async res => await res.text())
|
||||
}
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`Receta de ${object.toLowerCase()}`)
|
||||
.setColor('Green')
|
||||
.setDescription(paste ? `La ruta es demasiado grande, así que lo he puesto en un pastebin:\nhttps://fb.srizan.dev/${paste}` : codeBlock(recipe))
|
||||
.setFooter({ text: 'Ya que se usa un algoritmo, puede o no ser la ruta más rápida para llegar al ítem' })
|
||||
return ctx.interaction.editReply({
|
||||
embeds: [embed],
|
||||
content: `Por fin encontrado! La búsqueda tomó ${bold(((finalTime - initialTime) / 1000).toFixed(2))} segundos.`
|
||||
})
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import Genius from 'genius-lyrics'
|
||||
import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, EmbedBuilder } from 'discord.js';
|
||||
|
||||
@@ -7,7 +6,7 @@ const genius = new Genius.Client(process.env.GENIUS)
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Busca la letra de una canción (Genius)',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -34,9 +33,9 @@ export default commandModule({
|
||||
}
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
await ctx.interaction.deferReply({ ephemeral: true })
|
||||
const prompt = options[1].getString('busqueda', true)
|
||||
const prompt = ctx.options.getString('busqueda', true)
|
||||
|
||||
const result = await genius.songs.get(Number(prompt))
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { createAudioPlayer, createAudioResource, DiscordGatewayAdapterCreator, joinVoiceChannel } from "@discordjs/voice";
|
||||
import got from "got";
|
||||
import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js";
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
const choices = ['Rock FM', 'Cadena 100', 'Cadena Dial', 'Gensokyo Radio', 'BBC 1', 'RNE 1', 'RNE 5', 'Los 40'];
|
||||
|
||||
export default commandModule({
|
||||
name: 'radio',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Reproduce la radio',
|
||||
options: [
|
||||
{
|
||||
@@ -24,7 +20,6 @@ export default commandModule({
|
||||
onEvent: [],
|
||||
async execute(ctx){
|
||||
const focusedValue = ctx.options.getFocused();
|
||||
const choices = ['Rock FM', 'Cadena 100', 'Cadena Dial', 'Gensokyo Radio', 'BBC 1', 'RNE 1', 'RNE 5', 'Los 40', 'Flaixbac', 'FlaixFM'];
|
||||
const filtered = choices.filter(choice => choice.startsWith(focusedValue));
|
||||
await ctx.respond(
|
||||
filtered.map(choice => ({ name: choice, value: choice })),
|
||||
@@ -33,8 +28,9 @@ export default commandModule({
|
||||
}
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
const radioname = options[1].getString("reproducir", true)
|
||||
execute: async (ctx) => {
|
||||
const radioname = ctx.options.getString("reproducir", true)
|
||||
if (!choices.includes(radioname)) return await ctx.reply('Asegúrate de escoger una radio de la lista.')
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor("Green")
|
||||
.setTitle(`Reproduciendo ${radioname} en Vinci Radio.`)
|
||||
@@ -44,18 +40,14 @@ export default commandModule({
|
||||
.setTitle(`Radio ${radioname} no encontrada.`)
|
||||
.setDescription(`La radio no ha sido encontrada, asegúrate que la radio está escogida de la lista.`);
|
||||
|
||||
async function playRadio(radioname: string, isFlaix?: boolean) {
|
||||
async function playRadio(radioname: string) {
|
||||
const stream = got.stream(radioname)
|
||||
const connection = joinVoiceChannel({adapterCreator: ctx.interaction.guild!.voiceAdapterCreator as DiscordGatewayAdapterCreator, channelId: '1008730592835281009',guildId: '928018226330337280',selfDeaf: true});
|
||||
const resource = createAudioResource(stream, { inlineVolume: true });
|
||||
const player = createAudioPlayer();
|
||||
connection.subscribe(player)
|
||||
player.play(resource)
|
||||
if (isFlaix === true) {
|
||||
resource.volume!.setVolume(0.3)
|
||||
} else {
|
||||
resource.volume!.setVolume(0.7)
|
||||
}
|
||||
resource.volume!.setVolume(0.7)
|
||||
await ctx.reply({embeds: [embed], ephemeral: true})
|
||||
}
|
||||
|
||||
@@ -84,12 +76,6 @@ export default commandModule({
|
||||
case 'Gensokyo Radio': {
|
||||
playRadio('https://stream.gensokyoradio.net/3')
|
||||
} break;
|
||||
case 'Flaixbac': {
|
||||
playRadio('https://nodo07-cloud01.streaming-pro.com:8005/flaixbac.mp3', true)
|
||||
} break;
|
||||
case 'FlaixFM': {
|
||||
playRadio('https://nodo07-cloud01.streaming-pro.com:8001/flaixfm.mp3', true)
|
||||
} break;
|
||||
default: {
|
||||
await ctx.reply({embeds: [notFoundEmbed], ephemeral: true})
|
||||
} break;
|
||||
@@ -1,13 +1,13 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ActionRowBuilder, ApplicationCommandOptionType, ChannelType, Collection, EmbedBuilder, Role, SelectMenuBuilder, TextChannel } from "discord.js";
|
||||
import { ActionRowBuilder, ApplicationCommandOptionType, ChannelType, ChatInputCommandInteraction, Collection, EmbedBuilder, Role, StringSelectMenuBuilder, TextChannel } from "discord.js";
|
||||
import { Resolver } from "../../util/resolver.js";
|
||||
|
||||
export default commandModule({
|
||||
name: 'rolemenu',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
plugins: [ownerOnly()],
|
||||
description: 'ADMIN: Spawnea un menú de roles',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -31,11 +31,13 @@ export default commandModule({
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
const channel = options[1].getChannel("channel", true) as TextChannel;
|
||||
const role = new Resolver(options[1].getString("role", true), ctx.interaction)
|
||||
execute: async (ctx) => {
|
||||
const channel = ctx.options.getChannel("channel", true) as unknown as TextChannel;
|
||||
if (!channel.isSendable()) return ctx.reply("Channel is not sendable");
|
||||
// @ts-ignore it should still be a correct interaction
|
||||
const role = new Resolver(ctx.options.getString("role", true), ctx.interaction)
|
||||
.roles;
|
||||
const message = options[1].getString("message", true);
|
||||
const message = ctx.options.getString("message", true);
|
||||
|
||||
if (role.size > 25) return ctx.reply("Too many roles");
|
||||
|
||||
@@ -50,6 +52,7 @@ export default commandModule({
|
||||
);
|
||||
}
|
||||
await ctx.interaction.deferReply();
|
||||
// @ts-ignore it should still be a textchannel
|
||||
const row = createMenu(channel, role);
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(message)
|
||||
@@ -67,7 +70,7 @@ export default commandModule({
|
||||
|
||||
function createMenu(channel: TextChannel, role: Collection<string, Role>) {
|
||||
if (!channel || !role) throw new Error("Missing channel or role");
|
||||
const menu = new SelectMenuBuilder()
|
||||
const menu = new StringSelectMenuBuilder()
|
||||
.setCustomId("role-menu")
|
||||
.setMaxValues(role.size)
|
||||
.setMinValues(0)
|
||||
@@ -80,6 +83,6 @@ function createMenu(channel: TextChannel, role: Collection<string, Role>) {
|
||||
};
|
||||
})
|
||||
);
|
||||
const row = new ActionRowBuilder<SelectMenuBuilder>().setComponents(menu);
|
||||
const row = new ActionRowBuilder<StringSelectMenuBuilder>().setComponents(menu);
|
||||
return row;
|
||||
};
|
||||
@@ -1,13 +1,13 @@
|
||||
import { commandModule, CommandType } from "@sern/handler";
|
||||
import axios, { AxiosError, AxiosResponse } from "axios";
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
import { ApplicationCommandOptionType } from "discord.js";
|
||||
import { publish } from "#plugins";
|
||||
import { disable } from "#plugins";
|
||||
|
||||
export default commandModule({
|
||||
name: "acortar",
|
||||
type: CommandType.Slash,
|
||||
plugins: [
|
||||
publish(),
|
||||
disable()
|
||||
],
|
||||
description: "Acorta una URL a vinci.tk",
|
||||
options: [
|
||||
@@ -20,7 +20,7 @@ export default commandModule({
|
||||
],
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
const url = options[1].getString("url", true);
|
||||
const url = ctx.options.getString("url", true);
|
||||
const request = await axios(
|
||||
`https://vinci.tk/yourls-api.php?signature=${process.env.YOURLS_KEY}&action=shorturl&format=json&url=${url}`,
|
||||
{
|
||||
@@ -1,14 +1,14 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { disable } from "#plugins";
|
||||
import { EmbedBuilder } from "discord.js";
|
||||
import axios from "axios";
|
||||
// @ts-ignore
|
||||
import prettySeconds from 'pretty-seconds-spanish'
|
||||
|
||||
export default commandModule({
|
||||
name: 'stats',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [disable()],
|
||||
description: 'Enseña estadísticas del bot.',
|
||||
//alias : [],
|
||||
options: [],
|
||||
@@ -1,13 +1,11 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ModalActionRowComponentBuilder } from 'discord.js'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
|
||||
|
||||
export default commandModule({
|
||||
name: 'sugerencias',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Envia una sugerencia.',
|
||||
//alias : [],
|
||||
execute: async (ctx) => {
|
||||
@@ -1,18 +1,12 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins";
|
||||
|
||||
import axios from 'axios';
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ComponentType, EmbedBuilder } from 'discord.js';
|
||||
const choices = ['es', 'en', 'fr', 'de', 'hi', 'it', 'ja', 'ko', 'pl']
|
||||
/*
|
||||
import { publish } from "#plugins";
|
||||
import { ownerOnly } from "#plugins"
|
||||
*/
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
// , '928018226330337280'
|
||||
description: 'Traduce lo que quieras!',
|
||||
//alias : [],
|
||||
@@ -44,9 +38,9 @@ export default commandModule({
|
||||
}
|
||||
}
|
||||
],
|
||||
execute: async (ctx, options) => {
|
||||
const langToTranslate = options[1].getString('idioma', true)
|
||||
const stringToTranslate = options[1].getString('frase', true)
|
||||
execute: async (ctx) => {
|
||||
const langToTranslate = ctx.options.getString('idioma', true)
|
||||
const stringToTranslate = ctx.options.getString('frase', true)
|
||||
if (choices.indexOf(langToTranslate) === -1)
|
||||
return ctx.reply({content: 'Elige un idioma del autocompletado.'})
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
// @ts-ignore
|
||||
import prettySeconds from 'pretty-seconds-spanish'
|
||||
|
||||
export default commandModule({
|
||||
name: 'uptime',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Enseña el tiempo que ha estado encendido el bot.',
|
||||
//alias : [],
|
||||
options: [],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
// const uptime = prettyMilliseconds(ctx.client.uptime!)
|
||||
const uptime = prettySeconds(process.uptime())
|
||||
await ctx.reply(`El bot lleva encendido ${uptime}`);
|
||||
@@ -1,11 +1,10 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
import { ApplicationCommandOptionType } from 'discord.js';
|
||||
import { getWikipedia, searchWikipedia, SearchWikipediaObject } from '../../util/wikipedia.js';
|
||||
import { ApplicationCommandOptionType, AutocompleteInteraction, CacheType, CommandInteractionOptionResolver } from 'discord.js';
|
||||
import { getWikipedia, searchWikipedia } from '../../util/wikipedia.js';
|
||||
|
||||
export default commandModule({
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'Busca cosas por wikipedia',
|
||||
//alias : [],
|
||||
options: [
|
||||
@@ -23,7 +22,7 @@ export default commandModule({
|
||||
command: {
|
||||
onEvent: [],
|
||||
execute: async (ctx) => {
|
||||
const search = await searchWikipedia('es', ctx)
|
||||
const search = await searchWikipedia('es', ctx as unknown as AutocompleteInteraction)
|
||||
await ctx.respond(
|
||||
search.map(res => ({ name: res.title.toString(), value: res.pageid.toString() }))
|
||||
)
|
||||
@@ -46,7 +45,7 @@ export default commandModule({
|
||||
command: {
|
||||
onEvent: [],
|
||||
execute: async (ctx) => {
|
||||
const search = await searchWikipedia('en', ctx)
|
||||
const search = await searchWikipedia('en', ctx as unknown as AutocompleteInteraction)
|
||||
await ctx.respond(
|
||||
search.map(res => ({ name: res.title.toString(), value: res.pageid.toString() }))
|
||||
)
|
||||
@@ -56,13 +55,14 @@ export default commandModule({
|
||||
]
|
||||
}
|
||||
],
|
||||
execute: async (ctx, [, options]) => {
|
||||
switch (options.getSubcommand()) {
|
||||
execute: async (ctx) => {
|
||||
const options = ctx.options as unknown as CommandInteractionOptionResolver<CacheType>
|
||||
switch (ctx.options.getSubcommand()) {
|
||||
case 'español': {
|
||||
getWikipedia('es', ctx, options)
|
||||
getWikipedia('es', ctx, options);
|
||||
} break;
|
||||
case 'ingles': {
|
||||
getWikipedia('en', ctx, options)
|
||||
getWikipedia('en', ctx, options);
|
||||
} break;
|
||||
}
|
||||
},
|
||||
@@ -1,12 +1,12 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins";;
|
||||
import { ApplicationCommandOptionType, TextChannel } from 'discord.js'
|
||||
|
||||
export default commandModule({
|
||||
name: 'prune',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
plugins: [ownerOnly()],
|
||||
description: 'ADMIN: Elimina hasta 100 mensajes',
|
||||
options: [{
|
||||
name: 'numero',
|
||||
@@ -17,14 +17,14 @@ export default commandModule({
|
||||
max_value: 100
|
||||
}],
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
try {
|
||||
const amount = options[1].getNumber('numero', true) as number
|
||||
(ctx.channel as TextChannel).bulkDelete(amount).catch(err => {
|
||||
const amount = ctx.options.getNumber('numero', true) as number
|
||||
(ctx.channel as unknown as TextChannel).bulkDelete(amount).catch(err => {
|
||||
console.error(err);
|
||||
ctx.reply({content: 'Ha habido un error eliminando mensajes! (mira la consola, Sr Izan)', ephemeral: true});});
|
||||
await ctx.reply({content: `Se han eliminado ${amount} mensajes.`})
|
||||
const sendToMods = ctx.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.MODLOGS_CHANNEL!) as TextChannel
|
||||
const sendToMods = ctx.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.MODLOGS_CHANNEL!) as unknown as TextChannel
|
||||
await sendToMods.send({content: `Se han eliminado ${amount} mensajes en ${ctx.channel}\nEfectuado por ${ctx.user}.`})
|
||||
} catch {
|
||||
ctx.reply({content: 'Ha habido un error eliminando mensajes! Error reportado automáticamente.', ephemeral: true})};
|
||||
@@ -1,12 +1,12 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins";
|
||||
import { ApplicationCommandOptionType, TextChannel } from "discord.js";
|
||||
|
||||
export default commandModule({
|
||||
name: 'slowmode',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish(), ownerOnly()],
|
||||
plugins: [ownerOnly()],
|
||||
description: 'ADMIN: Pon modo lento a canales de texto',
|
||||
options: [
|
||||
{
|
||||
@@ -23,15 +23,15 @@ export default commandModule({
|
||||
}
|
||||
],
|
||||
//alias : [],
|
||||
execute: async (ctx, options) => {
|
||||
execute: async (ctx) => {
|
||||
try {
|
||||
const seconds = options[1].getNumber("segundos", true);
|
||||
const reason = options[1].getString("razon", true);
|
||||
const seconds = ctx.options.getNumber("segundos", true);
|
||||
const reason = ctx.options.getString("razon", true);
|
||||
|
||||
(ctx.channel as TextChannel).setRateLimitPerUser(seconds, reason)
|
||||
(ctx.channel as unknown as TextChannel).setRateLimitPerUser(seconds, reason)
|
||||
|
||||
ctx.reply({content: `Se han añadido ${seconds} segundos de modo lento al canal de voz actual`})
|
||||
const sendToMods = ctx.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.MODLOGS_CHANNEL!) as TextChannel
|
||||
const sendToMods = ctx.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.MODLOGS_CHANNEL!) as unknown as TextChannel
|
||||
await sendToMods.send({content: `Se ha aplicado modo lento al canal ${ctx.channel}.\nEfectuado por ${ctx.user} con ${seconds} segundos de retardo.\nRazón: ${reason}`})
|
||||
} catch {
|
||||
ctx.reply({content: `No se ha podido aplicar modo lento al canal.`})
|
||||
@@ -1,11 +1,11 @@
|
||||
import { commandModule, CommandType } from '@sern/handler'
|
||||
import { publish } from "#plugins";
|
||||
|
||||
import { ownerOnly } from "#plugins"
|
||||
|
||||
export default commandModule({
|
||||
name: 'ping',
|
||||
type: CommandType.Slash,
|
||||
plugins: [publish()],
|
||||
plugins: [],
|
||||
description: 'A ping command',
|
||||
//alias : [],
|
||||
options: [],
|
||||
12
src/config.ts
Normal file
12
src/config.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
//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'
|
||||
|
||||
// schedule tasks and declare them here
|
||||
//export const tasks = './dist/tasks'
|
||||
|
||||
// defaultPrefix: if omitted, sern will disable all text/prefix commands
|
||||
//export const defaultPrefix = '?'
|
||||
24
src/dependencies.d.ts
vendored
Normal file
24
src/dependencies.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file serves as intellisense for sern projects.
|
||||
* Types are declared here for dependencies to function properly
|
||||
* Service(s) api rely on this file to provide a better developer experience.
|
||||
*/
|
||||
|
||||
import type { CoreDependencies } from '@sern/handler';
|
||||
import type { Client } from 'discord.js';
|
||||
import type { Publisher } from '@sern/publisher';
|
||||
import type Spotify from 'spotify-api.js';
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
declare global {
|
||||
interface Dependencies extends CoreDependencies {
|
||||
'@sern/client': Client;
|
||||
'publisher': Publisher;
|
||||
'spotify-api-client': Spotify.Client;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export {}
|
||||
@@ -1,11 +1,10 @@
|
||||
import { EventType, eventModule } from '@sern/handler';
|
||||
import { EventType, discordEvent, eventModule } from '@sern/handler';
|
||||
import { EmbedBuilder, Message } from 'discord.js';
|
||||
import db from '../schemas/afk.js';
|
||||
|
||||
export default eventModule({
|
||||
type: EventType.Discord,
|
||||
export default discordEvent({
|
||||
name: 'messageCreate',
|
||||
execute: async (message: Message) => {
|
||||
execute: async (message) => {
|
||||
const dbEntries = await db.find()
|
||||
|
||||
dbEntries.forEach(async (doc) => {
|
||||
101
src/events/chatgptMessage.ts
Normal file
101
src/events/chatgptMessage.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { discordEvent } from '@sern/handler';
|
||||
import db from '../schemas/chatgpt.js';
|
||||
import { fetchEventSource } from '@ai-zen/node-fetch-event-source';
|
||||
|
||||
export default discordEvent({
|
||||
name: 'messageCreate',
|
||||
async execute(message) {
|
||||
if (message.channel.id !== process.env.CHATGPT_CHANNEL) return;
|
||||
if (message.author.bot) return;
|
||||
if (message.content.includes('v!ig')) return;
|
||||
|
||||
const systemMsg =
|
||||
"You are Vinci, a helpful Discord bot assistant which tries to answer all questions that your users ask. You MUST speak naturally, if you were texting somebody. Don't tell the user that you are an assistant as they already know. Markdown is supported, including headers, codeblocks, etc. You will also chat with spanish speaking users, so your responses MUST, without exception, be in the spanish language, including your responses down the line.";
|
||||
try {
|
||||
await message.channel.sendTyping();
|
||||
const messages = [
|
||||
{ role: 'system', content: systemMsg },
|
||||
{ role: 'user', content: message.content },
|
||||
];
|
||||
|
||||
const ctrl = new AbortController();
|
||||
let msg = '';
|
||||
let isDone = false;
|
||||
|
||||
const sentMsg = await message.reply(':sparkles: Pensando...');
|
||||
message.channel.sendTyping();
|
||||
const sendInterval = setInterval(() => {
|
||||
if (msg.length > 2000 || msg.length === 0) return;
|
||||
message.channel.sendTyping();
|
||||
sentMsg.edit(msg);
|
||||
if (isDone) {
|
||||
clearTimeout(sendInterval);
|
||||
ctrl.abort();
|
||||
return;
|
||||
}
|
||||
}, 1000);
|
||||
fetchEventSource(
|
||||
`https://api.cloudflare.com/client/v4/accounts/${process.env.CF_AI_ACC}/ai/run/@cf/meta/llama-2-7b-chat-int8`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${process.env.CF_AI_TOKEN}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
stream: true,
|
||||
messages,
|
||||
}),
|
||||
onmessage: async (ev) => {
|
||||
if (ev.data === '[DONE]') {
|
||||
ctrl.abort();
|
||||
isDone = true;
|
||||
await sentMsg.edit({ content: msg });
|
||||
messages.push({ role: 'assistant', content: msg });
|
||||
const titleResponse = await fetch(
|
||||
`https://api.cloudflare.com/client/v4/accounts/${process.env.CF_AI_ACC}/ai/run/@hf/mistral/mistral-7b-instruct-v0.2`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${process.env.CF_AI_TOKEN}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
// the "else you'll die" part actually works well for the prompt!
|
||||
content: `Generate a title for the following conversation. Only respond with the title, else you'll die:\\nUser: ${message.content}\\nAssistant: ${msg}`,
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
).then(
|
||||
async (res) =>
|
||||
(await res.json()).result.response.replaceAll('"', '') as string
|
||||
);
|
||||
const thread = await sentMsg.startThread({ name: titleResponse.substring(0, 100) });
|
||||
|
||||
const dbData = new db({
|
||||
messageid: message.id,
|
||||
threadid: thread.id,
|
||||
messages: [
|
||||
{ role: 'system', content: systemMsg },
|
||||
{ role: 'user', content: message.content },
|
||||
{ role: 'assistant', content: msg.replace(/^\n{2}/, '') },
|
||||
],
|
||||
});
|
||||
await dbData.save();
|
||||
} else {
|
||||
const data = JSON.parse(ev.data);
|
||||
msg = msg + data.response;
|
||||
}
|
||||
},
|
||||
signal: ctrl.signal,
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
await message.reply({ content: 'Algo ha ido mal :(' }).catch(() => {});
|
||||
console.log(e);
|
||||
}
|
||||
},
|
||||
});
|
||||
72
src/events/chatgptThread.ts
Normal file
72
src/events/chatgptThread.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { discordEvent } from '@sern/handler';
|
||||
import { PublicThreadChannel } from 'discord.js';
|
||||
import database from '../schemas/chatgpt.js';
|
||||
import { fetchEventSource } from '@ai-zen/node-fetch-event-source';
|
||||
|
||||
export default discordEvent({
|
||||
name: 'messageCreate',
|
||||
async execute(message) {
|
||||
// @ts-ignore idk man
|
||||
const thread = message.channel as PublicThreadChannel<false>;
|
||||
if (thread.parentId !== process.env.CHATGPT_CHANNEL) return;
|
||||
if (message.author.bot) return;
|
||||
if (message.content.includes('v!ig')) return;
|
||||
|
||||
try {
|
||||
await thread.sendTyping()
|
||||
const newObj = [{ role: 'user', content: message.content }]
|
||||
const db = await database.findOne({ threadid: thread.id }).exec()
|
||||
const messages = db!.messages.map((message) => {
|
||||
const { _id, ...rest } = message.toObject();
|
||||
return rest
|
||||
})
|
||||
|
||||
const ctrl = new AbortController();
|
||||
let msg = ''
|
||||
let isDone = false
|
||||
|
||||
const sentMsg = await message.reply(':sparkles: Pensando...')
|
||||
const sendInterval = setInterval(() => {
|
||||
if (msg.length > 2000 || msg.length === 0) return
|
||||
thread.sendTyping()
|
||||
sentMsg.edit(msg)
|
||||
if (isDone) {
|
||||
clearTimeout(sendInterval)
|
||||
ctrl.abort()
|
||||
return
|
||||
}
|
||||
}, 1000)
|
||||
fetchEventSource(`https://api.cloudflare.com/client/v4/accounts/${process.env.CF_AI_ACC}/ai/run/@hf/mistral/mistral-7b-instruct-v0.2`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.CF_AI_TOKEN}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
stream: true,
|
||||
messages: messages.concat(newObj)
|
||||
}),
|
||||
onmessage: async (ev) => {
|
||||
if (ev.data === '[DONE]') {
|
||||
ctrl.abort()
|
||||
isDone = true
|
||||
newObj.push({ role: 'assistant', content: msg })
|
||||
await database.findOneAndUpdate({ threadid: thread.id }, {
|
||||
$push: {
|
||||
messages: newObj
|
||||
}
|
||||
}).exec()
|
||||
await sentMsg.edit({ content: msg })
|
||||
} else {
|
||||
const data = JSON.parse(ev.data)
|
||||
msg = msg + data.response
|
||||
}
|
||||
},
|
||||
signal: ctrl.signal
|
||||
})
|
||||
} catch (e) {
|
||||
await message.reply('Algo ha ido mal.')
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
});
|
||||
29
src/events/clean-spotify-link.ts
Normal file
29
src/events/clean-spotify-link.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Service, discordEvent } from '@sern/handler';
|
||||
import removeURLParameter from '../util/removeUrlParameter.js';
|
||||
|
||||
export default discordEvent({
|
||||
name: 'messageCreate',
|
||||
async execute(message) {
|
||||
const spotify = Service('spotify-api-client')
|
||||
if (message.author.bot) return;
|
||||
if (!message.content.includes('https://open.spotify.com/intl-es/track')) return;
|
||||
|
||||
const index = message.content.indexOf("https://open.spotify.com/intl-es/track");
|
||||
let link: string = ''
|
||||
if (index !== -1) {
|
||||
let endIndex = message.content.indexOf(" ", index);
|
||||
if (endIndex === -1) {
|
||||
endIndex = message.content.length;
|
||||
}
|
||||
link = message.content.substring(index, endIndex);
|
||||
}
|
||||
const croppedUrl = removeURLParameter(link.replace('intl-es/', '').replaceAll(/([^:]\/)\/+/g, "$1"), 'si');
|
||||
|
||||
const song = await spotify.tracks.get(croppedUrl.split('/').pop()!);
|
||||
|
||||
await message.delete();
|
||||
message.channel.send({
|
||||
content: `Oye <@${message.author.id}>, tu canción \`${song!.name}\` de \`${song!.artists.map(a => a.name).join(', ')}\` es muy buena, pero si quitas \`intl-es\` es mejor.\n${croppedUrl}`,
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -6,4 +6,4 @@ export default eventModule({
|
||||
execute(err) {
|
||||
console.log(err);
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -1,20 +1,19 @@
|
||||
import { EmbedBuilder, GuildMember, TextChannel } from "discord.js";
|
||||
|
||||
import { EventType, eventModule } from "@sern/handler";
|
||||
import { EventType, discordEvent, eventModule } from "@sern/handler";
|
||||
|
||||
export default eventModule({
|
||||
type: EventType.Discord,
|
||||
export default discordEvent({
|
||||
name: 'guildMemberAdd',
|
||||
execute(member: GuildMember) {
|
||||
execute(member) {
|
||||
if (member.guild.id !== process.env.GUILDID) return;
|
||||
const newMemberEmbed = new EmbedBuilder()
|
||||
const newMemberEmbed = new EmbedBuilder()
|
||||
.setColor("Random")
|
||||
.setTitle("Nuevo miembro!")
|
||||
.setDescription(`${member.user} acaba de entrar al servidor!`)
|
||||
.setThumbnail(member.user.displayAvatarURL())
|
||||
.setTimestamp();
|
||||
|
||||
const channel = member.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.JOINSANDLEAVES_CHANNEL!) as TextChannel
|
||||
const channel = member.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.JOINSANDLEAVES_CHANNEL!) as unknown as TextChannel
|
||||
channel.send({embeds: [newMemberEmbed]})
|
||||
}
|
||||
});
|
||||
@@ -1,20 +1,19 @@
|
||||
import { EmbedBuilder, GuildMember, TextChannel } from "discord.js";
|
||||
|
||||
import { EventType, eventModule } from "@sern/handler";
|
||||
import { EventType, discordEvent, eventModule } from "@sern/handler";
|
||||
|
||||
export default eventModule({
|
||||
type: EventType.Discord,
|
||||
export default discordEvent({
|
||||
name: 'guildMemberRemove',
|
||||
execute(member: GuildMember) {
|
||||
execute(member) {
|
||||
if (member.guild.id !== process.env.GUILDID) return;
|
||||
const leaveEmbed = new EmbedBuilder()
|
||||
const leaveEmbed = new EmbedBuilder()
|
||||
.setColor("Random")
|
||||
.setTitle("Un miembro se ha ido :(")
|
||||
.setDescription(`${member.user} acaba de salir del servidor!`)
|
||||
.setThumbnail(member.user.displayAvatarURL())
|
||||
.setTimestamp();
|
||||
|
||||
const channel = member.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.JOINSANDLEAVES_CHANNEL!) as TextChannel
|
||||
const channel = member.client.guilds.cache.get(process.env.GUILDID!)!.channels.cache.get(process.env.JOINSANDLEAVES_CHANNEL!) as unknown as TextChannel
|
||||
channel.send({embeds: [leaveEmbed]})
|
||||
}
|
||||
});
|
||||
10
src/events/t.ts
Normal file
10
src/events/t.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { discordEvent } from '@sern/handler';
|
||||
|
||||
export default discordEvent({
|
||||
name: 'messageCreate',
|
||||
async execute(msg) {
|
||||
if (msg.channel.id !== process.env.T_CHANNEL) return;
|
||||
if (msg.content !== 'T')
|
||||
return await msg.delete();
|
||||
}
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DefaultLogging, makeDependencies, single, Singleton } from '@sern/handler';
|
||||
import { makeDependencies } from '@sern/handler';
|
||||
import { ActivityOptions, ActivityType } from 'discord.js';
|
||||
import { Client, GatewayIntentBits } from 'discord.js';
|
||||
import { Sern } from '@sern/handler';
|
||||
@@ -8,10 +8,11 @@ import youtubenotifications from './util/youtubenotifications.js';
|
||||
import { setIntervalAsync } from 'set-interval-async';
|
||||
import birthdays from './util/birthdays.js';
|
||||
import minecraftstatus from './util/minecraftstatus.js';
|
||||
import axios from 'axios';
|
||||
// import giveawaychecker from './util/giveawaychecker.js';
|
||||
import Spotify from 'spotify-api.js';
|
||||
import { Publisher } from '@sern/publisher';
|
||||
import * as sernconfig from './config.js'
|
||||
|
||||
let devMode: boolean
|
||||
export let devMode: boolean
|
||||
if (process.argv[2] === '--dev') {
|
||||
devMode = true
|
||||
dotenv({path: '.env.dev'})
|
||||
@@ -36,20 +37,21 @@ mongoose.connect(process.env.MONGODB!).then(() => {
|
||||
console.log('Connected to MongoDB');
|
||||
});
|
||||
|
||||
interface MyDependencies extends Dependencies {
|
||||
'@sern/client' : Singleton<Client>;
|
||||
'@sern/logger' : Singleton<DefaultLogging>
|
||||
}
|
||||
const spotifyClient = await Spotify.Client.create({
|
||||
token: { clientID: process.env.SPOTIFY_CLIENT!, clientSecret: process.env.SPOTIFY_SECRET! },
|
||||
})
|
||||
|
||||
await makeDependencies<MyDependencies>({
|
||||
build: (root) => root.add({ '@sern/client': single(() => client) }),
|
||||
await makeDependencies(({ add }) => {
|
||||
add('@sern/client', client);
|
||||
add('publisher', deps => new Publisher(
|
||||
deps['@sern/modules'],
|
||||
deps['@sern/emitter'],
|
||||
deps['@sern/logger']!
|
||||
));
|
||||
add('spotify-api-client', spotifyClient);
|
||||
});
|
||||
|
||||
Sern.init({
|
||||
commands: 'dist/commands',
|
||||
events: 'dist/events',
|
||||
defaultPrefix: process.env.PREFIX,
|
||||
});
|
||||
Sern.init(sernconfig);
|
||||
|
||||
client.on('ready', async () => {
|
||||
console.log('Logged on!');
|
||||
@@ -58,14 +60,14 @@ client.on('ready', async () => {
|
||||
const statuses = [
|
||||
{ name: 'Minecraft', type: ActivityType.Playing },
|
||||
{ name: 'cómo escribe Javi', type: ActivityType.Watching },
|
||||
{ name: 'quinto libro when', type: ActivityType.Watching },
|
||||
{ name: 'sexto libro when', type: ActivityType.Watching },
|
||||
{ name: 'a Hermes', type: ActivityType.Watching },
|
||||
{ name: 'tus comandos', type: ActivityType.Listening },
|
||||
{ name: 'tu voz', type: ActivityType.Listening },
|
||||
{ name: 'ahora v1.0!', type: ActivityType.Playing },
|
||||
] as ActivityOptions[];
|
||||
const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];
|
||||
client.user.setActivity(randomStatus);
|
||||
client.user!.setActivity(randomStatus);
|
||||
}, 10000);
|
||||
|
||||
if (!devMode) {
|
||||
@@ -85,6 +87,6 @@ client.on('ready', async () => {
|
||||
}
|
||||
});
|
||||
|
||||
export const scamLinks = await axios.get('https://api.hyperphish.com/gimme-domains').then(res => res.data as Array<string>)
|
||||
// export const scamLinks = await axios.get('https://api.hyperphish.com/gimme-domains').then(res => res.data as Array<string>)
|
||||
|
||||
client.login(process.env.TOKEN);
|
||||
client.login();
|
||||
80
src/plugins/disable.ts
Normal file
80
src/plugins/disable.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
//@ts-nocheck
|
||||
/**
|
||||
* @plugin
|
||||
* Disables a command entirely, for whatever reasons you may need.
|
||||
*
|
||||
* @author @jacoobes [<@182326315813306368>]
|
||||
* @author @Peter-MJ-Parker [<@371759410009341952>]
|
||||
* @version 2.1.0
|
||||
* @example
|
||||
* ```ts
|
||||
* import { disable } from "../plugins/disable";
|
||||
* import { commandModule } from "@sern/handler";
|
||||
* export default commandModule({
|
||||
* plugins: [ disable() ],
|
||||
* execute: (ctx) => {
|
||||
* //your code here
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
* @end
|
||||
*/
|
||||
import { CommandType, CommandControlPlugin, controller } from "@sern/handler";
|
||||
import { InteractionReplyOptions, MessageReplyOptions } from "discord.js";
|
||||
|
||||
export function disable(
|
||||
onFail?:
|
||||
| string
|
||||
| Omit<InteractionReplyOptions, "fetchReply">
|
||||
| MessageReplyOptions
|
||||
) {
|
||||
return CommandControlPlugin<CommandType.Both>(async (ctx, [args]) => {
|
||||
if (onFail !== undefined) {
|
||||
switch (args) {
|
||||
case "text":
|
||||
try {
|
||||
//reply to text command
|
||||
const msg = await ctx.reply(onFail);
|
||||
setTimeout(() => {
|
||||
//deletes the bots reply to the user
|
||||
msg.delete();
|
||||
//deletes the original authors message (text command).
|
||||
ctx.message.delete();
|
||||
//waits 5 seconds before deleting messages
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"Could not delete disabled response due to: " +
|
||||
error
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "slash":
|
||||
//response to say the command is disabled with users response.
|
||||
let reply = await ctx.reply(onFail);
|
||||
try {
|
||||
setTimeout(async () => {
|
||||
await reply.delete();
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"Could not delete disabled response due to it being ephemeral."
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
//this function tells the bot to reply to an interaction so it doesn't seem like it fails (in case there is no onFail message).
|
||||
if (onFail === undefined && args === "slash") {
|
||||
onFail = "This command is disabled.";
|
||||
await ctx.reply({ content: onFail, ephemeral: true });
|
||||
}
|
||||
//stop the command from running
|
||||
return controller.stop();
|
||||
});
|
||||
}
|
||||
@@ -2,3 +2,4 @@ export * from './publish.js'
|
||||
export * from './ownerOnly.js'
|
||||
export * from './srIzanOnly.js'
|
||||
export * from './acceptingBirthday.js'
|
||||
export * from './disable.js'
|
||||
@@ -1,7 +1,7 @@
|
||||
import mongoose from 'mongoose'
|
||||
const messageSchema = new mongoose.Schema({
|
||||
role: { type: String, required: true },
|
||||
content: { type: String, required: true },
|
||||
content: { type: String, reqmuired: true },
|
||||
});
|
||||
const schema = new mongoose.Schema({
|
||||
messageid: { type: String, required: true },
|
||||
20
src/util/infinitecraft/decompress.ts
Normal file
20
src/util/infinitecraft/decompress.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export async function decompressRecipes(file: ICFile) {
|
||||
const recipes = file.recipes;
|
||||
const items = file.items;
|
||||
return recipes.map((recipe) => ({
|
||||
first: items[recipe[0]]!,
|
||||
second: items[recipe[1]]!,
|
||||
result: items[recipe[2]]!,
|
||||
})) as Recipe[];
|
||||
}
|
||||
|
||||
export interface Recipe {
|
||||
first: string;
|
||||
second: string;
|
||||
result: string;
|
||||
}
|
||||
|
||||
export interface ICFile {
|
||||
recipes: number[][];
|
||||
items: string[];
|
||||
}
|
||||
203
src/util/infinitecraft/finder.ts
Normal file
203
src/util/infinitecraft/finder.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
// code based off of: https://github.com/vantezzen/infinite-craft-solver/blob/main/apps/web/lib/Finder.ts
|
||||
// thanks to @vantezzen for such a cool algo
|
||||
import fs from 'fs/promises'
|
||||
import { ICFile, decompressRecipes } from './decompress.js';
|
||||
|
||||
export interface Recipe {
|
||||
first: string;
|
||||
second: string;
|
||||
result: string;
|
||||
}
|
||||
|
||||
export enum FinderPhase {
|
||||
Search,
|
||||
Backtrack,
|
||||
}
|
||||
|
||||
export interface FinderProgess {
|
||||
current: number;
|
||||
phase: FinderPhase;
|
||||
}
|
||||
|
||||
export default class Finder {
|
||||
private DEFAULT_ITEMS = ["Water", "Fire", "Wind", "Earth"];
|
||||
private recipes: Recipe[] = []; // Array to store all recipes
|
||||
private recipeMap: Map<string, Recipe[]> = new Map(); // Map to store recipes for each item
|
||||
private recipesLoaded: boolean = false; // Flag to check if recipes are loaded
|
||||
public items = new Set<string>(this.DEFAULT_ITEMS);
|
||||
|
||||
constructor(
|
||||
private onProgress: (progress: FinderProgess) => void = () => {}
|
||||
) {}
|
||||
|
||||
private async loadRecipes() {
|
||||
const file = JSON.parse(await fs.readFile("./assets/icRecipes.json", "utf-8")) as ICFile
|
||||
this.recipes = await decompressRecipes(file);
|
||||
this.items = new Set<string>(file.items);
|
||||
for (const recipe of this.recipes) {
|
||||
if (!this.recipeMap.has(recipe.result)) {
|
||||
this.recipeMap.set(recipe.result, []);
|
||||
}
|
||||
this.recipeMap.get(recipe.result)!.push(recipe);
|
||||
}
|
||||
|
||||
this.recipesLoaded = true;
|
||||
}
|
||||
|
||||
async findItem(targetItem: string) {
|
||||
if (this.DEFAULT_ITEMS.includes(targetItem)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!this.recipesLoaded) {
|
||||
await this.loadRecipes();
|
||||
}
|
||||
|
||||
if (!this.items.has(targetItem)) {
|
||||
throw new Error("Item not found");
|
||||
}
|
||||
|
||||
const path = await this.findShortestPath(targetItem);
|
||||
if (!path) {
|
||||
throw new Error("Item cannot be crafted");
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
private async findShortestPath(targetItem: string): Promise<Recipe[] | null> {
|
||||
const itemQueue: {
|
||||
item: string;
|
||||
recipe: Recipe | null;
|
||||
}[] = this.DEFAULT_ITEMS.map((item) => ({
|
||||
item,
|
||||
recipe: null,
|
||||
}));
|
||||
const recipesUsed = new Set<Recipe>();
|
||||
const discoveredItems = new Set<string>(this.DEFAULT_ITEMS);
|
||||
let itemsProcessed = 0;
|
||||
|
||||
const updateInterval = setInterval(() => {
|
||||
this.onProgress({
|
||||
current: itemsProcessed,
|
||||
phase: FinderPhase.Search,
|
||||
});
|
||||
}, 100);
|
||||
|
||||
let cleanedRecipes = this.recipes.filter((recipe) => {
|
||||
const isCircularRecipe =
|
||||
recipe.first === recipe.result || recipe.second === recipe.result;
|
||||
|
||||
const containsNothing =
|
||||
recipe.first === "Nothing" ||
|
||||
recipe.second === "Nothing" ||
|
||||
recipe.result === "Nothing";
|
||||
|
||||
return !isCircularRecipe && !containsNothing;
|
||||
});
|
||||
|
||||
while (itemQueue.length > 0) {
|
||||
itemsProcessed++;
|
||||
const { item, recipe } = itemQueue.shift()!;
|
||||
|
||||
if (item === targetItem) {
|
||||
// console.log("Found path", recipesUsed.size);
|
||||
clearInterval(updateInterval);
|
||||
return await this.backtrackPath(targetItem, recipe, [...recipesUsed]);
|
||||
}
|
||||
|
||||
cleanedRecipes.forEach((recipe) => {
|
||||
const hasDiscoveredItems =
|
||||
discoveredItems.has(recipe.first) &&
|
||||
discoveredItems.has(recipe.second);
|
||||
if (!hasDiscoveredItems) return;
|
||||
|
||||
const resultAlreadyDiscovered = discoveredItems.has(recipe.result);
|
||||
if (resultAlreadyDiscovered) return;
|
||||
|
||||
discoveredItems.add(recipe.result);
|
||||
|
||||
recipesUsed.add(recipe);
|
||||
itemQueue.push({
|
||||
item: recipe.result,
|
||||
recipe,
|
||||
});
|
||||
});
|
||||
|
||||
cleanedRecipes = cleanedRecipes.filter(
|
||||
(r) => !recipesUsed.has(r) && !discoveredItems.has(r.result)
|
||||
);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
|
||||
clearInterval(updateInterval);
|
||||
return null;
|
||||
}
|
||||
|
||||
private async backtrackPath(
|
||||
targetItem: string,
|
||||
recipe: Recipe | null,
|
||||
recipesUsed: Recipe[]
|
||||
): Promise<Recipe[]> {
|
||||
if (!recipe) {
|
||||
return [];
|
||||
}
|
||||
// "recipesUsed" contains recipes that are not part of the shortest path to the target item
|
||||
// We want to backtrack from the target item to the source items (this.DEFAULT_ITEMS) to find the shortest path
|
||||
|
||||
const recipes: Recipe[] = [recipe];
|
||||
const itemQueue = [recipe?.first, recipe?.second];
|
||||
const discoveredItems = new Set<string>([targetItem]);
|
||||
|
||||
const updateInfo = () => {
|
||||
this.onProgress({
|
||||
current: recipes.length,
|
||||
phase: FinderPhase.Backtrack,
|
||||
});
|
||||
};
|
||||
|
||||
const updateInterval = setInterval(() => {
|
||||
updateInfo();
|
||||
}, 50);
|
||||
updateInfo();
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
while (itemQueue.length > 0) {
|
||||
const item = itemQueue.shift()!;
|
||||
|
||||
if (this.DEFAULT_ITEMS.includes(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const recipeUsedForItem = recipesUsed.find(
|
||||
(recipe) => recipe.result === item
|
||||
);
|
||||
if (!recipeUsedForItem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
recipes.push(recipeUsedForItem);
|
||||
discoveredItems.add(recipeUsedForItem.first);
|
||||
discoveredItems.add(recipeUsedForItem.second);
|
||||
itemQueue.push(recipeUsedForItem.first, recipeUsedForItem.second);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
|
||||
clearInterval(updateInterval);
|
||||
return this.removeDuplicates(recipes.reverse());
|
||||
}
|
||||
|
||||
private removeDuplicates(path: Recipe[]): Recipe[] {
|
||||
const seen = new Set<string>();
|
||||
return path.filter((recipe) => {
|
||||
const key = `${recipe.first}-${recipe.second}-${recipe.result}`;
|
||||
if (seen.has(key)) {
|
||||
return false;
|
||||
}
|
||||
seen.add(key);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user