Checkpoint. Not working

This commit is contained in:
Christopher T. Johnson
2024-04-05 10:56:22 -04:00
parent e69e958562
commit ea882a6de3
4 changed files with 346 additions and 796 deletions

0
plugins/__init__.py Normal file
View File

253
plugins/merriam-webster.py Normal file
View File

@@ -0,0 +1,253 @@
from trycast import trycast
import json
import re
from typing import Any, NamedTuple, TypedDict, cast
from PyQt6.QtCore import QEventLoop, QUrl, Qt
from PyQt6.QtGui import QColor, QFont
from PyQt6.QtNetwork import QNetworkRequest
from lib.words import Word
from lib.definition import Line, Fragment
registration = {
'source': 'mw',
'name': 'Merriam-Webster',
}
API = "https://www.dictionaryapi.com/api/v3/references/collegiate/json/{word}?key={key}"
key = "51d9df34-ee13-489e-8656-478c215e846c"
class TextTuple(NamedTuple):
type_: str # 'text'
text: str
class TTuple(NamedTuple):
type_: str # 't'
text: str
class VerbalIllustration(TypedDict):
t: str
aq: str
class VerbalIllustrationTuple(NamedTuple):
type_: str # 'vis'
data: list[VerbalIllustration]
class Sound(TypedDict):
audio: str
ref: str
stat: str
class Pronunciation(TypedDict):
mw: str
l: str
l2: str
pun: str
sound: Sound
class Meta(TypedDict):
id: str
uuid: str
sort: str
src: str
section: str
stems: list[str]
offensive: bool
class HeadWordInfo(TypedDict):
hw: str
prs: list[Pronunciation]
class HeadWord(TypedDict):
hw: str
prs: list[Pronunciation]
psl: str
class Variant(TypedDict):
va: str
vl: str
prs: list[Pronunciation]
spl: str
class Inflection(TypedDict):
if_: str
ifc: str
il: str
prs: list[Pronunciation]
spl: str
class DividedSense(TypedDict):
sd: str
et: list[str] # Not full
ins: list[Inflection]
lbs: list[str]
prs: list[Pronunciation]
sgram: str
sls: list[str]
vrs: list[Variant]
class BioGraphicalNameWrap(TypedDict):
pname: str
sname: str
altname: str
prs: list[Pronunciation]
class CalledAlsoTarget(TypedDict):
cat: str
catref: str
pn: str
prs: list[Pronunciation]
psl: str
class CalledAlso(TypedDict):
intro: str
cats: list[CalledAlsoTarget]
class RunInWrap(TypedDict):
rie: str
prs: list[Pronunciation]
text: str
vrs: list[Variant]
class Sense:
dt: list[str] # not full
et: list[str] # not full
ins: list[Inflection]
lbs: list[str]
prs: list[Pronunciation]
sdsense: DividedSense
sgram: str
sls: list[str]
sn: str
vrs: list[Variant]
class SenseSequence(TypedDict):
sense: Sense
sen: Sense
class Definition(TypedDict):
sseq: list[SenseSequence]
vd: str
class Entry(TypedDict):
meta: Meta
hom: str
hwi: HeadWordInfo
ahws: list[HeadWord]
vrs: list[Variant]
fl: str
def_: list[Definition]
def fetch(word:str) -> dict[str, Any]:
request = QNetworkRequest()
url = QUrl(API.format(word=word, key=key))
request.setUrl(url)
request.setTransferTimeout(3000)
reply = Word._nam.get(request)
assert reply is not None
loop = QEventLoop()
reply.finished.connect(loop.quit)
loop.exec()
content = reply.readAll()
data = json.loads(content.data().decode('utf-8'))
return {
'word': word,
'source': 'mw',
'definition': data,
}
def soundUrl(sound:Sound, fmt='ogg') -> QUrl:
"""Create a URL from a PRS structure."""
base = f"https://media.merriam-webster.com/audio/prons/en/us/{fmt}"
audio = sound['audio']
m = re.match(r"(bix|gg|[a-zA-Z])", audio)
if m:
url = base + f"/{m.group(1)}/"
else:
url = base + "/number/"
url += audio + f".{fmt}"
return QUrl(url)
def getFirstSound(definition: list[Entry]) -> QUrl:
# ahws, cats, dros, hwi, ins, ri, sdsense, sen, sense, uros, vrs
for entry in definition:
for v in entry.values():
hwi = trycast(HeadWordInfo, v)
if hwi is None:
continue
if 'prs' in hwi:
for pr in hwi['prs']:
if 'sound' in pr:
url = soundUrl(pr['sound'])
if url.isValid():
return url
return QUrl()
def do_prs(prs: list[Pronunciation]) -> list[Fragment]:
frags: list[Fragment] = []
font = trycast(QFont, Word._resources['fonts']['label'])
assert font is not None
linkColor = trycast(QColor, Word._resources['colors']['link'])
assert linkColor is not None
subduedColor = trycast(QColor, Word._resources['colors']['subdued'])
assert subduedColor is not None
for pr in prs:
if 'pun' in pr:
pun = pr['pun']
else:
pun = ' '
if 'l' in pr:
frags.append(
Fragment(pr['l'] + pun, font, color=subduedColor)
)
frag = Fragment(pr['mw'], font, color=subduedColor)
if 'sound' in pr:
frag.setAudio(soundUrl(pr['sound']))
frags.append(frag)
if 'l2' in pr:
frags.append(
Fragment(pun + pr['l2'], font, color=subduedColor)
)
return frags
def getDef(definition: list[Entry]) -> list[Line]:
lines = []
headerFont = trycast(QFont, Word._resources['fonts']['header'])
assert headerFont is not None
textFont = trycast(QFont, Word._resources['fonts']['text'])
assert textFont is not None
labelFont = trycast(QFont, Word._resources['fonts']['label'])
assert labelFont is not None
baseColor = trycast(QColor, Word._resources['colors']['base'])
assert baseColor is not None
linkColor = trycast(QColor, Word._resources['colors']['link'])
assert linkColor is not None
subduedColor = trycast(QColor, Word._resources['colors']['subdued'])
assert subduedColor is not None
entries = len(definition)
for count, entry in enumerate(definition):
#
# Create the First line from the hwi and fl
#
line = Line()
hwi = trycast(HeadWordInfo, entry['hwi'])
assert hwi is not None
hw = re.sub(r'\*', '', hwi['hw'])
line.addFragment(Fragment(hw + ' ', headerFont, color=baseColor))
frag = Fragment(f"{count} of {entries} ", textFont, color=linkColor)
frag.setBackground(QColor(Qt.GlobalColor.gray))
line.addFragment(frag)
line.addFragment(Fragment(entry['fl'], labelFont, color=baseColor))
lines.append(line)
#
# Next is the pronunciation.
#
line = Line()
hw = re.sub(r'\*', '\u00b7', hwi['hw'])
line.addFragment(Fragment(hw + ' ', textFont, color=subduedColor))
for frag in do_prs(hwi['prs']):
line.addFragment(frag)
return [Line()]