Compare commits
6
Commits
development
...
2024.11.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63e4d85cbb
|
||
|
|
d79713eae9
|
||
|
|
cfb6930ccc
|
||
|
|
6250ba601f | ||
|
|
0bc97f89fd | ||
|
|
ec34590cf7 |
No files matched your search
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"root": true,
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"warnOnUnsupportedTypeScriptVersion": false,
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"browser": false,
|
|
||||||
"node": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
|
|
||||||
"plugins": ["@typescript-eslint", "import", "simple-import-sort"],
|
|
||||||
"ignorePatterns": ["**/node_modules/**", "/dist/**", "/tests/**"],
|
|
||||||
"rules": {
|
|
||||||
"curly": ["error", "all"],
|
|
||||||
"simple-import-sort/imports": "error",
|
|
||||||
"simple-import-sort/exports": "error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,8 +13,8 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.x]
|
node-version: [22.x]
|
||||||
pnpm-version: [8]
|
pnpm-version: [9]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
@@ -35,11 +35,6 @@ jobs:
|
|||||||
- name: ESLint & Prettier
|
- name: ESLint & Prettier
|
||||||
run: pnpm run lint
|
run: pnpm run lint
|
||||||
|
|
||||||
- name: Prisma Migration
|
|
||||||
env:
|
|
||||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
||||||
run: pnpm exec prisma migrate deploy
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm run build
|
run: pnpm run build
|
||||||
|
|
||||||
@@ -54,6 +49,12 @@ jobs:
|
|||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||||
with:
|
with:
|
||||||
@@ -65,7 +66,7 @@ jobs:
|
|||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
unknowableshade/quetza
|
deytenit/quetza
|
||||||
# generate Docker tags based on the following events/attributes
|
# generate Docker tags based on the following events/attributes
|
||||||
# on tag event: tag using git tag, and as latest if the tag doesn't contain hyphens (pre-releases)
|
# on tag event: tag using git tag, and as latest if the tag doesn't contain hyphens (pre-releases)
|
||||||
# on push event: tag using git sha, branch name and as latest-dev
|
# on push event: tag using git sha, branch name and as latest-dev
|
||||||
@@ -82,5 +83,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Privacy Policy of Quetza
|
||||||
|
|
||||||
|
This privacy policy applies to the Discord bot Quetza (hereby referred to as "Quetza")
|
||||||
|
that was created by Vladimir Eremin (hereby referred to as "Service Provider")
|
||||||
|
as an Open Source service.
|
||||||
|
|
||||||
|
Quetza is intended for use "AS IS",
|
||||||
|
in compliance with [Discord Privacy Policy](https://discord.com/privacy).
|
||||||
|
|
||||||
|
## What information does Quetza store and how is it used?
|
||||||
|
|
||||||
|
Quetza does not store any information.
|
||||||
|
|
||||||
|
## Do third parties see and/or have access to information obtained by the Quetza?
|
||||||
|
|
||||||
|
Since Quetza does not store any information, no data is shared with third parties.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
This Privacy Policy may be updated from time to time for any reason.
|
||||||
|
The Service Provider will notify you of any changes to their Privacy Policy
|
||||||
|
by updating this page with the new Privacy Policy.
|
||||||
|
You are advised to consult this Privacy Policy regularly for any changes,
|
||||||
|
as continued use is deemed approval of all changes.
|
||||||
|
|
||||||
|
_This privacy policy is effective as of 2024-11-08_
|
||||||
|
|
||||||
|
## Your Consent
|
||||||
|
|
||||||
|
By using Quetza, you are consenting to the processing of your information
|
||||||
|
as set forth in this Privacy Policy now and as amended by the Service Provider.
|
||||||
|
|
||||||
|
## Contact Us
|
||||||
|
|
||||||
|
If you have any questions regarding privacy while using Quetza, or have questions
|
||||||
|
about the practices, please contact the Service Provider via email at [personal@ermnvldmr.com](mailto:personal@ermnvldmr.com).
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
||||||
|
import globals from "globals";
|
||||||
|
import tsParser from "@typescript-eslint/parser";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import js from "@eslint/js";
|
||||||
|
import { FlatCompat } from "@eslint/eslintrc";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all
|
||||||
|
});
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{ ignores: ["**/node_modules/**/*", "dist/**/*", "tests/**/*"] },
|
||||||
|
...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"),
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
"@typescript-eslint": typescriptEslint
|
||||||
|
},
|
||||||
|
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...Object.fromEntries(Object.entries(globals.browser).map(([key]) => [key, "off"])),
|
||||||
|
...globals.node
|
||||||
|
},
|
||||||
|
|
||||||
|
parser: tsParser,
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
sourceType: "module",
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
warnOnUnsupportedTypeScriptVersion: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
curly: ["error", "all"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -4,8 +4,6 @@
|
|||||||
* Replies module listing as well as description of each.
|
* Replies module listing as well as description of each.
|
||||||
*
|
*
|
||||||
* Just for the information I guess...
|
* Just for the information I guess...
|
||||||
*
|
|
||||||
* @packageDocumentation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
* Replies websocket ping (ping between bot and discord) and real ping (ping to fetch + process).
|
* Replies websocket ping (ping between bot and discord) and real ping (ping to fetch + process).
|
||||||
*
|
*
|
||||||
* @remarks Probably should double their value as two ways, but nvm.
|
* @remarks Probably should double their value as two ways, but nvm.
|
||||||
*
|
|
||||||
* @packageDocumentation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
* Resolves creation of an interaction by users.
|
* Resolves creation of an interaction by users.
|
||||||
*
|
*
|
||||||
* @remark Only {@link ChatInputCommand} currently being resolved.
|
* @remark Only {@link ChatInputCommand} currently being resolved.
|
||||||
*
|
|
||||||
* @packageDocumentation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Events, Interaction } from "discord.js";
|
import { Events, Interaction } from "discord.js";
|
||||||
|
|
||||||
import Client from "$lib/client.js";
|
import Client from "$lib/client.js";
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
*
|
*
|
||||||
* @remarks Will push slash commands, set activity status,
|
* @remarks Will push slash commands, set activity status,
|
||||||
* and log bot's initials.
|
* and log bot's initials.
|
||||||
*
|
|
||||||
* @packageDocumentation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { generateDependencyReport } from "@discordjs/voice";
|
import { generateDependencyReport } from "@discordjs/voice";
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
* There a lot of speaking because it's as important as $lib.
|
* There a lot of speaking because it's as important as $lib.
|
||||||
*
|
*
|
||||||
* @packageDocumentation
|
* @packageDocumentation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const name = "core";
|
const name = "core";
|
||||||
|
|||||||
@@ -1,12 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* /clear
|
||||||
|
*
|
||||||
|
* Clears Player queue entirely.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with amount of tracks deleted.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* /connect
|
||||||
|
*
|
||||||
|
* Connects bot to the voice channel.
|
||||||
|
*
|
||||||
|
* Just like play but without query.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with Voice Channel bot connected to.
|
||||||
|
* - Requester does not connected to the Voice Channel.
|
||||||
|
*
|
||||||
|
* @deprecated Does not make sense.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,13 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* /filter <filter id>
|
||||||
|
*
|
||||||
|
* Toggles filter that will be applied to the playback.
|
||||||
|
* Such as nightcore, etc.
|
||||||
|
*
|
||||||
|
* If no filter id was provided clears them all.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with chosen filter status or filters being cleared.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import Filter from "../lib/filter.js";
|
import Filter from "../lib/filter.js";
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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 });
|
||||||
|
|
||||||
@@ -36,7 +53,7 @@ const data = new SlashCommandBuilder()
|
|||||||
option
|
option
|
||||||
.setName("filter")
|
.setName("filter")
|
||||||
.setDescription("Filter to apply.")
|
.setDescription("Filter to apply.")
|
||||||
.setChoices(...Object.values(Filter.FILTERS))
|
.setChoices(...Filter.filterChoices())
|
||||||
)
|
)
|
||||||
.setDMPermission(false);
|
.setDMPermission(false);
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* /info
|
||||||
|
*
|
||||||
|
* Replies with very stylish player info card.
|
||||||
|
*
|
||||||
|
* Playback status bar with title, thumbnail and duration.
|
||||||
|
* Queue length and duration.
|
||||||
|
* Applied filters.
|
||||||
|
* Current loop option.
|
||||||
|
* Player lifetime.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with info card.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* /insert (query) (position)
|
||||||
|
*
|
||||||
|
* Inserts specified track/album to the position specified.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with first added track info.
|
||||||
|
* - Player does not exists.
|
||||||
|
* - No track was added.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* /jump (query)
|
||||||
|
*
|
||||||
|
* Jumps to the specified Track from the queue.
|
||||||
|
* If number was provided - resolves as position at where queue position should be set.
|
||||||
|
* If string was provided - jumps to the most similar if terms of {@link ../lib/misc#LargestCommonSequence} Track title.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with selected track data.
|
||||||
|
* - Such track does not exists, though cannot be jumped to.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,13 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* /loop (option)
|
||||||
|
*
|
||||||
|
* Changes loop option.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* @see {@link ../lib/types} for LoopOption definition.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with new loop option.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { LoopOption } from "../lib/types.js";
|
import { LoopOption } from "../lib/types.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* /next
|
||||||
|
*
|
||||||
|
* Skips current track.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with confirmation of skip. (even there is nothing to skip)
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* /pause
|
||||||
|
*
|
||||||
|
* Toggles playback pause.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with setted state (paused, resumed).
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* /play <query>
|
||||||
|
*
|
||||||
|
* Starts up the Player.
|
||||||
|
* If query provided searches corresponding track/album and adds it to the queue end.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with first added track info.
|
||||||
|
* - Denies if requester is not connected to the Voice Channel.
|
||||||
|
* - No track was added, but player was set.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,3 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* /queue
|
||||||
|
*
|
||||||
|
* Replies interactive queue with current playing track at the top and 10 tracks from queue on each page.
|
||||||
|
* Interactiveness provided by buttons:
|
||||||
|
* - First page.
|
||||||
|
* - Previous page.
|
||||||
|
* - Next page.
|
||||||
|
* - Last page.
|
||||||
|
*
|
||||||
|
* Buttons live up to 30 seconds.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with interactive queue.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActionRowBuilder,
|
ActionRowBuilder,
|
||||||
ButtonBuilder,
|
ButtonBuilder,
|
||||||
@@ -10,11 +27,15 @@ import {
|
|||||||
|
|
||||||
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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* /remove (query)
|
||||||
|
*
|
||||||
|
* Removes Track from the queue.
|
||||||
|
* If number was provided - resolves as position at where deletion should occurr.
|
||||||
|
* If string was provided - removes most similar if terms of {@link ../lib/misc#LargestCommonSequence} Track title.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with removed track data.
|
||||||
|
* - Such track does not exists, though cannot be removed.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* /reshuffle
|
||||||
|
* Shuffles the queue, so real order is changed.
|
||||||
|
* DO NOT Confuse it with AUTO LoopOption.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with queue being reshuffled.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* /seek <hrs> <mins> <secs>
|
||||||
|
*
|
||||||
|
* Changes current Track playback duration to value given.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* If not stated - default value for all imputs is 0.
|
||||||
|
* Input resolution is defined by FFmpeg.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with previous and new playback duration.
|
||||||
|
* - Player does not exists.
|
||||||
|
* - No resource is currently playing.
|
||||||
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,12 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* /stop
|
||||||
|
*
|
||||||
|
* Destroys player of the Guild where it was emitted.
|
||||||
|
* Also disconnects user from Voice Channel Quetza was in.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with player being destroyed.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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,19 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* /volume (amount)
|
||||||
|
*
|
||||||
|
* Sets volume of {@link ../lib/player#Player | Player} in percent scale,
|
||||||
|
* clamping it in range defined in Player.
|
||||||
|
*
|
||||||
|
* Possible replies:
|
||||||
|
* - Success with new volume value.
|
||||||
|
* - Player does not exists.
|
||||||
|
*/
|
||||||
|
|
||||||
import { ChatInputCommandInteraction, 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 Music from "$mlib/music.js";
|
||||||
|
|
||||||
import replies from "../lib/replies.js";
|
import replies from "../lib/replies.js";
|
||||||
import { controller } from "../module.js";
|
|
||||||
|
|
||||||
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
|
async function execute(
|
||||||
|
_: Client,
|
||||||
|
interaction: ChatInputCommandInteraction,
|
||||||
|
controller: Music
|
||||||
|
): 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 });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const volume = interaction.options.getInteger("volume") ?? 100;
|
const volume = interaction.options.getInteger("volume", true);
|
||||||
|
|
||||||
const player = controller.get(interaction.guild, interaction.channel);
|
const player = controller.get(interaction.guild, interaction.channel);
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
*
|
*
|
||||||
* Monitors voice states of attended guilds.
|
* Monitors voice states of attended guilds.
|
||||||
* If Quetza happens to be alone in the Voice Channel - destroys guilds player and disconnects.
|
* If Quetza happens to be alone in the Voice Channel - destroys guilds player and disconnects.
|
||||||
*
|
|
||||||
* @packageDocumentation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BaseGuildVoiceChannel, User, VoiceState } from "discord.js";
|
import { BaseGuildVoiceChannel, User, VoiceState } from "discord.js";
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @see ../../../src/lib/error.ts
|
* @see ../../../src/lib/error.ts
|
||||||
*
|
|
||||||
* @packageDocumentation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QuetzaError from "$lib/error.js";
|
import QuetzaError from "$lib/error.js";
|
||||||
|
|||||||
@@ -52,6 +52,18 @@ export default class Filter {
|
|||||||
*/
|
*/
|
||||||
private switches_ = new Map<filterPreset, filterValue>();
|
private switches_ = new Map<filterPreset, filterValue>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns filters as Discord API Choices compatible array.
|
||||||
|
*
|
||||||
|
* @returns {@link Filter#FILTERS} as { name: FILTERS[key].name, value: key }.
|
||||||
|
*/
|
||||||
|
public static filterChoices(): { name: string; value: string }[] {
|
||||||
|
return Object.entries(Filter.FILTERS).map(([key, value]) => ({
|
||||||
|
name: value.name,
|
||||||
|
value: key
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts active {@link filterValue | filterValues} to array.
|
* Converts active {@link filterValue | filterValues} to array.
|
||||||
*
|
*
|
||||||
@@ -101,9 +113,9 @@ export default class Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts active filters to FFmpeg compatable argument.
|
* Converts active filters to FFmpeg compatible argument.
|
||||||
*
|
*
|
||||||
* @returns FFmpeg compatable argument representing active filters.
|
* @returns FFmpeg compatible argument representing active filters.
|
||||||
*/
|
*/
|
||||||
public toString(): string {
|
public toString(): string {
|
||||||
return this.toggled()
|
return this.toggled()
|
||||||
|
|||||||
+21
-18
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "quetza",
|
"name": "quetza",
|
||||||
"version": "2024.3.0",
|
"version": "2024.11.0",
|
||||||
"description": "Awesome Discord bot that performs various duties",
|
"description": "Awesome Discord bot that performs various duties",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/src/index.js",
|
"main": "./dist/src/index.js",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/unknowableshade/Quetza.git"
|
"url": "git+https://github.com/deytenit/Quetza.git"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Vladimir Eremin",
|
"name": "Vladimir Eremin",
|
||||||
@@ -23,32 +23,35 @@
|
|||||||
"url": "https://ermnvldmr.com"
|
"url": "https://ermnvldmr.com"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/unknowableshade/Quetza/issues"
|
"url": "https://github.com/deytenit/Quetza/issues"
|
||||||
},
|
},
|
||||||
"readme": "https://github.com/unknowableshade/Quetza#readme",
|
"readme": "https://github.com/deytenit/Quetza#readme",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "20.x.x",
|
"node": "22.x.x",
|
||||||
"npm": "*"
|
"npm": "*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/opus": "^0.9.0",
|
"@discordjs/opus": "^0.9.0",
|
||||||
"@discordjs/voice": "^0.16.1",
|
"@discordjs/voice": "^0.17.0",
|
||||||
"discord.js": "^14.14.1",
|
"discord.js": "^14.16.3",
|
||||||
"prism-media": "^1.3.5",
|
"prism-media": "^1.3.5",
|
||||||
"tweetnacl": "^1.0.3",
|
"tweetnacl": "^1.0.3",
|
||||||
"winston": "^3.11.0"
|
"winston": "^3.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.11.24",
|
"@eslint/eslintrc": "^3.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
"@eslint/js": "^9.14.0",
|
||||||
"@typescript-eslint/parser": "^7.1.0",
|
"@types/node": "^22.9.0",
|
||||||
"eslint": "^8.57.0",
|
"@typescript-eslint/eslint-plugin": "^8.13.0",
|
||||||
|
"@typescript-eslint/parser": "^8.13.0",
|
||||||
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-simple-import-sort": "^12.0.0",
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
"mocha": "^10.3.0",
|
"globals": "^15.12.0",
|
||||||
"prettier": "^3.2.5",
|
"mocha": "^10.8.2",
|
||||||
"tsc-alias": "^1.8.8",
|
"prettier": "^3.3.3",
|
||||||
"typescript": "^5.3.3"
|
"tsc-alias": "^1.8.10",
|
||||||
|
"typescript": "^5.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+2496
-1999
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
mkdir -p .git/hooks
|
||||||
|
|
||||||
|
HOOK_CONTENT="#!/bin/sh
|
||||||
|
pnpm run lint
|
||||||
|
if [ \$? -ne 0 ]; then
|
||||||
|
echo 'Pre-commit hook failed. Please fix the issues and commit again.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
"
|
||||||
|
|
||||||
|
echo "$HOOK_CONTENT" > .git/hooks/pre-commit
|
||||||
|
|
||||||
|
chmod +x .git/hooks/pre-commit
|
||||||
|
|
||||||
|
echo "Pre-commit hook installed successfully!"
|
||||||
Reference in new issue
Block a user