Compare commits

...

109 Commits

Author SHA1 Message Date
045c89a6cb chore: some prompt stuff
Some checks failed
Publish Docker image / Push Docker image to Docker Hub (push) Failing after 33s
2026-04-03 23:30:07 +02:00
8dcd2de683 chore: switch models again 2026-04-03 23:28:39 +02:00
e3c63632a1 chore: switch models 2026-04-03 23:27:13 +02:00
a6df2e4f31 fix: dont use the imports
Some checks failed
Publish Docker image / Push Docker image to Docker Hub (push) Failing after 13m0s
2026-04-02 17:47:59 +02:00
502811ca9f fix: disable scripts 2026-04-02 17:44:54 +02:00
58dd540ea9 fix: use bun 2026-04-02 17:42:24 +02:00
589f53c65c fix: install sern cli 2026-04-02 17:41:17 +02:00
66594ce8bd chore: run db migrations 2026-04-02 17:32:25 +02:00
effbe7d9c5 feat: the rewrite (#55) 2026-04-02 17:09:04 +02:00
0e8703629d fix: use node instead of nodemon
Some checks failed
Publish Docker image / Push Docker image to Docker Hub (push) Has been cancelled
2025-09-08 22:58:22 +02:00
b20a969dee chore: nixpacks deployment 2025-09-08 22:44:01 +02:00
b82784608f fix: racoon and capybara images command 2024-10-04 16:55:31 +02:00
ea1d086fd0 fix: docker builds 2 2024-09-20 19:42:21 +02:00
b84260901d fix: docker builds 2024-09-20 19:37:32 +02:00
8ac9c16945 refactor: basically everything, move to src dir, move to sern build, publisher, v4, fix commands 2024-09-20 19:32:03 +02:00
8aeebb1164 fix: v ig on thread 2024-07-28 17:57:39 +02:00
fa23042c99 ci: update docker yml 2024-07-28 15:12:10 +02:00
2aafce2429 docs: remove discordapp attachment 2024-07-20 00:01:34 +02:00
8d5c962049 fix: some random bugs 2024-07-09 23:36:57 +02:00
37d983e150 chore: change model to mistral 2024-07-09 23:29:24 +02:00
3b9acf6f29 chore: empty redeploy commit 2024-07-09 23:20:20 +02:00
51ea593bcd copy all 2024-04-23 19:42:23 +02:00
8112f232e3 add corepack 2024-04-23 19:39:45 +02:00
214c35a7e6 docker buildx 2024-04-23 19:37:19 +02:00
d208f6b8c7 fix: why is ts not installing 2024-04-23 19:31:55 +02:00
0b8f23cefd fix: update tsc version 2024-04-23 19:27:52 +02:00
c95ceb1539 chore: set version 2024-04-23 19:21:14 +02:00
0654ce2bfd fix: some small stuff 2024-04-23 17:20:06 +02:00
b84bd0a250 chore: change to v!ig instead of "ig" 2024-04-22 21:33:42 +02:00
8005ac0699 La year inactivity update! (#48)
* feat: non t message deletion

* feat: cloudflare ai!

* feat: image classification and llama 3

* feat: image classification and infinitecraft

* feat: add initial find and lower the paste length

* chore: add devServer boolean to gpt
2024-04-22 21:25:52 +02:00
ecada7600e fix: the goofy ahh youtube notifications bug 2024-04-02 19:54:22 +02:00
73e397be5b fix: util folder getting copied over to root 2023-11-29 20:36:19 +01:00
0f08d35876 chore: empty commit 2023-11-04 23:04:52 +01:00
116f0be0b2 feat: spotify link cleaner, bye scam links 2023-11-04 22:53:10 +01:00
43c0b40703 Merge pull request #39 from SrIzan10/snyk-fix-f8a2f0a23fb4b30c3b5997999e893e30
[Snyk] Security upgrade systeminformation from 5.17.12 to 5.21.7
2023-10-11 22:06:44 +02:00
snyk-bot
10aa847aba fix: package.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-SYSTEMINFORMATION-5914637
2023-09-22 17:01:02 +00:00
d786e40af3 fix: ts type errors and migrate to v3 2023-09-04 16:41:45 +02:00
a2e1f7d9ac fix: various stuff 2023-09-03 21:46:33 +02:00
309fa913c4 chore: oops 2023-08-18 15:46:36 +02:00
f4d759e9a8 chore: oops 2023-08-18 15:40:55 +02:00
c57db2e3ee Merge remote-tracking branch 'origin/main'
# Conflicts:
#	package-lock.json
2023-08-18 15:38:03 +02:00
f386532ed1 feat: new server migration (prayge) 2023-08-18 15:37:34 +02:00
c79f7e613f Merge pull request #37 from SrIzan10/snyk-fix-41c89fa0640a3f0da96f415704cb37fc
[Snyk] Security upgrade mongoose from 6.10.1 to 6.11.3
2023-07-26 14:27:16 +02:00
snyk-bot
1f9a7cdf2a fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-MONGOOSE-5777721
2023-07-26 12:26:56 +00:00
607ec84dd3 fix: really bad security vulnerability (yes commit in 1 month)
chore(deps): bump fast-xml-parser and @aws-sdk/credential-providers
2023-06-13 21:12:47 +02:00
dependabot[bot]
e08e6d0079 chore(deps): bump fast-xml-parser and @aws-sdk/credential-providers
Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) and [@aws-sdk/credential-providers](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/credential-providers). These dependencies needed to be updated together.

Updates `fast-xml-parser` from 4.1.2 to 4.2.4
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.1.2...v4.2.4)

Updates `@aws-sdk/credential-providers` from 3.282.0 to 3.351.0
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-providers/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.351.0/packages/credential-providers)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-type: indirect
- dependency-name: "@aws-sdk/credential-providers"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-13 19:11:37 +00:00
e94476e984 chore: add oliver to credits 2023-03-19 17:06:37 +01:00
99cfa39d6e chore: get back ig 2023-03-16 17:24:24 +01:00
c5919cf223 chore: remove ignoring thing 2023-03-16 17:07:53 +01:00
204ea32f23 fix: ignore messages 2023-03-15 21:31:37 +01:00
819fff74a9 feat: chatgpt functionality! 2023-03-15 18:29:12 +01:00
c880d16daf fix: minetools api certificate expired lol 2023-03-09 16:01:22 +01:00
fe839191cd fix: remove debug stuff 2023-03-04 18:23:56 +01:00
7dc203c046 fix: help 2023-03-04 18:13:52 +01:00
19ef02f88c fix: help 2023-03-04 18:00:45 +01:00
be5fc6db37 fix: bruh stop 2023-03-04 17:49:01 +01:00
84ee02e273 fix: take idk 2023-03-04 17:45:52 +01:00
2de7306e63 fix: dude 2023-03-04 17:35:47 +01:00
6a780c495b fix: take 4 2023-03-04 17:34:52 +01:00
de1aaf7ede fix: take 3 2023-03-04 17:33:44 +01:00
c2cdc1327d fix: i think thats it 2023-03-04 17:06:37 +01:00
39a3940683 fix: tryna fix vinci errors 2023-03-04 16:50:18 +01:00
878aef7e7a Merge branch 'main' of https://github.com/SrIzan10/vinci 2023-03-02 23:07:23 +01:00
337d739d56 feat: nsfw detection for images attached 2023-03-02 23:07:18 +01:00
365a5b4809 fix: two security vulnerabilities
chore(deps): bump undici from 5.14.0 to 5.20.0
2023-02-25 21:24:35 +01:00
dependabot[bot]
dcc8b2fceb chore(deps): bump undici from 5.14.0 to 5.20.0
Bumps [undici](https://github.com/nodejs/undici) from 5.14.0 to 5.20.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.14.0...v5.20.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-25 20:23:18 +00:00
1611b5e475 feat: lyrics, google and wikipedia command 2023-02-23 21:22:20 +01:00
594dd65adf fix: yt notifications and autocomplete 2023-02-14 15:50:58 +01:00
16ad8418e9 fix: bonzify sometimes returns 0 bytes 2023-02-10 19:02:07 +01:00
323eed54a7 feat: some random afk stuff 2023-02-10 18:56:22 +01:00
201ab3b13c feat: fix makesweet error 2023-02-10 17:08:39 +01:00
455bb4b4ef feat: even more storage saving 2023-02-09 17:18:46 +01:00
b1dcff540f chore: empty commit to change domain 2023-02-09 17:16:29 +01:00
94e5e87602 chore: save some more storage 2023-02-05 15:13:13 +01:00
9d381672e2 chore: dependency lock consumet extensions 2023-02-05 15:06:59 +01:00
ca20533534 feat: afk thing 2023-02-04 22:56:42 +01:00
0193f8da25 feat: change to dependabot 2023-02-04 20:55:56 +01:00
637e1b5bb5 chore: take 2 2023-02-04 19:48:09 +01:00
deb6f0a4b9 fix: gitkeep bonzitemp 2023-02-04 19:46:36 +01:00
9b0afc515f feat: bonzify now converts to mp3 2023-02-04 11:50:41 +01:00
61c1605af2 feat: update sern and bonzify 2023-02-03 21:23:34 +01:00
c6be2d9a87 feat: add and update As 2023-02-02 08:14:57 +01:00
cdec00ca82 fix: typos ofc 2023-01-28 19:30:03 +01:00
f19d514ed0 docs: shoutout to @sern-handler 2023-01-28 19:28:19 +01:00
77ae011307 feat: auto download gif using my API 2023-01-28 10:42:25 +01:00
242f680980 feat: compress images and fix typos 2023-01-27 23:36:54 +01:00
a17fd1aea4 feat: makesweet command (heart locket) 2023-01-25 17:13:34 +01:00
ce0c92b3f7 feat: minecraft server status 2023-01-14 23:54:50 +01:00
435f21b7f7 fix: typo 2023-01-14 14:13:55 +01:00
743c20ba28 feat: plot problem tag 2023-01-14 14:12:23 +01:00
525d7acfb5 feat: minecraft faq command 2023-01-13 21:42:33 +01:00
3d1e245331 feat: auto adapt text in megamind 2023-01-05 21:02:34 +01:00
6f96eec7fe feat: add Tormentica to /a 2023-01-05 13:41:50 +01:00
31378b91fe fix: mcform not sending 2022-12-31 20:53:54 +01:00
b3f5687ad9 fix: oh wait 2022-12-29 12:24:34 +01:00
1b55774ed2 feat: change to sern 2.0 2022-12-29 12:23:21 +01:00
8c146b2407 fix: lol what 2022-12-28 22:05:42 +01:00
81b4d8430a perf: don't pass errors if there's no need to 2022-12-28 13:12:19 +01:00
31fabf024f feat: more beautiful mcform 2022-12-28 13:09:31 +01:00
9ead07d208 Merge branch 'main' of https://github.com/SrIzan10/vinci 2022-12-26 18:20:34 +01:00
36bc63a403 chore: update vinci star count 2022-12-26 18:20:33 +01:00
c1eb347571 feat: removed word limit on megamind to crazy 2022-12-23 14:38:35 +01:00
36ea08ad34 refactor: more radio refactoring 2022-12-19 15:57:33 +01:00
750adabcc4 feat: add flaix group radios (and edited links) 2022-12-19 15:46:08 +01:00
eba657a24d fix: twitter just crashing oh my god i hate it 2022-12-12 16:47:48 +01:00
18b3a291e2 Merge branch 'main' of https://github.com/SrIzan10/vinci 2022-12-10 00:44:51 +01:00
f824d68175 feat: translation system 2022-12-10 00:44:49 +01:00
990fbb1b52 fix: twitter notification system 2022-12-09 17:50:43 +01:00
e70b4fb845 Merge pull request #23 from SrIzan10/snyk-upgrade-b69603f3219dffa0a0820dcd54b9a683 2022-12-06 21:35:04 +01:00
139 changed files with 1063018 additions and 8624 deletions

View File

@@ -0,0 +1,7 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"runArgs": ["--device=/dev/net/tun"],
"features": {
"ghcr.io/tailscale/codespace/tailscale": {}
}
}

9
.dockerignore Normal file
View File

@@ -0,0 +1,9 @@
.env*
node_modules/
json.sqlite
dist/
*giveaway*
.sern
/generated/generated/prisma
prisma/vinci.db
!.env.example

View File

@@ -1,6 +1,27 @@
TOKEN=token
PREFIX=v!
MONGODB=mongodb://
HYPIXEL_API=API_KEY
YOURLS_KEY=YOURLS_SIGNATURE
YOUTUBE_API=
DISCORD_TOKEN=
PREFIX=
# Database (before rewrites)
MONGODB=
# API keys
CATAPI=
DOGAPI=
TWITTER=
# request makesweet creator for this
MAKESWEET=
GENIUS=
SPOTIFY_CLIENT=
SPOTIFY_SECRET=
CF_AI_TOKEN=
CF_AI_ACC=
# Guild configs
GUILDID=
SUGGESTIONS_CHANNEL=
MODLOGS_CHANNEL=
JOINSANDLEAVES_CHANNEL=
SOCIALS_CHANNEL=
GIVEAWAYS_CHANNEL=
MCFORM_CHANNEL=
CHATGPT_CHANNEL=
T_CHANNEL=
NODE_ENV=development

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

56
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
name: Publish Docker image
on:
push:
branches:
- main
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: srizan10/vinci
tags: latest
- name: Build and push Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Emit a webhook to the server
env:
AUTH_HEADER: ${{ secrets.WHSERVER_TOKEN }}
run: |
curl -X POST \
-H "Authorization: $AUTH_HEADER" \
https://webhooks.srizan.dev/hooks/vinci

12
.gitignore vendored
View File

@@ -1,5 +1,11 @@
.env
.env.dev
.env*
node_modules/
json.sqlite
dist/
dist/
*giveaway*
.sern
/generated/generated/prisma
src/utils/db/dict.db
prisma/vinci.db
!.env.example
.codex

View File

@@ -1,5 +1,8 @@
{
"tabWidth": 2,
"useTabs": true,
"singleQuote": true
"useTabs": false,
"printWidth": 100,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "es5",
"semi": true
}

View File

@@ -1,3 +1,7 @@
{
"dotenv.enableAutocloaking": false
"dotenv.enableAutocloaking": false,
"editor.tabSize": 2,
"editor.detectIndentation": false,
"editor.insertSpaces": true,
"editor.rulers": [100]
}

View File

@@ -1,18 +1,39 @@
FROM node:lts-alpine
FROM oven/bun:alpine AS base
WORKDIR /app
RUN bun add -g @sern/cli
RUN apk add bash ffmpeg msttcorefonts-installer fontconfig
RUN update-ms-fonts && fc-cache -f
# Install dependencies
FROM base AS deps
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile --ignore-scripts
# Build the application
FROM base AS build
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN bun prisma generate
RUN bun run build
# Production image
FROM base AS runner
WORKDIR /app
COPY package.json ./
ENV NODE_ENV=production
RUN npm i
# Install system dependencies
RUN apk add --no-cache ffmpeg fontconfig ttf-opensans msttcorefonts-installer && \
update-ms-fonts && \
fc-cache -f
EXPOSE 7272
RUN mkdir -p ./src/utils/db && \
wget -O ./src/utils/db/dict.db https://github.com/SrIzan10/vinci/releases/download/dict-1/dict.db
COPY . .
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/assets ./assets
COPY --from=build /app/images ./images
COPY --from=build /app/.sern ./.sern
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/prisma ./prisma
RUN npm run build
CMD node ./dist/index.js
CMD ["sh", "-c", "bun run db:migrate && bun dist/index.js"]

View File

