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"