feat(commands:cnf|Linux): add new Command Not Found scrapper (Known issue: cache resolve on none results)
This commit is contained in:
parent
fcc23d87df
commit
88f60690dd
12 changed files with 247 additions and 0 deletions
19
tuxbot/cogs/Linux/__init__.py
Normal file
19
tuxbot/cogs/Linux/__init__.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
from tuxbot.core.bot import Tux
|
||||||
|
from .linux import Linux
|
||||||
|
from .config import LinuxConfig, HAS_MODELS
|
||||||
|
|
||||||
|
VersionInfo = namedtuple("VersionInfo", "major minor micro release_level")
|
||||||
|
version_info = VersionInfo(major=1, minor=0, micro=0, release_level="alpha")
|
||||||
|
|
||||||
|
__version__ = "v{}.{}.{}-{}".format(
|
||||||
|
version_info.major,
|
||||||
|
version_info.minor,
|
||||||
|
version_info.micro,
|
||||||
|
version_info.release_level,
|
||||||
|
).replace("\n", "")
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot: Tux):
|
||||||
|
bot.add_cog(Linux(bot))
|
12
tuxbot/cogs/Linux/config.py
Normal file
12
tuxbot/cogs/Linux/config.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from structured_config import Structure
|
||||||
|
|
||||||
|
HAS_MODELS = False
|
||||||
|
|
||||||
|
|
||||||
|
class LinuxConfig(Structure):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
extra: Dict[str, Dict] = {}
|
0
tuxbot/cogs/Linux/functions/__init__.py
Normal file
0
tuxbot/cogs/Linux/functions/__init__.py
Normal file
77
tuxbot/cogs/Linux/functions/cnf.py
Normal file
77
tuxbot/cogs/Linux/functions/cnf.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
from tuxbot.cogs.Linux.functions.exceptions import CNFException
|
||||||
|
|
||||||
|
|
||||||
|
def _(x):
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
class CNF:
|
||||||
|
_url = "https://command-not-found.com/{}"
|
||||||
|
_content: BeautifulSoup
|
||||||
|
|
||||||
|
command: str
|
||||||
|
|
||||||
|
description: str = ""
|
||||||
|
meta: dict = {}
|
||||||
|
distro: dict = {}
|
||||||
|
|
||||||
|
def __init__(self, command: str):
|
||||||
|
self.command = command
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
async def fetch(self):
|
||||||
|
try:
|
||||||
|
async with aiohttp.ClientSession() as cs:
|
||||||
|
async with cs.get(self._url.format(self.command)) as s:
|
||||||
|
if s.status == 200:
|
||||||
|
self._content = BeautifulSoup(
|
||||||
|
await s.text(), "html.parser"
|
||||||
|
)
|
||||||
|
return self.parse()
|
||||||
|
|
||||||
|
except (aiohttp.ClientError, asyncio.exceptions.TimeoutError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
raise CNFException(_("Something went wrong ..."))
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
info = self._content.find("div", class_="row-command-info")
|
||||||
|
distro = self._content.find_all("div", class_="command-install")
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.description = info.find("p", class_="my-0").text.strip()
|
||||||
|
except AttributeError:
|
||||||
|
self.description = "N/A"
|
||||||
|
|
||||||
|
try:
|
||||||
|
for m in info.find("ul", class_="list-group").find_all("li"):
|
||||||
|
row = m.text.strip().split("\n")
|
||||||
|
|
||||||
|
self.meta[row[0].lower()[:-1]] = row[1]
|
||||||
|
except AttributeError:
|
||||||
|
self.meta = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
del distro[0] # unused row
|
||||||
|
|
||||||
|
for d in distro:
|
||||||
|
self.distro[
|
||||||
|
d.find("dt").text.strip().split("\n")[-1].strip()
|
||||||
|
] = d.find("code").text
|
||||||
|
except (AttributeError, IndexError):
|
||||||
|
self.distro = {}
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
"command": self.command,
|
||||||
|
"description": self.description,
|
||||||
|
"meta": self.meta,
|
||||||
|
"distro": self.distro,
|
||||||
|
}
|
9
tuxbot/cogs/Linux/functions/exceptions.py
Normal file
9
tuxbot/cogs/Linux/functions/exceptions.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
|
||||||
|
class LinuxException(commands.BadArgument):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CNFException(LinuxException):
|
||||||
|
pass
|
17
tuxbot/cogs/Linux/functions/utils.py
Normal file
17
tuxbot/cogs/Linux/functions/utils.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from aiocache import cached, Cache
|
||||||
|
from aiocache.serializers import PickleSerializer
|
||||||
|
|
||||||
|
from tuxbot.cogs.Linux.functions.cnf import CNF
|
||||||
|
|
||||||
|
|
||||||
|
@cached(
|
||||||
|
ttl=24 * 3600,
|
||||||
|
serializer=PickleSerializer(),
|
||||||
|
cache=Cache.MEMORY,
|
||||||
|
namespace="linux",
|
||||||
|
)
|
||||||
|
async def get_from_cnf(command: str) -> dict:
|
||||||
|
cnf = CNF(command)
|
||||||
|
await cnf.fetch()
|
||||||
|
|
||||||
|
return cnf.to_dict()
|
56
tuxbot/cogs/Linux/linux.py
Normal file
56
tuxbot/cogs/Linux/linux.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from tuxbot.cogs.Linux.functions.utils import get_from_cnf
|
||||||
|
from tuxbot.core.utils.functions.extra import command_extra, ContextPlus
|
||||||
|
from tuxbot.core.bot import Tux
|
||||||
|
from tuxbot.core.i18n import (
|
||||||
|
Translator,
|
||||||
|
)
|
||||||
|
|
||||||
|
log = logging.getLogger("tuxbot.cogs.Linux")
|
||||||
|
_ = Translator("Linux", __file__)
|
||||||
|
|
||||||
|
|
||||||
|
class Linux(commands.Cog):
|
||||||
|
def __init__(self, bot: Tux):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
async def cog_before_invoke(self, ctx: ContextPlus):
|
||||||
|
await ctx.trigger_typing()
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
@command_extra(name="cnf")
|
||||||
|
async def _cnf(self, ctx: ContextPlus, command: str):
|
||||||
|
cnf = await get_from_cnf(command)
|
||||||
|
|
||||||
|
if cnf["distro"]:
|
||||||
|
e = discord.Embed(title=f"{cnf['description']} ({cnf['command']})")
|
||||||
|
|
||||||
|
description = (
|
||||||
|
"__Maintainer:__ {maintainer}\n"
|
||||||
|
"__Homepage:__ [{homepage}]({homepage})\n"
|
||||||
|
"__Section:__ {section}".format(
|
||||||
|
maintainer=cnf["meta"].get("maintainer", "N/A"),
|
||||||
|
homepage=cnf["meta"].get("homepage", "N/A"),
|
||||||
|
section=cnf["meta"].get("section", "N/A"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
e.description = description
|
||||||
|
|
||||||
|
e.set_footer(
|
||||||
|
text="Powered by https://command-not-found.com/ "
|
||||||
|
"and with his authorization"
|
||||||
|
)
|
||||||
|
|
||||||
|
for k, v in cnf["distro"].items():
|
||||||
|
e.add_field(name=f"**__{k}__**", value=f"```{v}```")
|
||||||
|
|
||||||
|
return await ctx.send(embed=e)
|
||||||
|
|
||||||
|
await ctx.send(_("No result found", ctx, self.bot.config))
|
18
tuxbot/cogs/Linux/locales/en-US.po
Normal file
18
tuxbot/cogs/Linux/locales/en-US.po
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# English translations for Tuxbot-bot package.
|
||||||
|
# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the Tuxbot-bot package.
|
||||||
|
# Automatically generated, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
|
"POT-Creation-Date: 2021-01-25 14:36+0100\n"
|
||||||
|
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
||||||
|
"Last-Translator: Automatically generated\n"
|
||||||
|
"Language-Team: none\n"
|
||||||
|
"Language: en_US\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
19
tuxbot/cogs/Linux/locales/fr-FR.po
Normal file
19
tuxbot/cogs/Linux/locales/fr-FR.po
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# French translations for Tuxbot-bot package
|
||||||
|
# Traductions françaises du paquet Tuxbot-bot.
|
||||||
|
# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the Tuxbot-bot package.
|
||||||
|
# Automatically generated, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
|
"POT-Creation-Date: 2021-01-25 14:36+0100\n"
|
||||||
|
"PO-Revision-Date: 2020-06-10 00:38+0200\n"
|
||||||
|
"Last-Translator: Automatically generated\n"
|
||||||
|
"Language-Team: none\n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
19
tuxbot/cogs/Linux/locales/messages.pot
Normal file
19
tuxbot/cogs/Linux/locales/messages.pot
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the Tuxbot-bot package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Tuxbot-bot\n"
|
||||||
|
"Report-Msgid-Bugs-To: rick@gnous.eu\n"
|
||||||
|
"POT-Creation-Date: 2021-03-01 14:59+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
0
tuxbot/cogs/Linux/models/__init__.py
Normal file
0
tuxbot/cogs/Linux/models/__init__.py
Normal file
|
@ -42,6 +42,7 @@ packages: Tuple = (
|
||||||
"tuxbot.cogs.Polls",
|
"tuxbot.cogs.Polls",
|
||||||
"tuxbot.cogs.Custom",
|
"tuxbot.cogs.Custom",
|
||||||
"tuxbot.cogs.Network",
|
"tuxbot.cogs.Network",
|
||||||
|
"tuxbot.cogs.Linux",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue