From a8af888e7a318698ae3d89d8582d5dcdc0bcf5a3 Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Sun, 1 May 2022 20:09:02 -0600 Subject: [PATCH] Add reddit hot command --- jarvis/cogs/reddit.py | 95 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/jarvis/cogs/reddit.py b/jarvis/cogs/reddit.py index 9207ea6..1456a09 100644 --- a/jarvis/cogs/reddit.py +++ b/jarvis/cogs/reddit.py @@ -1,13 +1,17 @@ """JARVIS Reddit cog.""" import asyncio import logging +from typing import List, Optional from asyncpraw import Reddit +from asyncpraw.models.reddit.submission import Submission +from asyncpraw.models.reddit.submission import Subreddit as Sub from asyncprawcore.exceptions import Forbidden, NotFound, Redirect from dis_snek import InteractionContext, Permissions, Scale, Snake from dis_snek.client.utils.misc_utils import get from dis_snek.models.discord.channel import ChannelTypes, GuildText from dis_snek.models.discord.components import ActionRow, Select, SelectOption +from dis_snek.models.discord.embed import Embed from dis_snek.models.snek.application_commands import ( OptionTypes, SlashCommand, @@ -19,6 +23,7 @@ from jarvis_core.db.models import Subreddit, SubredditFollow from jarvis import const from jarvis.config import JarvisConfig +from jarvis.utils import build_embed from jarvis.utils.permissions import admin_or_permissions DEFAULT_USER_AGENT = f"python:JARVIS:{const.__version__} (by u/zevaryx)" @@ -34,6 +39,70 @@ class RedditCog(Scale): config.reddit["user_agent"] = config.reddit.get("user_agent", DEFAULT_USER_AGENT) self.api = Reddit(**config.reddit) + async def post_embeds(self, sub: Sub, post: Submission) -> Optional[List[Embed]]: + """ + Build a post embeds. + + Args: + post: Post to build embeds + """ + url = "https://reddit.com" + post.permalink + await post.author.load() + author_url = f"https://reddit.com/u/{post.author.name}" + images = [] + content = f"**{post.title}**" + if "url" in vars(post): + if any(post.url.endswith(x) for x in ["jpeg", "jpg", "png", "gif"]): + images = [post.url] + if "media_metadata" in vars(post): + for k, v in post.media_metadata.items(): + if v["status"] != "valid" or v["m"] not in ["image/jpg", "image/png", "image/gif"]: + continue + ext = v["m"].split("/")[-1] + i_url = f"https://i.redd.it/{k}.{ext}" + images.append(i_url) + if len(images) == 4: + break + + if "selftext" in vars(post) and post.selftext: + content += "\n\n" + post.selftext + if len(content) > 600: + content = content[:600] + "..." + content += f"\n\n[View this post]({url})" + + if not images and not content: + self.logger.debug(f"Post {post.id} had neither content nor images?") + return None + + color = "#FF4500" + if "primary_color" in vars(sub): + color = sub.primary_color + base_embed = build_embed( + title="", + description=content, + fields=[], + timestamp=post.created_utc, + url=url, + color=color, + ) + base_embed.set_author( + name="u/" + post.author.name, url=author_url, icon_url=post.author.icon_img + ) + base_embed.set_footer( + text="Reddit", icon_url="https://www.redditinc.com/assets/images/site/reddit-logo.png" + ) + + embeds = [base_embed] + + if len(images) > 0: + embeds[0].set_image(url=images[0]) + for image in images[1:4]: + embed = Embed(url=url) + embed.set_image(url=image) + embeds.append(embed) + + return embeds + reddit = SlashCommand(name="reddit", description="Manage Reddit follows") @reddit.subcommand(sub_cmd_name="follow", sub_cmd_description="Follow a Subreddit") @@ -160,6 +229,32 @@ class RedditCog(Scale): component.disabled = True await message.edit(components=components) + @reddit.subcommand(sub_cmd_name="hot", sub_cmd_description="Get the hot post of a subreddit") + @slash_option( + name="name", description="Subreddit name", opt_type=OptionTypes.STRING, required=True + ) + async def _subreddit_hot(self, ctx: InteractionContext, name: str) -> None: + name = name.replace("r/", "") + if len(name) > 20 or len(name) < 3: + await ctx.send("Invalid Subreddit name", ephemeral=True) + return + try: + subreddit = await self.api.subreddit(name) + await subreddit.load() + except (NotFound, Forbidden, Redirect) as e: + self.logger.debug(f"Subreddit {name} raised {e.__class__.__name__} in hot") + await ctx.send("Subreddit may be private, quarantined, or nonexistent.", ephemeral=True) + return + try: + hot = [x async for x in subreddit.hot(limit=1)][0] + except Exception as e: + self.logger.error(f"Failed to get hot from {name}", exc_info=e) + await ctx.send("Well, this is awkward. Something went wrong", ephemeral=True) + return + + embeds = await self.post_embeds(subreddit, hot) + await ctx.send(embeds=embeds) + def setup(bot: Snake) -> None: """Add RedditCog to JARVIS"""