[discord.py] 1. 간단하게 봇과 놀기

chaejm55·2021년 3월 5일
2

디스코드봇

목록 보기
2/18
post-thumbnail

0. 들어가기 전에

봇이 태어나고 hello world를 말한지 3일, 이젠 아기가 엄마 아빠 하듯 새로운 말을 배울 시기가 된 것이다. 그래서 이번 포스팅에서는 간단하게 봇과 놀 수 있도록 random 라이브러리를 사용한 명령어를 작성할 것이다.

1. 주사위 굴리기

아마 파이썬을 조금이라도 맛 봤다면 다 작성 해봤을 코드이다. 바로 코드를 보자.

@bot.command()
async def dice(ctx):
    randnum = random.randint(1, 6)  # 1이상 6이하 랜덤 숫자를 뽑음
    await ctx.send(f'주사위 결과는 {randnum} 입니다.')

실행을 시켜보면 이렇게 주사위 숫자를 출력한다.

2. 광물캐기

주사위는 너무 밋밋한 면이 있다.
그래서 이번에는 random.choices()를 이용하여 로직이 아닌 공개된 가중치를 부여하여 광물을 캐는 미니게임을 작성한다. 한번에 5개를 캐서 결과를 출력하는 방식의 게임이다.

@bot.command()
async def mining(ctx):
    minerals = ['다이아몬드', '루비', '에메랄드', '자수정', '철', '석탄']
    weights = [1, 3, 6, 15, 25, 50]
    results = random.choices(minerals, weights=weights, k=5)  # 광물 5개를 가중치에 따라 뽑음
    await ctx.send(', '.join(results) + ' 광물들을 획득하였습니다.')

실행을 하면 가중치에따라 결과가 나오는 모습을 확인할 수 있다.

3. 가위바위보

봇에 의해 정해지는 결과를 보는 건 조금 심심한 느낌이다.
그래서 다음 명령어는 가위바위보를 작성해보겠다. 입력을 받아야 하기 때문에 함수형태가 약간 달라진다. 아래 코드를 통해 살펴보자.

@bot.command()
async def game(ctx, user: str):  # user:str로 !game 다음에 나오는 메시지를 받아줌
    rps_table = ['가위', '바위', '보']
    bot = random.choice(rps_table)
    result = rps_table.index(user) - rps_table.index(bot)  # 인덱스 비교로 결과 결정
    if result == 0:
        await ctx.send(f'{user} vs {bot}  비겼습니다.')
    elif result == 1 or result == -2:
        await ctx.send(f'{user} vs {bot}  유저가 이겼습니다.')
    else:
        await ctx.send(f'{user} vs {bot}  봇이 이겼습니다.')

함수의 파라미터가 한 개 더 추가된 것을 볼 수 있다. 여기서는 str형식이지만 용도에 따라 다른 type을 사용할 수도 있다.
실행결과를 살펴보자.

4. 발생할 법한 에러

1. CommandNotFound

명령어 함수 이름에 오타가 발생한게 아니라면 함수 위에 데코레이터인 @bot.command()가 빠진것이다.

2. ClientException: missing "ctx" parameter

모든 명령어 함수에는 첫 번째 파라미터로 ctx가 들어 가야한다. ctx는 context class를 의미하며 명령어 실행에 대한 많은 정보를 담고 있다.
아래는 공식 문서 자료이다.

3. MissingRequiredArgument

위의 가위바위보 명령어에서 만약 !game 만 입력한다면 이런 에러가 발생한다. 파라미터로 명령어 뒤의 메시지를 받아야 하는데 받지 못해서 생긴 에러이다. 이것은 catch문이 아닌 discord.py의 특수 구문으로 해결해야한다. 이는 추후 포스팅에서 다루겠다.

5. 마무리

hello world 밖에 모르는 갓난봇에서 이젠 서로 놀 수도 있는 봇으로 발전시켜 보았다. 다음 포스팅에는 예쁘게 메시지를 전달하는 Embed 기능에 대해서 알아보겠다.
github에 전체 코드를 올려두었다.

time.sleep(259200)
profile
여러가지를 시도하는 학생입니다

0개의 댓글