Discord의 활동을 Slack의 Status에 반영하는 이야기

개요



Discord 활동


Slack의 Status에 반영했다.


누득이야 이거…

ぢ s 자 rd. py



이번에는 Discord API의 Python 라이브러리인 discord.py를 이용한다.
  • 공식 참조

  • 참고



    Token의 취득등은 위대한 선구자 분들이 이미 기사를 쓰고 있으므로 그쪽을 참조해 주었으면 한다.
  • 파이썬에서 실용 Discord Bot (discordpy 해설)

  • 구현



    기본적으로는 스스로 지은 discord 서버에 bot를 두고, 그 bot가 서버 멤버의 액티비티를 취득하는 형태가 된다.
    ※더 좋은 방법이 있으면 가르쳐 주었으면 한다.

    discord의 각 이벤트 핸들러에 처리를 기술해 가게 되지만,
    이번에는
  • bot 시작시
  • 회원 프로필 업데이트 시

  • 에 활동을 얻기로 한다.

    각 이벤트 핸들러는 다음과 같습니다.
    # bot起動時
    @client.event
    async def on_ready():
         ...
    
    # メンバーのプロフィール更新時
    @client.event
    async def on_member_update(before, after):
         ...
    

    활동 얻기



    공식 참조를 읽는 한 discord.Member에 사용자의 활동이 있다는 것.

    즉 각 이벤트 핸들러로 Member 를 취득할 수 있으면 된다.
    그래서 Client.get_all_members()를 사용하기로 결정했습니다.

    그러나 서버에 참여하는 모든 회원을 얻기 때문에,discord.util 함수를 사용하여 지정한 멤버의 Member 만 가져옵니다.
    member = discord.utils.get(client.get_all_members(), name='Discord上の名前')
    if member.activity != None:
        print(member.activity.name)
    

    KovaaK를 시작한 경우,


    실행 결과
    KovaaK 2.0: The Meta
    

    된다.

    액티비티 획득 시 주의사항


    discord.Member.activity에는 다양한 활동이 있으며,
    게임의 경우는 위에서 잘 되지만, Discord에 등록되어 있지 않은 게임이나 Spotify 재생중등의 액티비티는 어쩌면 잘 가지 않을지도 모른다.

    자세한 내용은 아래를 참조하십시오.
  • discord.Member.activity
  • discord.BaseActivity

  • 일단 BaseActivity 의 멤버와 Spotify 는 모두 name 를 가지고 있으니까 괜찮을까…

    Slack 상태 재작성



    Slack API users.profile.set에 post 요청을 던지면 할 수 있습니다.

  • users.profile.set
    Tester 탭에서 다양한 요청을 테스트 할 수 있습니다!

  • 기본적으로는 name 에 갱신하고 싶은 프로파일명, value 에 프로파일의 내용을 건네주는 것으로 실현 가능.
    response = requests.post('https://slack.com/api/users.profile.set', 
                           data={'token': 'Slackのトークン',
                           'name': 'status_text',
                           'value': 'test',
                           'user': 'SlackのユーザID', 
                           'pretty': '1'})
    

    이것을 던지면,

    이런 느낌이 된다.

    이것들을 정리하면 이런 느낌



    ※Python 초보자의 코드이므로 보기 흉한 점 있으면 죄송합니다…
    import discord
    import requests
    
    DISCORD_TOKEN = '******'
    SLACK_TOKEN = '******'
    
    game = None
    
    # Discordに接続するためのオブジェクトを生成
    client = discord.Client()
    
    # memberからアクティビティの名前を取得して変数にセット
    def set_game_name(member):
        global game
        if member.activity != None:
            game = member.activity.name + 'をプレイ中'
        else:
            game = 'Not Playing game.'
    
    # Slackのstatusを更新
    def post_slack_status():
        global game
        response = request.post('https://slack.com/api/users.profile.set',
                                data={
                                     'token': SLACK_TOKEN,
                                     'profile': '{ "status_text":"' + game + '",
                                                   "status_emoji": ":nick:" }',
                                     'user': '*****',
                                     'pretty': '1'})
    
    # bot起動時
    @client.event
    async def on_ready():
        member = discord.utils.get(client.get_all_members(), name='*****')
        set_game_name(member)
        post_slack_status()
    
    # メンバーのプロフィール更新時
    @client.event
    async def on_member_update(befor, after):
        set_game_name(after)
        post_slack_status()
    
    # bot起動
    client.run(DISCORD_TOKEN)
    

    응? 간단하죠?

    친구 A 「n분 경과도 낼 수 있으면 좋다」



    자세한 실장 방법은 나중에 신경이 쓰이면 기재합니다…
    간단히 설명하면
  • post_slack_status() 의 요청을 1분마다 돌리는 루프 내에서 던진다.
  • post_slack_status() 를 쓰레드화해 다른 thread로서 실행.
  • on_member_update(befor, after) 가 실행되면 루프 플래그를 False 로 설정하여 스레드를 종료하고 활동을 다시 가져온 후 다시 post_slack_status() 의 스레드를 실행합니다.

  • 이런 느낌.
    (쓰고 생각했지만, on_member_update() 안에서 스레드의 종료를 기다리고 있을 때, 또 한번 on_member_update() 가 달리면 어떻게 될까……. 이벤트 핸들러 힘들다……….)

    추가 (2020/05/07)


    on_member_update() 의 사양 이해 부족이 있었다.
    on_member_update()

    회원의 다음 사항이 업데이트될 때 실행되므로,
    activity가 업데이트되었을 때만 달리도록 하자!
  • 상태
  • activity
  • 닉네임
  • 직책
  • 좋은 웹페이지 즐겨찾기