aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/evergreen/stackoverflow.py
blob: 0aebac2d530fb94e64673e5057cb6c2573e6aad9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import logging
from html import unescape
from urllib.parse import quote_plus

from discord import Embed
from discord.errors import HTTPException
from discord.ext import commands

from bot.constants import Colours

logger = logging.getLogger(__name__)

BASE_URL = "https://api.stackexchange.com/2.2/search/advanced?order=desc&sort=activity&site=stackoverflow&q={query}"
SEARCH_URL = "https://stackoverflow.com/search?q={query}"


class Stackoverflow(commands.Cog):
    """A cog which returns the top 5 results of a query from stackoverflow."""

    def __init__(self, bot: commands.Bot):
        self.bot = bot

    @commands.command(aliases=["so"])
    @commands.cooldown(1, 15, commands.cooldowns.BucketType.user)
    async def stackoverflow(self, ctx: commands.Context, *, search_query: str) -> None:
        """Sends the top 5 results of a search query from stackoverflow."""
        for _ in range(3):
            async with self.bot.http_session.get(BASE_URL.format(query=quote_plus(search_query))) as response:
                if response.status == 200:
                    data = await response.json()
                    break
                else:
                    logger.error(f'Status code is not 200, it is {response.status}')
                    continue
        if response.status != 200:  # If the status is still not 200 after the 3 tries
            err_embed = Embed(
                title="Error in fetching results from Stackoverflow",
                description=("Sorry, there was en error while trying to fetch data from the Stackoverflow website. "
                             "Please try again in some time. If this issue persists, please contact the mods or send a "
                             "message in #dev-contrib."),
                color=Colours.soft_red
            )
            await ctx.send(embed=err_embed)
            return
        elif not data['items']:
            err_embed = Embed(
                title=f"No search results found for {search_query!r}",
                color=Colours.soft_red
            )
            await ctx.send(embed=err_embed)
            return

        top5 = data["items"][:5]
        embed = Embed(title=f"Search results for {search_query!r} - Stackoverflow",
                      url=SEARCH_URL.format(query=quote_plus(search_query)),
                      description=f"Here are the top {len(top5)} results:",
                      color=Colours.orange)
        for item in top5:
            embed.add_field(
                name=f"{unescape(item['title'])}",
                value=(f"[{item['score']} upvote{'s' if item['score'] != 1 else ''} ┃ "
                       f"{item['view_count']} view{'s' if item['view_count'] != 1 else ''} ┃ "
                       f"{item['answer_count']} answer{'s' if item['answer_count'] != 1 else ''} ┃ "
                       f"Tags: {', '.join(item['tags'])}]"
                       f"({item['link']})"),
                inline=False)
        embed.set_footer(text="View the original link for more results.")
        try:
            await ctx.send(embed=embed)
        except HTTPException:
            err_embed = Embed(
                title="Your search query is too long, please try shortening your search query",
                color=Colours.soft_red
            )
            await ctx.send(embed=err_embed)


def setup(bot: commands.Bot) -> None:
    """Loads Stackoverflow Cog."""
    bot.add_cog(Stackoverflow(bot))