chore: merge branch dev to main #195

Merged
Anri merged 18 commits from dev into main 2024-10-14 23:41:43 +02:00
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)
[**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
### Avec docker-compose (recommandé)
```yaml
version: "3.9"
services:
botanique:
image: git.mylloon.fr/confreriedukassoulait/botanique:latest

148
package-lock.json generated
View file

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

View file

@ -4,12 +4,13 @@
"description": "Bot discord",
"main": "src/index.js",
"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",
"lint": "npx eslint src",
"format-check": "npx prettier --check src",
"format-write": "npx prettier --write src",
"test": "npx jest"
"test": "npm run compile && npx jest"
},
"repository": {
"type": "git",
@ -24,17 +25,17 @@
"@types/uuid": "^10.0.0",
"discord-player": "^6.7.1",
"discord-player-youtubei": "^1.3.2",
"discord.js": "^14.16.2",
"discord.js": "^14.16.3",
"mediaplex": "^0.0.9",
"moment-timezone": "^0.5.45",
"moment-timezone": "^0.5.46",
"sqlite3": "^5.1.7",
"typescript": "^5.6.2",
"typescript": "^5.6.3",
"uuid": "^10.0.0"
},
"devDependencies": {
"@types/jest": "~29.5.13",
"@typescript-eslint/eslint-plugin": "~8.6.0",
"@typescript-eslint/parser": "~8.6.0",
"@typescript-eslint/eslint-plugin": "~8.8.1",
"@typescript-eslint/parser": "~8.8.1",
"dotenv": "~16.4.5",
"jest": "~29.7.0",
"prettier-eslint": "~16.3.0",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,8 +1,9 @@
import { Client, EmbedBuilder, Message, TextBasedChannel } from "discord.js";
import { getLocale } from "../../utils/locales";
import { isImage, userWithNickname } from "../../utils/misc";
import { userWithNickname } from "../../utils/misc";
import { showDate } from "../../utils/time";
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 */
export default async (message: Message, client: Client) => {
@ -96,7 +97,7 @@ export default async (message: Message, client: Client) => {
// Remove undefined elements
.filter(Boolean);
const loc = getLocale(client, client.config.default_lang);
const loc = getLocale(client);
// Remove duplicates then map the quoted posts
[...new Set(messages)]
@ -109,24 +110,7 @@ export default async (message: Message, client: Client) => {
// Handle attachments
if (quoted_post.attachments.size !== 0) {
if (quoted_post.attachments.size === 1 && isImage(quoted_post.attachments.first()!.name)) {
// 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)}.`,
});
}
handleAttachments(loc, embed, quoted_post.attachments);
}
// Description as post content

View file

@ -173,5 +173,8 @@
"c_repeat6": "enabled",
"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é",
"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 { getFilename } from "../../utils/misc";
import { newReminder } from "../../utils/reminder";
import { newReminder } from "../../utils/commands/reminder";
export default {
data: {

View file

@ -1,4 +1,4 @@
import { OptionReminder, splitTime } from "../../utils/reminder";
import { OptionReminder, splitTime } from "../../../utils/commands/reminder";
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/);
});
}
{
const name = Date.now();
test(name.toString(), () => {
expect(timeDeltaToString(name)).toMatch(/\ds/);
});
}
});

View file

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

View file

@ -1,8 +1,8 @@
import { Client, Colors, EmbedBuilder, User } from "discord.js";
import { getLocale } from "./locales";
import { blank, cleanCodeBlock } from "./misc";
import { showDate, strToSeconds, timeDeltaToString } from "./time";
import { RegexC, RegExpFlags } from "./regex";
import { getLocale } from "../locales";
import { blank, cleanCodeBlock } from "../misc";
import { showDate, strToSeconds, timeDeltaToString } from "../time";
import { RegexC, RegExpFlags } from "../regex";
/**
* 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);
// Send the message in the appropriate channel
// TODO: Embed
let message: string;
if (info.message === null || info.message.length === 0) {
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
* @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
const default_locales = client.locales.get(client.config.default_lang);
if (!lang) {
return default_locales!;
}
// Load desired lang
const desired_locales = client.locales.get(lang);

View file

@ -101,7 +101,7 @@ export const strToSeconds = (time: string) => {
*/
export const timeDeltaToString = (time: number) => {
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) {
return "0s";