Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ace8170323 | ||
|
|
1374bcc25d | ||
|
|
757d6e3501 | ||
|
|
b023f7134d | ||
|
|
9f191e6e80 | ||
|
|
7ca5041725 | ||
|
|
a045be3f2f | ||
|
|
c569661481 | ||
|
|
e8cd52d315 | ||
|
|
d4d2930f58 | ||
|
|
0f6ad29a3c | ||
|
|
e4397c3f54 |
No files matched your search
@@ -48,19 +48,19 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
|
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
- name: Extract metadata (tags, labels) for Docker
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||||
with:
|
with:
|
||||||
images: unknowableshade/quetza-bot
|
images: unknowableshade/quetza-bot
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
"printWidth": 100,
|
"printWidth": 100,
|
||||||
"arrowParens": "always",
|
"arrowParens": "always",
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"endOfLine": "crlf",
|
"endOfLine": "lf",
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": ["**/*.json, **/*.yml"],
|
"files": ["**/*.json, **/*.yml"],
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
FROM node:18-alpine as builder
|
FROM node:18-alpine as builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache python3
|
||||||
|
RUN apk add --no-cache make
|
||||||
|
RUN apk add --no-cache gcc
|
||||||
|
RUN apk add --no-cache build-base
|
||||||
|
|
||||||
RUN npm install -g pnpm
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
@@ -19,6 +24,9 @@ RUN apk add --no-cache bash
|
|||||||
RUN apk add --no-cache curl
|
RUN apk add --no-cache curl
|
||||||
RUN apk add --no-cache ffmpeg
|
RUN apk add --no-cache ffmpeg
|
||||||
RUN apk add --no-cache python3
|
RUN apk add --no-cache python3
|
||||||
|
RUN apk add --no-cache make
|
||||||
|
RUN apk add --no-cache gcc
|
||||||
|
RUN apk add --no-cache build-base
|
||||||
|
|
||||||
RUN npm install -g pnpm
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
|||||||
+35
-28
@@ -1,54 +1,61 @@
|
|||||||
{
|
{
|
||||||
"name": "quetza-bot",
|
"name": "quetza-bot",
|
||||||
"engines": {
|
"version": "4.2.2",
|
||||||
"node": "18.x.x",
|
"description": "Discord multipurpose bot",
|
||||||
"npm": "*"
|
|
||||||
},
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "4.0.0",
|
"main": "./dist/index.js",
|
||||||
"description": "Discord multifunctional bot",
|
"scripts": {
|
||||||
|
"start": "node ./dist/index.js",
|
||||||
|
"build": "pnpm exec tsc --build",
|
||||||
|
"clean": "rm -rf ./dist && pnpm run build",
|
||||||
|
"lint": "pnpm exec eslint . && pnpm exec prettier --check .",
|
||||||
|
"format": "pnpm exec eslint --fix . && pnpm exec prettier --write .",
|
||||||
|
"preinstall": "pnpm dlx only-allow pnpm"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"discord",
|
||||||
|
"bot",
|
||||||
|
"music"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/unknowableshade/quetza-bot.git"
|
||||||
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"name": "unknowableshade",
|
"name": "unknowableshade",
|
||||||
"email": "60275123+unknowableshade@users.noreply.github.com",
|
"email": "60275123+unknowableshade@users.noreply.github.com",
|
||||||
"url": "https://unknowableshade.ru"
|
"url": "https://unknowableshade.ru"
|
||||||
},
|
},
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/unknowableshade/quetza-bot.git"
|
|
||||||
},
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/unknowableshade/quetza-bot/issues"
|
"url": "https://github.com/unknowableshade/quetza-bot/issues"
|
||||||
},
|
},
|
||||||
"readme": "https://github.com/unknowableshade/quetza-bot#readme",
|
"readme": "https://github.com/unknowableshade/quetza-bot#readme",
|
||||||
"license": "MIT",
|
"engines": {
|
||||||
"main": "dist/index.js",
|
"node": "18.x.x",
|
||||||
"scripts": {
|
"npm": "*"
|
||||||
"start": "node dist/index.js",
|
|
||||||
"build": "pnpm exec tsc --build",
|
|
||||||
"clean": "pnpm exec tsc --build --clean",
|
|
||||||
"lint": "pnpm exec eslint --fix . && pnpm exec prettier --write .",
|
|
||||||
"preinstall": "pnpx only-allow pnpm"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/opus": "^0.9.0",
|
"@discordjs/opus": "^0.9.0",
|
||||||
"@discordjs/voice": "^0.16.0",
|
"@discordjs/voice": "^0.16.0",
|
||||||
"@prisma/client": "4.13.0",
|
"@prisma/client": "5.0.0",
|
||||||
"discord-ytdl-core": "^5.0.4",
|
|
||||||
"discord.js": "^14.11.0",
|
"discord.js": "^14.11.0",
|
||||||
|
"prism-media": "^1.3.5",
|
||||||
"tweetnacl": "^1.0.3",
|
"tweetnacl": "^1.0.3",
|
||||||
"winston": "^3.8.2",
|
"winston": "^3.10.0",
|
||||||
"ytdl-core": "^4.11.4"
|
"ytdl-core": "^4.11.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.16.6",
|
"@types/node": "^20.4.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||||
"@typescript-eslint/parser": "^5.59.5",
|
"@typescript-eslint/parser": "^6.0.0",
|
||||||
"eslint": "^8.40.0",
|
"eslint": "^8.44.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||||
"prettier": "^2.8.8",
|
"mocha": "^10.2.0",
|
||||||
"prisma": "^4.13.0",
|
"prettier": "^3.0.0",
|
||||||
"typescript": "^4.9.5"
|
"prisma": "^5.0.0",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+634
-295
File diff suppressed because it is too large.
Load diff
+4
-1
@@ -58,7 +58,10 @@ export default class Client extends DiscordClient {
|
|||||||
});
|
});
|
||||||
|
|
||||||
importModule(path.join(data.rootDir, MODULE_EVENTS), (event: Event) => {
|
importModule(path.join(data.rootDir, MODULE_EVENTS), (event: Event) => {
|
||||||
this.on(event.name, (...eventee: unknown[]) => event.execute(this, eventee));
|
this.on(
|
||||||
|
event.name,
|
||||||
|
async (...eventee: unknown[]) => await event.execute(this, eventee)
|
||||||
|
);
|
||||||
events.push(event.name);
|
events.push(event.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+1
-8
@@ -4,17 +4,10 @@ const logger = winston.createLogger({
|
|||||||
level: "info",
|
level: "info",
|
||||||
format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
|
format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
|
||||||
transports: [
|
transports: [
|
||||||
|
new winston.transports.Console({ format: winston.format.simple() }),
|
||||||
new winston.transports.File({ filename: "logs/error.log", level: "error" }),
|
new winston.transports.File({ filename: "logs/error.log", level: "error" }),
|
||||||
new winston.transports.File({ filename: "logs/combined.log" })
|
new winston.transports.File({ filename: "logs/combined.log" })
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== "production") {
|
|
||||||
logger.add(
|
|
||||||
new winston.transports.Console({
|
|
||||||
format: winston.format.simple()
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default logger;
|
export default logger;
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction): Promise<void> {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
||||||
if (!interaction.isChatInputCommand()) {
|
if (!interaction.isChatInputCommand()) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction): Promise<void> {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
||||||
if (!interaction.isChatInputCommand()) {
|
if (!interaction.isChatInputCommand()) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,23 @@ import logger from "../../../lib/logger.js";
|
|||||||
async function execute(client: Client, eventee: [Interaction]): Promise<void> {
|
async function execute(client: Client, eventee: [Interaction]): Promise<void> {
|
||||||
const [interaction] = eventee;
|
const [interaction] = eventee;
|
||||||
|
|
||||||
logger.info("Interaction created.", interaction);
|
if (interaction.isChatInputCommand()) {
|
||||||
|
|
||||||
if (interaction.isCommand()) {
|
|
||||||
const command = client.commands.get(interaction.commandName);
|
const command = client.commands.get(interaction.commandName);
|
||||||
|
|
||||||
if (command) {
|
if (!command) {
|
||||||
command.execute(client, interaction);
|
logger.error(`No command matching ${interaction.commandName} was found.`, {
|
||||||
|
interaction
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.info(`Interaction ${interaction.commandName} was created.`, interaction);
|
||||||
|
|
||||||
|
await command.execute(client, interaction);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("Interaction error occured. ", { error, interaction });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { fileURLToPath } from "url";
|
|||||||
const name = "core";
|
const name = "core";
|
||||||
const description = "Quetza core functionality";
|
const description = "Quetza core functionality";
|
||||||
const author = "unknowableshade";
|
const author = "unknowableshade";
|
||||||
const tag = "4.2.0";
|
const tag = "4.2.2";
|
||||||
|
|
||||||
const rootDir = path.dirname(fileURLToPath(import.meta.url));
|
const rootDir = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction): Promise<void> {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction): Promise<void> {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
@@ -6,7 +6,7 @@ import Filter from "../lib/filter.js";
|
|||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pos = interaction.options.getNumber("position", true);
|
|
||||||
const query = interaction.options.getString("query", true);
|
const query = interaction.options.getString("query", true);
|
||||||
|
const pos = interaction.options.getInteger("position", true);
|
||||||
|
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
@@ -6,7 +6,7 @@ import replies from "../lib/replies.js";
|
|||||||
import { LoopOption } from "../lib/types.js";
|
import { LoopOption } from "../lib/types.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ async function execute(client: Client, interaction: Interaction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!player.resource) {
|
if (!player.resource) {
|
||||||
player.play();
|
await player.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
ButtonBuilder,
|
ButtonBuilder,
|
||||||
ButtonInteraction,
|
ButtonInteraction,
|
||||||
ButtonStyle,
|
ButtonStyle,
|
||||||
Interaction,
|
ChatInputCommandInteraction,
|
||||||
MessageActionRowComponentBuilder,
|
MessageActionRowComponentBuilder,
|
||||||
SlashCommandBuilder
|
SlashCommandBuilder
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
@@ -13,7 +13,7 @@ import logger from "../../../lib/logger.js";
|
|||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Interaction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
import { controller } from "../module.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction) {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
|
|||||||
+160
-17
@@ -1,13 +1,29 @@
|
|||||||
import { execFile } from "child_process";
|
import { execFile } from "child_process";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import prismMedia from "prism-media";
|
||||||
|
import { Duplex, Readable } from "stream";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
|
import ytdl from "ytdl-core";
|
||||||
|
|
||||||
import config from "../../../config.js";
|
import config from "../../../config.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
|
import { StreamOptions, YtdlDump, YtdlResult, YtdlStreamOptions } from "./types.js";
|
||||||
|
|
||||||
|
const { opus: Opus, FFmpeg } = prismMedia;
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
const SEARCH_DEPTH = 5;
|
const SEARCH_DEPTH = 5;
|
||||||
|
const YTDL_EVENTS = [
|
||||||
|
"info",
|
||||||
|
"progress",
|
||||||
|
"abort",
|
||||||
|
"request",
|
||||||
|
"response",
|
||||||
|
"error",
|
||||||
|
"redirect",
|
||||||
|
"retry",
|
||||||
|
"reconnect"
|
||||||
|
];
|
||||||
|
|
||||||
function isURL(url: string): boolean {
|
function isURL(url: string): boolean {
|
||||||
return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/.test(
|
return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/.test(
|
||||||
@@ -15,23 +31,6 @@ function isURL(url: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface YtdlDump {
|
|
||||||
id: string;
|
|
||||||
original_url: string;
|
|
||||||
title?: string;
|
|
||||||
uploader?: string;
|
|
||||||
duration?: number;
|
|
||||||
extractor_key: string;
|
|
||||||
thumbnail?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface YtdlResult {
|
|
||||||
url: string;
|
|
||||||
title: string;
|
|
||||||
thumbnail: string;
|
|
||||||
duration: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchInfoRecursive(query: string, depth = 0): Promise<YtdlResult[]> {
|
async function fetchInfoRecursive(query: string, depth = 0): Promise<YtdlResult[]> {
|
||||||
if (depth === SEARCH_DEPTH) {
|
if (depth === SEARCH_DEPTH) {
|
||||||
logger.warn("yt-dlp failed to find anything.", { query });
|
logger.warn("yt-dlp failed to find anything.", { query });
|
||||||
@@ -100,3 +99,147 @@ export async function fetchInfo(query: string): Promise<YtdlResult[]> {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ytdlStream(url: string, options?: YtdlStreamOptions) {
|
||||||
|
logger.info("Created ytdl stream.", { url, options });
|
||||||
|
|
||||||
|
let ffmpegArgs: string[] = [
|
||||||
|
"-analyzeduration",
|
||||||
|
"0",
|
||||||
|
"-loglevel",
|
||||||
|
"0",
|
||||||
|
"-f",
|
||||||
|
`${options?.fmt ? options.fmt : "s16le"}`,
|
||||||
|
"-ar",
|
||||||
|
"48000",
|
||||||
|
"-ac",
|
||||||
|
"2"
|
||||||
|
];
|
||||||
|
|
||||||
|
if (options?.seek) {
|
||||||
|
ffmpegArgs.unshift("-ss", options.seek.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.encoderArgs) {
|
||||||
|
ffmpegArgs = ffmpegArgs.concat(options.encoderArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const transcoder = new FFmpeg({
|
||||||
|
args: ffmpegArgs
|
||||||
|
});
|
||||||
|
|
||||||
|
const inputStream = ytdl(url, options);
|
||||||
|
const transcoderStream = inputStream.pipe(transcoder);
|
||||||
|
|
||||||
|
if (options && !options.opusEncoded) {
|
||||||
|
YTDL_EVENTS.forEach((event) =>
|
||||||
|
inputStream.on(event, (...args) => transcoderStream.emit(event, ...args))
|
||||||
|
);
|
||||||
|
inputStream.on("error", () => transcoder.destroy());
|
||||||
|
transcoderStream.on("close", () => transcoder.destroy());
|
||||||
|
|
||||||
|
return transcoderStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
const opus = new Opus.Encoder({
|
||||||
|
rate: 48000,
|
||||||
|
channels: 2,
|
||||||
|
frameSize: 960
|
||||||
|
});
|
||||||
|
|
||||||
|
const outputStream = transcoderStream.pipe(opus);
|
||||||
|
|
||||||
|
transcoderStream.on("error", (e) => outputStream.emit("error", e));
|
||||||
|
|
||||||
|
YTDL_EVENTS.forEach((event) =>
|
||||||
|
inputStream.on(event, (...args) => outputStream.emit(event, ...args))
|
||||||
|
);
|
||||||
|
|
||||||
|
outputStream.on("close", () => {
|
||||||
|
transcoder.destroy();
|
||||||
|
opus.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
return outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function arbitraryStream(stream: string | Readable | Duplex, options?: StreamOptions) {
|
||||||
|
logger.info("Created arbitrary stream.", { stream, options });
|
||||||
|
|
||||||
|
let ffmpegArgs: string[];
|
||||||
|
|
||||||
|
if (typeof stream === "string") {
|
||||||
|
ffmpegArgs = [
|
||||||
|
"-reconnect",
|
||||||
|
"1",
|
||||||
|
"-reconnect_streamed",
|
||||||
|
"1",
|
||||||
|
"-reconnect_delay_max",
|
||||||
|
"5",
|
||||||
|
"-i",
|
||||||
|
stream,
|
||||||
|
"-analyzeduration",
|
||||||
|
"0",
|
||||||
|
"-loglevel",
|
||||||
|
"0",
|
||||||
|
"-f",
|
||||||
|
`${options?.fmt ? options.fmt : "s16le"}`,
|
||||||
|
"-ar",
|
||||||
|
"48000",
|
||||||
|
"-ac",
|
||||||
|
"2"
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
ffmpegArgs = [
|
||||||
|
"-analyzeduration",
|
||||||
|
"0",
|
||||||
|
"-loglevel",
|
||||||
|
"0",
|
||||||
|
"-f",
|
||||||
|
`${options?.fmt ? options.fmt : "s16le"}`,
|
||||||
|
"-ar",
|
||||||
|
"48000",
|
||||||
|
"-ac",
|
||||||
|
"2"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.seek) {
|
||||||
|
ffmpegArgs.unshift("-ss", options.seek.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.encoderArgs) {
|
||||||
|
ffmpegArgs = ffmpegArgs.concat(options.encoderArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
let transcoder = new FFmpeg({
|
||||||
|
args: ffmpegArgs
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof stream !== "string") {
|
||||||
|
transcoder = stream.pipe(transcoder);
|
||||||
|
|
||||||
|
stream.on("error", () => transcoder.destroy());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options && !options.opusEncoded) {
|
||||||
|
transcoder.on("close", () => transcoder.destroy());
|
||||||
|
|
||||||
|
return transcoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
const opus = new Opus.Encoder({
|
||||||
|
rate: 48000,
|
||||||
|
channels: 2,
|
||||||
|
frameSize: 960
|
||||||
|
});
|
||||||
|
|
||||||
|
const outputStream = transcoder.pipe(opus);
|
||||||
|
|
||||||
|
outputStream.on("close", () => {
|
||||||
|
transcoder.destroy();
|
||||||
|
opus.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
return outputStream;
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ const STATUSBAR_LENGTH = 15;
|
|||||||
|
|
||||||
export function statusBarGenerator(resource?: AudioResource<Track>): string {
|
export function statusBarGenerator(resource?: AudioResource<Track>): string {
|
||||||
const duration = resource?.metadata.duration || 1;
|
const duration = resource?.metadata.duration || 1;
|
||||||
const playback = Math.min(resource?.playbackDuration || 0 / 1000, duration);
|
const playback = Math.min((resource?.playbackDuration || 0) / 1000, duration);
|
||||||
|
|
||||||
const filled = Array<string>(Math.floor((STATUSBAR_LENGTH * playback) / duration)).fill("🔹");
|
const filled = Array<string>(Math.floor((STATUSBAR_LENGTH * playback) / duration)).fill("🔹");
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,8 @@ import {
|
|||||||
VoiceConnection
|
VoiceConnection
|
||||||
} from "@discordjs/voice";
|
} from "@discordjs/voice";
|
||||||
import { Guild, GuildTextBasedChannel, Message, User, VoiceBasedChannel } from "discord.js";
|
import { Guild, GuildTextBasedChannel, Message, User, VoiceBasedChannel } from "discord.js";
|
||||||
import ytdl from "discord-ytdl-core";
|
|
||||||
|
|
||||||
import { fetchInfo } from "./fetch.js";
|
import { fetchInfo, ytdlStream } from "./fetch.js";
|
||||||
import Filter from "./filter.js";
|
import Filter from "./filter.js";
|
||||||
import { largestCommonSequence } from "./misc.js";
|
import { largestCommonSequence } from "./misc.js";
|
||||||
import Music from "./music.js";
|
import Music from "./music.js";
|
||||||
@@ -77,7 +76,7 @@ export default class Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private resourceGenerator(track: Track, seek?: number) {
|
private resourceGenerator(track: Track, seek?: number) {
|
||||||
const stream = ytdl(track.url, {
|
const stream = ytdlStream(track.url, {
|
||||||
opusEncoded: true,
|
opusEncoded: true,
|
||||||
filter: "audioonly",
|
filter: "audioonly",
|
||||||
highWaterMark: 1 << 25,
|
highWaterMark: 1 << 25,
|
||||||
@@ -134,7 +133,7 @@ export default class Player {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public play(seek?: number): void {
|
public async play(seek?: number): Promise<void> {
|
||||||
const track = this.queue.current();
|
const track = this.queue.current();
|
||||||
|
|
||||||
if (!this.connection_ || !track) {
|
if (!this.connection_ || !track) {
|
||||||
@@ -145,7 +144,7 @@ export default class Player {
|
|||||||
|
|
||||||
this.connection_.subscribe(this.player_);
|
this.connection_.subscribe(this.player_);
|
||||||
|
|
||||||
this.messageResolvable(track);
|
await this.messageResolvable(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
public connect(channel: VoiceBasedChannel): void {
|
public connect(channel: VoiceBasedChannel): void {
|
||||||
|
|||||||
@@ -63,20 +63,22 @@ export default class Queue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public push(tracks: Track[], index?: number): Track {
|
public push(tracks: Track[], index?: number): Track {
|
||||||
if (!index || index >= this.tracks_.length) {
|
|
||||||
this.tracks_ = this.tracks_.concat(tracks);
|
|
||||||
} else {
|
|
||||||
this.tracks_.splice(Math.max(0, index), 0, ...tracks);
|
|
||||||
if (this.position_ >= index) {
|
|
||||||
this.position_ += tracks.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const track of tracks) {
|
for (const track of tracks) {
|
||||||
this.duration_ += track.duration;
|
this.duration_ += track.duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.tracks_[index || this.tracks_.length - 1];
|
if (index === undefined || index >= this.tracks_.length) {
|
||||||
|
this.tracks_ = this.tracks_.concat(tracks);
|
||||||
|
|
||||||
|
return this.tracks_[this.tracks_.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tracks_.splice(Math.max(0, index), 0, ...tracks);
|
||||||
|
if (this.position_ >= index) {
|
||||||
|
this.position_ += tracks.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.tracks_[Math.max(0, index)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public pop(query: number): Track | undefined {
|
public pop(query: number): Track | undefined {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const replies = {
|
|||||||
.setColor(config.colors.default)
|
.setColor(config.colors.default)
|
||||||
.setAuthor({
|
.setAuthor({
|
||||||
iconURL: track.requester.avatarURL() ?? undefined,
|
iconURL: track.requester.avatarURL() ?? undefined,
|
||||||
name: track.requester.tag
|
name: track.requester.username
|
||||||
})
|
})
|
||||||
.setTitle(track.title)
|
.setTitle(track.title)
|
||||||
.setURL(track.url)
|
.setURL(track.url)
|
||||||
@@ -202,7 +202,7 @@ const replies = {
|
|||||||
.setColor(config.colors.success)
|
.setColor(config.colors.success)
|
||||||
.setAuthor({
|
.setAuthor({
|
||||||
iconURL: track.requester.avatarURL() ?? undefined,
|
iconURL: track.requester.avatarURL() ?? undefined,
|
||||||
name: track.requester.tag
|
name: track.requester.username
|
||||||
})
|
})
|
||||||
.setTitle(track.title)
|
.setTitle(track.title)
|
||||||
.setURL(track.url)
|
.setURL(track.url)
|
||||||
@@ -261,7 +261,7 @@ const replies = {
|
|||||||
|
|
||||||
embed
|
embed
|
||||||
.setColor(config.colors.success)
|
.setColor(config.colors.success)
|
||||||
.setDescription("Playback can experience some lags during intial transformation.");
|
.setDescription("Playback can experience some lags during initial transformation.");
|
||||||
|
|
||||||
return { embeds: [embed] };
|
return { embeds: [embed] };
|
||||||
},
|
},
|
||||||
@@ -290,7 +290,7 @@ const replies = {
|
|||||||
.setTitle(`${queue.position + 1}. ${resource.metadata.title}`)
|
.setTitle(`${queue.position + 1}. ${resource.metadata.title}`)
|
||||||
.setAuthor({
|
.setAuthor({
|
||||||
iconURL: resource.metadata.requester.avatarURL() ?? undefined,
|
iconURL: resource.metadata.requester.avatarURL() ?? undefined,
|
||||||
name: resource.metadata.requester.tag
|
name: resource.metadata.requester.username
|
||||||
})
|
})
|
||||||
.setURL(resource.metadata.url)
|
.setURL(resource.metadata.url)
|
||||||
.setDescription(statusBarGenerator(resource))
|
.setDescription(statusBarGenerator(resource))
|
||||||
@@ -306,7 +306,7 @@ const replies = {
|
|||||||
embed.setColor(config.colors.info).setFields(
|
embed.setColor(config.colors.info).setFields(
|
||||||
queue.tracks.slice(position, position + 10).map((value, index) => ({
|
queue.tracks.slice(position, position + 10).map((value, index) => ({
|
||||||
name: `${position + index + 1}. ${value.title.padEnd(35)}`,
|
name: `${position + index + 1}. ${value.title.padEnd(35)}`,
|
||||||
value: `[${toISOTime(value.duration)}] | ${value.requester.tag}`
|
value: `[${toISOTime(value.duration)}] | ${value.requester.username}`
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ const replies = {
|
|||||||
.setTitle(`${player.queue.position + 1}. ${player.resource.metadata.title}`)
|
.setTitle(`${player.queue.position + 1}. ${player.resource.metadata.title}`)
|
||||||
.setAuthor({
|
.setAuthor({
|
||||||
iconURL: player.resource.metadata.requester.avatarURL() ?? undefined,
|
iconURL: player.resource.metadata.requester.avatarURL() ?? undefined,
|
||||||
name: player.resource.metadata.requester.tag
|
name: player.resource.metadata.requester.username
|
||||||
})
|
})
|
||||||
.setURL(player.resource.metadata.url)
|
.setURL(player.resource.metadata.url)
|
||||||
.setDescription(statusBarGenerator(player.resource))
|
.setDescription(statusBarGenerator(player.resource))
|
||||||
|
|||||||
+27
-245
@@ -1,4 +1,5 @@
|
|||||||
import { User } from "discord.js";
|
import { User } from "discord.js";
|
||||||
|
import { downloadOptions } from "ytdl-core";
|
||||||
|
|
||||||
export interface Track {
|
export interface Track {
|
||||||
url: string;
|
url: string;
|
||||||
@@ -10,252 +11,33 @@ export interface Track {
|
|||||||
|
|
||||||
export type LoopOption = "LOOP" | "SONG" | "NONE" | "AUTO";
|
export type LoopOption = "LOOP" | "SONG" | "NONE" | "AUTO";
|
||||||
|
|
||||||
export interface YtdlArgs {
|
export interface YtdlDump {
|
||||||
help?: boolean;
|
|
||||||
version?: boolean;
|
|
||||||
update?: boolean;
|
|
||||||
ignoreErrors?: boolean;
|
|
||||||
abortOnError?: boolean;
|
|
||||||
dumpUserAgent?: boolean;
|
|
||||||
listExtractors?: boolean;
|
|
||||||
extractorDescriptions?: boolean;
|
|
||||||
forceGenericExtractor?: boolean;
|
|
||||||
defaultSearch?: string;
|
|
||||||
igonreConfig?: boolean;
|
|
||||||
configLocation?: string;
|
|
||||||
flatPlaylist?: boolean;
|
|
||||||
markWatched?: boolean;
|
|
||||||
noColor?: boolean;
|
|
||||||
proxy?: string;
|
|
||||||
socketTimeout?: number;
|
|
||||||
sourceAddress?: string;
|
|
||||||
forceIpv4?: boolean;
|
|
||||||
forceIpv6?: boolean;
|
|
||||||
geoVerificationProxy?: string;
|
|
||||||
geoBypass?: boolean;
|
|
||||||
geoBypassCountry?: string;
|
|
||||||
geoBypassIpBlock?: string;
|
|
||||||
playlistStart?: number;
|
|
||||||
playlistEnd?: number | "last";
|
|
||||||
playlistItems?: string;
|
|
||||||
matchTitle?: string;
|
|
||||||
rejectTitle?: string;
|
|
||||||
maxDownloads?: number;
|
|
||||||
minFilesize?: string;
|
|
||||||
maxFilesize?: string;
|
|
||||||
date?: string;
|
|
||||||
datebefore?: string;
|
|
||||||
dateafter?: string;
|
|
||||||
minViews?: number;
|
|
||||||
maxViews?: number;
|
|
||||||
matchFilter?: string;
|
|
||||||
noPlaylist?: boolean;
|
|
||||||
yesPlaylist?: boolean;
|
|
||||||
ageLimit?: number;
|
|
||||||
downloadArchive?: string;
|
|
||||||
includeAds?: boolean;
|
|
||||||
limitRate?: string;
|
|
||||||
retries?: number | "infinite";
|
|
||||||
skipUnavailableFragments?: boolean;
|
|
||||||
abortOnUnavailableFragment?: boolean;
|
|
||||||
keepFragments?: boolean;
|
|
||||||
bufferSize?: string;
|
|
||||||
noResizeBuffer?: boolean;
|
|
||||||
httpChunkSize?: string;
|
|
||||||
playlistReverse?: boolean;
|
|
||||||
playlistRandom?: boolean;
|
|
||||||
xattrSetFilesize?: boolean;
|
|
||||||
hlsPreferNative?: boolean;
|
|
||||||
hlsPreferFfmpeg?: boolean;
|
|
||||||
hlsUseMpegts?: boolean;
|
|
||||||
externalDownloader?: string;
|
|
||||||
externalDownloaderArgs?: string;
|
|
||||||
batchFile?: string;
|
|
||||||
id?: boolean;
|
|
||||||
output?: string;
|
|
||||||
outputNaPlaceholder?: string;
|
|
||||||
autonumberStart?: number;
|
|
||||||
restrictFilenames?: boolean;
|
|
||||||
noOverwrites?: boolean;
|
|
||||||
continue?: boolean;
|
|
||||||
noPart?: boolean;
|
|
||||||
noMtime?: boolean;
|
|
||||||
writeDescription?: boolean;
|
|
||||||
writeInfoJson?: boolean;
|
|
||||||
writeAnnotations?: boolean;
|
|
||||||
loadInfoJson?: string;
|
|
||||||
cookies?: string;
|
|
||||||
cacheDir?: string;
|
|
||||||
noCacheDir?: boolean;
|
|
||||||
rmCacheDir?: boolean;
|
|
||||||
writeThumbnail?: boolean;
|
|
||||||
writeAllThumbnails?: boolean;
|
|
||||||
listThumbnails?: boolean;
|
|
||||||
quiet?: boolean;
|
|
||||||
noWarnings?: boolean;
|
|
||||||
simulate?: boolean;
|
|
||||||
skipDownload?: boolean;
|
|
||||||
getUrl?: boolean;
|
|
||||||
getTitle?: boolean;
|
|
||||||
getId?: boolean;
|
|
||||||
getThumbnail?: boolean;
|
|
||||||
getDuration?: boolean;
|
|
||||||
getFilename?: boolean;
|
|
||||||
getFormat?: boolean;
|
|
||||||
dumpJson?: boolean;
|
|
||||||
dumpSingleJson?: boolean;
|
|
||||||
printJson?: boolean;
|
|
||||||
newline?: boolean;
|
|
||||||
noProgress?: boolean;
|
|
||||||
consoleTitle?: boolean;
|
|
||||||
verbose?: boolean;
|
|
||||||
dumpPages?: boolean;
|
|
||||||
writePages?: boolean;
|
|
||||||
printTraffic?: boolean;
|
|
||||||
callHome?: boolean;
|
|
||||||
encoding?: string;
|
|
||||||
noCheckCertificate?: boolean;
|
|
||||||
preferInsecure?: boolean;
|
|
||||||
userAgent?: string;
|
|
||||||
referer?: string;
|
|
||||||
addHeader?: string;
|
|
||||||
bidiWorkaround?: boolean;
|
|
||||||
sleepInterval?: number;
|
|
||||||
maxSleepInterval?: number;
|
|
||||||
format?: string;
|
|
||||||
allFormats?: boolean;
|
|
||||||
preferFreeFormats?: boolean;
|
|
||||||
listFormats?: boolean;
|
|
||||||
youtubeSkipDashManifest?: boolean;
|
|
||||||
mergeOutputFormat?: string;
|
|
||||||
writeSub?: boolean;
|
|
||||||
writeAutoSub?: boolean;
|
|
||||||
allSubs?: boolean;
|
|
||||||
listSubs?: boolean;
|
|
||||||
subFormat?: string;
|
|
||||||
subLang?: string;
|
|
||||||
username?: string;
|
|
||||||
password?: string;
|
|
||||||
twofactor?: string;
|
|
||||||
netrc?: boolean;
|
|
||||||
videoPassword?: string;
|
|
||||||
apMso?: string;
|
|
||||||
apUsername?: string;
|
|
||||||
apPassword?: string;
|
|
||||||
apListMso?: boolean;
|
|
||||||
extractAudio?: boolean;
|
|
||||||
audioFormat?: string;
|
|
||||||
audioQuality?: number;
|
|
||||||
recodeVideo?: string;
|
|
||||||
postprocessorArgs?: string;
|
|
||||||
keepVideo?: boolean;
|
|
||||||
noPostOverwrites?: boolean;
|
|
||||||
embedSubs?: boolean;
|
|
||||||
embedThumbnail?: boolean;
|
|
||||||
addMetadata?: boolean;
|
|
||||||
metadataFromFile?: string;
|
|
||||||
xattrs?: boolean;
|
|
||||||
fixup?: string;
|
|
||||||
preferAvconv?: boolean;
|
|
||||||
preferFfmpeg?: boolean;
|
|
||||||
ffmpegLocation?: string;
|
|
||||||
exec?: string;
|
|
||||||
convertSubs?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface YtdlFormat {
|
|
||||||
asr: number;
|
|
||||||
filesize: number;
|
|
||||||
format_id: string;
|
|
||||||
format_note: string;
|
|
||||||
fps: number;
|
|
||||||
height: number;
|
|
||||||
quality: number;
|
|
||||||
tbr: number;
|
|
||||||
url: string;
|
|
||||||
width: number;
|
|
||||||
ext: string;
|
|
||||||
vcodec: string;
|
|
||||||
acodec: string;
|
|
||||||
abr: number;
|
|
||||||
downloader_options: unknown;
|
|
||||||
container: string;
|
|
||||||
format: string;
|
|
||||||
protocol: string;
|
|
||||||
http_headers: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface YtdlThumbnail {
|
|
||||||
height: number;
|
|
||||||
url: string;
|
|
||||||
width: number;
|
|
||||||
resolution: string;
|
|
||||||
id: string;
|
id: string;
|
||||||
}
|
original_url: string;
|
||||||
|
title?: string;
|
||||||
interface YtdlEntry {
|
uploader?: string;
|
||||||
uploader: string;
|
duration?: number;
|
||||||
duration: number;
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface YtdlResponse {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
formats: YtdlFormat[];
|
|
||||||
thumbnails: YtdlThumbnail[];
|
|
||||||
description: string;
|
|
||||||
upload_date: string;
|
|
||||||
uploader: string;
|
|
||||||
uploader_id: string;
|
|
||||||
uploader_url: string;
|
|
||||||
channel_id: string;
|
|
||||||
channel_url: string;
|
|
||||||
duration: number;
|
|
||||||
view_count: number;
|
|
||||||
average_rating: number;
|
|
||||||
age_limit: number;
|
|
||||||
webpage_url: string;
|
|
||||||
categories: string[];
|
|
||||||
tags: string[];
|
|
||||||
is_live: boolean;
|
|
||||||
like_count: number;
|
|
||||||
dislike_count: number;
|
|
||||||
channel: string;
|
|
||||||
track: string;
|
|
||||||
artist: string;
|
|
||||||
creator: string;
|
|
||||||
alt_title: string;
|
|
||||||
extractor: string;
|
|
||||||
webpage_url_basename: string;
|
|
||||||
extractor_key: string;
|
extractor_key: string;
|
||||||
playlist: string;
|
thumbnail?: string;
|
||||||
playlist_index: number;
|
}
|
||||||
|
|
||||||
|
export interface YtdlResult {
|
||||||
|
url: string;
|
||||||
|
title: string;
|
||||||
thumbnail: string;
|
thumbnail: string;
|
||||||
display_id: string;
|
duration: number;
|
||||||
requested_subtitles: unknown;
|
}
|
||||||
asr: number;
|
|
||||||
filesize: number;
|
export interface YtdlStreamOptions extends downloadOptions {
|
||||||
format_id: string;
|
seek?: number;
|
||||||
format_note: string;
|
encoderArgs?: string[];
|
||||||
fps: number;
|
fmt?: string;
|
||||||
height: number;
|
opusEncoded?: boolean;
|
||||||
quality: number;
|
}
|
||||||
tbr: number;
|
|
||||||
url: string;
|
export interface StreamOptions {
|
||||||
width: number;
|
seek?: number;
|
||||||
ext: string;
|
encoderArgs?: string[];
|
||||||
vcodec: string;
|
fmt?: string;
|
||||||
acodec: string;
|
opusEncoded?: boolean;
|
||||||
abr: number;
|
|
||||||
downloader_options: { http_chunk_size: number };
|
|
||||||
container: string;
|
|
||||||
format: string;
|
|
||||||
protocol: string;
|
|
||||||
http_headers: unknown;
|
|
||||||
fulltitle: string;
|
|
||||||
_filename: string;
|
|
||||||
entries: YtdlEntry[];
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
import { Events, Interaction, PermissionFlagsBits, SlashCommandBuilder } from "discord.js";
|
import {
|
||||||
|
ChatInputCommandInteraction,
|
||||||
|
Events,
|
||||||
|
PermissionFlagsBits,
|
||||||
|
SlashCommandBuilder
|
||||||
|
} from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction): Promise<void> {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild()) {
|
if (!interaction.inCachedGuild()) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -49,7 +54,7 @@ async function execute(client: Client, interaction: Interaction): Promise<void>
|
|||||||
|
|
||||||
await interaction.editReply(replies.auto("add role to a member", event));
|
await interaction.editReply(replies.auto("add role to a member", event));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Error occured while quering db.", { interaction });
|
logger.error("Error occured while quering db.", { error });
|
||||||
} finally {
|
} finally {
|
||||||
await client.db.$disconnect();
|
await client.db.$disconnect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Interaction, PermissionFlagsBits, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, PermissionFlagsBits, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
import Client from "../../../lib/client.js";
|
import Client from "../../../lib/client.js";
|
||||||
import logger from "../../../lib/logger.js";
|
import logger from "../../../lib/logger.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
|
|
||||||
async function execute(client: Client, interaction: Interaction): Promise<void> {
|
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
||||||
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild()) {
|
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild()) {
|
||||||
logger.warn("Interaction rejected.", { interaction });
|
logger.warn("Interaction rejected.", { interaction });
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ async function execute(client: Client, interaction: Interaction): Promise<void>
|
|||||||
const member = await interaction.guild.members.fetch(user).catch(() => undefined);
|
const member = await interaction.guild.members.fetch(user).catch(() => undefined);
|
||||||
|
|
||||||
if (member) {
|
if (member) {
|
||||||
await interaction.reply(replies.roleList(user.tag, member.roles.cache));
|
await interaction.reply(replies.roleList(user.username, member.roles.cache));
|
||||||
} else {
|
} else {
|
||||||
await interaction.reply(replies.notMember("edited", user));
|
await interaction.reply(replies.notMember("edited", user));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const replies = {
|
|||||||
notMember: (action: string, user: User): InteractionReplyOptions => {
|
notMember: (action: string, user: User): InteractionReplyOptions => {
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor("Blue")
|
.setColor("Blue")
|
||||||
.setTitle(`${user.tag} cannot be ${action}`)
|
.setTitle(`${user.username} cannot be ${action}`)
|
||||||
.setDescription("They're not a guild member.")
|
.setDescription("They're not a guild member.")
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ const replies = {
|
|||||||
): InteractionReplyOptions => {
|
): InteractionReplyOptions => {
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor(config.colors.success)
|
.setColor(config.colors.success)
|
||||||
.setTitle(`Role ${roleName} was ${action} user ${user.tag}`)
|
.setTitle(`Role ${roleName} was ${action} user ${user.username}`)
|
||||||
.setDescription(reason ?? "No reason provided.")
|
.setDescription(reason ?? "No reason provided.")
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user