@@ -1,19 +1,46 @@
vinci bot
## badges yes sir
[![CodeFactor](https://www.codefactor.io/repository/github/srizan10/vinci/badge)](https://www.codefactor.io/repository/github/srizan10/vinci) [![wakatime](https://wakatime.com/badge/user/4ad16edf-eadc-48d9-b010-26f275fe0be6/project/120bd895-55e3-42fe-894b-bd974f6f7312.svg)](https://wakatime.com/badge/user/4ad16edf-eadc-48d9-b010-26f275fe0be6/project/120bd895-55e3-42fe-894b-bd974f6f7312)
# heres a roadmap
# vinci v2
- ~~form to apply for the minecraft server~~ DONE!
- ~~moderation commands~~ DONE!
- ~~welcome to users~~ DONE!
- modmail
- ~~socials notification system~~ DONE!
- chatbot using IBM's AI (thanks @gosevil for the idea)
- ~~joke command~~
<!--<img src="https://srizan.s-ul.eu/RddzT2f9">-->
Vinci v2 is a rewrite of my first JS project, a discord bot for [my favorite book series](https://maraturing.com) server. It aims to improve the code quality of the primary codebase, full of bugs and spaghetti code.
<img src="https://cdn.discordapp.com/attachments/928230817673641995/1036390945945559140/makesweet-hbt4h3.gif">
by @Oliverlg8
It is written, as always, under the [sern](https://sern.dev) framework.
9 stars! tysm!
It is 85% done, with hardest commands implemented.
This is a bot submission for [Converge](https://converge.hackclub.com) and [Summer of Making](https://summer.hackclub.com).
## New features
- More fun games
- Modern typescript and discord.js
- SQLite + Prisma instead of MongoDB + Mongoose
- Less API queries and more performance by using local datasets (like the Spanish dictionary)
# Available commands
- `/rolemenu` - Role selection menu (owner only)
- `/sugerencias` - Send a suggestion to the channel with upvote/downvote buttons
- `/mcform` - Submit a form to join a Minecraft server
- `/ip` - Get information about the Minecraft server IP
- `/acortar` - Shorten a URL
- `/wikipedia` - Search Wikipedia (Spanish/English)
- `/8ball` - Ask the magic 8-ball a question
- `/a` - Autogenerated "A" text with user autocomplete
- `/chiste` - Get a random joke from a local dataset
- `/google` - The most useless Google search command
- `/hangman` - Play a game of hangman
- `/makesweet` - Generate a heart locket image
- `/megamind` - Generate a Megamind meme with custom text
- `/palabra` - Returns a random Spanish word. That is it.
- `/rps` - Play rock paper scissors against someone
### Other stuff
- Bonzify - Text-to-speech with Bonzi Buddy voice
- Cursivify - Italicize message text
- Image classification - Classify images using Cloudflare AI
- AI chat - Chat with AI on a channel
## Development setup
1. Clone the repository
2. Run `bun install`
3. Install the sern cli: `npm install -g @sern/cli`
4. Create a copy of `.env.example` and rename it to `.env`
5. Fill in the file
6. Run `bunx prisma migrate dev` to set up the database
7. Run `bun dev`

55
TODO.md Normal file
View File

@@ -0,0 +1,55 @@
# Slash Commands
## Fun Commands
- [ ] /animal - Animal pictures with voting system (cat, dog, capybara, fox, raccoon)
- [x] /chiste - Joke command fetching from API
- [x] /rps - Rock Paper Scissors game
- [x] /8ball - Magic 8-ball responses
- [x] /megamind - Megamind meme generator with canvas
- [x] /makesweet - Heart locket image generator
- [x] /a - Custom command with user autocomplete
## Miscellaneous Commands
- [x] /rolemenu - Role selection menu (owner only)
- [ ] /creditos - Bot credits and acknowledgments
- [x] ~~/infinitecraft - InfiniteCraft recipe solver~~
- [ ] /letra - Song lyrics search via Genius API
- [x] /google - Google search results
- [x] /sugerencias - Suggestion system with upvote/downvote
- [x] /wikipedia - Wikipedia search (Spanish/English)
- [ ] /faq - FAQ system with Minecraft questions
- [ ] ~~/afk - AFK status management~~
- [x] /acortar - URL shortener
## Minecraft Commands
- [x] /ip - Minecraft server IP information
- [x] /mcform - Minecraft form submission
# Button Handlers
- [x] suggestions-yes - Upvote button handler
- [x] suggestions-no - Downvote button handler
- [x] suggestions-yes-who - Show upvoters
- [x] suggestions-no-who - Show downvoters
# Context Menu Commands
- [x] bonzify - Text-to-speech with Bonzi Buddy voice
- [x] cursivify - Italicize message text
- [x] image-classification - Cloudflare AI image classification
# Message driven functions
- [x] AI chat
# Utility Systems to Rewrite
- [x] Resolver - Role/user resolution utility
- [x] Wikipedia utility - Wikipedia search helper
# Background Services
- [x] ~YouTube notifications system~ using rss instead
- [x] Birthday checker service
- [x] Activity status rotation
# Database
- [x] Migration to sqlite
# Other
- [ ] Figure out fonts

1
assets/chistes.json Normal file

File diff suppressed because one or more lines are too long

1059783
assets/icRecipes.json Normal file

File diff suppressed because it is too large Load Diff

27
assets/mcTags.json Normal file
View File

@@ -0,0 +1,27 @@
[
{
"title": "Outdated client! I'm on 1.19.2",
"text": "Tu cliente de Minecraft está desactualizado.\nTienes que cerrarlo y elegir la versión 1.19.2 en tu launcher de confianza.",
"color": "#8B0000"
},
{
"title": "You are not whitelisted!",
"text": "No estás en la whitelist del servidor.\nTienes que poner el comando `/mcform` para que te acepten.\n**NO ES AUTOMÁTICO, LA VERIFICACIÓN ES HUMANA**",
"color": "#8B0000"
},
{
"title": "No me puedo mover!",
"text": "Tienes que registrarte o iniciar sesión con una contraseña.\n`/register tucontraseña` si es la primera vez que entras al server con esta nueva funcionalidad, `/login tucontraseña` para cuando te vuelvas a reconectar. Recuérdala!",
"color": "#8B0000"
},
{
"title": "No puedo entrar a nada en el garaje!",
"text": "<@375984365181599744> te tiene que dar el rol.\nMenciónale cuando esté conectado diciendo que te de el rol. Después espera un tiempo hasta que te lo de y listo.",
"color": "#8B0000"
},
{
"title": "No puedo hacer nada en mi plot! <:PANIK:1063806522993418300>",
"text": "Ha habido un problemilla en el sistema de plots, y eso ha hecho que se rompan todos los IDs de todos los plots del servidor.\nEsto significa que el plot no es tuyo.\nPuedes mencionar a <@375984365181599744> para que te configure de nuevo el plot.",
"color": "#8B0000"
}
]

584
bun.lock Normal file
View File

@@ -0,0 +1,584 @@
{
"lockfileVersion": 1,
"configVersion": 0,
"workspaces": {
"": {
"name": "ts-example",
"dependencies": {
"@napi-rs/canvas": "^0.1.72",
"@prisma/client": "^6.10.1",
"@sern/handler": "^4.2.4",
"@sern/publisher": "1.1.2",
"discord.js": "^14.21.0",
"dotenv": "^16.3.1",
"execa": "^9.6.0",
"mongodb": "^6.17.0",
"node-html-parser": "^7.0.1",
"openai": "^5.10.2",
"rockpaperscissors-checker": "^1.2.0",
"sharp": "^0.34.2",
},
"devDependencies": {
"@sern/cli": "^1.4.0",
"@types/bun": "^1.2.18",
"@types/mongodb": "^4.0.7",
"@types/node": "^17.0.25",
"prisma": "^6.10.1",
"typescript": "^5.0",
},
},
},
"packages": {
"@discordjs/builders": ["@discordjs/builders@1.11.2", "", { "dependencies": { "@discordjs/formatters": "^0.6.1", "@discordjs/util": "^1.1.1", "@sapphire/shapeshift": "^4.0.0", "discord-api-types": "^0.38.1", "fast-deep-equal": "^3.1.3", "ts-mixer": "^6.0.4", "tslib": "^2.6.3" } }, "sha512-F1WTABdd8/R9D1icJzajC4IuLyyS8f3rTOz66JsSI3pKvpCAtsMBweu8cyNYsIyvcrKAVn9EPK+Psoymq+XC0A=="],
"@discordjs/collection": ["@discordjs/collection@1.5.3", "", {}, "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ=="],
"@discordjs/formatters": ["@discordjs/formatters@0.6.1", "", { "dependencies": { "discord-api-types": "^0.38.1" } }, "sha512-5cnX+tASiPCqCWtFcFslxBVUaCetB0thvM/JyavhbXInP1HJIEU+Qv/zMrnuwSsX3yWH2lVXNJZeDK3EiP4HHg=="],
"@discordjs/rest": ["@discordjs/rest@2.5.1", "", { "dependencies": { "@discordjs/collection": "^2.1.1", "@discordjs/util": "^1.1.1", "@sapphire/async-queue": "^1.5.3", "@sapphire/snowflake": "^3.5.3", "@vladfrangu/async_event_emitter": "^2.4.6", "discord-api-types": "^0.38.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.3" } }, "sha512-Tg9840IneBcbrAjcGaQzHUJWFNq1MMWZjTdjJ0WS/89IffaNKc++iOvffucPxQTF/gviO9+9r8kEPea1X5J2Dw=="],
"@discordjs/util": ["@discordjs/util@1.1.1", "", {}, "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g=="],
"@discordjs/ws": ["@discordjs/ws@1.2.3", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.5.1", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.38.1", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw=="],
"@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="],
"@esbuild-kit/cjs-loader": ["@esbuild-kit/cjs-loader@2.4.4", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.2.3", "get-tsconfig": "^4.7.0" } }, "sha512-NfsJX4PdzhwSkfJukczyUiZGc7zNNWZcEAyqeISpDnn0PTfzMJR1aR8xAIPskBejIxBJbIgCCMzbaYa9SXepIg=="],
"@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
"@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.19.12", "", { "os": "android", "cpu": "arm" }, "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.19.12", "", { "os": "android", "cpu": "arm64" }, "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.19.12", "", { "os": "android", "cpu": "x64" }, "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.19.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.19.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.19.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.19.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.19.12", "", { "os": "linux", "cpu": "arm" }, "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.19.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.19.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.19.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.19.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.19.12", "", { "os": "linux", "cpu": "x64" }, "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.19.12", "", { "os": "none", "cpu": "x64" }, "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.19.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.19.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.19.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.19.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.19.12", "", { "os": "win32", "cpu": "x64" }, "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.1.0" }, "os": "darwin", "cpu": "arm64" }, "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg=="],
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.1.0" }, "os": "darwin", "cpu": "x64" }, "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g=="],
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.1.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA=="],
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.1.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ=="],
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.1.0", "", { "os": "linux", "cpu": "arm" }, "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA=="],
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew=="],
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.1.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ=="],
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.1.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA=="],
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q=="],
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w=="],
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A=="],
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.1.0" }, "os": "linux", "cpu": "arm" }, "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ=="],
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.1.0" }, "os": "linux", "cpu": "arm64" }, "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q=="],
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.1.0" }, "os": "linux", "cpu": "s390x" }, "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw=="],
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.1.0" }, "os": "linux", "cpu": "x64" }, "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ=="],
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" }, "os": "linux", "cpu": "arm64" }, "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA=="],
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.1.0" }, "os": "linux", "cpu": "x64" }, "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA=="],
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.2", "", { "dependencies": { "@emnapi/runtime": "^1.4.3" }, "cpu": "none" }, "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ=="],
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ=="],
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw=="],
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.2", "", { "os": "win32", "cpu": "x64" }, "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw=="],
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
"@mongodb-js/saslprep": ["@mongodb-js/saslprep@1.3.0", "", { "dependencies": { "sparse-bitfield": "^3.0.3" } }, "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ=="],
"@napi-rs/canvas": ["@napi-rs/canvas@0.1.72", "", { "optionalDependencies": { "@napi-rs/canvas-android-arm64": "0.1.72", "@napi-rs/canvas-darwin-arm64": "0.1.72", "@napi-rs/canvas-darwin-x64": "0.1.72", "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.72", "@napi-rs/canvas-linux-arm64-gnu": "0.1.72", "@napi-rs/canvas-linux-arm64-musl": "0.1.72", "@napi-rs/canvas-linux-riscv64-gnu": "0.1.72", "@napi-rs/canvas-linux-x64-gnu": "0.1.72", "@napi-rs/canvas-linux-x64-musl": "0.1.72", "@napi-rs/canvas-win32-x64-msvc": "0.1.72" } }, "sha512-ypTJ/DXzsJbTU3o7qXFlWmZGgEbh42JWQl7v5/i+DJz/HURELcSnq9ler9e1ukqma70JzmCQcIseiE/Xs6sczw=="],
"@napi-rs/canvas-android-arm64": ["@napi-rs/canvas-android-arm64@0.1.72", "", { "os": "android", "cpu": "arm64" }, "sha512-OW99TDJEdfOhpJWQ7SXFsQi1BXd6UFuWM8AoQvJ0SQMHWY/iwuopmb1UqGV6Df9aM/SWxvCWBN/onjeCM8KVKQ=="],
"@napi-rs/canvas-darwin-arm64": ["@napi-rs/canvas-darwin-arm64@0.1.72", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gB8Pn/4GdS+B6P4HYuNqPGx8iQJ16Go1D6e5hIxfUbA/efupVGZ7e3OMGWGCUgF0vgbEPEF31sPzhcad4mdR5g=="],
"@napi-rs/canvas-darwin-x64": ["@napi-rs/canvas-darwin-x64@0.1.72", "", { "os": "darwin", "cpu": "x64" }, "sha512-x1zKtWVSnf+yLETHdSDAFJ1w6bctS/V2NP0wskTTBKkC+c/AmI2Dl+ZMIW11gF6rilBibrIzBeXJKPzV0GMWGA=="],
"@napi-rs/canvas-linux-arm-gnueabihf": ["@napi-rs/canvas-linux-arm-gnueabihf@0.1.72", "", { "os": "linux", "cpu": "arm" }, "sha512-Ef6HMF+TBS+lqBNpcUj2D17ODJrbgevXaVPtr2nQFCao5IvoEhVMdmVwWk5YiI+GcgbAkg5AF3LiU47RoSY5yg=="],
"@napi-rs/canvas-linux-arm64-gnu": ["@napi-rs/canvas-linux-arm64-gnu@0.1.72", "", { "os": "linux", "cpu": "arm64" }, "sha512-i1tWu+Li1Z6G4t+ckT38JwuB/cAAREV6H8VD3dip2yTYU+qnLz6kG4i+whm+SEQb1e4vk3xA1lKnjYx3jlOy8g=="],
"@napi-rs/canvas-linux-arm64-musl": ["@napi-rs/canvas-linux-arm64-musl@0.1.72", "", { "os": "linux", "cpu": "arm64" }, "sha512-Mu+2hHZAT9SdrjiRtCxMD/Unac8vqVxF/p+Tvjb5sN1NZkLGu+l7WIfrug8aeX150OwrYgAvsR4mhrm0BZvLxg=="],
"@napi-rs/canvas-linux-riscv64-gnu": ["@napi-rs/canvas-linux-riscv64-gnu@0.1.72", "", { "os": "linux", "cpu": "none" }, "sha512-xBPG/ImL58I4Ep6VM+sCrpwl8rE/8e7Dt9U7zzggNvYHrWD13vIF3q5L2/N9VxdBMh1pee6dBC/VcaXLYccZNQ=="],
"@napi-rs/canvas-linux-x64-gnu": ["@napi-rs/canvas-linux-x64-gnu@0.1.72", "", { "os": "linux", "cpu": "x64" }, "sha512-jkC8L+QovHpzQrw+Jm1IUqxgLV5QB1hJ1cR8iYzxNRd0TOF7YfxLaIGxvd/ReRi9r48JT6PL7z2IGT7TqK8T4w=="],
"@napi-rs/canvas-linux-x64-musl": ["@napi-rs/canvas-linux-x64-musl@0.1.72", "", { "os": "linux", "cpu": "x64" }, "sha512-PwPdPmHgJYnTMUr8Gff80eRVdpGjwrxueIqw+7v4aeFxbQjmQ+paa2xaGedFtkvdS2Dn5z8a0mVlrlbSfec+1Q=="],
"@napi-rs/canvas-win32-x64-msvc": ["@napi-rs/canvas-win32-x64-msvc@0.1.72", "", { "os": "win32", "cpu": "x64" }, "sha512-hZhXJZZ/2ZjkAoOtyGUs3Mx6jA4o9ESbc5bk+NKYO6thZRvRNA7rqvT9WF9pZK0xcRK5EyWRymv8fCzqmSVEzg=="],
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
"@prisma/client": ["@prisma/client@6.10.1", "", { "peerDependencies": { "prisma": "*", "typescript": ">=5.1.0" }, "optionalPeers": ["prisma", "typescript"] }, "sha512-Re4pMlcUsQsUTAYMK7EJ4Bw2kg3WfZAAlr8GjORJaK4VOP6LxRQUQ1TuLnxcF42XqGkWQ36q5CQF1yVadANQ6w=="],
"@prisma/config": ["@prisma/config@6.10.1", "", { "dependencies": { "jiti": "2.4.2" } }, "sha512-kz4/bnqrOrzWo8KzYguN0cden4CzLJJ+2VSpKtF8utHS3l1JS0Lhv6BLwpOX6X9yNreTbZQZwewb+/BMPDCIYQ=="],
"@prisma/debug": ["@prisma/debug@6.10.1", "", {}, "sha512-k2YT53cWxv9OLjW4zSYTZ6Z7j0gPfCzcr2Mj99qsuvlxr8WAKSZ2NcSR0zLf/mP4oxnYG842IMj3utTgcd7CaA=="],
"@prisma/engines": ["@prisma/engines@6.10.1", "", { "dependencies": { "@prisma/debug": "6.10.1", "@prisma/engines-version": "6.10.1-1.9b628578b3b7cae625e8c927178f15a170e74a9c", "@prisma/fetch-engine": "6.10.1", "@prisma/get-platform": "6.10.1" } }, "sha512-Q07P5rS2iPwk2IQr/rUQJ42tHjpPyFcbiH7PXZlV81Ryr9NYIgdxcUrwgVOWVm5T7ap02C0dNd1dpnNcSWig8A=="],
"@prisma/engines-version": ["@prisma/engines-version@6.10.1-1.9b628578b3b7cae625e8c927178f15a170e74a9c", "", {}, "sha512-ZJFTsEqapiTYVzXya6TUKYDFnSWCNegfUiG5ik9fleQva5Sk3DNyyUi7X1+0ZxWFHwHDr6BZV5Vm+iwP+LlciA=="],
"@prisma/fetch-engine": ["@prisma/fetch-engine@6.10.1", "", { "dependencies": { "@prisma/debug": "6.10.1", "@prisma/engines-version": "6.10.1-1.9b628578b3b7cae625e8c927178f15a170e74a9c", "@prisma/get-platform": "6.10.1" } }, "sha512-clmbG/Jgmrc/n6Y77QcBmAUlq9LrwI9Dbgy4pq5jeEARBpRCWJDJ7PWW1P8p0LfFU0i5fsyO7FqRzRB8mkdS4g=="],
"@prisma/get-platform": ["@prisma/get-platform@6.10.1", "", { "dependencies": { "@prisma/debug": "6.10.1" } }, "sha512-4CY5ndKylcsce9Mv+VWp5obbR2/86SHOLVV053pwIkhVtT9C9A83yqiqI/5kJM9T1v1u1qco/bYjDKycmei9HA=="],
"@sapphire/async-queue": ["@sapphire/async-queue@1.5.5", "", {}, "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="],
"@sapphire/shapeshift": ["@sapphire/shapeshift@4.0.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" } }, "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg=="],
"@sapphire/snowflake": ["@sapphire/snowflake@3.5.3", "", {}, "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ=="],
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
"@sern/cli": ["@sern/cli@1.4.0", "", { "dependencies": { "@esbuild-kit/cjs-loader": "^2.4.2", "@esbuild-kit/esm-loader": "^2.5.5", "colorette": "2.0.20", "commander": "11.0.0", "dotenv": "^16.3.1", "esbuild": "^0.19.1", "execa": "7.2.0", "find-up": "6.3.0", "glob": "^10.3.3", "ora": "6.3.1", "prompts": "2.4.2", "undici": "5.23.0" }, "bin": { "sern": "dist/index.js" } }, "sha512-IePGYYJvIVwNtnukblYxE2X7hiFivLa/p4UVaMi0XLpZ+Fa3BAdsSiBKRzLtBYWl8J2Se9StLSFwBYQW7ik+/Q=="],
"@sern/handler": ["@sern/handler@4.2.4", "", { "dependencies": { "@sern/ioc": "^1.1.2", "callsites": "^3.1.0", "cron": "^3.1.7", "deepmerge": "^4.3.1" } }, "sha512-8qnYSwH2x5zhp7YidtDxQZFaQrwYn+YITk4kWrvqOx6b9PVDKtdzkjXd4e7dnI0tdmGuVwJGk6eRl/RnGUVDqw=="],
"@sern/ioc": ["@sern/ioc@1.1.2", "", {}, "sha512-n84w7n5hB1dl8N6dfSbeYIo0QYORMS1bpG/P7J7GoMNTu8c28EYVZ8uGs3Md9GB09UseOKn3mfv1QBDtRsbb1g=="],
"@sern/publisher": ["@sern/publisher@1.1.2", "", {}, "sha512-1zh99JZykKUhqHhE75ZXfiLsBtf1WI+NnDCojv8UlpnGBEyzO8xyI1X7PNf6cPKRs4W9XqY3PqTJ+hrqzIsMkg=="],
"@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="],
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
"@types/luxon": ["@types/luxon@3.4.2", "", {}, "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA=="],
"@types/mongodb": ["@types/mongodb@4.0.7", "", { "dependencies": { "mongodb": "*" } }, "sha512-lPUYPpzA43baXqnd36cZ9xxorprybxXDzteVKCPAdp14ppHtFJHnXYvNpmBvtMUTb5fKXVv6sVbzo1LHkWhJlw=="],
"@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="],
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
"@types/webidl-conversions": ["@types/webidl-conversions@7.0.3", "", {}, "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="],
"@types/whatwg-url": ["@types/whatwg-url@11.0.5", "", { "dependencies": { "@types/webidl-conversions": "*" } }, "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ=="],
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
"@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.6", "", {}, "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="],
"ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
"bl": ["bl@5.1.0", "", { "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ=="],
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
"bson": ["bson@6.10.4", "", {}, "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng=="],
"buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
"chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
"cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="],
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
"clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
"colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
"commander": ["commander@11.0.0", "", {}, "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ=="],
"cron": ["cron@3.5.0", "", { "dependencies": { "@types/luxon": "~3.4.0", "luxon": "~3.5.0" } }, "sha512-0eYZqCnapmxYcV06uktql93wNWdlTmmBFP2iYz+JPVcQqlyFYcn1lFuIk4R54pkOmE7mcldTAPZv6X5XA4Q46A=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
"css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
"defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="],
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
"discord-api-types": ["discord-api-types@0.38.13", "", {}, "sha512-FELWJRgLVQuR7Az8RhdEZE0k6QNjSW9PCUcU1iyP2Gke8HrJmnMceSS9pD93UM64s3tvZzJPajpPLjWZJylf4g=="],
"discord.js": ["discord.js@14.21.0", "", { "dependencies": { "@discordjs/builders": "^1.11.2", "@discordjs/collection": "1.5.3", "@discordjs/formatters": "^0.6.1", "@discordjs/rest": "^2.5.1", "@discordjs/util": "^1.1.1", "@discordjs/ws": "^1.2.3", "@sapphire/snowflake": "3.5.3", "discord-api-types": "^0.38.1", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.3" } }, "sha512-U5w41cEmcnSfwKYlLv5RJjB8Joa+QJyRwIJz5i/eg+v2Qvv6EYpCRhN9I2Rlf0900LuqSDg8edakUATrDZQncQ=="],
"dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
"domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
"domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
"dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="],
"execa": ["execa@9.6.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw=="],
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
"figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
"find-up": ["find-up@6.3.0", "", { "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" } }, "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw=="],
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
"get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
"get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="],
"glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
"he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="],
"human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
"is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
"is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
"is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="],
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
"kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
"locate-path": ["locate-path@7.2.0", "", { "dependencies": { "p-locate": "^6.0.0" } }, "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA=="],
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="],
"log-symbols": ["log-symbols@5.1.0", "", { "dependencies": { "chalk": "^5.0.0", "is-unicode-supported": "^1.1.0" } }, "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA=="],
"lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
"luxon": ["luxon@3.5.0", "", {}, "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ=="],
"magic-bytes.js": ["magic-bytes.js@1.12.1", "", {}, "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA=="],
"memory-pager": ["memory-pager@1.5.0", "", {}, "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="],
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"mongodb": ["mongodb@6.17.0", "", { "dependencies": { "@mongodb-js/saslprep": "^1.1.9", "bson": "^6.10.4", "mongodb-connection-string-url": "^3.0.0" }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.188.0", "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", "gcp-metadata": "^5.2.0", "kerberos": "^2.0.1", "mongodb-client-encryption": ">=6.0.0 <7", "snappy": "^7.2.2", "socks": "^2.7.1" }, "optionalPeers": ["@aws-sdk/credential-providers", "@mongodb-js/zstd", "gcp-metadata", "kerberos", "mongodb-client-encryption", "snappy", "socks"] }, "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA=="],
"mongodb-connection-string-url": ["mongodb-connection-string-url@3.0.2", "", { "dependencies": { "@types/whatwg-url": "^11.0.2", "whatwg-url": "^14.1.0 || ^13.0.0" } }, "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA=="],
"node-html-parser": ["node-html-parser@7.0.1", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA=="],
"npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
"onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
"openai": ["openai@5.10.2", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-n+vi74LzHtvlKcDPn9aApgELGiu5CwhaLG40zxLTlFQdoSJCLACORIPC2uVQ3JEYAbqapM+XyRKFy2Thej7bIw=="],
"ora": ["ora@6.3.1", "", { "dependencies": { "chalk": "^5.0.0", "cli-cursor": "^4.0.0", "cli-spinners": "^2.6.1", "is-interactive": "^2.0.0", "is-unicode-supported": "^1.1.0", "log-symbols": "^5.1.0", "stdin-discarder": "^0.1.0", "strip-ansi": "^7.0.1", "wcwidth": "^1.0.1" } }, "sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ=="],
"p-limit": ["p-limit@4.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ=="],
"p-locate": ["p-locate@6.0.0", "", { "dependencies": { "p-limit": "^4.0.0" } }, "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw=="],
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
"parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="],
"path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
"pretty-ms": ["pretty-ms@9.2.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg=="],
"prisma": ["prisma@6.10.1", "", { "dependencies": { "@prisma/config": "6.10.1", "@prisma/engines": "6.10.1" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-khhlC/G49E4+uyA3T3H5PRBut486HD2bDqE2+rvkU0pwk9IAqGFacLFUyIx9Uw+W2eCtf6XGwsp+/strUwMNPw=="],
"prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
"restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="],
"rockpaperscissors-checker": ["rockpaperscissors-checker@1.2.0", "", {}, "sha512-JfndRzDvMo1st+iK9dKZIEToFDouc+53+whmVFs+zyBOp0zv/sMNY9hUZI5J7ulygmW1fI6QmvRyXmfpN9Sh8Q=="],
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"sharp": ["sharp@0.34.2", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.4", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.2", "@img/sharp-darwin-x64": "0.34.2", "@img/sharp-libvips-darwin-arm64": "1.1.0", "@img/sharp-libvips-darwin-x64": "1.1.0", "@img/sharp-libvips-linux-arm": "1.1.0", "@img/sharp-libvips-linux-arm64": "1.1.0", "@img/sharp-libvips-linux-ppc64": "1.1.0", "@img/sharp-libvips-linux-s390x": "1.1.0", "@img/sharp-libvips-linux-x64": "1.1.0", "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", "@img/sharp-libvips-linuxmusl-x64": "1.1.0", "@img/sharp-linux-arm": "0.34.2", "@img/sharp-linux-arm64": "0.34.2", "@img/sharp-linux-s390x": "0.34.2", "@img/sharp-linux-x64": "0.34.2", "@img/sharp-linuxmusl-arm64": "0.34.2", "@img/sharp-linuxmusl-x64": "0.34.2", "@img/sharp-wasm32": "0.34.2", "@img/sharp-win32-arm64": "0.34.2", "@img/sharp-win32-ia32": "0.34.2", "@img/sharp-win32-x64": "0.34.2" } }, "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg=="],
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
"sparse-bitfield": ["sparse-bitfield@3.0.3", "", { "dependencies": { "memory-pager": "^1.0.2" } }, "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ=="],
"stdin-discarder": ["stdin-discarder@0.1.0", "", { "dependencies": { "bl": "^5.0.0" } }, "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ=="],
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
"string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
"strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="],
"tr46": ["tr46@5.1.1", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw=="],
"ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"undici": ["undici@5.23.0", "", { "dependencies": { "busboy": "^1.6.0" } }, "sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg=="],
"unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
"webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
"whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
"yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="],
"yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="],
"@discordjs/rest/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
"@discordjs/rest/undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="],
"@discordjs/ws/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
"@sern/cli/execa": ["execa@7.2.0", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", "human-signals": "^4.3.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^3.0.7", "strip-final-newline": "^3.0.0" } }, "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA=="],
"discord.js/undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="],
"figures/is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
"restore-cursor/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
"restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
"@sern/cli/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
"@sern/cli/execa/human-signals": ["human-signals@4.3.1", "", {}, "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ=="],
"@sern/cli/execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
"@sern/cli/execa/npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
"@sern/cli/execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"@sern/cli/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
"restore-cursor/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
"string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"@sern/cli/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
}
}

