From 9c78146c79dd7b4c3a633f3eabeef2036eb8ab7f Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Fri, 25 Oct 2019 18:39:58 +0200 Subject: Move offensive message delete time to config file. --- config-default.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 197743296..fc702e991 100644 --- a/config-default.yml +++ b/config-default.yml @@ -161,7 +161,8 @@ filter: notify_user_domains: false # Filter configuration - ping_everyone: true # Ping @everyone when we send a mod-alert? + ping_everyone: true # Ping @everyone when we send a mod-alert? + offensive_msg_delete_time: 7 # How many days before deleting an offensive message? guild_invite_whitelist: - 280033776820813825 # Functional Programming -- cgit v1.2.3 From e6940b938882aaeda18baa9fcc23cc297c6cfcd2 Mon Sep 17 00:00:00 2001 From: Akarys42 Date: Sat, 14 Dec 2019 11:31:32 +0100 Subject: Rename config entry to offensive_msg_delete_days --- bot/cogs/filtering.py | 2 +- bot/constants.py | 2 +- config-default.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 4388b29ad..c0e115a8f 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -42,7 +42,7 @@ TOKEN_WATCHLIST_PATTERNS = [ re.compile(fr'{expression}', flags=re.IGNORECASE) for expression in Filter.token_watchlist ] -OFFENSIVE_MSG_DELETE_TIME = datetime.timedelta(days=Filter.offensive_msg_delete_time) +OFFENSIVE_MSG_DELETE_TIME = datetime.timedelta(days=Filter.offensive_msg_delete_day) class Filtering(Cog, Scheduler): diff --git a/bot/constants.py b/bot/constants.py index 075722a01..e6f23ff61 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -211,7 +211,7 @@ class Filter(metaclass=YAMLGetter): notify_user_domains: bool ping_everyone: bool - offensive_msg_delete_time: int + offensive_msg_delete_day: int guild_invite_whitelist: List[int] domain_blacklist: List[str] word_watchlist: List[str] diff --git a/config-default.yml b/config-default.yml index 0765407af..33072790b 100644 --- a/config-default.yml +++ b/config-default.yml @@ -180,7 +180,7 @@ filter: # Filter configuration ping_everyone: true # Ping @everyone when we send a mod-alert? - offensive_msg_delete_time: 7 # How many days before deleting an offensive message? + offensive_msg_delete_days: 7 # How many days before deleting an offensive message? guild_invite_whitelist: - 280033776820813825 # Functional Programming -- cgit v1.2.3 From e980dab7aa7e2fb6a402b452a376bf94f899989d Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 20 Dec 2019 21:26:46 -0800 Subject: Constants: add dev-core channel and check mark emoji --- bot/constants.py | 2 ++ config-default.yml | 2 ++ 2 files changed, 4 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index fe8e57322..6279388de 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -263,6 +263,7 @@ class Emojis(metaclass=YAMLGetter): new: str pencil: str cross_mark: str + check_mark: str ducky_yellow: int ducky_blurple: int @@ -365,6 +366,7 @@ class Channels(metaclass=YAMLGetter): bot: int checkpoint_test: int defcon: int + devcore: int devlog: int devtest: int esoteric: int diff --git a/config-default.yml b/config-default.yml index fda14b511..74dcc1862 100644 --- a/config-default.yml +++ b/config-default.yml @@ -34,6 +34,7 @@ style: pencil: "\u270F" new: "\U0001F195" cross_mark: "\u274C" + check_mark: "\u2705" ducky_yellow: &DUCKY_YELLOW 574951975574175744 ducky_blurple: &DUCKY_BLURPLE 574951975310065675 @@ -121,6 +122,7 @@ guild: bot: 267659945086812160 checkpoint_test: 422077681434099723 defcon: &DEFCON 464469101889454091 + devcore: 411200599653351425 devlog: &DEVLOG 622895325144940554 devtest: &DEVTEST 414574275865870337 esoteric: 470884583684964352 -- cgit v1.2.3 From ee930bdde1e99cb9e2880e86dd647a42e90d2580 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Wed, 12 Feb 2020 17:14:49 -0500 Subject: Expand reminder channel whitelist to dev-contrib for non-staff Add channel ID to config files --- bot/cogs/reminders.py | 2 +- bot/constants.py | 1 + config-default.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/cogs/reminders.py b/bot/cogs/reminders.py index 715c2d89b..57a74270a 100644 --- a/bot/cogs/reminders.py +++ b/bot/cogs/reminders.py @@ -20,7 +20,7 @@ from bot.utils.time import humanize_delta, wait_until log = logging.getLogger(__name__) -WHITELISTED_CHANNELS = (Channels.bot,) +WHITELISTED_CHANNELS = (Channels.bot, Channels.devcontrib) MAXIMUM_REMINDERS = 5 diff --git a/bot/constants.py b/bot/constants.py index fe8e57322..e2704bfa8 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -365,6 +365,7 @@ class Channels(metaclass=YAMLGetter): bot: int checkpoint_test: int defcon: int + devcontrib: int devlog: int devtest: int esoteric: int diff --git a/config-default.yml b/config-default.yml index fda14b511..ab610d618 100644 --- a/config-default.yml +++ b/config-default.yml @@ -121,6 +121,7 @@ guild: bot: 267659945086812160 checkpoint_test: 422077681434099723 defcon: &DEFCON 464469101889454091 + devcontrib: 635950537262759947 devlog: &DEVLOG 622895325144940554 devtest: &DEVTEST 414574275865870337 esoteric: 470884583684964352 -- cgit v1.2.3 From 5086ca94cb45e411f6463fbe338ba0d6b2192be5 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Sat, 15 Feb 2020 10:38:41 -0500 Subject: Styling & refactors from review * Refactor confirmation embed footer string generation to be more concise * Multiline long method calls * Refactor humanized delta f string generation for readability * Switch from `datetime.isoformat` to `dateutils.parser.isoparse` to align with changes elsewhere in the codebase (should be more robust) * Shift reminder channel whitelist to constants Co-Authored-By: Mark --- bot/cogs/reminders.py | 39 +++++++++++++++++++++++++-------------- bot/constants.py | 2 +- config-default.yml | 5 +++-- 3 files changed, 29 insertions(+), 17 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/reminders.py b/bot/cogs/reminders.py index 57a74270a..efeafa0bc 100644 --- a/bot/cogs/reminders.py +++ b/bot/cogs/reminders.py @@ -6,12 +6,13 @@ from datetime import datetime, timedelta from operator import itemgetter from typing import Optional +from dateutil.parser import isoparse from dateutil.relativedelta import relativedelta from discord import Colour, Embed, Message from discord.ext.commands import Cog, Context, group from bot.bot import Bot -from bot.constants import Channels, Icons, NEGATIVE_REPLIES, POSITIVE_REPLIES, STAFF_ROLES +from bot.constants import Guild, Icons, NEGATIVE_REPLIES, POSITIVE_REPLIES, STAFF_ROLES from bot.converters import Duration from bot.pagination import LinePaginator from bot.utils.checks import without_role_check @@ -20,7 +21,7 @@ from bot.utils.time import humanize_delta, wait_until log = logging.getLogger(__name__) -WHITELISTED_CHANNELS = (Channels.bot, Channels.devcontrib) +WHITELISTED_CHANNELS = Guild.reminder_whitelist MAXIMUM_REMINDERS = 5 @@ -45,13 +46,12 @@ class Reminders(Scheduler, Cog): loop = asyncio.get_event_loop() for reminder in response: - remind_at = datetime.fromisoformat(reminder['expiration'][:-1]) + remind_at = isoparse(reminder['expiration']).replace(tzinfo=None) # If the reminder is already overdue ... if remind_at < now: late = relativedelta(now, remind_at) await self.send_reminder(reminder, late) - else: self.schedule_task(loop, reminder["id"], reminder) @@ -65,18 +65,19 @@ class Reminders(Scheduler, Cog): embed.title = random.choice(POSITIVE_REPLIES) embed.description = on_success + footer_str = f"ID: {reminder_id}" if delivery_dt: - embed.set_footer(text=f"ID: {reminder_id}, Due: {delivery_dt.strftime('%Y-%m-%dT%H:%M:%S')}") - else: # Reminder deletion will have a `None` `delivery_dt` - embed.set_footer(text=f"ID: {reminder_id}") + footer_str = f"{footer_str}, Due: {delivery_dt.strftime('%Y-%m-%dT%H:%M:%S')}" + + embed.set_footer(text=footer_str) await ctx.send(embed=embed) async def _scheduled_task(self, reminder: dict) -> None: """A coroutine which sends the reminder once the time is reached, and cancels the running task.""" reminder_id = reminder["id"] - reminder_datetime = datetime.fromisoformat(reminder['expiration'][:-1]) + reminder_datetime = isoparse(reminder['expiration']).replace(tzinfo=None) # Send the reminder message once the desired duration has passed await wait_until(reminder_datetime) @@ -187,11 +188,12 @@ class Reminders(Scheduler, Cog): ) now = datetime.utcnow() - timedelta(seconds=1) + humanized_delta = humanize_delta(relativedelta(expiration, now)) # Confirm to the user that it worked. await self._send_confirmation( ctx, - on_success=f"Your reminder will arrive in {humanize_delta(relativedelta(expiration, now))}!", + on_success=f"Your reminder will arrive in {humanized_delta}!", reminder_id=reminder["id"], delivery_dt=expiration, ) @@ -223,7 +225,7 @@ class Reminders(Scheduler, Cog): for content, remind_at, id_ in reminders: # Parse and humanize the time, make it pretty :D - remind_datetime = datetime.fromisoformat(remind_at[:-1]) + remind_datetime = isoparse(remind_at).replace(tzinfo=None) time = humanize_delta(relativedelta(remind_datetime, now)) text = textwrap.dedent(f""" @@ -272,7 +274,10 @@ class Reminders(Scheduler, Cog): # Send a confirmation message to the channel await self._send_confirmation( - ctx, on_success="That reminder has been edited successfully!", reminder_id=id_, delivery_dt=expiration + ctx, + on_success="That reminder has been edited successfully!", + reminder_id=id_, + delivery_dt=expiration, ) await self._reschedule_reminder(reminder) @@ -287,11 +292,14 @@ class Reminders(Scheduler, Cog): ) # Parse the reminder expiration back into a datetime for the confirmation message - expiration = datetime.fromisoformat(reminder['expiration'][:-1]) + expiration = isoparse(reminder['expiration']).replace(tzinfo=None) # Send a confirmation message to the channel await self._send_confirmation( - ctx, on_success="That reminder has been edited successfully!", reminder_id=id_, delivery_dt=expiration + ctx, + on_success="That reminder has been edited successfully!", + reminder_id=id_, + delivery_dt=expiration, ) await self._reschedule_reminder(reminder) @@ -300,7 +308,10 @@ class Reminders(Scheduler, Cog): """Delete one of your active reminders.""" await self._delete_reminder(id_) await self._send_confirmation( - ctx, on_success="That reminder has been deleted successfully!", reminder_id=id_, delivery_dt=None + ctx, + on_success="That reminder has been deleted successfully!", + reminder_id=id_, + delivery_dt=None, ) diff --git a/bot/constants.py b/bot/constants.py index e2704bfa8..e9990307a 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -433,7 +433,7 @@ class Guild(metaclass=YAMLGetter): id: int ignored: List[int] staff_channels: List[int] - + reminder_whitelist: List[int] class Keys(metaclass=YAMLGetter): section = "keys" diff --git a/config-default.yml b/config-default.yml index ab610d618..3de7c6ba4 100644 --- a/config-default.yml +++ b/config-default.yml @@ -118,10 +118,10 @@ guild: announcements: 354619224620138496 attachment_log: &ATTCH_LOG 649243850006855680 big_brother_logs: &BBLOGS 468507907357409333 - bot: 267659945086812160 + bot: &BOT_CMD 267659945086812160 checkpoint_test: 422077681434099723 defcon: &DEFCON 464469101889454091 - devcontrib: 635950537262759947 + devcontrib: &DEV_CONTRIB 635950537262759947 devlog: &DEVLOG 622895325144940554 devtest: &DEVTEST 414574275865870337 esoteric: 470884583684964352 @@ -156,6 +156,7 @@ guild: staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG, *ADMINS_VOICE, *STAFF_VOICE, *ATTCH_LOG] + reminder_whitelist: [*BOT_CMD, *DEV_CONTRIB] roles: admin: &ADMIN_ROLE 267628507062992896 -- cgit v1.2.3 From e5a7af3811f7f2687026254f44194b3a16459ca2 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Wed, 19 Feb 2020 09:26:42 -0800 Subject: Sync: add confirmation timeout and max diff to config --- bot/cogs/sync/syncers.py | 25 +++++++++++-------------- bot/constants.py | 7 +++++++ config-default.yml | 4 ++++ tests/bot/cogs/sync/test_base.py | 4 ++-- 4 files changed, 24 insertions(+), 16 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/sync/syncers.py b/bot/cogs/sync/syncers.py index 23039d1fc..43a8f2b62 100644 --- a/bot/cogs/sync/syncers.py +++ b/bot/cogs/sync/syncers.py @@ -26,9 +26,6 @@ class Syncer(abc.ABC): _CORE_DEV_MENTION = f"<@&{constants.Roles.core_developer}> " _REACTION_EMOJIS = (constants.Emojis.check_mark, constants.Emojis.cross_mark) - CONFIRM_TIMEOUT = 60 * 5 # 5 minutes - MAX_DIFF = 10 - def __init__(self, bot: Bot) -> None: self.bot = bot @@ -50,7 +47,7 @@ class Syncer(abc.ABC): msg_content = ( f'Possible cache issue while syncing {self.name}s. ' - f'More than {self.MAX_DIFF} {self.name}s were changed. ' + f'More than {constants.Sync.max_diff} {self.name}s were changed. ' f'React to confirm or abort the sync.' ) @@ -110,8 +107,8 @@ class Syncer(abc.ABC): Uses the `_reaction_check` function to determine if a reaction is valid. - If there is no reaction within `CONFIRM_TIMEOUT` seconds, return False. To acknowledge the - reaction (or lack thereof), `message` will be edited. + If there is no reaction within `bot.constants.Sync.confirm_timeout` seconds, return False. + To acknowledge the reaction (or lack thereof), `message` will be edited. """ # Preserve the core-dev role mention in the message edits so users aren't confused about # where notifications came from. @@ -123,7 +120,7 @@ class Syncer(abc.ABC): reaction, _ = await self.bot.wait_for( 'reaction_add', check=partial(self._reaction_check, author, message), - timeout=self.CONFIRM_TIMEOUT + timeout=constants.Sync.confirm_timeout ) except TimeoutError: # reaction will remain none thus sync will be aborted in the finally block below. @@ -159,15 +156,15 @@ class Syncer(abc.ABC): """ Prompt for confirmation and return a tuple of the result and the prompt message. - `diff_size` is the size of the diff of the sync. If it is greater than `MAX_DIFF`, the - prompt will be sent. The `author` is the invoked of the sync and the `message` is an extant - message to edit to display the prompt. + `diff_size` is the size of the diff of the sync. If it is greater than + `bot.constants.Sync.max_diff`, the prompt will be sent. The `author` is the invoked of the + sync and the `message` is an extant message to edit to display the prompt. If confirmed or no confirmation was needed, the result is True. The returned message will either be the given `message` or a new one which was created when sending the prompt. """ log.trace(f"Determining if confirmation prompt should be sent for {self.name} syncer.") - if diff_size > self.MAX_DIFF: + if diff_size > constants.Sync.max_diff: message = await self._send_prompt(message) if not message: return False, None # Couldn't get channel. @@ -182,9 +179,9 @@ class Syncer(abc.ABC): """ Synchronise the database with the cache of `guild`. - If the differences between the cache and the database are greater than `MAX_DIFF`, then - a confirmation prompt will be sent to the dev-core channel. The confirmation can be - optionally redirect to `ctx` instead. + If the differences between the cache and the database are greater than + `bot.constants.Sync.max_diff`, then a confirmation prompt will be sent to the dev-core + channel. The confirmation can be optionally redirect to `ctx` instead. """ log.info(f"Starting {self.name} syncer.") diff --git a/bot/constants.py b/bot/constants.py index 6279388de..81ce3e903 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -539,6 +539,13 @@ class RedirectOutput(metaclass=YAMLGetter): delete_delay: int +class Sync(metaclass=YAMLGetter): + section = 'sync' + + confirm_timeout: int + max_diff: int + + class Event(Enum): """ Event names. This does not include every event (for example, raw diff --git a/config-default.yml b/config-default.yml index 74dcc1862..0ebdc4080 100644 --- a/config-default.yml +++ b/config-default.yml @@ -430,6 +430,10 @@ redirect_output: delete_invocation: true delete_delay: 15 +sync: + confirm_timeout: 300 + max_diff: 10 + duck_pond: threshold: 5 custom_emojis: [*DUCKY_YELLOW, *DUCKY_BLURPLE, *DUCKY_CAMO, *DUCKY_DEVIL, *DUCKY_NINJA, *DUCKY_REGAL, *DUCKY_TUBE, *DUCKY_HUNT, *DUCKY_WIZARD, *DUCKY_PARTY, *DUCKY_ANGEL, *DUCKY_MAUL, *DUCKY_SANTA] diff --git a/tests/bot/cogs/sync/test_base.py b/tests/bot/cogs/sync/test_base.py index 0539f5683..e6a6f9688 100644 --- a/tests/bot/cogs/sync/test_base.py +++ b/tests/bot/cogs/sync/test_base.py @@ -361,10 +361,10 @@ class SyncerSyncTests(unittest.TestCase): self.assertEqual(self.syncer._get_confirmation_result.call_args[0][1], author) self.assertEqual(self.syncer._get_confirmation_result.call_args[0][2], message) + @mock.patch.object(constants.Sync, "max_diff", new=3) @helpers.async_test async def test_confirmation_result_small_diff(self): """Should always return True and the given message if the diff size is too small.""" - self.syncer.MAX_DIFF = 3 author = helpers.MockMember() expected_message = helpers.MockMessage() @@ -381,10 +381,10 @@ class SyncerSyncTests(unittest.TestCase): self.syncer._send_prompt.assert_not_called() self.syncer._wait_for_confirmation.assert_not_called() + @mock.patch.object(constants.Sync, "max_diff", new=3) @helpers.async_test async def test_confirmation_result_large_diff(self): """Should return True if confirmed and False if _send_prompt fails or aborted.""" - self.syncer.MAX_DIFF = 3 author = helpers.MockMember() mock_message = helpers.MockMessage() -- cgit v1.2.3 From e3fab4567031cb0a3087b3335cd30f87e0027301 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 21 Feb 2020 12:11:12 -0800 Subject: Bot: send empty cache warning to a webhook This is more visible than it would be if it was only logged. * Add a webhook for the dev-log channel to constants --- bot/bot.py | 13 ++++++++++--- bot/constants.py | 1 + config-default.yml | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/bot/bot.py b/bot/bot.py index e5b9717db..c818e79fb 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -68,9 +68,16 @@ class Bot(commands.Bot): return if not guild.roles or not guild.members or not guild.channels: - log.warning( - "Guild available event was dispatched but the cache appears to still be empty!" - ) + msg = "Guild available event was dispatched but the cache appears to still be empty!" + log.warning(msg) + + try: + webhook = await self.fetch_webhook(constants.Webhooks.dev_log) + except discord.HTTPException as e: + log.error(f"Failed to fetch webhook to send empty cache warning: status {e.status}") + else: + await webhook.send(f"<@&{constants.Roles.admin}> {msg}") + return self._guild_available.set() diff --git a/bot/constants.py b/bot/constants.py index 81ce3e903..9856854d7 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -406,6 +406,7 @@ class Webhooks(metaclass=YAMLGetter): big_brother: int reddit: int duck_pond: int + dev_log: int class Roles(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 0ebdc4080..6808925c2 100644 --- a/config-default.yml +++ b/config-default.yml @@ -179,6 +179,7 @@ guild: big_brother: 569133704568373283 reddit: 635408384794951680 duck_pond: 637821475327311927 + dev_log: 680501655111729222 filter: -- cgit v1.2.3 From 5c8a4954d9d22e444cfed6f35057d85185100043 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 23 Feb 2020 18:14:26 +0100 Subject: Add Sentdex server to whitelist --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 2eaf8ee06..ba6ea2742 100644 --- a/config-default.yml +++ b/config-default.yml @@ -217,6 +217,7 @@ filter: - 438622377094414346 # Pyglet - 524691714909274162 # Panda3D - 336642139381301249 # discord.py + - 405403391410438165 # Sentdex domain_blacklist: - pornhub.com -- cgit v1.2.3 From f12d76dca1073b489b4a407a17dbab623aa0dce5 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 11:18:01 -0800 Subject: Config: rename roles to match their names in the guild --- config-default.yml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 379475907..5755b2191 100644 --- a/config-default.yml +++ b/config-default.yml @@ -160,20 +160,20 @@ guild: reminder_whitelist: [*BOT_CMD, *DEV_CONTRIB] roles: - admin: &ADMIN_ROLE 267628507062992896 - announcements: 463658397560995840 - champion: 430492892331769857 - contributor: 295488872404484098 - core_developer: 587606783669829632 - helpers: 267630620367257601 - jammer: 591786436651646989 - moderator: &MOD_ROLE 267629731250176001 - muted: &MUTED_ROLE 277914926603829249 - owner: &OWNER_ROLE 267627879762755584 - partners: 323426753857191936 - rockstars: &ROCKSTARS_ROLE 458226413825294336 - team_leader: 501324292341104650 - verified: 352427296948486144 + admins: &ADMINS_ROLE 267628507062992896 + announcements: 463658397560995840 + code_jam_champions: 430492892331769857 + contributors: 295488872404484098 + core_developers: 587606783669829632 + developers: 352427296948486144 + helpers: 267630620367257601 + jammers: 591786436651646989 + moderators: &MODS_ROLE 267629731250176001 + muted: &MUTED_ROLE 277914926603829249 + owners: &OWNERS_ROLE 267627879762755584 + partners: 323426753857191936 + python_community: &PYTHON_COMMUNITY_ROLE 458226413825294336 + team_leaders: 501324292341104650 webhooks: talent_pool: 569145364800602132 @@ -267,10 +267,10 @@ filter: - *USER_EVENT_A role_whitelist: - - *ADMIN_ROLE - - *MOD_ROLE - - *OWNER_ROLE - - *ROCKSTARS_ROLE + - *ADMINS_ROLE + - *MODS_ROLE + - *OWNERS_ROLE + - *PYTHON_COMMUNITY_ROLE keys: -- cgit v1.2.3 From ffdde0f8a2f14590baf47462143fbd685d851fad Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 11:20:54 -0800 Subject: Config: split roles into categories --- config-default.yml | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 5755b2191..203f9e64e 100644 --- a/config-default.yml +++ b/config-default.yml @@ -160,26 +160,30 @@ guild: reminder_whitelist: [*BOT_CMD, *DEV_CONTRIB] roles: - admins: &ADMINS_ROLE 267628507062992896 announcements: 463658397560995840 - code_jam_champions: 430492892331769857 contributors: 295488872404484098 - core_developers: 587606783669829632 developers: 352427296948486144 - helpers: 267630620367257601 - jammers: 591786436651646989 - moderators: &MODS_ROLE 267629731250176001 muted: &MUTED_ROLE 277914926603829249 - owners: &OWNERS_ROLE 267627879762755584 partners: 323426753857191936 python_community: &PYTHON_COMMUNITY_ROLE 458226413825294336 - team_leaders: 501324292341104650 + + # Staff + admins: &ADMINS_ROLE 267628507062992896 + core_developers: 587606783669829632 + helpers: 267630620367257601 + moderators: &MODS_ROLE 267629731250176001 + owners: &OWNERS_ROLE 267627879762755584 + + # Code Jam + code_jam_champions: 430492892331769857 + jammers: 591786436651646989 + team_leaders: 501324292341104650 webhooks: - talent_pool: 569145364800602132 - big_brother: 569133704568373283 - reddit: 635408384794951680 - duck_pond: 637821475327311927 + talent_pool: 569145364800602132 + big_brother: 569133704568373283 + reddit: 635408384794951680 + duck_pond: 637821475327311927 filter: -- cgit v1.2.3 From bf7dd8c17dea3d0c12139893c210500fdad820f9 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 11:46:12 -0800 Subject: Config: split channels into categories --- config-default.yml | 60 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 21 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 203f9e64e..415ed13f4 100644 --- a/config-default.yml +++ b/config-default.yml @@ -113,19 +113,32 @@ guild: python_help: 356013061213126657 channels: - admins: &ADMINS 365960823622991872 - admin_spam: &ADMIN_SPAM 563594791770914816 - admins_voice: &ADMINS_VOICE 500734494840717332 announcements: 354619224620138496 - attachment_log: &ATTCH_LOG 649243850006855680 - big_brother_logs: &BBLOGS 468507907357409333 - bot: &BOT_CMD 267659945086812160 checkpoint_test: 422077681434099723 - defcon: &DEFCON 464469101889454091 + user_event_a: &USER_EVENT_A 592000283102674944 + + # Development devcontrib: &DEV_CONTRIB 635950537262759947 devlog: &DEVLOG 622895325144940554 devtest: &DEVTEST 414574275865870337 - esoteric: 470884583684964352 + + # Discussion + meta: 429409067623251969 + python: 267624335836053506 + + # Logs + attachment_log: &ATTCH_LOG 649243850006855680 + message_log: &MESSAGE_LOG 467752170159079424 + modlog: &MODLOG 282638479504965634 + userlog: 528976905546760203 + voice_log: 640292421988646961 + + # Off-topic + off_topic_0: 291284109232308226 + off_topic_1: 463035241142026251 + off_topic_2: 463035268514185226 + + # Python Help help_0: 303906576991780866 help_1: 303906556754395136 help_2: 303906514266226689 @@ -134,26 +147,31 @@ guild: help_5: 454941769734422538 help_6: 587375753306570782 help_7: 587375768556797982 + + # Special + bot: &BOT_CMD 267659945086812160 + esoteric: 470884583684964352 + reddit: 458224812528238616 + verification: 352442727016693763 + + # Staff + admins: &ADMINS 365960823622991872 + admin_spam: &ADMIN_SPAM 563594791770914816 + defcon: &DEFCON 464469101889454091 helpers: &HELPERS 385474242440986624 - message_log: &MESSAGE_LOG 467752170159079424 - meta: 429409067623251969 - mod_spam: &MOD_SPAM 620607373828030464 mods: &MODS 305126844661760000 mod_alerts: 473092532147060736 - modlog: &MODLOG 282638479504965634 - off_topic_0: 291284109232308226 - off_topic_1: 463035241142026251 - off_topic_2: 463035268514185226 + mod_spam: &MOD_SPAM 620607373828030464 organisation: &ORGANISATION 551789653284356126 - python: 267624335836053506 - reddit: 458224812528238616 staff_lounge: &STAFF_LOUNGE 464905259261755392 + + # Voice + admins_voice: &ADMINS_VOICE 500734494840717332 staff_voice: &STAFF_VOICE 412375055910043655 + + # Watch + big_brother_logs: &BBLOGS 468507907357409333 talent_pool: &TALENT_POOL 534321732593647616 - userlog: 528976905546760203 - user_event_a: &USER_EVENT_A 592000283102674944 - verification: 352442727016693763 - voice_log: 640292421988646961 staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG, *ADMINS_VOICE, *STAFF_VOICE, *ATTCH_LOG] -- cgit v1.2.3 From 707d2f7208e7008f94bfff1a1e13664dc38c6d6c Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 11:47:11 -0800 Subject: Config: shorten name of PYTHON_COMMUNITY_ROLE --- config-default.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 415ed13f4..1e478154f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -178,12 +178,12 @@ guild: reminder_whitelist: [*BOT_CMD, *DEV_CONTRIB] roles: - announcements: 463658397560995840 - contributors: 295488872404484098 - developers: 352427296948486144 - muted: &MUTED_ROLE 277914926603829249 - partners: 323426753857191936 - python_community: &PYTHON_COMMUNITY_ROLE 458226413825294336 + announcements: 463658397560995840 + contributors: 295488872404484098 + developers: 352427296948486144 + muted: &MUTED_ROLE 277914926603829249 + partners: 323426753857191936 + python_community: &PY_COMMUNITY_ROLE 458226413825294336 # Staff admins: &ADMINS_ROLE 267628507062992896 @@ -292,7 +292,7 @@ filter: - *ADMINS_ROLE - *MODS_ROLE - *OWNERS_ROLE - - *PYTHON_COMMUNITY_ROLE + - *PY_COMMUNITY_ROLE keys: -- cgit v1.2.3 From 8c1a31b7d043facd876b22800e8cb44ae15d9492 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 11:50:21 -0800 Subject: Config: remove checkpoint_test and devtest They no longer exist in the guild. * Move devlog under the "Logs" category --- bot/cogs/bot.py | 1 - bot/cogs/tags.py | 1 - bot/constants.py | 2 -- config-default.yml | 2 -- 4 files changed, 6 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/bot.py b/bot/cogs/bot.py index 73b1e8f41..74e882e0e 100644 --- a/bot/cogs/bot.py +++ b/bot/cogs/bot.py @@ -40,7 +40,6 @@ class BotCog(Cog, name="Bot"): # These channels will also work, but will not be subject to cooldown self.channel_whitelist = ( Channels.bot, - Channels.devtest, ) # Stores improperly formatted Python codeblock message ids and the corresponding bot message diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index b6360dfae..a38f5617f 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -15,7 +15,6 @@ from bot.pagination import LinePaginator log = logging.getLogger(__name__) TEST_CHANNELS = ( - Channels.devtest, Channels.bot, Channels.helpers ) diff --git a/bot/constants.py b/bot/constants.py index 681d8da49..15f078cbf 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -363,11 +363,9 @@ class Channels(metaclass=YAMLGetter): attachment_log: int big_brother_logs: int bot: int - checkpoint_test: int defcon: int devcontrib: int devlog: int - devtest: int esoteric: int help_0: int help_1: int diff --git a/config-default.yml b/config-default.yml index 1e478154f..058317262 100644 --- a/config-default.yml +++ b/config-default.yml @@ -114,13 +114,11 @@ guild: channels: announcements: 354619224620138496 - checkpoint_test: 422077681434099723 user_event_a: &USER_EVENT_A 592000283102674944 # Development devcontrib: &DEV_CONTRIB 635950537262759947 devlog: &DEVLOG 622895325144940554 - devtest: &DEVTEST 414574275865870337 # Discussion meta: 429409067623251969 -- cgit v1.2.3 From ed25a7ae240cce1162a0a67fa6451363671cc7de Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 11:58:51 -0800 Subject: Constants: rename developers role back to verified It makes the code which uses it more readable. A comment was added to explain the discrepancy between the constant's name and the name in the guild. --- config-default.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 058317262..dc5be5d47 100644 --- a/config-default.yml +++ b/config-default.yml @@ -178,11 +178,13 @@ guild: roles: announcements: 463658397560995840 contributors: 295488872404484098 - developers: 352427296948486144 muted: &MUTED_ROLE 277914926603829249 partners: 323426753857191936 python_community: &PY_COMMUNITY_ROLE 458226413825294336 + # This is the Developers role on PyDis, here named verified for readability reasons + verified: 352427296948486144 + # Staff admins: &ADMINS_ROLE 267628507062992896 core_developers: 587606783669829632 -- cgit v1.2.3 From e38990dc26fd77323e33da267ab8f16538f32438 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 11:59:38 -0800 Subject: Constants: remove code jam champions role Nothing was using it. --- bot/constants.py | 1 - config-default.yml | 1 - 2 files changed, 2 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 03578fefd..98914fb9d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -411,7 +411,6 @@ class Roles(metaclass=YAMLGetter): admins: int announcements: int - code_jam_champions: int contributors: int core_developers: int helpers: int diff --git a/config-default.yml b/config-default.yml index dc5be5d47..10cc34816 100644 --- a/config-default.yml +++ b/config-default.yml @@ -193,7 +193,6 @@ guild: owners: &OWNERS_ROLE 267627879762755584 # Code Jam - code_jam_champions: 430492892331769857 jammers: 591786436651646989 team_leaders: 501324292341104650 -- cgit v1.2.3 From 734fd8ff1a0e5bc309b0d84e34b2b6a1d0c204d9 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 12:16:32 -0800 Subject: Config: rename channels to match their names in the guild --- bot/cogs/bot.py | 4 +- bot/cogs/clean.py | 2 +- bot/cogs/defcon.py | 2 +- bot/cogs/free.py | 2 +- bot/cogs/help.py | 2 +- bot/cogs/information.py | 6 +-- bot/cogs/logging.py | 2 +- bot/cogs/moderation/modlog.py | 12 +++--- bot/cogs/snekbox.py | 2 +- bot/cogs/tags.py | 2 +- bot/cogs/utils.py | 2 +- bot/cogs/verification.py | 9 +++-- bot/constants.py | 12 +++--- config-default.yml | 93 +++++++++++++++++++++---------------------- 14 files changed, 76 insertions(+), 76 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/bot.py b/bot/cogs/bot.py index 74e882e0e..f17135877 100644 --- a/bot/cogs/bot.py +++ b/bot/cogs/bot.py @@ -34,12 +34,12 @@ class BotCog(Cog, name="Bot"): Channels.help_5: 0, Channels.help_6: 0, Channels.help_7: 0, - Channels.python: 0, + Channels.python_discussion: 0, } # These channels will also work, but will not be subject to cooldown self.channel_whitelist = ( - Channels.bot, + Channels.bot_commands, ) # Stores improperly formatted Python codeblock message ids and the corresponding bot message diff --git a/bot/cogs/clean.py b/bot/cogs/clean.py index 2104efe57..5cdf0b048 100644 --- a/bot/cogs/clean.py +++ b/bot/cogs/clean.py @@ -173,7 +173,7 @@ class Clean(Cog): colour=Colour(Colours.soft_red), title="Bulk message delete", text=message, - channel_id=Channels.modlog, + channel_id=Channels.mod_log, ) @group(invoke_without_command=True, name="clean", aliases=["purge"]) diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py index c7ea1f2bf..050760a71 100644 --- a/bot/cogs/defcon.py +++ b/bot/cogs/defcon.py @@ -68,7 +68,7 @@ class Defcon(Cog): except Exception: # Yikes! log.exception("Unable to get DEFCON settings!") - await self.bot.get_channel(Channels.devlog).send( + await self.bot.get_channel(Channels.dev_log).send( f"<@&{Roles.admins}> **WARNING**: Unable to get DEFCON settings!" ) diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 49cab6172..02c02d067 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -22,7 +22,7 @@ class Free(Cog): PYTHON_HELP_ID = Categories.python_help @command(name="free", aliases=('f',)) - @redirect_output(destination_channel=Channels.bot, bypass_roles=STAFF_ROLES) + @redirect_output(destination_channel=Channels.bot_commands, bypass_roles=STAFF_ROLES) async def free(self, ctx: Context, user: Member = None, seek: int = 2) -> None: """ Lists free help channels by likeliness of availability. diff --git a/bot/cogs/help.py b/bot/cogs/help.py index fd5bbc3ca..744722220 100644 --- a/bot/cogs/help.py +++ b/bot/cogs/help.py @@ -507,7 +507,7 @@ class Help(DiscordCog): """Custom Embed Pagination Help feature.""" @commands.command('help') - @redirect_output(destination_channel=Channels.bot, bypass_roles=STAFF_ROLES) + @redirect_output(destination_channel=Channels.bot_commands, bypass_roles=STAFF_ROLES) async def new_help(self, ctx: Context, *commands) -> None: """Shows Command Help.""" try: diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 13c8aabaa..49beca15b 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -152,8 +152,8 @@ class Information(Cog): # Non-staff may only do this in #bot-commands if not with_role_check(ctx, *constants.STAFF_ROLES): - if not ctx.channel.id == constants.Channels.bot: - raise InChannelCheckFailure(constants.Channels.bot) + if not ctx.channel.id == constants.Channels.bot_commands: + raise InChannelCheckFailure(constants.Channels.bot_commands) embed = await self.create_user_embed(ctx, user) @@ -332,7 +332,7 @@ class Information(Cog): @cooldown_with_role_bypass(2, 60 * 3, BucketType.member, bypass_roles=constants.STAFF_ROLES) @group(invoke_without_command=True) - @in_channel(constants.Channels.bot, bypass_roles=constants.STAFF_ROLES) + @in_channel(constants.Channels.bot_commands, bypass_roles=constants.STAFF_ROLES) async def raw(self, ctx: Context, *, message: Message, json: bool = False) -> None: """Shows information about the raw API response.""" # I *guess* it could be deleted right as the command is invoked but I felt like it wasn't worth handling diff --git a/bot/cogs/logging.py b/bot/cogs/logging.py index d1b7dcab3..9dcb1456b 100644 --- a/bot/cogs/logging.py +++ b/bot/cogs/logging.py @@ -34,7 +34,7 @@ class Logging(Cog): ) if not DEBUG_MODE: - await self.bot.get_channel(Channels.devlog).send(embed=embed) + await self.bot.get_channel(Channels.dev_log).send(embed=embed) def setup(bot: Bot) -> None: diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index e8ae0dbe6..94e646248 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -87,7 +87,7 @@ class ModLog(Cog, name="ModLog"): title: t.Optional[str], text: str, thumbnail: t.Optional[t.Union[str, discord.Asset]] = None, - channel_id: int = Channels.modlog, + channel_id: int = Channels.mod_log, ping_everyone: bool = False, files: t.Optional[t.List[discord.File]] = None, content: t.Optional[str] = None, @@ -377,7 +377,7 @@ class ModLog(Cog, name="ModLog"): Icons.user_ban, Colours.soft_red, "User banned", f"{member} (`{member.id}`)", thumbnail=member.avatar_url_as(static_format="png"), - channel_id=Channels.userlog + channel_id=Channels.user_log ) @Cog.listener() @@ -399,7 +399,7 @@ class ModLog(Cog, name="ModLog"): Icons.sign_in, Colours.soft_green, "User joined", message, thumbnail=member.avatar_url_as(static_format="png"), - channel_id=Channels.userlog + channel_id=Channels.user_log ) @Cog.listener() @@ -416,7 +416,7 @@ class ModLog(Cog, name="ModLog"): Icons.sign_out, Colours.soft_red, "User left", f"{member} (`{member.id}`)", thumbnail=member.avatar_url_as(static_format="png"), - channel_id=Channels.userlog + channel_id=Channels.user_log ) @Cog.listener() @@ -433,7 +433,7 @@ class ModLog(Cog, name="ModLog"): Icons.user_unban, Colour.blurple(), "User unbanned", f"{member} (`{member.id}`)", thumbnail=member.avatar_url_as(static_format="png"), - channel_id=Channels.modlog + channel_id=Channels.mod_log ) @Cog.listener() @@ -529,7 +529,7 @@ class ModLog(Cog, name="ModLog"): Icons.user_update, Colour.blurple(), "Member updated", message, thumbnail=after.avatar_url_as(static_format="png"), - channel_id=Channels.userlog + channel_id=Channels.user_log ) @Cog.listener() diff --git a/bot/cogs/snekbox.py b/bot/cogs/snekbox.py index 84457e38f..aef12546d 100644 --- a/bot/cogs/snekbox.py +++ b/bot/cogs/snekbox.py @@ -177,7 +177,7 @@ class Snekbox(Cog): @command(name="eval", aliases=("e",)) @guild_only() - @in_channel(Channels.bot, hidden_channels=(Channels.esoteric,), bypass_roles=EVAL_ROLES) + @in_channel(Channels.bot_commands, hidden_channels=(Channels.esoteric,), bypass_roles=EVAL_ROLES) async def eval_command(self, ctx: Context, *, code: str = None) -> None: """ Run Python code and get the results. diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 2c4fa02bd..5da9a4148 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -15,7 +15,7 @@ from bot.pagination import LinePaginator log = logging.getLogger(__name__) TEST_CHANNELS = ( - Channels.bot, + Channels.bot_commands, Channels.helpers ) diff --git a/bot/cogs/utils.py b/bot/cogs/utils.py index da278011a..94b9d6b5a 100644 --- a/bot/cogs/utils.py +++ b/bot/cogs/utils.py @@ -89,7 +89,7 @@ class Utils(Cog): await ctx.message.channel.send(embed=pep_embed) @command() - @in_channel(Channels.bot, bypass_roles=STAFF_ROLES) + @in_channel(Channels.bot_commands, bypass_roles=STAFF_ROLES) async def charinfo(self, ctx: Context, *, characters: str) -> None: """Shows you information on up to 25 unicode characters.""" match = re.match(r"<(a?):(\w+):(\d+)>", characters) diff --git a/bot/cogs/verification.py b/bot/cogs/verification.py index 09bef80c4..94bef3188 100644 --- a/bot/cogs/verification.py +++ b/bot/cogs/verification.py @@ -30,10 +30,11 @@ your information removed here as well. Feel free to review them at any point! Additionally, if you'd like to receive notifications for the announcements we post in <#{Channels.announcements}> \ -from time to time, you can send `!subscribe` to <#{Channels.bot}> at any time to assign yourself the \ +from time to time, you can send `!subscribe` to <#{Channels.bot_commands}> at any time to assign yourself the \ **Announcements** role. We'll mention this role every time we make an announcement. -If you'd like to unsubscribe from the announcement notifications, simply send `!unsubscribe` to <#{Channels.bot}>. +If you'd like to unsubscribe from the announcement notifications, simply send `!unsubscribe` to \ +<#{Channels.bot_commands}>. """ PERIODIC_PING = ( @@ -136,7 +137,7 @@ class Verification(Cog): await ctx.message.delete() @command(name='subscribe') - @in_channel(Channels.bot) + @in_channel(Channels.bot_commands) async def subscribe_command(self, ctx: Context, *_) -> None: # We don't actually care about the args """Subscribe to announcement notifications by assigning yourself the role.""" has_role = False @@ -160,7 +161,7 @@ class Verification(Cog): ) @command(name='unsubscribe') - @in_channel(Channels.bot) + @in_channel(Channels.bot_commands) async def unsubscribe_command(self, ctx: Context, *_) -> None: # We don't actually care about the args """Unsubscribe from announcement notifications by removing the role from yourself.""" has_role = False diff --git a/bot/constants.py b/bot/constants.py index 98914fb9d..f35d608da 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -362,10 +362,10 @@ class Channels(metaclass=YAMLGetter): announcements: int attachment_log: int big_brother_logs: int - bot: int + bot_commands: int defcon: int devcontrib: int - devlog: int + dev_log: int esoteric: int help_0: int help_1: int @@ -381,16 +381,16 @@ class Channels(metaclass=YAMLGetter): mod_spam: int mods: int mod_alerts: int - modlog: int + mod_log: int off_topic_0: int off_topic_1: int off_topic_2: int organisation: int - python: int + python_discussion: int reddit: int talent_pool: int - userlog: int - user_event_a: int + user_log: int + user_event_announcements: int verification: int voice_log: int diff --git a/config-default.yml b/config-default.yml index 10cc34816..44da694c2 100644 --- a/config-default.yml +++ b/config-default.yml @@ -110,69 +110,69 @@ guild: id: 267624335836053506 categories: - python_help: 356013061213126657 + python_help: 356013061213126657 channels: - announcements: 354619224620138496 - user_event_a: &USER_EVENT_A 592000283102674944 + announcements: 354619224620138496 + user_event_announcements: &USER_EVENT_A 592000283102674944 # Development - devcontrib: &DEV_CONTRIB 635950537262759947 - devlog: &DEVLOG 622895325144940554 + devcontrib: &DEV_CONTRIB 635950537262759947 + dev_log: &DEVLOG 622895325144940554 # Discussion - meta: 429409067623251969 - python: 267624335836053506 + meta: 429409067623251969 + python_discussion: 267624335836053506 # Logs - attachment_log: &ATTCH_LOG 649243850006855680 - message_log: &MESSAGE_LOG 467752170159079424 - modlog: &MODLOG 282638479504965634 - userlog: 528976905546760203 - voice_log: 640292421988646961 + attachment_log: &ATTACH_LOG 649243850006855680 + message_log: &MESSAGE_LOG 467752170159079424 + mod_log: &MOD_LOG 282638479504965634 + user_log: 528976905546760203 + voice_log: 640292421988646961 # Off-topic - off_topic_0: 291284109232308226 - off_topic_1: 463035241142026251 - off_topic_2: 463035268514185226 + off_topic_0: 291284109232308226 + off_topic_1: 463035241142026251 + off_topic_2: 463035268514185226 # Python Help - help_0: 303906576991780866 - help_1: 303906556754395136 - help_2: 303906514266226689 - help_3: 439702951246692352 - help_4: 451312046647148554 - help_5: 454941769734422538 - help_6: 587375753306570782 - help_7: 587375768556797982 + help_0: 303906576991780866 + help_1: 303906556754395136 + help_2: 303906514266226689 + help_3: 439702951246692352 + help_4: 451312046647148554 + help_5: 454941769734422538 + help_6: 587375753306570782 + help_7: 587375768556797982 # Special - bot: &BOT_CMD 267659945086812160 - esoteric: 470884583684964352 - reddit: 458224812528238616 - verification: 352442727016693763 + bot_commands: &BOT_CMD 267659945086812160 + esoteric: 470884583684964352 + reddit: 458224812528238616 + verification: 352442727016693763 # Staff - admins: &ADMINS 365960823622991872 - admin_spam: &ADMIN_SPAM 563594791770914816 - defcon: &DEFCON 464469101889454091 - helpers: &HELPERS 385474242440986624 - mods: &MODS 305126844661760000 - mod_alerts: 473092532147060736 - mod_spam: &MOD_SPAM 620607373828030464 - organisation: &ORGANISATION 551789653284356126 - staff_lounge: &STAFF_LOUNGE 464905259261755392 + admins: &ADMINS 365960823622991872 + admin_spam: &ADMIN_SPAM 563594791770914816 + defcon: &DEFCON 464469101889454091 + helpers: &HELPERS 385474242440986624 + mods: &MODS 305126844661760000 + mod_alerts: 473092532147060736 + mod_spam: &MOD_SPAM 620607373828030464 + organisation: &ORGANISATION 551789653284356126 + staff_lounge: &STAFF_LOUNGE 464905259261755392 # Voice - admins_voice: &ADMINS_VOICE 500734494840717332 - staff_voice: &STAFF_VOICE 412375055910043655 + admins_voice: &ADMINS_VOICE 500734494840717332 + staff_voice: &STAFF_VOICE 412375055910043655 # Watch - big_brother_logs: &BBLOGS 468507907357409333 - talent_pool: &TALENT_POOL 534321732593647616 + big_brother_logs: &BB_LOGS 468507907357409333 + talent_pool: &TALENT_POOL 534321732593647616 staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] - ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG, *ADMINS_VOICE, *STAFF_VOICE, *ATTCH_LOG] + ignored: [*ADMINS, *MESSAGE_LOG, *MOD_LOG, *ADMINS_VOICE, *STAFF_VOICE, *ATTACH_LOG] reminder_whitelist: [*BOT_CMD, *DEV_CONTRIB] roles: @@ -193,8 +193,8 @@ guild: owners: &OWNERS_ROLE 267627879762755584 # Code Jam - jammers: 591786436651646989 - team_leaders: 501324292341104650 + jammers: 591786436651646989 + team_leaders: 501324292341104650 webhooks: talent_pool: 569145364800602132 @@ -278,12 +278,11 @@ filter: # Censor doesn't apply to these channel_whitelist: - *ADMINS - - *MODLOG + - *MOD_LOG - *MESSAGE_LOG - - *DEVLOG - - *BBLOGS + - *DEV_LOG + - *BB_LOGS - *STAFF_LOUNGE - - *DEVTEST - *TALENT_POOL - *USER_EVENT_A -- cgit v1.2.3 From 92e4e6d250d6de1b164d36b8a16c62dd4c71fa4f Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 12:40:21 -0800 Subject: Config: fix DEV_LOG variable thingy --- config-default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 44da694c2..51efe4d9a 100644 --- a/config-default.yml +++ b/config-default.yml @@ -117,8 +117,8 @@ guild: user_event_announcements: &USER_EVENT_A 592000283102674944 # Development - devcontrib: &DEV_CONTRIB 635950537262759947 - dev_log: &DEVLOG 622895325144940554 + devcontrib: &DEV_CONTRIB 635950537262759947 + dev_log: &DEV_LOG 622895325144940554 # Discussion meta: 429409067623251969 -- cgit v1.2.3 From 14536f873d5d233880a88c9f71710ef7c2061625 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 12:40:57 -0800 Subject: Config: add underscore to devcontrib --- bot/constants.py | 2 +- config-default.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index f35d608da..63f7b15ee 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -364,7 +364,7 @@ class Channels(metaclass=YAMLGetter): big_brother_logs: int bot_commands: int defcon: int - devcontrib: int + dev_contrib: int dev_log: int esoteric: int help_0: int diff --git a/config-default.yml b/config-default.yml index 51efe4d9a..a43610562 100644 --- a/config-default.yml +++ b/config-default.yml @@ -117,7 +117,7 @@ guild: user_event_announcements: &USER_EVENT_A 592000283102674944 # Development - devcontrib: &DEV_CONTRIB 635950537262759947 + dev_contrib: &DEV_CONTRIB 635950537262759947 dev_log: &DEV_LOG 622895325144940554 # Discussion -- cgit v1.2.3 From 7c14787a9b1550328180ac3ce3da4d9faa65f41e Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 13:05:36 -0800 Subject: Config: replace abbreviated lists with normal ones Lists were getting too long to be readable as one line. Having each element on a separate line also reduces merge conflicts. --- config-default.yml | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index a43610562..05059fbee 100644 --- a/config-default.yml +++ b/config-default.yml @@ -171,9 +171,26 @@ guild: big_brother_logs: &BB_LOGS 468507907357409333 talent_pool: &TALENT_POOL 534321732593647616 - staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] - ignored: [*ADMINS, *MESSAGE_LOG, *MOD_LOG, *ADMINS_VOICE, *STAFF_VOICE, *ATTACH_LOG] - reminder_whitelist: [*BOT_CMD, *DEV_CONTRIB] + staff_channels: + - *ADMINS + - *ADMIN_SPAM + - *DEFCON + - *HELPERS + - *MODS + - *MOD_SPAM + - *ORGANISATION + + ignored: + - *ADMINS + - *ADMINS_VOICE + - *ATTACH_LOG + - *MESSAGE_LOG + - *MOD_LOG + - *STAFF_VOICE + + reminder_whitelist: + - *BOT_CMD + - *DEV_CONTRIB roles: announcements: 463658397560995840 @@ -454,7 +471,20 @@ redirect_output: duck_pond: threshold: 5 - custom_emojis: [*DUCKY_YELLOW, *DUCKY_BLURPLE, *DUCKY_CAMO, *DUCKY_DEVIL, *DUCKY_NINJA, *DUCKY_REGAL, *DUCKY_TUBE, *DUCKY_HUNT, *DUCKY_WIZARD, *DUCKY_PARTY, *DUCKY_ANGEL, *DUCKY_MAUL, *DUCKY_SANTA] + custom_emojis: + - *DUCKY_YELLOW + - *DUCKY_BLURPLE + - *DUCKY_CAMO + - *DUCKY_DEVIL + - *DUCKY_NINJA + - *DUCKY_REGAL + - *DUCKY_TUBE + - *DUCKY_HUNT + - *DUCKY_WIZARD + - *DUCKY_PARTY + - *DUCKY_ANGEL + - *DUCKY_MAUL + - *DUCKY_SANTA config: required_keys: ['bot.token'] -- cgit v1.2.3 From 66fa960fcf0f1d11af20ec1c77039e9ca791f4dc Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 13:08:40 -0800 Subject: Constants: rename Guild.Constant.ignored to modlog_blacklist This name better explains what the list is for. --- bot/cogs/moderation/modlog.py | 10 +++++----- bot/constants.py | 2 +- config-default.yml | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index 94e646248..59ae6b587 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -538,7 +538,7 @@ class ModLog(Cog, name="ModLog"): channel = message.channel author = message.author - if message.guild.id != GuildConstant.id or channel.id in GuildConstant.ignored: + if message.guild.id != GuildConstant.id or channel.id in GuildConstant.modlog_blacklist: return self._cached_deletes.append(message.id) @@ -591,7 +591,7 @@ class ModLog(Cog, name="ModLog"): @Cog.listener() async def on_raw_message_delete(self, event: discord.RawMessageDeleteEvent) -> None: """Log raw message delete event to message change log.""" - if event.guild_id != GuildConstant.id or event.channel_id in GuildConstant.ignored: + if event.guild_id != GuildConstant.id or event.channel_id in GuildConstant.modlog_blacklist: return await asyncio.sleep(1) # Wait here in case the normal event was fired @@ -635,7 +635,7 @@ class ModLog(Cog, name="ModLog"): if ( not msg_before.guild or msg_before.guild.id != GuildConstant.id - or msg_before.channel.id in GuildConstant.ignored + or msg_before.channel.id in GuildConstant.modlog_blacklist or msg_before.author.bot ): return @@ -717,7 +717,7 @@ class ModLog(Cog, name="ModLog"): if ( not message.guild or message.guild.id != GuildConstant.id - or message.channel.id in GuildConstant.ignored + or message.channel.id in GuildConstant.modlog_blacklist or message.author.bot ): return @@ -769,7 +769,7 @@ class ModLog(Cog, name="ModLog"): """Log member voice state changes to the voice log channel.""" if ( member.guild.id != GuildConstant.id - or (before.channel and before.channel.id in GuildConstant.ignored) + or (before.channel and before.channel.id in GuildConstant.modlog_blacklist) ): return diff --git a/bot/constants.py b/bot/constants.py index 63f7b15ee..9855421c9 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -428,7 +428,7 @@ class Guild(metaclass=YAMLGetter): section = "guild" id: int - ignored: List[int] + modlog_blacklist: List[int] staff_channels: List[int] reminder_whitelist: List[int] diff --git a/config-default.yml b/config-default.yml index 05059fbee..b253f32e8 100644 --- a/config-default.yml +++ b/config-default.yml @@ -180,7 +180,8 @@ guild: - *MOD_SPAM - *ORGANISATION - ignored: + # Modlog cog ignores events which occur in these channels + modlog_blacklist: - *ADMINS - *ADMINS_VOICE - *ATTACH_LOG -- cgit v1.2.3 From 3b3206471c028f87685c4c07db0c167a7066ced2 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Tue, 25 Feb 2020 12:28:10 -0500 Subject: Configure staff role & channel groupings in YAML Delete duplicate keys that were missed in the merge --- bot/constants.py | 11 +++++++---- config-default.yml | 26 ++++++++++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 285761055..b1713aa60 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -431,9 +431,12 @@ class Guild(metaclass=YAMLGetter): section = "guild" id: int + moderation_channels: List[int] + moderation_roles: List[int] modlog_blacklist: List[int] - staff_channels: List[int] reminder_whitelist: List[int] + staff_channels: List[int] + staff_roles: List[int] class Keys(metaclass=YAMLGetter): section = "keys" @@ -579,14 +582,14 @@ BOT_DIR = os.path.dirname(__file__) PROJECT_ROOT = os.path.abspath(os.path.join(BOT_DIR, os.pardir)) # Default role combinations -MODERATION_ROLES = Roles.moderators, Roles.admins, Roles.owners -STAFF_ROLES = Roles.helpers, Roles.moderators, Roles.admins, Roles.owners +MODERATION_ROLES = Guild.moderation_roles +STAFF_ROLES = Guild.staff_roles # Roles combinations STAFF_CHANNELS = Guild.staff_channels # Default Channel combinations -MODERATION_CHANNELS = Channels.admins, Channels.admin_spam, Channels.mod_alerts, Channels.mods, Channels.mod_spam +MODERATION_CHANNELS = Guild.moderation_channels # Bot replies diff --git a/config-default.yml b/config-default.yml index dca00500e..ab237423f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -160,7 +160,7 @@ guild: defcon: &DEFCON 464469101889454091 helpers: &HELPERS 385474242440986624 mods: &MODS 305126844661760000 - mod_alerts: 473092532147060736 + mod_alerts: &MOD_ALERTS 473092532147060736 mod_spam: &MOD_SPAM 620607373828030464 organisation: &ORGANISATION 551789653284356126 staff_lounge: &STAFF_LOUNGE 464905259261755392 @@ -182,6 +182,13 @@ guild: - *MOD_SPAM - *ORGANISATION + moderation_channels: + - *ADMINS + - *ADMIN_SPAM + - *MOD_ALERTS + - *MODS + - *MOD_SPAM + # Modlog cog ignores events which occur in these channels modlog_blacklist: - *ADMINS @@ -195,10 +202,6 @@ guild: - *BOT_CMD - *DEV_CONTRIB - staff_channels: [*ADMINS, *ADMIN_SPAM, *MOD_SPAM, *MODS, *HELPERS, *ORGANISATION, *DEFCON] - ignored: [*ADMINS, *MESSAGE_LOG, *MODLOG, *ADMINS_VOICE, *STAFF_VOICE, *ATTCH_LOG] - reminder_whitelist: [*BOT_CMD, *DEV_CONTRIB] - roles: announcements: 463658397560995840 contributors: 295488872404484098 @@ -212,7 +215,7 @@ guild: # Staff admins: &ADMINS_ROLE 267628507062992896 core_developers: 587606783669829632 - helpers: 267630620367257601 + helpers: &HELPERS_ROLE 267630620367257601 moderators: &MODS_ROLE 267629731250176001 owners: &OWNERS_ROLE 267627879762755584 @@ -220,6 +223,17 @@ guild: jammers: 591786436651646989 team_leaders: 501324292341104650 + moderation_roles: + - *OWNERS_ROLE + - *ADMINS_ROLE + - *MODS_ROLE + + staff_roles: + - *OWNERS_ROLE + - *ADMINS_ROLE + - *MODS_ROLE + - *HELPERS_ROLE + webhooks: talent_pool: 569145364800602132 big_brother: 569133704568373283 -- cgit v1.2.3 From db1f74654f1999eaa9b0ae9d8dc49b073222f70b Mon Sep 17 00:00:00 2001 From: Joseph Date: Sun, 1 Mar 2020 21:03:54 +0000 Subject: Add grabify (IP logger) domains to banned domains --- config-default.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index ab237423f..9beb610cc 100644 --- a/config-default.yml +++ b/config-default.yml @@ -284,6 +284,30 @@ filter: domain_blacklist: - pornhub.com - liveleak.com + - grabify.link + - bmwforum.co + - leancoding.co + - spottyfly.com + - stopify.co + - yoütu.be + - discörd.com + - minecräft.com + - freegiftcards.co + - disçordapp.com + - fortnight.space + - fortnitechat.site + - joinmy.site + - curiouscat.club + - catsnthings.fun + - yourtube.site + - youtubeshort.watch + - catsnthing.com + - youtubeshort.pro + - canadianlumberjacks.online + - poweredbydialup.club + - poweredbydialup.online + - poweredbysecurity.org + - poweredbysecurity.online word_watchlist: - goo+ks* -- cgit v1.2.3 From cec9d77a0f8a738f74d02848265a6af86a9cc2d4 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Mon, 2 Mar 2020 13:10:40 +0100 Subject: Adding helpers to the Filtering whitelist Resolves an issue mentioned in https://github.com/python-discord/bot/issues/767, giving Helpers access to post invites and other things caught by the Filtering cog. --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 9beb610cc..5788d1e12 100644 --- a/config-default.yml +++ b/config-default.yml @@ -353,6 +353,7 @@ filter: - *ADMINS_ROLE - *MODS_ROLE - *OWNERS_ROLE + - *HELPERS_ROLE - *PY_COMMUNITY_ROLE -- cgit v1.2.3 From 01bf328bea69dfa773d42aab2fb43dcb2b218e0c Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 17:22:28 -0800 Subject: Constants: add constants for HelpChannels cog --- bot/constants.py | 8 ++++++++ config-default.yml | 11 +++++++++++ 2 files changed, 19 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 14f8dc094..4b47db03d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -532,6 +532,14 @@ class Free(metaclass=YAMLGetter): cooldown_per: float +class HelpChannels(metaclass=YAMLGetter): + section = 'help_channels' + + cmd_whitelist: List[int] + idle_minutes: int + max_available: int + + class Mention(metaclass=YAMLGetter): section = 'mention' diff --git a/config-default.yml b/config-default.yml index 5788d1e12..1f2b12412 100644 --- a/config-default.yml +++ b/config-default.yml @@ -512,6 +512,17 @@ mention: message_timeout: 300 reset_delay: 5 +help_channels: + # Roles which are allowed to use the command which makes channels dormant + cmd_whitelist: + - *HELPERS_ROLE + + # Allowed duration of inactivity before making a channel dormant + idle_minutes: 45 + + # Maximum number of channels to put in the available category + max_available: 2 + redirect_output: delete_invocation: true delete_delay: 15 -- cgit v1.2.3 From db185326bace6eb249fc2867472ae7d770f249db Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 23 Feb 2020 18:17:02 -0800 Subject: Constants: add help category constants The original category was re-purposed as the "in-use" category so that deployment of the new system will not interrupt ongoing help sessions. --- bot/cogs/free.py | 2 +- bot/constants.py | 4 +++- config-default.yml | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/free.py b/bot/cogs/free.py index 33b55e79a..99516fade 100644 --- a/bot/cogs/free.py +++ b/bot/cogs/free.py @@ -19,7 +19,7 @@ PER = Free.cooldown_per class Free(Cog): """Tries to figure out which help channels are free.""" - PYTHON_HELP_ID = Categories.python_help + PYTHON_HELP_ID = Categories.help_in_use @command(name="free", aliases=('f',)) @redirect_output(destination_channel=Channels.bot_commands, bypass_roles=STAFF_ROLES) diff --git a/bot/constants.py b/bot/constants.py index 4b47db03d..58a236546 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -356,7 +356,9 @@ class Categories(metaclass=YAMLGetter): section = "guild" subsection = "categories" - python_help: int + help_available: int + help_in_use: int + help_dormant: int class Channels(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 1f2b12412..27143ff30 100644 --- a/config-default.yml +++ b/config-default.yml @@ -111,7 +111,9 @@ guild: id: 267624335836053506 categories: - python_help: 356013061213126657 + help_available: 691405807388196926 + help_in_use: 356013061213126657 + help_dormant: 691405908919451718 channels: announcements: 354619224620138496 -- cgit v1.2.3 From ca995f96292d8ff334696e89353e977999f4b6b0 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 24 Feb 2020 13:23:51 -0800 Subject: Constants: add a help channel name prefix constant --- bot/cogs/help_channels.py | 2 +- bot/constants.py | 1 + config-default.yml | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 3d7ece909..026cb1f78 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -107,7 +107,7 @@ class HelpChannels(Scheduler, commands.Cog): def get_used_names(self) -> t.Set[str]: """Return channels names which are already being used.""" - start_index = len("help-") + start_index = len(constants.HelpChannels.name_prefix) names = set() for cat in (self.available_category, self.in_use_category, self.dormant_category): diff --git a/bot/constants.py b/bot/constants.py index 58a236546..5b50050d6 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -540,6 +540,7 @@ class HelpChannels(metaclass=YAMLGetter): cmd_whitelist: List[int] idle_minutes: int max_available: int + name_prefix: str class Mention(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 27143ff30..c095aa30b 100644 --- a/config-default.yml +++ b/config-default.yml @@ -525,6 +525,9 @@ help_channels: # Maximum number of channels to put in the available category max_available: 2 + # Prefix for help channel names + name_prefix: 'help-' + redirect_output: delete_invocation: true delete_delay: 15 -- cgit v1.2.3 From 1cd781f787c861790036f02f5c9c0ed3fa1d27cd Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 28 Feb 2020 21:16:02 -0800 Subject: Constants: add constant for max total help channels Represents the total number of help channels across all 3 categories. --- bot/constants.py | 1 + config-default.yml | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 5b50050d6..2f484f0ad 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -540,6 +540,7 @@ class HelpChannels(metaclass=YAMLGetter): cmd_whitelist: List[int] idle_minutes: int max_available: int + max_total_channels: int name_prefix: str diff --git a/config-default.yml b/config-default.yml index c095aa30b..a24092235 100644 --- a/config-default.yml +++ b/config-default.yml @@ -525,6 +525,10 @@ help_channels: # Maximum number of channels to put in the available category max_available: 2 + # Maximum number of channels across all 3 categories + # Note Discord has a hard limit of 50 channels per category, so this shouldn't be > 50 + max_total_channels: 50 + # Prefix for help channel names name_prefix: 'help-' -- cgit v1.2.3 From bcad1ad3a06df3a0d350839f2d861882f05dcd84 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Thu, 27 Feb 2020 22:13:43 -0800 Subject: HelpChannels: notify helpers if out of channels Send a message in the #helpers channel pinging the @helpers role to notify them of a lack of help channels. Can be toggled off in the config. --- bot/cogs/help_channels.py | 9 +++++++++ bot/constants.py | 1 + config-default.yml | 3 +++ 3 files changed, 13 insertions(+) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index bb2103c3a..f9fe9e6de 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -192,6 +192,15 @@ class HelpChannels(Scheduler, commands.Cog): if not channel: log.info("Couldn't create a candidate channel; waiting to get one from the queue.") + + if constants.HelpChannels.notify_helpers: + helpers_channel = self.bot.get_channel(constants.Channels.helpers) + await helpers_channel.send( + f"<@&{constants.Roles.helpers}> a help channel is in needed but none are " + f"available. Consider freeing up some in-use channels manually by using " + f"the `!dormant` command within the channels." + ) + channel = await self.channel_queue.get() return channel diff --git a/bot/constants.py b/bot/constants.py index 2f484f0ad..56ab7f84c 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -542,6 +542,7 @@ class HelpChannels(metaclass=YAMLGetter): max_available: int max_total_channels: int name_prefix: str + notify_helpers: bool class Mention(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index a24092235..0c4e226aa 100644 --- a/config-default.yml +++ b/config-default.yml @@ -532,6 +532,9 @@ help_channels: # Prefix for help channel names name_prefix: 'help-' + # Notify helpers if more channels are needed but none are available + notify_helpers: true + redirect_output: delete_invocation: true delete_delay: 15 -- cgit v1.2.3 From f7e29ba78ec3f25965ae9fb70729cc3eb895e808 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 28 Feb 2020 07:43:40 -0800 Subject: HelpChannels: add a minimum interval between helper notifications * Add configurable constant for minimum interval * Move helper notifications to a separate function --- bot/cogs/help_channels.py | 37 ++++++++++++++++++++++++++++--------- bot/constants.py | 1 + config-default.yml | 3 +++ 3 files changed, 32 insertions(+), 9 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 85015b5e9..809551131 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -100,6 +100,7 @@ class HelpChannels(Scheduler, commands.Cog): self.name_queue: t.Deque[str] = None self.elements = self.get_names() + self.last_notification: t.Optional[datetime] = None self.ready = asyncio.Event() self.on_message_lock = asyncio.Lock() @@ -192,15 +193,7 @@ class HelpChannels(Scheduler, commands.Cog): if not channel: log.info("Couldn't create a candidate channel; waiting to get one from the queue.") - - if constants.HelpChannels.notify_helpers: - helpers_channel = self.bot.get_channel(constants.Channels.helpers) - await helpers_channel.send( - f"<@&{constants.Roles.helpers}> a help channel is in needed but none are " - f"available. Consider freeing up some in-use channels manually by using " - f"the `!dormant` command within the channels." - ) - + await self.notify_helpers() channel = await self.channel_queue.get() return channel @@ -446,6 +439,32 @@ class HelpChannels(Scheduler, commands.Cog): data = ChannelTimeout(channel, timeout) self.schedule_task(self.bot.loop, channel.id, data) + async def notify_helpers(self) -> None: + """ + Notify helpers in the #helpers channel about a lack of available help channels. + + The notification can be disabled with `constants.HelpChannels.notify_helpers`. The + minimum interval between notifications can be configured with + `constants.HelpChannels.notify_minutes`. + """ + if not constants.HelpChannels.notify_helpers: + return + + if self.last_notification: + elapsed = (datetime.utcnow() - self.last_notification).seconds + minimum_interval = constants.HelpChannels.notify_minutes * 60 + should_send = elapsed >= minimum_interval + else: + should_send = True + + if should_send: + helpers_channel = self.bot.get_channel(constants.Channels.helpers) + await helpers_channel.send( + f"<@&{constants.Roles.helpers}> a help channel is in needed but none are " + f"available. Consider freeing up some in-use channels manually by using " + f"the `!dormant` command within the channels." + ) + @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Move an available channel to the In Use category and replace it with a dormant one.""" diff --git a/bot/constants.py b/bot/constants.py index 56ab7f84c..00694e1d7 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -543,6 +543,7 @@ class HelpChannels(metaclass=YAMLGetter): max_total_channels: int name_prefix: str notify_helpers: bool + notify_minutes: int class Mention(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 0c4e226aa..764cf5a3e 100644 --- a/config-default.yml +++ b/config-default.yml @@ -535,6 +535,9 @@ help_channels: # Notify helpers if more channels are needed but none are available notify_helpers: true + # Minimum interval between helper notifications + notify_minutes: 15 + redirect_output: delete_invocation: true delete_delay: 15 -- cgit v1.2.3 From 52b89b4cc406d0f9346e28b5ceb9bc8712be59b8 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 28 Feb 2020 08:01:00 -0800 Subject: Constants: rename HelpChannels.notify_helpers to notify --- bot/cogs/help_channels.py | 2 +- bot/constants.py | 2 +- config-default.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index f63370b24..dde52e1e7 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -447,7 +447,7 @@ class HelpChannels(Scheduler, commands.Cog): minimum interval between notifications can be configured with `constants.HelpChannels.notify_minutes`. """ - if not constants.HelpChannels.notify_helpers: + if not constants.HelpChannels.notify: return if self.last_notification: diff --git a/bot/constants.py b/bot/constants.py index 00694e1d7..32968cfaa 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -542,7 +542,7 @@ class HelpChannels(metaclass=YAMLGetter): max_available: int max_total_channels: int name_prefix: str - notify_helpers: bool + notify: bool notify_minutes: int diff --git a/config-default.yml b/config-default.yml index 764cf5a3e..27dfbdc64 100644 --- a/config-default.yml +++ b/config-default.yml @@ -532,8 +532,8 @@ help_channels: # Prefix for help channel names name_prefix: 'help-' - # Notify helpers if more channels are needed but none are available - notify_helpers: true + # Notify if more available channels are needed but there are no more dormant ones + notify: true # Minimum interval between helper notifications notify_minutes: 15 -- cgit v1.2.3 From 77392c9522eb2f69657d41537ba4e2109c35c315 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 28 Feb 2020 08:05:23 -0800 Subject: Constants: add a channel constant for help channel notifications --- bot/cogs/help_channels.py | 12 ++++++------ bot/constants.py | 1 + config-default.yml | 4 ++++ 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index dde52e1e7..d50a21f0b 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -441,11 +441,11 @@ class HelpChannels(Scheduler, commands.Cog): async def notify_helpers(self) -> None: """ - Notify helpers in the #helpers channel about a lack of available help channels. + Notify helpers about a lack of available help channels. - The notification can be disabled with `constants.HelpChannels.notify_helpers`. The - minimum interval between notifications can be configured with - `constants.HelpChannels.notify_minutes`. + The notification can be disabled with `constants.HelpChannels.notify`. The minimum interval + between notifications can be configured with `constants.HelpChannels.notify_minutes`. The + channel for notifications can be configured with `constants.HelpChannels.notify_channel`. """ if not constants.HelpChannels.notify: return @@ -458,8 +458,8 @@ class HelpChannels(Scheduler, commands.Cog): should_send = True if should_send: - helpers_channel = self.bot.get_channel(constants.Channels.helpers) - await helpers_channel.send( + channel = self.bot.get_channel(constants.HelpChannels.notify_channel) + await channel.send( f"<@&{constants.Roles.helpers}> a new available help channel is needed but there " f"are no more dormant ones. Consider freeing up some in-use channels manually by " f"using the `!dormant` command within the channels." diff --git a/bot/constants.py b/bot/constants.py index 32968cfaa..7a0760eef 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -543,6 +543,7 @@ class HelpChannels(metaclass=YAMLGetter): max_total_channels: int name_prefix: str notify: bool + notify_channel: int notify_minutes: int diff --git a/config-default.yml b/config-default.yml index 27dfbdc64..b23271899 100644 --- a/config-default.yml +++ b/config-default.yml @@ -532,9 +532,13 @@ help_channels: # Prefix for help channel names name_prefix: 'help-' + # Notify if more available channels are needed but there are no more dormant ones notify: true + # Channel in which to send notifications + notify_channel: *HELPERS + # Minimum interval between helper notifications notify_minutes: 15 -- cgit v1.2.3 From 91fd12b0b61bfe731095d30450ac5a24f7ff948c Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 28 Feb 2020 08:07:01 -0800 Subject: Constants: add a roles list constant for help channel notifications --- bot/constants.py | 1 + config-default.yml | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 7a0760eef..042e48a8b 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -545,6 +545,7 @@ class HelpChannels(metaclass=YAMLGetter): notify: bool notify_channel: int notify_minutes: int + notify_roles: List[int] class Mention(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index b23271899..22c05853c 100644 --- a/config-default.yml +++ b/config-default.yml @@ -532,7 +532,6 @@ help_channels: # Prefix for help channel names name_prefix: 'help-' - # Notify if more available channels are needed but there are no more dormant ones notify: true @@ -542,6 +541,10 @@ help_channels: # Minimum interval between helper notifications notify_minutes: 15 + # Mention these roles in notifications + notify_roles: + - *HELPERS_ROLE + redirect_output: delete_invocation: true delete_delay: 15 -- cgit v1.2.3 From deef254e905bf55ebadf36e0e2a5e1616a796706 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 28 Feb 2020 11:04:51 -0800 Subject: Constants: remove old help channel constants --- bot/constants.py | 8 -------- config-default.yml | 10 ---------- 2 files changed, 18 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 042e48a8b..7f19f8a0e 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -376,14 +376,6 @@ class Channels(metaclass=YAMLGetter): dev_core: int dev_log: int esoteric: int - help_0: int - help_1: int - help_2: int - help_3: int - help_4: int - help_5: int - help_6: int - help_7: int helpers: int message_log: int meta: int diff --git a/config-default.yml b/config-default.yml index 22c05853c..b91df4580 100644 --- a/config-default.yml +++ b/config-default.yml @@ -140,16 +140,6 @@ guild: off_topic_1: 463035241142026251 off_topic_2: 463035268514185226 - # Python Help - help_0: 303906576991780866 - help_1: 303906556754395136 - help_2: 303906514266226689 - help_3: 439702951246692352 - help_4: 451312046647148554 - help_5: 454941769734422538 - help_6: 587375753306570782 - help_7: 587375768556797982 - # Special bot_commands: &BOT_CMD 267659945086812160 esoteric: 470884583684964352 -- cgit v1.2.3 From 6173072011b69c54fe817f383b70487e0ad97dee Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sat, 29 Feb 2020 12:37:30 -0800 Subject: HelpChannels: allow users to claim a new channel every 15 minutes --- bot/cogs/help_channels.py | 20 ++++++++++++++++++++ bot/constants.py | 1 + config-default.yml | 3 +++ 3 files changed, 24 insertions(+) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 5b8de156e..e6401b14b 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -515,6 +515,7 @@ class HelpChannels(Scheduler, commands.Cog): return # Ignore messages outside the Available category. await self.move_to_in_use(message.channel) + await self.revoke_send_permissions(message.author) log.trace("Releasing on_message lock.") # Move a dormant channel to the Available category to fill in the gap. @@ -522,6 +523,25 @@ class HelpChannels(Scheduler, commands.Cog): # be put in the queue. await self.move_to_available() + async def revoke_send_permissions(self, member: discord.Member) -> None: + """ + Disallow `member` to send messages in the Available category for a certain time. + + The time until permissions are reinstated can be configured with + `HelpChannels.claim_minutes`. + """ + log.trace( + f"Revoking {member}'s ({member.id}) send message permissions in the Available category." + ) + + await self.available_category.set_permissions(member, send_messages=False) + + timeout = constants.HelpChannels.claim_minutes * 60 + callback = self.available_category.set_permissions(member, send_messages=None) + + log.trace(f"Scheduling {member}'s ({member.id}) send message permissions to be reinstated.") + self.schedule_task(member.id, TaskData(timeout, callback)) + async def send_available_message(self, channel: discord.TextChannel) -> None: """Send the available message by editing a dormant message or sending a new message.""" channel_info = f"#{channel.name} ({channel.id})" diff --git a/bot/constants.py b/bot/constants.py index 7f19f8a0e..8e9d40e8d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -529,6 +529,7 @@ class Free(metaclass=YAMLGetter): class HelpChannels(metaclass=YAMLGetter): section = 'help_channels' + claim_minutes: int cmd_whitelist: List[int] idle_minutes: int max_available: int diff --git a/config-default.yml b/config-default.yml index b91df4580..a62572b70 100644 --- a/config-default.yml +++ b/config-default.yml @@ -505,6 +505,9 @@ mention: reset_delay: 5 help_channels: + # Minimum interval before allowing a certain user to claim a new help channel + claim_minutes: 15 + # Roles which are allowed to use the command which makes channels dormant cmd_whitelist: - *HELPERS_ROLE -- cgit v1.2.3 From 5fba7ab0ca1bde23f028b654d0a69d0d48bec211 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 22 Mar 2020 14:43:59 -0700 Subject: HelpChannels: set idle minutes to 30 & max total channels to 32 --- config-default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index a62572b70..d87ceade7 100644 --- a/config-default.yml +++ b/config-default.yml @@ -513,14 +513,14 @@ help_channels: - *HELPERS_ROLE # Allowed duration of inactivity before making a channel dormant - idle_minutes: 45 + idle_minutes: 30 # Maximum number of channels to put in the available category max_available: 2 # Maximum number of channels across all 3 categories # Note Discord has a hard limit of 50 channels per category, so this shouldn't be > 50 - max_total_channels: 50 + max_total_channels: 32 # Prefix for help channel names name_prefix: 'help-' -- cgit v1.2.3 From ece898460abc2937e9b73d53d2f1f695069ef2e1 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 22 Mar 2020 15:03:34 -0700 Subject: Constants: add a config value to toggle help channels extension --- bot/__main__.py | 13 +++++++------ bot/constants.py | 1 + config-default.yml | 2 ++ 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'config-default.yml') diff --git a/bot/__main__.py b/bot/__main__.py index 30a7dee41..f6ca5a9c8 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -5,9 +5,8 @@ import sentry_sdk from discord.ext.commands import when_mentioned_or from sentry_sdk.integrations.logging import LoggingIntegration -from bot import patches +from bot import constants, patches from bot.bot import Bot -from bot.constants import Bot as BotConfig sentry_logging = LoggingIntegration( level=logging.DEBUG, @@ -15,12 +14,12 @@ sentry_logging = LoggingIntegration( ) sentry_sdk.init( - dsn=BotConfig.sentry_dsn, + dsn=constants.Bot.sentry_dsn, integrations=[sentry_logging] ) bot = Bot( - command_prefix=when_mentioned_or(BotConfig.prefix), + command_prefix=when_mentioned_or(constants.Bot.prefix), activity=discord.Game(name="Commands: !help"), case_insensitive=True, max_messages=10_000, @@ -49,7 +48,6 @@ bot.load_extension("bot.cogs.alias") bot.load_extension("bot.cogs.defcon") bot.load_extension("bot.cogs.eval") bot.load_extension("bot.cogs.duck_pond") -bot.load_extension("bot.cogs.help_channels") bot.load_extension("bot.cogs.information") bot.load_extension("bot.cogs.jams") bot.load_extension("bot.cogs.moderation") @@ -65,8 +63,11 @@ bot.load_extension("bot.cogs.utils") bot.load_extension("bot.cogs.watchchannels") bot.load_extension("bot.cogs.wolfram") +if constants.HelpChannels.enable: + bot.load_extension("bot.cogs.help_channels") + # Apply `message_edited_at` patch if discord.py did not yet release a bug fix. if not hasattr(discord.message.Message, '_handle_edited_timestamp'): patches.message_edited_at.apply_patch() -bot.run(BotConfig.token) +bot.run(constants.Bot.token) diff --git a/bot/constants.py b/bot/constants.py index 8e9d40e8d..da1a62780 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -529,6 +529,7 @@ class Free(metaclass=YAMLGetter): class HelpChannels(metaclass=YAMLGetter): section = 'help_channels' + enable: bool claim_minutes: int cmd_whitelist: List[int] idle_minutes: int diff --git a/config-default.yml b/config-default.yml index d87ceade7..12f69deca 100644 --- a/config-default.yml +++ b/config-default.yml @@ -505,6 +505,8 @@ mention: reset_delay: 5 help_channels: + enable: false + # Minimum interval before allowing a certain user to claim a new help channel claim_minutes: 15 -- cgit v1.2.3 From e88bb946fea8c4bc861f17772f8aca28f99be512 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 27 Mar 2020 11:22:34 -0700 Subject: Filtering: merge the word and token watch filters The only difference was the automatic addition of word boundaries. Otherwise, they shared a lot of code. The regex lists were kept separate in the config to retain the convenience of word boundaries automatically being added. * Rename filter to `watch_regex` * Expand spoilers for both words and tokens * Ignore URLs for both words and tokens --- bot/cogs/filtering.py | 56 +++++++++++++++++---------------------------------- bot/constants.py | 3 +-- config-default.yml | 3 +-- 3 files changed, 21 insertions(+), 41 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 6651d38e4..3f3dbb853 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -38,6 +38,7 @@ WORD_WATCHLIST_PATTERNS = [ TOKEN_WATCHLIST_PATTERNS = [ re.compile(fr'{expression}', flags=re.IGNORECASE) for expression in Filter.token_watchlist ] +WATCHLIST_PATTERNS = WORD_WATCHLIST_PATTERNS + TOKEN_WATCHLIST_PATTERNS def expand_spoilers(text: str) -> str: @@ -88,24 +89,18 @@ class Filtering(Cog): f"Your URL has been removed because it matched a blacklisted domain. {staff_mistake_str}" ) }, + "watch_regex": { + "enabled": Filter.watch_regex, + "function": self._has_watch_regex_match, + "type": "watchlist", + "content_only": True, + }, "watch_rich_embeds": { "enabled": Filter.watch_rich_embeds, "function": self._has_rich_embed, "type": "watchlist", "content_only": False, }, - "watch_words": { - "enabled": Filter.watch_words, - "function": self._has_watchlist_words, - "type": "watchlist", - "content_only": True, - }, - "watch_tokens": { - "enabled": Filter.watch_tokens, - "function": self._has_watchlist_tokens, - "type": "watchlist", - "content_only": True, - }, } @property @@ -191,8 +186,8 @@ class Filtering(Cog): else: channel_str = f"in {msg.channel.mention}" - # Word and match stats for watch_words and watch_tokens - if filter_name in ("watch_words", "watch_tokens"): + # Word and match stats for watch_regex + if filter_name == "watch_regex": surroundings = match.string[max(match.start() - 10, 0): match.end() + 10] message_content = ( f"**Match:** '{match[0]}'\n" @@ -248,37 +243,24 @@ class Filtering(Cog): break # We don't want multiple filters to trigger @staticmethod - async def _has_watchlist_words(text: str) -> Union[bool, re.Match]: + async def _has_watch_regex_match(text: str) -> Union[bool, re.Match]: """ - Returns True if the text contains one of the regular expressions from the word_watchlist in our filter config. + Return True if `text` matches any regex from `word_watchlist` or `token_watchlist` configs. - Only matches words with boundaries before and after the expression. + `word_watchlist`'s patterns are placed between word boundaries while `token_watchlist` is + matched as-is. Spoilers are expanded, if any, and URLs are ignored. """ if SPOILER_RE.search(text): text = expand_spoilers(text) - for regex_pattern in WORD_WATCHLIST_PATTERNS: - match = regex_pattern.search(text) - if match: - return match # match objects always have a boolean value of True - return False - - @staticmethod - async def _has_watchlist_tokens(text: str) -> Union[bool, re.Match]: - """ - Returns True if the text contains one of the regular expressions from the token_watchlist in our filter config. + # Make sure it's not a URL + if URL_RE.search(text): + return False - This will match the expression even if it does not have boundaries before and after. - """ - for regex_pattern in TOKEN_WATCHLIST_PATTERNS: - match = regex_pattern.search(text) + for pattern in WATCHLIST_PATTERNS: + match = pattern.search(text) if match: - - # Make sure it's not a URL - if not URL_RE.search(text): - return match # match objects always have a boolean value of True - - return False + return match @staticmethod async def _has_urls(text: str) -> bool: diff --git a/bot/constants.py b/bot/constants.py index 14f8dc094..549e69c8f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -206,9 +206,8 @@ class Filter(metaclass=YAMLGetter): filter_zalgo: bool filter_invites: bool filter_domains: bool + watch_regex: bool watch_rich_embeds: bool - watch_words: bool - watch_tokens: bool # Notifications are not expected for "watchlist" type filters notify_user_zalgo: bool diff --git a/config-default.yml b/config-default.yml index 5788d1e12..ef0ed970f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -248,9 +248,8 @@ filter: filter_zalgo: false filter_invites: true filter_domains: true + watch_regex: true watch_rich_embeds: true - watch_words: true - watch_tokens: true # Notify user on filter? # Notifications are not expected for "watchlist" type filters -- cgit v1.2.3 From 740bf3e81aba605cb2b4690e5bb25dcba85cd174 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 30 Mar 2020 10:11:24 -0700 Subject: HelpChannels: set to enabled by default --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 12f69deca..89f470e19 100644 --- a/config-default.yml +++ b/config-default.yml @@ -505,7 +505,7 @@ mention: reset_delay: 5 help_channels: - enable: false + enable: true # Minimum interval before allowing a certain user to claim a new help channel claim_minutes: 15 -- cgit v1.2.3 From 45306e1fb665e683d00b1f744958404b7c7eaf9b Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Wed, 1 Apr 2020 11:29:09 +0200 Subject: Add TCD to whitelist The Coding Den is a language agnostic community that's been around for years with over 12000 members. I think we can allow that invite in our community. --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index ef0ed970f..a9578d9bb 100644 --- a/config-default.yml +++ b/config-default.yml @@ -279,6 +279,7 @@ filter: - 524691714909274162 # Panda3D - 336642139381301249 # discord.py - 405403391410438165 # Sentdex + - 172018499005317120 # The Coding Den domain_blacklist: - pornhub.com -- cgit v1.2.3 From c4015d8137e7541f1e76666e28b3e707524e7d06 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Tue, 7 Apr 2020 09:30:37 +0200 Subject: Set the ID of the new Help: In Use category As Discord is having a rather persistent issue with one of the channels in the current `Help: In Use` category, we're going to start using a new category that excludes the old channel. The old channel, help-argon, appears to be completely broken on Discord's end, resulting in "Not found" errors for any kind of interaction, including channel move and/or channel delete admin actions. As it's still visible, it's currently triggering a lot questions from our members. We hope that using a new category will fix that. --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 70c31ebb5..896003973 100644 --- a/config-default.yml +++ b/config-default.yml @@ -112,7 +112,7 @@ guild: categories: help_available: 691405807388196926 - help_in_use: 356013061213126657 + help_in_use: 696958401460043776 help_dormant: 691405908919451718 channels: -- cgit v1.2.3 From ef555490e222474a48fa470f30a1e600816c465f Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 18:14:07 +0100 Subject: StatsD integration --- Pipfile | 3 ++- Pipfile.lock | 59 ++++++++++++++++++++-------------------- bot/__main__.py | 1 + bot/bot.py | 14 ++++++++-- bot/cogs/antispam.py | 1 + bot/cogs/defcon.py | 1 + bot/cogs/error_handler.py | 2 ++ bot/cogs/filtering.py | 2 ++ bot/cogs/help_channels.py | 21 +++++++++++++-- bot/cogs/stats.py | 65 +++++++++++++++++++++++++++++++++++++++++++++ bot/cogs/tags.py | 3 +++ bot/cogs/token_remover.py | 2 ++ bot/cogs/webhook_remover.py | 2 ++ bot/constants.py | 1 + config-default.yml | 2 ++ 15 files changed, 145 insertions(+), 34 deletions(-) create mode 100644 bot/cogs/stats.py (limited to 'config-default.yml') diff --git a/Pipfile b/Pipfile index 04cc98427..e7fb61957 100644 --- a/Pipfile +++ b/Pipfile @@ -19,7 +19,8 @@ requests = "~=2.22" more_itertools = "~=8.2" sentry-sdk = "~=0.14" coloredlogs = "~=14.0" -colorama = {version = "~=0.4.3", sys_platform = "== 'win32'"} +colorama = {version = "~=0.4.3",sys_platform = "== 'win32'"} +statsd = "~=3.3" [dev-packages] coverage = "~=5.0" diff --git a/Pipfile.lock b/Pipfile.lock index ad9a3173a..19e03bda4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2d3ba484e8467a115126b2ba39fa5f36f103ea455477813dd658797875c79cc9" + "sha256": "10636aef5a07f17bd00608df2cc5214fcbfe3de4745cdeea7a076b871754620a" }, "pipfile-spec": 6, "requires": { @@ -87,18 +87,18 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:05fd825eb01c290877657a56df4c6e4c311b3965bda790c613a3d6fb01a5462a", - "sha256:9fbb4d6e48ecd30bcacc5b63b94088192dcda178513b2ae3c394229f8911b887", - "sha256:e1505eeed31b0f4ce2dbb3bc8eb256c04cc2b3b72af7d551a4ab6efd5cbe5dae" + "sha256:594ca51a10d2b3443cbac41214e12dbb2a1cd57e1a7344659849e2e20ba6a8d8", + "sha256:a4bbe77fd30670455c5296242967a123ec28c37e9702a8a81bd2f20a4baf0368", + "sha256:d4e96ac9b0c3a6d3f0caae2e4124e6055c5dcafde8e2f831ff194c104f0775a0" ], - "version": "==4.8.2" + "version": "==4.9.0" }, "certifi": { "hashes": [ - "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", - "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", + "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" ], - "version": "==2019.11.28" + "version": "==2020.4.5.1" }, "cffi": { "hashes": [ @@ -167,10 +167,10 @@ }, "discord-py": { "hashes": [ - "sha256:7424be26b07b37ecad4404d9383d685995a0e0b3df3f9c645bdd3a4d977b83b4" + "sha256:406871b06d86c3dc49fba63238519f28628dac946fef8a0e22988ff58ec05580" ], "index": "pypi", - "version": "==1.3.2" + "version": "==1.3.3" }, "docutils": { "hashes": [ @@ -393,17 +393,10 @@ }, "pyparsing": { "hashes": [ - "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", - "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "version": "==2.4.6" - }, - "pyreadline": { - "hashes": [ - "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1" - ], - "markers": "sys_platform == 'win32'", - "version": "==2.1" + "version": "==2.4.7" }, "python-dateutil": { "hashes": [ @@ -524,6 +517,14 @@ ], "version": "==1.1.4" }, + "statsd": { + "hashes": [ + "sha256:c610fb80347fca0ef62666d241bce64184bd7cc1efe582f9690e045c25535eaa", + "sha256:e3e6db4c246f7c59003e51c9720a51a7f39a396541cb9b147ff4b14d15b5dd1f" + ], + "index": "pypi", + "version": "==3.3.0" + }, "urllib3": { "hashes": [ "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", @@ -717,11 +718,11 @@ }, "flake8-tidy-imports": { "hashes": [ - "sha256:5b6e75cec6d751e66534c522fbdce7dac1c2738b1216b0f6b10453995932e188", - "sha256:cf26fbb3ab31a398f265d53b6f711d80006450c19221e41b2b7b0e0b14ac39c5" + "sha256:62059ca07d8a4926b561d392cbab7f09ee042350214a25cf12823384a45d27dd", + "sha256:c30b40337a2e6802ba3bb611c26611154a27e94c53fc45639e3e282169574fd3" ], "index": "pypi", - "version": "==4.0.1" + "version": "==4.1.0" }, "flake8-todo": { "hashes": [ @@ -732,10 +733,10 @@ }, "identify": { "hashes": [ - "sha256:a7577a1f55cee1d21953a5cf11a3c839ab87f5ef909a4cba6cf52ed72b4c6059", - "sha256:ab246293e6585a1c6361a505b68d5b501a0409310932b7de2c2ead667b564d89" + "sha256:2bb8760d97d8df4408f4e805883dad26a2d076f04be92a10a3e43f09c6060742", + "sha256:faffea0fd8ec86bb146ac538ac350ed0c73908326426d387eded0bcc9d077522" ], - "version": "==1.4.13" + "version": "==1.4.14" }, "mccabe": { "hashes": [ @@ -835,10 +836,10 @@ }, "virtualenv": { "hashes": [ - "sha256:87831f1070534b636fea2241dd66f3afe37ac9041bcca6d0af3215cdcfbf7d82", - "sha256:f3128d882383c503003130389bf892856341c1da12c881ae24d6358c82561b55" + "sha256:00cfe8605fb97f5a59d52baab78e6070e72c12ca64f51151695407cc0eb8a431", + "sha256:c8364ec469084046c779c9a11ae6340094e8a0bf1d844330fc55c1cefe67c172" ], - "version": "==20.0.13" + "version": "==20.0.17" } } } diff --git a/bot/__main__.py b/bot/__main__.py index bf98f2cfd..2125e8590 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -57,6 +57,7 @@ bot.load_extension("bot.cogs.reminders") bot.load_extension("bot.cogs.site") bot.load_extension("bot.cogs.snekbox") bot.load_extension("bot.cogs.sync") +bot.load_extension("bot.cogs.stats") bot.load_extension("bot.cogs.tags") bot.load_extension("bot.cogs.token_remover") bot.load_extension("bot.cogs.utils") diff --git a/bot/bot.py b/bot/bot.py index 950ac6751..65081e438 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -6,10 +6,10 @@ from typing import Optional import aiohttp import discord +import statsd from discord.ext import commands -from bot import api -from bot import constants +from bot import DEBUG_MODE, api, constants log = logging.getLogger('bot') @@ -33,6 +33,16 @@ class Bot(commands.Bot): self._resolver = None self._guild_available = asyncio.Event() + statsd_url = constants.Bot.statsd_host + + if DEBUG_MODE: + # Since statsd is UDP, there are no errors for sending to a down port. + # For this reason, setting the statsd host to 127.0.0.1 for development + # will effectively disable stats. + statsd_url = "127.0.0.1" + + self.stats = statsd.StatsClient(statsd_url, 8125, prefix="bot") + def add_cog(self, cog: commands.Cog) -> None: """Adds a "cog" to the bot and logs the operation.""" super().add_cog(cog) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index baa6b9459..d63acbc4a 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -182,6 +182,7 @@ class AntiSpam(Cog): # which contains the reason for why the message violated the rule and # an iterable of all members that violated the rule. if result is not None: + self.bot.stats.incr(f"mod_alerts.{rule_name}") reason, members, relevant_messages = result full_reason = f"`{rule_name}` rule: {reason}" diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py index cc0f79fe8..80dc6082f 100644 --- a/bot/cogs/defcon.py +++ b/bot/cogs/defcon.py @@ -104,6 +104,7 @@ class Defcon(Cog): log.exception(f"Unable to send rejection message to user: {member}") await member.kick(reason="DEFCON active, user is too new") + self.bot.stats.incr("defcon_leaves") message = ( f"{member} (`{member.id}`) was denied entry because their account is too new." diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 6a622d2ce..747ab4a6e 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -236,6 +236,8 @@ class ErrorHandler(Cog): f"```{e.__class__.__name__}: {e}```" ) + ctx.bot.stats.incr("command_error_count") + with push_scope() as scope: scope.user = { "id": ctx.author.id, diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 3f3dbb853..fa4420be1 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -207,6 +207,8 @@ class Filtering(Cog): log.debug(message) + self.bot.stats.incr(f"bot.filters.{filter_name}") + additional_embeds = None additional_embeds_msg = None diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 697a4d3b7..389a4ad2a 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -367,6 +367,18 @@ class HelpChannels(Scheduler, commands.Cog): log.info("Cog is ready!") self.ready.set() + self.report_stats() + + def report_stats(self) -> None: + """Report the channel count stats.""" + total_in_use = len(list(self.get_category_channels(self.in_use_category))) + total_available = len(list(self.get_category_channels(self.available_category))) + total_dormant = len(list(self.get_category_channels(self.dormant_category))) + + self.bot.stats.gauge("help.total.in_use", total_in_use) + self.bot.stats.gauge("help.total.available", total_available) + self.bot.stats.gauge("help.total.dormant", total_dormant) + @staticmethod def is_dormant_message(message: t.Optional[discord.Message]) -> bool: """Return True if the contents of the `message` match `DORMANT_MSG`.""" @@ -432,6 +444,7 @@ class HelpChannels(Scheduler, commands.Cog): f"synchronized permissions after moving `{channel}` into it." ) await self.ensure_permissions_synchronization(self.available_category) + self.report_stats() async def move_to_dormant(self, channel: discord.TextChannel) -> None: """Make the `channel` dormant.""" @@ -442,7 +455,6 @@ class HelpChannels(Scheduler, commands.Cog): category=self.dormant_category, sync_permissions=True, topic=DORMANT_TOPIC, - position=10000, ) log.trace(f"Position of #{channel} ({channel.id}) is actually {channel.position}.") @@ -453,6 +465,7 @@ class HelpChannels(Scheduler, commands.Cog): log.trace(f"Pushing #{channel} ({channel.id}) into the channel queue.") self.channel_queue.put_nowait(channel) + self.report_stats() async def move_to_in_use(self, channel: discord.TextChannel) -> None: """Make a channel in-use and schedule it to be made dormant.""" @@ -463,7 +476,6 @@ class HelpChannels(Scheduler, commands.Cog): category=self.in_use_category, sync_permissions=True, topic=IN_USE_TOPIC, - position=10000, ) timeout = constants.HelpChannels.idle_minutes * 60 @@ -471,6 +483,7 @@ class HelpChannels(Scheduler, commands.Cog): log.trace(f"Scheduling #{channel} ({channel.id}) to become dormant in {timeout} sec.") data = TaskData(timeout, self.move_idle_channel(channel)) self.schedule_task(channel.id, data) + self.report_stats() async def notify(self) -> None: """ @@ -511,6 +524,8 @@ class HelpChannels(Scheduler, commands.Cog): f"using the `{constants.Bot.prefix}dormant` command within the channels." ) + self.bot.stats.incr("help.out_of_channel_alerts") + self.last_notification = message.created_at except Exception: # Handle it here cause this feature isn't critical for the functionality of the system. @@ -543,6 +558,8 @@ class HelpChannels(Scheduler, commands.Cog): await self.move_to_in_use(channel) await self.revoke_send_permissions(message.author) + self.bot.stats.incr("help.claimed") + log.trace(f"Releasing on_message lock for {message.id}.") # Move a dormant channel to the Available category to fill in the gap. diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py new file mode 100644 index 000000000..b75d29b7e --- /dev/null +++ b/bot/cogs/stats.py @@ -0,0 +1,65 @@ +from discord import Member, Message, Status +from discord.ext.commands import Bot, Cog, Context + + +class Stats(Cog): + """A cog which provides a way to hook onto Discord events and forward to stats.""" + + def __init__(self, bot: Bot): + self.bot = bot + + @Cog.listener() + async def on_message(self, message: Message) -> None: + """Report message events in the server to statsd.""" + if message.guild is None: + return + + reformatted_name = message.channel.name.replace('-', '_') + + if reformatted_name.startswith("ot"): + # Off-topic channels change names, we don't want this for stats. + # This will change 'ot1-lemon-in-the-dishwasher' to just 'ot1' + reformatted_name = reformatted_name[:3] + + stat_name = f"channels.{reformatted_name}" + self.bot.stats.incr(stat_name) + + # Increment the total message count + self.bot.stats.incr("messages") + + @Cog.listener() + async def on_command_completion(self, ctx: Context) -> None: + """Report completed commands to statsd.""" + command_name = ctx.command.qualified_name.replace(" ", "_") + + self.bot.stats.incr(f"commands.{command_name}") + + @Cog.listener() + async def on_member_join(self, member: Member) -> None: + """Update member count stat on member join.""" + self.bot.stats.gauge(f"guild.total_members", len(member.guild.members)) + + @Cog.listener() + async def on_member_leave(self, member: Member) -> None: + """Update member count stat on member leave.""" + self.bot.stats.gauge(f"guild.total_members", len(member.guild.members)) + + @Cog.listener() + async def on_member_update(self, _before: Member, after: Member) -> None: + """Update presence estimates on member update.""" + members = after.guild.members + + online = len([m for m in members if m.status == Status.online]) + idle = len([m for m in members if m.status == Status.idle]) + dnd = len([m for m in members if m.status == Status.do_not_disturb]) + offline = len([m for m in members if m.status == Status.offline]) + + self.bot.stats.gauge("guild.status.online", online) + self.bot.stats.gauge("guild.status.idle", idle) + self.bot.stats.gauge("guild.status.do_not_disturb", dnd) + self.bot.stats.gauge("guild.status.offline", offline) + + +def setup(bot: Bot) -> None: + """Load the stats cog.""" + bot.add_cog(Stats(bot)) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index a6e5952ff..b81859db1 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -207,6 +207,9 @@ class Tags(Cog): "time": time.time(), "channel": ctx.channel.id } + + self.bot.stats.incr(f"tags.usages.{tag_name.replace('-', '_')}") + await wait_for_deletion( await ctx.send(embed=Embed.from_dict(tag['embed'])), [ctx.author.id], diff --git a/bot/cogs/token_remover.py b/bot/cogs/token_remover.py index 421ad23e2..6721f0e02 100644 --- a/bot/cogs/token_remover.py +++ b/bot/cogs/token_remover.py @@ -93,6 +93,8 @@ class TokenRemover(Cog): channel_id=Channels.mod_alerts, ) + self.bot.stats.incr("tokens.removed_tokens") + @classmethod def find_token_in_message(cls, msg: Message) -> t.Optional[str]: """Return a seemingly valid token found in `msg` or `None` if no token is found.""" diff --git a/bot/cogs/webhook_remover.py b/bot/cogs/webhook_remover.py index 49692113d..1b5c3f821 100644 --- a/bot/cogs/webhook_remover.py +++ b/bot/cogs/webhook_remover.py @@ -54,6 +54,8 @@ class WebhookRemover(Cog): channel_id=Channels.mod_alerts ) + self.bot.stats.incr("tokens.removed_webhooks") + @Cog.listener() async def on_message(self, msg: Message) -> None: """Check if a Discord webhook URL is in `message`.""" diff --git a/bot/constants.py b/bot/constants.py index 60e3c4897..33c1d530d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -199,6 +199,7 @@ class Bot(metaclass=YAMLGetter): prefix: str token: str sentry_dsn: str + statsd_host: str class Filter(metaclass=YAMLGetter): section = "filter" diff --git a/config-default.yml b/config-default.yml index 896003973..567caacbf 100644 --- a/config-default.yml +++ b/config-default.yml @@ -3,6 +3,8 @@ bot: token: !ENV "BOT_TOKEN" sentry_dsn: !ENV "BOT_SENTRY_DSN" + statsd_host: "graphite" + cooldowns: # Per channel, per tag. tags: 60 -- cgit v1.2.3 From d5cd996864fe213d1c804911c2a17a6d04b8e170 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sun, 12 Apr 2020 01:00:27 +0100 Subject: Add a timeout to prevent the bot from being overloaded with presence updates --- bot/bot.py | 2 +- bot/cogs/stats.py | 12 ++++++++++-- bot/constants.py | 8 +++++++- config-default.yml | 4 +++- 4 files changed, 21 insertions(+), 5 deletions(-) (limited to 'config-default.yml') diff --git a/bot/bot.py b/bot/bot.py index ef4a325dc..6dd5ba896 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -33,7 +33,7 @@ class Bot(commands.Bot): self._resolver = None self._guild_available = asyncio.Event() - statsd_url = constants.Bot.statsd_host + statsd_url = constants.Stats.statsd_host if DEBUG_MODE: # Since statsd is UDP, there are no errors for sending to a down port. diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py index c15d0eb1b..df4827ba1 100644 --- a/bot/cogs/stats.py +++ b/bot/cogs/stats.py @@ -1,9 +1,10 @@ import string +from datetime import datetime from discord import Member, Message, Status from discord.ext.commands import Bot, Cog, Context -from bot.constants import Channels, Guild +from bot.constants import Channels, Guild, Stats as StatConf CHANNEL_NAME_OVERRIDES = { @@ -13,7 +14,7 @@ CHANNEL_NAME_OVERRIDES = { Channels.staff_lounge: "staff_lounge" } -ALLOWED_CHARS = string.ascii_letters + string.digits +ALLOWED_CHARS = string.ascii_letters + string.digits + "-" class Stats(Cog): @@ -21,6 +22,7 @@ class Stats(Cog): def __init__(self, bot: Bot): self.bot = bot + self.last_presence_update = None @Cog.listener() async def on_message(self, message: Message) -> None: @@ -73,6 +75,12 @@ class Stats(Cog): if after.guild.id != Guild.id: return + if self.last_presence_update: + if (datetime.now() - self.last_presence_update).seconds < StatConf.presence_update_timeout: + return + + self.last_presence_update = datetime.now() + online = 0 idle = 0 dnd = 0 diff --git a/bot/constants.py b/bot/constants.py index 33c1d530d..2add028e7 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -199,7 +199,6 @@ class Bot(metaclass=YAMLGetter): prefix: str token: str sentry_dsn: str - statsd_host: str class Filter(metaclass=YAMLGetter): section = "filter" @@ -351,6 +350,13 @@ class CleanMessages(metaclass=YAMLGetter): message_limit: int +class Stats(metaclass=YAMLGetter): + section = "bot" + subsection = "stats" + + presence_update_timeout: int + statsd_host: str + class Categories(metaclass=YAMLGetter): section = "guild" diff --git a/config-default.yml b/config-default.yml index 567caacbf..4cd61ce10 100644 --- a/config-default.yml +++ b/config-default.yml @@ -3,7 +3,9 @@ bot: token: !ENV "BOT_TOKEN" sentry_dsn: !ENV "BOT_SENTRY_DSN" - statsd_host: "graphite" + stats: + statsd_host: "graphite" + presence_update_timeout: 300 cooldowns: # Per channel, per tag. -- cgit v1.2.3 From b44caed7c5b26f13b4b31d237ffe07f3157aadfb Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Thu, 16 Apr 2020 16:21:25 +0200 Subject: Remove `.md` from anti-malware whitelist We want our members to use the paste site to share text-based files instead of them sharing the files as attachments on Discord. As `.md`, a file extensions used for plain-text files with markdown formatting, is such a text file, I've removed it from the anti-malware whitelist. --- config-default.yml | 1 - 1 file changed, 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 4cd61ce10..f2b0bfa9f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -475,7 +475,6 @@ anti_malware: - '.mp3' - '.wav' - '.ogg' - - '.md' reddit: -- cgit v1.2.3 From 5416280755631f7051e99e8a074af50c98974944 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 12 Apr 2020 11:56:54 -0700 Subject: Constants: add help channel cooldown role --- bot/constants.py | 1 + config-default.yml | 1 + 2 files changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 2add028e7..49098c9f2 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -421,6 +421,7 @@ class Roles(metaclass=YAMLGetter): announcements: int contributors: int core_developers: int + help_cooldown: int helpers: int jammers: int moderators: int diff --git a/config-default.yml b/config-default.yml index f2b0bfa9f..b0165adf6 100644 --- a/config-default.yml +++ b/config-default.yml @@ -201,6 +201,7 @@ guild: roles: announcements: 463658397560995840 contributors: 295488872404484098 + help_cooldown: 699189276025421825 muted: &MUTED_ROLE 277914926603829249 partners: 323426753857191936 python_community: &PY_COMMUNITY_ROLE 458226413825294336 -- cgit v1.2.3 From e5f30076304eac16d76b0daabead346253c7d9b4 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 20 Apr 2020 13:08:43 +0300 Subject: Added new category `python_news` to config, that hold mail lists, channel and webhook. This use local dev environment IDs. --- config-default.yml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index f2b0bfa9f..553afaa33 100644 --- a/config-default.yml +++ b/config-default.yml @@ -122,6 +122,7 @@ guild: channels: announcements: 354619224620138496 user_event_announcements: &USER_EVENT_A 592000283102674944 + python_news: &PYNEWS_CHANNEL 701667765102051398 # Development dev_contrib: &DEV_CONTRIB 635950537262759947 @@ -231,11 +232,12 @@ guild: - *HELPERS_ROLE webhooks: - talent_pool: 569145364800602132 - big_brother: 569133704568373283 - reddit: 635408384794951680 - duck_pond: 637821475327311927 - dev_log: 680501655111729222 + talent_pool: 569145364800602132 + big_brother: 569133704568373283 + reddit: 635408384794951680 + duck_pond: 637821475327311927 + dev_log: 680501655111729222 + python_news: &PYNEWS_WEBHOOK 701731296342179850 filter: @@ -568,5 +570,13 @@ duck_pond: - *DUCKY_MAUL - *DUCKY_SANTA +python_news: + mail_lists: + - 'python-ideas' + - 'python-announce-list' + - 'pypi-announce' + channel: *PYNEWS_CHANNEL + webhook: *PYNEWS_WEBHOOK + config: required_keys: ['bot.token'] -- cgit v1.2.3 From 6ba5999089ca1a9d79e32dd7ceefbf3d865c35f9 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 27 Apr 2020 20:21:35 +0300 Subject: Add Python News channel and webhook ID to config-default.yml Co-Authored-By: Joseph --- config-default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 553afaa33..2cc15c370 100644 --- a/config-default.yml +++ b/config-default.yml @@ -122,7 +122,7 @@ guild: channels: announcements: 354619224620138496 user_event_announcements: &USER_EVENT_A 592000283102674944 - python_news: &PYNEWS_CHANNEL 701667765102051398 + python_news: &PYNEWS_CHANNEL 704372456592506880 # Development dev_contrib: &DEV_CONTRIB 635950537262759947 @@ -237,7 +237,7 @@ guild: reddit: 635408384794951680 duck_pond: 637821475327311927 dev_log: 680501655111729222 - python_news: &PYNEWS_WEBHOOK 701731296342179850 + python_news: &PYNEWS_WEBHOOK 704381182279942324 filter: -- cgit v1.2.3 From 634dbc93645aebf87d102b1321001f2021def979 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Tue, 28 Apr 2020 01:29:09 +0200 Subject: Add option to ingore channels in help categories As we want to add an "informational" channel to the `Python Help: Available` category, we need to make sure that the Help Channel System ignores that channel. To do that, I've added an `is_excluded_channel` staticmethod that returns `True` if a channel is not a TextChannel or if it's in a special EXCLUDED_CHANNELS constant. This method is then used in the method that yields help channels from a category and in the `on_message` event listener that determines if a channel should be moved from `Available` to `Occupied`. --- bot/cogs/help_channels.py | 13 ++++++++++--- bot/constants.py | 1 + config-default.yml | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 3dea3b013..7aeaa2194 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -10,6 +10,7 @@ from datetime import datetime from pathlib import Path import discord +import discord.abc from discord.ext import commands from bot import constants @@ -21,6 +22,7 @@ log = logging.getLogger(__name__) ASKING_GUIDE_URL = "https://pythondiscord.com/pages/asking-good-questions/" MAX_CHANNELS_PER_CATEGORY = 50 +EXCLUDED_CHANNELS = (constants.Channels.how_to_get_help,) AVAILABLE_TOPIC = """ This channel is available. Feel free to ask a question in order to claim this channel! @@ -283,13 +285,18 @@ class HelpChannels(Scheduler, commands.Cog): return name + @staticmethod + def is_excluded_channel(channel: discord.abc.GuildChannel) -> bool: + """Check if a channel should be excluded from the help channel system.""" + return not isinstance(channel, discord.TextChannel) or channel.id in EXCLUDED_CHANNELS + def get_category_channels(self, category: discord.CategoryChannel) -> t.Iterable[discord.TextChannel]: """Yield the text channels of the `category` in an unsorted manner.""" log.trace(f"Getting text channels in the category '{category}' ({category.id}).") # This is faster than using category.channels because the latter sorts them. for channel in self.bot.get_guild(constants.Guild.id).channels: - if channel.category_id == category.id and isinstance(channel, discord.TextChannel): + if channel.category_id == category.id and not self.is_excluded_channel(channel): yield channel @staticmethod @@ -670,8 +677,8 @@ class HelpChannels(Scheduler, commands.Cog): await self.check_for_answer(message) - if not self.is_in_category(channel, constants.Categories.help_available): - return # Ignore messages outside the Available category. + if not self.is_in_category(channel, constants.Categories.help_available) or self.is_excluded_channel(channel): + return # Ignore messages outside the Available category or in excluded channels. log.trace("Waiting for the cog to be ready before processing messages.") await self.ready.wait() diff --git a/bot/constants.py b/bot/constants.py index 49098c9f2..a00b59505 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -383,6 +383,7 @@ class Channels(metaclass=YAMLGetter): dev_log: int esoteric: int helpers: int + how_to_get_help: int message_log: int meta: int mod_alerts: int diff --git a/config-default.yml b/config-default.yml index b0165adf6..78a2ff853 100644 --- a/config-default.yml +++ b/config-default.yml @@ -132,6 +132,9 @@ guild: meta: 429409067623251969 python_discussion: 267624335836053506 + # Python Help: Available + how_to_get_help: 704250143020417084 + # Logs attachment_log: &ATTACH_LOG 649243850006855680 message_log: &MESSAGE_LOG 467752170159079424 -- cgit v1.2.3 From debbe647589aa4c8d110cf7b25e4a68fe9eb5ff6 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sat, 2 May 2020 09:35:13 -0700 Subject: Remove mention command constants --- bot/constants.py | 7 ------- config-default.yml | 3 --- 2 files changed, 10 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index a00b59505..da29125eb 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -550,13 +550,6 @@ class HelpChannels(metaclass=YAMLGetter): notify_roles: List[int] -class Mention(metaclass=YAMLGetter): - section = 'mention' - - message_timeout: int - reset_delay: int - - class RedirectOutput(metaclass=YAMLGetter): section = 'redirect_output' diff --git a/config-default.yml b/config-default.yml index 78a2ff853..ff6790423 100644 --- a/config-default.yml +++ b/config-default.yml @@ -507,9 +507,6 @@ free: cooldown_rate: 1 cooldown_per: 60.0 -mention: - message_timeout: 300 - reset_delay: 5 help_channels: enable: true -- cgit v1.2.3 From 2368ab4d6f107868c40036438a7320a10d3c0184 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Wed, 6 May 2020 19:06:34 +0300 Subject: Fix config Webhook IDs formatting Co-authored-by: Sebastiaan Zeeff --- config-default.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 2cc15c370..90d5b1d29 100644 --- a/config-default.yml +++ b/config-default.yml @@ -232,12 +232,12 @@ guild: - *HELPERS_ROLE webhooks: - talent_pool: 569145364800602132 - big_brother: 569133704568373283 - reddit: 635408384794951680 - duck_pond: 637821475327311927 - dev_log: 680501655111729222 - python_news: &PYNEWS_WEBHOOK 704381182279942324 + talent_pool: 569145364800602132 + big_brother: 569133704568373283 + reddit: 635408384794951680 + duck_pond: 637821475327311927 + dev_log: 680501655111729222 + python_news: &PYNEWS_WEBHOOK 704381182279942324 filter: -- cgit v1.2.3 From 0c552b2dc3e88b5e13278cb705c371db48c72646 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Tue, 12 May 2020 21:29:35 -0400 Subject: Expand guild whitelist --- config-default.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index ff6790423..6d97b7f33 100644 --- a/config-default.yml +++ b/config-default.yml @@ -263,7 +263,8 @@ filter: guild_invite_whitelist: - 280033776820813825 # Functional Programming - 267624335836053506 # Python Discord - - 440186186024222721 # Python Discord: ModLog Emojis + - 440186186024222721 # Python Discord: Emojis 1 + - 578587418123304970 # Python Discord: Emojis 2 - 273944235143593984 # STEM - 348658686962696195 # RLBot - 531221516914917387 # Pallets @@ -280,6 +281,11 @@ filter: - 336642139381301249 # discord.py - 405403391410438165 # Sentdex - 172018499005317120 # The Coding Den + - 666560367173828639 # PyWeek + - 702724176489873509 # Microsoft Python + - 81384788765712384 # Discord API + - 613425648685547541 # Discord Developers + - 185590609631903755 # Blender Hub domain_blacklist: - pornhub.com -- cgit v1.2.3 From 258ad9d9c5601e01d135e706c256c0cd7f7fdbe0 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 17 May 2020 03:29:53 +0200 Subject: Make redis host and port configurable. --- bot/constants.py | 3 +++ bot/utils/redis_dict.py | 7 ++++++- config-default.yml | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index fd280e9de..01e8ac3a3 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -199,6 +199,9 @@ class Bot(metaclass=YAMLGetter): prefix: str token: str sentry_dsn: str + redis_host: str + redis_port: int + class Filter(metaclass=YAMLGetter): section = "filter" diff --git a/bot/utils/redis_dict.py b/bot/utils/redis_dict.py index c89765a24..dfb1c7252 100644 --- a/bot/utils/redis_dict.py +++ b/bot/utils/redis_dict.py @@ -7,6 +7,8 @@ from typing import Dict, List, Optional, Tuple, Union import redis as redis_py +from bot import constants + ValidRedisKey = Union[str, int, float] JSONSerializableType = Optional[Union[str, float, bool, Dict, List, Tuple, Enum]] @@ -24,7 +26,10 @@ class RedisDict(MutableMapping): """ _namespaces = [] - _redis = redis_py.Redis(host="redis") # Can be overridden for testing + _redis = redis_py.Redis( + host=constants.Bot.redis_host, + port=constants.Bot.redis_port, + ) # Can be overridden for testing def __init__(self, namespace: Optional[str] = None) -> None: """Initialize the RedisDict with the right namespace.""" diff --git a/config-default.yml b/config-default.yml index 83ea59016..722afa41b 100644 --- a/config-default.yml +++ b/config-default.yml @@ -2,6 +2,8 @@ bot: prefix: "!" token: !ENV "BOT_TOKEN" sentry_dsn: !ENV "BOT_SENTRY_DSN" + redis_host: "redis" + redis_port: 6379 stats: statsd_host: "graphite" -- cgit v1.2.3 From ecf7f24f05b9baa8705f3b2c2d044a42292fbc07 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 17 May 2020 19:50:12 +0200 Subject: Add the REDIS_PASSWORD environment variable In production, we will need this password to make a connection to Redis. --- bot/constants.py | 11 +++++++++-- bot/utils/redis_dict.py | 5 +++-- config-default.yml | 7 +++++-- 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 01e8ac3a3..5d854dd7a 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -199,8 +199,15 @@ class Bot(metaclass=YAMLGetter): prefix: str token: str sentry_dsn: str - redis_host: str - redis_port: int + + +class Redis(metaclass=YAMLGetter): + section = "bot" + subsection = "redis" + + host: str + port: int + password: str class Filter(metaclass=YAMLGetter): diff --git a/bot/utils/redis_dict.py b/bot/utils/redis_dict.py index 47905314a..4a5e34249 100644 --- a/bot/utils/redis_dict.py +++ b/bot/utils/redis_dict.py @@ -27,8 +27,9 @@ class RedisDict(MutableMapping): _namespaces = [] _redis = redis_py.Redis( - host=constants.Bot.redis_host, - port=constants.Bot.redis_port, + host=constants.Redis.host, + port=constants.Redis.port, + password=constants.Redis.password, ) # Can be overridden for testing def __init__(self, namespace: Optional[str] = None) -> None: diff --git a/config-default.yml b/config-default.yml index 722afa41b..3b58d9099 100644 --- a/config-default.yml +++ b/config-default.yml @@ -2,8 +2,11 @@ bot: prefix: "!" token: !ENV "BOT_TOKEN" sentry_dsn: !ENV "BOT_SENTRY_DSN" - redis_host: "redis" - redis_port: 6379 + + redis: + host: "redis" + port: 6379 + password: !ENV "REDIS_PASSWORD" stats: statsd_host: "graphite" -- cgit v1.2.3 From 1d36ec7001c35d96ff24f7493d26997c02891e93 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Mon, 18 May 2020 21:17:53 -0400 Subject: Add Steam gift card scam to domain blacklist --- config-default.yml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 83ea59016..c0b5b062f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -316,6 +316,8 @@ filter: - poweredbydialup.online - poweredbysecurity.org - poweredbysecurity.online + - ssteam.site + - steamwalletgift.com word_watchlist: - goo+ks* -- cgit v1.2.3 From 6c5979b88961cb1df3d669e07ae108d12e698119 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Thu, 21 May 2020 11:47:39 +0300 Subject: Config: Added new `HelpChannels` config `deleted_idle_minutes` This show how much minutes should this wait before making channel dormant when no messages in channel (original message deleted). --- bot/constants.py | 1 + config-default.yml | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index fd280e9de..3003c9d36 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -541,6 +541,7 @@ class HelpChannels(metaclass=YAMLGetter): claim_minutes: int cmd_whitelist: List[int] idle_minutes: int + deleted_idle_minutes: int max_available: int max_total_channels: int name_prefix: str diff --git a/config-default.yml b/config-default.yml index 83ea59016..2e8a777ba 100644 --- a/config-default.yml +++ b/config-default.yml @@ -529,6 +529,10 @@ help_channels: # Allowed duration of inactivity before making a channel dormant idle_minutes: 30 + # Allowed duration of inactivity when question message deleted + # and no one other sent before message making channel dormant. + deleted_idle_minutes: 5 + # Maximum number of channels to put in the available category max_available: 2 -- cgit v1.2.3 From 66d273f0b8f1de6850760f4d561db446c027fdfe Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 24 May 2020 15:21:35 +0200 Subject: Add an option to use fakeredis in Bot. Without this option, all contributors would need to set up a Redis server in order to run the bot. But with use_fakeredis set to True, this is no longer necessary because it will just set up a fakeredis redis pool instead of trying to contact an actual server. This is more than good enough for most local testing purposes, since data persistence across restarts isn't really relevant for them. This also means we need to move fakeredis into our real dependency list instead of having it as a dev dependency, so there's a minor change for that as well. I also made a small kaizen change to sort all the dependencies in the Pipfile alphabetically. --- Pipfile | 28 +++++++++++++------------- Pipfile.lock | 58 +++++++++++++++++++++++++++--------------------------- bot/bot.py | 26 +++++++++++++++++++----- bot/constants.py | 1 + config-default.yml | 1 + 5 files changed, 66 insertions(+), 48 deletions(-) (limited to 'config-default.yml') diff --git a/Pipfile b/Pipfile index cd2f2ad7a..b42ca6d58 100644 --- a/Pipfile +++ b/Pipfile @@ -4,30 +4,30 @@ verify_ssl = true name = "pypi" [packages] -discord.py = "~=1.3.2" +aio-pika = "~=6.1" aiodns = "~=2.0" aiohttp = "~=3.5" -sphinx = "~=2.2" -markdownify = "~=0.4" -lxml = "~=4.4" -pyyaml = "~=5.1" +aioredis = "~=1.3.1" +beautifulsoup4 = "~=4.9" +colorama = {version = "~=0.4.3",sys_platform = "== 'win32'"} +coloredlogs = "~=14.0" +deepdiff = "~=4.0" +discord.py = "~=1.3.2" +fakeredis = "~=1.4" +feedparser = "~=5.2" fuzzywuzzy = "~=0.17" -aio-pika = "~=6.1" +lxml = "~=4.4" +markdownify = "~=0.4" +more_itertools = "~=8.2" python-dateutil = "~=2.8" -deepdiff = "~=4.0" +pyyaml = "~=5.1" requests = "~=2.22" -more_itertools = "~=8.2" sentry-sdk = "~=0.14" -coloredlogs = "~=14.0" -colorama = {version = "~=0.4.3",sys_platform = "== 'win32'"} +sphinx = "~=2.2" statsd = "~=3.3" -feedparser = "~=5.2" -beautifulsoup4 = "~=4.9" -aioredis = "~=1.3.1" [dev-packages] coverage = "~=5.0" -fakeredis = "~=1.4" flake8 = "~=3.7" flake8-annotations = "~=2.0" flake8-bugbear = "~=20.1" diff --git a/Pipfile.lock b/Pipfile.lock index 1941f6887..0e591710c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "c0b3e4d3e2c9ddb6ba28d2c09d521fe90ad4ea3df5c7ea7cd3a8b679fb3f85f9" + "sha256": "0297accc3d614d3da8080b89d56ef7fe489c28a0ada8102df396a604af7ee330" }, "pipfile-spec": 6, "requires": { @@ -196,6 +196,14 @@ ], "version": "==0.16" }, + "fakeredis": { + "hashes": [ + "sha256:4d170886865a91dbc8b7f8cbd4e5d488f4c5f2f25dfae127f001617bbe9e8f97", + "sha256:647b2593d349d9d4e566c8dadb2e4c71ba35be5bdc4f1f7ac2d565a12a965053" + ], + "index": "pypi", + "version": "==1.4.1" + }, "feedparser": { "hashes": [ "sha256:bd030652c2d08532c034c27fcd7c85868e7fa3cb2b17f230a44a6bbc92519bf9", @@ -501,6 +509,13 @@ "index": "pypi", "version": "==5.3.1" }, + "redis": { + "hashes": [ + "sha256:2ef11f489003f151777c064c5dbc6653dfb9f3eade159bcadc524619fddc2242", + "sha256:6d65e84bc58091140081ee9d9c187aab0480097750fac44239307a3bdf0b1251" + ], + "version": "==3.5.2" + }, "requests": { "hashes": [ "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", @@ -531,6 +546,13 @@ ], "version": "==2.0.0" }, + "sortedcontainers": { + "hashes": [ + "sha256:974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a", + "sha256:d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60" + ], + "version": "==2.1.0" + }, "soupsieve": { "hashes": [ "sha256:1634eea42ab371d3d346309b93df7870a88610f0725d47528be902a0d95ecc55", @@ -718,14 +740,6 @@ ], "version": "==0.3.0" }, - "fakeredis": { - "hashes": [ - "sha256:4d170886865a91dbc8b7f8cbd4e5d488f4c5f2f25dfae127f001617bbe9e8f97", - "sha256:647b2593d349d9d4e566c8dadb2e4c71ba35be5bdc4f1f7ac2d565a12a965053" - ], - "index": "pypi", - "version": "==1.4.1" - }, "filelock": { "hashes": [ "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", @@ -735,11 +749,11 @@ }, "flake8": { "hashes": [ - "sha256:6c1193b0c3f853ef763969238f6c81e9e63ace9d024518edc020d5f1d6d93195", - "sha256:ea6623797bf9a52f4c9577d780da0bb17d65f870213f7b5bcc9fca82540c31d5" + "sha256:c69ac1668e434d37a2d2880b3ca9aafd54b3a10a3ac1ab101d22f29e29cf8634", + "sha256:ccaa799ef9893cebe69fdfefed76865aeaefbb94cb8545617b2298786a4de9a5" ], "index": "pypi", - "version": "==3.8.1" + "version": "==3.8.2" }, "flake8-annotations": { "hashes": [ @@ -805,10 +819,10 @@ }, "identify": { "hashes": [ - "sha256:23c18d97bb50e05be1a54917ee45cc61d57cb96aedc06aabb2b02331edf0dbf0", - "sha256:88ed90632023e52a6495749c6732e61e08ec9f4f04e95484a5c37b9caf40283c" + "sha256:0f3c3aac62b51b86fea6ff52fe8ff9e06f57f10411502443809064d23e16f1c2", + "sha256:f9ad3d41f01e98eb066b6e05c5b184fd1e925fadec48eb165b4e01c72a1ef3a7" ], - "version": "==1.4.15" + "version": "==1.4.16" }, "mccabe": { "hashes": [ @@ -877,13 +891,6 @@ "index": "pypi", "version": "==5.3.1" }, - "redis": { - "hashes": [ - "sha256:2ef11f489003f151777c064c5dbc6653dfb9f3eade159bcadc524619fddc2242", - "sha256:6d65e84bc58091140081ee9d9c187aab0480097750fac44239307a3bdf0b1251" - ], - "version": "==3.5.2" - }, "six": { "hashes": [ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", @@ -898,13 +905,6 @@ ], "version": "==2.0.0" }, - "sortedcontainers": { - "hashes": [ - "sha256:974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a", - "sha256:d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60" - ], - "version": "==2.1.0" - }, "toml": { "hashes": [ "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f", diff --git a/bot/bot.py b/bot/bot.py index 0d423201b..f1365d532 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -7,6 +7,7 @@ from typing import Optional import aiohttp import aioredis import discord +import fakeredis.aioredis from discord.ext import commands from sentry_sdk import push_scope @@ -48,11 +49,26 @@ class Bot(commands.Bot): self.stats = AsyncStatsClient(self.loop, statsd_url, 8125, prefix="bot") async def _create_redis_session(self) -> None: - """Create the Redis connection pool, and then open the redis event gate.""" - self.redis_session = await aioredis.create_redis_pool( - address=(constants.Redis.host, constants.Redis.port), - password=constants.Redis.password, - ) + """ + Create the Redis connection pool, and then open the redis event gate. + + If constants.Redis.use_fakeredis is True, we'll set up a fake redis pool instead + of attempting to communicate with a real Redis server. This is useful because it + means contributors don't necessarily need to get Redis running locally just + to run the bot. + + The fakeredis cache won't have persistence across restarts, but that + usually won't matter for local bot testing. + """ + if constants.Redis.use_fakeredis: + log.info("Using fakeredis instead of communicating with a real Redis server.") + self.redis_session = await fakeredis.aioredis.create_redis_pool() + else: + self.redis_session = await aioredis.create_redis_pool( + address=(constants.Redis.host, constants.Redis.port), + password=constants.Redis.password, + ) + self.redis_ready.set() def add_cog(self, cog: commands.Cog) -> None: diff --git a/bot/constants.py b/bot/constants.py index 5d854dd7a..75d394b6a 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -208,6 +208,7 @@ class Redis(metaclass=YAMLGetter): host: str port: int password: str + use_fakeredis: bool # If this is True, Bot will use fakeredis.aioredis class Filter(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 5be393463..cee955f20 100644 --- a/config-default.yml +++ b/config-default.yml @@ -7,6 +7,7 @@ bot: host: "redis" port: 6379 password: !ENV "REDIS_PASSWORD" + use_fakeredis: false stats: statsd_host: "graphite" -- cgit v1.2.3 From 185c9e84b5fde13ab21de614564eee94963d05b5 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sun, 24 May 2020 22:46:48 +0100 Subject: Add discord.gift to URL blacklist, closes #958 --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 2e98186f1..9a28be700 100644 --- a/config-default.yml +++ b/config-default.yml @@ -318,6 +318,7 @@ filter: - poweredbysecurity.online - ssteam.site - steamwalletgift.com + - discord.gift word_watchlist: - goo+ks* -- cgit v1.2.3 From 6cedfdc0b24ea44b86fca039c9d7335072abede6 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Tue, 26 May 2020 02:21:58 +0100 Subject: [stats] Do not report modmail channels to stats --- bot/cogs/stats.py | 8 +++++++- bot/constants.py | 2 ++ config-default.yml | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py index 9baf222e2..14409ecb0 100644 --- a/bot/cogs/stats.py +++ b/bot/cogs/stats.py @@ -6,7 +6,7 @@ from discord.ext.commands import Cog, Context from discord.ext.tasks import loop from bot.bot import Bot -from bot.constants import Channels, Guild, Stats as StatConf +from bot.constants import Categories, Channels, Guild, Stats as StatConf CHANNEL_NAME_OVERRIDES = { @@ -36,6 +36,12 @@ class Stats(Cog): if message.guild.id != Guild.id: return + if message.channel.category.id == Categories.modmail: + if message.channel.id != Channels.incidents: + # Do not report modmail channels to stats, there are too many + # of them for interesting statistics to be drawn out of this. + return + reformatted_name = message.channel.name.replace('-', '_') if CHANNEL_NAME_OVERRIDES.get(message.channel.id): diff --git a/bot/constants.py b/bot/constants.py index 3003c9d36..39de2ee41 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -365,6 +365,7 @@ class Categories(metaclass=YAMLGetter): help_available: int help_in_use: int help_dormant: int + modmail: int class Channels(metaclass=YAMLGetter): @@ -384,6 +385,7 @@ class Channels(metaclass=YAMLGetter): esoteric: int helpers: int how_to_get_help: int + incidents: int message_log: int meta: int mod_alerts: int diff --git a/config-default.yml b/config-default.yml index 9a28be700..c7d25894c 100644 --- a/config-default.yml +++ b/config-default.yml @@ -118,6 +118,7 @@ guild: help_available: 691405807388196926 help_in_use: 696958401460043776 help_dormant: 691405908919451718 + modmail: 714494672835444826 channels: announcements: 354619224620138496 @@ -164,6 +165,7 @@ guild: mod_spam: &MOD_SPAM 620607373828030464 organisation: &ORGANISATION 551789653284356126 staff_lounge: &STAFF_LOUNGE 464905259261755392 + incidents: 714214212200562749 # Voice admins_voice: &ADMINS_VOICE 500734494840717332 -- cgit v1.2.3 From 63a922e629af76692c4af3902a33942b13f784b6 Mon Sep 17 00:00:00 2001 From: Dennis Pham Date: Tue, 26 May 2020 17:11:49 -0400 Subject: Add /r/FlutterDev to the guild invite whitelist --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index c7d25894c..7edfb131f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -290,6 +290,7 @@ filter: - 81384788765712384 # Discord API - 613425648685547541 # Discord Developers - 185590609631903755 # Blender Hub + - 420324994703163402 # /r/FlutterDev domain_blacklist: - pornhub.com -- cgit v1.2.3 From 29ab6dc350f0063bcac2218aee7c9170e83f980a Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 8 Jun 2020 23:33:58 +0200 Subject: Incidents: add new emoji constants --- bot/constants.py | 4 ++++ config-default.yml | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index b31a9c99e..02b82cf23 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -271,6 +271,10 @@ class Emojis(metaclass=YAMLGetter): status_idle: str status_dnd: str + incident_actioned: str + incident_unactioned: str + incident_investigating: str + failmail: str trashcan: str diff --git a/config-default.yml b/config-default.yml index 2c85f5ef3..c59abdc39 100644 --- a/config-default.yml +++ b/config-default.yml @@ -38,6 +38,10 @@ style: status_dnd: "<:status_dnd:470326272082313216>" status_offline: "<:status_offline:470326266537705472>" + incident_actioned: "<:incident_actioned:719645530128646266>" + incident_unactioned: "<:incident_unactioned:719645583245180960>" + incident_investigating: "<:incident_investigating:719645658671480924>" + failmail: "<:failmail:633660039931887616>" trashcan: "<:trashcan:637136429717389331>" -- cgit v1.2.3 From 290f0982be7bf0f0a709d2c65bee413b11430ba3 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Tue, 9 Jun 2020 01:29:02 +0100 Subject: Add Python Atlanta to guild whitelists --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 2c85f5ef3..3a1bdae54 100644 --- a/config-default.yml +++ b/config-default.yml @@ -297,6 +297,7 @@ filter: - 613425648685547541 # Discord Developers - 185590609631903755 # Blender Hub - 420324994703163402 # /r/FlutterDev + - 488751051629920277 # Python Atlanta domain_blacklist: - pornhub.com -- cgit v1.2.3 From 16f160fda34c67c9840ed753b593d93d460a0d97 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Thu, 11 Jun 2020 12:44:17 +0100 Subject: Add cooldown channel to config-default.yml --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 3a1bdae54..3388e5f78 100644 --- a/config-default.yml +++ b/config-default.yml @@ -142,6 +142,7 @@ guild: # Python Help: Available how_to_get_help: 704250143020417084 + cooldown: 720603994149486673 # Logs attachment_log: &ATTACH_LOG 649243850006855680 -- cgit v1.2.3 From f4767769afc8c6dfe4ac81d4e9b9e02f2f58054c Mon Sep 17 00:00:00 2001 From: kwzrd Date: Thu, 11 Jun 2020 18:06:59 +0200 Subject: Incidents: add #incidents-archive channel constant --- bot/constants.py | 1 + config-default.yml | 1 + 2 files changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 02b82cf23..02c8adf43 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -401,6 +401,7 @@ class Channels(metaclass=YAMLGetter): helpers: int how_to_get_help: int incidents: int + incidents_archive: int message_log: int meta: int mod_alerts: int diff --git a/config-default.yml b/config-default.yml index c59abdc39..a68647f72 100644 --- a/config-default.yml +++ b/config-default.yml @@ -176,6 +176,7 @@ guild: organisation: &ORGANISATION 551789653284356126 staff_lounge: &STAFF_LOUNGE 464905259261755392 incidents: 714214212200562749 + incidents_archive: 720668923636351037 # Voice admins_voice: &ADMINS_VOICE 500734494840717332 -- cgit v1.2.3 From 5db3a82de9f37d769ed8983c83063dfdd6878fee Mon Sep 17 00:00:00 2001 From: kwzrd Date: Thu, 11 Jun 2020 18:26:21 +0200 Subject: Incidents: add #incidents-archive webhook constant --- bot/constants.py | 1 + config-default.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 02c8adf43..c663db333 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -430,6 +430,7 @@ class Webhooks(metaclass=YAMLGetter): reddit: int duck_pond: int dev_log: int + incidents_archive: int class Roles(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index a68647f72..974ce508d 100644 --- a/config-default.yml +++ b/config-default.yml @@ -255,7 +255,7 @@ guild: duck_pond: 637821475327311927 dev_log: 680501655111729222 python_news: &PYNEWS_WEBHOOK 704381182279942324 - + incidents_archive: 720671599790915702 filter: -- cgit v1.2.3 From 99a1734e8c6ace3e7a6418882f8dae40a3877534 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Fri, 8 May 2020 17:43:21 -0700 Subject: Code block: add configurable variables --- bot/cogs/codeblock/cog.py | 29 +++++++++++------------------ bot/cogs/codeblock/parsing.py | 3 ++- bot/constants.py | 9 +++++++++ config-default.yml | 21 +++++++++++++++++++-- 4 files changed, 41 insertions(+), 21 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/codeblock/cog.py b/bot/cogs/codeblock/cog.py index ecaf51aa0..e3917751b 100644 --- a/bot/cogs/codeblock/cog.py +++ b/bot/cogs/codeblock/cog.py @@ -6,8 +6,8 @@ import discord from discord import Message, RawMessageUpdateEvent from discord.ext.commands import Bot, Cog +from bot import constants from bot.cogs.token_remover import TokenRemover -from bot.constants import Channels, DEBUG_MODE from bot.utils import has_lines from bot.utils.channel import is_help_channel from bot.utils.messages import wait_for_deletion @@ -33,8 +33,7 @@ class CodeBlockCog(Cog, name="Code Block"): 1. Spaces before the language 2. No newline immediately following the language - Messages with 3 or fewer lines overall are ignored. Each code block is subject to this threshold - as well i.e. the text between the ticks must be greater than 3 lines. Detecting multiple code + Messages or code blocks must meet a minimum line count to be detected. Detecting multiple code blocks is supported. However, if at least one code block is correct, then instructions will not be sent even if others are incorrect. When multiple incorrect code blocks are found, only the first one is used as the basis for the instructions sent. @@ -45,23 +44,17 @@ class CodeBlockCog(Cog, name="Code Block"): show what is still incorrect after the user's edit. The embed can be manually deleted with a reaction. Otherwise, it will automatically be removed after 5 minutes. - The cog only detects messages in whitelisted channels. Channels may also have a 300-second - cooldown on the instructions being sent. See `__init__` for which channels are whitelisted or - have cooldowns enabled. Note that all help channels are also whitelisted with cooldowns enabled. + The cog only detects messages in whitelisted channels. Channels may also have a cooldown on the + instructions being sent. Note all help channels are also whitelisted with cooldowns enabled. + + For configurable parameters, see the `code_block` section in config-default.py. """ def __init__(self, bot: Bot): self.bot = bot # Stores allowed channels plus epoch times since the last instructional messages sent. - self.channel_cooldowns = { - Channels.python_discussion: 0, - } - - # These channels will also work, but will not be subject to a cooldown. - self.channel_whitelist = ( - Channels.bot_commands, - ) + self.channel_cooldowns = {channel: 0.0 for channel in constants.CodeBlock.cooldown_channels} # Maps users' messages to the messages the bot sent with instructions. self.codeblock_message_ids = {} @@ -102,7 +95,7 @@ class CodeBlockCog(Cog, name="Code Block"): return ( is_help_channel(channel) or channel.id in self.channel_cooldowns - or channel.id in self.channel_whitelist + or channel.id in constants.CodeBlock.channel_whitelist ) async def send_instructions(self, message: discord.Message, instructions: str) -> None: @@ -135,7 +128,7 @@ class CodeBlockCog(Cog, name="Code Block"): return ( not message.author.bot and self.is_valid_channel(message.channel) - and has_lines(message.content, 4) + and has_lines(message.content, constants.CodeBlock.minimum_lines) and not TokenRemover.find_token_in_message(message) ) @@ -147,7 +140,7 @@ class CodeBlockCog(Cog, name="Code Block"): return # When debugging, ignore cooldowns. - if self.is_on_cooldown(msg.channel) and not DEBUG_MODE: + if self.is_on_cooldown(msg.channel) and not constants.DEBUG_MODE: log.trace(f"Skipping code block detection of {msg.id}: #{msg.channel} is on cooldown.") return @@ -155,7 +148,7 @@ class CodeBlockCog(Cog, name="Code Block"): if instructions: await self.send_instructions(msg, instructions) - if msg.channel.id not in self.channel_whitelist: + if msg.channel.id not in constants.CodeBlock.channel_whitelist: log.debug(f"Adding #{msg.channel} to the channel cooldowns.") self.channel_cooldowns[msg.channel.id] = time.time() diff --git a/bot/cogs/codeblock/parsing.py b/bot/cogs/codeblock/parsing.py index 332a1deb0..89f8111fc 100644 --- a/bot/cogs/codeblock/parsing.py +++ b/bot/cogs/codeblock/parsing.py @@ -5,6 +5,7 @@ import logging import re from typing import NamedTuple, Optional, Sequence +from bot import constants from bot.utils import has_lines log = logging.getLogger(__name__) @@ -84,7 +85,7 @@ def find_code_blocks(message: str) -> Optional[Sequence[CodeBlock]]: if groups["tick"] == BACKTICK and language: log.trace("Message has a valid code block with a language; returning None.") return None - elif has_lines(groups["code"], 4): + elif has_lines(groups["code"], constants.CodeBlock.minimum_lines): code_block = CodeBlock(groups["code"], language, groups["tick"]) code_blocks.append(code_block) else: diff --git a/bot/constants.py b/bot/constants.py index 470221369..6c9654e89 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -540,6 +540,15 @@ class BigBrother(metaclass=YAMLGetter): header_message_limit: int +class CodeBlock(metaclass=YAMLGetter): + section = 'code_block' + + channel_whitelist: List[int] + cooldown_channels: List[int] + cooldown_seconds: int + minimum_lines: int + + class Free(metaclass=YAMLGetter): section = 'free' diff --git a/config-default.yml b/config-default.yml index 3388e5f78..845a20979 100644 --- a/config-default.yml +++ b/config-default.yml @@ -137,8 +137,8 @@ guild: dev_log: &DEV_LOG 622895325144940554 # Discussion - meta: 429409067623251969 - python_discussion: 267624335836053506 + meta: 429409067623251969 + python_discussion: &PY_DISCUSSION 267624335836053506 # Python Help: Available how_to_get_help: 704250143020417084 @@ -522,6 +522,23 @@ big_brother: header_message_limit: 15 +code_block: + # The channels in which code blocks will be detected. They are not subject to a cooldown. + channel_whitelist: + - *BOT_CMD + + # The channels which will be affected by a cooldown. These channels are also whitelisted. + cooldown_channels: + - *PY_DISCUSSION + + # Sending instructions triggers a cooldown on a per-channel basis. + # More instruction messages will not be sent in the same channel until the cooldown has elapsed. + cooldown_seconds: 300 + + # The minimum amount of lines a message or code block must have for instructions to be sent. + minimum_lines: 4 + + free: # Seconds to elapse for a channel # to be considered inactive. -- cgit v1.2.3 From 1d0cbbeb46a811b5a049d712aae1a90a1f3a7359 Mon Sep 17 00:00:00 2001 From: Dennis Pham Date: Mon, 15 Jun 2020 00:36:53 -0400 Subject: Add the C# guild to the whitelist --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 3388e5f78..aff5fb2e1 100644 --- a/config-default.yml +++ b/config-default.yml @@ -299,6 +299,7 @@ filter: - 185590609631903755 # Blender Hub - 420324994703163402 # /r/FlutterDev - 488751051629920277 # Python Atlanta + - 143867839282020352 # C# domain_blacklist: - pornhub.com -- cgit v1.2.3 From 778635241bf6c1a97f60f48a2bc9b40791a524e9 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Wed, 17 Jun 2020 19:15:31 +0100 Subject: Add LMGTFY to domain blacklist --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index aff5fb2e1..f111c64f5 100644 --- a/config-default.yml +++ b/config-default.yml @@ -331,6 +331,7 @@ filter: - ssteam.site - steamwalletgift.com - discord.gift + - lmgtfy.com word_watchlist: - goo+ks* -- cgit v1.2.3 From d10a61d3ef21cbf511304a97a5e2871bd1fcb2dd Mon Sep 17 00:00:00 2001 From: kwzrd Date: Thu, 9 Jul 2020 12:18:21 +0200 Subject: Config: refactor #incidents constants to lexicographical sorting Co-authored-by: MarkKoz --- bot/constants.py | 6 +++--- config-default.yml | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index b3ef1660f..cd660acee 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -427,12 +427,12 @@ class Webhooks(metaclass=YAMLGetter): section = "guild" subsection = "webhooks" - talent_pool: int big_brother: int - reddit: int - duck_pond: int dev_log: int + duck_pond: int incidents_archive: int + reddit: int + talent_pool: int class Roles(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 4c0196dc5..7fcc27d64 100644 --- a/config-default.yml +++ b/config-default.yml @@ -171,13 +171,13 @@ guild: admin_spam: &ADMIN_SPAM 563594791770914816 defcon: &DEFCON 464469101889454091 helpers: &HELPERS 385474242440986624 + incidents: 714214212200562749 + incidents_archive: 720668923636351037 mods: &MODS 305126844661760000 mod_alerts: &MOD_ALERTS 473092532147060736 mod_spam: &MOD_SPAM 620607373828030464 organisation: &ORGANISATION 551789653284356126 staff_lounge: &STAFF_LOUNGE 464905259261755392 - incidents: 714214212200562749 - incidents_archive: 720668923636351037 # Voice admins_voice: &ADMINS_VOICE 500734494840717332 @@ -250,13 +250,13 @@ guild: - *HELPERS_ROLE webhooks: - talent_pool: 569145364800602132 - big_brother: 569133704568373283 - reddit: 635408384794951680 - duck_pond: 637821475327311927 - dev_log: 680501655111729222 - python_news: &PYNEWS_WEBHOOK 704381182279942324 - incidents_archive: 720671599790915702 + big_brother: 569133704568373283 + dev_log: 680501655111729222 + duck_pond: 637821475327311927 + incidents_archive: 720671599790915702 + python_news: &PYNEWS_WEBHOOK 704381182279942324 + reddit: 635408384794951680 + talent_pool: 569145364800602132 filter: -- cgit v1.2.3 From 210c0a09b1bced80d03ed9ac81845f5f94c8b687 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 12 Jul 2020 13:23:22 +0200 Subject: Ping @Moderators in ModLog Instead of pinging @everyone, let's just ping the people who actually need to see the mod alerts or the modlogs, which would be the mods. `@everyone` is currently not permitted by our allowed_mentions setting, so this also restores pings to those channels. GitHub #1038 https://github.com/python-discord/bot/issues/1038 --- bot/cogs/antispam.py | 4 ++-- bot/cogs/filtering.py | 2 +- bot/cogs/moderation/modlog.py | 10 +++++----- bot/cogs/watchchannels/watchchannel.py | 4 ++-- bot/constants.py | 4 ++-- config-default.yml | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 0bcca578d..71382bba9 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -98,7 +98,7 @@ class DeletionContext: text=mod_alert_message, thumbnail=last_message.author.avatar_url_as(static_format="png"), channel_id=Channels.mod_alerts, - ping_everyone=AntiSpamConfig.ping_everyone + ping_moderators=AntiSpamConfig.ping_moderators ) @@ -132,7 +132,7 @@ class AntiSpam(Cog): await self.mod_log.send_log_message( title="Error: AntiSpam configuration validation failed!", text=body, - ping_everyone=True, + ping_moderators=True, icon_url=Icons.token_removed, colour=Colour.red() ) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 76ea68660..a5d59085f 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -329,7 +329,7 @@ class Filtering(Cog, Scheduler): text=message, thumbnail=msg.author.avatar_url_as(static_format="png"), channel_id=Channels.mod_alerts, - ping_everyone=Filter.ping_everyone, + ping_moderators=Filter.ping_moderators, additional_embeds=additional_embeds, additional_embeds_msg=additional_embeds_msg ) diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index ffbb87bbe..a37a9faf5 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -15,7 +15,7 @@ from discord.ext.commands import Cog, Context from discord.utils import escape_markdown from bot.bot import Bot -from bot.constants import Categories, Channels, Colours, Emojis, Event, Guild as GuildConstant, Icons, URLs +from bot.constants import Categories, Channels, Colours, Emojis, Event, Guild as GuildConstant, Icons, Roles, URLs from bot.utils.time import humanize_delta log = logging.getLogger(__name__) @@ -88,7 +88,7 @@ class ModLog(Cog, name="ModLog"): text: str, thumbnail: t.Optional[t.Union[str, discord.Asset]] = None, channel_id: int = Channels.mod_log, - ping_everyone: bool = False, + ping_moderators: bool = False, files: t.Optional[t.List[discord.File]] = None, content: t.Optional[str] = None, additional_embeds: t.Optional[t.List[discord.Embed]] = None, @@ -114,11 +114,11 @@ class ModLog(Cog, name="ModLog"): if thumbnail: embed.set_thumbnail(url=thumbnail) - if ping_everyone: + if ping_moderators: if content: - content = f"@everyone\n{content}" + content = f"<@&{Roles.moderators}>\n{content}" else: - content = "@everyone" + content = f"<@&{Roles.moderators}>" channel = self.bot.get_channel(channel_id) log_message = await channel.send(content=content, embed=embed, files=files) diff --git a/bot/cogs/watchchannels/watchchannel.py b/bot/cogs/watchchannels/watchchannel.py index 7c58a0fb5..8c4af4581 100644 --- a/bot/cogs/watchchannels/watchchannel.py +++ b/bot/cogs/watchchannels/watchchannel.py @@ -120,7 +120,7 @@ class WatchChannel(metaclass=CogABCMeta): await self.modlog.send_log_message( title=f"Error: Failed to initialize the {self.__class__.__name__} watch channel", text=message, - ping_everyone=True, + ping_moderators=True, icon_url=Icons.token_removed, colour=Color.red() ) @@ -132,7 +132,7 @@ class WatchChannel(metaclass=CogABCMeta): await self.modlog.send_log_message( title=f"Warning: Failed to retrieve user cache for the {self.__class__.__name__} watch channel", text="Could not retrieve the list of watched users from the API and messages will not be relayed.", - ping_everyone=True, + ping_moderators=True, icon_url=Icons.token_removed, colour=Color.red() ) diff --git a/bot/constants.py b/bot/constants.py index a1b392c82..34b312d2d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -225,7 +225,7 @@ class Filter(metaclass=YAMLGetter): notify_user_invites: bool notify_user_domains: bool - ping_everyone: bool + ping_moderators: bool offensive_msg_delete_days: int guild_invite_whitelist: List[int] domain_blacklist: List[str] @@ -522,7 +522,7 @@ class AntiSpam(metaclass=YAMLGetter): section = 'anti_spam' clean_offending: bool - ping_everyone: bool + ping_moderators: bool punishment: Dict[str, Dict[str, int]] rules: Dict[str, Dict[str, int]] diff --git a/config-default.yml b/config-default.yml index 64c4e715b..5dd96d67a 100644 --- a/config-default.yml +++ b/config-default.yml @@ -269,7 +269,7 @@ filter: notify_user_domains: false # Filter configuration - ping_everyone: true # Ping @everyone when we send a mod-alert? + ping_moderators: true # Ping @everyone when we send a mod-alert? offensive_msg_delete_days: 7 # How many days before deleting an offensive message? guild_invite_whitelist: @@ -428,7 +428,7 @@ urls: anti_spam: # Clean messages that violate a rule. clean_offending: true - ping_everyone: true + ping_moderators: true punishment: role_id: *MUTED_ROLE -- cgit v1.2.3 From cb5e361d04cd9c430bca4fb3496284e469d35c98 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 12 Jul 2020 14:40:26 +0200 Subject: Add the #dm_log ID to constants. https://github.com/python-discord/bot/issues/667 --- bot/constants.py | 1 + config-default.yml | 1 + 2 files changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index a1b392c82..074699025 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -416,6 +416,7 @@ class Channels(metaclass=YAMLGetter): user_log: int verification: int voice_log: int + dm_log: int class Webhooks(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 64c4e715b..d3ba45f88 100644 --- a/config-default.yml +++ b/config-default.yml @@ -150,6 +150,7 @@ guild: mod_log: &MOD_LOG 282638479504965634 user_log: 528976905546760203 voice_log: 640292421988646961 + dm_log: 653713721625018428 # Off-topic off_topic_0: 291284109232308226 -- cgit v1.2.3 From 3fd89d59081f2c906fa43265471d235f4f5b4749 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 12 Jul 2020 15:08:54 +0200 Subject: Remove pointless comment This comment violates the DRY principle. Co-authored-by: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 5dd96d67a..0f6a25ef2 100644 --- a/config-default.yml +++ b/config-default.yml @@ -269,7 +269,7 @@ filter: notify_user_domains: false # Filter configuration - ping_moderators: true # Ping @everyone when we send a mod-alert? + ping_moderators: true offensive_msg_delete_days: 7 # How many days before deleting an offensive message? guild_invite_whitelist: -- cgit v1.2.3 From 5007e736b93017003f02a75d12ce1ef8bae9fd69 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 12 Jul 2020 15:34:39 +0200 Subject: Replace channel ID with webhook ID for dm_log. https://github.com/python-discord/bot/issues/667 --- bot/constants.py | 2 +- config-default.yml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 074699025..3f44003a8 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -416,7 +416,6 @@ class Channels(metaclass=YAMLGetter): user_log: int verification: int voice_log: int - dm_log: int class Webhooks(metaclass=YAMLGetter): @@ -428,6 +427,7 @@ class Webhooks(metaclass=YAMLGetter): reddit: int duck_pond: int dev_log: int + dm_log: int class Roles(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index d3ba45f88..c09902a5d 100644 --- a/config-default.yml +++ b/config-default.yml @@ -150,7 +150,6 @@ guild: mod_log: &MOD_LOG 282638479504965634 user_log: 528976905546760203 voice_log: 640292421988646961 - dm_log: 653713721625018428 # Off-topic off_topic_0: 291284109232308226 @@ -252,10 +251,9 @@ guild: duck_pond: 637821475327311927 dev_log: 680501655111729222 python_news: &PYNEWS_WEBHOOK 704381182279942324 - + dm_log: 654567640664244225 filter: - # What do we filter? filter_zalgo: false filter_invites: true -- cgit v1.2.3 From 4527c038d21149d4d3fab73c54b9a1ad31e671c0 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Mon, 13 Jul 2020 00:17:37 +0200 Subject: Revert "Ping @Moderators in ModLog" Let's continue to use "@everyone" for now, and add an explicit allow for it so that it successfully pings people. There's a full justification for this in the pull request. https://github.com/python-discord/bot/issues/1038 --- bot/cogs/antispam.py | 4 ++-- bot/cogs/filtering.py | 2 +- bot/cogs/moderation/modlog.py | 17 +++++++++++------ bot/cogs/watchchannels/watchchannel.py | 4 ++-- bot/constants.py | 4 ++-- config-default.yml | 4 ++-- 6 files changed, 20 insertions(+), 15 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index 71382bba9..0bcca578d 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -98,7 +98,7 @@ class DeletionContext: text=mod_alert_message, thumbnail=last_message.author.avatar_url_as(static_format="png"), channel_id=Channels.mod_alerts, - ping_moderators=AntiSpamConfig.ping_moderators + ping_everyone=AntiSpamConfig.ping_everyone ) @@ -132,7 +132,7 @@ class AntiSpam(Cog): await self.mod_log.send_log_message( title="Error: AntiSpam configuration validation failed!", text=body, - ping_moderators=True, + ping_everyone=True, icon_url=Icons.token_removed, colour=Colour.red() ) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index a5d59085f..76ea68660 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -329,7 +329,7 @@ class Filtering(Cog, Scheduler): text=message, thumbnail=msg.author.avatar_url_as(static_format="png"), channel_id=Channels.mod_alerts, - ping_moderators=Filter.ping_moderators, + ping_everyone=Filter.ping_everyone, additional_embeds=additional_embeds, additional_embeds_msg=additional_embeds_msg ) diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py index a37a9faf5..0a63f57b8 100644 --- a/bot/cogs/moderation/modlog.py +++ b/bot/cogs/moderation/modlog.py @@ -15,7 +15,7 @@ from discord.ext.commands import Cog, Context from discord.utils import escape_markdown from bot.bot import Bot -from bot.constants import Categories, Channels, Colours, Emojis, Event, Guild as GuildConstant, Icons, Roles, URLs +from bot.constants import Categories, Channels, Colours, Emojis, Event, Guild as GuildConstant, Icons, URLs from bot.utils.time import humanize_delta log = logging.getLogger(__name__) @@ -88,7 +88,7 @@ class ModLog(Cog, name="ModLog"): text: str, thumbnail: t.Optional[t.Union[str, discord.Asset]] = None, channel_id: int = Channels.mod_log, - ping_moderators: bool = False, + ping_everyone: bool = False, files: t.Optional[t.List[discord.File]] = None, content: t.Optional[str] = None, additional_embeds: t.Optional[t.List[discord.Embed]] = None, @@ -114,14 +114,19 @@ class ModLog(Cog, name="ModLog"): if thumbnail: embed.set_thumbnail(url=thumbnail) - if ping_moderators: + if ping_everyone: if content: - content = f"<@&{Roles.moderators}>\n{content}" + content = f"@everyone\n{content}" else: - content = f"<@&{Roles.moderators}>" + content = "@everyone" channel = self.bot.get_channel(channel_id) - log_message = await channel.send(content=content, embed=embed, files=files) + log_message = await channel.send( + content=content, + embed=embed, + files=files, + allowed_mentions=discord.AllowedMentions(everyone=True) + ) if additional_embeds: if additional_embeds_msg: diff --git a/bot/cogs/watchchannels/watchchannel.py b/bot/cogs/watchchannels/watchchannel.py index 8c4af4581..7c58a0fb5 100644 --- a/bot/cogs/watchchannels/watchchannel.py +++ b/bot/cogs/watchchannels/watchchannel.py @@ -120,7 +120,7 @@ class WatchChannel(metaclass=CogABCMeta): await self.modlog.send_log_message( title=f"Error: Failed to initialize the {self.__class__.__name__} watch channel", text=message, - ping_moderators=True, + ping_everyone=True, icon_url=Icons.token_removed, colour=Color.red() ) @@ -132,7 +132,7 @@ class WatchChannel(metaclass=CogABCMeta): await self.modlog.send_log_message( title=f"Warning: Failed to retrieve user cache for the {self.__class__.__name__} watch channel", text="Could not retrieve the list of watched users from the API and messages will not be relayed.", - ping_moderators=True, + ping_everyone=True, icon_url=Icons.token_removed, colour=Color.red() ) diff --git a/bot/constants.py b/bot/constants.py index 34b312d2d..a1b392c82 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -225,7 +225,7 @@ class Filter(metaclass=YAMLGetter): notify_user_invites: bool notify_user_domains: bool - ping_moderators: bool + ping_everyone: bool offensive_msg_delete_days: int guild_invite_whitelist: List[int] domain_blacklist: List[str] @@ -522,7 +522,7 @@ class AntiSpam(metaclass=YAMLGetter): section = 'anti_spam' clean_offending: bool - ping_moderators: bool + ping_everyone: bool punishment: Dict[str, Dict[str, int]] rules: Dict[str, Dict[str, int]] diff --git a/config-default.yml b/config-default.yml index 0f6a25ef2..636b9db37 100644 --- a/config-default.yml +++ b/config-default.yml @@ -269,7 +269,7 @@ filter: notify_user_domains: false # Filter configuration - ping_moderators: true + ping_everyone: true offensive_msg_delete_days: 7 # How many days before deleting an offensive message? guild_invite_whitelist: @@ -428,7 +428,7 @@ urls: anti_spam: # Clean messages that violate a rule. clean_offending: true - ping_moderators: true + ping_everyone: true punishment: role_id: *MUTED_ROLE -- cgit v1.2.3 From c91ad4b74d4aea220ef564af3b1c044ab81a01d8 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Mon, 13 Jul 2020 21:19:30 +0200 Subject: Whitelisting some popular communities The following communities are whitelisted by this commit: - Django - Programming Discussions - JetBrains Community - Raspberry Pi - Programmers Hangout - SpeakJS - DevCord - Unity - Programmer Humor - Microsoft Community Most of these are partners, or otherwise friendly communities that aren't worth pinging mods over. --- config-default.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 636b9db37..19d79fa76 100644 --- a/config-default.yml +++ b/config-default.yml @@ -295,12 +295,22 @@ filter: - 172018499005317120 # The Coding Den - 666560367173828639 # PyWeek - 702724176489873509 # Microsoft Python + - 150662382874525696 # Microsoft Community - 81384788765712384 # Discord API - 613425648685547541 # Discord Developers - 185590609631903755 # Blender Hub - 420324994703163402 # /r/FlutterDev - 488751051629920277 # Python Atlanta - 143867839282020352 # C# + - 159039020565790721 # Django + - 238666723824238602 # Programming Discussions + - 433980600391696384 # JetBrains Community + - 204621105720328193 # Raspberry Pi + - 244230771232079873 # Programmers Hangout + - 239433591950540801 # SpeakJS + - 174075418410876928 # DevCord + - 489222168727519232 # Unity + - 494558898880118785 # Programmer Humor domain_blacklist: - pornhub.com -- cgit v1.2.3 From 042f472ac3207ad685a5acb659a5a69f22c72282 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Wed, 15 Jul 2020 01:09:35 +0200 Subject: Remove caching of last_dm_user. If you're typing up a reply and the bot gets another DM while you're typing, you might accidentally send your reply to the wrong person. This could happen even if you're very attentive, because it might be a matter of milliseconds. The complexity to prevent this isn't worth the convenience of the feature, and it's nice to get rid of the caching as well, so I've decided to just make .reply require a user for every reply. https://github.com/python-discord/bot/issues/1041 --- bot/cogs/dm_relay.py | 42 +++++++++++++++++------------------------- bot/constants.py | 2 ++ config-default.yml | 1 + 3 files changed, 20 insertions(+), 25 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/dm_relay.py b/bot/cogs/dm_relay.py index 3fce52b93..f62d6105e 100644 --- a/bot/cogs/dm_relay.py +++ b/bot/cogs/dm_relay.py @@ -1,5 +1,4 @@ import logging -from typing import Optional import discord from discord import Color @@ -8,9 +7,7 @@ from discord.ext.commands import Cog from bot import constants from bot.bot import Bot -from bot.constants import MODERATION_ROLES -from bot.utils import RedisCache -from bot.utils.checks import with_role_check +from bot.utils.checks import in_whitelist_check, with_role_check from bot.utils.messages import send_attachments from bot.utils.webhooks import send_webhook @@ -20,9 +17,6 @@ log = logging.getLogger(__name__) class DMRelay(Cog): """Relay direct messages to and from the bot.""" - # RedisCache[str, t.Union[discord.User.id, discord.Member.id]] - dm_cache = RedisCache() - def __init__(self, bot: Bot): self.bot = bot self.webhook_id = constants.Webhooks.dm_log @@ -30,11 +24,11 @@ class DMRelay(Cog): self.bot.loop.create_task(self.fetch_webhook()) @commands.command(aliases=("reply",)) - async def send_dm(self, ctx: commands.Context, member: Optional[discord.Member], *, message: str) -> None: + async def send_dm(self, ctx: commands.Context, member: discord.Member, *, message: str) -> None: """ Allows you to send a DM to a user from the bot. - If `member` is not provided, it will send to the last user who DM'd the bot. + A `member` must be provided. This feature should be used extremely sparingly. Use ModMail if you need to have a serious conversation with a user. This is just for responding to extraordinary DMs, having a little @@ -42,21 +36,11 @@ class DMRelay(Cog): NOTE: This feature will be removed if it is overused. """ - user_id = await self.dm_cache.get("last_user") - last_dm_user = ctx.guild.get_member(user_id) if user_id else None - try: - if member: - await member.send(message) - await ctx.message.add_reaction("✅") - return - elif last_dm_user: - await last_dm_user.send(message) - await ctx.message.add_reaction("✅") - return - else: - log.debug("This bot has never gotten a DM, or the RedisCache has been cleared.") - await ctx.message.add_reaction("❌") + await member.send(message) + await ctx.message.add_reaction("✅") + return + except discord.errors.Forbidden: log.debug("User has disabled DMs.") await ctx.message.add_reaction("❌") @@ -84,7 +68,6 @@ class DMRelay(Cog): username=message.author.display_name, avatar_url=message.author.avatar_url ) - await self.dm_cache.set("last_user", message.author.id) # Handle any attachments if message.attachments: @@ -106,7 +89,16 @@ class DMRelay(Cog): def cog_check(self, ctx: commands.Context) -> bool: """Only allow moderators to invoke the commands in this cog.""" - return with_role_check(ctx, *MODERATION_ROLES) + checks = [ + with_role_check(ctx, *constants.MODERATION_ROLES), + in_whitelist_check( + ctx, + channels=[constants.Channels.dm_log], + redirect=None, + fail_silently=True, + ) + ] + return all(checks) def setup(bot: Bot) -> None: diff --git a/bot/constants.py b/bot/constants.py index 3f44003a8..778bc093c 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -395,6 +395,7 @@ class Channels(metaclass=YAMLGetter): dev_contrib: int dev_core: int dev_log: int + dm_log: int esoteric: int helpers: int how_to_get_help: int @@ -461,6 +462,7 @@ class Guild(metaclass=YAMLGetter): staff_channels: List[int] staff_roles: List[int] + class Keys(metaclass=YAMLGetter): section = "keys" diff --git a/config-default.yml b/config-default.yml index d12b9be27..8061e5e16 100644 --- a/config-default.yml +++ b/config-default.yml @@ -150,6 +150,7 @@ guild: mod_log: &MOD_LOG 282638479504965634 user_log: 528976905546760203 voice_log: 640292421988646961 + dm_log: 653713721625018428 # Off-topic off_topic_0: 291284109232308226 -- cgit v1.2.3 From d07b1af634787f53ee381d31a4c125498af52beb Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sat, 18 Jul 2020 15:55:56 +0200 Subject: Remove Filtering constants, use cache data. Instead of fetching the guild invite IDs from config-default.yml, we will now be using the AllowDenyList cache to check these. --- bot/cogs/filtering.py | 62 ++++++++++++++++--------------- bot/constants.py | 4 -- config-default.yml | 101 -------------------------------------------------- 3 files changed, 32 insertions(+), 135 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index bd665f424..9e35a83d1 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -22,6 +22,7 @@ from bot.utils.scheduling import Scheduler log = logging.getLogger(__name__) +# Regular expressions INVITE_RE = re.compile( r"(?:discord(?:[\.,]|dot)gg|" # Could be discord.gg/ r"discord(?:[\.,]|dot)com(?:\/|slash)invite|" # or discord.com/invite/ @@ -37,25 +38,8 @@ SPOILER_RE = re.compile(r"(\|\|.+?\|\|)", re.DOTALL) URL_RE = re.compile(r"(https?://[^\s]+)", flags=re.IGNORECASE) ZALGO_RE = re.compile(r"[\u0300-\u036F\u0489]") -WORD_WATCHLIST_PATTERNS = [ - re.compile(fr'\b{expression}\b', flags=re.IGNORECASE) for expression in Filter.word_watchlist -] -TOKEN_WATCHLIST_PATTERNS = [ - re.compile(fr'{expression}', flags=re.IGNORECASE) for expression in Filter.token_watchlist -] -WATCHLIST_PATTERNS = WORD_WATCHLIST_PATTERNS + TOKEN_WATCHLIST_PATTERNS - +# Other constants. DAYS_BETWEEN_ALERTS = 3 - - -def expand_spoilers(text: str) -> str: - """Return a string containing all interpretations of a spoilered message.""" - split_text = SPOILER_RE.split(text) - return ''.join( - split_text[0::2] + split_text[1::2] + split_text - ) - - OFFENSIVE_MSG_DELETE_TIME = timedelta(days=Filter.offensive_msg_delete_days) @@ -125,6 +109,23 @@ class Filtering(Cog): self.bot.loop.create_task(self.reschedule_offensive_msg_deletion()) + def _get_allowlist_items(self, allow: bool, list_type: str, compiled: Optional[bool] = False) -> list: + """Fetch items from the allow_deny_list_cache.""" + items = self.bot.allow_deny_list_cache[f"{list_type}.{allow}"] + + if compiled: + return [re.compile(fr'{item.get("content")}', flags=re.IGNORECASE) for item in items] + else: + return [item.get("content") for item in items] + + @staticmethod + def _expand_spoilers(text: str) -> str: + """Return a string containing all interpretations of a spoilered message.""" + split_text = SPOILER_RE.split(text) + return ''.join( + split_text[0::2] + split_text[1::2] + split_text + ) + @property def mod_log(self) -> ModLog: """Get currently loaded ModLog cog instance.""" @@ -149,11 +150,11 @@ class Filtering(Cog): delta = relativedelta(after.edited_at, before.edited_at).microseconds await self._filter_message(after, delta) - @staticmethod - def get_name_matches(name: str) -> List[re.Match]: + def get_name_matches(self, name: str) -> List[re.Match]: """Check bad words from passed string (name). Return list of matches.""" matches = [] - for pattern in WATCHLIST_PATTERNS: + watchlist_patterns = self._get_allowlist_items(False, 'word_watchlist', compiled=True) + for pattern in watchlist_patterns: if match := pattern.search(name): matches.append(match) return matches @@ -403,8 +404,7 @@ class Filtering(Cog): and not msg.author.bot # Author not a bot ) - @staticmethod - async def _has_watch_regex_match(text: str) -> Union[bool, re.Match]: + async def _has_watch_regex_match(self, text: str) -> Union[bool, re.Match]: """ Return True if `text` matches any regex from `word_watchlist` or `token_watchlist` configs. @@ -412,26 +412,27 @@ class Filtering(Cog): matched as-is. Spoilers are expanded, if any, and URLs are ignored. """ if SPOILER_RE.search(text): - text = expand_spoilers(text) + text = self._expand_spoilers(text) # Make sure it's not a URL if URL_RE.search(text): return False - for pattern in WATCHLIST_PATTERNS: + watchlist_patterns = self._get_allowlist_items(False, 'word_watchlist', compiled=True) + for pattern in watchlist_patterns: match = pattern.search(text) if match: return match - @staticmethod - async def _has_urls(text: str) -> bool: + async def _has_urls(self, text: str) -> bool: """Returns True if the text contains one of the blacklisted URLs from the config file.""" if not URL_RE.search(text): return False text = text.lower() + domain_blacklist = self._get_allowlist_items(False, "domain_name") - for url in Filter.domain_blacklist: + for url in domain_blacklist: if url.lower() in text: return True @@ -476,9 +477,10 @@ class Filtering(Cog): # between invalid and expired invites return True - guild_id = int(guild.get("id")) + guild_id = guild.get("id") + guild_invite_whitelist = self._get_allowlist_items(True, "guild_invite_id") - if guild_id not in Filter.guild_invite_whitelist: + if guild_id not in guild_invite_whitelist: guild_icon_hash = guild["icon"] guild_icon = ( "https://cdn.discordapp.com/icons/" diff --git a/bot/constants.py b/bot/constants.py index 778bc093c..f5245ca50 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -227,10 +227,6 @@ class Filter(metaclass=YAMLGetter): ping_everyone: bool offensive_msg_delete_days: int - guild_invite_whitelist: List[int] - domain_blacklist: List[str] - word_watchlist: List[str] - token_watchlist: List[str] channel_whitelist: List[int] role_whitelist: List[int] diff --git a/config-default.yml b/config-default.yml index f2eb17b89..81c8c40d5 100644 --- a/config-default.yml +++ b/config-default.yml @@ -272,107 +272,6 @@ filter: ping_everyone: true offensive_msg_delete_days: 7 # How many days before deleting an offensive message? - guild_invite_whitelist: - - 280033776820813825 # Functional Programming - - 267624335836053506 # Python Discord - - 440186186024222721 # Python Discord: Emojis 1 - - 578587418123304970 # Python Discord: Emojis 2 - - 273944235143593984 # STEM - - 348658686962696195 # RLBot - - 531221516914917387 # Pallets - - 249111029668249601 # Gentoo - - 327254708534116352 # Adafruit - - 544525886180032552 # kennethreitz.org - - 590806733924859943 # Discord Hack Week - - 423249981340778496 # Kivy - - 197038439483310086 # Discord Testers - - 286633898581164032 # Ren'Py - - 349505959032389632 # PyGame - - 438622377094414346 # Pyglet - - 524691714909274162 # Panda3D - - 336642139381301249 # discord.py - - 405403391410438165 # Sentdex - - 172018499005317120 # The Coding Den - - 666560367173828639 # PyWeek - - 702724176489873509 # Microsoft Python - - 150662382874525696 # Microsoft Community - - 81384788765712384 # Discord API - - 613425648685547541 # Discord Developers - - 185590609631903755 # Blender Hub - - 420324994703163402 # /r/FlutterDev - - 488751051629920277 # Python Atlanta - - 143867839282020352 # C# - - 159039020565790721 # Django - - 238666723824238602 # Programming Discussions - - 433980600391696384 # JetBrains Community - - 204621105720328193 # Raspberry Pi - - 244230771232079873 # Programmers Hangout - - 239433591950540801 # SpeakJS - - 174075418410876928 # DevCord - - 489222168727519232 # Unity - - 494558898880118785 # Programmer Humor - - domain_blacklist: - - pornhub.com - - liveleak.com - - grabify.link - - bmwforum.co - - leancoding.co - - spottyfly.com - - stopify.co - - yoütu.be - - discörd.com - - minecräft.com - - freegiftcards.co - - disçordapp.com - - fortnight.space - - fortnitechat.site - - joinmy.site - - curiouscat.club - - catsnthings.fun - - yourtube.site - - youtubeshort.watch - - catsnthing.com - - youtubeshort.pro - - canadianlumberjacks.online - - poweredbydialup.club - - poweredbydialup.online - - poweredbysecurity.org - - poweredbysecurity.online - - ssteam.site - - steamwalletgift.com - - discord.gift - - lmgtfy.com - - word_watchlist: - - goo+ks* - - ky+s+ - - ki+ke+s* - - beaner+s? - - coo+ns* - - nig+lets* - - slant-eyes* - - towe?l-?head+s* - - chi*n+k+s* - - spick*s* - - kill* +(?:yo)?urself+ - - jew+s* - - suicide - - rape - - (re+)tar+(d+|t+)(ed)? - - ta+r+d+ - - cunts* - - trann*y - - shemale - - token_watchlist: - - fa+g+s* - - 卐 - - 卍 - - cuck(?!oo+) - - nigg+(?:e*r+|a+h*?|u+h+)s? - - fag+o+t+s* - # Censor doesn't apply to these channel_whitelist: - *ADMINS -- cgit v1.2.3 From 1c569f2f38fe18d6210deec001046cf9ee68ea53 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sat, 18 Jul 2020 16:54:01 +0200 Subject: Remove AntiMalWare constants, use cache data. Also updates the tests for this cog. --- bot/bot.py | 2 +- bot/cogs/antimalware.py | 24 ++++++++++++++---------- bot/constants.py | 6 ------ config-default.yml | 29 ----------------------------- tests/bot/cogs/test_antimalware.py | 24 +++++++++++++++--------- 5 files changed, 30 insertions(+), 55 deletions(-) (limited to 'config-default.yml') diff --git a/bot/bot.py b/bot/bot.py index 6c02e72a7..962c8dd93 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -34,6 +34,7 @@ class Bot(commands.Bot): self.redis_ready = asyncio.Event() self.redis_closed = False self.api_client = api.APIClient(loop=self.loop) + self.allow_deny_list_cache = {} self._connector = None self._resolver = None @@ -52,7 +53,6 @@ class Bot(commands.Bot): async def _cache_allow_deny_list_data(self) -> None: """Cache all the data in the AllowDenyList on the site.""" full_cache = await self.api_client.get('bot/allow_deny_lists') - self.allow_deny_list_cache = {} for item in full_cache: type_ = item.get("type") diff --git a/bot/cogs/antimalware.py b/bot/cogs/antimalware.py index ea257442e..38ff1133d 100644 --- a/bot/cogs/antimalware.py +++ b/bot/cogs/antimalware.py @@ -6,7 +6,7 @@ from discord import Embed, Message, NotFound from discord.ext.commands import Cog from bot.bot import Bot -from bot.constants import AntiMalware as AntiMalwareConfig, Channels, STAFF_ROLES, URLs +from bot.constants import Channels, STAFF_ROLES, URLs log = logging.getLogger(__name__) @@ -27,7 +27,7 @@ TXT_EMBED_DESCRIPTION = ( DISALLOWED_EMBED_DESCRIPTION = ( "It looks like you tried to attach file type(s) that we do not allow ({blocked_extensions_str}). " - f"We currently allow the following file types: **{', '.join(AntiMalwareConfig.whitelist)}**.\n\n" + "We currently allow the following file types: **{joined_whitelist}**.\n\n" "Feel free to ask in {meta_channel_mention} if you think this is a mistake." ) @@ -38,6 +38,16 @@ class AntiMalware(Cog): def __init__(self, bot: Bot): self.bot = bot + def _get_whitelisted_file_formats(self) -> list: + """Get the file formats currently on the whitelist.""" + return [item.get('content') for item in self.bot.allow_deny_list_cache['file_format.True']] + + def _get_disallowed_extensions(self, message: Message) -> t.Iterable[str]: + """Get an iterable containing all the disallowed extensions of attachments.""" + file_extensions = {splitext(attachment.filename.lower())[1] for attachment in message.attachments} + extensions_blocked = file_extensions - set(self._get_whitelisted_file_formats()) + return extensions_blocked + @Cog.listener() async def on_message(self, message: Message) -> None: """Identify messages with prohibited attachments.""" @@ -51,7 +61,7 @@ class AntiMalware(Cog): return embed = Embed() - extensions_blocked = self.get_disallowed_extensions(message) + extensions_blocked = self._get_disallowed_extensions(message) blocked_extensions_str = ', '.join(extensions_blocked) if ".py" in extensions_blocked: # Short-circuit on *.py files to provide a pastebin link @@ -63,6 +73,7 @@ class AntiMalware(Cog): elif extensions_blocked: meta_channel = self.bot.get_channel(Channels.meta) embed.description = DISALLOWED_EMBED_DESCRIPTION.format( + joined_whitelist=', '.join(self._get_whitelisted_file_formats()), blocked_extensions_str=blocked_extensions_str, meta_channel_mention=meta_channel.mention, ) @@ -81,13 +92,6 @@ class AntiMalware(Cog): except NotFound: log.info(f"Tried to delete message `{message.id}`, but message could not be found.") - @classmethod - def get_disallowed_extensions(cls, message: Message) -> t.Iterable[str]: - """Get an iterable containing all the disallowed extensions of attachments.""" - file_extensions = {splitext(attachment.filename.lower())[1] for attachment in message.attachments} - extensions_blocked = file_extensions - set(AntiMalwareConfig.whitelist) - return extensions_blocked - def setup(bot: Bot) -> None: """Load the AntiMalware cog.""" diff --git a/bot/constants.py b/bot/constants.py index f5245ca50..857e6c4f0 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -527,12 +527,6 @@ class AntiSpam(metaclass=YAMLGetter): rules: Dict[str, Dict[str, int]] -class AntiMalware(metaclass=YAMLGetter): - section = "anti_malware" - - whitelist: list - - class BigBrother(metaclass=YAMLGetter): section = 'big_brother' diff --git a/config-default.yml b/config-default.yml index 81c8c40d5..503cc2b52 100644 --- a/config-default.yml +++ b/config-default.yml @@ -386,35 +386,6 @@ anti_spam: max: 3 -anti_malware: - whitelist: - - '.3gp' - - '.3g2' - - '.avi' - - '.bmp' - - '.gif' - - '.h264' - - '.jpg' - - '.jpeg' - - '.m4v' - - '.mkv' - - '.mov' - - '.mp4' - - '.mpeg' - - '.mpg' - - '.png' - - '.tiff' - - '.wmv' - - '.svg' - - '.psd' # Photoshop - - '.ai' # Illustrator - - '.aep' # After Effects - - '.xcf' # GIMP - - '.mp3' - - '.wav' - - '.ogg' - - reddit: subreddits: - 'r/Python' diff --git a/tests/bot/cogs/test_antimalware.py b/tests/bot/cogs/test_antimalware.py index f219fc1ba..1e010d2ce 100644 --- a/tests/bot/cogs/test_antimalware.py +++ b/tests/bot/cogs/test_antimalware.py @@ -1,28 +1,33 @@ import unittest -from unittest.mock import AsyncMock, Mock, patch +from unittest.mock import AsyncMock, Mock from discord import NotFound from bot.cogs import antimalware -from bot.constants import AntiMalware as AntiMalwareConfig, Channels, STAFF_ROLES +from bot.constants import Channels, STAFF_ROLES from tests.helpers import MockAttachment, MockBot, MockMessage, MockRole -MODULE = "bot.cogs.antimalware" - -@patch(f"{MODULE}.AntiMalwareConfig.whitelist", new=[".first", ".second", ".third"]) class AntiMalwareCogTests(unittest.IsolatedAsyncioTestCase): """Test the AntiMalware cog.""" def setUp(self): """Sets up fresh objects for each test.""" self.bot = MockBot() + self.bot.allow_deny_list_cache = { + "file_format.True": [ + {"content": ".first"}, + {"content": ".second"}, + {"content": ".third"} + ] + } self.cog = antimalware.AntiMalware(self.bot) self.message = MockMessage() + self.whitelist = [".first", ".second", ".third"] async def test_message_with_allowed_attachment(self): """Messages with allowed extensions should not be deleted""" - attachment = MockAttachment(filename=f"python{AntiMalwareConfig.whitelist[0]}") + attachment = MockAttachment(filename="python.first") self.message.attachments = [attachment] await self.cog.on_message(self.message) @@ -93,7 +98,7 @@ class AntiMalwareCogTests(unittest.IsolatedAsyncioTestCase): self.assertEqual(embed.description, antimalware.TXT_EMBED_DESCRIPTION.format.return_value) antimalware.TXT_EMBED_DESCRIPTION.format.assert_called_with(cmd_channel_mention=cmd_channel.mention) - async def test_other_disallowed_extention_embed_description(self): + async def test_other_disallowed_extension_embed_description(self): """Test the description for a non .py/.txt disallowed extension.""" attachment = MockAttachment(filename="python.disallowed") self.message.attachments = [attachment] @@ -109,6 +114,7 @@ class AntiMalwareCogTests(unittest.IsolatedAsyncioTestCase): self.assertEqual(embed.description, antimalware.DISALLOWED_EMBED_DESCRIPTION.format.return_value) antimalware.DISALLOWED_EMBED_DESCRIPTION.format.assert_called_with( + joined_whitelist=", ".join(self.whitelist), blocked_extensions_str=".disallowed", meta_channel_mention=meta_channel.mention ) @@ -135,7 +141,7 @@ class AntiMalwareCogTests(unittest.IsolatedAsyncioTestCase): """The return value should include all non-whitelisted extensions.""" test_values = ( ([], []), - (AntiMalwareConfig.whitelist, []), + (self.whitelist, []), ([".first"], []), ([".first", ".disallowed"], [".disallowed"]), ([".disallowed"], [".disallowed"]), @@ -145,7 +151,7 @@ class AntiMalwareCogTests(unittest.IsolatedAsyncioTestCase): for extensions, expected_disallowed_extensions in test_values: with self.subTest(extensions=extensions, expected_disallowed_extensions=expected_disallowed_extensions): self.message.attachments = [MockAttachment(filename=f"filename{extension}") for extension in extensions] - disallowed_extensions = self.cog.get_disallowed_extensions(self.message) + disallowed_extensions = self.cog._get_disallowed_extensions(self.message) self.assertCountEqual(disallowed_extensions, expected_disallowed_extensions) -- cgit v1.2.3 From be14db91b1c70993773e67cfa663fef0cfa85666 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 23 Jul 2020 18:27:55 +0100 Subject: Disabled burst_shared filter temporarily --- config-default.yml | 4 ---- 1 file changed, 4 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index ad6149f6f..d0262be33 100644 --- a/config-default.yml +++ b/config-default.yml @@ -459,10 +459,6 @@ anti_spam: interval: 10 max: 7 - burst_shared: - interval: 10 - max: 20 - chars: interval: 5 max: 3_000 -- cgit v1.2.3 From 71b9ab4e1e9d75e9240bc0c6825f43d978ef922b Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Mon, 27 Jul 2020 12:18:25 +0200 Subject: Update IDs of Code Jam roles I've updated the IDs of the two Code Jam Roles to the newly create roles we have. --- config-default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index d0262be33..fc093cc32 100644 --- a/config-default.yml +++ b/config-default.yml @@ -236,8 +236,8 @@ guild: owners: &OWNERS_ROLE 267627879762755584 # Code Jam - jammers: 591786436651646989 - team_leaders: 501324292341104650 + jammers: 737249140966162473 + team_leaders: 737250302834638889 moderation_roles: - *OWNERS_ROLE -- cgit v1.2.3 From 239fa5f43ab79435151657671ebcf21eac706fc6 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Tue, 4 Aug 2020 15:30:34 +0100 Subject: Revert "Disabled burst_shared filter temporarily" This reverts commit be14db91b1c70993773e67cfa663fef0cfa85666. --- config-default.yml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 14a073611..aacbe170f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -358,6 +358,10 @@ anti_spam: interval: 10 max: 7 + burst_shared: + interval: 10 + max: 20 + chars: interval: 5 max: 3_000 -- cgit v1.2.3 From 226af0e676e072696dba503e3873deeaf73202ac Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 4 Aug 2020 18:01:47 +0200 Subject: Verification: add @Unverified role to config --- bot/constants.py | 1 + config-default.yml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index cf4f3f666..cce64a7c4 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -454,6 +454,7 @@ class Roles(metaclass=YAMLGetter): partners: int python_community: int team_leaders: int + unverified: int verified: int # This is the Developers role on PyDis, here named verified for readability reasons. diff --git a/config-default.yml b/config-default.yml index fc093cc32..21a3eca87 100644 --- a/config-default.yml +++ b/config-default.yml @@ -225,8 +225,8 @@ guild: partners: 323426753857191936 python_community: &PY_COMMUNITY_ROLE 458226413825294336 - # This is the Developers role on PyDis, here named verified for readability reasons - verified: 352427296948486144 + unverified: 739794855945044069 + verified: 352427296948486144 # @Developers on PyDis # Staff admins: &ADMINS_ROLE 267628507062992896 -- cgit v1.2.3 From 2e46838aa561d93f70351d08ea275fd0c8b95de2 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 4 Aug 2020 13:50:19 -0700 Subject: HelpChannels: more accurate empty check The bot's pin message was being picked up as the last message, so the system was not considering the channel empty. --- bot/cogs/help_channels.py | 18 +++++++++++++++--- config-default.yml | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index d826463af..5ecf40e54 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -737,9 +737,21 @@ class HelpChannels(commands.Cog): self.scheduler.schedule_later(delay, msg.channel.id, self.move_idle_channel(msg.channel)) async def is_empty(self, channel: discord.TextChannel) -> bool: - """Return True if the most recent message in `channel` is the bot's `AVAILABLE_MSG`.""" - msg = await self.get_last_message(channel) - return self.match_bot_embed(msg, AVAILABLE_MSG) + """Return True if there's an AVAILABLE_MSG and the messages leading up are bot messages.""" + found = False + + # A limit of 100 results in a single API call. + # If AVAILABLE_MSG isn't found within 100 messages, then assume the channel is not empty. + # Not gonna do an extensive search for it cause it's too expensive. + async for msg in channel.history(limit=100): + if not msg.author.bot: + return False + + if self.match_bot_embed(msg, AVAILABLE_MSG): + found = True + break + + return found async def check_cooldowns(self) -> None: """Remove expired cooldowns and re-schedule active ones.""" diff --git a/config-default.yml b/config-default.yml index aacbe170f..4bd90511c 100644 --- a/config-default.yml +++ b/config-default.yml @@ -432,8 +432,8 @@ help_channels: # Allowed duration of inactivity before making a channel dormant idle_minutes: 30 - # Allowed duration of inactivity when question message deleted - # and no one other sent before message making channel dormant. + # Allowed duration of inactivity when channel is empty (due to deleted messages) + # before message making a channel dormant deleted_idle_minutes: 5 # Maximum number of channels to put in the available category -- cgit v1.2.3 From a36e04b70c3090b128ac80221582f140c196b20f Mon Sep 17 00:00:00 2001 From: Numerlor <25886452+Numerlor@users.noreply.github.com> Date: Mon, 10 Aug 2020 01:54:18 +0200 Subject: Remove unused api endpoint config constants. The constants aren't used anywhere in the bot, and are incompatible with the APIClient. --- bot/constants.py | 14 -------------- config-default.yml | 17 ----------------- 2 files changed, 31 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 9d00eac36..6baa04ec5 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -488,22 +488,8 @@ class URLs(metaclass=YAMLGetter): # Site endpoints site: str site_api: str - site_superstarify_api: str - site_logs_api: str site_logs_view: str - site_reminders_api: str - site_reminders_user_api: str site_schema: str - site_settings_api: str - site_tags_api: str - site_user_api: str - site_user_complete_api: str - site_infractions: str - site_infractions_user: str - site_infractions_type: str - site_infractions_by_id: str - site_infractions_user_type_current: str - site_infractions_user_type: str paste_service: str diff --git a/config-default.yml b/config-default.yml index 4bd90511c..e3ba9fb05 100644 --- a/config-default.yml +++ b/config-default.yml @@ -309,24 +309,7 @@ urls: site_staff: &STAFF !JOIN ["staff.", *DOMAIN] site_schema: &SCHEMA "https://" - site_bigbrother_api: !JOIN [*SCHEMA, *API, "/bot/bigbrother"] - site_docs_api: !JOIN [*SCHEMA, *API, "/bot/docs"] - site_superstarify_api: !JOIN [*SCHEMA, *API, "/bot/superstarify"] - site_infractions: !JOIN [*SCHEMA, *API, "/bot/infractions"] - site_infractions_user: !JOIN [*SCHEMA, *API, "/bot/infractions/user/{user_id}"] - site_infractions_type: !JOIN [*SCHEMA, *API, "/bot/infractions/type/{infraction_type}"] - site_infractions_by_id: !JOIN [*SCHEMA, *API, "/bot/infractions/id/{infraction_id}"] - site_infractions_user_type_current: !JOIN [*SCHEMA, *API, "/bot/infractions/user/{user_id}/{infraction_type}/current"] - site_infractions_user_type: !JOIN [*SCHEMA, *API, "/bot/infractions/user/{user_id}/{infraction_type}"] - site_logs_api: !JOIN [*SCHEMA, *API, "/bot/logs"] site_logs_view: !JOIN [*SCHEMA, *STAFF, "/bot/logs"] - site_off_topic_names_api: !JOIN [*SCHEMA, *API, "/bot/off-topic-names"] - site_reminders_api: !JOIN [*SCHEMA, *API, "/bot/reminders"] - site_reminders_user_api: !JOIN [*SCHEMA, *API, "/bot/reminders/user"] - site_settings_api: !JOIN [*SCHEMA, *API, "/bot/settings"] - site_tags_api: !JOIN [*SCHEMA, *API, "/bot/tags"] - site_user_api: !JOIN [*SCHEMA, *API, "/bot/users"] - site_user_complete_api: !JOIN [*SCHEMA, *API, "/bot/users/complete"] paste_service: !JOIN [*SCHEMA, *PASTE, "/{key}"] # Snekbox -- cgit v1.2.3 From f87db13ee549c64723086948b101292da93934d8 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Fri, 14 Aug 2020 21:13:05 +0100 Subject: Add YAML values for badges --- config-default.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index e3ba9fb05..8c0092e76 100644 --- a/config-default.yml +++ b/config-default.yml @@ -38,6 +38,17 @@ style: status_dnd: "<:status_dnd:470326272082313216>" status_offline: "<:status_offline:470326266537705472>" + badge_staff: "<:discord_staff:743882896498098226>" + badge_partner: "<:partner:743882897131569323>" + badge_hypesquad: "<:hypesquad_events:743882896892362873>" + badge_bug_hunter: "<:bug_hunter_lvl1:743882896372269137>" + badge_hypesquad_bravery: "<:hypesquad_bravery:743882896745693335>" + badge_hypesquad_brilliance: "<:hypesquad_brilliance:743882896938631248>" + badge_hypesquad_balance: "<:hypesquad_balance:743882896460480625>" + badge_early_supporter: "<:early_supporter:743882896909140058>" + badge_bug_hunter_level_2: "<:bug_hunter_lvl2:743882896611344505>" + badge_verified_bot_developer: "<:verified_bot_dev:743882897299210310>" + incident_actioned: "<:incident_actioned:719645530128646266>" incident_unactioned: "<:incident_unactioned:719645583245180960>" incident_investigating: "<:incident_investigating:719645658671480924>" -- cgit v1.2.3 From a565bb529cbfcb241a7cf63c114a17f695451721 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Wed, 26 Aug 2020 18:31:42 +0200 Subject: Verification: add guild invite to config --- bot/constants.py | 1 + config-default.yml | 1 + 2 files changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 0902858ac..daef6c095 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -458,6 +458,7 @@ class Guild(metaclass=YAMLGetter): section = "guild" id: int + invite: str # Discord invite, gets embedded in chat moderation_channels: List[int] moderation_roles: List[int] modlog_blacklist: List[int] diff --git a/config-default.yml b/config-default.yml index 58bdbe20f..a98fd14ef 100644 --- a/config-default.yml +++ b/config-default.yml @@ -123,6 +123,7 @@ style: guild: id: 267624335836053506 + invite: "https://discord.gg/python" categories: help_available: 691405807388196926 -- cgit v1.2.3 From 7016124192f3228145195765b1c94535700e54aa Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 27 Aug 2020 23:14:38 +0100 Subject: Update Discord Partner badge --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 8c0092e76..b4dc34e85 100644 --- a/config-default.yml +++ b/config-default.yml @@ -39,7 +39,7 @@ style: status_offline: "<:status_offline:470326266537705472>" badge_staff: "<:discord_staff:743882896498098226>" - badge_partner: "<:partner:743882897131569323>" + badge_partner: "<:partner:748666453242413136>" badge_hypesquad: "<:hypesquad_events:743882896892362873>" badge_bug_hunter: "<:bug_hunter_lvl1:743882896372269137>" badge_hypesquad_bravery: "<:hypesquad_bravery:743882896745693335>" -- cgit v1.2.3 From 8b10533851ca3fe3b44dd6662f634ae89550ad16 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 29 Aug 2020 01:38:04 -0700 Subject: Completely gutted the wolfram command. Moved to seasonalbot/bot/exts/evergreen/wolfram.py --- bot/cogs/wolfram.py | 280 ---------------------------------------------------- bot/constants.py | 8 -- config-default.yml | 7 -- 3 files changed, 295 deletions(-) delete mode 100644 bot/cogs/wolfram.py (limited to 'config-default.yml') diff --git a/bot/cogs/wolfram.py b/bot/cogs/wolfram.py deleted file mode 100644 index e6cae3bb8..000000000 --- a/bot/cogs/wolfram.py +++ /dev/null @@ -1,280 +0,0 @@ -import logging -from io import BytesIO -from typing import Callable, List, Optional, Tuple -from urllib import parse - -import discord -from dateutil.relativedelta import relativedelta -from discord import Embed -from discord.ext import commands -from discord.ext.commands import BucketType, Cog, Context, check, group - -from bot.bot import Bot -from bot.constants import Colours, STAFF_ROLES, Wolfram -from bot.pagination import ImagePaginator -from bot.utils.time import humanize_delta - -log = logging.getLogger(__name__) - -APPID = Wolfram.key -DEFAULT_OUTPUT_FORMAT = "JSON" -QUERY = "http://api.wolframalpha.com/v2/{request}?{data}" -WOLF_IMAGE = "https://www.symbols.com/gi.php?type=1&id=2886&i=1" - -MAX_PODS = 20 - -# Allows for 10 wolfram calls pr user pr day -usercd = commands.CooldownMapping.from_cooldown(Wolfram.user_limit_day, 60*60*24, BucketType.user) - -# Allows for max api requests / days in month per day for the entire guild (Temporary) -guildcd = commands.CooldownMapping.from_cooldown(Wolfram.guild_limit_day, 60*60*24, BucketType.guild) - - -async def send_embed( - ctx: Context, - message_txt: str, - colour: int = Colours.soft_red, - footer: str = None, - img_url: str = None, - f: discord.File = None -) -> None: - """Generate & send a response embed with Wolfram as the author.""" - embed = Embed(colour=colour) - embed.description = message_txt - embed.set_author(name="Wolfram Alpha", - icon_url=WOLF_IMAGE, - url="https://www.wolframalpha.com/") - if footer: - embed.set_footer(text=footer) - - if img_url: - embed.set_image(url=img_url) - - await ctx.send(embed=embed, file=f) - - -def custom_cooldown(*ignore: List[int]) -> Callable: - """ - Implement per-user and per-guild cooldowns for requests to the Wolfram API. - - A list of roles may be provided to ignore the per-user cooldown - """ - async def predicate(ctx: Context) -> bool: - if ctx.invoked_with == 'help': - # if the invoked command is help we don't want to increase the ratelimits since it's not actually - # invoking the command/making a request, so instead just check if the user/guild are on cooldown. - guild_cooldown = not guildcd.get_bucket(ctx.message).get_tokens() == 0 # if guild is on cooldown - if not any(r.id in ignore for r in ctx.author.roles): # check user bucket if user is not ignored - return guild_cooldown and not usercd.get_bucket(ctx.message).get_tokens() == 0 - return guild_cooldown - - user_bucket = usercd.get_bucket(ctx.message) - - if all(role.id not in ignore for role in ctx.author.roles): - user_rate = user_bucket.update_rate_limit() - - if user_rate: - # Can't use api; cause: member limit - delta = relativedelta(seconds=int(user_rate)) - cooldown = humanize_delta(delta) - message = ( - "You've used up your limit for Wolfram|Alpha requests.\n" - f"Cooldown: {cooldown}" - ) - await send_embed(ctx, message) - return False - - guild_bucket = guildcd.get_bucket(ctx.message) - guild_rate = guild_bucket.update_rate_limit() - - # Repr has a token attribute to read requests left - log.debug(guild_bucket) - - if guild_rate: - # Can't use api; cause: guild limit - message = ( - "The max limit of requests for the server has been reached for today.\n" - f"Cooldown: {int(guild_rate)}" - ) - await send_embed(ctx, message) - return False - - return True - return check(predicate) - - -async def get_pod_pages(ctx: Context, bot: Bot, query: str) -> Optional[List[Tuple]]: - """Get the Wolfram API pod pages for the provided query.""" - async with ctx.channel.typing(): - url_str = parse.urlencode({ - "input": query, - "appid": APPID, - "output": DEFAULT_OUTPUT_FORMAT, - "format": "image,plaintext" - }) - request_url = QUERY.format(request="query", data=url_str) - - async with bot.http_session.get(request_url) as response: - json = await response.json(content_type='text/plain') - - result = json["queryresult"] - - if result["error"]: - # API key not set up correctly - if result["error"]["msg"] == "Invalid appid": - message = "Wolfram API key is invalid or missing." - log.warning( - "API key seems to be missing, or invalid when " - f"processing a wolfram request: {url_str}, Response: {json}" - ) - await send_embed(ctx, message) - return - - message = "Something went wrong internally with your request, please notify staff!" - log.warning(f"Something went wrong getting a response from wolfram: {url_str}, Response: {json}") - await send_embed(ctx, message) - return - - if not result["success"]: - message = f"I couldn't find anything for {query}." - await send_embed(ctx, message) - return - - if not result["numpods"]: - message = "Could not find any results." - await send_embed(ctx, message) - return - - pods = result["pods"] - pages = [] - for pod in pods[:MAX_PODS]: - subs = pod.get("subpods") - - for sub in subs: - title = sub.get("title") or sub.get("plaintext") or sub.get("id", "") - img = sub["img"]["src"] - pages.append((title, img)) - return pages - - -class Wolfram(Cog): - """Commands for interacting with the Wolfram|Alpha API.""" - - def __init__(self, bot: Bot): - self.bot = bot - - @group(name="wolfram", aliases=("wolf", "wa"), invoke_without_command=True) - @custom_cooldown(*STAFF_ROLES) - async def wolfram_command(self, ctx: Context, *, query: str) -> None: - """Requests all answers on a single image, sends an image of all related pods.""" - url_str = parse.urlencode({ - "i": query, - "appid": APPID, - }) - query = QUERY.format(request="simple", data=url_str) - - # Give feedback that the bot is working. - async with ctx.channel.typing(): - async with self.bot.http_session.get(query) as response: - status = response.status - image_bytes = await response.read() - - f = discord.File(BytesIO(image_bytes), filename="image.png") - image_url = "attachment://image.png" - - if status == 501: - message = "Failed to get response" - footer = "" - color = Colours.soft_red - elif status == 400: - message = "No input found" - footer = "" - color = Colours.soft_red - elif status == 403: - message = "Wolfram API key is invalid or missing." - footer = "" - color = Colours.soft_red - else: - message = "" - footer = "View original for a bigger picture." - color = Colours.soft_orange - - # Sends a "blank" embed if no request is received, unsure how to fix - await send_embed(ctx, message, color, footer=footer, img_url=image_url, f=f) - - @wolfram_command.command(name="page", aliases=("pa", "p")) - @custom_cooldown(*STAFF_ROLES) - async def wolfram_page_command(self, ctx: Context, *, query: str) -> None: - """ - Requests a drawn image of given query. - - Keywords worth noting are, "like curve", "curve", "graph", "pokemon", etc. - """ - pages = await get_pod_pages(ctx, self.bot, query) - - if not pages: - return - - embed = Embed() - embed.set_author(name="Wolfram Alpha", - icon_url=WOLF_IMAGE, - url="https://www.wolframalpha.com/") - embed.colour = Colours.soft_orange - - await ImagePaginator.paginate(pages, ctx, embed) - - @wolfram_command.command(name="cut", aliases=("c",)) - @custom_cooldown(*STAFF_ROLES) - async def wolfram_cut_command(self, ctx: Context, *, query: str) -> None: - """ - Requests a drawn image of given query. - - Keywords worth noting are, "like curve", "curve", "graph", "pokemon", etc. - """ - pages = await get_pod_pages(ctx, self.bot, query) - - if not pages: - return - - if len(pages) >= 2: - page = pages[1] - else: - page = pages[0] - - await send_embed(ctx, page[0], colour=Colours.soft_orange, img_url=page[1]) - - @wolfram_command.command(name="short", aliases=("sh", "s")) - @custom_cooldown(*STAFF_ROLES) - async def wolfram_short_command(self, ctx: Context, *, query: str) -> None: - """Requests an answer to a simple question.""" - url_str = parse.urlencode({ - "i": query, - "appid": APPID, - }) - query = QUERY.format(request="result", data=url_str) - - # Give feedback that the bot is working. - async with ctx.channel.typing(): - async with self.bot.http_session.get(query) as response: - status = response.status - response_text = await response.text() - - if status == 501: - message = "Failed to get response" - color = Colours.soft_red - elif status == 400: - message = "No input found" - color = Colours.soft_red - elif response_text == "Error 1: Invalid appid": - message = "Wolfram API key is invalid or missing." - color = Colours.soft_red - else: - message = response_text - color = Colours.soft_orange - - await send_embed(ctx, message, color) - - -def setup(bot: Bot) -> None: - """Load the Wolfram cog.""" - bot.add_cog(Wolfram(bot)) diff --git a/bot/constants.py b/bot/constants.py index f3db80279..17fe34e95 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -514,14 +514,6 @@ class Reddit(metaclass=YAMLGetter): secret: Optional[str] -class Wolfram(metaclass=YAMLGetter): - section = "wolfram" - - user_limit_day: int - guild_limit_day: int - key: Optional[str] - - class AntiSpam(metaclass=YAMLGetter): section = 'anti_spam' diff --git a/config-default.yml b/config-default.yml index b4dc34e85..a0f601728 100644 --- a/config-default.yml +++ b/config-default.yml @@ -393,13 +393,6 @@ reddit: secret: !ENV "REDDIT_SECRET" -wolfram: - # Max requests per day. - user_limit_day: 10 - guild_limit_day: 67 - key: !ENV "WOLFRAM_API_KEY" - - big_brother: log_delay: 15 header_message_limit: 15 -- cgit v1.2.3 From 40ad0def564109884c607c78f95c67518d7a70a5 Mon Sep 17 00:00:00 2001 From: MrAwesomeRocks <42477863+MrAwesomeRocks@users.noreply.github.com> Date: Fri, 28 Aug 2020 11:53:08 -0500 Subject: Everyone Ping: Add rules to default config file --- config-default.yml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 8c0092e76..3a5918983 100644 --- a/config-default.yml +++ b/config-default.yml @@ -385,6 +385,9 @@ anti_spam: interval: 10 max: 3 + everyone_ping: + enabled: true + reddit: subreddits: -- cgit v1.2.3 From f873e685e34f1af62f2bc49bc3e37265c327b3ea Mon Sep 17 00:00:00 2001 From: MrAwesomeRocks <42477863+MrAwesomeRocks@users.noreply.github.com> Date: Fri, 28 Aug 2020 19:30:34 -0500 Subject: Everyone Ping: Added required values to config The `max` and `interval` values were required, so they were added to the config file and the rule was modified to accept these new values. --- bot/rules/everyone_ping.py | 2 +- config-default.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/bot/rules/everyone_ping.py b/bot/rules/everyone_ping.py index 29a734478..342727093 100644 --- a/bot/rules/everyone_ping.py +++ b/bot/rules/everyone_ping.py @@ -14,7 +14,7 @@ async def apply( ) ev_msgs_ct = 0 - if config["enabled"]: + if config["max"]: for msg in relevant_messages: ev_role = msg.guild.default_role msg_roles = msg.role_mentions diff --git a/config-default.yml b/config-default.yml index 3a5918983..18d7f4b0e 100644 --- a/config-default.yml +++ b/config-default.yml @@ -386,7 +386,8 @@ anti_spam: max: 3 everyone_ping: - enabled: true + interval: 1 + max: 1 reddit: -- cgit v1.2.3 From c55b7e3749166d06f66193692a7ded5d1317a154 Mon Sep 17 00:00:00 2001 From: MrAwesomeRocks <42477863+MrAwesomeRocks@users.noreply.github.com> Date: Fri, 28 Aug 2020 20:21:01 -0500 Subject: Everyone Ping: Fixed rule, edited config Changed the method of checking for an everyone ping. Also changed the config to act as `min pings` instead of `ping enabled/disabled`. --- bot/rules/everyone_ping.py | 16 ++++++---------- config-default.yml | 4 ++-- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'config-default.yml') diff --git a/bot/rules/everyone_ping.py b/bot/rules/everyone_ping.py index 342727093..bfc400831 100644 --- a/bot/rules/everyone_ping.py +++ b/bot/rules/everyone_ping.py @@ -14,18 +14,14 @@ async def apply( ) ev_msgs_ct = 0 - if config["max"]: - for msg in relevant_messages: - ev_role = msg.guild.default_role - msg_roles = msg.role_mentions + for msg in relevant_messages: + if '@everyone' in msg.content: + ev_msgs_ct += 1 - if ev_role in msg_roles: - ev_msgs_ct += 1 - - if ev_msgs_ct > 0: + if ev_msgs_ct >= config['max']: return ( - f"pinged the everyone role {ev_msgs_ct} times", - (last_message.author), + f"pinged the everyone role {ev_msgs_ct} times in {config['interval']}s", + (last_message.author,), relevant_messages, ) return None diff --git a/config-default.yml b/config-default.yml index 18d7f4b0e..8546b5310 100644 --- a/config-default.yml +++ b/config-default.yml @@ -386,8 +386,8 @@ anti_spam: max: 3 everyone_ping: - interval: 1 - max: 1 + interval: 10 + max: 0 reddit: -- cgit v1.2.3 From 203abc99ad104ddef068ef2ddddff37a9982c47d Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Wed, 2 Sep 2020 13:42:45 -0700 Subject: Constants: remove staff_channels No longer being used anywhere. --- bot/constants.py | 2 -- config-default.yml | 9 --------- 2 files changed, 11 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index f3db80279..b3825ea02 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -472,7 +472,6 @@ class Guild(metaclass=YAMLGetter): moderation_roles: List[int] modlog_blacklist: List[int] reminder_whitelist: List[int] - staff_channels: List[int] staff_roles: List[int] @@ -624,7 +623,6 @@ MODERATION_ROLES = Guild.moderation_roles STAFF_ROLES = Guild.staff_roles # Channel combinations -STAFF_CHANNELS = Guild.staff_channels MODERATION_CHANNELS = Guild.moderation_channels # Bot replies diff --git a/config-default.yml b/config-default.yml index 8c0092e76..9d29b9a96 100644 --- a/config-default.yml +++ b/config-default.yml @@ -199,15 +199,6 @@ guild: big_brother_logs: &BB_LOGS 468507907357409333 talent_pool: &TALENT_POOL 534321732593647616 - staff_channels: - - *ADMINS - - *ADMIN_SPAM - - *DEFCON - - *HELPERS - - *MODS - - *MOD_SPAM - - *ORGANISATION - moderation_channels: - *ADMINS - *ADMIN_SPAM -- cgit v1.2.3 From 1512dcc994dfacd0995a93320efc001550f15212 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Fri, 4 Sep 2020 20:05:03 +0200 Subject: Disable burst_shared filter of the AntiSpam cog Our AntiSpam cog suffers from a race condition that causes it to try and infract the same user multiple times. As that happens frequently with the burst_shared filter, it means that our bot joins in and starts spamming the channel with error messages. Another issue is that burst_shared may cause our bot to send a lot of DMs to a lot of different members. This caused our bot to get a DM ban from Discord after a recent `everyone` ping incident. I've decided to disable the `burst_shared` filter by commenting out the relevant lines but leave the code in place otherwise. This means we still have the implementation handy in case we want to re-enable it on short notice. Signed-off-by: Sebastiaan Zeeff --- bot/cogs/antispam.py | 3 ++- config-default.yml | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index d003f962b..b8939113f 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -27,7 +27,8 @@ log = logging.getLogger(__name__) RULE_FUNCTION_MAPPING = { 'attachments': rules.apply_attachments, 'burst': rules.apply_burst, - 'burst_shared': rules.apply_burst_shared, + # burst shared is temporarily disabled due to a bug + # 'burst_shared': rules.apply_burst_shared, 'chars': rules.apply_chars, 'discord_emojis': rules.apply_discord_emojis, 'duplicates': rules.apply_duplicates, diff --git a/config-default.yml b/config-default.yml index 766f7050c..e9324c62f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -352,9 +352,13 @@ anti_spam: interval: 10 max: 7 - burst_shared: - interval: 10 - max: 20 + # Burst shared it (temporarily) disabled to prevent + # the bug that triggers multiple infractions/DMs per + # user. It also tends to catch a lot of innocent users + # now that we're so big. + # burst_shared: + # interval: 10 + # max: 20 chars: interval: 5 -- cgit v1.2.3 From 53cb77bb2d541d0be61bc3c25e37b54601963b7c Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Sat, 5 Sep 2020 11:07:58 +0200 Subject: Disable everyone_ping filter in AntiSpam cog As there are a few bugs in the implementation, I've temporarily disabled the at-everyone ping filter in the AntiSpam cog. We can disable it after we've fixed the bugs. Signed-off-by: Sebastiaan Zeeff --- bot/cogs/antispam.py | 4 +++- config-default.yml | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index b8939113f..3ad487d8c 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -36,7 +36,9 @@ RULE_FUNCTION_MAPPING = { 'mentions': rules.apply_mentions, 'newlines': rules.apply_newlines, 'role_mentions': rules.apply_role_mentions, - 'everyone_ping': rules.apply_everyone_ping, + # the everyone filter is temporarily disabled until + # it has been improved. + # 'everyone_ping': rules.apply_everyone_ping, } diff --git a/config-default.yml b/config-default.yml index e9324c62f..6e7cff92d 100644 --- a/config-default.yml +++ b/config-default.yml @@ -389,9 +389,11 @@ anti_spam: interval: 10 max: 3 - everyone_ping: - interval: 10 - max: 0 + # The everyone ping filter is temporarily disabled + # until we've fixed a couple of bugs. + # everyone_ping: + # interval: 10 + # max: 0 reddit: -- cgit v1.2.3 From 0c6215f3f6e7247a5e13199931f733a8e203047e Mon Sep 17 00:00:00 2001 From: kosayoda Date: Mon, 7 Sep 2020 21:08:54 +0800 Subject: Remove everyone_ping rule from antispam. The feature will be moved to the filtering cog. --- bot/cogs/antispam.py | 1 - bot/rules/__init__.py | 1 - bot/rules/everyone_ping.py | 44 --------------- config-default.yml | 4 -- tests/bot/rules/test_everyone_ping.py | 102 ---------------------------------- 5 files changed, 152 deletions(-) delete mode 100644 bot/rules/everyone_ping.py delete mode 100644 tests/bot/rules/test_everyone_ping.py (limited to 'config-default.yml') diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index b8939113f..5c97621fb 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -36,7 +36,6 @@ RULE_FUNCTION_MAPPING = { 'mentions': rules.apply_mentions, 'newlines': rules.apply_newlines, 'role_mentions': rules.apply_role_mentions, - 'everyone_ping': rules.apply_everyone_ping, } diff --git a/bot/rules/__init__.py b/bot/rules/__init__.py index 8a69cadee..a01ceae73 100644 --- a/bot/rules/__init__.py +++ b/bot/rules/__init__.py @@ -10,4 +10,3 @@ from .links import apply as apply_links from .mentions import apply as apply_mentions from .newlines import apply as apply_newlines from .role_mentions import apply as apply_role_mentions -from .everyone_ping import apply as apply_everyone_ping diff --git a/bot/rules/everyone_ping.py b/bot/rules/everyone_ping.py deleted file mode 100644 index 8fc03b924..000000000 --- a/bot/rules/everyone_ping.py +++ /dev/null @@ -1,44 +0,0 @@ -import random -import re -from typing import Dict, Iterable, List, Optional, Tuple - -from discord import Embed, Member, Message - -from bot.constants import Colours, Guild, NEGATIVE_REPLIES - -# Generate regex for checking for pings: -guild_id = Guild.id -EVERYONE_PING_RE = re.compile(rf"@everyone|<@&{guild_id}>") -CODE_BLOCK_RE = re.compile( - r"(?P``?)[^`]+?(?P=delim)(?!`+)" # Inline codeblock - r"|```(.+?)```", # Multiline codeblock - re.DOTALL | re.MULTILINE -) - - -async def apply( - last_message: Message, - recent_messages: List[Message], - config: Dict[str, int], -) -> Optional[Tuple[str, Iterable[Member], Iterable[Message]]]: - """Detects if a user has sent an '@everyone' ping.""" - relevant_messages = tuple(msg for msg in recent_messages if msg.author == last_message.author) - - everyone_messages_count = 0 - for msg in relevant_messages: - content = CODE_BLOCK_RE.sub("", msg.content) # Remove codeblocks in the message - if matches := len(EVERYONE_PING_RE.findall(content)): - everyone_messages_count += matches - - if everyone_messages_count > config["max"]: - # Send the channel an embed giving the user more info: - embed_text = f"Please don't try to ping {last_message.guild.member_count:,} people." - embed = Embed(title=random.choice(NEGATIVE_REPLIES), description=embed_text, colour=Colours.soft_red) - await last_message.channel.send(embed=embed) - - return ( - "pinged the everyone role", - (last_message.author,), - relevant_messages, - ) - return None diff --git a/config-default.yml b/config-default.yml index e9324c62f..c1eef713f 100644 --- a/config-default.yml +++ b/config-default.yml @@ -389,10 +389,6 @@ anti_spam: interval: 10 max: 3 - everyone_ping: - interval: 10 - max: 0 - reddit: subreddits: diff --git a/tests/bot/rules/test_everyone_ping.py b/tests/bot/rules/test_everyone_ping.py deleted file mode 100644 index 3ecc43cdc..000000000 --- a/tests/bot/rules/test_everyone_ping.py +++ /dev/null @@ -1,102 +0,0 @@ -from typing import Iterable - -from bot.rules import everyone_ping -from tests.bot.rules import DisallowedCase, RuleTest -from tests.helpers import MockGuild, MockMessage - -NUM_GUILD_MEMBERS = 100 - - -def make_msg(author: str, message: str) -> MockMessage: - """Build a message with `message` as the content sent.""" - mocked_guild = MockGuild(member_count=NUM_GUILD_MEMBERS) - return MockMessage(author=author, content=message, guild=mocked_guild) - - -class EveryonePingRuleTest(RuleTest): - """Tests the `everyone_ping` antispam rule.""" - - def setUp(self): - self.apply = everyone_ping.apply - self.config = { - "max": 0, # Max allowed @everyone pings per user - "interval": 10, - } - - async def test_disallows_everyone_ping(self): - """Cases with an @everyone ping.""" - cases = ( - DisallowedCase( - [make_msg("bob", "@everyone")], - ("bob",), - 1 - ), - DisallowedCase( - [make_msg("bob", "Let me ping @everyone in the server.")], - ("bob",), - 1 - ), - DisallowedCase( - [make_msg("bob", "`codeblock message` and @everyone ping")], - ("bob",), - 1 - ), - DisallowedCase( - [make_msg("bob", "`sandwich` @everyone `ping between codeblocks`.")], - ("bob",), - 1 - ), - DisallowedCase( - [make_msg("bob", "This is a multiline\n@everyone\nping.")], - ("bob",), - 1 - ), - # Not actually valid code blocks - DisallowedCase( - [make_msg("bob", "`@everyone``")], - ("bob",), - 1 - ), - DisallowedCase( - [make_msg("bob", "`@everyone``````")], - ("bob",), - 1 - ), - DisallowedCase( - [make_msg("bob", "``@everyone``````")], - ("bob",), - 1 - ), - ) - - await self.run_disallowed(cases) - - async def test_allows_inline_codeblock_everyone_ping(self): - """Cases with an @everyone ping in an inline codeblock.""" - cases = ( - [make_msg("bob", "Codeblock has `@everyone` ping.")], - [make_msg("bob", "Multiple `codeblocks` including `@everyone` ping.")], - [make_msg("bob", "This is a valid ``inline @everyone` ping.")], - ) - - await self.run_allowed(cases) - - async def test_allows_multiline_codeblock_everyone_ping(self): - """Cases with an @everyone ping in a multiline codeblock.""" - cases = ( - [make_msg("bob", "```Multiline codeblock has\nan `@everyone` ping.```")], - [make_msg("bob", "``` `@everyone``` ` `")], - ) - - await self.run_allowed(cases) - - def relevant_messages(self, case: DisallowedCase) -> Iterable[MockMessage]: - last_message = case.recent_messages[0] - return tuple( - msg - for msg in case.recent_messages - if msg.author == last_message.author - ) - - def get_report(self, case: DisallowedCase) -> str: - return "pinged the everyone role" -- cgit v1.2.3 From 7b311196613e358557a14aa75f01e8a54ab3e698 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 7 Sep 2020 15:49:31 -0700 Subject: Sync: remove confirmation The confirmation was intended to be a safe guard against cache issues that would cause a huge number of roles/users to deleted after syncing. With `wait_until_guild_available`, such cache issue shouldn't arise. Therefore, this feature is obsolete. Resolve #1075 --- bot/cogs/sync/syncers.py | 170 +------------------ bot/constants.py | 7 - config-default.yml | 4 - tests/bot/cogs/sync/test_base.py | 357 ++------------------------------------- 4 files changed, 20 insertions(+), 518 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/sync/syncers.py b/bot/cogs/sync/syncers.py index f7ba811bc..b3819a1e1 100644 --- a/bot/cogs/sync/syncers.py +++ b/bot/cogs/sync/syncers.py @@ -1,15 +1,11 @@ import abc -import asyncio import logging import typing as t from collections import namedtuple -from functools import partial -import discord -from discord import Guild, HTTPException, Member, Message, Reaction, User +from discord import Guild from discord.ext.commands import Context -from bot import constants from bot.api import ResponseCodeError from bot.bot import Bot @@ -25,9 +21,6 @@ _Diff = namedtuple('Diff', ('created', 'updated', 'deleted')) class Syncer(abc.ABC): """Base class for synchronising the database with objects in the Discord cache.""" - _CORE_DEV_MENTION = f"<@&{constants.Roles.core_developers}> " - _REACTION_EMOJIS = (constants.Emojis.check_mark, constants.Emojis.cross_mark) - def __init__(self, bot: Bot) -> None: self.bot = bot @@ -37,112 +30,6 @@ class Syncer(abc.ABC): """The name of the syncer; used in output messages and logging.""" raise NotImplementedError # pragma: no cover - async def _send_prompt(self, message: t.Optional[Message] = None) -> t.Optional[Message]: - """ - Send a prompt to confirm or abort a sync using reactions and return the sent message. - - If a message is given, it is edited to display the prompt and reactions. Otherwise, a new - message is sent to the dev-core channel and mentions the core developers role. If the - channel cannot be retrieved, return None. - """ - log.trace(f"Sending {self.name} sync confirmation prompt.") - - msg_content = ( - f'Possible cache issue while syncing {self.name}s. ' - f'More than {constants.Sync.max_diff} {self.name}s were changed. ' - f'React to confirm or abort the sync.' - ) - - # Send to core developers if it's an automatic sync. - if not message: - log.trace("Message not provided for confirmation; creating a new one in dev-core.") - channel = self.bot.get_channel(constants.Channels.dev_core) - - if not channel: - log.debug("Failed to get the dev-core channel from cache; attempting to fetch it.") - try: - channel = await self.bot.fetch_channel(constants.Channels.dev_core) - except HTTPException: - log.exception( - f"Failed to fetch channel for sending sync confirmation prompt; " - f"aborting {self.name} sync." - ) - return None - - allowed_roles = [discord.Object(constants.Roles.core_developers)] - message = await channel.send( - f"{self._CORE_DEV_MENTION}{msg_content}", - allowed_mentions=discord.AllowedMentions(everyone=False, roles=allowed_roles) - ) - else: - await message.edit(content=msg_content) - - # Add the initial reactions. - log.trace(f"Adding reactions to {self.name} syncer confirmation prompt.") - for emoji in self._REACTION_EMOJIS: - await message.add_reaction(emoji) - - return message - - def _reaction_check( - self, - author: Member, - message: Message, - reaction: Reaction, - user: t.Union[Member, User] - ) -> bool: - """ - Return True if the `reaction` is a valid confirmation or abort reaction on `message`. - - If the `author` of the prompt is a bot, then a reaction by any core developer will be - considered valid. Otherwise, the author of the reaction (`user`) will have to be the - `author` of the prompt. - """ - # For automatic syncs, check for the core dev role instead of an exact author - has_role = any(constants.Roles.core_developers == role.id for role in user.roles) - return ( - reaction.message.id == message.id - and not user.bot - and (has_role if author.bot else user == author) - and str(reaction.emoji) in self._REACTION_EMOJIS - ) - - async def _wait_for_confirmation(self, author: Member, message: Message) -> bool: - """ - Wait for a confirmation reaction by `author` on `message` and return True if confirmed. - - Uses the `_reaction_check` function to determine if a reaction is valid. - - If there is no reaction within `bot.constants.Sync.confirm_timeout` seconds, return False. - To acknowledge the reaction (or lack thereof), `message` will be edited. - """ - # Preserve the core-dev role mention in the message edits so users aren't confused about - # where notifications came from. - mention = self._CORE_DEV_MENTION if author.bot else "" - - reaction = None - try: - log.trace(f"Waiting for a reaction to the {self.name} syncer confirmation prompt.") - reaction, _ = await self.bot.wait_for( - 'reaction_add', - check=partial(self._reaction_check, author, message), - timeout=constants.Sync.confirm_timeout - ) - except asyncio.TimeoutError: - # reaction will remain none thus sync will be aborted in the finally block below. - log.debug(f"The {self.name} syncer confirmation prompt timed out.") - - if str(reaction) == constants.Emojis.check_mark: - log.trace(f"The {self.name} syncer was confirmed.") - await message.edit(content=f':ok_hand: {mention}{self.name} sync will proceed.') - return True - else: - log.info(f"The {self.name} syncer was aborted or timed out!") - await message.edit( - content=f':warning: {mention}{self.name} sync aborted or timed out!' - ) - return False - @abc.abstractmethod async def _get_diff(self, guild: Guild) -> _Diff: """Return the difference between the cache of `guild` and the database.""" @@ -153,34 +40,6 @@ class Syncer(abc.ABC): """Perform the API calls for synchronisation.""" raise NotImplementedError # pragma: no cover - async def _get_confirmation_result( - self, - diff_size: int, - author: Member, - message: t.Optional[Message] = None - ) -> t.Tuple[bool, t.Optional[Message]]: - """ - Prompt for confirmation and return a tuple of the result and the prompt message. - - `diff_size` is the size of the diff of the sync. If it is greater than - `bot.constants.Sync.max_diff`, the prompt will be sent. The `author` is the invoked of the - sync and the `message` is an extant message to edit to display the prompt. - - If confirmed or no confirmation was needed, the result is True. The returned message will - either be the given `message` or a new one which was created when sending the prompt. - """ - log.trace(f"Determining if confirmation prompt should be sent for {self.name} syncer.") - if diff_size > constants.Sync.max_diff: - message = await self._send_prompt(message) - if not message: - return False, None # Couldn't get channel. - - confirmed = await self._wait_for_confirmation(author, message) - if not confirmed: - return False, message # Sync aborted. - - return True, message - async def sync(self, guild: Guild, ctx: t.Optional[Context] = None) -> None: """ Synchronise the database with the cache of `guild`. @@ -191,24 +50,8 @@ class Syncer(abc.ABC): """ log.info(f"Starting {self.name} syncer.") - message = None - author = self.bot.user - if ctx: - message = await ctx.send(f"📊 Synchronising {self.name}s.") - author = ctx.author - + message = await ctx.send(f"📊 Synchronising {self.name}s.") if ctx else None diff = await self._get_diff(guild) - diff_dict = diff._asdict() # Ugly method for transforming the NamedTuple into a dict - totals = {k: len(v) for k, v in diff_dict.items() if v is not None} - diff_size = sum(totals.values()) - - confirmed, message = await self._get_confirmation_result(diff_size, author, message) - if not confirmed: - return - - # Preserve the core-dev role mention in the message edits so users aren't confused about - # where notifications came from. - mention = self._CORE_DEV_MENTION if author.bot else "" try: await self._sync(diff) @@ -217,11 +60,14 @@ class Syncer(abc.ABC): # Don't show response text because it's probably some really long HTML. results = f"status {e.status}\n```{e.response_json or 'See log output for details'}```" - content = f":x: {mention}Synchronisation of {self.name}s failed: {results}" + content = f":x: Synchronisation of {self.name}s failed: {results}" else: - results = ", ".join(f"{name} `{total}`" for name, total in totals.items()) + diff_dict = diff._asdict() # Ugly method for transforming the NamedTuple into a dict + results = (f"{name} `{len(val)}`" for name, val in diff_dict.items() if val is not None) + results = ", ".join(results) + log.info(f"{self.name} syncer finished: {results}.") - content = f":ok_hand: {mention}Synchronisation of {self.name}s complete: {results}" + content = f":ok_hand: Synchronisation of {self.name}s complete: {results}" if message: await message.edit(content=content) diff --git a/bot/constants.py b/bot/constants.py index 17fe34e95..3129354d3 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -563,13 +563,6 @@ class RedirectOutput(metaclass=YAMLGetter): delete_delay: int -class Sync(metaclass=YAMLGetter): - section = 'sync' - - confirm_timeout: int - max_diff: int - - class PythonNews(metaclass=YAMLGetter): section = 'python_news' diff --git a/config-default.yml b/config-default.yml index 6e7cff92d..d48739002 100644 --- a/config-default.yml +++ b/config-default.yml @@ -460,10 +460,6 @@ redirect_output: delete_invocation: true delete_delay: 15 -sync: - confirm_timeout: 300 - max_diff: 10 - duck_pond: threshold: 5 custom_emojis: diff --git a/tests/bot/cogs/sync/test_base.py b/tests/bot/cogs/sync/test_base.py index 70aea2bab..c3456f724 100644 --- a/tests/bot/cogs/sync/test_base.py +++ b/tests/bot/cogs/sync/test_base.py @@ -1,12 +1,9 @@ -import asyncio import unittest from unittest import mock -import discord -from bot import constants from bot.api import ResponseCodeError -from bot.cogs.sync.syncers import Syncer, _Diff +from bot.cogs.sync.syncers import Syncer from tests import helpers @@ -30,280 +27,16 @@ class SyncerBaseTests(unittest.TestCase): Syncer(self.bot) -class SyncerSendPromptTests(unittest.IsolatedAsyncioTestCase): - """Tests for sending the sync confirmation prompt.""" - - def setUp(self): - self.bot = helpers.MockBot() - self.syncer = TestSyncer(self.bot) - - def mock_get_channel(self): - """Fixture to return a mock channel and message for when `get_channel` is used.""" - self.bot.reset_mock() - - mock_channel = helpers.MockTextChannel() - mock_message = helpers.MockMessage() - - mock_channel.send.return_value = mock_message - self.bot.get_channel.return_value = mock_channel - - return mock_channel, mock_message - - def mock_fetch_channel(self): - """Fixture to return a mock channel and message for when `fetch_channel` is used.""" - self.bot.reset_mock() - - mock_channel = helpers.MockTextChannel() - mock_message = helpers.MockMessage() - - self.bot.get_channel.return_value = None - mock_channel.send.return_value = mock_message - self.bot.fetch_channel.return_value = mock_channel - - return mock_channel, mock_message - - async def test_send_prompt_edits_and_returns_message(self): - """The given message should be edited to display the prompt and then should be returned.""" - msg = helpers.MockMessage() - ret_val = await self.syncer._send_prompt(msg) - - msg.edit.assert_called_once() - self.assertIn("content", msg.edit.call_args[1]) - self.assertEqual(ret_val, msg) - - async def test_send_prompt_gets_dev_core_channel(self): - """The dev-core channel should be retrieved if an extant message isn't given.""" - subtests = ( - (self.bot.get_channel, self.mock_get_channel), - (self.bot.fetch_channel, self.mock_fetch_channel), - ) - - for method, mock_ in subtests: - with self.subTest(method=method, msg=mock_.__name__): - mock_() - await self.syncer._send_prompt() - - method.assert_called_once_with(constants.Channels.dev_core) - - async def test_send_prompt_returns_none_if_channel_fetch_fails(self): - """None should be returned if there's an HTTPException when fetching the channel.""" - self.bot.get_channel.return_value = None - self.bot.fetch_channel.side_effect = discord.HTTPException(mock.MagicMock(), "test error!") - - ret_val = await self.syncer._send_prompt() - - self.assertIsNone(ret_val) - - async def test_send_prompt_sends_and_returns_new_message_if_not_given(self): - """A new message mentioning core devs should be sent and returned if message isn't given.""" - for mock_ in (self.mock_get_channel, self.mock_fetch_channel): - with self.subTest(msg=mock_.__name__): - mock_channel, mock_message = mock_() - ret_val = await self.syncer._send_prompt() - - mock_channel.send.assert_called_once() - self.assertIn(self.syncer._CORE_DEV_MENTION, mock_channel.send.call_args[0][0]) - self.assertEqual(ret_val, mock_message) - - async def test_send_prompt_adds_reactions(self): - """The message should have reactions for confirmation added.""" - extant_message = helpers.MockMessage() - subtests = ( - (extant_message, lambda: (None, extant_message)), - (None, self.mock_get_channel), - (None, self.mock_fetch_channel), - ) - - for message_arg, mock_ in subtests: - subtest_msg = "Extant message" if mock_.__name__ == "" else mock_.__name__ - - with self.subTest(msg=subtest_msg): - _, mock_message = mock_() - await self.syncer._send_prompt(message_arg) - - calls = [mock.call(emoji) for emoji in self.syncer._REACTION_EMOJIS] - mock_message.add_reaction.assert_has_calls(calls) - - -class SyncerConfirmationTests(unittest.IsolatedAsyncioTestCase): - """Tests for waiting for a sync confirmation reaction on the prompt.""" - - def setUp(self): - self.bot = helpers.MockBot() - self.syncer = TestSyncer(self.bot) - self.core_dev_role = helpers.MockRole(id=constants.Roles.core_developers) - - @staticmethod - def get_message_reaction(emoji): - """Fixture to return a mock message an reaction from the given `emoji`.""" - message = helpers.MockMessage() - reaction = helpers.MockReaction(emoji=emoji, message=message) - - return message, reaction - - def test_reaction_check_for_valid_emoji_and_authors(self): - """Should return True if authors are identical or are a bot and a core dev, respectively.""" - user_subtests = ( - ( - helpers.MockMember(id=77), - helpers.MockMember(id=77), - "identical users", - ), - ( - helpers.MockMember(id=77, bot=True), - helpers.MockMember(id=43, roles=[self.core_dev_role]), - "bot author and core-dev reactor", - ), - ) - - for emoji in self.syncer._REACTION_EMOJIS: - for author, user, msg in user_subtests: - with self.subTest(author=author, user=user, emoji=emoji, msg=msg): - message, reaction = self.get_message_reaction(emoji) - ret_val = self.syncer._reaction_check(author, message, reaction, user) - - self.assertTrue(ret_val) - - def test_reaction_check_for_invalid_reactions(self): - """Should return False for invalid reaction events.""" - valid_emoji = self.syncer._REACTION_EMOJIS[0] - subtests = ( - ( - helpers.MockMember(id=77), - *self.get_message_reaction(valid_emoji), - helpers.MockMember(id=43, roles=[self.core_dev_role]), - "users are not identical", - ), - ( - helpers.MockMember(id=77, bot=True), - *self.get_message_reaction(valid_emoji), - helpers.MockMember(id=43), - "reactor lacks the core-dev role", - ), - ( - helpers.MockMember(id=77, bot=True, roles=[self.core_dev_role]), - *self.get_message_reaction(valid_emoji), - helpers.MockMember(id=77, bot=True, roles=[self.core_dev_role]), - "reactor is a bot", - ), - ( - helpers.MockMember(id=77), - helpers.MockMessage(id=95), - helpers.MockReaction(emoji=valid_emoji, message=helpers.MockMessage(id=26)), - helpers.MockMember(id=77), - "messages are not identical", - ), - ( - helpers.MockMember(id=77), - *self.get_message_reaction("InVaLiD"), - helpers.MockMember(id=77), - "emoji is invalid", - ), - ) - - for *args, msg in subtests: - kwargs = dict(zip(("author", "message", "reaction", "user"), args)) - with self.subTest(**kwargs, msg=msg): - ret_val = self.syncer._reaction_check(*args) - self.assertFalse(ret_val) - - async def test_wait_for_confirmation(self): - """The message should always be edited and only return True if the emoji is a check mark.""" - subtests = ( - (constants.Emojis.check_mark, True, None), - ("InVaLiD", False, None), - (None, False, asyncio.TimeoutError), - ) - - for emoji, ret_val, side_effect in subtests: - for bot in (True, False): - with self.subTest(emoji=emoji, ret_val=ret_val, side_effect=side_effect, bot=bot): - # Set up mocks - message = helpers.MockMessage() - member = helpers.MockMember(bot=bot) - - self.bot.wait_for.reset_mock() - self.bot.wait_for.return_value = (helpers.MockReaction(emoji=emoji), None) - self.bot.wait_for.side_effect = side_effect - - # Call the function - actual_return = await self.syncer._wait_for_confirmation(member, message) - - # Perform assertions - self.bot.wait_for.assert_called_once() - self.assertIn("reaction_add", self.bot.wait_for.call_args[0]) - - message.edit.assert_called_once() - kwargs = message.edit.call_args[1] - self.assertIn("content", kwargs) - - # Core devs should only be mentioned if the author is a bot. - if bot: - self.assertIn(self.syncer._CORE_DEV_MENTION, kwargs["content"]) - else: - self.assertNotIn(self.syncer._CORE_DEV_MENTION, kwargs["content"]) - - self.assertIs(actual_return, ret_val) - - class SyncerSyncTests(unittest.IsolatedAsyncioTestCase): """Tests for main function orchestrating the sync.""" def setUp(self): self.bot = helpers.MockBot(user=helpers.MockMember(bot=True)) self.syncer = TestSyncer(self.bot) + self.guild = helpers.MockGuild() - async def test_sync_respects_confirmation_result(self): - """The sync should abort if confirmation fails and continue if confirmed.""" - mock_message = helpers.MockMessage() - subtests = ( - (True, mock_message), - (False, None), - ) - - for confirmed, message in subtests: - with self.subTest(confirmed=confirmed): - self.syncer._sync.reset_mock() - self.syncer._get_diff.reset_mock() - - diff = _Diff({1, 2, 3}, {4, 5}, None) - self.syncer._get_diff.return_value = diff - self.syncer._get_confirmation_result = mock.AsyncMock( - return_value=(confirmed, message) - ) - - guild = helpers.MockGuild() - await self.syncer.sync(guild) - - self.syncer._get_diff.assert_called_once_with(guild) - self.syncer._get_confirmation_result.assert_called_once() - - if confirmed: - self.syncer._sync.assert_called_once_with(diff) - else: - self.syncer._sync.assert_not_called() - - async def test_sync_diff_size(self): - """The diff size should be correctly calculated.""" - subtests = ( - (6, _Diff({1, 2}, {3, 4}, {5, 6})), - (5, _Diff({1, 2, 3}, None, {4, 5})), - (0, _Diff(None, None, None)), - (0, _Diff(set(), set(), set())), - ) - - for size, diff in subtests: - with self.subTest(size=size, diff=diff): - self.syncer._get_diff.reset_mock() - self.syncer._get_diff.return_value = diff - self.syncer._get_confirmation_result = mock.AsyncMock(return_value=(False, None)) - - guild = helpers.MockGuild() - await self.syncer.sync(guild) - - self.syncer._get_diff.assert_called_once_with(guild) - self.syncer._get_confirmation_result.assert_called_once() - self.assertEqual(self.syncer._get_confirmation_result.call_args[0][0], size) + # Make sure `_get_diff` returns a MagicMock, not an AsyncMock + self.syncer._get_diff.return_value = mock.MagicMock() async def test_sync_message_edited(self): """The message should be edited if one was sent, even if the sync has an API error.""" @@ -316,89 +49,23 @@ class SyncerSyncTests(unittest.IsolatedAsyncioTestCase): for message, side_effect, should_edit in subtests: with self.subTest(message=message, side_effect=side_effect, should_edit=should_edit): self.syncer._sync.side_effect = side_effect - self.syncer._get_confirmation_result = mock.AsyncMock( - return_value=(True, message) - ) - guild = helpers.MockGuild() - await self.syncer.sync(guild) + await self.syncer.sync(self.guild) if should_edit: message.edit.assert_called_once() self.assertIn("content", message.edit.call_args[1]) - async def test_sync_confirmation_context_redirect(self): - """If ctx is given, a new message should be sent and author should be ctx's author.""" - mock_member = helpers.MockMember() + async def test_sync_message_sent(self): + """If ctx is given, a new message should be sent.""" subtests = ( - (None, self.bot.user, None), - (helpers.MockContext(author=mock_member), mock_member, helpers.MockMessage()), + (None, None), + (helpers.MockContext(), helpers.MockMessage()), ) - for ctx, author, message in subtests: - with self.subTest(ctx=ctx, author=author, message=message): - if ctx is not None: - ctx.send.return_value = message - - # Make sure `_get_diff` returns a MagicMock, not an AsyncMock - self.syncer._get_diff.return_value = mock.MagicMock() - - self.syncer._get_confirmation_result = mock.AsyncMock(return_value=(False, None)) - - guild = helpers.MockGuild() - await self.syncer.sync(guild, ctx) + for ctx, message in subtests: + with self.subTest(ctx=ctx, message=message): + await self.syncer.sync(self.guild, ctx) if ctx is not None: ctx.send.assert_called_once() - - self.syncer._get_confirmation_result.assert_called_once() - self.assertEqual(self.syncer._get_confirmation_result.call_args[0][1], author) - self.assertEqual(self.syncer._get_confirmation_result.call_args[0][2], message) - - @mock.patch.object(constants.Sync, "max_diff", new=3) - async def test_confirmation_result_small_diff(self): - """Should always return True and the given message if the diff size is too small.""" - author = helpers.MockMember() - expected_message = helpers.MockMessage() - - for size in (3, 2): # pragma: no cover - with self.subTest(size=size): - self.syncer._send_prompt = mock.AsyncMock() - self.syncer._wait_for_confirmation = mock.AsyncMock() - - coro = self.syncer._get_confirmation_result(size, author, expected_message) - result, actual_message = await coro - - self.assertTrue(result) - self.assertEqual(actual_message, expected_message) - self.syncer._send_prompt.assert_not_called() - self.syncer._wait_for_confirmation.assert_not_called() - - @mock.patch.object(constants.Sync, "max_diff", new=3) - async def test_confirmation_result_large_diff(self): - """Should return True if confirmed and False if _send_prompt fails or aborted.""" - author = helpers.MockMember() - mock_message = helpers.MockMessage() - - subtests = ( - (True, mock_message, True, "confirmed"), - (False, None, False, "_send_prompt failed"), - (False, mock_message, False, "aborted"), - ) - - for expected_result, expected_message, confirmed, msg in subtests: # pragma: no cover - with self.subTest(msg=msg): - self.syncer._send_prompt = mock.AsyncMock(return_value=expected_message) - self.syncer._wait_for_confirmation = mock.AsyncMock(return_value=confirmed) - - coro = self.syncer._get_confirmation_result(4, author) - actual_result, actual_message = await coro - - self.syncer._send_prompt.assert_called_once_with(None) # message defaults to None - self.assertIs(actual_result, expected_result) - self.assertEqual(actual_message, expected_message) - - if expected_message: - self.syncer._wait_for_confirmation.assert_called_once_with( - author, expected_message - ) -- cgit v1.2.3 From ab4eb39fcdde62cc9f558f9e41a5f48d9a587d38 Mon Sep 17 00:00:00 2001 From: kosayoda Date: Tue, 8 Sep 2020 12:04:20 +0800 Subject: Add everyone_ping filter. --- bot/cogs/filtering.py | 38 +++++++++++++++++++++++++++++++++++--- bot/constants.py | 2 ++ config-default.yml | 18 ++++++++++-------- 3 files changed, 47 insertions(+), 11 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 99b659bff..aa0cbad97 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -15,8 +15,8 @@ from bot.api import ResponseCodeError from bot.bot import Bot from bot.cogs.moderation import ModLog from bot.constants import ( - Channels, Colours, - Filter, Icons, URLs + Channels, Colours, Filter, + Guild, Icons, URLs ) from bot.utils.redis_cache import RedisCache from bot.utils.regex import INVITE_RE @@ -25,6 +25,12 @@ from bot.utils.scheduling import Scheduler log = logging.getLogger(__name__) # Regular expressions +CODE_BLOCK_RE = re.compile( + r"(?P``?)[^`]+?(?P=delim)(?!`+)" # Inline codeblock + r"|```(.+?)```", # Multiline codeblock + re.DOTALL | re.MULTILINE +) +EVERYONE_PING_RE = re.compile(rf"@everyone|<@&{Guild.id}>|@here") SPOILER_RE = re.compile(r"(\|\|.+?\|\|)", re.DOTALL) URL_RE = re.compile(r"(https?://[^\s]+)", flags=re.IGNORECASE) ZALGO_RE = re.compile(r"[\u0300-\u036F\u0489]") @@ -82,6 +88,19 @@ class Filtering(Cog): ), "schedule_deletion": False }, + "filter_everyone_ping": { + "enabled": Filter.filter_everyone_ping, + "function": self._has_everyone_ping, + "type": "filter", + "content_only": True, + "user_notification": Filter.notify_user_everyone_ping, + "notification_msg": ( + "Please don't try to ping `@everyone` or `@here`. " + f"Your message has been removed. {staff_mistake_str}" + ), + "schedule_deletion": False, + "ping_everyone": False + }, "watch_regex": { "enabled": Filter.watch_regex, "function": self._has_watch_regex_match, @@ -332,6 +351,9 @@ class Filtering(Cog): log.debug(message) + # Allow specific filters to override ping_everyone + ping_everyone = Filter.ping_everyone and _filter.get("ping_everyone", True) + # Send pretty mod log embed to mod-alerts await self.mod_log.send_log_message( icon_url=Icons.filtering, @@ -340,7 +362,7 @@ class Filtering(Cog): text=message, thumbnail=msg.author.avatar_url_as(static_format="png"), channel_id=Channels.mod_alerts, - ping_everyone=Filter.ping_everyone if not is_private else False, + ping_everyone=ping_everyone if not is_private else False, additional_embeds=additional_embeds, additional_embeds_msg=additional_embeds_msg ) @@ -528,6 +550,16 @@ class Filtering(Cog): return False return False + @staticmethod + async def _has_everyone_ping(text: str) -> bool: + """Determines if `msg` contains an @everyone or @here ping outside of a codeblock.""" + # First pass to avoid running re.sub on every message + if not EVERYONE_PING_RE.search(text): + return False + + content_without_codeblocks = CODE_BLOCK_RE.sub("", text) + return bool(EVERYONE_PING_RE.search(content_without_codeblocks)) + async def notify_member(self, filtered_member: Member, reason: str, channel: TextChannel) -> None: """ Notify filtered_member about a moderation action with the reason str. diff --git a/bot/constants.py b/bot/constants.py index 17fe34e95..70b36984f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -217,6 +217,7 @@ class Filter(metaclass=YAMLGetter): filter_zalgo: bool filter_invites: bool filter_domains: bool + filter_everyone_ping: bool watch_regex: bool watch_rich_embeds: bool @@ -224,6 +225,7 @@ class Filter(metaclass=YAMLGetter): notify_user_zalgo: bool notify_user_invites: bool notify_user_domains: bool + notify_user_everyone_ping: bool ping_everyone: bool offensive_msg_delete_days: int diff --git a/config-default.yml b/config-default.yml index c1eef713f..cf9ce8798 100644 --- a/config-default.yml +++ b/config-default.yml @@ -273,17 +273,19 @@ guild: filter: # What do we filter? - filter_zalgo: false - filter_invites: true - filter_domains: true - watch_regex: true - watch_rich_embeds: true + filter_zalgo: false + filter_invites: true + filter_domains: true + filter_everyone_ping: true + watch_regex: true + watch_rich_embeds: true # Notify user on filter? # Notifications are not expected for "watchlist" type filters - notify_user_zalgo: false - notify_user_invites: true - notify_user_domains: false + notify_user_zalgo: false + notify_user_invites: true + notify_user_domains: false + notify_user_everyone_ping: true # Filter configuration ping_everyone: true -- cgit v1.2.3 From 1b3a5c5d90bb658895fea8a2bed91366d2f2f76e Mon Sep 17 00:00:00 2001 From: kwzrd Date: Thu, 10 Sep 2020 18:41:07 +0200 Subject: Verification: move constants to config --- bot/cogs/verification.py | 45 ++++++++++++++++++++------------------------- bot/constants.py | 10 ++++++++++ config-default.yml | 13 +++++++++++++ 3 files changed, 43 insertions(+), 25 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/verification.py b/bot/cogs/verification.py index 08f7c282e..0092a0898 100644 --- a/bot/cogs/verification.py +++ b/bot/cogs/verification.py @@ -18,16 +18,6 @@ from bot.utils.redis_cache import RedisCache log = logging.getLogger(__name__) -UNVERIFIED_AFTER = 3 # Amount of days after which non-Developers receive the @Unverified role -KICKED_AFTER = 30 # Amount of days after which non-Developers get kicked from the guild - -# Number in range [0, 1] determining the percentage of unverified users that are safe -# to be kicked from the guild in one batch, any larger amount will require staff confirmation, -# set this to 0 to require explicit approval for batches of any size -KICK_CONFIRMATION_THRESHOLD = 0.01 # 1% - -BOT_MESSAGE_DELETE_DELAY = 10 - # Sent via DMs once user joins the guild ON_JOIN_MESSAGE = f""" Hello! Welcome to Python Discord! @@ -62,7 +52,7 @@ If you'd like to unsubscribe from the announcement notifications, simply send `! # Sent via DMs to users kicked for failing to verify KICKED_MESSAGE = f""" Hi! You have been automatically kicked from Python Discord as you have failed to accept our rules \ -within `{KICKED_AFTER}` days. If this was an accident, please feel free to join us again! +within `{constants.Verification.kicked_after}` days. If this was an accident, please feel free to join us again! {constants.Guild.invite} """ @@ -74,11 +64,9 @@ REMINDER_MESSAGE = f""" Welcome to Python Discord! Please read the documents mentioned above and type `!accept` to gain permissions \ to send messages in the community! -You will be kicked if you don't verify within `{KICKED_AFTER}` days. +You will be kicked if you don't verify within `{constants.Verification.kicked_after}` days. """.strip() -REMINDER_FREQUENCY = 28 # Hours to wait between sending `REMINDER_MESSAGE` - # An async function taking a Member param Request = t.Callable[[discord.Member], t.Awaitable] @@ -209,7 +197,7 @@ class Verification(Cog): pydis = self.bot.get_guild(constants.Guild.id) percentage = n_members / len(pydis.members) - if percentage < KICK_CONFIRMATION_THRESHOLD: + if percentage < constants.Verification.kick_confirmation_threshold: log.debug(f"Kicking {percentage:.2%} of the guild's population is seen as safe") return True @@ -221,7 +209,8 @@ class Verification(Cog): confirmation_msg = await core_dev_channel.send( f"{core_dev_ping} Verification determined that `{n_members}` members should be kicked as they haven't " - f"verified in `{KICKED_AFTER}` days. This is `{percentage:.2%}` of the guild's population. Proceed?", + f"verified in `{constants.Verification.kicked_after}` days. This is `{percentage:.2%}` of the guild's " + f"population. Proceed?", allowed_mentions=mention_role(constants.Roles.core_developers), ) @@ -333,7 +322,7 @@ class Verification(Cog): Note that this is a potentially destructive operation. Returns the amount of successful requests. """ - log.info(f"Kicking {len(members)} members from the guild (not verified after {KICKED_AFTER} days)") + log.info(f"Kicking {len(members)} members (not verified after {constants.Verification.kicked_after} days)") async def kick_request(member: discord.Member) -> None: """Send `KICKED_MESSAGE` to `member` and kick them from the guild.""" @@ -343,7 +332,7 @@ class Verification(Cog): log.trace(f"DM dispatch failed on 403 error with code: {exc_403.code}") if exc_403.code != 50_007: # 403 raised for any other reason than disabled DMs raise StopExecution(reason=exc_403) - await member.kick(reason=f"User has not verified in {KICKED_AFTER} days") + await member.kick(reason=f"User has not verified in {constants.Verification.kicked_after} days") n_kicked = await self._send_requests(members, kick_request, Limit(batch_size=2, sleep_secs=1)) self.bot.stats.incr("verification.kicked", count=n_kicked) @@ -358,11 +347,14 @@ class Verification(Cog): Returns the amount of successful requests. """ - log.info(f"Assigning {role} role to {len(members)} members (not verified after {UNVERIFIED_AFTER} days)") + log.info( + f"Assigning {role} role to {len(members)} members (not verified " + f"after {constants.Verification.unverified_after} days)" + ) async def role_request(member: discord.Member) -> None: """Add `role` to `member`.""" - await member.add_roles(role, reason=f"User has not verified in {UNVERIFIED_AFTER} days") + await member.add_roles(role, reason=f"Not verified after {constants.Verification.unverified_after} days") return await self._send_requests(members, role_request, Limit(batch_size=25, sleep_secs=1)) @@ -397,10 +389,13 @@ class Verification(Cog): # to do with them based on time passed since their join date since_join = current_dt - member.joined_at - if since_join > timedelta(days=KICKED_AFTER): + if since_join > timedelta(days=constants.Verification.kicked_after): for_kick.add(member) # User should be removed from the guild - elif since_join > timedelta(days=UNVERIFIED_AFTER) and unverified not in member.roles: + elif ( + since_join > timedelta(days=constants.Verification.unverified_after) + and unverified not in member.roles + ): for_role.add(member) # User should be given the @Unverified role log.debug(f"Found {len(for_role)} users for {unverified} role, {len(for_kick)} users to be kicked") @@ -445,7 +440,7 @@ class Verification(Cog): # endregion # region: periodically ping @Unverified - @tasks.loop(hours=REMINDER_FREQUENCY) + @tasks.loop(hours=constants.Verification.reminder_frequency) async def ping_unverified(self) -> None: """ Delete latest `REMINDER_MESSAGE` and send it again. @@ -488,7 +483,7 @@ class Verification(Cog): time_since = datetime.utcnow() - snowflake_time(last_reminder) log.trace(f"Time since latest verification reminder: {time_since}") - to_sleep = timedelta(hours=REMINDER_FREQUENCY) - time_since + to_sleep = timedelta(hours=constants.Verification.reminder_frequency) - time_since log.trace(f"Time to sleep until next ping: {to_sleep}") # Delta can be negative if `REMINDER_FREQUENCY` has already passed @@ -519,7 +514,7 @@ class Verification(Cog): if message.author.bot: # They're a bot, delete their message after the delay. - await message.delete(delay=BOT_MESSAGE_DELETE_DELAY) + await message.delete(delay=constants.Verification.bot_message_delete_delay) return # if a user mentions a role or guild member diff --git a/bot/constants.py b/bot/constants.py index daef6c095..820828a19 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -589,6 +589,16 @@ class PythonNews(metaclass=YAMLGetter): webhook: int +class Verification(metaclass=YAMLGetter): + section = "verification" + + unverified_after: int + kicked_after: int + reminder_frequency: int + bot_message_delete_delay: int + kick_confirmation_threshold: float + + class Event(Enum): """ Event names. This does not include every event (for example, raw diff --git a/config-default.yml b/config-default.yml index a98fd14ef..c89695bd9 100644 --- a/config-default.yml +++ b/config-default.yml @@ -493,5 +493,18 @@ python_news: channel: *PYNEWS_CHANNEL webhook: *PYNEWS_WEBHOOK + +verification: + unverified_after: 3 # Days after which non-Developers receive the @Unverified role + kicked_after: 30 # Days after which non-Developers get kicked from the guild + reminder_frequency: 28 # Hours between @Unverified pings + bot_message_delete_delay: 10 # Seconds before deleting bots response in #verification + + # Number in range [0, 1] determining the percentage of unverified users that are safe + # to be kicked from the guild in one batch, any larger amount will require staff confirmation, + # set this to 0 to require explicit approval for batches of any size + kick_confirmation_threshold: 0.01 # 1% + + config: required_keys: ['bot.token'] -- cgit v1.2.3 From 93145528d7859842602df5c6535f3995187ffadb Mon Sep 17 00:00:00 2001 From: Senjan21 <53477086+Senjan21@users.noreply.github.com> Date: Wed, 16 Sep 2020 17:34:12 +0200 Subject: Updating names of reddit emotes. --- config-default.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 20254d584..e97ebf0e8 100644 --- a/config-default.yml +++ b/config-default.yml @@ -76,9 +76,10 @@ style: ducky_maul: &DUCKY_MAUL 640137724958867467 ducky_santa: &DUCKY_SANTA 655360331002019870 - upvotes: "<:upvotes:638729835245731840>" - comments: "<:comments:638729835073765387>" - user: "<:user:638729835442602003>" + # emotes used for #reddit + upvotes: "<:reddit_upvotes:638729835245731840>" + comments: "<:reddit_comments:638729835073765387>" + user: "<:reddit_user:638729835442602003>" icons: crown_blurple: "https://cdn.discordapp.com/emojis/469964153289965568.png" -- cgit v1.2.3 From f8272b4cdcab08145c1cecedd8bbbfea4bbf3239 Mon Sep 17 00:00:00 2001 From: Senjan21 <53477086+Senjan21@users.noreply.github.com> Date: Wed, 16 Sep 2020 19:42:10 +0200 Subject: update the reddit emojis to actual emojis' --- config-default.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index e97ebf0e8..87bfd1378 100644 --- a/config-default.yml +++ b/config-default.yml @@ -77,9 +77,9 @@ style: ducky_santa: &DUCKY_SANTA 655360331002019870 # emotes used for #reddit - upvotes: "<:reddit_upvotes:638729835245731840>" - comments: "<:reddit_comments:638729835073765387>" - user: "<:reddit_user:638729835442602003>" + upvotes: "<:reddit_upvotes:755845219890757644> " + comments: "<:reddit_comments:755845255001014384>" + user: "<:reddit_users:755845303822974997>" icons: crown_blurple: "https://cdn.discordapp.com/emojis/469964153289965568.png" -- cgit v1.2.3 From 6cef33ee7b68d07a1026b784f0350b146469702d Mon Sep 17 00:00:00 2001 From: Senjan21 <53477086+Senjan21@users.noreply.github.com> Date: Wed, 16 Sep 2020 19:43:44 +0200 Subject: remove random space in `upvotes` value --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 87bfd1378..58651f548 100644 --- a/config-default.yml +++ b/config-default.yml @@ -77,7 +77,7 @@ style: ducky_santa: &DUCKY_SANTA 655360331002019870 # emotes used for #reddit - upvotes: "<:reddit_upvotes:755845219890757644> " + upvotes: "<:reddit_upvotes:755845219890757644>" comments: "<:reddit_comments:755845255001014384>" user: "<:reddit_users:755845303822974997>" -- cgit v1.2.3 From 409f0b5e5a0f71a0858c91ffde46275cf755f067 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Sun, 20 Sep 2020 11:41:48 +0200 Subject: Determine eligible duckpond emojis dynamically Instead of maintaining a list of duckpond IDs manually, it's a much better idea to detect ducky emojis dynamically using the new emoji name grouping we've introduced: All emojis that start with `ducky_` will now be counted as a duckpond ducky. The unicode duck emoji obviously still counts in addition to custom emojis with the `ducky_` prefix. Signed-off-by: Sebastiaan Zeeff --- bot/cogs/duck_pond.py | 54 +++++++++++++++++++++++++-------------------------- bot/constants.py | 15 -------------- config-default.yml | 28 -------------------------- 3 files changed, 27 insertions(+), 70 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/duck_pond.py b/bot/cogs/duck_pond.py index 7021069fa..e1aceb482 100644 --- a/bot/cogs/duck_pond.py +++ b/bot/cogs/duck_pond.py @@ -49,32 +49,32 @@ class DuckPond(Cog): return True return False + @staticmethod + def _is_duck_emoji(emoji: Union[str, discord.PartialEmoji, discord.Emoji]) -> bool: + """Check if the emoji is a valid duck emoji.""" + if isinstance(emoji, str): + return emoji == "🦆" + else: + return hasattr(emoji, "name") and emoji.name.startswith("ducky_") + async def count_ducks(self, message: Message) -> int: """ Count the number of ducks in the reactions of a specific message. Only counts ducks added by staff members. """ - duck_count = 0 - duck_reactors = [] + duck_reactors = set() + # iterate over all reactions for reaction in message.reactions: - async for user in reaction.users(): - - # Is the user a staff member and not already counted as reactor? - if not self.is_staff(user) or user.id in duck_reactors: - continue - - # Is the emoji a duck? - if hasattr(reaction.emoji, "id"): - if reaction.emoji.id in constants.DuckPond.custom_emojis: - duck_count += 1 - duck_reactors.append(user.id) - elif isinstance(reaction.emoji, str): - if reaction.emoji == "🦆": - duck_count += 1 - duck_reactors.append(user.id) - return duck_count + # check if the current reaction is a duck + if not self._is_duck_emoji(reaction.emoji): + continue + + # update the set of reactors with all staff reactors + duck_reactors |= {user.id async for user in reaction.users() if self.is_staff(user)} + + return len(duck_reactors) async def relay_message(self, message: Message) -> None: """Relays the message's content and attachments to the duck pond channel.""" @@ -105,16 +105,16 @@ class DuckPond(Cog): await message.add_reaction("✅") - @staticmethod - def _payload_has_duckpond_emoji(payload: RawReactionActionEvent) -> bool: + def _payload_has_duckpond_emoji(self, emoji: discord.PartialEmoji) -> bool: """Test if the RawReactionActionEvent payload contains a duckpond emoji.""" - if payload.emoji.is_custom_emoji(): - if payload.emoji.id in constants.DuckPond.custom_emojis: - return True - elif payload.emoji.name == "🦆": - return True + if emoji.is_unicode_emoji(): + # For unicode PartialEmojis, the `name` attribute is just the string + # representation of the emoji. This is what the helper method + # expects, as unicode emojis show up as just a `str` instance when + # inspecting the reactions attached to a message. + emoji = emoji.name - return False + return self._is_duck_emoji(emoji) @Cog.listener() async def on_raw_reaction_add(self, payload: RawReactionActionEvent) -> None: @@ -126,7 +126,7 @@ class DuckPond(Cog): send the message off to the duck pond. """ # Is the emoji in the reaction a duck? - if not self._payload_has_duckpond_emoji(payload): + if not self._payload_has_duckpond_emoji(payload.emoji): return channel = discord.utils.get(self.bot.get_all_channels(), id=payload.channel_id) diff --git a/bot/constants.py b/bot/constants.py index 17f14fec0..f087fd96f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -252,7 +252,6 @@ class DuckPond(metaclass=YAMLGetter): section = "duck_pond" threshold: int - custom_emojis: List[int] class Emojis(metaclass=YAMLGetter): @@ -292,20 +291,6 @@ class Emojis(metaclass=YAMLGetter): cross_mark: str check_mark: str - ducky_yellow: int - ducky_blurple: int - ducky_regal: int - ducky_camo: int - ducky_ninja: int - ducky_devil: int - ducky_tube: int - ducky_hunt: int - ducky_wizard: int - ducky_party: int - ducky_angel: int - ducky_maul: int - ducky_santa: int - upvotes: str comments: str user: str diff --git a/config-default.yml b/config-default.yml index 58651f548..8d13b2d11 100644 --- a/config-default.yml +++ b/config-default.yml @@ -62,20 +62,6 @@ style: cross_mark: "\u274C" check_mark: "\u2705" - ducky_yellow: &DUCKY_YELLOW 574951975574175744 - ducky_blurple: &DUCKY_BLURPLE 574951975310065675 - ducky_regal: &DUCKY_REGAL 637883439185395712 - ducky_camo: &DUCKY_CAMO 637914731566596096 - ducky_ninja: &DUCKY_NINJA 637923502535606293 - ducky_devil: &DUCKY_DEVIL 637925314982576139 - ducky_tube: &DUCKY_TUBE 637881368008851456 - ducky_hunt: &DUCKY_HUNT 639355090909528084 - ducky_wizard: &DUCKY_WIZARD 639355996954689536 - ducky_party: &DUCKY_PARTY 639468753440210977 - ducky_angel: &DUCKY_ANGEL 640121935610511361 - ducky_maul: &DUCKY_MAUL 640137724958867467 - ducky_santa: &DUCKY_SANTA 655360331002019870 - # emotes used for #reddit upvotes: "<:reddit_upvotes:755845219890757644>" comments: "<:reddit_comments:755845255001014384>" @@ -468,20 +454,6 @@ sync: duck_pond: threshold: 5 - custom_emojis: - - *DUCKY_YELLOW - - *DUCKY_BLURPLE - - *DUCKY_CAMO - - *DUCKY_DEVIL - - *DUCKY_NINJA - - *DUCKY_REGAL - - *DUCKY_TUBE - - *DUCKY_HUNT - - *DUCKY_WIZARD - - *DUCKY_PARTY - - *DUCKY_ANGEL - - *DUCKY_MAUL - - *DUCKY_SANTA python_news: mail_lists: -- cgit v1.2.3 From 9410194c058675428c4ed99f403e84cb65c18a71 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Sun, 20 Sep 2020 12:04:56 +0200 Subject: Add channel blacklist for duckpond As announcements already get a lot of exposure and have a high risk of getting "ducked", duckpond will now ignore those channels and never relay those announcements to our duckpond. Signed-off-by: Sebastiaan Zeeff --- bot/cogs/duck_pond.py | 4 ++++ bot/constants.py | 8 ++++++++ config-default.yml | 30 ++++++++++++++++++++++++++---- 3 files changed, 38 insertions(+), 4 deletions(-) (limited to 'config-default.yml') diff --git a/bot/cogs/duck_pond.py b/bot/cogs/duck_pond.py index 66e862ab2..84c0c4265 100644 --- a/bot/cogs/duck_pond.py +++ b/bot/cogs/duck_pond.py @@ -125,6 +125,10 @@ class DuckPond(Cog): amount of ducks specified in the config under duck_pond/threshold, it will send the message off to the duck pond. """ + # Was this reaction issued in a blacklisted channel? + if payload.channel_id in constants.DuckPond.channel_blacklist: + return + # Is the emoji in the reaction a duck? if not self._payload_has_duckpond_emoji(payload.emoji): return diff --git a/bot/constants.py b/bot/constants.py index f087fd96f..aec0ffce3 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -252,6 +252,7 @@ class DuckPond(metaclass=YAMLGetter): section = "duck_pond" threshold: int + channel_blacklist: List[int] class Emojis(metaclass=YAMLGetter): @@ -380,12 +381,14 @@ class Channels(metaclass=YAMLGetter): section = "guild" subsection = "channels" + admin_announcements: int admin_spam: int admins: int announcements: int attachment_log: int big_brother_logs: int bot_commands: int + change_log: int cooldown: int defcon: int dev_contrib: int @@ -397,9 +400,11 @@ class Channels(metaclass=YAMLGetter): how_to_get_help: int incidents: int incidents_archive: int + mailing_lists: int message_log: int meta: int mod_alerts: int + mod_announcements: int mod_log: int mod_spam: int mods: int @@ -408,7 +413,10 @@ class Channels(metaclass=YAMLGetter): off_topic_2: int organisation: int python_discussion: int + python_events: int + python_news: int reddit: int + staff_announcements: int talent_pool: int user_event_announcements: int user_log: int diff --git a/config-default.yml b/config-default.yml index 8d13b2d11..4c1c7e483 100644 --- a/config-default.yml +++ b/config-default.yml @@ -130,9 +130,14 @@ guild: modmail: 714494672835444826 channels: - announcements: 354619224620138496 - user_event_announcements: &USER_EVENT_A 592000283102674944 - python_news: &PYNEWS_CHANNEL 704372456592506880 + # Public announcement and news channels + change_log: &CHANGE_LOG 748238795236704388 + announcements: &ANNOUNCEMENTS 354619224620138496 + python_news: &PYNEWS_CHANNEL 704372456592506880 + python_events: &PYEVENTS_CHANNEL 729674110270963822 + mailing_lists: &MAILING_LISTS 704372456592506880 + reddit: &REDDIT_CHANNEL 458224812528238616 + user_event_announcements: &USER_EVENT_A 592000283102674944 # Development dev_contrib: &DEV_CONTRIB 635950537262759947 @@ -163,7 +168,6 @@ guild: # Special bot_commands: &BOT_CMD 267659945086812160 esoteric: 470884583684964352 - reddit: 458224812528238616 verification: 352442727016693763 # Staff @@ -178,6 +182,12 @@ guild: mod_spam: &MOD_SPAM 620607373828030464 organisation: &ORGANISATION 551789653284356126 staff_lounge: &STAFF_LOUNGE 464905259261755392 + duck_pond: &DUCK_POND 637820308341915648 + + # Staff announcement channels + staff_announcements: &STAFF_ANNOUNCEMENTS 464033278631084042 + mod_announcements: &MOD_ANNOUNCEMENTS 372115205867700225 + admin_announcements: &ADMIN_ANNOUNCEMENTS 749736155569848370 # Voice admins_voice: &ADMINS_VOICE 500734494840717332 @@ -454,6 +464,18 @@ sync: duck_pond: threshold: 5 + channel_blacklist: + - *ANNOUNCEMENTS + - *PYNEWS_CHANNEL + - *PYEVENTS_CHANNEL + - *MAILING_LISTS + - *REDDIT_CHANNEL + - *USER_EVENT_A + - *DUCK_POND + - *CHANGE_LOG + - *STAFF_ANNOUNCEMENTS + - *MOD_ANNOUNCEMENTS + - *ADMIN_ANNOUNCEMENTS python_news: mail_lists: -- cgit v1.2.3 From 588213c6209b8df143634f916ff866bea4a9cec3 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Sun, 20 Sep 2020 20:26:25 +0200 Subject: Lower duckpond threshold to increase activity There's not a lot of activity in our duckpond at the moment. To activate our duckies, I've decreased the duckpond threshold to 4. This means that a message will now be relayed once it's been ducked four times. Let's get all of our ducks in a row. Signed-off-by: Sebastiaan Zeeff --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 4c1c7e483..fe15e5a87 100644 --- a/config-default.yml +++ b/config-default.yml @@ -463,7 +463,7 @@ sync: max_diff: 10 duck_pond: - threshold: 5 + threshold: 4 channel_blacklist: - *ANNOUNCEMENTS - *PYNEWS_CHANNEL -- cgit v1.2.3 From 921198829a3339caf5e027ac893c0996815650f3 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Sun, 27 Sep 2020 17:02:56 +0200 Subject: Allow !eval in #code-help-voice --- bot/constants.py | 1 + bot/exts/utils/snekbox.py | 2 +- config-default.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index c710e2dff..d3794d173 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -391,6 +391,7 @@ class Channels(metaclass=YAMLGetter): big_brother_logs: int bot_commands: int change_log: int + code_help_voice: int cooldown: int defcon: int dev_contrib: int diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index b3baffba2..18b9a5014 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -41,7 +41,7 @@ RAW_CODE_REGEX = re.compile( MAX_PASTE_LEN = 1000 # `!eval` command whitelists -EVAL_CHANNELS = (Channels.bot_commands, Channels.esoteric) +EVAL_CHANNELS = (Channels.bot_commands, Channels.esoteric, Channels.code_help_voice) EVAL_CATEGORIES = (Categories.help_available, Categories.help_in_use) EVAL_ROLES = (Roles.helpers, Roles.moderators, Roles.admins, Roles.owners, Roles.python_community, Roles.partners) diff --git a/config-default.yml b/config-default.yml index e7669e6db..5112af95b 100644 --- a/config-default.yml +++ b/config-default.yml @@ -190,6 +190,7 @@ guild: admin_announcements: &ADMIN_ANNOUNCEMENTS 749736155569848370 # Voice + code_help_voice: 755154969761677312 admins_voice: &ADMINS_VOICE 500734494840717332 staff_voice: &STAFF_VOICE 412375055910043655 -- cgit v1.2.3 From 80409d40d0f9d39d08b287d5db460fba7c26ea0d Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sat, 10 Oct 2020 17:50:27 +0300 Subject: Add voice gate configuration to config-default.yml --- config-default.yml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 3de83dbb1..2d70c17e4 100644 --- a/config-default.yml +++ b/config-default.yml @@ -481,5 +481,11 @@ verification: kick_confirmation_threshold: 0.01 # 1% +voice_gate: + minimum_days_verified: 3 # Days how much user have to be verified to pass Voice Gate + minimum_messages: 50 # How much messages user must have to pass Voice Gate + bot_message_delete_delay: 10 # Seconds before deleting bot's response in Voice Gate + + config: required_keys: ['bot.token'] -- cgit v1.2.3 From 7598faddd8f68e9263d1c9748becd49cb1917919 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 11 Oct 2020 15:05:20 +0300 Subject: Add production voice gate role and channel to configuration --- config-default.yml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index afdb8fe95..a536a94db 100644 --- a/config-default.yml +++ b/config-default.yml @@ -169,6 +169,7 @@ guild: bot_commands: &BOT_CMD 267659945086812160 esoteric: 470884583684964352 verification: 352442727016693763 + voice_gate: 764802555427029012 # Staff admins: &ADMINS 365960823622991872 @@ -228,6 +229,7 @@ guild: unverified: 739794855945044069 verified: 352427296948486144 # @Developers on PyDis + voice_verified: 764802720779337729 # Staff admins: &ADMINS_ROLE 267628507062992896 -- cgit v1.2.3 From 29d370da244801040f128ad2dca9976c0c7ad61a Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Sat, 17 Oct 2020 10:30:13 +0200 Subject: Add sprinters role to filter whitelist I've added the sprinters role to the filter whitelist. This will not affect antispam and antimalware just yet, as they currently default to using the STAFF_ROLES constant. I've also kaizened the config-default.yml file by ensuring there are two linebreaks between all sections. Signed-off-by: Sebastiaan Zeeff --- bot/constants.py | 1 + config-default.yml | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 6c8b933af..0a3e48616 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -456,6 +456,7 @@ class Roles(metaclass=YAMLGetter): owners: int partners: int python_community: int + sprinters: int team_leaders: int unverified: int verified: int # This is the Developers role on PyDis, here named verified for readability reasons. diff --git a/config-default.yml b/config-default.yml index 0e7ebf2e3..c93ab9e0c 100644 --- a/config-default.yml +++ b/config-default.yml @@ -119,6 +119,7 @@ style: voice_state_green: "https://cdn.discordapp.com/emojis/656899770094452754.png" voice_state_red: "https://cdn.discordapp.com/emojis/656899769905709076.png" + guild: id: 267624335836053506 invite: "https://discord.gg/python" @@ -225,6 +226,7 @@ guild: muted: &MUTED_ROLE 277914926603829249 partners: 323426753857191936 python_community: &PY_COMMUNITY_ROLE 458226413825294336 + sprinters: &SPRINTERS 758422482289426471 unverified: 739794855945044069 verified: 352427296948486144 # @Developers on PyDis @@ -261,6 +263,7 @@ guild: reddit: 635408384794951680 talent_pool: 569145364800602132 + filter: # What do we filter? filter_zalgo: false @@ -298,6 +301,7 @@ filter: - *OWNERS_ROLE - *HELPERS_ROLE - *PY_COMMUNITY_ROLE + - *SPRINTERS keys: @@ -326,6 +330,7 @@ urls: bot_avatar: "https://raw.githubusercontent.com/discord-python/branding/master/logos/logo_circle/logo_circle.png" github_bot_repo: "https://github.com/python-discord/bot" + anti_spam: # Clean messages that violate a rule. clean_offending: true @@ -459,10 +464,12 @@ help_channels: notify_roles: - *HELPERS_ROLE + redirect_output: delete_invocation: true delete_delay: 15 + duck_pond: threshold: 4 channel_blacklist: @@ -478,6 +485,7 @@ duck_pond: - *MOD_ANNOUNCEMENTS - *ADMIN_ANNOUNCEMENTS + python_news: mail_lists: - 'python-ideas' -- cgit v1.2.3 From 7c5c8fa776e351263ecf6aa24f3d69570443b622 Mon Sep 17 00:00:00 2001 From: mbaruh Date: Sat, 17 Oct 2020 16:01:28 +0300 Subject: Centralize moderation channel checks --- bot/exts/info/information.py | 9 ++------- bot/exts/moderation/infraction/_scheduler.py | 5 +++-- bot/exts/moderation/infraction/management.py | 10 ++-------- bot/utils/channel.py | 10 +++++++++- config-default.yml | 4 ++-- 5 files changed, 18 insertions(+), 20 deletions(-) (limited to 'config-default.yml') diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index 0f50138e7..2d9cab94b 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -14,6 +14,7 @@ from bot import constants from bot.bot import Bot from bot.decorators import in_whitelist from bot.pagination import LinePaginator +from bot.utils.channel import is_mod_channel from bot.utils.checks import cooldown_with_role_bypass, has_no_roles_check, in_whitelist_check from bot.utils.time import time_since @@ -241,14 +242,8 @@ class Information(Cog): ), ] - # Use getattr to future-proof for commands invoked via DMs. - show_verbose = ( - ctx.channel.id in constants.MODERATION_CHANNELS - or getattr(ctx.channel, "category_id", None) == constants.Categories.modmail - ) - # Show more verbose output in moderation channels for infractions and nominations - if show_verbose: + if is_mod_channel(ctx.channel): fields.append(await self.expanded_user_infraction_counts(user)) fields.append(await self.user_nomination_counts(user)) else: diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 814b17830..12d831453 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -12,11 +12,12 @@ from discord.ext.commands import Context from bot import constants from bot.api import ResponseCodeError from bot.bot import Bot -from bot.constants import Colours, MODERATION_CHANNELS +from bot.constants import Colours from bot.exts.moderation.infraction import _utils from bot.exts.moderation.infraction._utils import UserSnowflake from bot.exts.moderation.modlog import ModLog from bot.utils import messages, scheduling, time +from bot.utils.channel import is_mod_channel log = logging.getLogger(__name__) @@ -136,7 +137,7 @@ class InfractionScheduler: ) if reason: end_msg = f" (reason: {textwrap.shorten(reason, width=1500, placeholder='...')})" - elif ctx.channel.id not in MODERATION_CHANNELS: + elif not is_mod_channel(ctx.channel): log.trace( f"Infraction #{id_} context is not in a mod channel; omitting infraction count." ) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index cdab1a6c7..394f63da3 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -15,7 +15,7 @@ from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator from bot.utils import messages, time -from bot.utils.checks import in_whitelist_check +from bot.utils.channel import is_mod_channel log = logging.getLogger(__name__) @@ -295,13 +295,7 @@ class ModManagement(commands.Cog): """Only allow moderators inside moderator channels to invoke the commands in this cog.""" checks = [ await commands.has_any_role(*constants.MODERATION_ROLES).predicate(ctx), - in_whitelist_check( - ctx, - channels=constants.MODERATION_CHANNELS, - categories=[constants.Categories.modmail], - redirect=None, - fail_silently=True, - ) + is_mod_channel(ctx.channel) ] return all(checks) diff --git a/bot/utils/channel.py b/bot/utils/channel.py index 851f9e1fe..d55faab57 100644 --- a/bot/utils/channel.py +++ b/bot/utils/channel.py @@ -2,7 +2,7 @@ import logging import discord -from bot.constants import Categories +from bot.constants import Categories, MODERATION_CHANNELS log = logging.getLogger(__name__) @@ -15,6 +15,14 @@ def is_help_channel(channel: discord.TextChannel) -> bool: return any(is_in_category(channel, category) for category in categories) +def is_mod_channel(channel: discord.TextChannel) -> bool: + """Return True if `channel` is one of the moderation channels or in one of the moderation categories.""" + log.trace(f"Checking if #{channel} is a mod channel.") + categories = (Categories.modmail, Categories.logs) + + return channel.id in MODERATION_CHANNELS or any(is_in_category(channel, category) for category in categories) + + def is_in_category(channel: discord.TextChannel, category_id: int) -> bool: """Return True if `channel` is within a category with `category_id`.""" return getattr(channel, "category_id", None) == category_id diff --git a/config-default.yml b/config-default.yml index c93ab9e0c..12f6582ec 100644 --- a/config-default.yml +++ b/config-default.yml @@ -129,6 +129,7 @@ guild: help_in_use: 696958401460043776 help_dormant: 691405908919451718 modmail: 714494672835444826 + logs: 468520609152892958 channels: # Public announcement and news channels @@ -179,7 +180,7 @@ guild: incidents: 714214212200562749 incidents_archive: 720668923636351037 mods: &MODS 305126844661760000 - mod_alerts: &MOD_ALERTS 473092532147060736 + mod_alerts: 473092532147060736 mod_spam: &MOD_SPAM 620607373828030464 organisation: &ORGANISATION 551789653284356126 staff_lounge: &STAFF_LOUNGE 464905259261755392 @@ -202,7 +203,6 @@ guild: moderation_channels: - *ADMINS - *ADMIN_SPAM - - *MOD_ALERTS - *MODS - *MOD_SPAM -- cgit v1.2.3 From 39ab2d8a2b00793ccf3ba51f21ece771624e24e0 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Sat, 17 Oct 2020 19:16:34 +0200 Subject: Allow !eval in #code-help-voice-2 --- bot/constants.py | 1 + bot/exts/utils/snekbox.py | 2 +- config-default.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 0a3e48616..99584ab6c 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -392,6 +392,7 @@ class Channels(metaclass=YAMLGetter): bot_commands: int change_log: int code_help_voice: int + code_help_voice_2: int cooldown: int defcon: int dev_contrib: int diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index 59a27a2be..cad451571 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -41,7 +41,7 @@ RAW_CODE_REGEX = re.compile( MAX_PASTE_LEN = 10000 # `!eval` command whitelists -EVAL_CHANNELS = (Channels.bot_commands, Channels.esoteric, Channels.code_help_voice) +EVAL_CHANNELS = (Channels.bot_commands, Channels.esoteric, Channels.code_help_voice, Channels.code_help_voice_2) EVAL_CATEGORIES = (Categories.help_available, Categories.help_in_use) EVAL_ROLES = (Roles.helpers, Roles.moderators, Roles.admins, Roles.owners, Roles.python_community, Roles.partners) diff --git a/config-default.yml b/config-default.yml index c93ab9e0c..fd96ff2c6 100644 --- a/config-default.yml +++ b/config-default.yml @@ -192,6 +192,7 @@ guild: # Voice code_help_voice: 755154969761677312 + code_help_voice_2: 766330079135268884 admins_voice: &ADMINS_VOICE 500734494840717332 staff_voice: &STAFF_VOICE 412375055910043655 -- cgit v1.2.3 From e214f6e6cd0770625cd9a102b1d14a3772990534 Mon Sep 17 00:00:00 2001 From: mbaruh Date: Sun, 18 Oct 2020 00:10:09 +0300 Subject: Added moderation categories section to config --- bot/constants.py | 4 ++++ bot/utils/channel.py | 7 ++++--- config-default.yml | 8 ++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 0a3e48616..2e6c84fc7 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -468,6 +468,7 @@ class Guild(metaclass=YAMLGetter): id: int invite: str # Discord invite, gets embedded in chat moderation_channels: List[int] + moderation_categories: List[int] moderation_roles: List[int] modlog_blacklist: List[int] reminder_whitelist: List[int] @@ -628,6 +629,9 @@ STAFF_ROLES = Guild.staff_roles # Channel combinations MODERATION_CHANNELS = Guild.moderation_channels +# Category combinations +MODERATION_CATEGORIES = Guild.moderation_categories + # Bot replies NEGATIVE_REPLIES = [ "Noooooo!!", diff --git a/bot/utils/channel.py b/bot/utils/channel.py index 487794c59..1e67d1a9b 100644 --- a/bot/utils/channel.py +++ b/bot/utils/channel.py @@ -19,10 +19,11 @@ def is_help_channel(channel: discord.TextChannel) -> bool: def is_mod_channel(channel: discord.TextChannel) -> bool: """Return True if `channel` is one of the moderation channels or in one of the moderation categories.""" log.trace(f"Checking if #{channel} is a mod channel.") - categories = (Categories.modmail, Categories.logs) - return (channel.id in constants.MODERATION_CHANNELS - or any(is_in_category(channel, category) for category in categories)) + return ( + channel.id in constants.MODERATION_CHANNELS + or any(is_in_category(channel, category) for category in constants.MODERATION_CATEGORIES) + ) def is_in_category(channel: discord.TextChannel, category_id: int) -> bool: diff --git a/config-default.yml b/config-default.yml index 12f6582ec..baa5c783a 100644 --- a/config-default.yml +++ b/config-default.yml @@ -128,8 +128,8 @@ guild: help_available: 691405807388196926 help_in_use: 696958401460043776 help_dormant: 691405908919451718 - modmail: 714494672835444826 - logs: 468520609152892958 + modmail: &MODMAIL 714494672835444826 + logs: &LOGS 468520609152892958 channels: # Public announcement and news channels @@ -200,6 +200,10 @@ guild: big_brother_logs: &BB_LOGS 468507907357409333 talent_pool: &TALENT_POOL 534321732593647616 + moderation_categories: + - *MODMAIL + - *LOGS + moderation_channels: - *ADMINS - *ADMIN_SPAM -- cgit v1.2.3 From a04575ce7ba43623d79ad4ae5611a093a7a452c5 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:37:25 +0300 Subject: Fix grammar of voice verification config comments Co-authored-by: Joe Banks --- config-default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 5060e48e0..c712d1eb7 100644 --- a/config-default.yml +++ b/config-default.yml @@ -511,8 +511,8 @@ verification: voice_gate: - minimum_days_verified: 3 # Days how much user have to be verified to pass Voice Gate - minimum_messages: 50 # How much messages user must have to pass Voice Gate + minimum_days_verified: 3 # How many days the user must have been verified for + minimum_messages: 50 # How many messages a user must have to be eligible for voice bot_message_delete_delay: 10 # Seconds before deleting bot's response in Voice Gate -- cgit v1.2.3 From 5be3f87751d4bf87c848f278050867ba45c442ec Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Wed, 21 Oct 2020 12:42:08 +0100 Subject: Relay python-dev to mailing lists channel --- config-default.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 71d4419a7..98c5ff42c 100644 --- a/config-default.yml +++ b/config-default.yml @@ -498,6 +498,7 @@ python_news: - 'python-ideas' - 'python-announce-list' - 'pypi-announce' + - 'python-dev' channel: *PYNEWS_CHANNEL webhook: *PYNEWS_WEBHOOK -- cgit v1.2.3 From aa06b099fc66ad87cbdb75d8f096ca189fd2a57f Mon Sep 17 00:00:00 2001 From: Daniel Brown Date: Thu, 22 Oct 2020 09:53:07 -0500 Subject: Added voice_chat to eval list Signed-off-by: Daniel Brown --- bot/constants.py | 1 + bot/exts/utils/snekbox.py | 8 +++++++- config-default.yml | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index b615dcd19..1bd6ef5e0 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -425,6 +425,7 @@ class Channels(metaclass=YAMLGetter): user_event_announcements: int user_log: int verification: int + voice_chat: int voice_gate: int voice_log: int diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index cad451571..8befb6fde 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -41,7 +41,13 @@ RAW_CODE_REGEX = re.compile( MAX_PASTE_LEN = 10000 # `!eval` command whitelists -EVAL_CHANNELS = (Channels.bot_commands, Channels.esoteric, Channels.code_help_voice, Channels.code_help_voice_2) +EVAL_CHANNELS = ( + Channels.bot_commands, + Channels.esoteric, + Channels.code_help_voice, + Channels.code_help_voice_2, + Channels.voice_chat +) EVAL_CATEGORIES = (Categories.help_available, Categories.help_in_use) EVAL_ROLES = (Roles.helpers, Roles.moderators, Roles.admins, Roles.owners, Roles.python_community, Roles.partners) diff --git a/config-default.yml b/config-default.yml index 98c5ff42c..3eac3d171 100644 --- a/config-default.yml +++ b/config-default.yml @@ -195,6 +195,7 @@ guild: # Voice code_help_voice: 755154969761677312 code_help_voice_2: 766330079135268884 + voice-chat: 412357430186344448 admins_voice: &ADMINS_VOICE 500734494840717332 staff_voice: &STAFF_VOICE 412375055910043655 -- cgit v1.2.3 From 0a02ba8d61fa4cee2e38baf3c34d8cb76d7530b0 Mon Sep 17 00:00:00 2001 From: Daniel Brown Date: Thu, 22 Oct 2020 10:14:47 -0500 Subject: Update config-default.yml Changing a hyphen to an underscore in the config Co-authored-by: kwzrd <44734341+kwzrd@users.noreply.github.com> --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 3eac3d171..3f4352153 100644 --- a/config-default.yml +++ b/config-default.yml @@ -195,7 +195,7 @@ guild: # Voice code_help_voice: 755154969761677312 code_help_voice_2: 766330079135268884 - voice-chat: 412357430186344448 + voice_chat: 412357430186344448 admins_voice: &ADMINS_VOICE 500734494840717332 staff_voice: &STAFF_VOICE 412375055910043655 -- cgit v1.2.3 From eb9777bb0563e02d46d1b6597a39e6e3a9131334 Mon Sep 17 00:00:00 2001 From: Daniel Brown Date: Thu, 22 Oct 2020 10:18:36 -0500 Subject: Swapped individual channel ids for category id. Signed-off-by: Daniel Brown --- bot/constants.py | 1 + bot/exts/utils/snekbox.py | 10 ++-------- config-default.yml | 1 + 3 files changed, 4 insertions(+), 8 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 1bd6ef5e0..23d5b4304 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -377,6 +377,7 @@ class Categories(metaclass=YAMLGetter): help_in_use: int help_dormant: int modmail: int + voice: int class Channels(metaclass=YAMLGetter): diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index 8befb6fde..213d57365 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -41,14 +41,8 @@ RAW_CODE_REGEX = re.compile( MAX_PASTE_LEN = 10000 # `!eval` command whitelists -EVAL_CHANNELS = ( - Channels.bot_commands, - Channels.esoteric, - Channels.code_help_voice, - Channels.code_help_voice_2, - Channels.voice_chat -) -EVAL_CATEGORIES = (Categories.help_available, Categories.help_in_use) +EVAL_CHANNELS = (Channels.bot_commands, Channels.esoteric) +EVAL_CATEGORIES = (Categories.help_available, Categories.help_in_use, Categories.voice) EVAL_ROLES = (Roles.helpers, Roles.moderators, Roles.admins, Roles.owners, Roles.python_community, Roles.partners) SIGKILL = 9 diff --git a/config-default.yml b/config-default.yml index 3f4352153..071f6e1ec 100644 --- a/config-default.yml +++ b/config-default.yml @@ -130,6 +130,7 @@ guild: help_dormant: 691405908919451718 modmail: &MODMAIL 714494672835444826 logs: &LOGS 468520609152892958 + voice: 356013253765234688 channels: # Public announcement and news channels -- cgit v1.2.3 From 765961e784ca5c1d949bd4b02251d3d3132760a8 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 31 Oct 2020 16:06:42 +0000 Subject: Add new activity block constant --- bot/constants.py | 1 + config-default.yml | 1 + 2 files changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 23d5b4304..4d41f4eb2 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -600,6 +600,7 @@ class VoiceGate(metaclass=YAMLGetter): minimum_days_verified: int minimum_messages: int bot_message_delete_delay: int + minimum_activity_blocks: int class Event(Enum): diff --git a/config-default.yml b/config-default.yml index 071f6e1ec..a2cabf5fc 100644 --- a/config-default.yml +++ b/config-default.yml @@ -521,6 +521,7 @@ voice_gate: minimum_days_verified: 3 # How many days the user must have been verified for minimum_messages: 50 # How many messages a user must have to be eligible for voice bot_message_delete_delay: 10 # Seconds before deleting bot's response in Voice Gate + minimum_activity_blocks: 3 # Number of 10 minute blocks during which a user must have been active config: -- cgit v1.2.3 From f076231f9919c1f9320c48e5e4af7a1ad2a0401f Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sun, 1 Nov 2020 02:28:43 +0000 Subject: Indent inline comment by two spaces in config-default.yml --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index a2cabf5fc..2afdcd594 100644 --- a/config-default.yml +++ b/config-default.yml @@ -521,7 +521,7 @@ voice_gate: minimum_days_verified: 3 # How many days the user must have been verified for minimum_messages: 50 # How many messages a user must have to be eligible for voice bot_message_delete_delay: 10 # Seconds before deleting bot's response in Voice Gate - minimum_activity_blocks: 3 # Number of 10 minute blocks during which a user must have been active + minimum_activity_blocks: 3 # Number of 10 minute blocks during which a user must have been active config: -- cgit v1.2.3 From bf7916a3e197540420167fd82cd2de269ff52624 Mon Sep 17 00:00:00 2001 From: Daniel Brown Date: Thu, 5 Nov 2020 14:08:45 -0600 Subject: - Added ping deletion time to config file. - Added ping message constant to the top of the voice_gate.py file. - Corrected logic error in checking if a user is cached and in a voice channel. - Reduced default message deletion time to 1 minute from 5 minutes. - Adjusted on_message event to ignore the verification ping message. Signed-off-by: Daniel Brown --- bot/constants.py | 1 + bot/exts/moderation/voice_gate.py | 26 +++++++++++++++++--------- config-default.yml | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 23d5b4304..db8b5f0a0 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -600,6 +600,7 @@ class VoiceGate(metaclass=YAMLGetter): minimum_days_verified: int minimum_messages: int bot_message_delete_delay: int + voice_ping_delete_delay: int class Event(Enum): diff --git a/bot/exts/moderation/voice_gate.py b/bot/exts/moderation/voice_gate.py index 95130fbfc..56e0149e0 100644 --- a/bot/exts/moderation/voice_gate.py +++ b/bot/exts/moderation/voice_gate.py @@ -28,6 +28,12 @@ MESSAGE_FIELD_MAP = { "total_messages": f"have sent less than {GateConf.minimum_messages} messages", } +VOICE_PING = ( + "Hello, {}! Wondering why you can't talk in the voice channels? " + "Use the `!voiceverify` command in here to verify. " + "If you don't yet qualify, you'll be told why!" +) + class VoiceGate(Cog): """Voice channels verification management.""" @@ -158,6 +164,10 @@ class VoiceGate(Cog): # When it's bot sent message, delete it after some time if message.author.bot: + # Comparing the message with the voice ping constant + if message.content.endswith(VOICE_PING[-45:]): + log.trace("Message is the voice verification ping. Ignore.") + return with suppress(discord.NotFound): await message.delete(delay=GateConf.bot_message_delete_delay) return @@ -177,7 +187,6 @@ class VoiceGate(Cog): @Cog.listener() async def on_voice_state_update(self, member: Member, *_) -> None: """Pings a user if they've never joined the voice chat before and aren't verified""" - if member.bot: log.trace("User is a bot. Ignore.") return @@ -185,7 +194,7 @@ class VoiceGate(Cog): in_cache = await self.redis_cache.get(member.id, None) # member.voice will return None if the user is not in a voice channel - if in_cache is not None and member.voice is not None: + if in_cache is None and member.voice is not None: log.trace("User not in cache and is in a voice channel") verified = any(Roles.voice_verified == role.id for role in member.roles) if verified: @@ -195,15 +204,14 @@ class VoiceGate(Cog): return log.trace("User is unverified. Send ping.") - message = await self._voice_verification_channel.send( - f"Hello, {member.mention}! Wondering why you can't talk in the voice channels? " - "Use the `!voiceverify` command in here to verify. " - "If you don't yet qualify, you'll be told why!" - ) + message = await self._voice_verification_channel.send(VOICE_PING.format(member.mention)) await self.redis_cache.set(member.id, message.id) - # Message will try to be deleted after 5 minutes. If it fails, it'll do so silently - await message.delete(delay=300) + # Message will try to be deleted after 1 minutes. If it fails, it'll do so silently + await message.delete(delay=GateConf.voice_ping_delete_delay) + else: + log.trace("User is either in the cache or not in a voice channel. Ignore.") + return async def cog_command_error(self, ctx: Context, error: Exception) -> None: """Check for & ignore any InWhitelistCheckFailure.""" diff --git a/config-default.yml b/config-default.yml index 071f6e1ec..058efa9ad 100644 --- a/config-default.yml +++ b/config-default.yml @@ -521,6 +521,7 @@ voice_gate: minimum_days_verified: 3 # How many days the user must have been verified for minimum_messages: 50 # How many messages a user must have to be eligible for voice bot_message_delete_delay: 10 # Seconds before deleting bot's response in Voice Gate + voice_ping_delete_delay: 60 # Seconds before deleting the bot's ping to user in Voice Gate config: -- cgit v1.2.3 From ec019d5d012f178acc2d9de756f694d534d71e1f Mon Sep 17 00:00:00 2001 From: Daniel Brown Date: Fri, 6 Nov 2020 13:28:04 -0600 Subject: Requested fixes - Various restructures of code. - Changed `VOICE_PING` constant to not contain the format brackets. - Added more detailed description of what the `redis_cache` will hold. - Changed message content verification to use the whole newly formatted `VOICE_PING` constant instead of a slice of it. - Added remaining parameters for the `on_voice_state_update` event for clarity. - Reorganized the logic of the `on_voice_state_update` for better clarity and better logging purposes. - Removed `_async_init` in favor of checking if the guild is ready inside the `on_voice_state_update` event. Verification channel is now loaded each time when needed, reducing risk of the object becoming stale or erroring out due to the not being ready before an event was triggered. Signed-off-by: Daniel Brown --- bot/exts/moderation/voice_gate.py | 64 ++++++++++++++++++++++----------------- config-default.yml | 2 +- 2 files changed, 37 insertions(+), 29 deletions(-) (limited to 'config-default.yml') diff --git a/bot/exts/moderation/voice_gate.py b/bot/exts/moderation/voice_gate.py index 6bcca2874..eba05901f 100644 --- a/bot/exts/moderation/voice_gate.py +++ b/bot/exts/moderation/voice_gate.py @@ -30,7 +30,7 @@ MESSAGE_FIELD_MAP = { } VOICE_PING = ( - "Hello, {0}! Wondering why you can't talk in the voice channels? " + "Wondering why you can't talk in the voice channels? " "Use the `!voiceverify` command in here to verify. " "If you don't yet qualify, you'll be told why!" ) @@ -40,15 +40,12 @@ class VoiceGate(Cog): """Voice channels verification management.""" # RedisCache[t.Union[discord.User.id, discord.Member.id], t.Union[discord.Message.id, bool]] + # The cache's keys are the IDs of members who are verified or have joined a voice channel + # The cache's values are either the message ID of the ping message or False if no message is present redis_cache = RedisCache() def __init__(self, bot: Bot) -> None: self.bot = bot - self._init_task = self.bot.loop.create_task(self._async_init()) - - async def _async_init(self) -> None: - await self.bot.wait_until_guild_available() - self._voice_verification_channel = self.bot.get_channel(Channels.voice_gate) @property def mod_log(self) -> ModLog: @@ -164,10 +161,10 @@ class VoiceGate(Cog): ctx = await self.bot.get_context(message) is_verify_command = ctx.command is not None and ctx.command.name == "voice_verify" - # When it's bot sent message, delete it after some time + # When it's a bot sent message, delete it after some time if message.author.bot: # Comparing the message with the voice ping constant - if message.content.endswith(VOICE_PING[-45:]): + if message.content.endswith(VOICE_PING): log.trace("Message is the voice verification ping. Ignore.") return with suppress(discord.NotFound): @@ -187,33 +184,44 @@ class VoiceGate(Cog): await message.delete() @Cog.listener() - async def on_voice_state_update(self, member: Member, *_) -> None: + async def on_voice_state_update( + self, + member: Member, + before: discord.VoiceState, + after: discord.VoiceState + ) -> None: """Pings a user if they've never joined the voice chat before and aren't verified.""" if member.bot: log.trace("User is a bot. Ignore.") return - in_cache = await self.redis_cache.get(member.id, None) - # member.voice will return None if the user is not in a voice channel - if in_cache is None and member.voice is not None: - log.trace("User not in cache and is in a voice channel") - verified = any(Roles.voice_verified == role.id for role in member.roles) - if verified: - log.trace("User is verified, add to the cache and ignore") - # redis cache does not accept None, so False is used to signify no message - await self.redis_cache.set(member.id, False) - return - - log.trace("User is unverified. Send ping.") - message = await self._voice_verification_channel.send(VOICE_PING.format(member.mention)) - await self.redis_cache.set(member.id, message.id) - - # Message will try to be deleted after 1 minutes. If it fails, it'll do so silently - await message.delete(delay=GateConf.voice_ping_delete_delay) - else: - log.trace("User is either in the cache or not in a voice channel. Ignore.") + if member.voice is None: + log.trace("User not in a voice channel. Ignore.") return + else: + in_cache = await self.redis_cache.get(member.id, None) + if in_cache: + log.trace("User already in cache. Ignore.") + return + else: + log.trace("User not in cache and is in a voice channel") + verified = any(Roles.voice_verified == role.id for role in member.roles) + if verified: + log.trace("User is verified, add to the cache and ignore") + # redis cache does not accept None, so False is used to signify no message + await self.redis_cache.set(member.id, False) + return + + log.trace("User is unverified. Send ping.") + await self.bot.wait_until_guild_available() + voice_verification_channel = self.bot.get_channel(Channels.voice_gate) + + message = await voice_verification_channel.send(f"Hello, {member.mention}! {VOICE_PING}") + await self.redis_cache.set(member.id, message.id) + + # Message will try to be deleted after 1 minutes. If it fails, it'll do so silently + await message.delete(delay=GateConf.voice_ping_delete_delay) async def cog_command_error(self, ctx: Context, error: Exception) -> None: """Check for & ignore any InWhitelistCheckFailure.""" diff --git a/config-default.yml b/config-default.yml index 7de9faeda..c2a4e71ad 100644 --- a/config-default.yml +++ b/config-default.yml @@ -522,7 +522,7 @@ voice_gate: minimum_messages: 50 # How many messages a user must have to be eligible for voice bot_message_delete_delay: 10 # Seconds before deleting bot's response in Voice Gate minimum_activity_blocks: 3 # Number of 10 minute blocks during which a user must have been active - voice_ping_delete_delay: 60 # Seconds before deleting the bot's ping to user in Voice Gate + voice_ping_delete_delay: 60 # Seconds before deleting the bot's ping to user in Voice Gate config: required_keys: ['bot.token'] -- cgit v1.2.3 From 8c8b65c4647f23010d7fb458246c28b3ccbeb549 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Wed, 11 Nov 2020 22:37:28 +0100 Subject: Config: ensure 2 blank lines between classes Previous changes reduced the spacing to 1 blank line, which is inconsistent with the prevailing style. --- bot/constants.py | 2 ++ config-default.yml | 1 + 2 files changed, 3 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 66a049851..731f06fed 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -361,6 +361,7 @@ class CleanMessages(metaclass=YAMLGetter): message_limit: int + class Stats(metaclass=YAMLGetter): section = "bot" subsection = "stats" @@ -603,6 +604,7 @@ class VoiceGate(metaclass=YAMLGetter): minimum_activity_blocks: int voice_ping_delete_delay: int + class Event(Enum): """ Event names. This does not include every event (for example, raw diff --git a/config-default.yml b/config-default.yml index c2a4e71ad..8912841ff 100644 --- a/config-default.yml +++ b/config-default.yml @@ -524,5 +524,6 @@ voice_gate: minimum_activity_blocks: 3 # Number of 10 minute blocks during which a user must have been active voice_ping_delete_delay: 60 # Seconds before deleting the bot's ping to user in Voice Gate + config: required_keys: ['bot.token'] -- cgit v1.2.3 From 6c8fed8aeb4850990f9f027401898aeb3330e732 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sun, 15 Nov 2020 19:57:00 +0000 Subject: Update config options with new hosts --- config-default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index 8912841ff..ac67251b0 100644 --- a/config-default.yml +++ b/config-default.yml @@ -4,13 +4,13 @@ bot: sentry_dsn: !ENV "BOT_SENTRY_DSN" redis: - host: "redis" + host: "redis.default.svc.cluster.local" port: 6379 password: !ENV "REDIS_PASSWORD" use_fakeredis: false stats: - statsd_host: "graphite" + statsd_host: "graphite.default.svc.cluster.local" presence_update_timeout: 300 cooldowns: -- cgit v1.2.3 From 99ffe92dee79f4884bde4c086b2a8dc853684861 Mon Sep 17 00:00:00 2001 From: Gustav Odinger Date: Mon, 16 Nov 2020 01:10:20 +0100 Subject: Add bright green color to constants - The color is used in the new help channel embed --- bot/constants.py | 1 + config-default.yml | 1 + 2 files changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 731f06fed..719895567 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -248,6 +248,7 @@ class Colours(metaclass=YAMLGetter): soft_red: int soft_green: int soft_orange: int + bright_green: int class DuckPond(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 8912841ff..cdcf914ce 100644 --- a/config-default.yml +++ b/config-default.yml @@ -27,6 +27,7 @@ style: soft_red: 0xcd6d6d soft_green: 0x68c290 soft_orange: 0xf9cb54 + bright_green: 0x01d277 emojis: defcon_disabled: "<:defcondisabled:470326273952972810>" -- cgit v1.2.3 From 43e52d7102c2bf33186b527dc512566d08b0d1fd Mon Sep 17 00:00:00 2001 From: Gustav Odinger Date: Tue, 17 Nov 2020 23:03:11 +0100 Subject: Add green-checkmark to bot constants --- bot/constants.py | 2 ++ config-default.yml | 2 ++ 2 files changed, 4 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 719895567..d2e88a744 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -355,6 +355,8 @@ class Icons(metaclass=YAMLGetter): voice_state_green: str voice_state_red: str + green_checkmark: str + class CleanMessages(metaclass=YAMLGetter): section = "bot" diff --git a/config-default.yml b/config-default.yml index cdcf914ce..30b607f94 100644 --- a/config-default.yml +++ b/config-default.yml @@ -120,6 +120,8 @@ style: voice_state_green: "https://cdn.discordapp.com/emojis/656899770094452754.png" voice_state_red: "https://cdn.discordapp.com/emojis/656899769905709076.png" + green_checkmark: "https://raw.githubusercontent.com/python-discord/branding/master/icons/checkmark/green-checkmark-dist.png" + guild: id: 267624335836053506 -- cgit v1.2.3 From ebd440ac8aff27ad70f6a59fde6af15fa8c61b68 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 19 Nov 2020 00:27:05 +0000 Subject: Update snekbox address in config-default.yml --- config-default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index ac67251b0..89493c4de 100644 --- a/config-default.yml +++ b/config-default.yml @@ -329,7 +329,7 @@ urls: paste_service: !JOIN [*SCHEMA, *PASTE, "/{key}"] # Snekbox - snekbox_eval_api: "http://snekbox:8060/eval" + snekbox_eval_api: "http://snekbox.default.svc.cluster.local/eval" # Discord API URLs discord_api: &DISCORD_API "https://discordapp.com/api/v7/" -- cgit v1.2.3 From 6204906c734e0f0d44f7c1c544fbf4eb2443acc8 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Tue, 24 Nov 2020 21:56:34 +0300 Subject: Adds VoiceChannels and Related Chats to Config Updates config-default.yml to include voice channels, and the text chat channel they map to. Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/constants.py | 7 +++++++ config-default.yml | 13 ++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 6bb6aacd2..ecbf5f98e 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -398,6 +398,9 @@ class Channels(metaclass=YAMLGetter): change_log: int code_help_voice: int code_help_voice_2: int + general_voice: int + admins_voice: int + staff_voice: int cooldown: int defcon: int dev_contrib: int @@ -430,7 +433,11 @@ class Channels(metaclass=YAMLGetter): user_event_announcements: int user_log: int verification: int + code_help_chat: int + code_help_chat_2: int voice_chat: int + admins_voice_chat: int + staff_voice_chat: int voice_gate: int voice_log: int diff --git a/config-default.yml b/config-default.yml index 60eb437af..8ba3b7175 100644 --- a/config-default.yml +++ b/config-default.yml @@ -196,10 +196,17 @@ guild: mod_announcements: &MOD_ANNOUNCEMENTS 372115205867700225 admin_announcements: &ADMIN_ANNOUNCEMENTS 749736155569848370 - # Voice - code_help_voice: 755154969761677312 - code_help_voice_2: 766330079135268884 + # Voice Chat + code_help_chat: 755154969761677312 + code_help_chat_2: 766330079135268884 voice_chat: 412357430186344448 + admins_voice_chat: 000000000000000000 # FIXME + staff_voice_chat: 541638762007101470 + + # Voice Channels + code_help_voice: 751592231726481530 + code_help_voice_2: 764232549840846858 + general_voice: 751591688538947646 admins_voice: &ADMINS_VOICE 500734494840717332 staff_voice: &STAFF_VOICE 412375055910043655 -- cgit v1.2.3 From 0242b4ed4145edf3e3e6ea6ebcef62aaff77d7ec Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Thu, 26 Nov 2020 13:57:55 -0800 Subject: Help channels: remove how_to_get_help from excluded channels The channel as moved out of this category. Delete the constant too since it isn't used anywhere else. Keep the excluded channels a tuple to conveniently support excluding multiple channels in the future. --- bot/constants.py | 1 - bot/exts/help_channels/_channel.py | 2 +- config-default.yml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 6bb6aacd2..fb280b042 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -406,7 +406,6 @@ class Channels(metaclass=YAMLGetter): dm_log: int esoteric: int helpers: int - how_to_get_help: int incidents: int incidents_archive: int mailing_lists: int diff --git a/bot/exts/help_channels/_channel.py b/bot/exts/help_channels/_channel.py index d6d6f1245..e717d7af8 100644 --- a/bot/exts/help_channels/_channel.py +++ b/bot/exts/help_channels/_channel.py @@ -10,7 +10,7 @@ from bot.exts.help_channels import _caches, _message log = logging.getLogger(__name__) MAX_CHANNELS_PER_CATEGORY = 50 -EXCLUDED_CHANNELS = (constants.Channels.how_to_get_help, constants.Channels.cooldown) +EXCLUDED_CHANNELS = (constants.Channels.cooldown,) def get_category_channels(category: discord.CategoryChannel) -> t.Iterable[discord.TextChannel]: diff --git a/config-default.yml b/config-default.yml index 60eb437af..82023aae1 100644 --- a/config-default.yml +++ b/config-default.yml @@ -155,7 +155,6 @@ guild: python_discussion: &PY_DISCUSSION 267624335836053506 # Python Help: Available - how_to_get_help: 704250143020417084 cooldown: 720603994149486673 # Logs -- cgit v1.2.3 From fde6dd9a37cf5f5a98eed7ffcb05f43dca6886a3 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sat, 28 Nov 2020 21:18:13 +0300 Subject: Removes Non-Existent Channel Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/constants.py | 1 - config-default.yml | 1 - 2 files changed, 2 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index ecbf5f98e..5b3779eb6 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -436,7 +436,6 @@ class Channels(metaclass=YAMLGetter): code_help_chat: int code_help_chat_2: int voice_chat: int - admins_voice_chat: int staff_voice_chat: int voice_gate: int voice_log: int diff --git a/config-default.yml b/config-default.yml index 8ba3b7175..563244819 100644 --- a/config-default.yml +++ b/config-default.yml @@ -200,7 +200,6 @@ guild: code_help_chat: 755154969761677312 code_help_chat_2: 766330079135268884 voice_chat: 412357430186344448 - admins_voice_chat: 000000000000000000 # FIXME staff_voice_chat: 541638762007101470 # Voice Channels -- cgit v1.2.3 From cd8b4b91fbfe69b9370fec1a89dc82688f7d317b Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sat, 28 Nov 2020 21:19:34 +0300 Subject: Renames Code Help Channel Renames code_help_channel to be more inline with channel 2. Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/constants.py | 4 ++-- config-default.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 5b3779eb6..42b3d7008 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -396,7 +396,7 @@ class Channels(metaclass=YAMLGetter): big_brother_logs: int bot_commands: int change_log: int - code_help_voice: int + code_help_voice_1: int code_help_voice_2: int general_voice: int admins_voice: int @@ -433,7 +433,7 @@ class Channels(metaclass=YAMLGetter): user_event_announcements: int user_log: int verification: int - code_help_chat: int + code_help_chat_1: int code_help_chat_2: int voice_chat: int staff_voice_chat: int diff --git a/config-default.yml b/config-default.yml index 563244819..f18d08126 100644 --- a/config-default.yml +++ b/config-default.yml @@ -197,13 +197,13 @@ guild: admin_announcements: &ADMIN_ANNOUNCEMENTS 749736155569848370 # Voice Chat - code_help_chat: 755154969761677312 + code_help_chat_1: 755154969761677312 code_help_chat_2: 766330079135268884 voice_chat: 412357430186344448 staff_voice_chat: 541638762007101470 # Voice Channels - code_help_voice: 751592231726481530 + code_help_voice_1: 751592231726481530 code_help_voice_2: 764232549840846858 general_voice: 751591688538947646 admins_voice: &ADMINS_VOICE 500734494840717332 -- cgit v1.2.3 From d190056ac6fa39ac54b4eafc566c2f05fc0b6f8e Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sat, 28 Nov 2020 21:48:51 +0300 Subject: Fixes Alignment Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- config-default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'config-default.yml') diff --git a/config-default.yml b/config-default.yml index f18d08126..df3d971ff 100644 --- a/config-default.yml +++ b/config-default.yml @@ -197,13 +197,13 @@ guild: admin_announcements: &ADMIN_ANNOUNCEMENTS 749736155569848370 # Voice Chat - code_help_chat_1: 755154969761677312 + code_help_chat_1: 755154969761677312 code_help_chat_2: 766330079135268884 voice_chat: 412357430186344448 staff_voice_chat: 541638762007101470 # Voice Channels - code_help_voice_1: 751592231726481530 + code_help_voice_1: 751592231726481530 code_help_voice_2: 764232549840846858 general_voice: 751591688538947646 admins_voice: &ADMINS_VOICE 500734494840717332 -- cgit v1.2.3 From 114e3058ca18cf45a55d7dcdf7d509de44d7ad1a Mon Sep 17 00:00:00 2001 From: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> Date: Sat, 28 Nov 2020 23:52:30 +0300 Subject: Alphabetizes Channel Ordering Signed-off-by: Hassan Abouelela <47495861+HassanAbouelela@users.noreply.github.com> --- bot/constants.py | 12 ++++++------ config-default.yml | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 42b3d7008..a33939537 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -391,16 +391,16 @@ class Channels(metaclass=YAMLGetter): admin_announcements: int admin_spam: int admins: int + admins_voice: int announcements: int attachment_log: int big_brother_logs: int bot_commands: int change_log: int + code_help_chat_1: int + code_help_chat_2: int code_help_voice_1: int code_help_voice_2: int - general_voice: int - admins_voice: int - staff_voice: int cooldown: int defcon: int dev_contrib: int @@ -408,6 +408,7 @@ class Channels(metaclass=YAMLGetter): dev_log: int dm_log: int esoteric: int + general_voice: int helpers: int how_to_get_help: int incidents: int @@ -429,14 +430,13 @@ class Channels(metaclass=YAMLGetter): python_news: int reddit: int staff_announcements: int + staff_voice: int + staff_voice_chat: int talent_pool: int user_event_announcements: int user_log: int verification: int - code_help_chat_1: int - code_help_chat_2: int voice_chat: int - staff_voice_chat: int voice_gate: int voice_log: int diff --git a/config-default.yml b/config-default.yml index df3d971ff..9dc1ac18e 100644 --- a/config-default.yml +++ b/config-default.yml @@ -196,19 +196,19 @@ guild: mod_announcements: &MOD_ANNOUNCEMENTS 372115205867700225 admin_announcements: &ADMIN_ANNOUNCEMENTS 749736155569848370 - # Voice Chat - code_help_chat_1: 755154969761677312 - code_help_chat_2: 766330079135268884 - voice_chat: 412357430186344448 - staff_voice_chat: 541638762007101470 - # Voice Channels + admins_voice: &ADMINS_VOICE 500734494840717332 code_help_voice_1: 751592231726481530 code_help_voice_2: 764232549840846858 general_voice: 751591688538947646 - admins_voice: &ADMINS_VOICE 500734494840717332 staff_voice: &STAFF_VOICE 412375055910043655 + # Voice Chat + code_help_chat_1: 755154969761677312 + code_help_chat_2: 766330079135268884 + staff_voice_chat: 541638762007101470 + voice_chat: 412357430186344448 + # Watch big_brother_logs: &BB_LOGS 468507907357409333 talent_pool: &TALENT_POOL 534321732593647616 -- cgit v1.2.3 From fa60dc9b7bbbc8bdf06afc46c672015598c5df66 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 19 Dec 2020 03:55:14 +0000 Subject: Remove usage of joined_at metricity API item --- bot/constants.py | 2 +- bot/exts/info/information.py | 19 +++++-------------- bot/exts/moderation/voice_gate.py | 10 ++-------- config-default.yml | 2 +- 4 files changed, 9 insertions(+), 24 deletions(-) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index 08ae0d52f..c4bb6b2d6 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -606,7 +606,7 @@ class Verification(metaclass=YAMLGetter): class VoiceGate(metaclass=YAMLGetter): section = "voice_gate" - minimum_days_verified: int + minimum_days_member: int minimum_messages: int bot_message_delete_delay: int minimum_activity_blocks: int diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index 187950689..5450ff377 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -225,12 +225,12 @@ class Information(Cog): if is_set and (emoji := getattr(constants.Emojis, f"badge_{badge}", None)): badges.append(emoji) - verified_at, activity = await self.user_verification_and_messages(user) + activity = await self.user_messages(user) if on_server: joined = time_since(user.joined_at, max_units=3) roles = ", ".join(role.mention for role in user.roles[1:]) - membership = {"Joined": joined, "Verified": verified_at or "False", "Roles": roles or None} + membership = {"Joined": joined, "Verified": user.pending, "Roles": roles or None} if not is_mod_channel(ctx.channel): membership.pop("Verified") @@ -360,30 +360,21 @@ class Information(Cog): return "Nominations", "\n".join(output) - async def user_verification_and_messages(self, user: FetchedMember) -> Tuple[Union[bool, str], Tuple[str, str]]: + async def user_messages(self, user: FetchedMember) -> Tuple[Union[bool, str], Tuple[str, str]]: """ - Gets the time of verification and amount of messages for `member`. + Gets the amount of messages for `member`. Fetches information from the metricity database that's hosted by the site. If the database returns a code besides a 404, then many parts of the bot are broken including this one. """ activity_output = [] - verified_at = False try: user_activity = await self.bot.api_client.get(f"bot/users/{user.id}/metricity_data") except ResponseCodeError as e: if e.status == 404: activity_output = "No activity" - else: - try: - if (verified_at := user_activity["verified_at"]) is not None: - verified_at = time_since(parser.isoparse(verified_at), max_units=3) - except ValueError: - log.warning(f"Could not parse ISO string correctly for user {user.id} verification date.") - verified_at = None - activity_output.append(user_activity["total_messages"] or "No messages") activity_output.append(user_activity["activity_blocks"] or "No activity") @@ -391,7 +382,7 @@ class Information(Cog): f"{name}: {metric}" for name, metric in zip(["Messages", "Activity blocks"], activity_output) ) - return verified_at, ("Activity", activity_output) + return ("Activity", activity_output) def format_fields(self, mapping: Mapping[str, Any], field_width: Optional[int] = None) -> str: """Format a mapping to be readable to a human.""" diff --git a/bot/exts/moderation/voice_gate.py b/bot/exts/moderation/voice_gate.py index 4d48d2c1b..b8f37adf2 100644 --- a/bot/exts/moderation/voice_gate.py +++ b/bot/exts/moderation/voice_gate.py @@ -29,7 +29,7 @@ FAILED_MESSAGE = ( ) MESSAGE_FIELD_MAP = { - "verified_at": f"have been verified for less than {GateConf.minimum_days_verified} days", + "joined_at": f"have been on the server for less than {GateConf.minimum_days_member} days", "voice_banned": "have an active voice ban infraction", "total_messages": f"have sent less than {GateConf.minimum_messages} messages", "activity_blocks": f"have been active for fewer than {GateConf.minimum_activity_blocks} ten-minute blocks", @@ -149,14 +149,8 @@ class VoiceGate(Cog): await ctx.author.send(embed=embed) return - # Pre-parse this for better code style - if data["verified_at"] is not None: - data["verified_at"] = parser.isoparse(data["verified_at"]) - else: - data["verified_at"] = datetime.utcnow() - timedelta(days=3) - checks = { - "verified_at": data["verified_at"] > datetime.utcnow() - timedelta(days=GateConf.minimum_days_verified), + "joined_at": ctx.author.joined_at > datetime.utcnow() - timedelta(days=GateConf.minimum_days_verified), "total_messages": data["total_messages"] < GateConf.minimum_messages, "voice_banned": data["voice_banned"], "activity_blocks": data["activity_blocks"] < GateConf.minimum_activity_blocks diff --git a/config-default.yml b/config-default.yml index 006743342..3f3f66962 100644 --- a/config-default.yml +++ b/config-default.yml @@ -526,7 +526,7 @@ verification: voice_gate: - minimum_days_verified: 3 # How many days the user must have been verified for + minimum_days_member: 3 # How many days the user must have been a member for minimum_messages: 50 # How many messages a user must have to be eligible for voice bot_message_delete_delay: 10 # Seconds before deleting bot's response in Voice Gate minimum_activity_blocks: 3 # Number of 10 minute blocks during which a user must have been active -- cgit v1.2.3 From 477af4efe7a0ed155bf6f5805a2d0fd3674e0e6f Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 20 Dec 2020 09:38:49 +0200 Subject: Add GitHub API key to config as environment variable --- bot/constants.py | 1 + config-default.yml | 1 + 2 files changed, 2 insertions(+) (limited to 'config-default.yml') diff --git a/bot/constants.py b/bot/constants.py index c4bb6b2d6..25a4c4d09 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -493,6 +493,7 @@ class Keys(metaclass=YAMLGetter): section = "keys" site_api: Optional[str] + github: Optional[str] class URLs(metaclass=YAMLGetter): diff --git a/config-default.yml b/config-default.yml index 3f3f66962..ca89bb639 100644 --- a/config-default.yml +++ b/config-default.yml @@ -323,6 +323,7 @@ filter: keys: site_api: !ENV "BOT_API_KEY" + github: !ENV "GITHUB_API_KEY" urls: -- cgit v1.2.3