diff --git a/cogs/pin.py b/cogs/pin.py index 4f169e4..61e6e6f 100644 --- a/cogs/pin.py +++ b/cogs/pin.py @@ -1,7 +1,11 @@ import config from discord.ext.commands import Cog from discord.enums import MessageType - +from discord import Embed +import aiohttp +import gidgethub.aiohttp +from helpers.checks import check_if_collaborator +from helpers.checks import check_if_pin_channel class Pin(Cog): """ @@ -11,16 +15,37 @@ class Pin(Cog): def __init__(self, bot): self.bot = bot + async def get_pinboard(self, gh, channel): + # Find pinboard pin + pinboard_msg = None + for msg in reversed(await channel.pins()): + if msg.author == self.bot.user and len(msg.embeds) > 0 and msg.embeds[0].title == "Pinboard": + # Found pinboard, return content and gist id + id = msg.embeds[0].url.split("/")[-1] + data = await gh.getitem(f"/gists/{id}") + return (id, data["files"]["pinboard.md"]["content"]) + + # Create pinboard pin if it does not exist + data = await gh.post("/gists", data={"files": {"pinboard.md": {"content": "Old pins are available here:\n\n"}}, "description": f"Pinboard for SwitchRoot #{channel.name}", "public": True}) + msg = await channel.send(embed=Embed(title="Pinboard", description="Old pins are moved to the pinboard to make space for new ones. Check it out!", url=data["html_url"])) + await msg.pin() + return (data["id"], data["files"]["pinboard.md"]["content"]) + + async def add_pin_to_pinboard(self, channel, data): + if config.github_oauth_token == "": + # Don't add to gist pinboard if we don't have an oauth token + return + + async with aiohttp.ClientSession() as session: + gh = gidgethub.aiohttp.GitHubAPI(session, "RoboCop-NG", oauth_token=config.github_oauth_token) + (id, content) = await self.get_pinboard(gh, channel) + content += "- " + data + "\n" + + await gh.patch(f"/gists/{id}", data={"files": {"pinboard.md": {"content": content}}}) + # Use raw_reaction to allow pinning old messages. @Cog.listener() async def on_raw_reaction_add(self, payload): - # TODO: handle more than 50 pinned message - # BODY: If there are more than 50 pinned messages, - # BODY: we should move the oldest pin to a pinboard - # BODY: channel to make room for the new pin. - # BODY: This is why we use the pin reaction to remember - # BODY: that a message is pinned. - # Check that the user wants to pin this message if payload.emoji.name not in ["📌", "📍"]: return @@ -45,17 +70,24 @@ class Pin(Cog): if reaction.emoji == "📌": if reaction.me: return - break + else: + break - # Wait for the automated "Pinned" message so we can delete it - waitable = self.bot.wait_for('message', check=check) + # Add pin to pinboard, create one if none is found + await self.add_pin_to_pinboard(target_chan, target_msg.jump_url) - # Pin the message - await target_msg.pin() + # Avoid staying "stuck" waiting for the pin message if message + # was already manually pinned + if not target_msg.pinned: + # Wait for the automated "Pinned" message so we can delete it + waitable = self.bot.wait_for('message', check=check) - # Delete the automated Pinned message - msg = await waitable - await msg.delete() + # Pin the message + await target_msg.pin() + + # Delete the automated Pinned message + msg = await waitable + await msg.delete() # Add a Pin reaction so we remember that the message is pinned await target_msg.add_reaction("📌") diff --git a/config_template.py b/config_template.py index 9c69127..46caaba 100644 --- a/config_template.py +++ b/config_template.py @@ -94,3 +94,6 @@ spy_channels = general_channels # Channels and roles where users can pin messages allowed_pin_channels = [] allowed_pin_roles = [] + +# Used for the pinboard. Leave empty if you don't wish for a gist pinboard. +github_oauth_token = "" diff --git a/requirements.txt b/requirements.txt index de97058..1a0200c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,6 @@ git+https://github.com/Rapptz/discord.py@rewrite asyncio python-dateutil humanize -parsedatetime \ No newline at end of file +parsedatetime +aiohttp +gidgethub