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