블로깅 챌린지 운영기 : 디스코드 챗봇 v2.0 유저용 명령어 구현

길하균(Lagun)·2023년 11월 11일

이전 : 디스코드 챗봇 v2.0 함수 및 기타설정

지금까지 디스코드에서 블로깅 챌린지를 운영하기 위한 디스코드 챗봇 구상과 관련된 글을 포스팅 했습니다. v1.0에 대한 내용은 아래 포스팅을 참고해주시면 감사하겠습니다.

🔥 블로깅 챌린지 운영기 : 디스코드 챗봇 구상하기
🔥 블로깅 챌린지 운영기 : 디스코드 챗봇 v1.0 만들기

v1.0에 대한 포스팅 이후에는 v2.0에 대해서 포스팅을 이어오고 있습니다. 앞의 포스팅은 아래 링크를 참고해주시면 감사하겠습니다. 직전 포스팅에서는 챗봇에서 사용할 함수들을 만들고 몇가지를 설정하기 위한 코드들을 살펴봤었습니다.

🔥 블로깅 챌린지 운영기 : 디스코드 챗봇 v2.0 구상하기
🔥 블로깅 챌린지 운영기 : 디스코드 챗봇 v2.0 함수 및 기타설정

이번 포스팅에서는 챗봇 v2.0에서 유저들이 사용할 명령어를 어떻게 구현했는지를 살펴보려 합니다. 코드의 완성도가 높지 않지만 기록 및 공유 차원에서 내용들을 정리하고 있습니다. 포스팅과 관련해서 피드백 할 부분이 있으시다면 댓글이나 ghaguniv@gmail.com으로 메일 주시면 감사하겠습니다.

Part VIII : 챗봇 v2.0 유저용 명렁어

i) 유저용 명령어 목차

코드를 살펴보기 전에 유저들이 사용할 명령어가 뭔지 다시 살펴보고 가려 합니다. v2.0에서 유저들이 이용하게 될 명령어는 아래와 같습니다. 각 명령어는 앞에 !를 붙여서 사용하도록 하였습니다.

  • 명령어 : 유저가 사용 가능한 명령어를 출력합니다.
  • 등록 : 자신의 블로그를 챌린지에 등록합니다.
  • 게시물 : 게시물을 챌린지에 공유합니다.
  • 회고록 : 월간회고록을 챌린지에 공유합니다.
  • 정보글 : 정보글을 챌린지에 공유합니다.
  • 점수 : 현재 유저의 점수를 알려줍니다.
  • 기록 : 현재까지의 유저 활동 기록을 알려줍니다.
  • 전체등수 : 현재 전체 등수를 알려줍니다.

이 목차 순서대로 각 기능을 구현한 코드들을 정리하도록 하겠습니다.

ii) 명령어

이 명령어는 유저가 사용 가능한 명령어 목록을 보여줍니다. 이전에는 dict 형식으로 관리하고 있었지만 사용하는 명령어가 많지 않기 때문에 직관적인 관리를 하고자 조금은 허접하게 만들어졌습니다.

if '!명령어' in content:
      await message.channel.send(
          '!뒤에 원하시는 명령어를 입력해주세요. \n 사용 가능한 명령어 : 등록, 게시물, 회고록, 정보글, 점수, 기록, 전체등수'
      )

content는 메시지 입력 이벤트가 발생했을 때 메시지에 들어있는 내용이 저장된 변수입니다. 만약 유저에 메시지로 !명령어를 보낸다면 해당 함수가 실행되게 됩니다. 보다시피 간단하게 str 형식으로 어떤 명령어들이 있는지를 나열하는 코드입니다.

iii) 등록

이 명령어는 챌린지 참가자가 자신이 사용할 블로그를 등록하는 명렁어입니다. 이 명령어를 먼저 실행해야 DB에 사용자의 정보가 생성되기 때문에 필수적인 코드입니다.

if '!등록' in content:
      if (id not in db["name_info"].keys()) & ('http' in content):
        name = message.author.global_name
        db["name_info"][id] = name

        now = datetime.datetime.now()
        week = str(int(now.strftime('%W')) - 36)
        today = now.strftime('%m.%d')

        act, url = content.split(" ")

        score = self.send_score(act)

        db['data_log'].append([week, today, id, name, act[1:], url, score])

        await message.channel.send(f'{name}님 환영합니다!🤗')
      elif 'http' not in content:
        await message.channel.send('✅ 명령어 뒤에 URL 주소를 같이 보내주세요.')

