Esempio n. 1
0
 async def reddit_pages(self, ctx, subreddit, limit: int = 5):
     """Gives you a paginated menu of any subreddit"""
     posts = []
     u = '\u200b'
     async with self.bot.session.get(f"https://www.reddit.com/r/{subreddit}/hot.json", params={'limit': 100}) as r:
         res = await r.json()
     for i in res['data']['children']:
         if i['data']['over_18'] and not ctx.channel.is_nsfw():
             raise commands.NSFWChannelRequired(ctx.channel)
         posts.append(i['data'])
     counter = 0
     embeds = []
     async with ctx.typing():
         for s in random.sample(posts, len(posts)):
             embed = discord.Embed(title=str(s['title']), colour=self.bot.colour,
                                   url=f"https://reddit.com/{s['permalink']}")
             embed.set_author(name=s['author'])
             embed.set_footer(text=f"{s['upvote_ratio'] * 100:,}% upvote ratio | posted to r/{s['subreddit']}")
             if s['is_self']:
                 embed.description = f"{s['selftext'].replace('**', f'{u}')}\n{self.up} **{s['score']:,}** :speech_balloon: **{s['num_comments']:,}** {self.share} **{s['num_crossposts']:,}** :medal: **{s['total_awards_received']}**"
             else:
                 embed.set_image(url=s['url'].split("?")[0])
                 embed.description = f"{self.up} **{s['score']:,}** :speech_balloon: **{s['num_comments']:,}** {self.share} **{s['num_crossposts']:,}** :medal: **{s['total_awards_received']}**"
             embeds.append(embed)
             counter += 1
             if counter == limit:
                 break
             else:
                 continue
     menu = paginator.CatchAllMenu(paginator.EmbedSource(embeds))
     menu.add_info_fields({self.up: "How many upvotes the post has", "💬": "How many comments the post has", self.share: "How many shares/cross-posts the post has", ":medal:": "How many awards the post has"})
     await menu.start(ctx)
Esempio n. 2
0
 async def post(self, ctx, subreddit, sort='hot'):
     posts = []
     sorts = ['new', 'hot', 'top', 'rising', 'controversial']
     if sort not in sorts:
         raise commands.BadArgument(
             f"that isn't a valid sort! Valid sorts include {', '.join(sorts)}."
         )
     async with ctx.typing():
         try:
             s = random.choice(await self.get_post_data(subreddit, sort))
         except IndexError:
             raise commands.BadArgument('subreddit not found!')
         embed = discord.Embed(title=str(s['title']),
                               colour=self.bot.colour,
                               url=f"https://reddit.com/{s['permalink']}")
         embed.set_author(name=s['author'])
         embed.set_footer(
             text=
             f"r/{s['subreddit']} • {s['upvote_ratio'] * 100:,}% upvote ratio"
         )
         embed.timestamp = datetime.datetime.utcfromtimestamp(s['created'])
         if s['is_self']:
             embed.description = f"{s['selftext']}\n{self.up} **{s['score']:,}** :speech_balloon: **{s['num_comments']:,}** {self.share} **{s['num_crossposts']:,}** :medal: **{s['total_awards_received']}**"
         else:
             embed.set_image(url=s['url'])
             embed.description = f"{self.up} **{s['score']:,}** :speech_balloon: **{s['num_comments']:,}** {self.share} **{s['num_crossposts']:,}** :medal: **{s['total_awards_received']}**"
     if s['over_18'] and not ctx.channel.is_nsfw():
         raise commands.NSFWChannelRequired(ctx.channel)
     return await ctx.send(embed=embed)
