LoginSignup
11
11

More than 3 years have passed since last update.

クラスDiscordに課題管理Botを導入した話

Last updated at Posted at 2020-05-18

こんばんは。りーぜんとです。

題名の通りです。経緯↓

流行りのオンライン授業が弊学でも始まりました。草ですね。

もはやオンライン授業の代名詞となっているZoomではなくMicrosoftのTeamsというものを使って授業が行われています。このTeams、学生側は課題が絶望的に管理しづらいです。(個人の意見)

じゃあクラスのDiscordに管理用Bot作って入れれば良いじゃん。(名案)

他の高校生たちがクラスDiscordを運用してるかは知りませんが、うちはあるので活用するまでです。

要は、この記事ではPythonを使ってdiscordのbotを作る方法を説明します。
作成したコードはGitHubに載っているので参考にしてみてください。

目次

  1. Discord上でBotアプリを作る
  2. とりあえず接続してみる
  3. コマンドを追加してみる
  4. まとめ

Discord上でBotアプリを作る

新しいBotをDiscordに登録します。Discord Developer Portalにアクセスします。
右上のNew Applicationをクリックして好きな名前(Botの名前になります)で新しいアプリケーションを作成しましょう。
Applicatonis.png

次に左のタブのBotからAdd Botします。
Usernameの下にTokenというところがあるのでCopyしてどこかに保存しておきましょう。
Bot.png

今度はOAuth2タブに移動します。Scopesの中のbotにチェックマークを入れて、Bot PermissionのSend messagesとManage messagesにチェックを入れます。
OAuth2.png

出てきたリンクを開いてBotを自分が参加しているDiscordサーバーに追加することができます。
Discordを開いて確認してみましょう。

とりあえず接続してみる

今回はPythonを使ってコードを書きます。discord.pyを使うので各自使えるようにしておいてください。

とりあえずメッセージに反応するようにします。

main.py
import discord

TOKEN = '***'

client = discord.Client()

@client.event
async def on_message(message):
    if message.content == 'hello':
        await message.channel.send('hi')

client.run(TOKEN)

TOKENDiscord上でBotアプリを作るでコピーした文字列に置き換えてください。

実行してみましょう。
スクリーンショット 2020-05-18 23.02.21.png

かわいいですね。

client.run()でBotを実行してます。
on_message()は何かメッセージが送信されたときに実行されます。送られてきた内容がhelloだったときにhiと返すだけのBotです。
次はよくある!pのようなコマンドを実装してみます。

コマンドを追加してみる

コマンドの数だけif文を書くのはセンスがないのでコマンドリストを作っておいてそこからコマンドを読むようにしましょう。

main.py
import discord

assignment_list = []

client = discord.Client()

async def kadaihelp(message):
    string = 'コマンドリスト\n'
    for command in COMMANDS:
        string += '------------------------\n'
        string += '{}: {}\n'.format('!' + command, COMMANDS[command]['description'])
        string += '    使い方: {}\n'.format(COMMANDS[command]['use'])
        string += '    省略形: {}\n'.format(COMMANDS[command]['alias'])
        string += '------------------------'

    await message.channel.send(string)

async def newkadai(message):
    msg = message.content.split(' ')
    try:
        title, deadline, memo = msg[1:]

        assignment_list.append({
            'title': title,
            'deadline': deadline,
            'memo': memo
        })

        await message.channel.send('課題を追加しました!')
    except:
        await message.channel.send('入力形式が間違っています。')

async def deletekadai(message):
    msg = message.content.split(' ')
    for i in range(len(assignment_list)):
        if assignment_list[i]['title'] == msg[1]:
            assignment_list.pop(i)
            await message.channel.send('課題を削除しました')

async def kadailist(message):
    string = '課題一覧\n'
    for i, assignment in enumerate(assignment_list):
        string += '------------------------\n'
        string += '{}. {}\n'.format(i + 1, assignment['title'])
        string += '締切: {}\n'.format(assignment['deadline'])
        string += '備考: {}\n'.format(assignment['memo'])
        string += '------------------------\n'

    string += '現在、{}個の課題が出されています。'.format(len(assignment_list))
    await message.channel.send(string)

async def close(message):
    await client.close()

TOKEN = '***'
COMMANDS = {
    'kadaihelp': {
        'description': 'このリストを表示します。',
        'use': '!kadaihelp',
        'alias': '!kh',
        'func': kadaihelp
    },
    'newkadai': {
        'description': '新しい課題を追加します。',
        'use': '!newkadai \{タイトル\} \{締切\} \{備考\}',
        'alias': '!nk',
        'func': newkadai
    },
    'deletekadai': {
        'description': '課題削除',
        'use': '!deletekadai \{課題名\}',
        'alias': '!dk',
        'func': deletekadai
    },
    'kadailist': {
        'description': '登録されている課題一覧を表示します。',
        'use': '!kadailist',
        'alias': '!kl',
        'func': kadailist
    },
    'exit': {
        'description': 'Botを終了します。',
        'use': '!exit',
        'alias': '!ex',
        'func': close
    }
}

@client.event
async def on_ready():
    print('KadaiShosu起動')

@client.event
async def on_message(message):
    msg = message.content.split(' ')

    if message.author.bot:
        return

    for command in COMMANDS:
        if msg[0] in ['!' + command, COMMANDS[command]['alias']]:
            await COMMANDS[command]['func'](message)

client.run(TOKEN)

とりあえず5つコマンドを追加してみました。
COMMANDSの中に辞書形式でコマンドリストを作成しました。on_message()の中で全てのコマンドに対して呼び出されたかどうかを判別して実際にその動作を行う関数を実行します。

それぞれのコマンドに省略形としてaliasを用意しました。もっと良い書き方があるかもしれません。是非いろいろ試してみてください。

ここまででとりあえず課題管理Botとしては機能します。しかし、このままではプログラムを閉じたときに課題がリセットされてしまいます。
最後に変数を保存、読み込む部分だけ書いてみます。

main.py
import pickle

async def close(message):
    pickle.dump(assignment_list, open('assignments.pkl', 'wb'))

    await message.channel.send('Bye^^')

    await client.close()

def load_assignments():
    global assignment_list

    assignment_list = pickle.load(open('assignments.pkl', 'rb'))

load_assignments()

新しくpickleというモジュールを使います。このモジュールは変数の保存を実現してくれます。

close()は書き換えて、他は書き足してください。
!exitでBotを終了したときにassignments_listが保存されて、起動時に読み込まれます。

まとめ

今回はここまでとします。他にもいろいろな機能があると嬉しいと思うので、自分で実装してみてください。

よければTwitterフォローしてください。じゃあね。

11
11
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11