팁과 강좌

음성채널 입장 유저를 알려주는 디스코드 봇 만들어 보기

인심좋은 2022. 12. 6. 06:08

이건 강좌랄건 없다. 그저 필요에 의해 검색해서 만들어 봤을 뿐이다.

 

굉장히 허접하니 감안하고 보시기 바랍니다.

저는 코딩을 배운적도 없고, 필요에 의해 구글링하고 네이버링해서 짜집기로 만들었습니다.

 

오딘이라는 게임을 하면서 디스코드를 하는데, 음성채널을 할 경우 40명 안팎의 사람들이 음성 채널에 들어왔다 나갔다한다. 오더를 하거나 운영진들은 누가 들어오고 나가는지 알고 싶어하는데, 들어오고 나가는 소리만 있지 누가 왔다가는지는 모르기 때문에 이걸 봇을 만들어서 음성채널 인원 출입 시 일반 채팅 채널에 알리도록 하는 목적으로 만들게 되었다.

 

사용언어는 파이썬

자바, C++ 등 다양한 언어로 만드는게 가능하니 본인이 편한 언어로 검색해서 제작에 입문하면 될 것 같다.

내가 찾을때는 자바가 외국 사이트에 많았다.

 

사용한 도구는 Visual Studio Code 다.

이유는 내가 이것저것 건드리고 시도할때 많이 접한게 VS Code라서다. 도구는 많이 있으니, 본인이 편한  도구를 선정하면 될 것이다.

 

봇을 만들고, 서버에 넣는건 검색 사이트에 "디스코드 봇 만들기" 로 검색하면 처음 셋팅하는 내용이 정말 많다.

 

다른건 그대로 따라하면 되는데 내가 검색해서 제작하면서 골치 아팠던게

뒤에 설명하겠지만 봇 설정 중에 "Privileged Gateway Intents" 부분 설정이다. 단순히 제작으로 검색하면 잘 나오지 않는다. 옛날 자료들이 대부분이 그런데 최근 자료로 찾아보길 바란다. 반드시 설정해야하는 부분이다.

일종의 개발 의도가 무엇이냐 묻는건데, 솔직히 초보라서 상세한 내용을 지금은 모르겠다. 봇 기능을 나중에 업그레이드하면서 좀 더 파고들어야할 것 같다. 일단은 난 1개 서버에 대한 봇이라 그냥 활성화하면 되서 넘어갔다.

맞는지는 모르겠지만 첫번째는 서버 내 변동 사항을 받는 봇 제작, 두번째는 서버 멤버에 대한 봇, 세번째는 채팅 관련 봇 이라는 뜻 같음.

난 3개를 다 활성화 했는데, 2,3번째만 활성화 했더니 코드가 에러를 쳐서 그냥 셋 다 활성화 했다. ㅠ_ㅠ

 

이제 본격 봇 코딩에 돌입

 

일단 관련 모듈 설치부터 한다. discord.py 와 asyncio.py 설치

 

import discord, asyncio

 

사용하기 위해 설치 한 것이니, 불러온다.

 

d_intents = discord.Intents.all()
client = discord.Client(intents=d_intents)

 

앞서 언급했던 Intent 설정 부분이다.

난 전부 활성화 했기 때문에 Intents.all 설정 했다.

그리고 d_intents 까진 굳이 변수 넣어줄 필요는 없을 것 같은데, 일단 나중에 확장할때 반복 안하기 위해 설정했다.

client 선언도 마찬가지다. 길어서 반복하기 귀찮다.

 

다음은 실행해서 봇이 기동 됐을때 설정을 위한 부분이다.

 

@client.event
async def on_ready(): #봇 실행시 한번 실행됨
    print("봇 기동 시작")
    await client.change_presence(status=discord.Status.online, activity=discord.Game("음성채널 감지"))

 

주석 달은바와 같이 봇 실행 시에 단 한번 설정되는 부분이다.

print 구문은 VS code의 터미널에만 출력된다. 잘 안되면 테스트 구동을 여러번하는데 제대로 입력이 됐는지 확인하기 위함이다.

 

change_presence 는 봇의 상태를 바꿔주는 내용이다.

status 에서 online으로 설정해주고, activity 에서는 봇이 뭐하고 있는지를 기록한다.

(디스코드 보면 누가 무슨 게임하고 있는지 예를 들어 "Overwatch2 중" 이런거다. 저렇게 쓰면 봇 이름 밑에 "음성채널 감지 중" 이라고 뜬다.)

