aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/utilities/wikipedia.py
blob: 5bc7bacbdabae90993684e14cf44b616e6a350b0 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import re
from datetime import UTC, datetime
from html import unescape

from discord import Color, Embed, TextChannel
from discord.ext import commands
from pydis_core.utils.logging import get_logger

from bot.bot import Bot
from bot.utils import LinePaginator
from bot.utils.exceptions import APIError

log = get_logger(__name__)

SEARCH_API = (
    "https://en.wikipedia.org/w/api.php"
)
WIKI_PARAMS = {
    "action": "query",
    "list": "search",
    "prop": "info",
    "inprop": "url",
    "utf8": "",
    "format": "json",
    "origin": "*",

}
WIKI_THUMBNAIL = (
    "https://upload.wikimedia.org/wikipedia/en/thumb/8/80/Wikipedia-logo-v2.svg"
    "/330px-Wikipedia-logo-v2.svg.png"
)
WIKI_SNIPPET_REGEX = r"(<!--.*?-->|<[^>]*>)"
WIKI_SEARCH_RESULT = (
    "**[{name}]({url})**\n"
    "{description}\n"
)

WIKI_HEADERS = {
    "User-Agent": "SirLancebot/0.0 (https://github.com/python-discord; [email protected]) aiohttp/0.0"
}


class WikipediaSearch(commands.Cog):
    """Get info from wikipedia."""

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

    async def wiki_request(self, channel: TextChannel, search: str) -> list[str]:
        """Search wikipedia search string and return formatted first 10 pages found."""
        params = WIKI_PARAMS | {"srlimit": 10, "srsearch": search}
        async with self.bot.http_session.get(url=SEARCH_API, params=params, headers=WIKI_HEADERS) as resp:
            if resp.status != 200:
                log.info(f"Unexpected response `{resp.status}` while searching wikipedia for `{search}`")
                raise APIError("Wikipedia API", resp.status)

            raw_data = await resp.json()

            if not raw_data.get("query"):
                if error := raw_data.get("errors"):
                    log.error(f"There was an error while communicating with the Wikipedia API: {error}")
                raise APIError("Wikipedia API", resp.status, error)

            lines = []
            if raw_data["query"]["searchinfo"]["totalhits"]:
                for article in raw_data["query"]["search"]:
                    line = WIKI_SEARCH_RESULT.format(
                        name=article["title"],
                        description=unescape(
                            re.sub(
                                WIKI_SNIPPET_REGEX, "", article["snippet"]
                            )
                        ),
                        url=f"https://en.wikipedia.org/?curid={article['pageid']}"
                    )
                    lines.append(line)

            return lines

    @commands.cooldown(1, 10, commands.BucketType.user)
    @commands.command(name="wikipedia", aliases=("wiki",))
    async def wikipedia_search_command(self, ctx: commands.Context, *, search: str) -> None:
        """Sends paginated top 10 results of Wikipedia search.."""
        contents = await self.wiki_request(ctx.channel, search)

        if contents:
            embed = Embed(
                title="Wikipedia Search Results",
                colour=Color.og_blurple()
            )
            embed.set_thumbnail(url=WIKI_THUMBNAIL)
            embed.timestamp = datetime.now(tz=UTC)
            await LinePaginator.paginate(contents, ctx, embed, restrict_to_user=ctx.author)
        else:
            await ctx.send(
                "Sorry, we could not find a wikipedia article using that search term."
            )


async def setup(bot: Bot) -> None:
    """Load the WikipediaSearch cog."""
    await bot.add_cog(WikipediaSearch(bot))