teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

10

複数の引数・引数がないときに対応

2021/10/24 23:55

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -7,6 +7,9 @@
7
7
 
8
8
  以下のコードではトークンや合言葉など見られてはまずいものを環境変数から読み込むようにしていますので、HerokuのConfig Varsに適宜設定するか書き換えてください。
9
9
 
10
+ 【追記】
11
+ `add_role()`の2つ目以降の引数に`?r`の引数が渡されるので、いくつ渡されてもいいように可変引数とし、引数がなかったり引数に渡されたフレーズが間違っていれば「合言葉が間違っています」と表示するようにしました。
12
+
10
13
  ```python
11
14
  import discord
12
15
  from discord.ext.commands import Bot
@@ -49,14 +52,17 @@
49
52
 
50
53
 
51
54
  @bot.command(name='r')
52
- async def add_role(ctx, word):
55
+ async def add_role(ctx, *args):
53
56
  """DM経由かつ合言葉が合っていれば役職を付与"""
57
+ # 「?r あああ いいい」 → add_role(ctx, ['あああ', 'いいい']) → 'あああ いいい'
58
+ # 「?r」 → add_role(ctx, []) → ''
59
+ word = ' '.join(args)
54
60
  if role is not None and is_DM(ctx.message) and word == WORD:
55
61
  user = guild.get_member(ctx.message.author.id)
56
- await ctx.send("Roles added")
62
+ await ctx.send("役職を付与しました。")
57
63
  await user.add_roles(role)
58
64
  else:
59
- await ctx.send('Fail to add roles')
65
+ await ctx.send('合言葉が間違っています。')
60
66
 
61
67
  bot.run(TOKEN)
62
68
  ```

9

型変換を追加

2021/10/24 23:55

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -15,8 +15,8 @@
15
15
 
16
16
 
17
17
  TOKEN = os.getenv('DISCORD_BOT_TOKEN')
18
- GUILD_ID = os.getenv('DISCORD_BOT_GUILD_ID')
18
+ GUILD_ID = int(os.getenv('DISCORD_BOT_GUILD_ID'))
19
- ROLE_ID = os.getenv('DISCORD_BOT_ROLE_ID')
19
+ ROLE_ID = int(os.getenv('DISCORD_BOT_ROLE_ID'))
20
20
  WORD = os.getenv('DISCORD_BOT_WORD')
21
21
 
22
22
 

8

command_prefixを修正

2021/10/23 11:47

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  intents = discord.Intents.default()
24
24
  intents.members = True
25
- bot = Bot(command_prefix='/', intents=intents)
25
+ bot = Bot(command_prefix='?', intents=intents)
26
26
 
27
27
 
28
28
  guild = None

7

説明を追記