이렇게 해주는 기능이다.

 

-----------  조건문 수정하였습니다 --------------

@client.event
async def on_voice_state_update(member,before,after):
    ch=client.get_channel(채팅을 입력할 채널ID)
    if not before.channel and after.channel:
        print(member.display_name,'joined',after.channel,before.channel)
        await ch.send("{} 님이 {} 에 입장하셨습니다.".format(member.display_name,after.channel))
    if not after.channel and before.channel:
        print(member.display_name,'leaved',before.channel)
        await ch.send("{} 님이 {} 에서 퇴장하셨습니다.".format(member.display_name,before.channel))

이제 진짜로 음성채널 출입하는걸 감지하는 기능 구현이다.

 

on_voice_state_update 음성채널에 대한 변동 사항을 감지하는데 서버 내 멤버의 음성채널 위치의 변화를 감지한다.

내가 저렇게 언급한 이유가 다음에 연결되는 IF 구문 때문인데

이 명령어는 보이스 채널의 변동을 감지하는게 아니라 서버 멤버의 스테이터스 변화를 감지한다.

before는 이벤트가 생기기 전 내가 있던 보이스 채널의 상태를 반환한다. 마이크 음소거 혹은 듣기 음소거, 입장 채널 ID 등등의 다양한 정보가 입력된다.

after는 이벤트가 생긴 후 보이스 채널의 상태를 반환한다.

내가 쓰는건 이중에 Channel 에 대한 정보이다.

 

당연히 나는 보이스 채널에 안 들어가 있다가 진입했기 때문에 before.channel 은 None 이며, after.channel에는 진입한 채널명이 들어가 있을 것이다.

 

if not ~ and ~ 이부분은 구글 검색으로 입력한건데

이해를 제대로 하지 못했다. (아시는 분은 설명 부탁요.ㅠㅠ)

 

------- 수정한 이유 ---------

내가 실수한 부분이 있었다.

첫 글 작성 시 조건문 나가는걸 else로 설정했는데 이렇게되면 굳이 채널 변화가 없어도 마이크 끄고 킨것만으로도 else 구문이 작동하여 퇴장했다는 알림을 띄워 버린다.

그래서 조건문을 추가하여 퇴장만 따로 감지하도록 하였다.

-----------------------------------

 

ch 에는 봇이 출입을 기록할 채팅방을 저장했다.

채팅방 ID는 디스코드 개발자 모드에서 채팅방에 우클릭하면 ID를 복사할 수 있다.

 

print 구문은 역시나 터미널에서 확인하기 위함이다.

 

await를 통해 봇에게 지시하는데 앞서 지정한 채팅방에 send 하라고 지시한다.

누구를 지정할때 그냥 member로 하면 프로필을 출력해버린다. 게임 디스코드는 그 게임 닉네임으로 활동하는데 프로필로 출력하면 안되서 display_name 구문으로 닉네임을 출력하도록 했다.

 

출력은 첫 {} 가 유저 닉네임 두번째 {} 가 입장 채널 명이다.

 

만약 유저가 채널을 나간다면, after가 None이 되어 else에 해당되기 때문에

퇴장 문구를 출력한다.

 

마무리로 봇을 실행시키는 명령어를 입력한다.

 

client.run('봇 토큰 입력')

 

봇 토큰은 알다시피 고유 번호로 함부로 노출되서는 안된다.

 

결과는

이런식으로 봇이 채팅방에 글을 쓴다.

 

참고로 VS Code를 실행하면 계속 실행상태가 되어 봇이 작동하지만, VS Code를 끄면 봇은 멈추게 된다.

즉, 봇을 항시 대기 상태로 놓고 싶다면, 컴퓨터에 코드 작동 상태를 유지해야한다는 것이다.

 

그게 아니면 NAS 같은 서버에 코드를 구동시켜서 실행 상태를 유지하면 되는게 이 방법은 아직 쓰지 않았다.

 

난 디코를 사용할때만 VS Code로 봇 활성화해서 사용할 예정

 

PS) 코드 테스트 할때 코드 수정하기 위해 VS Code를 끄지 않고 정지하는 방법은 터미널에서 Ctrl+C 를 입력하면 종료되니, 굳이 껐다켰다 하지 말자.

 

이건 내가 필요에 의해 찾아서 짜집기로 넣은거라 많은 부분이 비효율적이고 잘못되었을 수 있습니다.

 

그러므로 비난보다는 개선 의견을 주시면 감사하겠습니다.

반응형