View File

@@ -1,36 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ApplicationCommandOptionType } from "discord.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
name: '8ball',
type: CommandType.Slash,
plugins: [publish()],
description: 'Preguntale a la 8-ball cosas.',
//alias : [],
options: [{
name: "pregunta",
description: "Escribe lo que le quieres preguntar.",
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.
var eightballwords = [
'Probablemente',
'Sí',
'No',
'Dudable',
'Como lo veo, todo indica a que sí',
'A lo mejor',
'No cuentes con ello',
'Buena suerte'
]
await ctx.reply({content: `La bola tiene respuesta: ${eightballwords[Math.floor(Math.random() * eightballwords.length)]}.`, ephemeral: true})
},
});

View File

@@ -1,66 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { Context } from "@sern/handler";
import { ApplicationCommandOptionType, AttachmentBuilder, AutocompleteInteraction, EmbedBuilder } from "discord.js";
import { publish } from "../../src/plugins/publish.js";
const choices = ['XaviXE', 'Paula', 'William', 'Espejito2500', 'Wheelook', 'MarioCabrera', 'Paticama', 'Vinci', 'SrIzan', 'ItsAdrian', 'ByHGT', 'Irene', 'Boniato64'];
export default commandModule({
name: 'a',
type: CommandType.Slash,
plugins: [publish()],
description: 'A',
//alias : [],
options: [
{
name: 'usuario',
description: 'Usuario que debería aparecer',
type: ApplicationCommandOptionType.String,
autocomplete: true,
command: {
onEvent: [],
async execute(ctx: AutocompleteInteraction){
const focusedValue = ctx.options.getFocused();
const filtered = choices.filter(choice => choice.startsWith(focusedValue));
await ctx.respond(
filtered.map(choice => ({ name: choice, value: choice })),
);
}
}
}
],
execute: async (ctx, options) => {
let option
try {option = options[1].getString('usuario', true)} catch(error) {option = undefined}
if (!option) {
const imagesArray = [
'./images/a/XaviXE.png',
'./images/a/Paula.png',
'./images/a/William.png',
'./images/a/Espejito2500.png',
'./images/a/Wheelook.png',
'./images/a/MarioCabrera.png',
'./images/a/Paticama.png',
'./images/a/Vinci.png',
'./images/a/SrIzan.png',
'./images/a/ItsAdrian.png',
'./images/a/ByHGT.png',
'./images/a/Irene.png',
'./images/a/Boniato64.png',
]
const images = imagesArray[Math.floor(Math.random() * imagesArray.length)];
await ctx.reply({content: 'A', files: [images]});
} else {
if (choices.indexOf(options[1].getString('usuario', true)) > -1) {
const attachmentbuilder = new AttachmentBuilder(`./images/a/${options[1].getString('usuario', true)}.png`)
await ctx.reply({content: 'A', files: [attachmentbuilder]})
} else {
const embed = new EmbedBuilder()
.setTitle("A no encontrado!")
.setDescription(`Qué raro, no se ha encontrado ese /a...\nPorqué no pruebas a poner uno del autocompletado?`)
.setColor("Red")
await ctx.reply({embeds: [embed], ephemeral: true})
}
}
},
});

View File

