본문 바로가기

개발일지/디스코드 봇

디스코드 봇 개발 일지 2022-12-29 - Commands

 

※ 작성자가 작성한 내용이 일부 틀릴 수도 있음 주의

※ 작성자가 코드 쓰다가 계속 코드 수정함 주의

 

* 참고 사이트

https://2island.tistory.com/19

 

디스코드 봇 만들기 (5) - 사용할 수 있는 이벤트 알아보기 (1)

앞의 1,2,3,4 편에서는 디스코드 봇을 세팅하고, 구동시켜봤다면 이번 편에서는 어떤 활용할만한 이벤트들이 있는지 알아볼 것이다. 1. 봇의 상태 설정하기 처음 봇을 활성화시키면 아래와 같이

2island.tistory.com

 

일단 기본적인 이벤트를 알아보기에는 이분의 글이 되게 깔끔했다고 생각한다.

 

그리고 또한

 

https://discordpy.readthedocs.io/en/stable/api.html#

 

API Reference

Loads the libopus shared library for use with voice. If this function is not called then the library uses the function ctypes.util.find_library() and then loads that one if available. Not loading a library and attempting to use PCM based AudioSources will

discordpy.readthedocs.io

 

앞으로 웬만하면 여기를 메인으로 참고하여 진행할 것 같다.

 

 

 

일단 다른 분들의 예시 코드를 보면 대체로 이 bot.command 데코레이터로 시작하는 경우가 많았다.

 

그래서 얘네들부터 뜯어보고자 한다. 정확히는 어떻게 쓰면 되는지 알아보자.

 

 


 

@bot.command()

 

 

사실 따지고 보면 bot.command 가 아니라 commands.Bot.add_command() 다.

 

대체로 "bot"을 쓴 코드가 많은 것은

 

bot = commands.Bot(command_prefix=':',intents=discord.Intents.all())

 

이걸 먼저 썼기 때문이다. 사실 내가 까먹을 것 같아서 적어봤다.

 

그리고 이런 식으로 쓰는게 훨씬 편하다. 항상 이용해주자.

 

 

아 참고로 message_content intent 를 활성화해야 함수가 작동한다고 한다.

 

이전 글에서 디코 봇 설정에서 Privileged Intent 활성화해준 그것과 관련된 건갑다.

 

 

 

 

예시 코드 뜯어보기 (1)

 

@bot.command()
async def test(message):
    await message.channel.send('Hello?')
    print(f'Reply for "test" -> "Hello?"')

 

내가 적당히 고쳐 쓴 함수 하나다.

 

:(test    ( ":(" 를 접두사로 지정했다. )    를 쓰면 "Hello?" 라고 대답하고 콘솔에 로그를 남기는 함수다.

 

함수에 들어가는 Variable 개수가 하나일 때, 이 Variable은 대충 메시지의 위치 정도로 생각하면 되겠다.

 

그래서 "메시지가 온 채널에 "Hello?" 라고 보낸다." 정도로 이해하면 되겠다.

 

 

 

근데 우리가 다른 봇들을 사용하다 보면 ":abcd xyz" 와 같이 띄어쓰기로 들어가는 경우가 있다.

 

다음 코드를 보자.

 

 

@bot.command()
async def 주사위(message,var1):
    if(var1=="help") :
        await message.channel.send('Commands\n:주사위 N - 1부터 N까지 중 무작위 숫자 하나를 출력해줍니다.')
    elif(var1.isdecimal()) :
        if int(var1) < 1 :
            await message.channel.send('Warning!! 주사위 값의 범위가 정상적이지 않습니다.')
        else :
            n = random.randrange(1,int(var1)+1)
            await message.channel.send(f'주사위 결과 : {n}')
    else :
        await message.channel.send(f'Warning!! ":주사위 {var1}"에 해당하는 명령은 존재하지 않습니다.')
    print(f'Reply for "주사위 {var1}"')

 

간단하게 주사위 굴리는 명령어(함수)를 만든 것이다.

 

:(주사위 help - 명령어 쓰는 법 출력

:(주사위 (N) - 1부터 N까지의 값 중에 무작위 하나 출력 (약간의 범위 오류를 걸러냄, 소수의 경우는 귀찮아서 안 넣음)

존재하지 않는 명령 - 해당 명령이 존재하지 않는다는 오류 메시지 출력

 

이해하는데 어려움은 없을 것이라 생각한다.

 

 

함수를 보면 위에서처럼 "message" 뿐만 아니라, "var1" 이라는 변수도 읽는데,

 

이 "var1" 은 명령어 뒤에 추가한 변수를 읽어들인다.

 

그래서 var1.isdecimal()에 의해 정상적인 주사위 값에 대해 무작위 숫자를 출력할 수 있게 된다.

 

 

다만 변수가 2개 이상 들어오면, 맨 처음에 있는 변수 하나만 이용된다.

 

 

 

 

하지만 변수가 1개 뿐만 아닌 0개 또는 2개 이상으로 갯수에 따라 실행을 달리 할 경우, 코드를 수정해줘야 한다.

 

@bot.command()
async def 주사위(message,*vars):
    
    if(len(vars)==0):
        await message.channel.send(Dicehelp)
        
    elif(len(vars)==1):
        if(vars[0]=="help"):
            await message.channel.send(Dicehelp)
        elif(vars[0].isdecimal() and int(vars[0]) > 0):
            n = random.randrange(1,int(vars[0])+1)
            await message.channel.send(f'주사위 결과 : {n}')

    reply = ' '.join(vars)
    print(f'Reply for "주사위 {reply}')

 

오류 메시지를 출력하니 디코 채널이 너무 더러워져서 오류 메시지는 출력하지 않기로 했다.

 

다음과 같이 *(변수) 로 변수를 tuple 형태로 받아주면, 변수 개수에 따라 명령을 달리할 수 있다.

 

변수가 없을 경우 사용법을 출력하도록 했다(Dicehelp는 명령어 사용법을 담은 string이다).

 

 

명령이 잘못되었을 경우, 오류 메시지를 출력하지 않고 로그만 남기는 것이 깔끔해보였다.

 

잘 되는 것을 확인할 수 있다.

 

 

 

아 참고로

 

@bot.command()
async def 주사위(message,*,vars):

 

이렇게 해주면 ":(주사위 " 뒤의 모든 값들(공백 포함)을 "vars"가 받는다.

 

vars만을 그대로 send 하면 예를 들어 ":(주사위 나는 주사위다" 에 대해 "나는 주사위다" 하고 대답한다.

 

귀찮아서 vars의 형식을 찾아보지는 않았다. string형이 아닐까...??

 

 

 

 

 

728x90