디스코드 TTS봇 만들기

U U·2023년 12월 14일
1

[ 사이드 ]

목록 보기
3/4
post-thumbnail

여느때와 같이 백수 생활을 즐기다가 클라이언트(친구)가 요즘 TTS봇은 예의가 없다고 한다.
뭔 소리인가 했더니 우리 서버는 TTS봇 사용하고 있는데 얘가 일정 시간 메세지가 올라오지 않으면 음성채널에서 나간다. 그런데 얘가 말도 없이 나간다고 나갈 땐 인사하고 나가야하지 않겠냐는 말이었다.

그런가?

그리하여 나갈 때 인사하고 나가는 TTS봇을 만들기로 했다

Github

전체 소스코드는 하단 링크 참고
https://github.com/HYK-Nov/polite-tts-bot-js


지난 글과 같이 Discord.js를 사용했다.
그리고 Typescript로 코드 작성하였으나 Javascript랑 크게 다르진 않으니 보는데는 문제 없다.

[ 지난 이야기 ] 디스코드 알림봇 만들기(진)

일단 초반부는 위 글과 얼추 비슷하니 설정까지는 위에서 작성한 것과 동일하게 하면 된다.

설정

npm install google-tts-api

추가로 google-tts를 설치해주자

코드

const client = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.MessageContent,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.GuildVoiceStates,
    ],
});

client.login(BOT_TOKEN);

클라이언트를 설정해주자. TTS봇은 메세지를 읽어줘야하기 때문에 Message 기능을 넣어주어야 한다.

let voiceConnection: VoiceConnection;
const audioPlayer = createAudioPlayer();

let ttsTimeout: NodeJS.Timeout;
let disconnectTimeout: NodeJS.Timeout;

const closeTTSUrl = googleTTS.getAudioUrl('저는 이만 가볼게요', {lang: 'ko'});
const closeAudioResource = createAudioResource(closeTTSUrl);

위와 같이 작성해준다. 각각 무슨 역할인지는 아래 참고

  • voiceConnection: 음성채널 연결 관련
  • audioPlayer: 오디오 재생 플레이어
  • ttsTimeout: 퇴장 인사 재생 타이밍
  • disconnectTimeout: 음성채널 연결 해제 타이밍
  • closeTTSUrl: TTS 음성 생성
  • closeAudioResource: audioPlayer에 집어넣을 리소스 생성
client.on('messageCreate', (msg) => {
	if (msg.author.bot) return;
})

메세지를 수신해야하기 때문에 메세지가 새로 생길 때 이벤트를 만들어준다.
그리고 혹여나 다른 봇이 날린 메세지를 읽어주면 안되니 작성자가 봇이면 바로 이벤트를 끝내버린다

const ttsUrl = googleTTS.getAudioUrl(msg.content, {lang: 'ko', slow: false});
const audioResource = createAudioResource(ttsUrl);

Discord.js Voice 모듈은 놀랍게도 googleTTS로 만들어진 url을 그냥 집어넣으면 재생이 된다. url을 audioResource에 집어넣어준다.

voiceConnection = joinVoiceChannel({
	channelId: VOICE_CHANNEL_ID,
	guildId: GUILD_ID,
	adapterCreator: msg.guild?.voiceAdapterCreator!,
});

voiceConnection.subscribe(audioPlayer);

audioPlayer.play(audioResource);

voiceConnection으로 음성채널에 들어가주고 audioPlayer에 TTS음성을 재생시켜준다.

clearTimeout(ttsTimeout);
clearTimeout(disconnectTimeout);

ttsTimeout = setTimeout(() => audioPlayer.play(closeAudioResource), 12_000);
disconnectTimeout = setTimeout(() => voiceConnection.destroy(), 15_000);

마지막으로 음성채널에서 나갈 타이밍을 설정해준다.

위에서 미리 timeout을 만들어준 이유가 clearTimeout을 하기 위함이었다. 만약 setTimeout이 설정된 상태인데 새로운 메세지가 올라오면 timeout을 취소한다.
그리고 다시 timeout을 설정하고 일정 시간동안 메세지가 올라오지 않으면 미리 만들어두었던 퇴장 인사를 재생하고 나간다.

profile
언제까지 할 건데

0개의 댓글