Add skip current command

This commit is contained in:
kimpure 2026-02-23 11:21:48 +00:00
parent bc4cc2b6b1
commit dd16ffe945
2 changed files with 45 additions and 2 deletions

View file

@ -0,0 +1,25 @@
import { ChatInputCommandInteraction, MessageFlags, SlashCommandBuilder } from "discord.js";
import { defineCommand } from "../command";
import { skipCurrentVoice } from "../tts";
export default defineCommand(
new SlashCommandBuilder()
.setName("스킵")
.setDescription("실행중인 보이스를 건너뜁니다"),
async (interaction: ChatInputCommandInteraction): Promise<any> => {
await interaction.deferReply({
flags: [MessageFlags.Ephemeral]
});
if (!interaction.guild) {
await interaction.editReply("서버에서만 사용할 수 있어요");
return;
}
if (await skipCurrentVoice(interaction.guild)) {
await interaction.editReply("스킵 되었어요");
} else {
await interaction.editReply("실행중인 보이스가 없어요");
}
}
)

View file

@ -1,4 +1,4 @@
import { AudioPlayerStatus, AudioResource, createAudioPlayer, VoiceConnection } from "@discordjs/voice"; import { AudioPlayer, AudioPlayerStatus, AudioResource, createAudioPlayer, VoiceConnection } from "@discordjs/voice";
import { Voice } from "../db/generated/prisma/enums"; import { Voice } from "../db/generated/prisma/enums";
import TTSTypecastModel from "../tts/typecast"; import TTSTypecastModel from "../tts/typecast";
import TTSPapagoModel from "../tts/papago"; import TTSPapagoModel from "../tts/papago";
@ -35,6 +35,7 @@ export async function createVoiceBuffer(voice: Voice, text: string): Promise<Buf
class VoiceQueue { class VoiceQueue {
private connection: VoiceConnection; private connection: VoiceConnection;
private list: AudioResource[]; private list: AudioResource[];
private currentPlayer?: AudioPlayer;
constructor(connection: VoiceConnection) { constructor(connection: VoiceConnection) {
this.connection = connection; this.connection = connection;
this.list = []; this.list = [];
@ -44,7 +45,7 @@ class VoiceQueue {
} }
private play() { private play() {
if (!this.list[0]) return; if (!this.list[0]) return;
const player = createAudioPlayer(); const player = this.currentPlayer = createAudioPlayer();
this.connection.subscribe(player); this.connection.subscribe(player);
player.once(AudioPlayerStatus.Idle, this.next.bind(this)); player.once(AudioPlayerStatus.Idle, this.next.bind(this));
player.play(this.list[0]); player.play(this.list[0]);
@ -57,9 +58,13 @@ class VoiceQueue {
} }
} }
public next() { public next() {
this.currentPlayer?.removeAllListeners(AudioPlayerStatus.Idle);
this.list.shift(); this.list.shift();
this.play(); this.play();
} }
public hasNext(): boolean {
return !!this.list[0];
}
} }
export async function playVoice(guild: Guild, profile: DiscordUserProfile, text: string) { export async function playVoice(guild: Guild, profile: DiscordUserProfile, text: string) {
@ -90,3 +95,16 @@ export async function playVoice(guild: Guild, profile: DiscordUserProfile, text:
throw new Error(err as any); throw new Error(err as any);
} }
} }
export async function skipCurrentVoice(guild: Guild): Promise<boolean> {
let connection = await getOrCreateVoiceConnection(guild);
if (!connection)
throw new Error("Yaeju is not joined VoiceChat");
const vqueue = VoiceQueue.fromConnection(connection);
if (vqueue.hasNext()) {
vqueue.next();
return true;
}
return false;
}