From 226550317a22ab6595bb6d3bcef8ca6032ee66c7 Mon Sep 17 00:00:00 2001 From: tetsuya-k <64536338+tetsuya-ki@users.noreply.github.com> Date: Sat, 20 Feb 2021 15:29:10 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E3=83=AA=E3=82=A2=E3=82=AF=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E6=A9=9F=E8=83=BD=E3=81=AE=E6=8B=A1=E5=BC=B5=E3=81=97?= =?UTF-8?q?=E3=80=81Webhook=E3=82=82=E7=99=BB=E9=8C=B2=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4(issue=20?= =?UTF-8?q?#58)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 3 +- cogs/modules/files/.env-docker.sample | 1 + cogs/modules/files/.env.sample | 1 + cogs/modules/reactionchannel.py | 106 ++++++++++++++++++++++---- cogs/modules/settings.py | 1 + cogs/reactionchannelercog.py | 47 +++++++++--- readme.md | 10 ++- 7 files changed, 140 insertions(+), 29 deletions(-) diff --git a/Dockerfile b/Dockerfile index d90e5f9..240383b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,7 +32,8 @@ FIRST_REACTION_CHECK=True \ SCRAPBOX_SID_AND_PROJECTNAME1=xxx:sid@pjname \ COUNT_RANK_SETTING=5 \ PURGE_TARGET_IS_ME_AND_BOT=False \ -OHGIRI_JSON_URL=XXXXXXXXXX +OHGIRI_JSON_URL=XXXXXXXXXX\ +REACTION_CHANNELER_PERMIT_WEBHOOK_ID=99999999 WORKDIR $dir diff --git a/cogs/modules/files/.env-docker.sample b/cogs/modules/files/.env-docker.sample index d6f95a5..adad720 100644 --- a/cogs/modules/files/.env-docker.sample +++ b/cogs/modules/files/.env-docker.sample @@ -8,3 +8,4 @@ SCRAPBOX_SID_AND_PROJECTNAME=all:scrapbox_sid@projectname1,projectname2;guild1:s COUNT_RANK_SETTING=5 PURGE_TARGET_IS_ME_AND_BOT=False OHGIRI_JSON_URL=ohgiri_json_url +REACTION_CHANNELER_PERMIT_WEBHOOK_ID=99999999;99999999 \ No newline at end of file diff --git a/cogs/modules/files/.env.sample b/cogs/modules/files/.env.sample index 5749be2..dfa95c2 100644 --- a/cogs/modules/files/.env.sample +++ b/cogs/modules/files/.env.sample @@ -8,3 +8,4 @@ SCRAPBOX_SID_AND_PROJECTNAME = "all:scrapbox_sid@projectname1,projectname2;guild COUNT_RANK_SETTING = 5 PURGE_TARGET_IS_ME_AND_BOT=False OHGIRI_JSON_URL = "ohgiri_json_url" +REACTION_CHANNELER_PERMIT_WEBHOOK_ID = 99999999;99999999 diff --git a/cogs/modules/reactionchannel.py b/cogs/modules/reactionchannel.py index 49b4cec..eaf1df6 100644 --- a/cogs/modules/reactionchannel.py +++ b/cogs/modules/reactionchannel.py @@ -1,3 +1,4 @@ +import re from discord.message import Attachment from discord.utils import get from os.path import join, dirname @@ -10,12 +11,15 @@ import base64 import json import datetime +import aiohttp logger = getLogger(__name__) class ReactionChannel: FILE = 'reaction-channel.json' REACTION_CHANNEL = 'reaction_channel_control' + WEBHOOK_URL = 'discord.com/api/webhooks/' + NOT_PERMIT_WEBHOOK_MESSAGE = '※環境変数に未登録のWebhookのため、実行されません。環境変数`REACTION_CHANNELER_PERMIT_WEBHOOK_ID`にWebhook IDか、「all」を記載ください(allの場合はすべてのWebhookが許可されます)。' def __init__(self, guilds, bot): self.guilds = guilds @@ -135,7 +139,27 @@ async def set_rc(self, guild:discord.Guild): with open(file_path, mode='r') as f: dict = json.load(f) serialize = dict["pickle"] - self.reaction_channels = pickle.loads(base64.b64decode(serialize.encode())) + reaction_channels = pickle.loads(base64.b64decode(serialize.encode())) + + # Wenhook対応 + reaction_channeler_permit_webhook_id_list = settings.REACTION_CHANNELER_PERMIT_WEBHOOK_ID.replace(' ', '').split(';') + for rc in reaction_channels: + # rc[3](チャンネル名が入るところ)が空ではない場合、通常のリアクションチャンネラーのためそのまま追加。そうではない場合はWebhookのため、有効か確認する + if rc[3] != '': + self.reaction_channels.append(rc) + else: + # 環境変数に登録されているものかチェック + ch_guild_id = str(re.search(self.WEBHOOK_URL+r'(\d+)/', rc[2]).group(1)) + l_in = [s for s in reaction_channeler_permit_webhook_id_list if (ch_guild_id in s or 'all' in s.lower())] + # 環境変数に登録されていないものの場合、先頭に「※」を付与 + if len(l_in) == 0: + logger.info(f'{rc[0]}の{rc[1]}→{rc[2]}は有効になっていません({self.NOT_PERMIT_WEBHOOK_MESSAGE})。') + rc[2] = re.sub('^※?', '※', rc[2]) + # 含まれる場合、先頭の「※」を削除 + else: + rc[2] = re.sub('^※?', '', rc[2]) + self.reaction_channels.append(rc) + self.guild_reaction_channels = [rc[1:] for rc in self.reaction_channels if str(guild.id) in map(str, rc)] # joinするので文字列に変換し、リストに追加する self.guild_rc_txt_lists = [] @@ -170,7 +194,7 @@ async def save(self, guild:discord.Guild): logger.error(self.rc_err) # 追加するリアクションチャネルが問題ないかチェック - def check(self, ctx, reaction:str, channel:str): + async def check(self, ctx, reaction:str, channel:str, is_webhook:bool = False): reaction_id = None if reaction.count(':') == 2: reaction_id = reaction.split(':')[1] @@ -188,11 +212,21 @@ def check(self, ctx, reaction:str, channel:str): self.rc_err = f'この絵文字を本Botで使用しているため、登録できません。(reaction: {reaction})' return False - # チャンネルが不正な場合 - get_channel = discord.utils.get(guild.text_channels, name=channel) - if get_channel is None: - self.rc_err = 'チャンネルが不正なので登録できません。' - return False + # webhookの場合のチェック + if is_webhook: + async with aiohttp.ClientSession() as session: + async with session.get(channel) as r: + logger.debug(channel) + if r.status != 200: + self.rc_err = 'Webhookが不正なので登録できません。' + logger.info(self.rc_err) + return False + else: + # チャンネルが不正(ギルドに存在しないチャンネル)な場合 + get_channel = discord.utils.get(guild.text_channels, name=channel) + if get_channel is None: + self.rc_err = 'チャンネルが不正なので登録できません。' + return False # リアクションチャンネルが未登録ならチェックOK if self.rc_len == 0: @@ -222,15 +256,35 @@ async def add(self, ctx, reaction:str, channel:str): if channel_info is not None: channel = channel_info.name - if self.check(ctx, reaction, channel) is False: + is_webhook = False + if self.WEBHOOK_URL in channel: + is_webhook = True + if await self.check(ctx, reaction, channel, is_webhook) is False: return self.rc_err get_channel = discord.utils.get(guild.text_channels, name=channel) + succeeded_channel_or_webhook = '' addItem = [] addItem.append(guild.id) addItem.append(reaction) - addItem.append(get_channel.name) - addItem.append(get_channel.id) + if is_webhook: + # 環境変数に登録されているものかチェック + ch_guild_id = str(re.search(self.WEBHOOK_URL+r'(\d+)/', channel).group(1)) + reaction_channeler_permit_webhook_id_list = settings.REACTION_CHANNELER_PERMIT_WEBHOOK_ID.replace(' ', '').split(';') + l_in = [s for s in reaction_channeler_permit_webhook_id_list if (ch_guild_id or 'all') in s.lower()] + # 環境変数に登録されていないものの場合、先頭に「※」を付与 + add_messsage = '' + webhook_url = channel + if len(l_in) == 0: + webhook_url = re.sub('^※?', '※', webhook_url) + add_messsage = self.NOT_PERMIT_WEBHOOK_MESSAGE + addItem.append(webhook_url) + addItem.append('') + succeeded_channel_or_webhook = f'{webhook_url}\n{add_messsage}' + else: + addItem.append(get_channel.name) + addItem.append(get_channel.id) + succeeded_channel_or_webhook = f'<#{get_channel.id}>' # 追加 self.reaction_channels.append(addItem) @@ -242,7 +296,7 @@ async def add(self, ctx, reaction:str, channel:str): if await self.save(guild) is False: return self.rc_err - msg = f'リアクションチャンネルの登録に成功しました!\n{reaction} → <#{get_channel.id}>' + msg = f'リアクションチャンネルの登録に成功しました!\n{reaction} → {succeeded_channel_or_webhook}' logger.info(msg) return msg @@ -252,11 +306,17 @@ async def list(self, ctx): logger.debug(f'**リスト**, {self.guild_reaction_channels}') text = '' for list in self.guild_reaction_channels: - text = f'{text} リアクション:{list[0]} → <#{list[2]}>\n' - + # list[2]が空文字でない場合、チャンネルとして出力。そうではない場合、Webhookのためlist[1]を出力 + if list[2] != '': + text = f'{text} リアクション:{list[0]} → <#{list[2]}>\n' + else: + text = f'{text} リアクション:{list[0]} → {list[1]}\n' if text == '': return f'*現在登録されているリアクションチャンネルはありません!' else: + # 有効でないWebhookがある場合、説明を付与 + if '※' in text: + text = text + f'\n{self.NOT_PERMIT_WEBHOOK_MESSAGE}' return f'*現在登録されているリアクションチャンネルの一覧です!({self.rc_len}種類)\n{text}' # 全削除 @@ -300,17 +360,31 @@ async def delete(self, ctx, reaction:str, channel:str): deleteItem = [] deleteItem.append(guild.id) deleteItem.append(reaction) - deleteItem.append(get_channel.name) - deleteItem.append(get_channel.id) + channel_or_webhook_msg = '' + if self.WEBHOOK_URL in channel: + deleteItem.append(channel) + deleteItem.append('') + channel_or_webhook_msg = f'{channel}' + else: + deleteItem.append(get_channel.name) + deleteItem.append(get_channel.id) + channel_or_webhook_msg = f'<#{get_channel.id}>' # 削除 self.reaction_channels = [s for s in self.reaction_channels if s != deleteItem] self.guild_reaction_channels = [s for s in self.guild_reaction_channels if s != deleteItem[1:]] self.guild_rc_txt_lists = [s for s in self.guild_rc_txt_lists if s != '+'.join(map(str, deleteItem[1:]))] self.rc_len = len(self.guild_reaction_channels) + # Webhookの場合、先頭に「※」をつけて再度削除する(有効でない時は※付与するため...) + if self.WEBHOOK_URL in channel: + deleteItem[2] = '※' + channel + self.reaction_channels = [s for s in self.reaction_channels if s != deleteItem] + self.guild_reaction_channels = [s for s in self.guild_reaction_channels if s != deleteItem[1:]] + self.guild_rc_txt_lists = [s for s in self.guild_rc_txt_lists if s != '+'.join(map(str, deleteItem[1:]))] + self.rc_len = len(self.guild_reaction_channels) # 保管 if await self.save(guild) is False: return self.rc_err - return f'リアクションチャンネラーの削除に成功しました!\n{reaction} → <#{get_channel.id}>' + return f'リアクションチャンネラーの削除に成功しました!\n{reaction} →{channel_or_webhook_msg}' diff --git a/cogs/modules/settings.py b/cogs/modules/settings.py index e02f3cd..3214295 100644 --- a/cogs/modules/settings.py +++ b/cogs/modules/settings.py @@ -42,3 +42,4 @@ def num_env(param): COUNT_RANK_SETTING = num_env(os.environ.get('COUNT_RANK_SETTING')) PURGE_TARGET_IS_ME_AND_BOT = if_env(os.environ.get('PURGE_TARGET_IS_ME_AND_BOT')) OHGIRI_JSON_URL = os.environ.get('OHGIRI_JSON_URL') +REACTION_CHANNELER_PERMIT_WEBHOOK_ID = os.environ.get('REACTION_CHANNELER_PERMIT_WEBHOOK_ID') \ No newline at end of file diff --git a/cogs/reactionchannelercog.py b/cogs/reactionchannelercog.py index d63a02c..01c1e3e 100644 --- a/cogs/reactionchannelercog.py +++ b/cogs/reactionchannelercog.py @@ -3,10 +3,12 @@ from .modules import settings from .onmessagecog import OnMessageCog from logging import getLogger +from discord import Webhook, AsyncWebhookAdapter import discord import datetime import asyncio +import aiohttp logger = getLogger(__name__) @@ -191,10 +193,22 @@ async def reaction_channeler(self, payload: discord.RawReactionActionEvent): logger.debug('Already reaction added. emoji_count:'+ str(message_reaction.count)) return - contents = [message.clean_content[i: i+200] for i in range(0, len(message.clean_content), 200)] - if len(contents) != 1 : + contents = [message.clean_content[i: i+1980] for i in range(0, len(message.clean_content), 1980)] + if len(contents) == 0: + return + elif len(contents) > 1: contents[0] += ' *長いので分割しました*' - embed = discord.Embed(title = contents[0], description = '<#' + str(message.channel.id) + '>', type='rich') + + is_webhook = False + channel = '' + # Webhookの場合 + if reaction[2] == '': + is_webhook = True + channel = f'{message.guild.name} / #{message.channel.name}' + else: + channel = f'<#{message.channel.id}>' + + embed = discord.Embed(description = contents[0], type='rich') embed.set_author(name=reaction[0] + ' :reaction_channeler', url='https://github.com/tetsuya-ki/discord-bot-heroku/') embed.set_thumbnail(url=message.author.avatar_url) @@ -202,16 +216,27 @@ async def reaction_channeler(self, payload: discord.RawReactionActionEvent): created_at_jst = created_at.astimezone(datetime.timezone(datetime.timedelta(hours=9))) embed.add_field(name='作成日時', value=created_at_jst.strftime('%Y/%m/%d(%a) %H:%M:%S')) + embed.add_field(name='元のチャンネル', value=channel) if len(contents) != 1 : - for addText in contents[1:]: - embed.add_field(name='addText', value=addText + ' *長いので分割しました*', inline=False) - - to_channel = guild.get_channel(int(reaction[2])) - logger.debug('setting:'+str(reaction[2])) - logger.debug('to_channel: '+str(to_channel)) - - await to_channel.send(reaction[1] + ': ' + message.jump_url, embed=embed) + embed.set_footer(text=contents[1] + ' *長いので分割しました(以降省略)*') + + # リアクションチャンネラーがWebhookだった場合の処理 + if is_webhook and '※' not in reaction[1]: + async with aiohttp.ClientSession() as session: + webhook = Webhook.from_url(reaction[1], adapter=AsyncWebhookAdapter(session)) + try: + await webhook.send('ReactionChanneler(Webhook): ' + message.jump_url, embed=embed, username='ReactionChanneler', avatar_url=message.author.avatar_url) + except (discord.HTTPException,discord.NotFound,discord.Forbidden,discord.InvalidArgument) as e: + logger.error(e) + elif '※' in reaction[1]: + logger.info('環境変数に登録されていないギルドIDをもつWebhookのため、実行されませんでした。') + # 通常のリアクションチャンネラー機能の実行 + else: + to_channel = guild.get_channel(int(reaction[2])) + logger.debug('setting:'+str(reaction[2])) + logger.debug('to_channel: '+str(to_channel)) + await to_channel.send(reaction[1] + ': ' + message.jump_url, embed=embed) # 画像を保存 async def save_file(self, payload: discord.RawReactionActionEvent): diff --git a/readme.md b/readme.md index 2e3e23c..75b7560 100644 --- a/readme.md +++ b/readme.md @@ -111,6 +111,9 @@ Discord用のBot。discord.pyのBot Commands Frameworkを使用して実装。 - あらかじめ指定されたチャンネルへリンクが投稿される ![image(reactionChanneler-2)](https://github.com/tetsuya-ki/images/blob/main/discord-bot-heroku/event_reaction_added.png?raw=True) +- [環境変数](#環境変数の説明)で設定しておけば、別のギルドのチャンネルへリンクを投稿することもできる(v0.7.1で実装) +![image(reactionChanneler-2)]() + ### ゲームカテゴリ(gamecog.pyで実装) `/wordWolf` ワードウルフを行うコマンド。お題を修正したい場合[jsonファイル](https://github.com/tetsuya-ki/discord-bot-heroku/blob/master/cogs/modules/files/wordwolf.json)を変更すること @@ -193,7 +196,7 @@ Discord用のBot。discord.pyのBot Commands Frameworkを使用して実装。 ## 環境変数の説明 -- DISCORD_TOKEN = 'discord_bot_token' +- DISCORD_TOKEN = "discord_bot_token" - ここにDiscord Botのトークンを貼り付ける(とても重要。これをしないと動かない) - LOG_LEVEL = INFO - ログレベルを設定したい場合、設定する。デフォルトはWARN。DEBUG, INFO, WARN, ERRORが設定可能 @@ -205,6 +208,11 @@ Discord用のBot。discord.pyのBot Commands Frameworkを使用して実装。 - 保存したい画像ファイルをもつURLの一部を指定。正規表現対応。複数ある場合はパイプ(|)などを駆使すること - FIRST_REACTION_CHECK = True - すでにリアクションが付けられた物について、**リアクションチャンネラーを発動しないかどうか**の設定。基本的にはTrueがオススメ。寂しいときはFalseでもOK(何回だってチャンネルに転記されちゃいますが!) +- REACTION_CHANNELER_PERMIT_WEBHOOK_ID = "webhook_id" + - リアクションチャンネラー機能の拡張設定。ここにWebhook IDか「all」という文字列を記載すると、リアクションチャンネラー機能でWebhookが使用できる(v0.7.1で実装) + - リアクションを設定するだけで、別のギルドにメッセージを転送することができるようになる + - この環境変数にWebhook IDがない、または、allが記載されていない場合、登録は可能だが、実際に実行はされない + - 勝手にリアクションチャンネラーを登録され情報が流出することを防ぐため、環境変数で指定がない限り実行されないようにする(少し面倒かもしれない) - SCRAPBOX_SID_AND_PROJECTNAME = "all:scrapbox_sid@projectname1,projectname2;guild1:scrapbox_sid@projectname3" - Scrapboxの展開をする際に使用する、sidとプロジェクト名についての設定 - sidについては、[ScrapboxのprivateプロジェクトのAPIを叩く](https://scrapbox.io/nishio/Scrapbox%E3%81%AEprivate%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AEAPI%E3%82%92%E5%8F%A9%E3%81%8F)を参照し、注意点を把握した上対応すること From eaace5db83404318e80ef2612337f5928d047f58 Mon Sep 17 00:00:00 2001 From: tetsuya-k <64536338+tetsuya-ki@users.noreply.github.com> Date: Sun, 21 Feb 2021 01:25:12 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E3=82=AD=E3=83=BC=E3=83=AF=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=82=92=E6=8C=87=E5=AE=9A=E3=81=97=E3=81=A6=E3=83=A1?= =?UTF-8?q?=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E5=89=8A=E9=99=A4=E3=81=99?= =?UTF-8?q?=E3=82=8B=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0(issue=20?= =?UTF-8?q?#47)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cogs/admincog.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/cogs/admincog.py b/cogs/admincog.py index b51bf8d..d5bc19c 100644 --- a/cogs/admincog.py +++ b/cogs/admincog.py @@ -423,6 +423,42 @@ def check(reaction, user): else: await confirm_msg.reply(f'チャンネル「{ctx.channel.name}」からロール**「{targetRole}」**の閲覧権限を削除しました!') + # 指定した文章を含むメッセージを削除するコマンド + @commands.command(aliases=['dm','dem','delm'],description='指定した文章を含むメッセージを削除します') + async def deleteMessage(self, ctx, keyword:str, limit_num:str='1'): + """ + 自分かBOTの指定した文章を含むメッセージを削除します。 + 削除対象のキーワード(必須)、削除対象とするメッセージの数(任意。デフォルトは1) + なお、BOTにメッセージの管理権限、メッセージの履歴閲覧権限、メッセージの閲覧権限がない場合は失敗します。 + """ + self.command_author = ctx.author + # botかコマンドの実行主かチェックし、キーワードを含むメッセージのみ削除 + def is_me_and_contain_keyword(m): + return (self.command_author == m.author or (m.author.bot and settings.PURGE_TARGET_IS_ME_AND_BOT)) and keyword in m.clean_content + + # 指定がない、または、不正な場合は、コマンドを削除。そうではない場合、コマンドを削除し、指定数だけメッセージを走査し、キーワードを含むものだけ削除する + if keyword is None: + await ctx.message.delete() + await ctx.channel.send('削除対象のキーワードを指定してください(削除対象とするメッセージ数を続けて指定してください)。\nあなたのコマンド:`{0}`'.format(ctx.message.clean_content)) + return + if limit_num.isdecimal(): + limit_num = int(limit_num) + 1 + else: + await ctx.message.delete() + await ctx.channel.send('有効な数字ではないようです。削除数は1以上の数値を指定してください。\nあなたのコマンド:`{0}`'.format(ctx.message.clean_content)) + return + + if limit_num > 1000: + limit_num = 1000 + elif limit_num < 2: + await ctx.message.delete() + await ctx.channel.send('削除数は1以上の数値を指定してください。\nあなたのコマンド:`{0}`'.format(ctx.message.clean_content)) + return + + # 違和感を持たせないため、コマンドを削除した分を省いた削除数を通知する。 + deleted = await ctx.channel.purge(limit=limit_num, check=is_me_and_contain_keyword) + await ctx.channel.send('{0}個のメッセージを削除しました。\nあなたのコマンド:`{1}`'.format(len(deleted) - 1, ctx.message.clean_content)) + # チャンネル作成時に実行されるイベントハンドラを定義 @commands.Cog.listener() async def on_guild_channel_create(self, channel: discord.abc.GuildChannel): From a6418f4395a30d09f0f5cacc3750ff9056a95579 Mon Sep 17 00:00:00 2001 From: tetsuya-k <64536338+tetsuya-ki@users.noreply.github.com> Date: Sun, 21 Feb 2021 01:38:51 +0900 Subject: [PATCH 3/3] =?UTF-8?q?readme.md=E3=81=AB=E3=82=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AF=E3=83=BC=E3=83=89=E3=82=92=E6=8C=87=E5=AE=9A=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92?= =?UTF-8?q?=E5=89=8A=E9=99=A4=E3=81=99=E3=82=8B=E6=A9=9F=E8=83=BD=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index 75b7560..eb7977b 100644 --- a/readme.md +++ b/readme.md @@ -81,9 +81,12 @@ Discord用のBot。discord.pyのBot Commands Frameworkを使用して実装。 `/getAuditLog` 監査ログを取得。とっても重たい上に見づらい。。。いつかなんとかしたい([AuditLogChanges](https://discordpy.readthedocs.io/ja/latest/api.html#discord.AuditLogChanges)をわかりやすく表示する方法あるのかな。。。) -`/purge` メッセージを削除(Botと自分のメッセージのみ削除される) +`/purge` メッセージを削除(自分とBot※のメッセージのみ削除される)※Botを削除対象とするかは[環境変数](#環境変数の説明)で指定可能。デフォルトは削除しない ![image(purge)](https://github.com/tetsuya-ki/images/blob/main/discord-bot-heroku/purge.png?raw=true) +`/deleteMessage` 指定したキーワードを含むメッセージを削除(自分とBot※のメッセージのみ削除される)※Botを削除対象とするかは[環境変数](#環境変数の説明)で指定可能。デフォルトは削除しない +![image(deleteMessage)](https://github.com/tetsuya-ki/images/blob/main/discord-bot-heroku/deleteMessage.png?raw=true) + ### リアクションチャンネラーカテゴリ(reactionchannelercog.pyで実装) `/reactionChanneler` リアクションチャンネラーを操作するコマンド(サブコマンド必須)。Slackのリアク字チャンネラーからインスパイアされ、作成したもの。 @@ -112,7 +115,7 @@ Discord用のBot。discord.pyのBot Commands Frameworkを使用して実装。 ![image(reactionChanneler-2)](https://github.com/tetsuya-ki/images/blob/main/discord-bot-heroku/event_reaction_added.png?raw=True) - [環境変数](#環境変数の説明)で設定しておけば、別のギルドのチャンネルへリンクを投稿することもできる(v0.7.1で実装) -![image(reactionChanneler-2)]() +![image(reactionChanneler-3)]() ### ゲームカテゴリ(gamecog.pyで実装) @@ -220,7 +223,7 @@ Discord用のBot。discord.pyのBot Commands Frameworkを使用して実装。 - 左端のallの部分(対象ギルド)をギルドIDにすると、指定のギルドでしか展開しない。allの場合、すべてのギルドで発動 - sidを適用したいプロジェクトが複数ある場合、「,」(コンマ)を挟む必要がある - PURGE_TARGET_IS_ME_AND_BOT=False - - `/purge`コマンドで削除する対象にBotを含むかの設定(設定がない場合は、自分の投稿のみが削除対象) + - `/purge`コマンド、`/deleteMessage`コマンドで削除する対象にBotを含むかの設定(設定がない場合は、**自分の投稿のみ**が削除対象) - OHGIRI_JSON_URL=ohgiri_json_url - 大喜利機能で使用するJSONをURLから取得する場合に設定(Cogを読み込む際に取得されます)