anki-generator/anki_generator/models.py

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)
]