diff options
author | 2022-10-05 19:19:07 +0100 | |
---|---|---|
committer | 2022-10-05 19:19:07 +0100 | |
commit | 5ab04a8e44a93ac2fac3b3a6c58c72b550dc5ef9 (patch) | |
tree | f0eebd3c4e386a6ec8550a3eac5d2c6289f2d099 | |
parent | Merge pull request #2284 from shtlrs/2281-fix-non-awaited-remove-cog-calls (diff) | |
parent | Merge branch 'main' into patreon (diff) |
Merge pull request #1917 from mathstrains21/patreon
Add Patreon Cog
-rw-r--r-- | bot/constants.py | 4 | ||||
-rw-r--r-- | bot/exts/info/patreon.py | 129 | ||||
-rw-r--r-- | config-default.yml | 5 |
3 files changed, 138 insertions, 0 deletions
diff --git a/bot/constants.py b/bot/constants.py index 830ba049c..ba7d53ea8 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -515,6 +515,10 @@ class Roles(metaclass=YAMLGetter): jammers: int + patreon_tier_1: int + patreon_tier_2: int + patreon_tier_3: int + class Guild(metaclass=YAMLGetter): section = "guild" diff --git a/bot/exts/info/patreon.py b/bot/exts/info/patreon.py new file mode 100644 index 000000000..e3c8c07d1 --- /dev/null +++ b/bot/exts/info/patreon.py @@ -0,0 +1,129 @@ +import datetime + +import arrow +import discord +from discord.ext import commands, tasks + +from bot import constants +from bot.bot import Bot +from bot.constants import Channels, Guild, Roles, STAFF_PARTNERS_COMMUNITY_ROLES +from bot.decorators import in_whitelist +from bot.log import get_logger +from bot.utils.channel import get_or_fetch_channel + +log = get_logger(__name__) + +PATREON_INFORMATION = ( + "Python Discord is a volunteer run non-profit organization, so we rely on Patreon donations to do what we do. " + "We use the money we get to offer excellent prizes for all of our events. These include t-shirts, " + "stickers, and sometimes even Raspberry Pis!\n\n" + "You can read more about how Patreon donations help us, and consider donating yourself, on our patreon page " + "[here](https://pydis.com/patreon)!" +) +NO_PATRONS_MESSAGE = "*There are currently no patrons at this tier.*" + +# List of tuples containing tier number and Discord role ID. +# Ordered from highest tier to lowest. +PATREON_TIERS: list[tuple[int, int]] = [ + (3, Roles.patreon_tier_3), + (2, Roles.patreon_tier_2), + (1, Roles.patreon_tier_1), +] + + +def get_patreon_tier(member: discord.Member) -> int: + """ + Get the patreon tier of `member`. + + A patreon tier of 0 indicates the user is not a patron. + """ + for tier, role_id in PATREON_TIERS: + if member.get_role(role_id): + return tier + return 0 + + +class Patreon(commands.Cog): + """Cog that shows patreon supporters.""" + + def __init__(self, bot: Bot) -> None: + self.bot = bot + + self.current_monthly_supporters.start() + + @commands.Cog.listener() + async def on_member_update(self, before: discord.Member, after: discord.Member) -> None: + """Send a message when someone receives a patreon role.""" + old_patreon_tier = get_patreon_tier(before) + new_patreon_tier = get_patreon_tier(after) + + if new_patreon_tier <= old_patreon_tier: + return + + message = ( + f":tada: {after.mention} just became a **tier {new_patreon_tier}** patron!\n" + "Support us on Patreon: https://pydis.com/patreon" + ) + channel = await get_or_fetch_channel(Channels.meta) + await channel.send(message) + + async def send_current_supporters(self, channel: discord.abc.Messageable, automatic: bool = False) -> None: + """Send the current list of patreon supporters, sorted by tier level.""" + guild = self.bot.get_guild(Guild.id) + + embed_list = [] + for tier, role_id in PATREON_TIERS: + role = guild.get_role(role_id) + + # Filter out any members where this is not their highest tier. + patrons = [member for member in role.members if get_patreon_tier(member) == tier] + patron_names = [f"• {patron}" for patron in patrons] + + embed = discord.Embed( + title=role.name, + description="\n".join(patron_names) if patron_names else NO_PATRONS_MESSAGE, + colour=role.colour + ) + embed_list.append(embed) + + main_embed = discord.Embed( + title="Patreon Supporters - Monthly Update" if automatic else "Patreon Supporters", + description=( + PATREON_INFORMATION + + "\n\nThank you to the users listed below who are already supporting us!" + ), + ) + + await channel.send(embeds=(main_embed, *embed_list)) + + @commands.group("patreon", aliases=("patron",), invoke_without_command=True) + async def patreon_info(self, ctx: commands.Context) -> None: + """Send information about how Python Discord uses Patreon.""" + embed = discord.Embed( + title="Patreon", + description=( + PATREON_INFORMATION + + "\n\nTo see our current supporters, run " + + f"`{constants.Bot.prefix}patreon supporters` in <#{Channels.bot_commands}>" + ) + ) + await ctx.send(embed=embed) + + @patreon_info.command("supporters", aliases=("patrons",)) + @in_whitelist(channels=(Channels.bot_commands,), roles=STAFF_PARTNERS_COMMUNITY_ROLES) + async def patreon_supporters(self, ctx: commands.Context) -> None: + """Sends the current list of patreon supporters, sorted by tier level.""" + await self.send_current_supporters(ctx.channel) + + @tasks.loop(time=datetime.time(hour=17)) + async def current_monthly_supporters(self) -> None: + """A loop running daily to see if it's the first of the month. If so call `self.send_current_supporters()`.""" + now = arrow.utcnow() + if now.day == 1: + meta_channel = await get_or_fetch_channel(Channels.meta) + await self.send_current_supporters(meta_channel, automatic=True) + + +async def setup(bot: Bot) -> None: + """Load the Patreon cog.""" + await bot.add_cog(Patreon(bot)) diff --git a/config-default.yml b/config-default.yml index e84a6045b..a5f4a5bda 100644 --- a/config-default.yml +++ b/config-default.yml @@ -300,6 +300,11 @@ guild: # Streaming video: 764245844798079016 + # Patreon + patreon_tier_1: 505040943800516611 + patreon_tier_2: 743399725914390631 + patreon_tier_3: 743400204367036520 + moderation_roles: - *ADMINS_ROLE - *MOD_TEAM_ROLE |