feat(commands:cnf|Linux): add new Command Not Found scrapper (Known issue: cache resolve on none results)

This commit is contained in:
Romain J 2021-04-25 23:33:30 +02:00
parent fcc23d87df
commit 88f60690dd
12 changed files with 247 additions and 0 deletions

View 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))

View 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] = {}

View file

View 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,
}

View file

@ -0,0 +1,9 @@
from discord.ext import commands
class LinuxException(commands.BadArgument):
pass
class CNFException(LinuxException):
pass

View 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()

View 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))

View 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"

View 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"

View 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"

View file

View 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",
) )