68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
import os
|
|
from typing import List, Optional
|
|
from pydantic import BaseModel, Field, HttpUrl
|
|
from pydantic_settings import BaseSettings
|
|
|
|
class Settings(BaseSettings):
|
|
"""Application settings with environment variable support."""
|
|
anthropic_api_key: str = Field(..., validation_alias="ANTHROPIC_API_KEY")
|
|
unsplash_api_key: str = Field(..., validation_alias="UNSPLASH_API_KEY")
|
|
|
|
class Config:
|
|
env_file = ".env"
|
|
env_file_encoding = "utf-8"
|
|
|
|
class UnsplashImage(BaseModel):
|
|
"""Unsplash image data."""
|
|
url: HttpUrl
|
|
photographer: str
|
|
local_path: Optional[str] = None
|
|
|
|
class GermanWord(BaseModel):
|
|
"""German word data structure."""
|
|
german_word: str
|
|
part_of_speech: str = Field(..., description="Noun, Verb, Adjective, etc.")
|
|
english_meaning: str
|
|
article: Optional[str] = Field(None, description="der/die/das for nouns")
|
|
plural_form: str
|
|
example_sentence: str
|
|
sentence_translation: str
|
|
usage_notes: str
|
|
related_words: str
|
|
image_search_term: str
|
|
tags: List[str] = Field(default_factory=list)
|
|
|
|
def is_noun(self) -> bool:
|
|
"""Check if the word is a noun."""
|
|
return self.part_of_speech.lower() == "noun"
|
|
|
|
def get_full_word(self) -> str:
|
|
"""Get the full word with article if it's a noun."""
|
|
if self.is_noun() and self.article:
|
|
return f"{self.article} {self.german_word}"
|
|
return self.german_word
|
|
|
|
class AnkiCard(BaseModel):
|
|
"""Anki card data structure."""
|
|
word: GermanWord
|
|
image: Optional[UnsplashImage] = None
|
|
source: str = Field(..., description="Source of the word (Babbel, Duolingo, etc.)")
|
|
|
|
def to_fields(self) -> List[str]:
|
|
"""Convert to Anki note fields."""
|
|
return [
|
|
self.word.german_word,
|
|
self.word.part_of_speech,
|
|
self.source,
|
|
self.word.english_meaning,
|
|
self.word.article or "",
|
|
self.word.plural_form,
|
|
self.word.example_sentence,
|
|
self.word.sentence_translation,
|
|
self.word.usage_notes,
|
|
self.word.related_words,
|
|
self.image.local_path if self.image else "",
|
|
self.image.photographer if self.image else "",
|
|
" ".join(self.word.tags)
|
|
]
|