# █ █ ▀ █▄▀ ▄▀█ █▀█ ▀
# █▀█ █ █ █ █▀█ █▀▄ █
# © Copyright 2022
# https://t.me/hikariatama
#
# 🔒 Licensed under the GNU AGPLv3
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
# meta pic: https://static.dan.tatar/oxford_icon.png
# meta banner: https://mods.hikariatama.ru/badges/oxford.jpg
# meta developer: @hikarimods
# requires: bs4
# scope: inline
# scope: hikka_only
# scope: hikka_min 1.3.0
import random
from urllib.parse import quote_plus
import grapheme
import requests
from bs4 import BeautifulSoup
from telethon.tl.types import Message
from .. import loader, utils
from ..inline.types import InlineCall
DEFAULT_HEADERS = {
"Connection": "keep-alive",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Upgrade-Insecure-Requests": "1",
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like"
" Gecko) Chrome/92.0.4515.131 Safari/537.36"
),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Referer": "https://www.oxfordlearnersdictionaries.com",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.9,ru;q=0.8",
}
async def search(term: str) -> str:
res = await utils.run_sync(
requests.get,
f"https://www.oxfordlearnersdictionaries.com/search/english/direct/?q={quote_plus(term)}",
headers=DEFAULT_HEADERS,
)
soup = BeautifulSoup(res.text, "html.parser")
if "spellcheck" in res.url:
try:
possible = [
a.get("href").split("?q=")[1]
for a in soup.find("ul", {"class": "result-list"}).find_all("a")
]
except Exception:
return {"ok": False, "possible": ["emptiness"]}
return {"ok": False, "possible": possible}
try:
soup.find("div", {"class": "idioms"}).clear()
except AttributeError:
pass
return {
"ok": True,
"definitions": [
definition.get_text()
for definition in soup.find_all("span", {"class": "def"})
],
"part_of_speech": soup.find("span", {"class": "pos"}).get_text(),
"pronunciation": soup.find("span", {"class": "phon"}).get_text(),
"term": term,
}
@loader.tds
class OxfordMod(loader.Module):
"""Quickly access word definitions in Oxford Learners dictionary"""
parts_of_speech = {
"noun": "существительное",
"pronoun": "местоимение",
"verb": "глагол",
"adjective": "прилагательное",
"adverb": "наречие",
"preposition": "предлог",
"conjunction": "союз",
"interjection": "междометие",
"determiner": "определитель",
"auxiliary verb": "вспомогательный глагол",
"modal verb": "модальный глагол",
"phrasal verb": "фразеологизм",
"idiom": "идиома",
"phrase": "фраза",
"abbreviation": "аббревиатура",
"article": "артикль",
"collocation": "коллокация",
"exclamation": "восклицание",
"expression": "выражение",
}
strings = {
"name": "Oxford",
"no_exact": (
"😔 There is no definition for {}\nMaybe, you"
" meant:"
),
"match": '{} {} [{}] ({})\n\n{}',
**{key: key for key in parts_of_speech},
}
strings_ru = {
"_cls_doc": (
"Быстрый доступ к определениям слов в образовательном Оксфордском словаре"
),
"no_exact": (
"😔 Нет определения для {}\nВозможно, вы имели в"
" виду:"
),
**parts_of_speech,
}
async def _search(self, call: InlineCall, term: str):
result = await search(term)
await call.edit(self.format_match(result))
def format_match(self, match: dict) -> str:
return self.strings("match").format(
random.choice(
[
"{}",
"{}",
"{}",
"{}",
"{}",
"{}",
"{}",
"{}",
]
).format(
random.choice(
list(
grapheme.graphemes(
"👩🎓🧑🎓👨🎓👨🏫🧑🏫👩🏫🤵♀️🤵🤵♂️💁♀️💁♂️🙋♂️🙋♀️🙍♀️🙎♂️"
)
)
)
),
f"https://www.oxfordlearnersdictionaries.com/search/english/direct/?q={match['term']}",
utils.escape_html(match["term"]),
utils.escape_html(match["pronunciation"]),
utils.escape_html(self.strings(match["part_of_speech"])),
"\n\n".join(
[
"▫️"
f" {utils.escape_html(definition)}"
for definition in match["definitions"]
]
),
)
@loader.command(
ru_doc="<слово> - Поиск слова в образовательном Оксфордском словаре"
)
async def oxford(self, message: Message):
""" - Search word in Oxford Learner's Dictionary"""
args = utils.get_args_raw(message)
if not args:
args = "emptiness"
result = await search(args)
if not result["ok"]:
await self.inline.form(
self.strings("no_exact").format(utils.escape_html(args)),
message,
reply_markup=utils.chunks(
[
{"text": term, "callback": self._search, "args": (term,)}
for term in result["possible"]
],
2,
),
)
return
await utils.answer(message, self.format_match(result))