@@ -1,192 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import axios from "axios";
import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ComponentType, EmbedBuilder } from "discord.js";
import { publish } from "../../src/plugins/publish.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
name: 'animal',
type: CommandType.Slash,
plugins: [publish()],
description: 'Enseña un animal',
//alias : [],
options: [
{
name: 'gato',
description: 'Enseña un gato',
type: ApplicationCommandOptionType.Subcommand
},
{
name: 'capybara',
description: 'Enseña un capybara',
type: ApplicationCommandOptionType.Subcommand
},
{
name: 'zorro',
description: 'Enseña un zorro',
type: ApplicationCommandOptionType.Subcommand
},
{
name: 'perro',
description: 'what the dog doin',
type: ApplicationCommandOptionType.Subcommand
},
{
name: 'mapache',
description: 'Enseña un mapache',
type: ApplicationCommandOptionType.Subcommand
}
],
execute: async (ctx, options) => {
switch (options[1].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()
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setColor("Random")
.setImage(request[0].url)
.setFooter({text: `ID: ${request[0].id}`})
.setTitle('Gato')
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId("cat-upvote")
.setEmoji("⬆️")
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId("cat-downvote")
.setEmoji("⬇️")
.setStyle(ButtonStyle.Danger),
)
const rowdisabled = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId("cat-upvote")
.setEmoji("⬆️")
.setStyle(ButtonStyle.Success)
.setDisabled(true),
new ButtonBuilder()
.setCustomId("cat-downvote")
.setEmoji("⬇️")
.setStyle(ButtonStyle.Danger)
.setDisabled(true),
)
const message = await ctx.reply({embeds: [embed], components: [row]})
const collector = message.createMessageComponentCollector({time: 30000, componentType: ComponentType.Button})
collector.on('collect', async (i) => {
await i.deferReply({ephemeral: true})
if (i.customId === "cat-upvote") {
await axios.post(`https://api.thecatapi.com/v1/votes?api_key=${process.env.CATAPI}`, {
"image_id": request[0].id,
"sub_id": i.user.id,
"value": 1
})
i.editReply({content: "Has votado positivamente al gato con ID " + "`" + request[0].id + "`"})
}
if (i.customId === "cat-downvote") {
await axios.post(`https://api.thecatapi.com/v1/votes?api_key=${process.env.CATAPI}`, {
"image_id": request[0].id,
"sub_id": i.user.id,
"value": -1
})
i.editReply({content: "Has votado negativamente al gato con ID " + "`" + request[0].id + "`"})
}
})
collector.on('end', async (i) => {
await message.edit({components: [rowdisabled]})
})
}
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}`})
await ctx.interaction.reply({embeds: [embed]})
}
case 'zorro': {
const request = await axios('https://randomfox.ca/floof/').then(res => res.data)
const embed = new EmbedBuilder()
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setTitle('Zorro')
.setColor('Random')
.setImage(request.image)
await ctx.interaction.reply({embeds: [embed]})
}
case 'perro': {
const request = await axios.get(`https://api.thedogapi.com/v1/images/search?api_key=${process.env.DOGAPI}`).then(res => res.data)
const embed = new EmbedBuilder()
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setColor("Random")
.setImage(request[0].url)
.setFooter({text: `ID: ${request[0].id}`})
.setTitle('Perro')
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId("dog-upvote")
.setEmoji("⬆️")
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId("dog-downvote")
.setEmoji("⬇️")
.setStyle(ButtonStyle.Danger),
)
const rowdisabled = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId("dog-upvote")
.setEmoji("⬆️")
.setStyle(ButtonStyle.Success)
.setDisabled(true),
new ButtonBuilder()
.setCustomId("dog-downvote")
.setEmoji("⬇️")
.setStyle(ButtonStyle.Danger)
.setDisabled(true),
)
const message = await ctx.reply({embeds: [embed], components: [row]})
const collector = message.createMessageComponentCollector({time: 30000, componentType: ComponentType.Button})
collector.on('collect', async (i) => {
await i.deferReply({ephemeral: true})
if (i.customId === "dog-upvote") {
await axios.post(`https://api.thedogapi.com/v1/votes?api_key=${process.env.DOGAPI}`, {
"image_id": request[0].id,
"sub_id": i.user.id,
"value": 1
})
i.editReply({content: "Has votado positivamente al gato con ID " + "`" + request[0].id + "`"})
}
if (i.customId === "dog-downvote") {
await axios.post(`https://api.thedogapi.com/v1/votes?api_key=${process.env.DOGAPI}`, {
"image_id": request[0].id,
"sub_id": i.user.id,
"value": -1
})
i.editReply({content: "Has votado negativamente al gato con ID " + "`" + request[0].id + "`"})
}
})
collector.on('end', async () => {
await message.edit({components: [rowdisabled]})
})
}
case 'mapache': {
const request = await axios('https://some-random-api.ml/animal/raccoon').then(res => res.data)
const embed = new EmbedBuilder()
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setTitle('Mapache')
.setDescription(`Fun fact: ${request.fact}`)
.setColor('Random')
.setImage(request.image)
await ctx.interaction.reply({embeds: [embed]})
}
}
},
});

View File

@@ -1,168 +0,0 @@
import { commandModule, CommandType } from '@sern/handler';
import { publish } from '../../src/plugins/publish.js';
import { ANIME } from '@consumet/extensions';
import {
ActionRowBuilder,
ApplicationCommandOptionType,
ButtonBuilder,
ButtonStyle,
ComponentType,
EmbedBuilder,
} from 'discord.js';
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
type: CommandType.Slash,
plugins: [publish()],
description: 'busca cosas en gogoanime',
//alias : [],
options: [
{
name: 'buscar',
description: 'Busca un anime',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'palabra-clave',
description: 'La palabra clave',
type: ApplicationCommandOptionType.String,
required: true,
},
],
},
{
name: 'capitulo',
description: 'Mira los links de directo de cualquier capítulo (con su ID)',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'id-serie',
description: 'El ID de la serie (búscalo primero)',
type: ApplicationCommandOptionType.String,
required: true
},
{
name: 'id-capitulo',
description: 'El ID del capítulo (usa el autocompletado)',
type: ApplicationCommandOptionType.String,
required: true,
autocomplete: true,
command: {
onEvent: [],
execute: async (autocomplete) => {
try {
const focusedOption = autocomplete.options.getFocused();
const gogoanime = new ANIME.Gogoanime();
const serieOption = autocomplete.options.getString('id-serie', true)
const fetch = await gogoanime.fetchAnimeInfo(serieOption)
let choices = fetch.episodes!.filter((choice) => choice.number.toString().startsWith(focusedOption))
choices = choices.slice(0, 25)
await autocomplete.respond(
choices.map((choice) => ({
name: choice.number.toString(),
value: choice.id.toString(),
}))
)
} catch (err) {
await autocomplete.respond([{name: 'Algo malo ha ocurrido! Asegúrate que hayas puesto el ID correctamente', value: 'error'}])
}
}
}
}
],
},
{
name: 'info',
description: 'INGLÉS: Consigue información sobre alguna serie con su ID.',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'id',
description: 'El nombre de la serie',
type: ApplicationCommandOptionType.String,
required: true
}
]
}
],
execute: async (ctx, options) => {
const gogoanime = new ANIME.Gogoanime();
const doubleslashregex = new RegExp('(?<!:)\/\/+')
switch (options[1].getSubcommand()) {
case 'buscar': {
await ctx.interaction.deferReply()
const option = options[1].getString('palabra-clave', true);
const search = await gogoanime.search(option);
const editedarray = await Promise.all(
search.results
.map((results) => {
return `[${results.title}](<${results.url!.replace(doubleslashregex, '/')}>)`;
})
.slice(0, 5)
);
const editedarrayids = await Promise.all(
search.results
.map((results) => {
return `[${results.id}](<${results.url!.replace(doubleslashregex, '/')}>)`;
})
.slice(0, 5)
);
const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('gogoanime-search-toid')
.setLabel('Cambiar a ID')
.setStyle(ButtonStyle.Secondary)
);
if (editedarray.length === 0) return await ctx.interaction.editReply({content: 'No se ha encontrado nada con ese resultado de búsqueda, prueba a ser más general o concreto idk'})
const message = await ctx.interaction.editReply({
content: `Resultados de la búsqueda \`${option}\`:\n${editedarray.join('\n')}`,
components: [button],
});
const collector = message.createMessageComponentCollector({max: 1, componentType: ComponentType.Button, time: 30000})
collector.on('collect', async (i) => {
if (i.customId !== 'gogoanime-search-toid') return;
await ctx.interaction.editReply({
content: `Resultados de la búsqueda \`${option}\` (modo ID):\n${editedarrayids.join('\n')}`,
components: []
})
await i.deferUpdate()
})
} break;
case 'capitulo': {
const selepisode = options[1].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, '/')}>)`))
await ctx.reply({content: `Todos los servidores de \`${selepisode}\` (Vinci no se hace cargo de los enlaces):\n${arrayed.join('\n')}`})
} catch (err) {
await ctx.reply({content: 'Ha ocurrido un error! Asegúrate que hayas seleccionado bien un capítulo.'})
}
} break;
case 'info': {
try {
const option = options[1].getString('id', true)
const info = await gogoanime.fetchAnimeInfo(option)
const embed = new EmbedBuilder()
.setColor('Random')
.setTitle(`${info.title}`)
.setURL(info.url!.replace(doubleslashregex, '/'))
.setThumbnail(info.image!)
.setFields(
{name: 'Géneros', value: `${info.genres!.join(', ')}`},
{name: 'Fecha de salida', value: `${info.releaseDate!}`, inline: true},
{name: 'Capítulos totales', value: `${info.totalEpisodes!}`, inline: true},
{name: '\u200B', value: '\u200B', inline: true},
{name: 'Tipo', value: `${info.type!}`, inline: true},
)
await ctx.reply({embeds: [embed]})
} catch (err) {
await ctx.reply({content: 'Algo malo ha ocurrido, asegúrate que hayas escrito el ID correctamente\nTip: Usa el comando de buscar y conviértelos a ID.'})
}
} break;
}
},
});

View File

@@ -1,15 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import axios from "axios";
import { publish } from "../../src/plugins/publish.js";
export default commandModule({
name: 'chiste',
type: CommandType.Slash,
plugins: [publish()],
description: 'Enseña un chiste en inglés.',
execute: async (ctx, args) => {
const jokeJSON = await axios(
'https://v2.jokeapi.dev/joke/Programming,Miscellaneous,Spooky,Christmas?blacklistFlags=nsfw,religious,racist,sexist,explicit'
).then((res) => res.data);
ctx.reply({content: `${jokeJSON.joke || jokeJSON.setup}\n${jokeJSON.delivery || ""}`})
}})

View File

@@ -1,56 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import Canvas from '@napi-rs/canvas';
import { ApplicationCommandOptionType, AttachmentBuilder } from 'discord.js';
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
type: CommandType.Slash,
plugins: [publish()],
// , '928018226330337280'
description: 'Añade a una imagen de megamind "No ...?"',
//alias : [],
options: [
{
name: 'texto',
description: 'El texto SIN "No" ni "?".',
type: ApplicationCommandOptionType.String,
required: true
}
],
execute: async (ctx, options) => {
const option = options[1].getString('texto', true)
if (option.length > 15) return await ctx.reply({content: `El texto es muy largo, intenta que sea menor que 15 caracteres.`, ephemeral: true})
await ctx.reply({content: 'Cargando...'})
const before = performance.now()
const canvas = Canvas.createCanvas(535, 540)
const context = canvas.getContext('2d')
const background = await Canvas.loadImage('./images/megamind/megamind.png')
context.drawImage(background, 0, 0, canvas.width, canvas.height)
const text = `No ${option}?`
context.font = '40px Impact'
context.fillStyle = 'red'
context.textAlign = 'center'
context.textBaseline = 'middle'
context.fillText(text, canvas.width / 2, canvas.height - 510)
const encode = await canvas.encode('png')
const after = performance.now()
const attachment = new AttachmentBuilder(encode, { name: 'megamind.png' });
await ctx.interaction.editReply({
content: `Aquí está tu megamind:\nLa generación de imagen ha tardado \`${(after - before).toFixed(2)}ms\`.`,
files: [attachment]
})
},
});

View File

@@ -1,113 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ComponentType, EmbedBuilder, GuildMember } from "discord.js";
import { publish } from "../../src/plugins/publish.js";
import rockpaperscissors from "rockpaperscissors-checker";
export default commandModule({
name: 'rps',
type: CommandType.Slash,
plugins: [publish()],
description: 'Juega piedra papel tijeras con los panas',
//alias : [],
options: [
{
name: 'usuario',
description: 'El usuario con el que enfrentarse',
type: ApplicationCommandOptionType.User,
required: true
}
],
execute: async (ctx, options) => {
// also the code is mine, I didn't steal from anyone
let player1, player2, winner, bothResponded
const option = options[1].getMember('usuario') 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) {
return await ctx.reply({content: `no puedes seleccionar a un bot.`, ephemeral: true})
}
const waitingEmbed = new EmbedBuilder()
.setColor('Red')
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setTitle(`Piedra, papel o tijera? <:PauseChamp:1030169623070519388>`)
.setDescription(`Esperando a que ambos jugadores eligan...\nJugador 1: ${ctx.user}\nJugador 2: ${option}`)
.setFooter({text: `Hay un máximo de 30 segundos para elegir.`})
const winEmbed = new EmbedBuilder()
.setColor('Green')
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setFooter({text: `Gracias por jugar!`})
const tieEmbed = new EmbedBuilder()
.setColor('Yellow')
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setTitle(`Ha habido un empate <:Sadge:1015764348385382451>`)
.setDescription(`Qué sadge, ha habido un empate...`)
.setFooter({text: `Volvemos a intentarlo?`})
const timeUpEmbed = new EmbedBuilder()
.setColor('Red')
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setTitle(`Se acabó!`)
.setDescription(`Uno de los dos jugadores no han respondido en los 30 segundos, así que se acabó la partida!`)
.setFooter({text: `Volvemos a intentarlo?`})
const buttons = ["Piedra", "Papel", "Tijera"].map(choice => {
return new ButtonBuilder()
.setLabel(choice)
.setCustomId(`rps-${choice.toLowerCase()}`)
.setStyle(ButtonStyle.Secondary)
})
const row = new ActionRowBuilder<ButtonBuilder>();
const message = await ctx.interaction.reply({content: `${option}, te han retado a Piedra Papel o Tijera!`, embeds: [waitingEmbed], fetchReply: true, components: [row.setComponents(buttons)]})
const collector = message.createMessageComponentCollector({time: 30_000, componentType: ComponentType.Button, filter: (i) => [ctx.user.id, option.id].includes(i.user.id),})
collector.on('collect', async (i) => {
await i.deferReply({ephemeral: true})
if (i.customId === "rps-piedra") {
if (i.user.id === ctx.user.id) {
player1 = 1
await i.editReply({content: `Se ha respondido **piedra** correctamente, buena suerte!\n[Volver al mensaje](${message.url})`})
} else if (i.user.id === option.id) {
player2 = 1
await i.editReply({content: `Se ha respondido **piedra** correctamente, buena suerte!\n[Volver al mensaje](${message.url})`})
}
} else if (i.customId === "rps-papel") {
if (i.user.id === ctx.user.id) {
player1 = 2
await i.editReply({content: `Se ha respondido **papel** correctamente, buena suerte!\n[Volver al mensaje](${message.url})`})
} else if (i.user.id === option.id) {
player2 = 2
await i.editReply({content: `Se ha respondido **papel** correctamente, buena suerte!\n[Volver al mensaje](${message.url})`})
}
} else if (i.customId === "rps-tijera") {
if (i.user.id === ctx.user.id) {
player1 = 3
await i.editReply({content: `Se ha respondido **tijera** correctamente, buena suerte!\n[Volver al mensaje](${message.url})`})
} else if (i.user.id === option.id) {
player2 = 3
await i.editReply({content: `Se ha respondido **tijera** correctamente, buena suerte!\n[Volver al mensaje](${message.url})`})
}
}
if (player1 && player2) {
const checker = rockpaperscissors(player1, player2)
bothResponded = true
if (checker === "player1") {
winner = ctx.user.username
const setDescription = winEmbed.setDescription(`Tenemos resultados!\n**${winner}** ha ganado.`).setTitle(`Ha ganado ${winner}! <:Pog:1030169609178976346>`)
await message.edit({embeds: [setDescription], components: [], content: ``})
message.react('<:Pog:1030169609178976346>')
} else if (checker === "player2") {
winner = option.user.username
const setDescription = winEmbed.setDescription(`Tenemos resultados!\n**${winner}** ha ganado.`).setTitle(`Ha ganado ${winner}! <:Pog:1030169609178976346>`)
await message.edit({embeds: [setDescription], components: [], content: ``})
message.react('<:Pog:1030169609178976346>')
} else if (checker === "tie") {
await message.edit({embeds: [tieEmbed], components: [], content: ``})
}
}
})
collector.on('ignore', async (i) => {
await i.reply({content: 'No estás jugando!', ephemeral: true})
})
collector.on('end', async () => {
if (bothResponded) return;
await message.edit({embeds: [timeUpEmbed], components: [], content: ``})
})
},
});