우선 if문을 통해서 기존에 등록한 유저인지를 확입합니다. 신규 유저라면 우선 name과 id를 name_info DB에 저장합니다. 그 다음 log 값을 남기기 위해 몇 가지 변수들을 저장합니다. 만약 블로그 주소가 명령어와 함께 전달되지 않은 경우 URL 주소를 함께 보내달라고 메시지를 보내게 됩니다.

iv) 게시물, 회고록, 정보글

이 세 명령어는 반영되는 점수만 다를뿐 기본적인 양식은 동일합니다. 따라서 앞선 포스팅에서 share_respond라는 이름으로 함수화 하였습니다. 자세한 내용은 이전 포스팅을 참고해주시기 바랍니다.

if '!게시물' in content:
      await message.channel.send((self.share_respond(message)))

if '!회고록' in content:
      await message.channel.send((self.share_respond(message)))

if '!정보글' in content:
      await message.channel.send((self.share_respond(message)))

앞에서 함수로 만든 덕분에 각 명령어를 구현하는 코드를 매우 단순하게 만들 수 있었습니다.

v) 점수

이 명령어는 명령어를 입력한 유저의 점수를 확인할 수 있는 명령어입니다. 현재 점수와 등수를 함께 알 수 있습니다.

if '!점수' in content:
      name = db['name_info'][id]

      data_log_pd = self.make_df()
      total_score = data_log_pd[data_log_pd['id'] == id]['score'].sum()
      rank_pd = data_log_pd.groupby('name')['score'].sum().sort_values(
          ascending=False)
      rank = list(rank_pd.index).index(name) + 1
      await message.channel.send(f'{name}님의 점수는 {total_score}점으로 {rank}등 입니다.')

우선 name_info DB에서 id를 통해서 name 값을 받아옵니다. 그 다음 data log들을 DataFrame 형식으로 변환한 다음 해당 유저의 활동 log들을 필터링합니다. 그 다음 score 열에 있는 데이터들을 모두 합쳐 total score를 구합니다. 등수의 경우 groupby를 통해서 구한 다음 정렬하는 식으로 구했습니다.

vi) 기록

이 명령어는 유저가 지금까지 활동한 내역을 확인할 수 있는 명령어입니다. 유저의 활동 케이스는 등록, 게시, 피드백, 회고, 정보, 반응입니다. 여기서 반응은 디스코드 메시지에 반응을 다는 것을 의미합니다.

if '!기록' in content:
      name = db['name_info'][id]
      act_list = ['등록', '게시', '피드백', '회고', '정보', '반응']

      data_log_pd = self.make_df()
      history = data_log_pd[data_log_pd['id'] == id].groupby(['act']).count()

      output_str = f'{name}님의 현재까지 기록은\n\n'
      for act in act_list:
        try:
          cnt = history.loc[act]['score']
          output_str += f'{act} : {cnt}회\n'

        except Exception as ex:
          output_str += f'{act} : 0회\n'
      output_str += f'\n입니다! 화이팅  😀😀😀'
      await message.channel.send(output_str)

크게 어려운 내용은 없으리라 생각합니다. data log를 DataFrame으로 변환하고 groupby를 이용해서 활동별 활동 횟수를 계산하였습니다. 여러번 메시지가 전송되는 상황을 방지하기 위해 output_str이라는 str 변수에 저장한 다음 한번에 전송하도록 구성했습니다.

vii) 전체등수

이 명령어는 현재 참가자들의 전체등수를 확인할 수 있는 명령어입니다. 위에서 살펴본 점수 명령어의 작동방식과 같이 data log를 DataFrame으로 변환한 다음 각자의 total score과 rank를 반환하도록 했습니다. 여러번 메시지가 전송되는 것을 막기 위해서 str문을 합친 다음 한번에 메시지로 보내도록 코드를 작성했습니다.

if '!전체등수' in content:
      data_log_pd = self.make_df()
      rank_pd = data_log_pd.groupby('name')['score'].sum().sort_values(
          ascending=False)

      output_str = f'현재 전체등수는\n\n'
      for name in rank_pd.index:
        rank = list(rank_pd.index).index(name) + 1
        total_score = data_log_pd[data_log_pd['name'] == name]['score'].sum()

        output_str += f'{rank}등 : {total_score}점, {name}님\n'
      output_str += f'\n입니다! 다들 화이팅  😀😀😀'
      await message.channel.send(output_str)

다음 : 디스코드 챗봇 v2.0 관리자용 명령어 구현

다음 포스팅에서는 챗봇 v2.0의 관리자가 사용하는 명령어를 구현하고자 합니다. 이번 포스팅과 마찬가지로 각 기능들을 어떻게 코드로 구현했는지를 살펴보려 합니다.

profile
AI, 빅데이터를 배우기 위해 항해 중

0개의 댓글