Esempio n. 3
0
    async def _perform_search(self, requester: str,
                              channel: discord.TextChannel, subreddit: str,
                              sort_by: str):
        """ Performs the search for queries with aiohttp. Returns 10 items. """
        async with self.bot.session.get(
                f"https://reddit.com/r/{subreddit}/about.json",
                headers=self.headers) as subr_top_resp:
            subr_deets = await subr_top_resp.json()

        if "data" not in subr_deets:
            raise commands.BadArgument("Subreddit not found.")
        if subr_deets["data"].get("over18", None) and not channel.is_nsfw():
            raise commands.NSFWChannelRequired(channel)

        params = {"t": "all" if sort_by == "top" else ""}

        async with self.bot.session.get(
                f"https://reddit.com/r/{subreddit}/{sort_by}.json",
                headers=self.headers,
                params=params,
        ) as subr_resp:
            subreddit_json = await subr_resp.json()

        subreddit_pages = []
        common_img_exts = (".jpg", ".jpeg", ".png", ".gif")

        idx = 0
        for post_data in subreddit_json["data"]["children"]:
            image_url = None
            video_url = None

            if idx == 20:
                break

            _short = post_data["data"]
            if _short.get("stickied", False) or (_short.get("over_18", False)
                                                 and not channel.is_nsfw()):
                idx += 1
                continue

            image_url = (_short["url"]
                         if _short["url"].endswith(common_img_exts) else None)
            if "v.redd.it" in _short["url"]:
                image_url = _short["thumbnail"]
                video_teriary = _short.get("media", None)
                if video_teriary:
                    video_url = _short["url"]
                else:
                    continue

            subreddit_pages.append(
                SubredditPost(_short,
                              image_link=image_url,
                              video_link=video_url))
            idx += 1

        return self._gen_embeds(requester, subreddit_pages[:30])
Esempio n. 4
0
 async def thonk(self, ctx):
     async with ctx.typing():
         s = random.choice(await self.get_post_data('showerthoughts', 'top'))
         embed = discord.Embed(title=str(s['title']),
                               colour=self.bot.colour,
                               url=f"https://reddit.com/{s['permalink']}",
                               description=f"{self.up} **{s['score']:,}** :speech_balloon: **{s['num_comments']:,}** {self.share} **{s['num_crossposts']:,}** :medal: **{s['total_awards_received']}**")
         embed.timestamp = datetime.datetime.utcfromtimestamp(s['created'])
         embed.set_author(name=s['author'])
         embed.set_footer(text=f"r/{s['subreddit']} • {s['upvote_ratio'] * 100:,}% upvote ratio")
     if s['over_18'] and not ctx.channel.is_nsfw():
         raise commands.NSFWChannelRequired(ctx.channel)
     return await ctx.send(embed=embed)
Esempio n. 5
0
 async def meme(self, ctx):
     subreddit = random.choice(['memes', 'meme', 'dankmemes', 'okbuddyretard', 'memeeconomy', 'dankexchange', 'pewdiepiesubmissions', 'wholesomememes'])
     async with ctx.typing():
         s = random.choice(await self.get_post_data(subreddit, 'hot'))
         embed = discord.Embed(title=str(s['title']),
                               colour=self.bot.colour,
                               url=f"https://reddit.com/{s['permalink']}",
                               description=f"{self.up} **{s['score']:,}** :speech_balloon: **{s['num_comments']:,}** {self.share} **{s['num_crossposts']:,}** :medal: **{s['total_awards_received']}**")
         embed.timestamp = datetime.datetime.utcfromtimestamp(s['created'])
         embed.set_author(name=s['author'])
         embed.set_footer(text=f"r/{s['subreddit']} • {s['upvote_ratio'] * 100:,}% upvote ratio")
         embed.set_image(url=s['url'])
     if s['over_18'] and not ctx.channel.is_nsfw():
         raise commands.NSFWChannelRequired(ctx.channel)
     return await ctx.send(embed=embed)