View File

@@ -1,24 +0,0 @@
import TicTacToe from 'discord-tictactoe';
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ApplicationCommandOptionType } from "discord.js";
const game = new TicTacToe({language: 'en'})
export default commandModule({
name: 'tictactoe',
type: CommandType.Slash,
plugins: [publish()],
description: 'tres en raya',
//alias : [],
options: [
{
name: "opponent",
description: "opponent",
type: ApplicationCommandOptionType.User
}
],
execute: async (ctx, options) => {
await game.handleInteraction(ctx.interaction)
},
});

View File

@@ -1,26 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import axios from "axios";
import { GuildBasedChannel, TextChannel } from 'discord.js';
export default commandModule({
type: CommandType.Modal,
plugins: [],
description: 'Envia el formulario para entrar al servidor.',
//alias : [],
async execute (modal) {
const value = modal.fields.getTextInputValue('mcUsernameInput') as any
var specialChars = /[`!@#$%^&*()+\-=\[\]{};':"\\|,.<>\/?~]/;
if (value > 16 || value < 3 || specialChars.test(value)) {
modal.reply({content: `ERROR: El nombre de usuario no es válido.`, ephemeral: true});
} else {
try {
const request = await axios(`https://api.mojang.com/users/profiles/minecraft/${value}`, {validateStatus: function (status) {return status === 200 || status === 400; }})
const data = request.data
await modal.reply({content: 'Enviado!, Gracias por utilizar tu Mona Lisa de confianza\n~Sr Izan, 2022', ephemeral: true});
(modal.client.guilds.cache.get("928018226330337280")!.channels.cache.get("998195363376803850") as TextChannel).send(`Solicitud enviada por ${modal.user}.\nUsername de Minecraft: ${value}`);
} catch (err) {
await modal.reply({content: 'ERROR: No se ha podido enviar ya que eres un usuario no premium o de MC Bedrock.\nAsegúrate que has puesto bien el nombre de usuario.', ephemeral: true})
}
}
}
});

View File

@@ -1,35 +0,0 @@
import { commandModule, CommandType } from "@sern/handler";
import type { APISelectMenuComponent, GuildMember } from "discord.js";
export default commandModule({
type: CommandType.MenuSelect,
name: 'role-menu',
async execute(interaction) {
await interaction.deferReply({ ephemeral: true });
const roles = interaction.values;
const menuRoles: string[] = (
interaction.message.components[0].components[0]
.data as Readonly<APISelectMenuComponent>
// @ts-ignore
).options.map((o: { label: string; value: string }) => o.value);
const member = interaction.member as GuildMember;
if (!member) return;
let content = `Los roles han sido actualizados. Te he dado estos:\n${roles
.map((r) => `<@&${r}>`)
.join("\n")}`;
if (roles.length === 0) content = "Se han actualizado los roles a ninguno o no se han seleccionado roles...";
const existing = member.roles.cache
.filter((r) => r.id !== interaction.guildId)
.map((r) => r.id)
.filter((r) => !menuRoles.includes(r));
await member.roles.set(roles.concat(existing)).catch(() => null);
await interaction.editReply(content);
},
});

View File

@@ -1,69 +0,0 @@
import { commandModule, CommandType } from '@sern/handler';
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from 'discord.js';
import {
TextChannel,
ThreadAutoArchiveDuration,
} from 'discord.js';
export default commandModule({
type: CommandType.Modal,
async execute(modal) {
const value = modal.fields.getTextInputValue('sugerenciasInput');
function onlySpaces(str: string) {
return str.trim().length === 0;
}
if (onlySpaces(value) === true)
return await modal.reply({
content: 'Buen intento enviando un mensaje vacío >:D',
ephemeral: true,
});
const embed = new EmbedBuilder()
.setColor('Random')
.setTitle('Sugerencia')
.setAuthor({
name: `${modal.user.username}`,
iconURL: `${modal.user.displayAvatarURL()}`,
})
.setDescription(value);
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId('suggestions-yes')
.setEmoji('✅')
.setLabel('0')
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId('suggestions-no')
.setEmoji('❎')
.setLabel('0')
.setStyle(ButtonStyle.Danger),
)
const row2 = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId('suggestions-yes-who')
.setEmoji('✅')
.setLabel('Quién')
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId('suggestions-no-who')
.setEmoji('❎')
.setLabel('Quién')
.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({
name: `Sugerencia de ${modal.user.username}`,
autoArchiveDuration: ThreadAutoArchiveDuration.ThreeDays,
reason: 'AUTOMATIZADO: Hilo para discutir sobre la sugerencia.',
});
modal.reply({
content:
'¡Enviado!\nRECUERDA QUE NO ESTÁ PERMITIDO ENVIAR MENSAJES VACÍOS.',
ephemeral: true,
});
},
});

View File

@@ -1,24 +0,0 @@
import { commandModule, CommandType } from "@sern/handler";
import db from "../../schemas/suggestions.js";
export default commandModule({
type: CommandType.Button,
async execute(interaction) {
let finalarray
await interaction.deferReply({ephemeral: true})
const findeverything = await db.find({msgid: interaction.message.id, upordown: -1})
const array = findeverything.filter(message => message.msgid)
const fetchedids = await Promise.all(array.map(async (user) => {
return interaction.client.users.fetch(user.userid)
}))
if (fetchedids.length === 0) {
finalarray = 'Nadie, de momento'
} else {
finalarray = fetchedids.join(', ')
}
await interaction.editReply({
content: `Gente que ha hecho downvote:\n${finalarray}`,
allowedMentions: {repliedUser: false}
})
}
})

View File

@@ -1,50 +0,0 @@
import { commandModule, CommandType } from "@sern/handler";
import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, ComponentType } 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 row2 = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(interaction.message!.components[1].components[0].data),
new ButtonBuilder(interaction.message!.components[1].components[1].data)
)
if (await db.exists({msgid: interaction.message.id, userid: interaction.user.id, upordown: 1})) {
await db.findOneAndUpdate({msgid: interaction.message.id, userid: interaction.user.id, upordown: 1}, {upordown: -1}, {returnOriginal: false})
// god forbid I use any! I'm literally done with trying to solve this dude
const upvoteLabel = JSON.stringify(interaction.message!.components[0].components[0].data) as string
const downvotebuttons = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(interaction.message!.components[0].components[0].data)
.setLabel((Number(JSON.parse(upvoteLabel).label) - 1).toString()),
new ButtonBuilder()
.setCustomId('suggestions-no')
.setEmoji('❎')
.setLabel((convertToNumber + 1).toString())
.setStyle(ButtonStyle.Danger),
)
await interaction.message.edit({components: [downvotebuttons, row2]})
await interaction.deferUpdate()
} else if (await db.exists({msgid: interaction.message.id, userid: interaction.user.id, upordown: -1})) {
return await interaction.reply({content: 'Ya has hecho downvote.', ephemeral: true})
} else {
const downvotebuttons = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(interaction.message!.components[0].components[0].data),
new ButtonBuilder()
.setCustomId('suggestions-no')
.setEmoji('❎')
.setLabel((convertToNumber + 1).toString())
.setStyle(ButtonStyle.Danger),
)
const addToDB = new db({
msgid: interaction.message.id,
userid: interaction.user.id,
upordown: -1
})
await addToDB.save()
await interaction.message.edit({components: [downvotebuttons, row2]})
await interaction.deferUpdate()
}
}
})

View File

@@ -1,25 +0,0 @@
import { commandModule, CommandType } from "@sern/handler";
import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, ComponentType } from "discord.js";
import db from "../../schemas/suggestions.js";
export default commandModule({
type: CommandType.Button,
async execute(interaction) {
let finalarray
await interaction.deferReply({ephemeral: true})
const findeverything = await db.find({msgid: interaction.message.id, upordown: 1})
const array = findeverything.filter(message => message.msgid)
const fetchedids = await Promise.all(array.map(async (user) => {
return interaction.client.users.fetch(user.userid)
}))
if (fetchedids.length === 0) {
finalarray = 'Nadie, de momento'
} else {
finalarray = fetchedids.join(', ')
}
await interaction.editReply({
content: `Gente que ha hecho upvote:\n${finalarray}`,
allowedMentions: {repliedUser: false}
})
}
})

View File

@@ -1,50 +0,0 @@
import { commandModule, CommandType } from "@sern/handler";
import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, ComponentType } 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 row2 = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(interaction.message!.components[1].components[0].data),
new ButtonBuilder(interaction.message!.components[1].components[1].data)
)
if (await db.exists({msgid: interaction.message.id, userid: interaction.user.id, upordown: -1})) {
await db.findOneAndUpdate({msgid: interaction.message.id, userid: interaction.user.id, upordown: -1}, {upordown: 1}, {returnOriginal: false})
// god forbid I use any! I'm literally done with trying to solve this dude
const upvoteLabel = JSON.stringify(interaction.message!.components[0].components[1].data) as string
const downvotebuttons = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder()
.setCustomId('suggestions-yes')
.setEmoji('✅')
.setLabel((convertToNumber + 1).toString())
.setStyle(ButtonStyle.Success),
new ButtonBuilder(interaction.message!.components[0].components[1].data)
.setLabel((Number(JSON.parse(upvoteLabel).label) - 1).toString()),
)
await interaction.message.edit({components: [downvotebuttons, row2]})
await interaction.deferUpdate()
} else if (await db.exists({msgid: interaction.message.id, userid: interaction.user.id, upordown: 1})) {
return await interaction.reply({content: 'Ya has hecho upvote.', ephemeral: true})
} else {
const downvotebuttons = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder()
.setCustomId('suggestions-yes')
.setEmoji('✅')
.setLabel((convertToNumber + 1).toString())
.setStyle(ButtonStyle.Success),
new ButtonBuilder(interaction.message!.components[0].components[1].data)
)
const addToDB = new db({
msgid: interaction.message.id,
userid: interaction.user.id,
upordown: 1
})
await addToDB.save()
await interaction.message.edit({components: [downvotebuttons, row2]})
await interaction.deferUpdate()
}
}
})

View File

@@ -1,33 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ApplicationCommandOptionType } from "discord.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
name: 'ip',
type: CommandType.Slash,
plugins: [publish()],
//
description: 'La IP del servidor de Minecraft',
options: [
{
name: 'usuario',
description: 'Menciona al usuario al que va dirigido el comando.',
type: ApplicationCommandOptionType.User
}
],
//alias : [],
execute: async (ctx, options) => {
const usuario = options[1].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})
} else {
await ctx.reply({content: `${usuario}` + ", la IP del servidor de Minecraft es `minecraft.maraturing.com`,\nPide acceso con el comando </mcform:1000747672690499594>."})
}
},
});

View File

@@ -1,32 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ModalActionRowComponentBuilder } from 'discord.js'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
export default commandModule({
name: 'mcform',
type: CommandType.Slash,
plugins: [publish()],
description: 'Envia el formulario para entrar al servidor.',
//alias : [],
execute: async (ctx) => {
const modal = new ModalBuilder()
.setCustomId('mcform')
.setTitle('Formulario para entrar al servidor');
// Create the text input components
const input = new TextInputBuilder()
.setCustomId('mcUsernameInput')
// The label is the prompt the user sees for this input
.setLabel("Cuál es tu nombre de usuario de Minecraft?")
// Short means only a single line of text
.setStyle(TextInputStyle.Short);
// An action row only holds one text input,
// so you need one action row per text input.
const usernameActionRow = new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(input);
// Add inputs to the modal
modal.addComponents(usernameActionRow);
await ctx.interaction.showModal(modal);
}
});

View File

@@ -1,19 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ApplicationCommandOptionType } from "discord.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
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})
},
});

View File

@@ -1,192 +0,0 @@
import { commandModule, CommandType } from '@sern/handler';
import {
ActionRowBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle,
ModalActionRowComponentBuilder,
ButtonBuilder,
ButtonStyle,
ComponentType,
ModalSubmitInteraction,
ApplicationCommandOptionType,
} from 'discord.js';
import { publish } from '../../src/plugins/publish.js';
import { ownerOnly } from '../../src/plugins/ownerOnly.js';
import padyama from '../../schemas/padyama.js';
import { randomnumbergen } from '../../util/randomnumbergen.js';
export default commandModule({
name: 'askjavi',
type: CommandType.Slash,
plugins: [
// publish(),
],
description: 'TEMP: Pregunta a Javi LO QUE SEA!',
//alias : [],
options: [
{
name: 'new',
description: 'Haz una nueva pregunta',
type: ApplicationCommandOptionType.Subcommand,
},
{
name: 'get',
description: 'Mira una pregunta teniendo su ID.',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'id',
description: 'El ID de la pregunta',
type: ApplicationCommandOptionType.String,
required: true,
},
],
},
{
name: 'you',
description: 'Todos los IDs de las preguntas que hayas hecho',
type: ApplicationCommandOptionType.Subcommand,
},
{
name: 'answered',
description:
'ORGANIZADOR: Todos los IDs de las preguntas que hayas hecho',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'id',
description: 'El ID de la pregunta',
type: ApplicationCommandOptionType.String,
required: true,
},
],
},
],
execute: async (ctx, options) => {
switch (ctx.interaction.options.getSubcommand()) {
case 'new': {
const modal = new ModalBuilder()
.setCustomId('askjavi')
.setTitle('Sugerencias');
const input = new TextInputBuilder()
.setCustomId('askjavi-prompt')
.setLabel('Qué quieres preguntarle?')
.setStyle(TextInputStyle.Paragraph);
const suggestionsActionRow =
new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(
input
);
modal.addComponents(suggestionsActionRow);
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('askjavi-buttons-yes')
.setLabel('Sí!')
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId('askjavi-buttons-no')
.setLabel('Ok mejor no')
.setStyle(ButtonStyle.Danger)
);
const message = await ctx.reply({
content: `No puedes enviar sugerencias inútiles o spam.\nSi haces esto, serás descalificado.\nContinuas?`,
components: [buttons],
ephemeral: true,
});
const collector = message.createMessageComponentCollector({
max: 1,
componentType: ComponentType.Button,
time: 60_000,
});
collector.on('collect', async (i) => {
if (i.customId === 'askjavi-buttons-yes') {
const suggestionid = randomnumbergen(5);
await i.showModal(modal);
await ctx.interaction.editReply({
components: [],
});
const submitted = (await ctx.interaction
.awaitModalSubmit({
time: 180000,
filter: (i) => i.user.id === ctx.user.id,
})
.catch((error) => {})) as ModalSubmitInteraction;
const db = new padyama({
id: i.user.id,
user: i.user.username,
suggestionid: suggestionid,
suggestion: submitted.fields.getTextInputValue('askjavi-prompt'),
});
await db.save();
await submitted.reply({
content: `Tu pregunta ha sido registrada en la base de datos correctamente.\nEl ID de esta pregunta es: \`${suggestionid}\`. Se te contactará por DMs cuando se responda la pregunta.\nPuedes ver tus IDs de preguntas con el comando </askjavi you:1040938647001776199>.`,
ephemeral: true,
});
}
if (i.customId === 'askjavi-buttons-no') {
await ctx.interaction.editReply({
content: 'Ok pues...',
components: [],
});
}
});
}
case 'get': {
const option = options[1].getString('id');
const db = await padyama.findOne({ suggestionid: option });
if (db?.suggestion !== undefined)
return await ctx.reply({
content: `La sugerencia es:\n${db?.suggestion}`,
ephemeral: true,
});
else
return await ctx.reply({
content: `Parece que ese ID no se ha encontrado...`,
ephemeral: true,
});
}
case 'you': {
const db = await padyama.find({ id: ctx.user.id });
await ctx.reply({
content: `Los IDs de las preguntas que has hecho:\n${db.map(
(doc) => `\`${doc.suggestionid}\``
)}`,
ephemeral: true,
});
}
case 'answered': {
if (ctx.user.id !== '703974042700611634')
return await ctx.reply({
content: `No puedes usar este comando.`,
ephemeral: true,
});
const option = options[1].getString('id');
const db = await padyama.findOne({ suggestionid: option });
if (db?.user !== undefined) {
try {
await (await ctx.user.fetch(db?.id))
.send({
content: `Hola!\nRespecto al AMA del sevidor de Mara:\nTu pregunta con ID \`${option}\` ha sido respondida correctamente!`,
})
.then(async () => {
await ctx.reply({
content: `DM enviado correctamente!`,
ephemeral: true,
});
});
} catch (err) {
await ctx.reply({
content: `Parece que no se ha podido enviar el DM...`,
ephemeral: true,
});
}
} else {
await ctx.reply({
content: `No se ha encontrado el usuario enlazado con el ID en cuestión...`,
ephemeral: true,
});
}
}
}
},
});

