LoginSignup
0
0

More than 3 years have passed since last update.

DiscordのSimplePollっぽいやつをスクラッチ実装しようとしたら手間取った

Last updated at Posted at 2020-08-30

(2020/09/09 一部追記)
(2020/09/14 一部再追記)

↑こういうのを導入しようという話がありましたが、敢えて他にbotを入れるよりも自前のPython botで作った方が早そう&メンテしやすそうだったのでしました

手間取ったポイント

  • 「自分がしたばかりの発言」にリアクションをつける方法
  • リアクション絵文字の指定

コード

#poll
@bot.command()
async def poll(ctx, *args):
    text = "**{}**".format(args[0])
    n = len(args)-1
    if(n == 0):
        await ctx.send("ないようがないよう")
        return
    if(n > 20):
        await ctx.send("ないようがありすぎるよう")
        return
    chars = "abcdefghijklmnopqrstuvwxyz"
    desc = ""
    for i in range(n):
        desc += ":regional_indicator_{}:{}\n".format(chars[i],args[i+1])
    embed = discord.Embed(description=desc)
    message = await ctx.send(text,embed=embed)
    emoji = "🇦🇧🇨🇩🇪🇫🇬🇭🇮🇯🇰🇱🇲🇳🇴🇵🇶🇷🇸🇹🇺🇻🇼🇽🇾🇿"
    for i in range(n):
        await message.add_reaction(emoji[i])

手間取ったポイント1

  • 「自分がしたばかりの発言」にリアクションをつける方法

 ctx.messageでコマンドのきっかけとなったメッセージオブジェクトは拾えますが、crx.sendで送ったbot自身の発言のメッセージにリアクションで投票ボタンをつける必要があるので、それは別に取得する必要があります。

 最初は、https://discordpy.readthedocs.io/ja/latest/api.html#discord.TextChannel.last_message_id last_message_idでIDを取得し、https://discordpy.readthedocs.io/ja/latest/api.html#discord.TextChannel.fetch_message fetch_messageでなんとかなるかと思いましたが、これで得られたmessageオブジェクトがなんか違うものだったらしく、add_reactionの属性なしと言われて失敗。

 結論的にはhttps://discordpy.readthedocs.io/ja/latest/api.html#discord.TextChannel.last_message last_messageという属性でメッセージオブジェクトがそのまま取得できたのでそれで敢行。これだと任意のメッセージIDから取得することはできないですが、今回はそこまで必要なかったのであきらめました。ちょっと時間差があるらしく、add_reactionの直前にしないと一つ前のメッセージにリアクションをつけてしまうことがありました。

(2020/09/09追記) fetch_messageのコマンドの前にawaitをつけると上手くいきました。

(2020/09/14再追記) await ctx.sendが送信したメッセージのオブジェクトを返してくれるようで、わわざわざlast_message_idから拾う必要がありませんでした。@coolwind0202さんご指摘ありがとうございました。

手間取ったポイント2

 公式リファレンス → https://discordpy.readthedocs.io/ja/latest/faq.html

 テキストであれば、普段discordで打ってるように:hogehoge:と打てばそのまま絵文字になってくれますが、リアクションだとそうはいかないようです。Unicode絵文字をそのまま打ったり、{THUMBS UP SIGN}等のキーワード(Discord内のそれとは別)が必要なようです。
 
 また、今回わかったこととして、サーバー独自の絵文字と、デフォルトの絵文字では方法が異なるということです。

サーバー独自の絵文字の場合

 サーバーのIDを指定して、絵文字の名前で検索する必要があります。

guild = bot.get_guild('ここにサーバーのID')
emoji = discord.utils.get(guild.emojis, name='ここに絵文字のDiscordでの呼び方')
if emoji:
    await message.add_reaction(emoji)

 また、Discordのチャットで\:hogehoge:などと発言するとIDを表示してくれるので、ID直打ちも可です。そんな手間は変わらないですが。サーバーIDが分からなければ、開発者モードを有効にしてサーバーアイコンを右クリックすると得られます。

 上のコードのbotは、参考にしたコードによってはclientになっているかもしれません。いずれにせよ、最初に指定した変数名と一致させる必要があります。

Unicodeにデフォルトで入っている絵文字の場合

 こっちの方がめんどくさかったです。この場合はコード内でそのままUnicode絵文字が使えるので、emoji='😩'というような形で指定することができます。しかし、これのA,B,C……はどうやって打てばよいでしょうか? Discord内では:regional_indicator_a:等で出力できますが、これはあくまでDiscord内の呼び名であり、例えば上のコードでemoji = discord.utils.get(guild.emojis, name='regional_indicator_a')とやってもAの絵文字は出てきません。コピペしても:regional_code_a:というテキストがコピーされて絵文字にはなりません。なんだこの制御。

 結論的にいうと、:regional_indicator_a:\でリテラル表示してそれをコピーして文字列を作りました。26文字……。それが🇦🇧🇨🇩🇪🇫🇬🇭🇮🇯🇰🇱🇲🇳🇴🇵🇶🇷🇸🇹🇺🇻🇼🇽🇾🇿という文字列です。これがUnicode上でどういう位置づけになって、皆様のOS上でどのように表示されているかは分かりませんが、めんどくさかった……。

0
0
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
0
0