chore: merge branch dev to main (#195)
All checks were successful
Publish latest version / build (push) Successful in 1m45s

Close #188

Also better support of assets

Reviewed-on: #195
Co-authored-by: Mylloon <kennel.anri@tutanota.com>
Co-committed-by: Mylloon <kennel.anri@tutanota.com>
This commit is contained in:
Mylloon 2024-10-14 23:41:43 +02:00 committed by Mylloon
parent 74fdfb7626
commit 82e2f5a209
Signed by: Forgejo
GPG key ID: E72245C752A07631
22 changed files with 350 additions and 133 deletions

View file

@ -1,14 +1,12 @@
# 🌱 Botanique [![status-badge](https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/badges/workflows/publish.yml/badge.svg)](https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/actions?workflow=publish.yml) # 🌱 Botanique [![status-badge](https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/badges/workflows/publish.yml/badge.svg)](https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/actions?workflow=publish.yml)
[**Ajoute le bot à ton serveur**](https://discord.com/api/oauth2/authorize?client_id=965598852407230494&permissions=8&scope=bot%20applications.commands) [**Ajoute le bot à un serveur**](https://discord.com/api/oauth2/authorize?client_id=965598852407230494&permissions=8&scope=bot%20applications.commands)
## Lancer le bot ## Lancer le bot
### Avec docker-compose (recommandé) ### Avec docker-compose (recommandé)
```yaml ```yaml
version: "3.9"
services: services:
botanique: botanique:
image: git.mylloon.fr/confreriedukassoulait/botanique:latest image: git.mylloon.fr/confreriedukassoulait/botanique:latest

148
package-lock.json generated
View file

@ -15,17 +15,17 @@
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"discord-player": "^6.7.1", "discord-player": "^6.7.1",
"discord-player-youtubei": "^1.3.2", "discord-player-youtubei": "^1.3.2",
"discord.js": "^14.16.2", "discord.js": "^14.16.3",
"mediaplex": "^0.0.9", "mediaplex": "^0.0.9",
"moment-timezone": "^0.5.45", "moment-timezone": "^0.5.46",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",
"typescript": "^5.6.2", "typescript": "^5.6.3",
"uuid": "^10.0.0" "uuid": "^10.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "~29.5.13", "@types/jest": "~29.5.13",
"@typescript-eslint/eslint-plugin": "~8.6.0", "@typescript-eslint/eslint-plugin": "~8.8.1",
"@typescript-eslint/parser": "~8.6.0", "@typescript-eslint/parser": "~8.8.1",
"dotenv": "~16.4.5", "dotenv": "~16.4.5",
"jest": "~29.7.0", "jest": "~29.7.0",
"prettier-eslint": "~16.3.0", "prettier-eslint": "~16.3.0",
@ -62,9 +62,9 @@
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.25.7", "version": "7.25.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz",
"integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -72,9 +72,9 @@
} }
}, },
"node_modules/@babel/core": { "node_modules/@babel/core": {
"version": "7.25.7", "version": "7.25.8",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz",
"integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -84,10 +84,10 @@
"@babel/helper-compilation-targets": "^7.25.7", "@babel/helper-compilation-targets": "^7.25.7",
"@babel/helper-module-transforms": "^7.25.7", "@babel/helper-module-transforms": "^7.25.7",
"@babel/helpers": "^7.25.7", "@babel/helpers": "^7.25.7",
"@babel/parser": "^7.25.7", "@babel/parser": "^7.25.8",
"@babel/template": "^7.25.7", "@babel/template": "^7.25.7",
"@babel/traverse": "^7.25.7", "@babel/traverse": "^7.25.7",
"@babel/types": "^7.25.7", "@babel/types": "^7.25.8",
"convert-source-map": "^2.0.0", "convert-source-map": "^2.0.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"gensync": "^1.0.0-beta.2", "gensync": "^1.0.0-beta.2",
@ -351,13 +351,13 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.25.7", "version": "7.25.8",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz",
"integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.25.7" "@babel/types": "^7.25.8"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@ -650,9 +650,9 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.25.7", "version": "7.25.8",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz",
"integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -672,9 +672,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@bufbuild/protobuf": { "node_modules/@bufbuild/protobuf": {
"version": "2.1.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.0.tgz",
"integrity": "sha512-+2Mx67Y3skJ4NCD/qNSdBJNWtu6x6Qr53jeNg+QcwiL6mt0wK+3jwHH2x1p7xaYH6Ve2JKOVn0OxU35WsmqI9A==", "integrity": "sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ==",
"license": "(Apache-2.0 AND BSD-3-Clause)" "license": "(Apache-2.0 AND BSD-3-Clause)"
}, },
"node_modules/@cspotcode/source-map-support": { "node_modules/@cspotcode/source-map-support": {
@ -1829,17 +1829,17 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz",
"integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", "integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.6.0", "@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/type-utils": "8.6.0", "@typescript-eslint/type-utils": "8.8.1",
"@typescript-eslint/utils": "8.6.0", "@typescript-eslint/utils": "8.8.1",
"@typescript-eslint/visitor-keys": "8.6.0", "@typescript-eslint/visitor-keys": "8.8.1",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@ -1863,16 +1863,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz",
"integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", "integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==",
"dev": true, "dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.6.0", "@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/types": "8.6.0", "@typescript-eslint/types": "8.8.1",
"@typescript-eslint/typescript-estree": "8.6.0", "@typescript-eslint/typescript-estree": "8.8.1",
"@typescript-eslint/visitor-keys": "8.6.0", "@typescript-eslint/visitor-keys": "8.8.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -1892,14 +1892,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz",
"integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.6.0", "@typescript-eslint/types": "8.8.1",
"@typescript-eslint/visitor-keys": "8.6.0" "@typescript-eslint/visitor-keys": "8.8.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -1910,14 +1910,14 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz",
"integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", "integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.6.0", "@typescript-eslint/typescript-estree": "8.8.1",
"@typescript-eslint/utils": "8.6.0", "@typescript-eslint/utils": "8.8.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^1.3.0" "ts-api-utils": "^1.3.0"
}, },
@ -1935,9 +1935,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz",
"integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -1949,14 +1949,14 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz",
"integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==",
"dev": true, "dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.6.0", "@typescript-eslint/types": "8.8.1",
"@typescript-eslint/visitor-keys": "8.6.0", "@typescript-eslint/visitor-keys": "8.8.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -1978,16 +1978,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz",
"integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.6.0", "@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/types": "8.6.0", "@typescript-eslint/types": "8.8.1",
"@typescript-eslint/typescript-estree": "8.6.0" "@typescript-eslint/typescript-estree": "8.8.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2001,13 +2001,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.6.0", "version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz",
"integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.6.0", "@typescript-eslint/types": "8.8.1",
"eslint-visitor-keys": "^3.4.3" "eslint-visitor-keys": "^3.4.3"
}, },
"engines": { "engines": {
@ -2625,9 +2625,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001667", "version": "1.0.30001668",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz",
"integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -3273,9 +3273,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.33", "version": "1.5.36",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.36.tgz",
"integrity": "sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA==", "integrity": "sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@ -7952,9 +7952,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.6.2", "version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",

View file

@ -4,12 +4,13 @@
"description": "Bot discord", "description": "Bot discord",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {
"main": "rm -r dist 2> /dev/null; npx tsc && node ./dist/index.js", "compile": "rm -r dist 2> /dev/null; npx tsc",
"main": "npm run compile && node ./dist/index.js",
"debug": "npx tsnd --respawn ./src/index.ts", "debug": "npx tsnd --respawn ./src/index.ts",
"lint": "npx eslint src", "lint": "npx eslint src",
"format-check": "npx prettier --check src", "format-check": "npx prettier --check src",
"format-write": "npx prettier --write src", "format-write": "npx prettier --write src",
"test": "npx jest" "test": "npm run compile && npx jest"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -24,17 +25,17 @@
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"discord-player": "^6.7.1", "discord-player": "^6.7.1",
"discord-player-youtubei": "^1.3.2", "discord-player-youtubei": "^1.3.2",
"discord.js": "^14.16.2", "discord.js": "^14.16.3",
"mediaplex": "^0.0.9", "mediaplex": "^0.0.9",
"moment-timezone": "^0.5.45", "moment-timezone": "^0.5.46",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",
"typescript": "^5.6.2", "typescript": "^5.6.3",
"uuid": "^10.0.0" "uuid": "^10.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "~29.5.13", "@types/jest": "~29.5.13",
"@typescript-eslint/eslint-plugin": "~8.6.0", "@typescript-eslint/eslint-plugin": "~8.8.1",
"@typescript-eslint/parser": "~8.6.0", "@typescript-eslint/parser": "~8.8.1",
"dotenv": "~16.4.5", "dotenv": "~16.4.5",
"jest": "~29.7.0", "jest": "~29.7.0",
"prettier-eslint": "~16.3.0", "prettier-eslint": "~16.3.0",

View file

@ -8,7 +8,7 @@ import {
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { getLocale } from "../../utils/locales"; import { getLocale } from "../../utils/locales";
import { getFilename } from "../../utils/misc"; import { getFilename } from "../../utils/misc";
import { embedListReminders } from "../../utils/reminder"; import { embedListReminders } from "../../utils/commands/reminder";
import { collect } from "../loader"; import { collect } from "../loader";
export default { export default {

View file

@ -8,7 +8,7 @@ import {
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { getLocale } from "../../utils/locales"; import { getLocale } from "../../utils/locales";
import { getFilename } from "../../utils/misc"; import { getFilename } from "../../utils/misc";
import { embedListReminders } from "../../utils/reminder"; import { embedListReminders } from "../../utils/commands/reminder";
import { collect } from "../loader"; import { collect } from "../loader";
export default { export default {

View file

@ -10,8 +10,8 @@ import {
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { getLocale } from "../../utils/locales"; import { getLocale } from "../../utils/locales";
import { getFilename } from "../../utils/misc"; import { getFilename } from "../../utils/misc";
import { embedListQueue } from "../../utils/music";
import { collect } from "../loader"; import { collect } from "../loader";
import { embedListQueue } from "../../utils/commands/music";
export default { export default {
data: { data: {

View file

@ -10,8 +10,8 @@ import {
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { getLocale } from "../../utils/locales"; import { getLocale } from "../../utils/locales";
import { getFilename } from "../../utils/misc"; import { getFilename } from "../../utils/misc";
import { embedListQueue } from "../../utils/music";
import { collect } from "../loader"; import { collect } from "../loader";
import { embedListQueue } from "../../utils/commands/music";
export default { export default {
data: { data: {

View file

@ -19,7 +19,7 @@ import {
embedListReminders, embedListReminders,
getReminderInfo, getReminderInfo,
newReminder, newReminder,
} from "../../utils/reminder"; } from "../../utils/commands/reminder";
export default { export default {
scope: () => [], scope: () => [],

View file

@ -12,7 +12,7 @@ import { v4 as uuidv4 } from "uuid";
import { collect } from "../../buttons/loader"; import { collect } from "../../buttons/loader";
import { getLocale, getLocalizations } from "../../utils/locales"; import { getLocale, getLocalizations } from "../../utils/locales";
import { getFilename } from "../../utils/misc"; import { getFilename } from "../../utils/misc";
import { embedListQueue } from "../../utils/music"; import { embedListQueue } from "../../utils/commands/music";
export default { export default {
scope: () => [], scope: () => [],

View file

@ -8,7 +8,7 @@ import {
sendReminder, sendReminder,
setTimeoutReminder, setTimeoutReminder,
updateReminder, updateReminder,
} from "../../utils/reminder"; } from "../../utils/commands/reminder";
export const once = true; export const once = true;
@ -41,14 +41,18 @@ export default async (client: Client) => {
} as infoReminder; } as infoReminder;
if (element.expiration_date <= now) { if (element.expiration_date <= now) {
// Reminder expired sendReminder(client, info, element.option_id as OptionReminder)
deleteReminder(client, element.creation_date, `${element.user_id}`).then((res) => { .then(() =>
if (res != true) { // Reminder expired
throw res; deleteReminder(client, element.creation_date, `${element.user_id}`).then((res) => {
} if (res != true) {
}); throw res;
}
sendReminder(client, info, element.option_id as OptionReminder); }),
)
.catch((err) => {
throw err;
});
} else { } else {
// Restart timeout // Restart timeout
const timeoutId = setTimeoutReminder( const timeoutId = setTimeoutReminder(

View file

@ -1,8 +1,9 @@
import { Client, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; import { Client, EmbedBuilder, Message, TextBasedChannel } from "discord.js";
import { getLocale } from "../../utils/locales"; import { getLocale } from "../../utils/locales";
import { isImage, userWithNickname } from "../../utils/misc"; import { userWithNickname } from "../../utils/misc";
import { showDate } from "../../utils/time"; import { showDate } from "../../utils/time";
import { RegexC, RegExpFlags } from "../../utils/regex"; import { RegexC, RegExpFlags } from "../../utils/regex";
import { handleAttachments } from "../../utils/events/citation";
/** https://discord.js.org/#/docs/discord.js/main/class/Client?scrollTo=e-messageCreate */ /** https://discord.js.org/#/docs/discord.js/main/class/Client?scrollTo=e-messageCreate */
export default async (message: Message, client: Client) => { export default async (message: Message, client: Client) => {
@ -96,7 +97,7 @@ export default async (message: Message, client: Client) => {
// Remove undefined elements // Remove undefined elements
.filter(Boolean); .filter(Boolean);
const loc = getLocale(client, client.config.default_lang); const loc = getLocale(client);
// Remove duplicates then map the quoted posts // Remove duplicates then map the quoted posts
[...new Set(messages)] [...new Set(messages)]
@ -109,24 +110,7 @@ export default async (message: Message, client: Client) => {
// Handle attachments // Handle attachments
if (quoted_post.attachments.size !== 0) { if (quoted_post.attachments.size !== 0) {
if (quoted_post.attachments.size === 1 && isImage(quoted_post.attachments.first()!.name)) { handleAttachments(loc, embed, quoted_post.attachments);
// Only contains one image
embed.setImage(quoted_post.attachments.first()!.url);
} else {
// Contains more than one image and/or other files
let files = "";
quoted_post.attachments.forEach((file) => (files += `[${file.name}](${file.url}), `));
embed.addFields({
// TODO: Don't pluralize when there is only one file.
// TODO: Locales
// https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/issues/188
name: "Fichiers joints",
// TODO: Check if don't exceed char limit, if yes, split
// files into multiples field.
value: `${files.slice(0, -2)}.`,
});
}
} }
// Description as post content // Description as post content

View file

@ -173,5 +173,8 @@
"c_repeat6": "enabled", "c_repeat6": "enabled",
"e_trackstart1": "Asked by", "e_trackstart1": "Asked by",
"e_trackstart2": "Duration :" "e_trackstart2": "Duration :",
"e_attachement": "Attachement",
"e_attachements": "Attachements"
} }

View file

@ -173,5 +173,8 @@
"c_repeat6": "activé", "c_repeat6": "activé",
"e_trackstart1": "Demandé par", "e_trackstart1": "Demandé par",
"e_trackstart2": "Durée :" "e_trackstart2": "Durée :",
"e_attachement": "Fichier joint",
"e_attachements": "Fichiers joint"
} }

View file

@ -1,6 +1,6 @@
import { Client, ModalSubmitInteraction } from "discord.js"; import { Client, ModalSubmitInteraction } from "discord.js";
import { getFilename } from "../../utils/misc"; import { getFilename } from "../../utils/misc";
import { newReminder } from "../../utils/reminder"; import { newReminder } from "../../utils/commands/reminder";
export default { export default {
data: { data: {

View file

@ -1,4 +1,4 @@
import { OptionReminder, splitTime } from "../../utils/reminder"; import { OptionReminder, splitTime } from "../../../utils/commands/reminder";
describe("Time splitter", () => { describe("Time splitter", () => {
{ {

View file

@ -0,0 +1,149 @@
import { Attachment, Collection, EmbedBuilder } from "discord.js";
import { handleAttachments } from "../../../utils/events/citation";
/**
* Generate a new random string
* @returns random string
*/
const newKey = () => Math.random().toString(36).substring(2);
describe("Attachements Handler", () => {
const map = new Map([
["e_attachements", "yes_s"],
["e_attachement", "no_s"],
]);
// 102 is the maximum for [f](url) before rupture in a field
const max = 102;
const max_field = Array.from({ length: max }, () => "[f](url)").join(", ");
{
const name = "One image";
test(name, () => {
const embedExpected = new EmbedBuilder();
embedExpected.setImage("http://url");
const embedTest = new EmbedBuilder();
handleAttachments(
map,
embedTest,
new Collection([[newKey(), { name: "image.png", url: "http://url" } as Attachment]]),
);
expect(embedTest).toStrictEqual(embedExpected);
});
}
{
const name = "Two images";
test(name, () => {
const embedExpected = new EmbedBuilder();
embedExpected.addFields({
name: "yes_s",
value: "[image.png](http://url), [image.png](http://url)",
});
const embedTest = new EmbedBuilder();
handleAttachments(
map,
embedTest,
new Collection([
[newKey(), { name: "image.png", url: "http://url" } as Attachment],
[newKey(), { name: "image.png", url: "http://url" } as Attachment],
]),
);
expect(embedTest).toStrictEqual(embedExpected);
});
}
{
const name = "One link";
test(name, () => {
const embedExpected = new EmbedBuilder();
embedExpected.addFields({ name: "no_s", value: "[f](url)" });
const embedTest = new EmbedBuilder();
handleAttachments(
map,
embedTest,
new Collection([[newKey(), { name: "f", url: "url" } as Attachment]]),
);
expect(embedTest).toStrictEqual(embedExpected);
});
}
{
const name = "Two files";
test(name, () => {
const embedExpected = new EmbedBuilder();
embedExpected.addFields({ name: "yes_s", value: "[f](url), [f](url)" });
const embedTest = new EmbedBuilder();
handleAttachments(
map,
embedTest,
new Collection([
[newKey(), { name: "f", url: "url" } as Attachment],
[newKey(), { name: "f", url: "url" } as Attachment],
]),
);
expect(embedTest).toStrictEqual(embedExpected);
});
}
{
const name = "Two fields with multiples files each";
test(name, () => {
const total = 150;
const embedExpected = new EmbedBuilder();
embedExpected.addFields(
{
name: "yes_s (1)",
value: max_field,
},
{
name: "yes_s (2)",
value: Array.from({ length: total - max }, () => "[f](url)").join(", "),
},
);
const embedTest = new EmbedBuilder();
handleAttachments(
map,
embedTest,
new Collection(
Array.from({ length: total }, () => [newKey(), { name: "f", url: "url" } as Attachment]),
),
);
expect(embedTest).toStrictEqual(embedExpected);
});
}
{
const name = "Two fields with one field with one element";
test(name, () => {
const total = 103;
const embedExpected = new EmbedBuilder();
embedExpected.addFields(
{
name: "yes_s (1)",
value: max_field,
},
{
name: "no_s (2)",
value: Array.from({ length: total - max }, () => "[f](url)").join(", "),
},
);
const embedTest = new EmbedBuilder();
handleAttachments(
map,
embedTest,
new Collection(
Array.from({ length: total }, () => [newKey(), { name: "f", url: "url" } as Attachment]),
),
);
expect(embedTest).toStrictEqual(embedExpected);
});
}
});

View file

@ -111,4 +111,10 @@ describe("Relative time", () => {
expect(timeDeltaToString(name)).toMatch(/1w 1d 6h|1w 1d 5h 59m 5\ds/); expect(timeDeltaToString(name)).toMatch(/1w 1d 6h|1w 1d 5h 59m 5\ds/);
}); });
} }
{
const name = Date.now();
test(name.toString(), () => {
expect(timeDeltaToString(name)).toMatch(/\ds/);
});
}
}); });

View file

@ -1,8 +1,8 @@
import { EmbedBuilder } from "@discordjs/builders"; import { EmbedBuilder } from "@discordjs/builders";
import { GuildQueue, QueueRepeatMode } from "discord-player"; import { GuildQueue, QueueRepeatMode } from "discord-player";
import { Client } from "discord.js"; import { Client } from "discord.js";
import { getLocale } from "./locales"; import { getLocale } from "../locales";
import { blank } from "./misc"; import { blank } from "../misc";
export const embedListQueue = ( export const embedListQueue = (
client: Client, client: Client,

View file

@ -1,8 +1,8 @@
import { Client, Colors, EmbedBuilder, User } from "discord.js"; import { Client, Colors, EmbedBuilder, User } from "discord.js";
import { getLocale } from "./locales"; import { getLocale } from "../locales";
import { blank, cleanCodeBlock } from "./misc"; import { blank, cleanCodeBlock } from "../misc";
import { showDate, strToSeconds, timeDeltaToString } from "./time"; import { showDate, strToSeconds, timeDeltaToString } from "../time";
import { RegexC, RegExpFlags } from "./regex"; import { RegexC, RegExpFlags } from "../regex";
/** /**
* Option possible for reminders * Option possible for reminders
@ -143,10 +143,18 @@ export const deleteReminder = (client: Client, createdAt: string, userId: string
}); });
}; };
export const sendReminder = (client: Client, info: infoReminder, option: OptionReminder) => { export const sendReminder = (client: Client, info: infoReminder, option: OptionReminder) =>
new Promise((resolve, reject) => {
try {
resolve(sendReminderAux(client, info, option));
} catch (error) {
reject(error);
}
});
const sendReminderAux = (client: Client, info: infoReminder, option: OptionReminder) => {
const loc = getLocale(client, info.locale); const loc = getLocale(client, info.locale);
// Send the message in the appropriate channel // Send the message in the appropriate channel
// TODO: Embed
let message: string; let message: string;
if (info.message === null || info.message.length === 0) { if (info.message === null || info.message.length === 0) {
message = loc.get("c_reminder7"); message = loc.get("c_reminder7");

View file

@ -0,0 +1,57 @@
import { APIEmbedField, Attachment, Collection, EmbedBuilder } from "discord.js";
import { isImage } from "../misc";
export const handleAttachments = (
loc: Map<string, string>,
embed: EmbedBuilder,
attachments: Collection<string, Attachment>,
) => {
if (attachments.size === 1 && isImage(attachments.first()!.name)) {
// Only contains one image
embed.setImage(attachments.first()!.url);
} else {
// Contains more than one image and/or other files
// We are currently losing a link to a file if the link is too long
// We could truncate the filename ?
const maxFieldValueLength = 1024;
const files = attachments
.map((file) => `[${file.name}](${file.url})`)
.filter((link) => link.length <= maxFieldValueLength);
let currentField = "";
const fields: APIEmbedField[] = [];
let multipleFields = 0;
let numberOfLinks = 0;
files.forEach((file, idx) => {
numberOfLinks++;
const fieldValue = currentField.length > 0 ? `${currentField}, ${file}` : file;
if (fieldValue.length > maxFieldValueLength) {
multipleFields = multipleFields === 0 && idx !== files.length - 1 ? 1 : multipleFields + 1;
fields.push({
name:
loc.get(
attachments.size > 1 && numberOfLinks > 1 ? "e_attachements" : "e_attachement",
) + (multipleFields ? ` (${multipleFields})` : ""),
value: currentField,
});
currentField = file;
numberOfLinks = 0;
} else {
currentField = fieldValue;
}
});
if (currentField.length > 0) {
fields.push({
name:
loc.get(attachments.size > 1 && numberOfLinks > 1 ? "e_attachements" : "e_attachement") +
(multipleFields ? ` (${multipleFields + 1})` : ""),
value: currentField,
});
}
embed.addFields(fields);
}
};

View file

@ -81,9 +81,13 @@ export const getLocalizations = (client: Client, text: string, lowercase = false
* @param lang Lang to fetch * @param lang Lang to fetch
* @returns the map with the desired languaged clogged with the default one * @returns the map with the desired languaged clogged with the default one
*/ */
export const getLocale = (client: Client, lang: string) => { export const getLocale = (client: Client, lang: string | undefined = undefined) => {
// Load default lang // Load default lang
const default_locales = client.locales.get(client.config.default_lang); const default_locales = client.locales.get(client.config.default_lang);
if (!lang) {
return default_locales!;
}
// Load desired lang // Load desired lang
const desired_locales = client.locales.get(lang); const desired_locales = client.locales.get(lang);

View file

@ -101,7 +101,7 @@ export const strToSeconds = (time: string) => {
*/ */
export const timeDeltaToString = (time: number) => { export const timeDeltaToString = (time: number) => {
const now = Date.now(); const now = Date.now();
let secondsDifference = Math.abs(Math.ceil((time - now) / 1000) - 2); let secondsDifference = Math.abs(Math.ceil((time - now) / 1000));
if (secondsDifference === 0) { if (secondsDifference === 0) {
return "0s"; return "0s";