View File

@@ -1,49 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { Context, SlashOptions } from "@sern/handler";
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
import { publish } from "../../src/plugins/publish.js";
export default commandModule({
name: 'creditos',
type: CommandType.Slash,
plugins: [publish()],
description: 'Créditos del bot (en inglés)',
//alias : [],
options: [],
execute: async (ctx, options) => {
const baseEmbed = new EmbedBuilder()
.setColor('Blurple')
.setTitle(`Without these people, the bot wouldn't exist!`)
.setAuthor({name: ctx.user.username, iconURL: ctx.user.displayAvatarURL()})
.setFooter({text: `Created by Sr Izan | This list will be expanded`, iconURL: ctx.client.user?.displayAvatarURL()})
const page1 = baseEmbed
.setDescription(`**Development**\n
<@703974042700611634>: Main development.\n
<@464397024247152640>: Trusting me and inviting the bot.\n
**For helping me out**\n
<@182326315813306368>: sern handler dev, helper at WOK, such a cool guy and helper <3\n
<@697795666373640213>: sern handler dev, also helper at WOK, helped me out a ton\n
*Some people at the D.JS discord*: yeah\n
**Motivation**\n
<@719678368173523015>: WHAT ARE YOU DOING ON VINCI RN?!?!?!\n
<@530870655005097995>: Gave some ideas on the *original* roadmap\n
<@678000774441336842>: My good'ol friend, always has been trying new Vinci stuff\n
<@758743564879659069>: Believe it or not, this looper has alvays been beta-testing stuff\n
<@697146020647403651>: For always thanking all my work\n
**And, of course, you <3**\n
Thanks everyone, this has been an absolute ride, I don't have words to express my appreciation! <:Pepelove:1030904410307563542>
`)
const buttons = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setLabel('lol')
.setURL('https://discord.com/channels/928018226330337280/928018227156643857/1030480463690731530')
.setStyle(ButtonStyle.Link),
new ButtonBuilder()
.setLabel('<3')
.setURL('https://discord.com/channels/928018226330337280/1030913456846680134')
.setStyle(ButtonStyle.Link)
)
await ctx.reply({embeds: [page1], components: [buttons], ephemeral: true})
},
});

View File

@@ -1,61 +0,0 @@
import { commandModule, CommandType } from "@sern/handler";
import { publish } from "../../src/plugins/publish.js";
import { ApplicationCommandOptionType } from "discord.js";
import { readFileSync } from "node:fs";
import birthdays from "../../schemas/birthdays.js";
import { confirmation } from "../../src/plugins/acceptingBirthday.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
name: "cumple",
type: CommandType.Slash,
plugins: [publish(), confirmation()],
description: "Pon tu cumpleaños en la base de datos para ser felicitado!",
//alias : [],
options: [
{
name: "fecha",
description: "La fecha de tu cumple (D-M) (elige en el autocompletado)",
type: ApplicationCommandOptionType.String,
autocomplete: true,
required: true,
command: {
onEvent: [],
execute: async (autocomplete) => {
const focusedValue = autocomplete.options.getFocused();
let choices = JSON.parse(
String(readFileSync("./util/daysinyear.txt"))
) as Array<string>;
choices = choices.filter((choice) =>
choice.toString().startsWith(focusedValue)
);
choices = choices.slice(0, 25);
await autocomplete.respond(
choices.map((choice) => ({
name: choice.toString(),
value: choice,
}))
);
},
},
},
],
execute: async (ctx, options) => {
const option = ctx.interaction.options.getString("fecha")
const array = JSON.parse(
String(readFileSync("./util/daysinyear.txt"))
) as Array<string>;
if (!array.includes(option!)) return await ctx.interaction.editReply('Asegúrate que estás eligiendo una fecha del autocompletado!')
if (await birthdays.exists({id: ctx.user.id})) return await ctx.interaction.editReply('No puedes poner tu fecha de nuevo!')
const db = new birthdays({
id: ctx.user.id,
date: option,
alreadysent: false
});
await db.save();
await ctx.interaction.editReply('Ok, guardado correctamente. No puedes volver a cambiar la fecha.')
},
});

View File

@@ -1,80 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { createAudioPlayer, createAudioResource, DiscordGatewayAdapterCreator, joinVoiceChannel } from "@discordjs/voice";
import got from "got";
import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
name: 'radio',
type: CommandType.Slash,
plugins: [publish()],
description: 'Reproduce la radio',
options: [
{
name: 'reproducir',
description: 'Reproduce una radio de la lista',
type: ApplicationCommandOptionType.String,
autocomplete: true,
required: true,
command: {
onEvent: [],
async execute(ctx){
const focusedValue = ctx.options.getFocused();
const choices = ['Rock FM', 'Cadena 100', 'Cadena Dial', 'Gensokyo Radio', 'BBC 1', 'BBC 5', 'RNE 1', 'RNE 5', 'Los 40'];
const filtered = choices.filter(choice => choice.startsWith(focusedValue));
await ctx.respond(
filtered.map(choice => ({ name: choice, value: choice })),
);
}
}
}
],
execute: async (ctx, options) => {
const radioname = options[1].getString("reproducir", true) as string;
const embed = new EmbedBuilder()
.setColor("Green")
.setTitle(`Reproduciendo ${radioname} en Vinci Radio.`)
.setDescription(`A veces la radio tarda en cargar, sé paciente :'D`);
const notFoundEmbed = new EmbedBuilder()
.setColor("Red")
.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) {
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)
resource.volume!.setVolume(0.7)
await ctx.reply({embeds: [embed], ephemeral: true})
}
if (radioname === 'Rock FM') {
playRadio("https://flucast-m04-06.flumotion.com/cope/rockfm.mp3")
} else if (radioname === 'Cadena 100') {
playRadio("https://server8.emitironline.com:18196/stream")
} else if (radioname === 'Cadena Dial') {
playRadio("http://20853.live.streamtheworld.com/CADENADIAL.mp3")
} else if (radioname === 'BBC 1') {
playRadio("http://stream.live.vc.bbcmedia.co.uk/bbc_radio_one")
} else if (radioname === 'BBC 5') {
playRadio("https://server8.emitironline.com:18196/stream")
} else if (radioname === 'RNE 1') {
playRadio("https://crtve-rne1-cnr.cast.addradio.de/crtve/rne1/cnr/mp3/high")
} else if (radioname === 'RNE 5') {
playRadio("http://crtve--di--crtve-ice--02--cdn.cast.addradio.de/crtve/rne5/sev/mp3/high")
} else if (radioname === 'Los 40') {
playRadio('http://stream.ondaceronoroeste.es:8000/stream')
} else if (radioname === 'Gensokyo Radio') {
playRadio('https://stream.gensokyoradio.net/3')
} else {
ctx.reply({embeds: [notFoundEmbed], ephemeral: true})
}
},
});

View File

@@ -1,37 +0,0 @@
import { commandModule, CommandType } from "@sern/handler";
import axios, { AxiosError, AxiosResponse } from "axios";
import { ApplicationCommandOptionType } from "discord.js";
import { publish } from "../../src/plugins/publish.js";
export default commandModule({
name: "acortar",
type: CommandType.Slash,
plugins: [
publish(),
],
description: "Acorta una URL a vinci.tk",
options: [
{
name: "url",
description: "la URL larga",
type: ApplicationCommandOptionType.String,
required: true,
},
],
//alias : [],
execute: async (ctx, options) => {
const url = options[1].getString("url", true);
const request = await axios(
`https://vinci.tk/yourls-api.php?signature=${process.env.YOURLS_KEY}&action=shorturl&format=json&url=${url}`,
{
validateStatus: function (status) {
return status === 200 || status === 400;
},
}
).then((res: AxiosResponse) => res.data);
ctx.reply({
content: `URL acortada: <${request.shorturl}>\nURL original: <${url}>`,
ephemeral: true,
});
},
});

View File

@@ -1,44 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { EmbedBuilder } from "discord.js";
import axios from "axios";
import prettySeconds from 'pretty-seconds-spanish'
export default commandModule({
name: 'stats',
type: CommandType.Slash,
plugins: [publish()],
description: 'Enseña estadísticas del bot.',
//alias : [],
options: [],
execute: async (ctx, options) => {
await ctx.interaction.deferReply({ ephemeral: true })
const cpubrand = await axios(`http://192.168.1.44:7271/cpubrand`)
const cpucores = await axios(`http://192.168.1.44:7271/cpucores`)
const ramtotal = await axios(`http://192.168.1.44:7271/ramtotal`)
const ramfree = await axios(`http://192.168.1.44:7271/ramfree`)
const dockertotal = await axios(`http://192.168.1.44:7271/dockertotal`)
const uptime = prettySeconds(process.uptime())
const embed = new EmbedBuilder()
.setAuthor({name: `${ctx.user.username}`, iconURL: `${ctx.user.displayAvatarURL()}`})
.setTitle(`Estadísticas de Vinci.`)
.setThumbnail(`https://i.imgur.com/UwC1x8T.png`)
.setURL('https://status.vinci.tk')
.setColor('Random')
.addFields(
{name: "Fabricante de CPU", value: `${cpubrand.data}`, inline: true},
{name: `Núcleos de CPU`, value: `${cpucores.data}`, inline: true},
{name: '\u200B', value: '\u200B', inline: true},
{name: `RAM total`, value: `${ramtotal.data}`, inline: true},
{name: `RAM libre`, value: `${ramfree.data}`, inline: true},
{name: '\u200B', value: '\u200B', inline: true},
{name: 'Contenedores de Docker', value: `${dockertotal.data}`, inline: true},
{name: '\u200B', value: '\u200B', inline: true},
{name: 'Tiempo encendido', value: `${uptime}`},
// {name: '\u200B', value: '\u200B', inline: true},
// {name: 'Uptime del servidor', value: `${prettySeconds(`${nodeuptime.data}`)}`}
)
await ctx.interaction.editReply({embeds: [embed]})
},
});

View File

@@ -1,32 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ModalActionRowComponentBuilder } from 'discord.js'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
export default commandModule({
name: 'sugerencias',
type: CommandType.Slash,
plugins: [publish()],
description: 'Envia una sugerencia.',
//alias : [],
execute: async (ctx) => {
const modal = new ModalBuilder()
.setCustomId('sugerencias')
.setTitle('Sugerencias');
// Create the text input components
const input = new TextInputBuilder()
.setCustomId('sugerenciasInput')
// The label is the prompt the user sees for this input
.setLabel("Tienes sugerencias?")
// Short means only a single line of text
.setStyle(TextInputStyle.Paragraph);
// An action row only holds one text input,
// so you need one action row per text input.
const suggestionsActionRow = new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(input);
// Add inputs to the modal
modal.addComponents(suggestionsActionRow);
await ctx.interaction.showModal(modal);
}
});

View File

@@ -1,17 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import prettySeconds from 'pretty-seconds-spanish'
export default commandModule({
name: 'uptime',
type: CommandType.Slash,
plugins: [publish()],
description: 'Enseña el tiempo que ha estado encendido el bot.',
//alias : [],
options: [],
execute: async (ctx, options) => {
// const uptime = prettyMilliseconds(ctx.client.uptime!)
const uptime = prettySeconds(process.uptime())
await ctx.reply(`El bot lleva encendido ${uptime}`);
},
});

View File

@@ -1,36 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js";
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 (e) {
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.`})
}
},
});

View File

@@ -1,42 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ApplicationCommandOptionType, TextChannel } from "discord.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
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 (e) {
await ctx.reply({content: `ERROR: No se ha podido eliminar el mensaje, asegúrate que estás usando el ID y el canal correcto.`})
}
},
});

View File

@@ -1,38 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js";
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 (e) {
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.`})
}
},
});

View File

@@ -1,32 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js";
import { ApplicationCommandOptionType, TextChannel } from 'discord.js'
export default commandModule({
name: 'prune',
type: CommandType.Slash,
plugins: [publish(), ownerOnly()],
description: 'ADMIN: Elimina hasta 100 mensajes',
options: [{
name: 'numero',
description: 'Escribe un número',
type: ApplicationCommandOptionType.Number,
required: true,
min_value: 1,
max_value: 100
}],
//alias : [],
execute: async (ctx, options) => {
try {
const amount = options[1].getNumber('numero', true) as number
(ctx.channel 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
await sendToMods.send({content: `Se han eliminado ${amount} mensajes en ${ctx.channel}\nEfectuado por ${ctx.user}.`})
} catch (e){
ctx.reply({content: 'Ha habido un error eliminando mensajes! Error reportado automáticamente.', ephemeral: true})};
}
});

View File

@@ -1,40 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ApplicationCommandOptionType, TextChannel } from "discord.js";
export default commandModule({
name: 'slowmode',
type: CommandType.Slash,
plugins: [publish(), ownerOnly()],
description: 'ADMIN: Pon modo lento a canales de texto',
options: [
{
name: "segundos",
description: "Los segundos de modo lento",
type: ApplicationCommandOptionType.Number,
required: true
},
{
name: "razon",
description: "La razón del modo lento",
type: ApplicationCommandOptionType.String,
required: true
}
],
//alias : [],
execute: async (ctx, options) => {
try {
const seconds = options[1].getNumber("segundos", true);
const reason = options[1].getString("razon", true);
(ctx.channel 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
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 (e) {
ctx.reply({content: `No se ha podido aplicar modo lento al canal.`})
}
},
});

View File

@@ -1,50 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ApplicationCommandOptionType, GuildMember, TextChannel } from "discord.js";
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
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 (e) {
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.`})
}
},
});

View File

@@ -1,212 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js";
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}.`))
}
}
}
});
}
}
}
})

View File

@@ -1,20 +0,0 @@
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../src/plugins/publish.js";
import { ownerOnly } from "../src/plugins/ownerOnly.js"
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
name: 'ping',
type: CommandType.Slash,
plugins: [publish()],
// , '928018226330337280'
description: 'A ping command',
//alias : [],
options: [],
execute: async (ctx, options) => {
await ctx.reply('Hello World!');
},
});

View File

@@ -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

View File

@@ -1,9 +0,0 @@
import { EventType, eventModule } from "@sern/handler";
export default eventModule({
type: EventType.Sern,
name : 'error',
execute(err) {
console.log(err);
}
})

View File

@@ -1,20 +0,0 @@
import { EmbedBuilder, GuildMember, TextChannel } from "discord.js";
import { EventType, eventModule } from "@sern/handler";
export default eventModule({
type: EventType.Discord,
name: 'guildMemberAdd',
execute(member: GuildMember) {
if (member.guild.id !== process.env.GUILDID) return;
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
channel.send({embeds: [newMemberEmbed]})
}
});

View File

@@ -1,20 +0,0 @@
import { EmbedBuilder, GuildMember, TextChannel } from "discord.js";
import { EventType, eventModule } from "@sern/handler";
export default eventModule({
type: EventType.Discord,
name: 'guildMemberRemove',
execute(member: GuildMember) {
if (member.guild.id !== process.env.GUILDID) return;
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
channel.send({embeds: [leaveEmbed]})
}
});

