지금까지 내용 커밋

This commit is contained in:
2026-04-08 12:59:45 +09:00
commit b0dae31cb9
68 changed files with 12083 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
import { Connectors, LoadType, Shoukaku } from "shoukaku";
import { Client } from "discord.js";
import { GuildPlayer } from "./GuildPlayer";
import { Config } from "../utils/Config";
import { Logger } from "../utils/Logger";
import { parseLink } from "../utils/music/Url";
import { shuffle } from "../utils/Shuffle";
import { Spotify } from "../utils/api/Spotify";
import { YoutubeMusic } from "../utils/api/YoutubeMusic";
export class LavalinkManager {
public shoukaku: Shoukaku;
private players: Map<string, GuildPlayer> = new Map();
constructor(readonly client: Client) {
this.shoukaku = new Shoukaku(new Connectors.DiscordJS(client), [{
name: "tkrmagid-Lavalink-Server",
url: `${Config.lavalink.host}:${Config.lavalink.port}`,
auth: Config.lavalink.pw,
secure: false,
}], {
moveOnDisconnect: true,
reconnectTries: 3,
});
this.shoukaku.on("ready", (name) => {
Logger.ready(`[LavalinkManager] 노드 [${name}] 연결 완료!`);
});
this.shoukaku.on("error", (name, err) => {
Logger.error(`[LavalinkManager] 노드 [${name}] 에러: ${String(err)}`);
});
}
getPlayer(guildId: string) {
return this.players.get(guildId);
}
addPlayer(guildId: string, player: GuildPlayer) {
this.players.set(guildId, player);
}
delPlayer(guildId: string) {
this.players.delete(guildId);
}
async search(guildId: string, query: string, userId: string, player?: GuildPlayer) {
const node = this.shoukaku.options.nodeResolver(this.shoukaku.nodes);
if (!node) {
this.delPlayer(guildId);
throw new ReferenceError(`[LavalinkManager] lavalink node is missing`);
}
player = player ?? this.getPlayer(guildId);
if (!player) return;
const { isUrl, text, flags } = parseLink(query.trim());
let searchText = isUrl ? text : (await Spotify.getSearchUrl(text)) ?? (await YoutubeMusic.getSearchUrl(text)) ?? `ytsearch:${text}`;
if (flags.has('y')) searchText = (await YoutubeMusic.getSearchUrl(text)) ?? `ytsearch:${text}`;
if (searchText.startsWith("ytsearch") && !flags.has('o')) searchText += " Topic";
const result = await node.rest.resolve(searchText);
if (!result || result.loadType === LoadType.EMPTY || result.loadType === LoadType.ERROR) {
if (result?.loadType === LoadType.ERROR) Logger.error(`[LavalinkManager] loadtype ERROR: ${result.data.message}`);
// 노래 못찾았을때
player.errMsg(`노래를 찾을수 없습니다.`);
return;
}
if (result.loadType === LoadType.PLAYLIST) {
player.addTracks(
flags?.has("s") ? shuffle(result.data.tracks) : result.data.tracks,
userId
);
return;
}
if (result.loadType === LoadType.TRACK) {
player.addTrack(result.data, userId);
return;
}
if (result.loadType === LoadType.SEARCH) {
if (result.data.length === 0) {
player.errMsg(`노래를 찾을수 없습니다.`);
return;
}
player.addTrack(result.data[0], userId);
return;
}
}
}