Compare commits

..

1 commit

Author SHA1 Message Date
f334deacc4
[chore] vscode rule
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
2024-06-10 21:35:28 +02:00
20 changed files with 484 additions and 494 deletions

View file

@ -1,23 +0,0 @@
name: Lint and Format Check
on:
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
- dev
jobs:
lint-and-format:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: npm install
- name: Run lint
run: npm run lint
- name: Run format check
run: npm run format-check

View file

@ -1,36 +1,15 @@
name: Publish latest version
on:
push:
branches: [main]
jobs:
build:
container:
image: ghcr.io/catthehacker/ubuntu:act-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Sanitize metadata
id: meta
uses: docker/metadata-action@v5
with:
tags: latest
images: git.mylloon.fr/${{ github.repository }}
- name: Login to Registry
uses: docker/login-action@v3
with:
registry: ${{ github.server_url }}
username: ${{ github.actor }}
password: ${{ secrets.TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
publish:
image: woodpeckerci/plugin-docker-buildx:2
settings:
labels:
platform: linux/amd64
repo: git.mylloon.fr/${CI_REPO,,}
auto_tag: true
registry: git.mylloon.fr
username: ${CI_REPO_OWNER}
password:
from_secret: cb_token
when:
event: push
branch: main

View file

@ -1,4 +1,4 @@
# 🌱 Botanique ![status-badge](https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/badges/workflows/publish.yml/badge.svg)
# 🌱 Botanique [![status-badge](https://ci.mylloon.fr/api/badges/ConfrerieDuKassoulait/Botanique/status.svg)](https://ci.mylloon.fr/ConfrerieDuKassoulait/Botanique)
[**Ajoute le bot à ton serveur**](https://discord.com/api/oauth2/authorize?client_id=965598852407230494&permissions=8&scope=bot%20applications.commands)

717
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -17,21 +17,21 @@
"author": "La confrérie du Kassoulait",
"license": "AGPL-3.0-only",
"dependencies": {
"@discord-player/extractor": "^4.5.1",
"@discordjs/rest": "^2.4.0",
"@discord-player/extractor": "^4.4.7",
"@discordjs/rest": "^2.3.0",
"@distube/ytdl-core": "^4.13.4",
"@types/sqlite3": "^3.1.11",
"@types/uuid": "^10.0.0",
"discord-player": "^6.7.1",
"discord-player-youtubei": "^1.3.1",
"discord.js": "^14.16.1",
"@types/uuid": "^9.0.8",
"discord-player": "^6.6.10",
"discord.js": "^14.15.3",
"mediaplex": "^0.0.9",
"sqlite3": "^5.1.7",
"typescript": "^5.5.4",
"typescript": "^5.4.5",
"uuid": "^10.0.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "~8.4.0",
"@typescript-eslint/parser": "~8.4.0",
"@typescript-eslint/eslint-plugin": "~7.13.0",
"@typescript-eslint/parser": "~7.13.0",
"dotenv": "~16.4.5",
"prettier-eslint": "~16.3.0",
"ts-node-dev": "~2.0.0"

View file

@ -1,11 +1,6 @@
import { readdir } from "fs/promises";
import { removeExtension } from "../utils/misc";
import {
ChatInputCommandInteraction,
Client,
Message,
MessageComponentInteraction,
} from "discord.js";
import { ChatInputCommandInteraction, Client, MessageComponentInteraction } from "discord.js";
import { getLocale } from "../utils/locales";
export default async (client: Client) => {
@ -42,14 +37,12 @@ export default async (client: Client) => {
* @param client Client
* @param interaction Chat interaction
* @param id Button ID
* @param message Message holding the buttons
* @param deferUpdate defer update in case update take time
*/
export const collect = (
client: Client,
interaction: ChatInputCommandInteraction | MessageComponentInteraction,
id: string,
message: Message,
deferUpdate = false,
) => {
const loc = getLocale(client, interaction.locale);
@ -63,7 +56,7 @@ export const collect = (
}
const filter = (i: MessageComponentInteraction) => i.customId === id;
const collector = message.createMessageComponentCollector({
const collector = interaction.channel?.createMessageComponentCollector({
filter,
max: 1,
});

View file

@ -59,8 +59,8 @@ export default {
);
// Buttons interactions
collect(client, interaction, idPrec, interaction.message);
collect(client, interaction, idNext, interaction.message);
collect(client, interaction, idPrec);
collect(client, interaction, idNext);
return {
embeds: [list],

View file

@ -59,8 +59,8 @@ export default {
);
// Buttons interactions
collect(client, interaction, idPrec, interaction.message);
collect(client, interaction, idNext, interaction.message);
collect(client, interaction, idPrec);
collect(client, interaction, idNext);
return {
embeds: [list],

View file

@ -59,8 +59,8 @@ export default {
);
// Buttons interactions
collect(client, interaction, idPrec, interaction.message);
collect(client, interaction, idNext, interaction.message);
collect(client, interaction, idPrec);
collect(client, interaction, idNext);
} else {
// In case queue doesn't exists
embed.setDescription(loc.get("c_queue2"));

View file

@ -59,8 +59,8 @@ export default {
);
// Buttons interactions
collect(client, interaction, idPrec, interaction.message);
collect(client, interaction, idNext, interaction.message);
collect(client, interaction, idPrec);
collect(client, interaction, idNext);
} else {
// In case queue doesn't exists
embed.setDescription(loc.get("c_queue2"));

View file

@ -230,18 +230,15 @@ export default {
.setStyle(ButtonStyle.Primary),
);
const message = await interaction.reply({
// Buttons interactions
collect(client, interaction, idPrec);
collect(client, interaction, idNext);
return await interaction.reply({
ephemeral: true,
embeds: [list],
components: [row],
fetchReply: true,
});
// Buttons interactions
collect(client, interaction, idPrec, message);
collect(client, interaction, idNext, message);
return;
}
// Delete a reminder
case loc_default?.get(`c_${filename}_sub3_name`)?.toLowerCase() ?? "": {

View file

@ -1,6 +1,6 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { Player, useMainPlayer, useQueue } from "discord-player";
import { ChannelType, ChatInputCommandInteraction, Client, EmbedBuilder } from "discord.js";
import { ChatInputCommandInteraction, Client, EmbedBuilder } from "discord.js";
import { getLocale, getLocalizations } from "../../utils/locales";
import { getFilename } from "../../utils/misc";
@ -56,15 +56,6 @@ export default {
.setDescriptionLocalizations(getLocalizations(client, `c_${filename}_opt1_desc`)),
),
)
// Synced
.addSubcommand((subcommand) =>
subcommand
.setName(loc_default.get(`c_${filename}_sub3_name`)?.toLowerCase() ?? "")
.setDescription(loc_default.get(`c_${filename}_sub3_desc`) ?? "")
.setNameLocalizations(getLocalizations(client, `c_${filename}_sub3_name`, true))
.setDescriptionLocalizations(getLocalizations(client, `c_${filename}_sub3_desc`)),
)
);
},
@ -82,7 +73,6 @@ export default {
await interaction.deferReply();
const player = useMainPlayer() as Player;
const queue = useQueue(interaction.guildId ?? "");
if (request) {
if (
interaction.options.getSubcommand() ==
@ -98,7 +88,9 @@ export default {
} catch {
return await interaction.followUp(`❌ | ${loc.get("c_lyrics2")} \`${request}\``);
}
} else if (queue) {
} else {
const queue = useQueue(interaction.guildId ?? "");
if (queue) {
const track = queue.history.currentTrack;
if (track) {
try {
@ -110,48 +102,9 @@ export default {
}
}
}
if (
interaction.options.getSubcommand() ==
loc_default?.get(`c_${filename}_sub3_name`)?.toLowerCase() ??
""
) {
if (queue === null) {
return await interaction.followUp(`❌ | ${loc.get("c_lyrics1")}`);
}
if (data === null || !data[0] || !data[0].syncedLyrics) {
return await interaction.followUp(
`❌ | ${loc.get("c_lyrics3")} \`${queue.currentTrack?.cleanTitle}\``,
);
}
// Load lyrics
const syncedLyrics = queue.syncedLyrics(data[0]);
syncedLyrics?.onChange(async (lyrics) => {
const content = `[${data[0].trackName}]: ${lyrics}`;
if (interaction.channel?.type === ChannelType.GroupDM) {
await interaction.followUp({
content,
});
} else {
await interaction.channel?.send({
content,
});
}
});
// Live update
syncedLyrics.subscribe();
return await interaction.followUp({
content: `🎤 | ${loc.get("c_lyrics4")}`,
ephemeral: true,
});
}
if (data && data.length > 0 && data[0].plainLyrics !== null) {
if (data && data.length > 0) {
const title = data[0];
const limit_desc = 4096;
const nb_embed = Math.ceil(title.plainLyrics.length / limit_desc);

View file

@ -181,7 +181,6 @@ export default {
delay,
player.search(query, {
requestedBy: interaction.user,
searchEngine: "spotifySearch",
}),
])
.then((res) => {

View file

@ -96,6 +96,7 @@ export default {
const queue = useQueue(interaction.guildId ?? "");
const embed = new EmbedBuilder();
const rows = [];
if (queue) {
const subcommand = interaction.options.getSubcommand();
@ -109,7 +110,6 @@ export default {
embedListQueue(client, embed, queue, page, interaction.locale);
const rows = [];
const idPrec = "queueList-prec_" + uuidv4();
const idNext = "queueList-next_" + uuidv4();
rows.push(
@ -128,17 +128,11 @@ export default {
),
);
const message = await interaction.reply({
embeds: [embed],
components: rows,
fetchReply: true,
});
// Buttons interactions
collect(client, interaction, idPrec, message);
collect(client, interaction, idNext, message);
collect(client, interaction, idPrec);
collect(client, interaction, idNext);
return;
break;
}
// Shuffle Queue
@ -172,6 +166,6 @@ export default {
embed.setDescription(loc.get("c_queue2"));
}
return await interaction.reply({ embeds: [embed] });
return await interaction.reply({ embeds: [embed], components: rows });
},
};

View file

@ -1,11 +1,4 @@
import {
ChannelType,
Client,
EmbedBuilder,
GuildMember,
Message,
TextBasedChannel,
} from "discord.js";
import { Client, EmbedBuilder, GuildMember, Message, TextBasedChannel } from "discord.js";
import { getLocale } from "../../utils/locales";
import { isImage, userWithNickname } from "../../utils/misc";
import { showDate } from "../../utils/time";
@ -171,8 +164,7 @@ export default async (message: Message, client: Client) => {
if (
!message.content.replace(new RegExp(regex, "g"), "").trim() &&
messages.length === urls.length &&
!message.mentions.repliedUser &&
message.channel.type !== ChannelType.GroupDM
!message.mentions.repliedUser
) {
message.delete();
return message.channel.send({ embeds: [embed] });

View file

@ -1,6 +1,6 @@
import { EmbedBuilder } from "@discordjs/builders";
import { GuildQueue, Track } from "discord-player";
import { ChannelType, Client } from "discord.js";
import { Client } from "discord.js";
import { Metadata } from "../../utils/metadata";
import { emojiPng } from "../../utils/misc";
@ -19,8 +19,5 @@ export default (queue: GuildQueue<Metadata>, track: Track, client: Client) => {
} via ${track.source.capitalize()}`,
iconURL: emojiPng("🎶"),
});
if (queue.metadata.channel?.type !== ChannelType.GroupDM) {
queue.metadata?.channel?.send({ embeds: [embed] });
}
};

View file

@ -134,14 +134,10 @@
"c_lyrics_name": "lyrics",
"c_lyrics_desc": "Displays the lyrics of a song",
"c_lyrics_sub3_name": "synced",
"c_lyrics_sub3_desc": "Synchronized lyrics search (updates in live)",
"c_lyrics_opt1_name": "song",
"c_lyrics_opt1_desc": "Wanted song",
"c_lyrics1": "The bot is not playing anything at the moment and no songs are specified.",
"c_lyrics2": "Unable to find the lyrics for",
"c_lyrics3": "Impossible to find synchronized lyrics for",
"c_lyrics4": "It's karaoke time!",
"c_repeat_name": "repeat",
"c_repeat_desc": "Command for the type of music repetition",

View file

@ -141,14 +141,10 @@
"c_lyrics_sub1_desc": "Recherche de paroles",
"c_lyrics_sub2_name": "romanized",
"c_lyrics_sub2_desc": "Recherche de paroles romanisée (ex: hangul -> latin)",
"c_lyrics_sub3_name": "synced",
"c_lyrics_sub3_desc": "Recherche de paroles synchronisée (se met à jour avec la chanson en direct)",
"c_lyrics_opt1_name": "chanson",
"c_lyrics_opt1_desc": "Chanson recherchée",
"c_lyrics1": "Le bot ne joue rien en ce moment et aucune chanson n'est renseignée.",
"c_lyrics2": "Impossible de trouver les paroles pour",
"c_lyrics3": "Impossible de trouver les paroles synchronisées pour",
"c_lyrics4": "C'est parti !",
"c_repeat_name": "repeat",
"c_repeat_desc": "Commande relative à la répétition des musiques",

View file

@ -4,7 +4,6 @@ import { readFileSync } from "fs";
import { Database } from "sqlite3";
import "../modules/client";
import { loadLocales } from "./locales";
import { YoutubeiExtractor } from "discord-player-youtubei";
/** Creation of the client and definition of its properties. */
export default async () => {
@ -45,8 +44,7 @@ export default async () => {
quality: "highestaudio",
},
});
await player.extractors.loadDefault((ext) => ext !== "YouTubeExtractor");
await player.extractors.register(YoutubeiExtractor, {});
await player.extractors.loadDefault();
console.log("Translations progression :");
client.locales = await loadLocales(client.config.default_lang);

View file

@ -1,4 +1,4 @@
import { ChannelType, Client, Colors, EmbedBuilder, User } from "discord.js";
import { Client, Colors, EmbedBuilder, User } from "discord.js";
import { getLocale } from "./locales";
import { cleanCodeBlock } from "./misc";
import { showDate, strToSeconds, timeDeltaToString } from "./time";
@ -169,7 +169,7 @@ export const sendReminder = (client: Client, info: infoReminder, option: OptionR
} else {
// Channel
client.channels.fetch(info.channelId ?? "").then((channel) => {
if (channel?.isTextBased() && channel.type !== ChannelType.GroupDM) {
if (channel?.isTextBased()) {
let content = `<@${info.userId}>`;
embed.setFooter({
text: `${loc.get("c_reminder17")} ${timeDeltaToString(info.createdAt)}`,