BIN
images/a/H.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
images/a/SpRaY.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
images/a/Tormentarosa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -1,85 +0,0 @@
import { SernEmitter } from '@sern/handler';
import { ActivityType } from 'discord.js';
import { Client, GatewayIntentBits } from 'discord.js';
import { Sern } from '@sern/handler';
import { config as dotenv } from 'dotenv';
import mongoose from 'mongoose';
import youtubenotifications from './util/youtubenotifications.js';
import { setIntervalAsync } from 'set-interval-async';
import birthdays from './util/birthdays.js';
import twitternotifications from './util/twitternotifications.js';
import webserver from './util/web/webserver.js'
let devMode
if (process.argv[2] === '--dev') {
devMode = true
dotenv({path: '.env.dev'})
console.clear()
} else {
dotenv()
}
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessageReactions,
GatewayIntentBits.GuildVoiceStates,
],
});
mongoose.connect(process.env.MONGODB!).then(() => {
console.log('Connected to MongoDB');
});
Sern.init({
client,
commands: './dist/commands',
sernEmitter: new SernEmitter(),
events: './dist/events',
defaultPrefix: process.env.PREFIX,
});
client.on('ready', async () => {
console.log('Logged on!');
setInterval(() => {
const statuses = [
{ name: 'Minecraft', type: ActivityType.Playing },
{ name: 'cómo escribe Javi', type: ActivityType.Watching },
{ name: 'quinto 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 },
];
const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];
// @ts-ignore
client.user!.setActivity(randomStatus);
}, 10000);
if (!devMode) {
setIntervalAsync(async () => {
await youtubenotifications(client);
}, 120_000);
// setIntervalAsync(async () => {
// await twitternotifications(client);
// }, 120_000);
setIntervalAsync(async () => {
await birthdays(client);
}, 3_600_000);
webserver()
} else {
console.log('DevMode got activated, there are no checkers or webserver in this version.')
}
});
client.on('rateLimit', async () => {
console.log(`I just got ratelimited!`);
});
client.login(process.env.TOKEN);

1
nixpacks.toml Normal file
View File

@@ -0,0 +1 @@
providers = ["node", "python"]

5583
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +1,44 @@
{
"name": "vinci",
"version": "1.0.0",
"description": "Vinci Discord Bot for Mara Turing",
"main": "dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "tsc-watch --onSuccess \"node ./dist/index.js --dev\"",
"compile": "tsc --build",
"build": "tsc --build",
"web": "node webserver.js",
"watch": "tsc --watch",
"start": "nodemon dist/index.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/SrIzan10/vinci.git"
},
"keywords": [
"discord-bot"
],
"type": "module",
"author": "Sr Izan",
"license": "MIT",
"bugs": {
"url": "https://github.com/SrIzan10/vinci/issues"
},
"homepage": "https://github.com/SrIzan10/vinci#readme",
"dependencies": {
"@consumet/extensions": "^1.2.8",
"@discordjs/opus": "^0.9.0",
"@discordjs/voice": "^0.14.0",
"@napi-rs/canvas": "^0.1.30",
"@sern/handler": "^1.2.1",
"axios": "^1.1.3",
"country-flag-emoji": "^1.0.3",
"dayjs": "^1.11.6",
"discord-bot-youtube-notifications": "^1.1.4",
"discord-tictactoe": "^4.0.0",
"discord.js": "^14.5.0",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"got": "^11.8.5",
"libsodium-wrappers": "^0.7.10",
"mongoose": "^6.5.1",
"pretty-seconds-spanish": "^2.1.0",
"rockpaperscissors-checker": "^1.2.0",
"set-interval-async": "^3.0.2",
"systeminformation": "^5.12.6"
},
"devDependencies": {
"@types/express": "^4.17.14",
"ts-node": "10.9.1",
"tsc-watch": "^5.0.3",
"typescript": "^4.9.3"
}
"name": "ts-example",
"version": "1.0.0",
"private": true,
"description": "",
"main": "dist/index.js",
"scripts": {
"build": "sern build",
"start": "bun run --inspect .",
"db:migrate": "prisma migrate deploy",
"install": "sern build",
"commands:publish": "sern commands publish",
"dev": "sern build -w --watch-command \"bun start\"",
"db:mongo": "bun run src/utils/db/migrateMongo.ts"
},
"keywords": [
"typescript",
"sern",
"discord.js"
],
"dependencies": {
"@napi-rs/canvas": "^0.1.72",
"@prisma/client": "^6.10.1",
"@sern/handler": "^4.2.4",
"@sern/publisher": "1.1.2",
"discord.js": "^14.21.0",
"dotenv": "^16.3.1",
"execa": "^9.6.0",
"mongodb": "^6.17.0",
"node-html-parser": "^7.0.1",
"openai": "^5.10.2",
"rockpaperscissors-checker": "^1.2.0",
"sharp": "^0.34.2"
},
"devDependencies": {
"@sern/cli": "^1.4.0",
"@types/bun": "^1.2.18",
"@types/mongodb": "^4.0.7",
"@types/node": "^17.0.25",
"prisma": "^6.10.1",
"typescript": "^5.0"
},
"type": "module"
}

View File

@@ -0,0 +1,15 @@
-- CreateTable
CREATE TABLE "ai_chats" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"messageid" TEXT NOT NULL,
"threadid" TEXT NOT NULL
);
-- CreateTable
CREATE TABLE "AIMessage" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"role" TEXT NOT NULL,
"content" TEXT NOT NULL,
"aiChatId" INTEGER NOT NULL,
CONSTRAINT "AIMessage_aiChatId_fkey" FOREIGN KEY ("aiChatId") REFERENCES "ai_chats" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);

View File

@@ -0,0 +1,19 @@
/*
Warnings:
- You are about to drop the `AIMessage` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropTable
PRAGMA foreign_keys=off;
DROP TABLE "AIMessage";
PRAGMA foreign_keys=on;
-- CreateTable
CREATE TABLE "AiMessage" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"role" TEXT NOT NULL,
"content" TEXT NOT NULL,
"aiChatId" INTEGER NOT NULL,
CONSTRAINT "AiMessage_aiChatId_fkey" FOREIGN KEY ("aiChatId") REFERENCES "ai_chats" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);

View File

@@ -0,0 +1,33 @@
/*
Warnings:
- You are about to drop the `ai_chats` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropTable
PRAGMA foreign_keys=off;
DROP TABLE "ai_chats";
PRAGMA foreign_keys=on;
-- CreateTable
CREATE TABLE "AiChat" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"messageid" TEXT NOT NULL,
"threadid" TEXT NOT NULL
);
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_AiMessage" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"role" TEXT NOT NULL,
"content" TEXT NOT NULL,
"aiChatId" INTEGER NOT NULL,
CONSTRAINT "AiMessage_aiChatId_fkey" FOREIGN KEY ("aiChatId") REFERENCES "AiChat" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_AiMessage" ("aiChatId", "content", "id", "role") SELECT "aiChatId", "content", "id", "role" FROM "AiMessage";
DROP TABLE "AiMessage";
ALTER TABLE "new_AiMessage" RENAME TO "AiMessage";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -0,0 +1,10 @@
-- CreateTable
CREATE TABLE "Afk" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userId" TEXT NOT NULL,
"reason" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "Afk_userId_key" ON "Afk"("userId");

View File

@@ -0,0 +1,12 @@
/*
Warnings:
- A unique constraint covering the columns `[messageid]` on the table `AiChat` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[threadid]` on the table `AiChat` will be added. If there are existing duplicate values, this will fail.
*/
-- CreateIndex
CREATE UNIQUE INDEX "AiChat_messageid_key" ON "AiChat"("messageid");
-- CreateIndex
CREATE UNIQUE INDEX "AiChat_threadid_key" ON "AiChat"("threadid");

View File

@@ -0,0 +1,20 @@
/*
Warnings:
- You are about to drop the column `expiresAt` on the `Afk` table. All the data in the column will be lost.
*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Afk" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userId" TEXT NOT NULL,
"reason" TEXT NOT NULL
);
INSERT INTO "new_Afk" ("id", "reason", "userId") SELECT "id", "reason", "userId" FROM "Afk";
DROP TABLE "Afk";
ALTER TABLE "new_Afk" RENAME TO "Afk";
CREATE UNIQUE INDEX "Afk_userId_key" ON "Afk"("userId");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -0,0 +1,10 @@
-- CreateTable
CREATE TABLE "Birthday" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userId" TEXT NOT NULL,
"date" TEXT NOT NULL,
"sent" BOOLEAN NOT NULL DEFAULT false
);
-- CreateIndex
CREATE UNIQUE INDEX "Birthday_userId_key" ON "Birthday"("userId");

View File

@@ -0,0 +1,12 @@
-- CreateTable
CREATE TABLE "Suggestion" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userId" TEXT NOT NULL,
"msgId" TEXT NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "Suggestion_userId_key" ON "Suggestion"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "Suggestion_msgId_key" ON "Suggestion"("msgId");

View File

@@ -0,0 +1,22 @@
/*
Warnings:
- Added the required column `upDown` to the `Suggestion` table without a default value. This is not possible if the table is not empty.
*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Suggestion" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"userId" TEXT NOT NULL,
"msgId" TEXT NOT NULL,
"upDown" INTEGER NOT NULL
);
INSERT INTO "new_Suggestion" ("id", "msgId", "userId") SELECT "id", "msgId", "userId" FROM "Suggestion";
DROP TABLE "Suggestion";
ALTER TABLE "new_Suggestion" RENAME TO "Suggestion";
CREATE UNIQUE INDEX "Suggestion_userId_key" ON "Suggestion"("userId");
CREATE UNIQUE INDEX "Suggestion_msgId_key" ON "Suggestion"("msgId");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -0,0 +1,2 @@
-- DropIndex
DROP INDEX "Suggestion_userId_key";

View File

@@ -0,0 +1,2 @@
-- DropIndex
DROP INDEX "Suggestion_msgId_key";

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "sqlite"

52
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,52 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "debian-openssl-3.0.x"]
}
datasource db {
provider = "sqlite"
url = "file:./vinci.db"
}
model AiChat {
id Int @id @default(autoincrement())
messageid String @unique
threadid String @unique
messages AiMessage[]
}
model AiMessage {
id Int @id @default(autoincrement())
role String
content String
aiChatId Int
aiChat AiChat @relation(fields: [aiChatId], references: [id])
}
model Afk {
id Int @id @default(autoincrement())
userId String @unique
reason String
}
model Birthday {
id Int @id @default(autoincrement())
userId String @unique
date String
sent Boolean @default(false)
}
model Suggestion {
id Int @id @default(autoincrement())
userId String
msgId String
upDown Int
}

View File

@@ -1,6 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}

View File

@@ -1,8 +0,0 @@
import mongoose from 'mongoose'
const schema = new mongoose.Schema({
id: {type: String, required: true},
date: {type: String, required: true},
alreadysent: {type: Boolean, required: true},
});
const db = mongoose.model('birthday', schema, 'birthdays');
export default db

View File

@@ -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;

View File

@@ -1,9 +0,0 @@
import mongoose from 'mongoose'
const schema = new mongoose.Schema({
id: {type: String, required: true},
user: {type: String, required: true},
suggestionid: {type: String, required: true},
suggestion: {type: String, required: true},
});
const db = mongoose.model('padyama', schema, 'padyama');
export default db

View File

@@ -1,8 +0,0 @@
import mongoose from 'mongoose'
const schema = new mongoose.Schema({
msgid: {type: String, required: true},
userid: {type: String, required: true},
upordown: {type: Number, required: true}
});
const db = mongoose.model('suggestions', schema, 'suggestions');
export default db

View File

@@ -1,7 +0,0 @@
import mongoose from 'mongoose'
const schema = new mongoose.Schema({
id: {type: String, required: true},
user: {type: String, required: true}
});
const db = mongoose.model('twitter', schema, 'twitter');
export default db

View File

@@ -1,7 +0,0 @@
import mongoose from "mongoose";
const schema = new mongoose.Schema({
id: {type: String, required: true},
times: {type: Number, required: true}
});
const db = mongoose.model("warn", schema);
export default db

View File

@@ -1,7 +0,0 @@
import mongoose from 'mongoose'
const schema = new mongoose.Schema({
id: {type: String, required: true},
user: {type: String, required: true}
});
const db = mongoose.model('youtube', schema, 'youtube');
export default db

View File

@@ -1,7 +1,7 @@
{
"language": "typescript",
"paths": {
"base": ".",
"base": "src",
"commands": "commands"
}
}

View File

@@ -1,13 +1,16 @@
import { Resolver } from '../../utils/resolver.js';
import { commandModule, CommandType } from '@sern/handler'
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
import { ActionRowBuilder, ApplicationCommandOptionType, ChannelType, Collection, EmbedBuilder, Role, SelectMenuBuilder, TextChannel } from "discord.js";
import { Resolver } from "../../util/resolver.js";
import { PublishConfig } from '@sern/publisher';
import { ActionRowBuilder, ApplicationCommandOptionType, ChannelType, Collection, EmbedBuilder, PermissionFlagsBits, Role, StringSelectMenuBuilder, TextChannel } from "discord.js";
export const config: PublishConfig = {
defaultMemberPermissions: PermissionFlagsBits.Administrator,
}
export default commandModule({
name: 'rolemenu',
type: CommandType.Slash,
plugins: [publish(), ownerOnly()],
plugins: [],
description: 'ADMIN: Spawnea un menú de roles',
//alias : [],
options: [
@@ -15,7 +18,7 @@ export default commandModule({
name: "channel",
type: ApplicationCommandOptionType.Channel,
description: "The channel to send the message to",
channelTypes: [ChannelType.GuildText],
channel_types: [ChannelType.GuildText],
required: true,
},
{
@@ -31,11 +34,12 @@ 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");
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 +54,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 +72,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 +85,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;
};
};

View File

@@ -0,0 +1,61 @@
import { commandModule, CommandType } from '@sern/handler';
import { AttachmentBuilder } from 'discord.js';
import { Readable } from 'node:stream';
import fs from 'fs';
import { execa } from 'execa';
export default commandModule({
type: CommandType.CtxMsg,
plugins: [],
execute: async (ctx) => {
await ctx.deferReply({ withResponse: true });
const text = ctx.targetMessage.content;
const encodedText = encodeURIComponent(text);
const url = `https://www.tetyys.com/SAPI4/SAPI4?text=${encodedText}&voice=Adult%20Male%20%232%2C%20American%20English%20(TruVoice)&pitch=140&speed=157`;
const request = await fetch(url).then((res) => res.arrayBuffer());
await new Promise((resolve) => setTimeout(resolve, 500));
const randomnumber = randomString(5);
const randomnumber_wav = `bonzi-wav-${randomnumber}.wav`;
const randomnumber_mp3 = `bonzi-mp3-${randomnumber}.mp3`;
fs.writeFileSync(`./src/utils/bonzi_temp/${randomnumber_wav}`, new Uint8Array(request));
const command = execa(
'ffmpeg',
[
'-i',
`./src/utils/bonzi_temp/${randomnumber_wav}`,
'-vn',
`./src/utils/bonzi_temp/${randomnumber_mp3}`,
],
{ shell: true }
);
await new Promise((resolve) => {
command.on('close', resolve);
});
const stream = new Readable();
stream._read = () => {};
stream.push(
Buffer.from(new Uint8Array(fs.readFileSync(`./src/utils/bonzi_temp/${randomnumber_mp3}`)))
);
stream.push(null);
const attachment = new AttachmentBuilder(stream, { name: 'bonzied.mp3' });
fs.unlinkSync(`./src/utils/bonzi_temp/${randomnumber_mp3}`);
fs.unlinkSync(`./src/utils/bonzi_temp/${randomnumber_wav}`);
await ctx.editReply({ files: [attachment] });
},
});
function randomString(length: number): string {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}

View File

@@ -1,14 +1,9 @@
import { commandModule, CommandType } from '@sern/handler';
import { publish } from '../../src/plugins/publish.js';
/*
import { publish } from "../../src/plugins/publish.js";
import { ownerOnly } from "../../src/plugins/ownerOnly.js"
*/
export default commandModule({
name: 'cursivify',
type: CommandType.MenuMsg,
plugins: [publish()],
type: CommandType.CtxMsg,
plugins: [],
execute: async (ctx) => {
await ctx.deferReply()
const trimmedstring = ctx.targetMessage.content.replaceAll('*', '');

View File

@@ -0,0 +1,60 @@
import { commandModule, CommandType } from '@sern/handler';
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)
.webp({ quality: 70 });
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}`,
'Content-Type': 'application/octet-stream',
},
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 imgMetadata = await compressed.metadata();
const canvas = createCanvas(imgMetadata.width!, imgMetadata.height!);
const ctxCanvas = canvas.getContext('2d');
const img = await loadImage(image.url);
ctxCanvas.drawImage(img, 0, 0, imgMetadata.width!, imgMetadata.height!);
ctxCanvas.font = '30px 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] });
},
});

View File

@@ -0,0 +1,26 @@
import { commandModule, CommandType } from '@sern/handler';
export default commandModule({
type: CommandType.Button,
execute: async (ctx) => {
await ctx.deferReply({ ephemeral: true });
const getUserID = await ctx.client.users.fetch(
ctx.message.embeds[0].footer!.text.replace('Discord ID: ', '')
);
await getUserID
.send({
content: `Tu solicitud de entrada al servidor ha sido aceptada correctamente!\nYa puedes entrar al servidor con la IP \`minecraft.maraturing.com\``,
})
.catch(async () => {
await ctx.editReply({
content: `No se ha podido enviar un DM a ${getUserID} <:Sadge:1015764348385382451>`,
});
})
.then(async () => {
await ctx.editReply({
content: `Se ha podido enviar un DM a ${getUserID} correctamente! <:Pog:1030169609178976346>`,
});
});
},
});

