From 2fa8877e5d12a4005f93a7abaea931e66deb8e9d Mon Sep 17 00:00:00 2001 From: "Christopher T. Johnson" Date: Sat, 16 Mar 2024 00:49:07 -0400 Subject: [PATCH] MW integration --- lib/words.py | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 lib/words.py diff --git a/lib/words.py b/lib/words.py new file mode 100644 index 0000000..623290e --- /dev/null +++ b/lib/words.py @@ -0,0 +1,144 @@ +import json +import requests + +from PyQt6.QtSql import QSqlQuery +from typing import Type, Self, Dict, Any, Optional + +from lib import query_error + +API = "https://api.dictionaryapi.dev/api/v2/entries/en/{word}" +MWAPI = "https://www.dictionaryapi.com/api/v3/references/collegiate/json/{word}?key=51d9df34-ee13-489e-8656-478c215e846c" + +class Word: + _instance = None + _words: Dict[str,str] = {} + _current: Optional[Dict[str,Any]] = None + + def __new__(cls: Type[Self], word:str ) -> Self: + if cls._instance: + return cls._instance + cls._instance = super(Word, cls).__new__(cls) + return cls._instance + + def __init__(self, word: str) -> None: + print(f"Word == {word}") + # + # Have we already retrieved this word? + # + try: + self._current = json.loads(self._words[word]) + return + except KeyError: + pass + query = QSqlQuery() + query.prepare("SELECT * FROM words " + "WHERE word = :word") + query.bindValue(":word", word) + if not query.exec(): + query_error(query) + if query.next(): + self._words[word] = query.value("definition") + self._current = json.loads(self._words[word]) + return + response = requests.get(MWAPI.format(word=word)) + if response.status_code != 200: + self._current = None + return + data = json.loads(response.content.decode("utf-8")) + # + # XXX - The first entry should be the correct entry. There could be more + # if there is a "hom" entry, then that will be appended to meta.id + # word = "lady", hom=1, meta.id = "lady:1"; + # + print(response.content.decode('utf-8')) + self._words[word] = json.dumps(data[0]) + self._current = data[0] + query.prepare("INSERT INTO words " + "(word, definition) " + "VALUES (:word, :definition)") + query.bindValue(":word", word) + query.bindValue(":definition", self._words[word]) + if not query.exec(): + query_error(query) + return + def get_html(self) -> str|None: + if not self._current: + return None + if "meta" in self._current.keys(): + return self.mw_html() + else: + return self.apidictionary_html() + + def mw_html(self) -> str: + + def sound_url(prs:Dict[str,Any]) -> str|None: + base = 'https://media.merriam-webster.com/audio/prons/en/us/ogg' + if 'sound' not in prs.keys(): + return None + audio = prs['sound']['audio'] + if audio.startswith('bix'): + url = base + '/bix/' + elif audio.startswith('gg'): + url = base + '/gg/' + elif audio[0] not in "abcdefghijklmnopqrstuvwxyz": + url = base + '/number/' + else: + url = base + '/' + audio[0] + '/' + url += audio + '.ogg' + return url + + def parse_sn(sn:str, old:str) -> str: + return sn + + assert self._current is not None + word = self._current['hwi']['hw'] + label = self._current['fl'] + html = f"

{word} {label}

\n" + if "vrs" in self._current.keys(): + html += "
    \n" + html += "
  1. " + html += "
  2. \n
  3. ".join([vrs['va'] for vrs in self._current['vrs']]) + html += "
  4. \n
\n" + if 'prs' in self._current['hwi'].keys(): + tmp = [] + for prs in self._current['hwi']['prs']: + url = sound_url(prs) + how = prs['mw'] + if url: + tmp.append(f'\\{how}\\') + else: + tmp.append(f'\\{how}\\') + html += '' + html += ''.join(tmp) + html += "\n" + if 'ins' in self._current.keys(): + html += "

" + html += ', '.join([ins['if'] for ins in self._current['ins']]) + html += "

\n" + html += "\n" + return html + + def apidictionary_html(self) ->str: + html = "" + return html