Esempio n. 6
0
    async def interaction_response_metacommand(self, ctx:utils.Context, users:commands.Greedy[discord.Member]):
        """Handles pinging out the responses for a given interaction. Users cannot call this."""

        # Get metadata
        metadata = ctx.response_metadata[0]
        command_name = metadata['command_name']

        # Get command enabled
        if metadata['enabled'] is False:
            raise utils.errors.DisabledCustomCommand()

        # Get command nsfw
        if metadata['nsfw'] and ctx.channel.is_nsfw is False:
            raise commands.NSFWChannelRequired()

        # Check mention count
        max_mentions = metadata['max_mentions']
        min_mentions = metadata['min_mentions']
        if len(users) > max_mentions:
            return await ctx.send("You've mentioned too many users for this command.")  # TODO raise custom error
        if len(users) < min_mentions:
            return await ctx.send("You've not mentioned enough users for this command.")  # TODO raise custom error

        # Get valid responses
        async with self.bot.database() as db:
            response = await db("SELECT response FROM command_responses WHERE command_name=$1 AND guild_id=$2 AND user_mention_count=$3 ORDER BY RANDOM() LIMIT 1", command_name, ctx.guild.id, len(users))
        if not response:
            return await ctx.send(f"There are no responses with {len(users)} user arguments set on the website.")

        # Build command response
        def argument_replacer(match):
            """Replaces the argument of the group with a user mention"""

            if match.group(2):
                return users[int(match.group(2)) - 1].mention
            if match.group(1) == 'user':
                return users[0].mention
            return ctx.author.mention

        # Output
        text = response[0]['response']
        await ctx.send(self.ARGUMENT_REPLACEMENT_REGEX.sub(argument_replacer, text))
Esempio n. 7
0
    async def get_subreddit_embed(self, ctx: MyContext, subreddit: str):
        min_creation = ctx.message.created_at - datetime.timedelta(hours=3)

        subinfo = await self.fetch_subreddit_info(subreddit)
        if subinfo['over18'] and not (ctx.guild and ctx.channel.is_nsfw()):
            raise commands.NSFWChannelRequired(ctx.channel)

        def check(post):
            return (post['approved_at_utc'] or datetime.datetime.fromtimestamp(post['created_utc']) <= min_creation) \
                and post['score'] >= 10 \
                and (not post['over_18'] or not (ctx.guild and ctx.channel.is_nsfw())) \
                and not post['spoiler']

        for attempt in range(10):
            child = await self.fetch_random_reddit_post(subreddit)
            if not check(child):
                continue
            if child.get('url_overridden_by_dest') and not child.get(
                    'is_video') and not child.get('media'):
                break
        else:
            raise NoPostsFound(subreddit)
        title: str = child['title']
        sub_prefixed: str = child['subreddit_name_prefixed']
        author: str = child['author']
        permalink: str = child['permalink']
        score: int = child['score']
        upvote_emoji: discord.Emoji = discord.utils.get(self.bot.emojis,
                                                        name='upvote')
        embed = discord.Embed(
            title=f'/{sub_prefixed}',
            description=f'[{title}](https://reddit.com{permalink})\n'
            f'Score: {score}{upvote_emoji}',
            url=f'https://reddit.com/{sub_prefixed}',
            colour=discord.Colour.dark_orange(),
            timestamp=datetime.datetime.fromtimestamp(child['created_utc']))
        embed.set_image(url=child['url'])
        embed.set_author(name=f'/u/{author}',
                         url=f'https://reddit.com/u/{author}')
        return embed