View File

@@ -0,0 +1,69 @@
import { commandModule, CommandType } from '@sern/handler';
import {
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
EmbedBuilder,
} from 'discord.js';
export default commandModule({
type: CommandType.Modal,
plugins: [],
description: 'Envia el formulario para entrar al servidor.',
//alias : [],
async execute(modal) {
const value = modal.fields.getTextInputValue('mcUsernameInput');
const specialChars = /[`!@#$%^&*()+\-=\[\]{};':"\\|,.<>\/?~]/;
if (value.length > 16 || value.length < 3 || specialChars.test(value)) {
modal.reply({
content: `ERROR: El nombre de usuario no es válido.`,
ephemeral: true,
});
} else {
try {
const request = await fetch(`https://mcprofile.io/api/v1/java/username/${value}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res.json());
await modal.reply({
content:
'Enviado!\nSé paciente ya que el bot no es automático.',
ephemeral: true,
});
const embed = new EmbedBuilder()
.setAuthor({
name: modal.user.username,
iconURL: modal.user.displayAvatarURL(),
})
.setColor('Green')
.setTitle('Nueva solicitud de entrada al servidor!')
.setDescription(
`Su nombre de usuario en Minecraft es: \`${value}\`\nSu UUID: \`${request.uuid}\``
)
.setFooter({ text: `Discord ID: ${modal.user.id}` });
const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('mcform-dm')
.setLabel('Añadido a la whitelist!')
.setStyle(ButtonStyle.Success)
);
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:
'ERROR: No se ha podido enviar ya que eres un usuario no premium o de MC Bedrock.\nAsegúrate que has puesto bien el nombre de usuario.',
ephemeral: true,
});
}
}
},
});

View File

@@ -0,0 +1,85 @@
import { commandModule, CommandType } from '@sern/handler';
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from 'discord.js';
import { ThreadAutoArchiveDuration } from 'discord.js';
export default commandModule({
type: CommandType.Modal,
async execute(modal) {
const value = modal.fields.getTextInputValue('sugerenciasInput');
if (onlySpaces(value) === true) {
return await modal.reply({
content: 'Buen intento enviando un mensaje vacío >:D',
ephemeral: true,
});
}
const embed = new EmbedBuilder()
.setColor('Random')
.setTitle('Sugerencia')
.setAuthor({
name: `${modal.user.username}`,
iconURL: `${modal.user.displayAvatarURL()}`,
})
.setDescription(value);
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('suggestions-yes')
.setEmoji('✅')
.setLabel('0')
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId('suggestions-no')
.setEmoji('❎')
.setLabel('0')
.setStyle(ButtonStyle.Danger)
);
const row2 = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('suggestions-yes-who')
.setEmoji('✅')
.setLabel('Quién')
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId('suggestions-no-who')
.setEmoji('❎')
.setLabel('Quién')
.setStyle(ButtonStyle.Secondary)
);
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.',
});
const rowSuccess = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setURL(msg.url)
.setLabel('Ver sugerencia')
.setStyle(ButtonStyle.Link)
);
const modalReply = await modal.reply({
content: '¡Enviado!',
ephemeral: true,
components: [rowSuccess],
});
setTimeout(() => {
modalReply.delete().catch(() => {});
}, 3000);
},
});
function onlySpaces(str: string) {
return str.trim().length === 0;
}

View File

@@ -0,0 +1,23 @@
import { commandModule, CommandType } from '@sern/handler';
import db from '../../utils/db';
export default commandModule({
type: CommandType.Button,
async execute(interaction) {
await interaction.deferReply({ ephemeral: true });
const votes = await db.suggestion.findMany({
where: { msgId: interaction.message.id, upDown: -1 },
});
const fetchedIds = await Promise.all(
votes.map(async (v) => {
return interaction.client.users.fetch(v.userId);
})
);
await interaction.editReply({
content: `Gente que ha hecho downvote:\n${
fetchedIds.length > 0 ? fetchedIds.join(', ') : 'Nadie, de momento'
}`,
allowedMentions: { repliedUser: false },
});
},
});

View File

@@ -0,0 +1,73 @@
import { commandModule, CommandType } from '@sern/handler';
import {
ActionRow,
ActionRowBuilder,
APIButtonComponentWithCustomId,
ButtonBuilder,
ButtonComponent,
ButtonComponentData,
ButtonStyle,
MessageActionRowComponent,
} from 'discord.js';
import db from '../../utils/db';
export default commandModule({
type: CommandType.Button,
async execute(interaction) {
const row1 = interaction.message!.components[0] as ActionRow<MessageActionRowComponent>;
const row2 = interaction.message!.components[1] as ActionRow<MessageActionRowComponent>;
const rows = {
yes: row1.components[0],
no: row1.components[1],
yesWho: row2.components[0],
noWho: row2.components[1],
} as {
yes: ButtonComponent;
no: ButtonComponent;
yesWho: ButtonComponent;
noWho: ButtonComponent;
};
const upvoteData = rows.yes.data as APIButtonComponentWithCustomId;
const downvoteData = rows.no.data as APIButtonComponentWithCustomId;
const userSuggestion = await db.suggestion.findFirst({
where: { msgId: interaction.message.id, userId: interaction.user.id },
});
if (!userSuggestion) {
const row1 = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(rows.yes.data),
new ButtonBuilder(rows.no.data).setLabel((parseInt(downvoteData.label!) + 1).toString())
);
await db.suggestion.create({
data: {
msgId: interaction.message.id,
userId: interaction.user.id,
upDown: -1,
},
});
await interaction.message.edit({ components: [row1, row2] });
await interaction.deferUpdate();
return;
}
const userSuggestionUpDown = userSuggestion.upDown === 1;
if (userSuggestionUpDown) {
await db.suggestion.updateMany({
where: { msgId: interaction.message.id, userId: interaction.user.id, upDown: 1 },
data: { upDown: -1 },
});
const row1 = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(rows.yes.data).setLabel((parseInt(upvoteData.label!) - 1).toString()),
new ButtonBuilder(rows.no.data).setLabel((parseInt(downvoteData.label!) + 1).toString())
);
await interaction.message.edit({ components: [row1, row2] });
await interaction.deferUpdate();
return;
} else {
await interaction.deferUpdate()
return;
}
},
});

View File

@@ -0,0 +1,23 @@
import { commandModule, CommandType } from '@sern/handler';
import db from '../../utils/db';
export default commandModule({
type: CommandType.Button,
async execute(interaction) {
await interaction.deferReply({ ephemeral: true });
const votes = await db.suggestion.findMany({
where: { msgId: interaction.message.id, upDown: 1 },
});
const fetchedIds = await Promise.all(
votes.map(async (v) => {
return interaction.client.users.fetch(v.userId);
})
);
await interaction.editReply({
content: `Gente que ha hecho upvote:\n${
fetchedIds.length > 0 ? fetchedIds.join(', ') : 'Nadie, de momento'
}`,
allowedMentions: { repliedUser: false },
});
},
});

View File

@@ -0,0 +1,73 @@
import { commandModule, CommandType } from '@sern/handler';
import {
ActionRow,
ActionRowBuilder,
APIButtonComponentWithCustomId,
ButtonBuilder,
ButtonComponent,
ButtonComponentData,
ButtonStyle,
MessageActionRowComponent,
} from 'discord.js';
import db from '../../utils/db';
export default commandModule({
type: CommandType.Button,
async execute(interaction) {
const row1 = interaction.message!.components[0] as ActionRow<MessageActionRowComponent>;
const row2 = interaction.message!.components[1] as ActionRow<MessageActionRowComponent>;
const rows = {
yes: row1.components[0],
no: row1.components[1],
yesWho: row2.components[0],
noWho: row2.components[1],
} as {
yes: ButtonComponent;
no: ButtonComponent;
yesWho: ButtonComponent;
noWho: ButtonComponent;
};
const upvoteData = rows.yes.data as APIButtonComponentWithCustomId;
const downvoteData = rows.no.data as APIButtonComponentWithCustomId;
const userSuggestion = await db.suggestion.findFirst({
where: { msgId: interaction.message.id, userId: interaction.user.id },
});
if (!userSuggestion) {
const row1 = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(rows.yes.data).setLabel((parseInt(upvoteData.label!) + 1).toString()),
new ButtonBuilder(rows.no.data)
);
await db.suggestion.create({
data: {
msgId: interaction.message.id,
userId: interaction.user.id,
upDown: 1,
},
});
await interaction.message.edit({ components: [row1, row2] });
await interaction.deferUpdate();
return;
}
const userSuggestionUpDown = userSuggestion.upDown === 1;
if (userSuggestionUpDown) {
await interaction.deferUpdate()
return;
} else {
await db.suggestion.updateMany({
where: { msgId: interaction.message.id, userId: interaction.user.id, upDown: -1 },
data: { upDown: 1 },
});
const row1 = new ActionRowBuilder<ButtonBuilder>().setComponents(
new ButtonBuilder(rows.yes.data).setLabel((parseInt(upvoteData.label!) + 1).toString()),
new ButtonBuilder(rows.no.data).setLabel((parseInt(downvoteData.label!) - 1).toString())
);
await interaction.message.edit({ components: [row1, row2] });
await interaction.deferUpdate();
return;
}
},
});

View File

@@ -0,0 +1,31 @@
import { commandModule, CommandType } from '@sern/handler';
import { ApplicationCommandOptionType } from 'discord.js';
export default commandModule({
name: 'ip',
type: CommandType.Slash,
plugins: [],
description: 'La IP del servidor de Minecraft',
options: [
{
name: 'usuario',
description: 'Menciona al usuario al que va dirigido el comando.',
type: ApplicationCommandOptionType.User,
},
],
execute: async (ctx) => {
const usuario = ctx.options.getMember('usuario');
const message = 'La IP del servidor de Minecraft es `minecraft.maraturing.com`,\nPide acceso con el comando `/mcform`.'
if (!usuario) {
await ctx.reply({
content: message,
ephemeral: true,
});
} else {
await ctx.reply({
content: `${usuario}, ${message}`,
});
}
},
});

View File

@@ -0,0 +1,29 @@
import { commandModule, CommandType } from '@sern/handler';
import {
ActionRowBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle,
ModalActionRowComponentBuilder,
} from 'discord.js';
export default commandModule({
name: 'mcform',
type: CommandType.Slash,
plugins: [],
description: 'Envia el formulario para entrar al servidor.',
execute: async (ctx) => {
const modal = new ModalBuilder()
.setCustomId('mcform-modal')
.setTitle('Formulario para entrar al servidor');
const input = new TextInputBuilder()
.setCustomId('mcUsernameInput')
.setLabel('Cuál es tu nombre de usuario de Minecraft?')
.setStyle(TextInputStyle.Short);
const usernameActionRow = new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(
input
);
modal.addComponents(usernameActionRow);
await ctx.interaction.showModal(modal);
},
});

View File

@@ -0,0 +1,58 @@
import { commandModule, CommandType } from '@sern/handler';
import { ApplicationCommandOptionType } from 'discord.js';
export default commandModule({
type: CommandType.Slash,
plugins: [],
description: 'acorta una url',
options: [
{
name: 'url',
description: 'la url a acortar',
type: ApplicationCommandOptionType.String,
required: true,
},
{
name: 'alias',
description: 'alias opcional para la url acortada',
type: ApplicationCommandOptionType.String,
required: false,
}
],
execute: async (ctx) => {
const url = ctx.options.getString('url', true);
const alias = ctx.options.getString('alias');
const res = await fetch('https://spoo.me', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
url,
// idk why copilot did that but ok
...(alias && { alias })
})
}).then(r => r.json());
if (res.error) {
return ctx.reply({
content: `Error al acortar la URL: ${res.message}`,
ephemeral: true,
});
}
if (res.short_url) {
return ctx.reply({
content: `URL acortada: ${res.short_url}`,
ephemeral: true,
});
}
return ctx.reply({
content: `Algo no ha ido bien!`,
ephemeral: true,
});
},
});

View File

@@ -0,0 +1,62 @@
import { commandModule, CommandType } from '@sern/handler';
import { ApplicationCommandOptionType } from 'discord.js';
import { readFileSync } from 'fs';
export default commandModule({
type: CommandType.Slash,
plugins: [],
description: 'Añade tu cumpleaños',
options: [
{
name: 'fecha',
description: 'La fecha de tu cumple (D-M) (elige en el autocompletado)',
type: ApplicationCommandOptionType.String,
autocomplete: true,
required: true,
command: {
onEvent: [],
execute: async (autocomplete) => {
const focusedValue = autocomplete.options.getFocused();
let choices = JSON.parse(readFileSync('./assets/daysinyear.json').toString()) as string[];
choices = choices.filter((choice) => choice.startsWith(focusedValue));
choices = choices.slice(0, 25);
await autocomplete.respond(
choices.map((choice) => ({
name: choice,
value: choice,
}))
);
},
},
},
],
execute: async (ctx, sdt) => {
const date = ctx.interaction.options.getString('fecha', true);
const existing = await sdt.deps.prisma.birthday.findUnique({
where: { userId: ctx.user.id },
});
if (existing) {
await sdt.deps.prisma.birthday.update({
where: { userId: ctx.user.id },
data: { date },
});
await ctx.reply({
content: `cumpleaños actualizado a ${date}!`,
ephemeral: true,
});
} else {
await sdt.deps.prisma.birthday.create({
data: {
userId: ctx.user.id,
date,
},
});
await ctx.reply({
content: `cumpleaños registrado para el ${date}!`,
ephemeral: true,
});
}
},
});

View File

@@ -0,0 +1,27 @@
import { commandModule, CommandType } from '@sern/handler';
import {
ActionRowBuilder,
ModalBuilder,
TextInputBuilder,
TextInputStyle,
ModalActionRowComponentBuilder,
} from 'discord.js';
export default commandModule({
name: 'sugerencias',
type: CommandType.Slash,
plugins: [],
description: 'Envia una sugerencia.',
execute: async (ctx) => {
const modal = new ModalBuilder().setCustomId('sugerencias').setTitle('Sugerencias');
const input = new TextInputBuilder()
.setCustomId('sugerenciasInput')
.setLabel('Tienes sugerencias?')
.setStyle(TextInputStyle.Paragraph);
const suggestionsActionRow =
new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(input);
modal.addComponents(suggestionsActionRow);
await ctx.interaction.showModal(modal);
},
});

View File

@@ -0,0 +1,69 @@
import { commandModule, CommandType } from '@sern/handler'
import { ApplicationCommandOptionType, AutocompleteInteraction, CacheType, CommandInteractionOptionResolver } from 'discord.js';
import { getWikipedia, searchWikipedia } from '../../utils/wikipedia';
export default commandModule({
type: CommandType.Slash,
plugins: [],
description: 'Busca cosas por wikipedia',
//alias : [],
options: [
{
name: 'español',
description: 'Busca cosas por Wikipedia en español',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'busqueda',
description: 'Escribe qué buscar.',
type: ApplicationCommandOptionType.String,
required: true,
autocomplete: true,
command: {
onEvent: [],
execute: async (ctx) => {
const search = await searchWikipedia('es', ctx as AutocompleteInteraction)
await ctx.respond(
search.map(res => ({ name: res.title.toString(), value: res.pageid.toString() }))
)
}
}
}
]
},
{
name: 'ingles',
description: 'Busca cosas por Wikipedia en inglés',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'search',
description: 'Escribe qué buscar.',
type: ApplicationCommandOptionType.String,
required: true,
autocomplete: true,
command: {
onEvent: [],
execute: async (ctx) => {
const search = await searchWikipedia('en', ctx as AutocompleteInteraction)
await ctx.respond(
search.map(res => ({ name: res.title.toString(), value: res.pageid.toString() }))
)
}
}
}
]
}
],
execute: async (ctx) => {
const options = ctx.options as unknown as CommandInteractionOptionResolver<CacheType>
switch (ctx.options.getSubcommand()) {
case 'español': {
getWikipedia('es', ctx, options);
} break;
case 'ingles': {
getWikipedia('en', ctx, options);
} break;
}
},
});

Some files were not shown because too many files have changed in this diff Show More