2021/10/23 09:40

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -79,6 +79,8 @@
79
79
  - [discord.ext.commands -- ボットコマンドのフレームワーク](https://discordpy.readthedocs.io/ja/latest/ext/commands/index.html)
80
80
 
81
81
  以下、少し見にくいかもしれませんが、動作した環境の各種設定です。
82
+ 権限はサーバの設定から変更することはできず、Botを導入するためのURLを生成するときにしか指定できませんので、変更したい場合は一度Botをサーバから削除して導入し直す必要があるようです。
83
+ Botの削除は「サーバの設定→Integrations→Bot名→Delete Integration」で可能です。
82
84
 
83
85
  ![インテント](37ea0f9a446af515bc37e5ab0854da08.png)
84
86
  ![パーミッション1](d5515a0a4921886d749d8f02de512e57.png)

6

設定がわかるスクショを追加

2021/10/22 18:40

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -78,4 +78,12 @@
78
78
  - [discord.py入門(1) - Qiita](https://qiita.com/sizumita/items/9d44ae7d1ce007391699)
79
79
  - [discord.ext.commands -- ボットコマンドのフレームワーク](https://discordpy.readthedocs.io/ja/latest/ext/commands/index.html)
80
80
 
81
+ 以下、少し見にくいかもしれませんが、動作した環境の各種設定です。
82
+
83
+ ![インテント](37ea0f9a446af515bc37e5ab0854da08.png)
84
+ ![パーミッション1](d5515a0a4921886d749d8f02de512e57.png)
85
+ ![パーミッション2](4cc9a4710544cec2af8ef6dfa33b53ea.png)
86
+ ![権限](8cb7df0634cafa5c0b626bb721f9fafe.png)
87
+ ![権限の順番](9ad77c0b2e94c3e3202c733bfb448928.png)
88
+
81
89
  以上、お役に立てれば幸いです

5

インテントの説明を追記

2021/10/22 18:36

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -64,6 +64,7 @@
64
64
  Botの権限も重要です。
65
65
  Discord Developer PotalでBotをサーバに登録するためのURLを生成するときにBotの権限を指定します。
66
66
  Manage RolesやSend Messagesが必要になります(とりあえず全部与えて試していたので、もしかしたら他にも必要な権限があるかもしれません)。
67
+ 同時に、2つあるインテントの設定もオンにしてください。
67
68
  詳しくは以下の質問の回答が画像付きなのでおすすめです。
68
69
 
69
70
  [Discord - How to give my bot permissions. [Javascript] - Stack Overflow](https://stackoverflow.com/questions/50224362/discord-how-to-give-my-bot-permissions-javascript)

4

説明を追加し、コードを修正

2021/10/22 16:46

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -1,46 +1,80 @@
1
1
  正直、discord.pyには詳しくありませんが、調べてみるとDMでも基本は普通のコマンドbotと変わらないようです。
2
2
  ただしDMの場合、`ctx.message.guild`は`None`になってしまうそうなので、事前に`guild`と`role`を取得しておきましょう。
3
- コードはこんな感じでどうでしょうか。
4
3
 
4
+ また、`DMChannel`からのメッセージの場合、`context.message.author`は`Member`ではなく`User`となります。
5
+ `Member.add_roles()`を使うためには`guild.get_member(context.message.author.id)`で改めて対応する`Member`オブジェクトを取得する必要があります。
6
+ そして、`guild.get_member()`を使用するには`Intents`というオブジェクトを使ってオプションを設定してあげる必要があります。
7
+
8
+ 以下のコードではトークンや合言葉など見られてはまずいものを環境変数から読み込むようにしていますので、HerokuのConfig Varsに適宜設定するか書き換えてください。
9
+
5
10
  ```python
6
11
  import discord
7
12
  from discord.ext.commands import Bot
8
13
  import os
9
- import sys
14
+ import traceback
10
15
 
11
- TOKEN = '' # ご自分のトークンに置き換えてください
12
16
 
13
- # discord.ext.commands.Botはdiscord.Clientのサブクラスなので
17
+ TOKEN = os.getenv('DISCORD_BOT_TOKEN')
18
+ GUILD_ID = os.getenv('DISCORD_BOT_GUILD_ID')
14
- # discord.Clientのメソッド(get_guild()とか)も使える
19
+ ROLE_ID = os.getenv('DISCORD_BOT_ROLE_ID')
15
- bot = Bot(command_prefix='?')
20
+ WORD = os.getenv('DISCORD_BOT_WORD')
16
21
 
17
- GUILD_ID = 0
18
- ROLE_ID = 0
19
22
 
23
+ intents = discord.Intents.default()
24
+ intents.members = True
25
+ bot = Bot(command_prefix='/', intents=intents)
26
+
27
+
28
+ guild = None
20
29
  role = None
21
30
 
31
+
22
32
  @bot.event
23
33
  async def on_ready():
24
- """Bot起動時にroleを取得"""
34
+ global guild
25
35
  global role
26
36
  guild = bot.get_guild(GUILD_ID)
27
37
  role = guild.get_role(ROLE_ID)
28
38
 
39
+
40
+ @bot.event
41
+ async def on_command_error(ctx, error):
42
+ orig_error = getattr(error, "original", error)
43
+ error_msg = ''.join(traceback.TracebackException.from_exception(orig_error).format())
44
+ await ctx.send(error_msg)
45
+
46
+
29
47
  def is_DM(message):
30
48
  return isinstance(message.channel, discord.DMChannel)
31
49
 
50
+
32
51
  @bot.command(name='r')
33
52
  async def add_role(ctx, word):
34
53
  """DM経由かつ合言葉が合っていれば役職を付与"""
35
- if role is not None and is_DM(ctx.message) and word == 'ラーメン大好き':
54
+ if role is not None and is_DM(ctx.message) and word == WORD:
55
+ user = guild.get_member(ctx.message.author.id)
56
+ await ctx.send("Roles added")
36
- await ctx.message.author.add_roles(role)
57
+ await user.add_roles(role)
58
+ else:
59
+ await ctx.send('Fail to add roles')
37
60
 
38
61
  bot.run(TOKEN)
39
62
  ```
40
63
 
64
+ Botの権限も重要です。
65
+ Discord Developer PotalでBotをサーバに登録するためのURLを生成するときにBotの権限を指定します。
66
+ Manage RolesやSend Messagesが必要になります(とりあえず全部与えて試していたので、もしかしたら他にも必要な権限があるかもしれません)。
67
+ 詳しくは以下の質問の回答が画像付きなのでおすすめです。
68
+
69
+ [Discord - How to give my bot permissions. [Javascript] - Stack Overflow](https://stackoverflow.com/questions/50224362/discord-how-to-give-my-bot-permissions-javascript)
70
+
71
+ その上で、サーバーの設定画面でBot用の権限(自動で作成されます)が他の権限よりも上に来るように設定しましょう。
72
+ これをしないと一部のユーザに対して操作できなくなったりするそうです。
73
+
41
74
  参考:
42
-
75
+ - [Discord Bot 最速チュートリアル【Python&Heroku&GitHub】 ​- Qiita](https://qiita.com/1ntegrale9/items/aa4b373e8895273875a8)
76
+ - [python - Permission error for discord.py bot despite having admin permissions - Stack Overflow](https://stackoverflow.com/questions/67665861/permission-error-for-discord-py-bot-despite-having-admin-permissions)
43
77
  - [discord.py入門(1) - Qiita](https://qiita.com/sizumita/items/9d44ae7d1ce007391699)
44
78
  - [discord.ext.commands -- ボットコマンドのフレームワーク](https://discordpy.readthedocs.io/ja/latest/ext/commands/index.html)
45
79
 
46
- 以上、お役に立てれば幸いです
80
+ 以上、お役に立てれば幸いです

3

コード修正

2021/10/22 16:43

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -5,8 +5,10 @@
5
5
  ```python
6
6
  import discord
7
7
  from discord.ext.commands import Bot
8
+ import os
9
+ import sys
8
10
 
9
- TOKEN = '...' # ご自分のTOKENに置き換えてください
11
+ TOKEN = '' # ご自分のトークンに置き換えてください
10
12
 
11
13
  # discord.ext.commands.Botはdiscord.Clientのサブクラスなので
12
14
  # discord.Clientのメソッド(get_guild()とか)も使える
@@ -20,15 +22,17 @@
20
22
  @bot.event
21
23
  async def on_ready():
22
24
  """Bot起動時にroleを取得"""
25
+ global role
23
26
  guild = bot.get_guild(GUILD_ID)
24
27
  role = guild.get_role(ROLE_ID)
25
28
 
29
+ def is_DM(message):
30
+ return isinstance(message.channel, discord.DMChannel)
31
+
26
32
  @bot.command(name='r')
27
33
  async def add_role(ctx, word):
28
34
  """DM経由かつ合言葉が合っていれば役職を付与"""
29
- if (role is not None
30
- and isinstance(ctx.message.channel, discord.DMChannel)
31
- and word == 'ラーメン大好き'):
35
+ if role is not None and is_DM(ctx.message) and word == 'ラーメン大好き':
32
36
  await ctx.message.author.add_roles(role)
33
37
 
34
38
  bot.run(TOKEN)

2

コード修正

2021/10/22 10:23

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -6,6 +6,8 @@
6
6
  import discord
7
7
  from discord.ext.commands import Bot
8
8
 
9
+ TOKEN = '...' # ご自分のTOKENに置き換えてください
10
+
9
11
  # discord.ext.commands.Botはdiscord.Clientのサブクラスなので
10
12
  # discord.Clientのメソッド(get_guild()とか)も使える
11
13
  bot = Bot(command_prefix='?')
@@ -28,6 +30,8 @@
28
30
  and isinstance(ctx.message.channel, discord.DMChannel)
29
31
  and word == 'ラーメン大好き'):
30
32
  await ctx.message.author.add_roles(role)
33
+
34
+ bot.run(TOKEN)
31
35
  ```
32
36
 
33
37
  参考:

1

コード修正

2021/10/22 01:52

投稿

fj68
fj68

スコア752

answer CHANGED
@@ -24,9 +24,9 @@
24
24
  @bot.command(name='r')
25
25
  async def add_role(ctx, word):
26
26
  """DM経由かつ合言葉が合っていれば役職を付与"""
27
- if role is not None
27
+ if (role is not None
28
28
  and isinstance(ctx.message.channel, discord.DMChannel)
29
- and word == 'ラーメン大好き':
29
+ and word == 'ラーメン大好き'):
30
30
  await ctx.message.author.add_roles(role)
31
31
  ```
32
32