Esempio n. 8
0
 async def subreddit(self, ctx, subreddit):
     try:
         async with ctx.typing(), self.bot.session.get(
                 f"https://reddit.com/r/{subreddit}/about/.json"
         ) as r, self.bot.session.get(
                 f"https://www.reddit.com/r/{subreddit}/about/moderators.json"
         ) as r1:
             res = await r.json()
             resp = await r1.json()
             data = res['data']
             icon = data['community_icon'].split("?")[0]
             banner = data['banner_background_image'].split("?")[0]
             embed = discord.Embed(
                 description=
                 f"{data['public_description']}\n**{data['subscribers']:,}** subscribers | **{data['active_user_count']:,}** active users",
                 colour=self.bot.colour)
             embed.title = data['display_name_prefixed']
             embed.url = f"https://reddit.com/r/{subreddit}"
             embed.set_thumbnail(url=icon)
             embed.description += f'\n<:asset:734531316741046283> [Icon URL]({str(icon)}) | [Banner URL]({str(banner)})'
             daba = resp['data']
             mods = [i for i in daba['children']]
             embed.add_field(
                 name=f"Mods (Total {len(mods)})",
                 value="\n".join([
                     f"[{mod['name']}](https://reddit.com/user/{mod['name']})"
                     for mod in mods[:10]
                 ]))
             embed.set_footer(
                 text=
                 f"Subreddit created {humanize.naturaltime(datetime.datetime.utcnow() - datetime.datetime.utcfromtimestamp(data['created_utc']))}"
             )
         if data['over18'] and not ctx.channel.is_nsfw():
             raise commands.NSFWChannelRequired(ctx.channel)
         return await ctx.send(embed=embed)
     except KeyError:
         raise commands.BadArgument(f'subreddit {subreddit} not found.')
Esempio n. 9
0
    async def reddit(self, ctx: NewCtx, sub: str = 'memes', sort: str = 'hot'):
        """Gets the <sub>reddits <amount> of posts sorted by <method>"""
        if sort.lower() not in ("top", "hot", "best", "controversial", "new",
                                "rising"):
            return await ctx.send("Not a valid sort-by type.")

        PostObj = namedtuple('PostObj', [
            'title', 'self_text', 'url', 'author', 'image_link', 'video_link',
            'upvotes', 'comment_count', 'subreddit'
        ])

        posts = set()

        subr_url = f"https://www.reddit.com/r/{sub}/about.json"
        base_url = f"https://www.reddit.com/r/{sub}/{sort}.json"

        async with self.bot.session.get(
                subr_url, headers={"User-Agent":
                                   "Yoink discord bot"}) as subr_resp:
            subr_deets = await subr_resp.json()

        if 'data' not in subr_deets:
            raise commands.BadArgument("Subreddit does not exist.")
        if subr_deets['data'].get('over18',
                                  None) and not ctx.channel.is_nsfw():
            raise commands.NSFWChannelRequired(ctx.channel)

        async with self.bot.session.get(base_url) as res:
            page_json = await res.json()

        idx = 0
        for post_data in page_json['data']['children']:
            image_url = None
            video_url = None

            if idx == 20:
                break

            post = post_data['data']
            if post['stickied'] or (post['over_18']
                                    and not ctx.channel.is_nsfw()):
                idx += 1
                continue

            title = shorten(post['title'], width=250)
            self_text = shorten(post['selftext'], width=1500)
            url = f"https://www.reddit.com{post['permalink']}"
            author = post['author']
            image_url = post['url'] if post['url'].endswith(
                (".jpg", ".png", ".jpeg", ".gif", ".webp")) else None
            if "v.redd.it" in post['url']:
                image_url = post['thumbnail']
                if post.get("media", None):
                    video_url = post['url']
                else:
                    continue
            upvotes = post['score']
            comment_count = post['num_comments']
            subreddit = post['subreddit']

            _post = PostObj(title=title,
                            self_text=self_text,
                            url=url,
                            author=author,
                            image_link=image_url,
                            video_link=video_url,
                            upvotes=upvotes,
                            comment_count=comment_count,
                            subreddit=subreddit)

            posts.add(_post)
        embeds = self._gen_embeds(ctx.author, list(posts))
        pages = menus.MenuPages(PagedEmbedMenu(embeds))
        await pages.start(ctx)
Esempio n. 10
0
 def predicate(ctx):
     if isinstance(ctx.channel, DMChannel):
         return True
     if ctx.channel.is_nsfw():
         return True
     raise commands.NSFWChannelRequired(ctx.channel)