Version Estable
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
# Keep environment variables out of version control
|
||||
.env
|
||||
|
||||
/src/generated/prisma
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
12
.idea/amayo.iml
generated
Normal file
12
.idea/amayo.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/jsLibraryMappings.xml
generated
Normal file
6
.idea/jsLibraryMappings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<includedPredefinedLibrary name="Node.js Core" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/amayo.iml" filepath="$PROJECT_DIR$/.idea/amayo.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
989
package-lock.json
generated
Normal file
989
package-lock.json
generated
Normal file
@@ -0,0 +1,989 @@
|
||||
{
|
||||
"name": "amayo",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "amayo",
|
||||
"version": "0.0.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@prisma/client": "6.16.2",
|
||||
"discord-api-types": "0.38.24",
|
||||
"discord.js": "14.22.1",
|
||||
"prisma": "6.16.2",
|
||||
"redis": "5.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.3.1",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders": {
|
||||
"version": "1.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.11.3.tgz",
|
||||
"integrity": "sha512-p3kf5eV49CJiRTfhtutUCeivSyQ/l2JlKodW1ZquRwwvlOWmG9+6jFShX6x8rUiYhnP6wKI96rgN/SXMy5e5aw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/formatters": "^0.6.1",
|
||||
"@discordjs/util": "^1.1.1",
|
||||
"@sapphire/shapeshift": "^4.0.0",
|
||||
"discord-api-types": "^0.38.16",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"ts-mixer": "^6.0.4",
|
||||
"tslib": "^2.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/collection": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
|
||||
"integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=16.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/formatters": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.6.1.tgz",
|
||||
"integrity": "sha512-5cnX+tASiPCqCWtFcFslxBVUaCetB0thvM/JyavhbXInP1HJIEU+Qv/zMrnuwSsX3yWH2lVXNJZeDK3EiP4HHg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"discord-api-types": "^0.38.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/rest": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.6.0.tgz",
|
||||
"integrity": "sha512-RDYrhmpB7mTvmCKcpj+pc5k7POKszS4E2O9TYc+U+Y4iaCP+r910QdO43qmpOja8LRr1RJ0b3U+CqVsnPqzf4w==",
|
||||
"license": "Apache-2.0",
|
||||
"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.16",
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.21.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/rest/node_modules/@discordjs/collection": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
|
||||
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/util": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz",
|
||||
"integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/ws": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.3.tgz",
|
||||
"integrity": "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==",
|
||||
"license": "Apache-2.0",
|
||||
"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"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/ws/node_modules/@discordjs/collection": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
|
||||
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/client": {
|
||||
"version": "6.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.16.2.tgz",
|
||||
"integrity": "sha512-E00PxBcalMfYO/TWnXobBVUai6eW/g5OsifWQsQDzJYm7yaY+IRLo7ZLsaefi0QkTpxfuhFcQ/w180i6kX3iJw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prisma": "*",
|
||||
"typescript": ">=5.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"prisma": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/config": {
|
||||
"version": "6.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.16.2.tgz",
|
||||
"integrity": "sha512-mKXSUrcqXj0LXWPmJsK2s3p9PN+aoAbyMx7m5E1v1FufofR1ZpPoIArjjzOIm+bJRLLvYftoNYLx1tbHgF9/yg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"c12": "3.1.0",
|
||||
"deepmerge-ts": "7.1.5",
|
||||
"effect": "3.16.12",
|
||||
"empathic": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/debug": {
|
||||
"version": "6.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.2.tgz",
|
||||
"integrity": "sha512-bo4/gA/HVV6u8YK2uY6glhNsJ7r+k/i5iQ9ny/3q5bt9ijCj7WMPUwfTKPvtEgLP+/r26Z686ly11hhcLiQ8zA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@prisma/engines": {
|
||||
"version": "6.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.16.2.tgz",
|
||||
"integrity": "sha512-7yf3AjfPUgsg/l7JSu1iEhsmZZ/YE00yURPjTikqm2z4btM0bCl2coFtTGfeSOWbQMmq45Jab+53yGUIAT1sjA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "6.16.2",
|
||||
"@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43",
|
||||
"@prisma/fetch-engine": "6.16.2",
|
||||
"@prisma/get-platform": "6.16.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/engines-version": {
|
||||
"version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43.tgz",
|
||||
"integrity": "sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@prisma/fetch-engine": {
|
||||
"version": "6.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.16.2.tgz",
|
||||
"integrity": "sha512-wPnZ8DMRqpgzye758ZvfAMiNJRuYpz+rhgEBZi60ZqDIgOU2694oJxiuu3GKFeYeR/hXxso4/2oBC243t/whxQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "6.16.2",
|
||||
"@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43",
|
||||
"@prisma/get-platform": "6.16.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/get-platform": {
|
||||
"version": "6.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.16.2.tgz",
|
||||
"integrity": "sha512-U/P36Uke5wS7r1+omtAgJpEB94tlT4SdlgaeTc6HVTTT93pXj7zZ+B/cZnmnvjcNPfWddgoDx8RLjmQwqGDYyA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/debug": "6.16.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/bloom": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.8.2.tgz",
|
||||
"integrity": "sha512-855DR0ChetZLarblio5eM0yLwxA9Dqq50t8StXKp5bAtLT0G+rZ+eRzzqxl37sPqQKjUudSYypz55o6nNhbz0A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/client": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-5.8.2.tgz",
|
||||
"integrity": "sha512-WtMScno3+eBpTac1Uav2zugXEoXqaU23YznwvFgkPwBQVwEHTDgOG7uEAObtZ/Nyn8SmAMbqkEubJaMOvnqdsQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/json": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/json/-/json-5.8.2.tgz",
|
||||
"integrity": "sha512-uxpVfas3I0LccBX9rIfDgJ0dBrUa3+0Gc8sEwmQQH0vHi7C1Rx1Qn8Nv1QWz5bohoeIXMICFZRcyDONvum2l/w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/search": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-5.8.2.tgz",
|
||||
"integrity": "sha512-cNv7HlgayavCBXqPXgaS97DRPVWFznuzsAmmuemi2TMCx5scwLiP50TeZvUS06h/MG96YNPe6A0Zt57yayfxwA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/time-series": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.8.2.tgz",
|
||||
"integrity": "sha512-g2NlHM07fK8H4k+613NBsk3y70R2JIM2dPMSkhIjl2Z17SYvaYKdusz85d7VYOrZBWtDrHV/WD2E3vGu+zni8A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^5.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@sapphire/async-queue": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
|
||||
"integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=v14.0.0",
|
||||
"npm": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sapphire/shapeshift": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-4.0.0.tgz",
|
||||
"integrity": "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v16"
|
||||
}
|
||||
},
|
||||
"node_modules/@sapphire/snowflake": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz",
|
||||
"integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=v14.0.0",
|
||||
"npm": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@standard-schema/spec": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
|
||||
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz",
|
||||
"integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@vladfrangu/async_event_emitter": {
|
||||
"version": "2.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.6.tgz",
|
||||
"integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=v14.0.0",
|
||||
"npm": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/c12": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz",
|
||||
"integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.3",
|
||||
"confbox": "^0.2.2",
|
||||
"defu": "^6.1.4",
|
||||
"dotenv": "^16.6.1",
|
||||
"exsolve": "^1.0.7",
|
||||
"giget": "^2.0.0",
|
||||
"jiti": "^2.4.2",
|
||||
"ohash": "^2.0.11",
|
||||
"pathe": "^2.0.3",
|
||||
"perfect-debounce": "^1.0.0",
|
||||
"pkg-types": "^2.2.0",
|
||||
"rc9": "^2.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"magicast": "^0.3.5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"magicast": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/citty": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz",
|
||||
"integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"consola": "^3.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/cluster-key-slot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/confbox": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
|
||||
"integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/consola": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
|
||||
"integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deepmerge-ts": {
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz",
|
||||
"integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/defu": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
|
||||
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/destr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
|
||||
"integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/discord-api-types": {
|
||||
"version": "0.38.24",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.24.tgz",
|
||||
"integrity": "sha512-P7/DkcFIiIoaBogStnhhcGRX7KR+gIFp0SpmwsZUIM0bgDkYMEUx+8l+t3quYc/KSgg92wvE9w/4mabO57EMug==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"scripts/actions/documentation"
|
||||
]
|
||||
},
|
||||
"node_modules/discord.js": {
|
||||
"version": "14.22.1",
|
||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.22.1.tgz",
|
||||
"integrity": "sha512-3k+Kisd/v570Jr68A1kNs7qVhNehDwDJAPe4DZ2Syt+/zobf9zEcuYFvsfIaAOgCa0BiHMfOOKQY4eYINl0z7w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^1.11.2",
|
||||
"@discordjs/collection": "1.5.3",
|
||||
"@discordjs/formatters": "^0.6.1",
|
||||
"@discordjs/rest": "^2.6.0",
|
||||
"@discordjs/util": "^1.1.1",
|
||||
"@discordjs/ws": "^1.2.3",
|
||||
"@sapphire/snowflake": "3.5.3",
|
||||
"discord-api-types": "^0.38.16",
|
||||
"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"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/effect": {
|
||||
"version": "3.16.12",
|
||||
"resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz",
|
||||
"integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"fast-check": "^3.23.1"
|
||||
}
|
||||
},
|
||||
"node_modules/empathic": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz",
|
||||
"integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/exsolve": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
|
||||
"integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-check": {
|
||||
"version": "3.23.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz",
|
||||
"integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/dubzzz"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fast-check"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pure-rand": "^6.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/giget": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
|
||||
"integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"citty": "^0.1.6",
|
||||
"consola": "^3.4.0",
|
||||
"defu": "^6.1.4",
|
||||
"node-fetch-native": "^1.6.6",
|
||||
"nypm": "^0.6.0",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"bin": {
|
||||
"giget": "dist/cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
|
||||
"integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.snakecase": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
|
||||
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/magic-bytes.js": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.12.1.tgz",
|
||||
"integrity": "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/node-fetch-native": {
|
||||
"version": "1.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
|
||||
"integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nypm": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz",
|
||||
"integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"citty": "^0.1.6",
|
||||
"consola": "^3.4.2",
|
||||
"pathe": "^2.0.3",
|
||||
"pkg-types": "^2.3.0",
|
||||
"tinyexec": "^1.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"nypm": "dist/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.16.0 || >=16.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ohash": {
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
|
||||
"integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pathe": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/perfect-debounce": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
||||
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pkg-types": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
|
||||
"integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"confbox": "^0.2.2",
|
||||
"exsolve": "^1.0.7",
|
||||
"pathe": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/prisma": {
|
||||
"version": "6.16.2",
|
||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-6.16.2.tgz",
|
||||
"integrity": "sha512-aRvldGE5UUJTtVmFiH3WfNFNiqFlAtePUxcI0UEGlnXCX7DqhiMT5TRYwncHFeA/Reca5W6ToXXyCMTeFPdSXA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prisma/config": "6.16.2",
|
||||
"@prisma/engines": "6.16.2"
|
||||
},
|
||||
"bin": {
|
||||
"prisma": "build/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=5.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pure-rand": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
|
||||
"integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/dubzzz"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fast-check"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rc9": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz",
|
||||
"integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"defu": "^6.1.4",
|
||||
"destr": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/redis": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-5.8.2.tgz",
|
||||
"integrity": "sha512-31vunZj07++Y1vcFGcnNWEf5jPoTkGARgfWI4+Tk55vdwHxhAvug8VEtW7Cx+/h47NuJTEg/JL77zAwC6E0OeA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@redis/bloom": "5.8.2",
|
||||
"@redis/client": "5.8.2",
|
||||
"@redis/json": "5.8.2",
|
||||
"@redis/search": "5.8.2",
|
||||
"@redis/time-series": "5.8.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyexec": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz",
|
||||
"integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ts-mixer": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
|
||||
"integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
"@tsconfig/node12": "^1.0.7",
|
||||
"@tsconfig/node14": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"arg": "^4.1.0",
|
||||
"create-require": "^1.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"v8-compile-cache-lib": "^3.0.1",
|
||||
"yn": "3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"ts-node": "dist/bin.js",
|
||||
"ts-node-cwd": "dist/bin-cwd.js",
|
||||
"ts-node-esm": "dist/bin-esm.js",
|
||||
"ts-node-script": "dist/bin-script.js",
|
||||
"ts-node-transpile-only": "dist/bin-transpile.js",
|
||||
"ts-script": "dist/bin-script-deprecated.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/core": ">=1.2.50",
|
||||
"@swc/wasm": ">=1.2.50",
|
||||
"@types/node": "*",
|
||||
"typescript": ">=2.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@swc/wasm": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.21.3",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
|
||||
"integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
|
||||
"integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
package.json
Normal file
25
package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "amayo",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "src/main.ts",
|
||||
"scripts": {
|
||||
"dev": "npx tsx watch src/main.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"type": "commonjs",
|
||||
"dependencies": {
|
||||
"@prisma/client": "6.16.2",
|
||||
"discord-api-types": "0.38.24",
|
||||
"discord.js": "14.22.1",
|
||||
"prisma": "6.16.2",
|
||||
"redis": "5.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.3.1",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.2"
|
||||
}
|
||||
}
|
||||
BIN
prisma/dev.db
Normal file
BIN
prisma/dev.db
Normal file
Binary file not shown.
62
prisma/migrations/20250917001309_modals/migration.sql
Normal file
62
prisma/migrations/20250917001309_modals/migration.sql
Normal file
@@ -0,0 +1,62 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "Guild" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PartnershipStats" (
|
||||
"totalPoints" INTEGER NOT NULL DEFAULT 0,
|
||||
"weeklyPoints" INTEGER NOT NULL DEFAULT 0,
|
||||
"monthlyPoints" INTEGER NOT NULL DEFAULT 0,
|
||||
"lastWeeklyReset" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"lastMonthlyReset" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"userId" TEXT NOT NULL,
|
||||
"guildId" TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY ("userId", "guildId"),
|
||||
CONSTRAINT "PartnershipStats_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT "PartnershipStats_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Alliance" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"channelId" TEXT NOT NULL,
|
||||
"messageId" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"guildId" TEXT NOT NULL,
|
||||
"creatorId" TEXT NOT NULL,
|
||||
CONSTRAINT "Alliance_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT "Alliance_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "EmbedConfig" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"color" TEXT,
|
||||
"title" TEXT,
|
||||
"url" TEXT,
|
||||
"authorName" TEXT,
|
||||
"authorIconURL" TEXT,
|
||||
"authorURL" TEXT,
|
||||
"description" TEXT,
|
||||
"thumbnailURL" TEXT,
|
||||
"imageURL" TEXT,
|
||||
"footerText" TEXT,
|
||||
"footerIconURL" TEXT,
|
||||
"fields" TEXT DEFAULT '[]',
|
||||
"guildId" TEXT NOT NULL,
|
||||
CONSTRAINT "EmbedConfig_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Alliance_messageId_key" ON "Alliance"("messageId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "EmbedConfig_guildId_key" ON "EmbedConfig"("guildId");
|
||||
33
prisma/migrations/20250917002041_modals/migration.sql
Normal file
33
prisma/migrations/20250917002041_modals/migration.sql
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- Added the required column `name` to the `EmbedConfig` 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_EmbedConfig" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"color" TEXT,
|
||||
"title" TEXT,
|
||||
"url" TEXT,
|
||||
"authorName" TEXT,
|
||||
"authorIconURL" TEXT,
|
||||
"authorURL" TEXT,
|
||||
"description" TEXT,
|
||||
"thumbnailURL" TEXT,
|
||||
"imageURL" TEXT,
|
||||
"footerText" TEXT,
|
||||
"footerIconURL" TEXT,
|
||||
"fields" TEXT DEFAULT '[]',
|
||||
"guildId" TEXT NOT NULL,
|
||||
CONSTRAINT "EmbedConfig_guildId_fkey" FOREIGN KEY ("guildId") REFERENCES "Guild" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
INSERT INTO "new_EmbedConfig" ("authorIconURL", "authorName", "authorURL", "color", "description", "fields", "footerIconURL", "footerText", "guildId", "id", "imageURL", "thumbnailURL", "title", "url") SELECT "authorIconURL", "authorName", "authorURL", "color", "description", "fields", "footerIconURL", "footerText", "guildId", "id", "imageURL", "thumbnailURL", "title", "url" FROM "EmbedConfig";
|
||||
DROP TABLE "EmbedConfig";
|
||||
ALTER TABLE "new_EmbedConfig" RENAME TO "EmbedConfig";
|
||||
CREATE UNIQUE INDEX "EmbedConfig_guildId_name_key" ON "EmbedConfig"("guildId", "name");
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA defer_foreign_keys=OFF;
|
||||
13
prisma/migrations/20250917044008_modals/migration.sql
Normal file
13
prisma/migrations/20250917044008_modals/migration.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
-- RedefineTables
|
||||
PRAGMA defer_foreign_keys=ON;
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_Guild" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"prefix" TEXT NOT NULL DEFAULT '!'
|
||||
);
|
||||
INSERT INTO "new_Guild" ("id", "name") SELECT "id", "name" FROM "Guild";
|
||||
DROP TABLE "Guild";
|
||||
ALTER TABLE "new_Guild" RENAME TO "Guild";
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA defer_foreign_keys=OFF;
|
||||
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal 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"
|
||||
133
prisma/schema.prisma
Normal file
133
prisma/schema.prisma
Normal file
@@ -0,0 +1,133 @@
|
||||
// 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"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Modelo para el Servidor (Guild)
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
model Guild {
|
||||
id String @id
|
||||
name String
|
||||
prefix String @default("!")
|
||||
|
||||
// Relaciones
|
||||
alliances Alliance[]
|
||||
partnerStats PartnershipStats[]
|
||||
|
||||
// ✅ CAMBIO: Ahora un Guild puede tener MÚLTIPLES configuraciones de embed.
|
||||
embedConfigs EmbedConfig[]
|
||||
}
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Modelo para el Usuario
|
||||
* -----------------------------------------------------------------------------
|
||||
* Representa a un usuario de Discord de manera global.
|
||||
*/
|
||||
model User {
|
||||
id String @id
|
||||
|
||||
// Relaciones
|
||||
partnerStats PartnershipStats[]
|
||||
createdAlliances Alliance[]
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Modelo para las Estadísticas de Alianza (Leaderboard)
|
||||
* -----------------------------------------------------------------------------
|
||||
* Almacena los puntos de un usuario EN UN SERVIDOR específico.
|
||||
* Se gana 1 punto por mensaje en los canales registrados.
|
||||
*/
|
||||
model PartnershipStats {
|
||||
// Puntos acumulados totales.
|
||||
totalPoints Int @default(0)
|
||||
|
||||
// Puntos para la tabla de clasificación semanal.
|
||||
weeklyPoints Int @default(0)
|
||||
|
||||
// Puntos para la tabla de clasificación mensual.
|
||||
monthlyPoints Int @default(0)
|
||||
|
||||
// Fecha del último reinicio para controlar los contadores.
|
||||
lastWeeklyReset DateTime @default(now())
|
||||
lastMonthlyReset DateTime @default(now())
|
||||
|
||||
// --- Relaciones y Clave Primaria ---
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
guild Guild @relation(fields: [guildId], references: [id])
|
||||
guildId String
|
||||
|
||||
// Un usuario solo puede tener un registro de estadísticas por servidor.
|
||||
@@id([userId, guildId])
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Modelo para la Alianza (El mensaje publicado)
|
||||
* -----------------------------------------------------------------------------
|
||||
* Guarda la referencia al mensaje de alianza, pero no su contenido.
|
||||
* El contenido se construye dinámicamente usando EmbedConfig y PartnershipStats.
|
||||
*/
|
||||
model Alliance {
|
||||
id String @id @default(cuid())
|
||||
channelId String
|
||||
messageId String @unique
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// --- Relaciones ---
|
||||
guild Guild @relation(fields: [guildId], references: [id])
|
||||
guildId String
|
||||
creator User @relation(fields: [creatorId], references: [id])
|
||||
creatorId String
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Modelo para la Configuración del Embed
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
model EmbedConfig {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// ✅ NUEVO: Un nombre único para identificar este embed dentro del servidor.
|
||||
// Ejemplos: "alianza", "bienvenida", "reglas"
|
||||
name String
|
||||
|
||||
// Campos del Embed (título, descripción, color, etc.)
|
||||
color String?
|
||||
title String?
|
||||
url String?
|
||||
authorName String?
|
||||
authorIconURL String?
|
||||
authorURL String?
|
||||
description String?
|
||||
thumbnailURL String?
|
||||
imageURL String?
|
||||
footerText String?
|
||||
footerIconURL String?
|
||||
fields String? @default("[]")
|
||||
|
||||
// --- Relación ---
|
||||
guild Guild @relation(fields: [guildId], references: [id])
|
||||
|
||||
// ✅ CAMBIO: Quitamos '@unique' para permitir que un guildId aparezca múltiples veces.
|
||||
guildId String
|
||||
|
||||
// ✅ NUEVO: Asegura que el 'name' sea único por cada servidor.
|
||||
// No puedes tener dos embeds llamados "alianza" en el mismo servidor.
|
||||
@@unique([guildId, name])
|
||||
}
|
||||
292
src/commands/messages/alliaces/createEmbed.ts
Normal file
292
src/commands/messages/alliaces/createEmbed.ts
Normal file
@@ -0,0 +1,292 @@
|
||||
import { CommandMessage } from "../../../core/types/commands";
|
||||
// @ts-ignore
|
||||
import { EmbedBuilder, ActionRowBuilder, ButtonBuilder, TextChannel, ChannelType } from "discord.js";
|
||||
//@ts-ignore
|
||||
import { ButtonStyle, ComponentType } from "discord.js";
|
||||
import { replaceVars } from "../../../core/lib/vars";
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: "embedcreate",
|
||||
type: "message",
|
||||
aliases: ["crearembed", "newembed"],
|
||||
cooldown: 20,
|
||||
// @ts-ignore
|
||||
run: async (message, args, client) => {
|
||||
if (!message.member?.permissions.has("Administrator")) {
|
||||
return message.reply("❌ No tienes permisos de Administrador.");
|
||||
}
|
||||
|
||||
const embedName: string | null = args[0] ?? null;
|
||||
if (!embedName) {
|
||||
return message.reply(
|
||||
"Debes proporcionar un nombre para el embed. Uso: `!embedcreate <nombre>`"
|
||||
);
|
||||
}
|
||||
|
||||
const nameIsValid = await client.prisma.embedConfig.findFirst({ where: {
|
||||
//@ts-ignore
|
||||
guildId: message.guild.id,
|
||||
name: embedName
|
||||
}})
|
||||
if(nameIsValid) return message.reply("❌ Nombre del embed ya fue tomado!")
|
||||
|
||||
// 📌 Estado independiente
|
||||
let embedState: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
color?: number;
|
||||
footer?: string;
|
||||
} = {
|
||||
title: `Editor de Embed: ${embedName}`,
|
||||
description:
|
||||
"Usa los botones de abajo para configurar este embed.\n\n_Ejemplo de variable: `{user.name}`_",
|
||||
color: 0x5865f2,
|
||||
footer: "Haz clic en Guardar cuando termines.",
|
||||
};
|
||||
|
||||
// 📌 Función para construir un embed a partir del estado
|
||||
const renderPreview = async () => {
|
||||
const preview = new EmbedBuilder()
|
||||
.setColor(embedState.color ?? 0x5865f2);
|
||||
|
||||
if (embedState.title)
|
||||
preview.setTitle(
|
||||
//@ts-ignore
|
||||
await replaceVars(embedState.title, message.member)
|
||||
);
|
||||
if (embedState.description)
|
||||
preview.setDescription(
|
||||
//@ts-ignore
|
||||
await replaceVars(embedState.description, message.member)
|
||||
);
|
||||
if (embedState.footer)
|
||||
preview.setFooter({
|
||||
//@ts-ignore
|
||||
text: await replaceVars(embedState.footer, message.member),
|
||||
});
|
||||
|
||||
return preview;
|
||||
};
|
||||
|
||||
// 📌 Botones
|
||||
const generateButtonRows = (disabled = false) => {
|
||||
const primaryRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_title")
|
||||
.setLabel("Título")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(disabled),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_description")
|
||||
.setLabel("Descripción")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(disabled),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_color")
|
||||
.setLabel("Color")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(disabled)
|
||||
);
|
||||
|
||||
const secondaryRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_footer")
|
||||
.setLabel("Footer")
|
||||
.setStyle(ButtonStyle.Secondary)
|
||||
.setDisabled(disabled)
|
||||
);
|
||||
|
||||
const controlRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("save_embed")
|
||||
.setLabel("Guardar")
|
||||
.setStyle(ButtonStyle.Success)
|
||||
.setDisabled(disabled),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("cancel_embed")
|
||||
.setLabel("Cancelar")
|
||||
.setStyle(ButtonStyle.Danger)
|
||||
.setDisabled(disabled)
|
||||
);
|
||||
|
||||
return [primaryRow, secondaryRow, controlRow];
|
||||
};
|
||||
|
||||
if (message.channel.type === ChannelType.GuildText) {
|
||||
const channel = message.channel as TextChannel;
|
||||
|
||||
const editorMessage = await channel.send({
|
||||
embeds: [await renderPreview()],
|
||||
components: generateButtonRows(),
|
||||
});
|
||||
|
||||
const collector = editorMessage.createMessageComponentCollector({
|
||||
componentType: ComponentType.Button,
|
||||
time: 300000,
|
||||
});
|
||||
|
||||
collector.on("collect", async (i) => {
|
||||
if (i.user.id !== message.author.id) {
|
||||
await i.reply({
|
||||
content: "No puedes usar este menú.",
|
||||
ephemeral: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await i.deferUpdate();
|
||||
await editorMessage.edit({ components: generateButtonRows(true) });
|
||||
|
||||
// Guardar
|
||||
if (i.customId === "save_embed") {
|
||||
try {
|
||||
const dataForDb = {
|
||||
title: embedState.title,
|
||||
description: embedState.description,
|
||||
color: embedState.color ? `#${embedState.color.toString(16).padStart(6, '0')}` : null,
|
||||
footerText: embedState.footer,
|
||||
};
|
||||
|
||||
await client.prisma.embedConfig.upsert({
|
||||
where: {
|
||||
guildId_name: {
|
||||
guildId: message.guildId!,
|
||||
name: embedName,
|
||||
},
|
||||
},
|
||||
update: dataForDb,
|
||||
create: {
|
||||
name: embedName,
|
||||
...dataForDb,
|
||||
// ✅ ESTA ES LA SOLUCIÓN:
|
||||
// Le decimos a Prisma que se conecte al Guild o lo cree si no existe.
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
where: { id: message.guildId! },
|
||||
create: {
|
||||
id: message.guildId!,
|
||||
name: message.guild!.name, // Asegura que el nombre del servidor se guarde
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const saved = new EmbedBuilder()
|
||||
.setColor(0x00ff00)
|
||||
.setTitle(`✅ Guardado: ${embedName}`)
|
||||
.setDescription("La configuración se guardó en la base de datos.");
|
||||
|
||||
await editorMessage.edit({
|
||||
embeds: [saved],
|
||||
components: [],
|
||||
});
|
||||
} catch (e) {
|
||||
const errorEmbed = new EmbedBuilder()
|
||||
.setColor(0xff0000)
|
||||
.setTitle("❌ Error al Guardar")
|
||||
.setDescription("No se pudo guardar en la base de datos. Revisa la consola.");
|
||||
await editorMessage.edit({
|
||||
embeds: [errorEmbed],
|
||||
components: [],
|
||||
});
|
||||
console.error("Error de Prisma al guardar el embed:", e);
|
||||
}
|
||||
collector.stop();
|
||||
return;
|
||||
}
|
||||
// Cancelar
|
||||
if (i.customId === "cancel_embed") {
|
||||
await editorMessage.delete();
|
||||
collector.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Edición
|
||||
let promptContent = "";
|
||||
let fieldToEdit: "title" | "description" | "color" | "footer" | null =
|
||||
null;
|
||||
|
||||
switch (i.customId) {
|
||||
case "edit_title":
|
||||
promptContent =
|
||||
"Escribe el nuevo **título** (puedes usar variables como `{user.name}`).";
|
||||
fieldToEdit = "title";
|
||||
break;
|
||||
case "edit_description":
|
||||
promptContent =
|
||||
"Escribe la nueva **descripción** (puedes usar variables).";
|
||||
fieldToEdit = "description";
|
||||
break;
|
||||
case "edit_color":
|
||||
promptContent =
|
||||
"Escribe el nuevo **color** en formato hexadecimal (ej: `#FF0000`).";
|
||||
fieldToEdit = "color";
|
||||
break;
|
||||
case "edit_footer":
|
||||
promptContent =
|
||||
"Escribe el nuevo **texto del footer** (puedes usar variables).";
|
||||
fieldToEdit = "footer";
|
||||
break;
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
const promptMessage = await i.channel.send(promptContent);
|
||||
|
||||
//@ts-ignore
|
||||
const messageCollector = i.channel!.createMessageCollector({
|
||||
//@ts-ignore
|
||||
filter: (m: Message) => m.author.id === i.user.id,
|
||||
max: 1,
|
||||
time: 60000,
|
||||
});
|
||||
//@ts-ignore
|
||||
messageCollector.on("collect", async (collectedMessage) => {
|
||||
const newValue = collectedMessage.content;
|
||||
|
||||
if (fieldToEdit === "title") embedState.title = newValue;
|
||||
if (fieldToEdit === "description") embedState.description = newValue;
|
||||
if (fieldToEdit === "footer") embedState.footer = newValue;
|
||||
|
||||
if (fieldToEdit === "color") {
|
||||
try {
|
||||
const hex = newValue.replace("#", "");
|
||||
embedState.color = parseInt(hex, 16);
|
||||
} catch {
|
||||
embedState.color = 0x5865f2;
|
||||
}
|
||||
}
|
||||
|
||||
await collectedMessage.delete();
|
||||
await promptMessage.delete();
|
||||
|
||||
await editorMessage.edit({
|
||||
embeds: [await renderPreview()],
|
||||
components: generateButtonRows(false),
|
||||
});
|
||||
});
|
||||
//@ts-ignore
|
||||
messageCollector.on("end", async (collected) => {
|
||||
if (collected.size === 0) {
|
||||
await promptMessage.delete();
|
||||
await editorMessage.edit({
|
||||
components: generateButtonRows(false),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
collector.on("end", async (_, reason) => {
|
||||
if (reason === "time") {
|
||||
const timeoutEmbed = new EmbedBuilder()
|
||||
.setColor(0xff0000)
|
||||
.setTitle("Editor finalizado por inactividad.");
|
||||
|
||||
await editorMessage.edit({
|
||||
embeds: [timeoutEmbed],
|
||||
components: [],
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
276
src/commands/messages/alliaces/editEmbed.ts
Normal file
276
src/commands/messages/alliaces/editEmbed.ts
Normal file
@@ -0,0 +1,276 @@
|
||||
import { CommandMessage } from "../../../core/types/commands";
|
||||
// @ts-ignore
|
||||
import { EmbedBuilder, ActionRowBuilder, ButtonBuilder, TextChannel, ChannelType } from "discord.js";
|
||||
//@ts-ignore
|
||||
import { ButtonStyle, ComponentType } from "discord.js";
|
||||
import { replaceVars } from "../../../core/lib/vars";
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: "editembed",
|
||||
type: "message",
|
||||
aliases: ["modembed", "updateembed"],
|
||||
cooldown: 20,
|
||||
// @ts-ignore
|
||||
run: async (message, args, client) => {
|
||||
if (!message.member?.permissions.has("Administrator")) {
|
||||
return message.reply("❌ No tienes permisos de Administrador.");
|
||||
}
|
||||
|
||||
const embedName: string | null = args[0] ?? null;
|
||||
if (!embedName) {
|
||||
return message.reply(
|
||||
"Debes proporcionar un nombre para el embed. Uso: `!editembed <nombre>`"
|
||||
);
|
||||
}
|
||||
|
||||
// 📌 Buscar en la base de datos
|
||||
const existing = await client.prisma.embedConfig.findUnique({
|
||||
where: {
|
||||
guildId_name: {
|
||||
guildId: message.guildId!,
|
||||
name: embedName,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
return message.reply("❌ No encontré un embed con ese nombre.");
|
||||
}
|
||||
|
||||
// 📌 Estado inicial desde DB
|
||||
let embedState: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
color?: number;
|
||||
footer?: string;
|
||||
} = {
|
||||
title: existing.title ?? undefined,
|
||||
description: existing.description ?? undefined,
|
||||
color: existing.color ? parseInt(existing.color.replace("#", ""), 16) : 0x5865f2,
|
||||
footer: existing.footerText ?? undefined,
|
||||
};
|
||||
|
||||
// 📌 Función para renderizar preview
|
||||
const renderPreview = async () => {
|
||||
const preview = new EmbedBuilder().setColor(embedState.color ?? 0x5865f2);
|
||||
|
||||
if (embedState.title)
|
||||
//@ts-ignore
|
||||
preview.setTitle(await replaceVars(embedState.title, message.member));
|
||||
if (embedState.description)
|
||||
//@ts-ignore
|
||||
preview.setDescription(await replaceVars(embedState.description, message.member));
|
||||
if (embedState.footer)
|
||||
preview.setFooter({
|
||||
//@ts-ignore
|
||||
text: await replaceVars(embedState.footer, message.member),
|
||||
});
|
||||
|
||||
return preview;
|
||||
};
|
||||
|
||||
const generateButtonRows = (disabled = false) => {
|
||||
const primaryRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_title")
|
||||
.setLabel("Título")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(disabled),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_description")
|
||||
.setLabel("Descripción")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(disabled),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_color")
|
||||
.setLabel("Color")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(disabled)
|
||||
);
|
||||
|
||||
const secondaryRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit_footer")
|
||||
.setLabel("Footer")
|
||||
.setStyle(ButtonStyle.Secondary)
|
||||
.setDisabled(disabled)
|
||||
);
|
||||
|
||||
const controlRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("save_embed")
|
||||
.setLabel("Guardar cambios")
|
||||
.setStyle(ButtonStyle.Success)
|
||||
.setDisabled(disabled),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("cancel_embed")
|
||||
.setLabel("Cancelar")
|
||||
.setStyle(ButtonStyle.Danger)
|
||||
.setDisabled(disabled)
|
||||
);
|
||||
|
||||
return [primaryRow, secondaryRow, controlRow];
|
||||
};
|
||||
|
||||
if (message.channel.type === ChannelType.GuildText) {
|
||||
const channel = message.channel as TextChannel;
|
||||
|
||||
const editorMessage = await channel.send({
|
||||
embeds: [await renderPreview()],
|
||||
components: generateButtonRows(),
|
||||
});
|
||||
|
||||
const collector = editorMessage.createMessageComponentCollector({
|
||||
componentType: ComponentType.Button,
|
||||
time: 300000,
|
||||
});
|
||||
|
||||
collector.on("collect", async (i) => {
|
||||
if (i.user.id !== message.author.id) {
|
||||
await i.reply({
|
||||
content: "No puedes usar este menú.",
|
||||
ephemeral: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await i.deferUpdate();
|
||||
await editorMessage.edit({ components: generateButtonRows(true) });
|
||||
|
||||
// Guardar cambios
|
||||
if (i.customId === "save_embed") {
|
||||
try {
|
||||
const dataForDb = {
|
||||
title: embedState.title,
|
||||
description: embedState.description,
|
||||
color: embedState.color ? `#${embedState.color.toString(16).padStart(6, '0')}` : null,
|
||||
footerText: embedState.footer,
|
||||
};
|
||||
|
||||
await client.prisma.embedConfig.update({
|
||||
where: {
|
||||
guildId_name: {
|
||||
guildId: message.guildId!,
|
||||
name: embedName,
|
||||
},
|
||||
},
|
||||
data: dataForDb,
|
||||
});
|
||||
|
||||
const saved = new EmbedBuilder()
|
||||
.setColor(0x00ff00)
|
||||
.setTitle(`✅ Actualizado: ${embedName}`)
|
||||
.setDescription("Los cambios fueron guardados en la base de datos.");
|
||||
|
||||
await editorMessage.edit({
|
||||
embeds: [saved],
|
||||
components: [],
|
||||
});
|
||||
} catch (e) {
|
||||
const errorEmbed = new EmbedBuilder()
|
||||
.setColor(0xff0000)
|
||||
.setTitle("❌ Error al Guardar")
|
||||
.setDescription("No se pudo guardar en la base de datos. Revisa la consola.");
|
||||
await editorMessage.edit({
|
||||
embeds: [errorEmbed],
|
||||
components: [],
|
||||
});
|
||||
console.error("Error de Prisma al actualizar el embed:", e);
|
||||
}
|
||||
collector.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancelar
|
||||
if (i.customId === "cancel_embed") {
|
||||
await editorMessage.delete();
|
||||
collector.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Edición
|
||||
let promptContent = "";
|
||||
let fieldToEdit: "title" | "description" | "color" | "footer" | null =
|
||||
null;
|
||||
|
||||
switch (i.customId) {
|
||||
case "edit_title":
|
||||
promptContent = "Escribe el nuevo **título** (puedes usar variables).";
|
||||
fieldToEdit = "title";
|
||||
break;
|
||||
case "edit_description":
|
||||
promptContent = "Escribe la nueva **descripción**.";
|
||||
fieldToEdit = "description";
|
||||
break;
|
||||
case "edit_color":
|
||||
promptContent = "Escribe el nuevo **color** en formato hexadecimal (ej: `#FF0000`).";
|
||||
fieldToEdit = "color";
|
||||
break;
|
||||
case "edit_footer":
|
||||
promptContent = "Escribe el nuevo **texto del footer**.";
|
||||
fieldToEdit = "footer";
|
||||
break;
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
const promptMessage = await i.channel.send(promptContent);
|
||||
|
||||
//@ts-ignore
|
||||
const messageCollector = i.channel!.createMessageCollector({
|
||||
//@ts-ignore
|
||||
filter: (m: Message) => m.author.id === i.user.id,
|
||||
max: 1,
|
||||
time: 60000,
|
||||
});
|
||||
|
||||
//@ts-ignore
|
||||
messageCollector.on("collect", async (collectedMessage) => {
|
||||
const newValue = collectedMessage.content;
|
||||
|
||||
if (fieldToEdit === "title") embedState.title = newValue;
|
||||
if (fieldToEdit === "description") embedState.description = newValue;
|
||||
if (fieldToEdit === "footer") embedState.footer = newValue;
|
||||
|
||||
if (fieldToEdit === "color") {
|
||||
try {
|
||||
const hex = newValue.replace("#", "");
|
||||
embedState.color = parseInt(hex, 16);
|
||||
} catch {
|
||||
embedState.color = 0x5865f2;
|
||||
}
|
||||
}
|
||||
|
||||
await collectedMessage.delete();
|
||||
await promptMessage.delete();
|
||||
|
||||
await editorMessage.edit({
|
||||
embeds: [await renderPreview()],
|
||||
components: generateButtonRows(false),
|
||||
});
|
||||
});
|
||||
|
||||
//@ts-ignore
|
||||
messageCollector.on("end", async (collected) => {
|
||||
if (collected.size === 0) {
|
||||
await promptMessage.delete();
|
||||
await editorMessage.edit({
|
||||
components: generateButtonRows(false),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
collector.on("end", async (_, reason) => {
|
||||
if (reason === "time") {
|
||||
const timeoutEmbed = new EmbedBuilder()
|
||||
.setColor(0xff0000)
|
||||
.setTitle("Editor finalizado por inactividad.");
|
||||
|
||||
await editorMessage.edit({
|
||||
embeds: [timeoutEmbed],
|
||||
components: [],
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
34
src/commands/messages/alliaces/embedDelete.ts
Normal file
34
src/commands/messages/alliaces/embedDelete.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { CommandMessage } from "../../../core/types/commands";
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: "embeddelete",
|
||||
type: "message",
|
||||
aliases: ["delembed", "removeembed"],
|
||||
cooldown: 10,
|
||||
//@ts-ignore
|
||||
run: async (message, args, client) => {
|
||||
if (!message.member?.permissions.has("Administrator")) {
|
||||
return message.reply("❌ No tienes permisos de Administrador.");
|
||||
}
|
||||
|
||||
const embedName = args[0];
|
||||
if (!embedName) {
|
||||
return message.reply("Debes proporcionar el nombre del embed a eliminar. Uso: `!embeddelete <nombre>`");
|
||||
}
|
||||
|
||||
try {
|
||||
await client.prisma.embedConfig.delete({
|
||||
where: {
|
||||
guildId_name: {
|
||||
guildId: message.guildId!,
|
||||
name: embedName,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return message.reply(`✅ El embed **${embedName}** fue eliminado con éxito.`);
|
||||
} catch {
|
||||
return message.reply("❌ No encontré un embed con ese nombre.");
|
||||
}
|
||||
},
|
||||
};
|
||||
75
src/commands/messages/alliaces/embedList.ts
Normal file
75
src/commands/messages/alliaces/embedList.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import {CommandMessage} from "../../../core/types/commands";
|
||||
import {
|
||||
//@ts-ignore
|
||||
ChannelType,
|
||||
ContainerBuilder,
|
||||
//@ts-ignore
|
||||
MessageFlags,
|
||||
SectionBuilder,
|
||||
SeparatorBuilder,
|
||||
//@ts-ignore
|
||||
SeparatorSpacingSize,
|
||||
TextChannel,
|
||||
TextDisplayBuilder
|
||||
} from "discord.js";
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: "embedlist",
|
||||
type: "message",
|
||||
aliases: ["listembeds", "embeds"],
|
||||
cooldown: 10,
|
||||
//@ts-ignore
|
||||
run: async (message, args, client) => {
|
||||
if (!message.member?.permissions.has("Administrator")) {
|
||||
return message.reply("❌ No tienes permisos de Administrador.");
|
||||
}
|
||||
|
||||
const embeds = await client.prisma.embedConfig.findMany({
|
||||
where: { guildId: message.guildId! },
|
||||
});
|
||||
|
||||
if (embeds.length === 0) {
|
||||
return message.reply("📭 No hay ningún embed guardado en este servidor.");
|
||||
}
|
||||
|
||||
const title = new TextDisplayBuilder()
|
||||
.setContent('﹒⌒ Embed List ╰୧﹒');
|
||||
|
||||
// Combina la lista de embeds en la misma sección que la miniatura
|
||||
// para un mejor diseño.
|
||||
//@ts-ignore
|
||||
const embedListContent = embeds.map((e, i) => `**${i + 1}.** ${e.name}`).join("\n");
|
||||
|
||||
// Obtenemos la URL del icono de forma segura
|
||||
const guildIconURL = message.guild?.iconURL({ forceStatic: false });
|
||||
|
||||
// Creamos la sección que contendrá el texto Y la miniatura
|
||||
const mainSection = new SectionBuilder()
|
||||
.addTextDisplayComponents(text => text.setContent(embedListContent)); // <--- Componente principal requerido
|
||||
|
||||
// Solo añadimos la miniatura si la URL existe
|
||||
if (guildIconURL) {
|
||||
//@ts-ignore
|
||||
mainSection.setThumbnailAccessory(thumbnail => thumbnail
|
||||
.setURL(guildIconURL)
|
||||
.setDescription('Icono del servidor')
|
||||
);
|
||||
}
|
||||
|
||||
const separator = new SeparatorBuilder()
|
||||
.setSpacing(SeparatorSpacingSize.Large)
|
||||
.setDivider(false);
|
||||
|
||||
const container = new ContainerBuilder()
|
||||
.setAccentColor(0x49225B)
|
||||
.addTextDisplayComponents(title)
|
||||
.addSeparatorComponents(separator)
|
||||
.addSectionComponents(mainSection); // <--- Añadimos la sección ya completa
|
||||
|
||||
|
||||
if (message.channel.type === ChannelType.GuildText) {
|
||||
const channel = message.channel as TextChannel;
|
||||
await channel.send({ components: [container], flags: MessageFlags.IsComponentsV2});
|
||||
}
|
||||
},
|
||||
};
|
||||
11
src/commands/messages/net/ping.ts
Normal file
11
src/commands/messages/net/ping.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import {CommandMessage} from "../../../core/types/commands";
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: 'ping',
|
||||
type: "message",
|
||||
aliases: ['latency', 'pong'],
|
||||
cooldown: 5,
|
||||
run: async (message, args) => {
|
||||
await message.reply('pong!')
|
||||
}
|
||||
}
|
||||
45
src/commands/messages/others/embedtested.ts
Normal file
45
src/commands/messages/others/embedtested.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import {CommandMessage} from "../../../core/types/commands";
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: 'test1',
|
||||
type: "message",
|
||||
cooldown: 5,
|
||||
run: async (message, args) => {
|
||||
//@ts-ignore
|
||||
await message.channel.send({
|
||||
"flags": 32768,
|
||||
"components": [
|
||||
{
|
||||
"type": 17,
|
||||
"components": [
|
||||
{
|
||||
"type": 10,
|
||||
"content": "## ﹒⌒ 🌹 Navegacion 🌹 ╰୧﹒"
|
||||
},
|
||||
{
|
||||
"type": 14,
|
||||
"spacing": 2,
|
||||
"divider": false
|
||||
},
|
||||
{
|
||||
"type": 9,
|
||||
"components": [
|
||||
{
|
||||
"type": 10,
|
||||
"content": "### Reglas dentro del Servidor"
|
||||
}
|
||||
],
|
||||
"accessory": {
|
||||
"style": 2,
|
||||
"type": 5,
|
||||
"label": "Ver",
|
||||
"url": "https://discord.com/channels/1316592320954630144/1417682278762676264/1417901305434734656",
|
||||
}
|
||||
}
|
||||
],
|
||||
"accent_color": 4393549
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
51
src/commands/messages/settings-server/settings.ts
Normal file
51
src/commands/messages/settings-server/settings.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import {CommandMessage} from "../../../core/types/commands";
|
||||
//@ts-ignore
|
||||
import {
|
||||
ButtonStyle, ChannelType,
|
||||
ContainerBuilder,
|
||||
MessageFlags,
|
||||
SectionBuilder, SeparatorBuilder, SeparatorSpacingSize, TextChannel,
|
||||
TextDisplayBuilder,
|
||||
UserSelectMenuBuilder
|
||||
} from "discord.js";
|
||||
|
||||
export const command: CommandMessage = {
|
||||
name: 'settings',
|
||||
type: "message",
|
||||
aliases: ['options', 'stts'],
|
||||
cooldown: 5,
|
||||
run: async (message, args, client) => {
|
||||
const server = await client.prisma.guild.findFirst({ where: { id: message.guild!.id } });
|
||||
const title = new TextDisplayBuilder()
|
||||
.setContent("## ﹒⌒ Settings Seɾveɾ ╰୧﹒")
|
||||
const description = new TextDisplayBuilder()
|
||||
.setContent("Panel de Administracion del bot dentro del servidor.")
|
||||
const sect = new TextDisplayBuilder()
|
||||
.setContent("**Prefix del bot:** " + ` \`\`\`${server.prefix}\`\`\``)
|
||||
|
||||
const section = new SectionBuilder()
|
||||
.addTextDisplayComponents(sect)
|
||||
//@ts-ignore
|
||||
.setButtonAccessory(button => button
|
||||
.setCustomId('prefixsettings')
|
||||
.setLabel('Prefix')
|
||||
.setStyle(ButtonStyle.Primary),
|
||||
)
|
||||
|
||||
const separator = new SeparatorBuilder()
|
||||
.setSpacing(SeparatorSpacingSize.Large)
|
||||
.setDivider(false);
|
||||
|
||||
const main = new ContainerBuilder()
|
||||
.addTextDisplayComponents(title, description)
|
||||
.addSeparatorComponents(separator)
|
||||
.addSectionComponents(section)
|
||||
|
||||
|
||||
//@ts-ignore
|
||||
if (message.channel.type === ChannelType.GuildText) {
|
||||
const channel = message.channel as TextChannel;
|
||||
await channel.send({ components: [main], flags: MessageFlags.IsComponentsV2});
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/commands/splashcmd/net/ping.ts
Normal file
12
src/commands/splashcmd/net/ping.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import {CommandSlash} from "../../../core/types/commands";
|
||||
|
||||
|
||||
export const command: CommandSlash = {
|
||||
name: 'ping',
|
||||
description: 'Ping',
|
||||
type: "slash",
|
||||
cooldown: 10,
|
||||
run: async (interaction, client) => {
|
||||
await interaction.reply('pong!')
|
||||
}
|
||||
}
|
||||
22
src/components/buttons/prefixSettings.ts
Normal file
22
src/components/buttons/prefixSettings.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type {ButtonInteraction} from "discord.js";
|
||||
//@ts-ignore
|
||||
import { ActionRowBuilder, Events, ModalBuilder, TextInputBuilder, TextInputStyle } from 'discord.js'
|
||||
|
||||
export default {
|
||||
customId: "prefixsettings",
|
||||
run: async(interaction: ButtonInteraction) => {
|
||||
const modal = new ModalBuilder()
|
||||
.setCustomId('prefixsettingsmodal')
|
||||
.setTitle('Prefix');
|
||||
|
||||
const prefixInput = new TextInputBuilder()
|
||||
.setCustomId('prefixInput')
|
||||
.setLabel("Change Prefix")
|
||||
.setStyle(TextInputStyle.Short);
|
||||
|
||||
const secondActionRow = new ActionRowBuilder().addComponents(prefixInput);
|
||||
modal.addComponents(secondActionRow);
|
||||
|
||||
await interaction.showModal(modal);
|
||||
}
|
||||
}
|
||||
10
src/components/modals/prefixSettingsModal.ts
Normal file
10
src/components/modals/prefixSettingsModal.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import {ModalSubmitInteraction} from "discord.js";
|
||||
|
||||
export default {
|
||||
customId: "prefixsettingsmodal",
|
||||
run: async (interaction: ModalSubmitInteraction) => {
|
||||
const newPrefix = interaction.fields.getTextInputValue("prefixInput")
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
41
src/core/api/discordAPI.ts
Normal file
41
src/core/api/discordAPI.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { REST } from "discord.js";
|
||||
// @ts-ignore
|
||||
import { Routes } from "discord-api-types/v10";
|
||||
import { commands } from "../loader";
|
||||
|
||||
export async function registeringCommands(): Promise<void> {
|
||||
const commandsToRegister: any[] = [];
|
||||
|
||||
// Recorremos la Collection que ya cargó loadCommands()
|
||||
for (const [name, cmd] of commands) {
|
||||
if (cmd.type === "slash") {
|
||||
commandsToRegister.push({
|
||||
name: cmd.name,
|
||||
description: cmd.description ?? "Sin descripción",
|
||||
type: 1, // CHAT_INPUT
|
||||
options: cmd.options ?? []
|
||||
});
|
||||
|
||||
console.log(`✅ Preparado para registrar: ${cmd.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
const rest = new REST().setToken(process.env.TOKEN ?? "");
|
||||
|
||||
try {
|
||||
console.log(`🚀 Registrando ${commandsToRegister.length} comandos slash...`);
|
||||
|
||||
const data: any = await rest.put(
|
||||
Routes.applicationGuildCommands(
|
||||
process.env.CLIENT!,
|
||||
process.env.guildTest!
|
||||
),
|
||||
{ body: commandsToRegister }
|
||||
);
|
||||
|
||||
console.log(`✅ ${data.length} comandos registrados correctamente.`);
|
||||
} catch (error) {
|
||||
console.error("❌ Error registrando comandos:", error);
|
||||
}
|
||||
}
|
||||
|
||||
49
src/core/client.ts
Normal file
49
src/core/client.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// @ts-ignore
|
||||
import { Client, GatewayIntentBits } from 'discord.js';
|
||||
// 1. Importa PrismaClient
|
||||
// @ts-ignore
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
process.loadEnvFile();
|
||||
|
||||
class Amayo extends Client {
|
||||
public key: string;
|
||||
// 2. Declara la propiedad prisma
|
||||
public prisma: PrismaClient;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
intents: [
|
||||
GatewayIntentBits.Guilds,
|
||||
GatewayIntentBits.GuildMembers,
|
||||
GatewayIntentBits.GuildMessages,
|
||||
GatewayIntentBits.MessageContent,
|
||||
GatewayIntentBits.GuildMessageTyping
|
||||
],
|
||||
rest: {
|
||||
retries: 10
|
||||
}
|
||||
});
|
||||
|
||||
this.key = process.env.TOKEN ?? '';
|
||||
// 3. Instancia PrismaClient en el constructor
|
||||
this.prisma = new PrismaClient();
|
||||
}
|
||||
|
||||
async play () {
|
||||
if(!this.key) {
|
||||
return console.error('No key provided');
|
||||
} else {
|
||||
// Ejemplo de cómo usarías prisma antes de iniciar sesión
|
||||
try {
|
||||
await this.prisma.$connect();
|
||||
console.log('Successfully connected to the database.');
|
||||
await this.login(this.key);
|
||||
} catch (error) {
|
||||
console.error('Failed to connect to the database:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Amayo;
|
||||
49
src/core/components.ts
Normal file
49
src/core/components.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import { Collection } from "discord.js";
|
||||
|
||||
export const buttons: Collection<string, any> = new Collection<string, any>();
|
||||
export const modals = new Collection<string, any>();
|
||||
export const selectmenus = new Collection<string, any>();
|
||||
export const contextmenus = new Collection<string, any>();
|
||||
|
||||
export function loadComponents(dir: string = path.join(__dirname, "..", "components")) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(dir, file);
|
||||
const stat = fs.statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
loadComponents(fullPath); // recursivo
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.endsWith(".ts") && !file.endsWith(".js")) continue;
|
||||
|
||||
const imported = require(fullPath);
|
||||
const component = imported.default ?? imported;
|
||||
|
||||
if (!component?.customId) {
|
||||
console.warn(`⚠️ Archivo ignorado: ${file} (no tiene "customId")`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Detectamos el tipo según la carpeta en la que está
|
||||
if (fullPath.includes("buttons")) {
|
||||
buttons.set(component.customId, component);
|
||||
console.log(`🔘 Botón cargado: ${component.customId}`);
|
||||
} else if (fullPath.includes("modals")) {
|
||||
modals.set(component.customId, component);
|
||||
console.log(`📄 Modal cargado: ${component.customId}`);
|
||||
} else if (fullPath.includes("selectmenus")) {
|
||||
selectmenus.set(component.customId, component);
|
||||
console.log(`📜 SelectMenu cargado: ${component.customId}`);
|
||||
} else if (fullPath.includes("contextmenu")) {
|
||||
contextmenus.set(component.customId, component);
|
||||
console.log(`📑 ContextMenu cargado: ${component.customId}`);
|
||||
} else {
|
||||
console.log(`⚠️ Componente desconocido: ${component.customId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/core/lib/vars.ts
Normal file
12
src/core/lib/vars.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import {Guild, User} from "discord.js";
|
||||
|
||||
export async function replaceVars(text: string, user: User | undefined, guild:
|
||||
Guild | undefined, stats: any) {
|
||||
if(!text) return;
|
||||
|
||||
return text
|
||||
.replace(/(user.name)/g, user!.username ?? '')
|
||||
.replace(/(user.id)/g, user!.id ?? '')
|
||||
.replace(/(user.mention)/g, `<@${user!.id}>`)
|
||||
.replace(/(user.avatar)/g, user!.displayAvatarURL({ forceStatic: false }))
|
||||
}
|
||||
43
src/core/loader.ts
Normal file
43
src/core/loader.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import * as fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { Collection } from "discord.js";
|
||||
|
||||
export const commands = new Collection<string, any>();
|
||||
|
||||
export function loadCommands(dir: string = path.join(__dirname, '..', 'commands')) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(dir, file);
|
||||
const stat = fs.statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
loadCommands(fullPath); // recursivo
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.endsWith('.ts')) continue;
|
||||
|
||||
const imported = require(fullPath);
|
||||
const command = imported.command ?? imported.default ?? imported;
|
||||
|
||||
if (!command?.data?.name && !command?.name) {
|
||||
console.warn(`⚠️ Archivo ignorado: ${file} (no es un comando válido)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = command.data?.name ?? command.name;
|
||||
console.log(`📦 Loading command: ${name}`);
|
||||
|
||||
// @ts-ignore
|
||||
commands.set(name, command);
|
||||
|
||||
if (command.aliases?.length) {
|
||||
for (const alias of command.aliases) {
|
||||
commands.set(alias, command);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ Cargado comando: ${name}`);
|
||||
}
|
||||
}
|
||||
32
src/core/loaderEvents.ts
Normal file
32
src/core/loaderEvents.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { bot } from "../main";
|
||||
import path from "node:path";
|
||||
import * as fs from "node:fs";
|
||||
|
||||
export function loadEvents(dir: string = path.join(__dirname, "../events")) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(dir, file);
|
||||
const stat = fs.statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
loadEvents(fullPath); // recursión para subcarpetas
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.endsWith(".ts") && !file.endsWith(".js")) continue;
|
||||
|
||||
const imported = require(fullPath);
|
||||
const event = imported.default ?? imported;
|
||||
|
||||
if (!event?.name || !event?.execute) continue;
|
||||
|
||||
if (event.once) {
|
||||
bot.once(event.name, (...args: any[]) => event.execute(...args));
|
||||
} else {
|
||||
bot.on(event.name, (...args: any[]) => event.execute(...args));
|
||||
}
|
||||
|
||||
console.log(`Evento cargado: ${event.name}`);
|
||||
}
|
||||
}
|
||||
13
src/core/redis.ts
Normal file
13
src/core/redis.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createClient } from "redis";
|
||||
|
||||
export const redis = createClient({
|
||||
url: process.env.REDIS_URL,
|
||||
})
|
||||
|
||||
redis.on("error", (err: any) => console.error("Redis error:", err));
|
||||
redis.on("connect", () => console.log("✅ Conectado a Redis"));
|
||||
redis.on("reconnecting", () => console.warn("♻️ Reintentando conexión Redis"));
|
||||
|
||||
export async function redisConnect () {
|
||||
if (!redis.isOpen) await redis.connect();
|
||||
}
|
||||
19
src/core/types/commands.ts
Normal file
19
src/core/types/commands.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type {ChatInputCommandInteraction, Client, Message} from "discord.js";
|
||||
import Amayo from "../client";
|
||||
|
||||
export interface CommandMessage {
|
||||
name: string;
|
||||
type: 'message';
|
||||
aliases?: string[];
|
||||
cooldown?: number;
|
||||
run: (message: Message, args: string[], client: Amayo) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface CommandSlash {
|
||||
name: string;
|
||||
description: string;
|
||||
type: 'slash';
|
||||
options?: string[];
|
||||
cooldown?: number;
|
||||
run: (i: ChatInputCommandInteraction, client: Client) => Promise<void>;
|
||||
}
|
||||
7
src/core/types/components.ts
Normal file
7
src/core/types/components.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type {ButtonInteraction} from "discord.js";
|
||||
|
||||
|
||||
export interface button {
|
||||
customId: string;
|
||||
run: (interaction: ButtonInteraction) => Promise<void>;
|
||||
}
|
||||
53
src/events/interactionCreate.ts
Normal file
53
src/events/interactionCreate.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { bot } from "../main";
|
||||
import type { BaseInteraction } from "discord.js";
|
||||
import { Events } from "discord.js";
|
||||
import { redis } from "../core/redis";
|
||||
import { commands } from "../core/loader";
|
||||
import { buttons, modals, selectmenus } from "../core/components";
|
||||
|
||||
bot.on(Events.InteractionCreate, async (interaction: BaseInteraction) => {
|
||||
try {
|
||||
// 🔹 Slash commands
|
||||
if (interaction.isChatInputCommand()) {
|
||||
const cmd = commands.get(interaction.commandName);
|
||||
if (!cmd) return;
|
||||
|
||||
const cooldown = Math.floor(Number(cmd.cooldown) || 0);
|
||||
|
||||
if (cooldown > 0) {
|
||||
const key = `cooldown:${cmd.name}:${interaction.user.id}`;
|
||||
const ttl = await redis.ttl(key);
|
||||
if (ttl > 0) {
|
||||
return interaction.reply(`⏳ Espera ${ttl}s antes de volver a usar **${cmd.name}**.`);
|
||||
}
|
||||
await redis.set(key, "1", { EX: cooldown });
|
||||
}
|
||||
|
||||
await cmd.run(interaction, bot);
|
||||
}
|
||||
|
||||
// 🔹 Botones
|
||||
if (interaction.isButton()) {
|
||||
//@ts-ignore
|
||||
const btn = buttons.get(interaction.customId);
|
||||
if (btn) await btn.run(interaction, bot);
|
||||
}
|
||||
|
||||
// 🔹 Select menus
|
||||
if (interaction.isStringSelectMenu()) {
|
||||
const menu = selectmenus.get(interaction.customId);
|
||||
if (menu) await menu.run(interaction, bot);
|
||||
}
|
||||
|
||||
// 🔹 Modales
|
||||
if (interaction.isModalSubmit()) {
|
||||
const modal = modals.get(interaction.customId);
|
||||
if (modal) await modal.run(interaction, bot);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (interaction.isRepliable()) {
|
||||
await interaction.reply({ content: "❌ Hubo un error ejecutando la interacción.", ephemeral: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
40
src/events/messageCreate.ts
Normal file
40
src/events/messageCreate.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import {bot} from "../main";
|
||||
import {Events} from "discord.js";
|
||||
import {redis} from "../core/redis";
|
||||
import {commands} from "../core/loader";
|
||||
|
||||
|
||||
bot.on(Events.MessageCreate, async (message) => {
|
||||
if (message.author.bot) return;
|
||||
const server = await bot.prisma.guild.findFirst({ where: { id: message.guild!.id } }) || "!";
|
||||
const PREFIX = server.prefix
|
||||
if (!message.content.startsWith(PREFIX)) return;
|
||||
|
||||
const [cmdName, ...args] = message.content.slice(PREFIX.length).trim().split(/\s+/);
|
||||
console.log(cmdName);
|
||||
const command = commands.get(cmdName);
|
||||
if (!command) return;
|
||||
|
||||
const cooldown = Math.floor(Number(command.cooldown) || 0);
|
||||
|
||||
if (cooldown > 0) {
|
||||
const key = `cooldown:${command.name}:${message.author.id}`;
|
||||
const ttl = await redis.ttl(key);
|
||||
console.log(`Key: ${key}, TTL: ${ttl}`);
|
||||
|
||||
if (ttl > 0) {
|
||||
return message.reply(`⏳ Espera ${ttl}s antes de volver a usar **${command.name}**.`);
|
||||
}
|
||||
|
||||
// SET con expiración correcta para redis v4+
|
||||
await redis.set(key, "1", { EX: cooldown });
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
await command.run(message, args, message.client);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
await message.reply("❌ Hubo un error ejecutando el comando.");
|
||||
}
|
||||
})
|
||||
6
src/events/ready.ts
Normal file
6
src/events/ready.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import {bot} from "../main";
|
||||
import {Events} from "discord.js";
|
||||
|
||||
bot.on(Events.ClientReady, () => {
|
||||
console.log("Ready!");
|
||||
})
|
||||
28
src/main.ts
Normal file
28
src/main.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import Amayo from "./core/client";
|
||||
import { loadCommands } from "./core/loader";
|
||||
import { loadEvents } from "./core/loaderEvents";
|
||||
import { redisConnect } from "./core/redis";
|
||||
import { registeringCommands } from "./core/api/discordAPI";
|
||||
import {loadComponents} from "./core/components";
|
||||
|
||||
export const bot = new Amayo();
|
||||
|
||||
async function bootstrap() {
|
||||
console.log("🚀 Iniciando bot...");
|
||||
|
||||
loadCommands(); // 1️⃣ Cargar comandos en la Collection
|
||||
loadComponents()
|
||||
loadEvents(); // 2️⃣ Cargar eventos
|
||||
|
||||
await registeringCommands(); // 3️⃣ Registrar los slash en Discord
|
||||
|
||||
await redisConnect(); // 4️⃣ Conectar Redis
|
||||
|
||||
await bot.play();
|
||||
console.log("✅ Bot conectado a Discord");
|
||||
}
|
||||
|
||||
bootstrap().catch((err) => {
|
||||
console.error("❌ Error en el arranque:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
13
tsconfig.json
Normal file
13
tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "nodenext",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Reference in New Issue
Block a user