from result import Result, Ok, Err import requests import logging from typing import List, Dict logger = logging.getLogger("flashcard-creator") class AnkiError(Exception): """Base class for Anki-related errors""" pass class ConnectionError(AnkiError): """Error connecting to AnkiConnect""" pass class DeckError(AnkiError): """Error related to deck operations""" pass class CardError(AnkiError): """Error related to card operations""" pass class AnkiConnect: def __init__(self, url="http://127.0.0.1:8765"): self.url = url def get_decks(self) -> Result[List[str], AnkiError]: """Get the list of decks from Anki using AnkiConnect.""" try: response = requests.post( self.url, json={"action": "deckNames", "version": 6} ) data = response.json() return Ok(data.get("result", [])) except requests.exceptions.RequestException as e: logger.error(f"Connection error getting Anki decks: {e}") return Err(ConnectionError(f"Failed to connect to Anki: {e}")) except Exception as e: logger.error(f"Error getting Anki decks: {e}") return Err(DeckError(f"Failed to get decks: {e}")) def create_cards(self, deck: str, cards: List[Dict[str, str]]) -> Result[bool, AnkiError]: """Create flashcards in Anki using AnkiConnect.""" try: # Prepare notes for addition notes = [] logger.info(f"Preparing to create {len(cards)} Anki cards in deck: {deck}") for card in cards: notes.append( { "deckName": deck, "modelName": "Basic", # Using the basic model "fields": {"Front": card["front"], "Back": card["back"]}, "options": {"allowDuplicate": False}, "tags": [f"{self.source_language}-{self.target_language}"], } ) # Add notes to Anki logger.info("Sending request to AnkiConnect to add notes") response = requests.post( self.url, json={"action": "addNotes", "version": 6, "params": {"notes": notes}}, ) data = response.json() success = all(id is not None for id in data.get("result", [])) if success: logger.info("Successfully added all cards to Anki") return Ok(True) else: logger.warning("Some cards failed to be added to Anki") return Err(CardError("Some cards failed to be added")) except requests.exceptions.RequestException as e: logger.error(f"Connection error creating Anki cards: {e}") return Err(ConnectionError(f"Failed to connect to Anki: {e}")) except Exception as e: logger.error(f"Error creating Anki cards: {e}") return Err(CardError(f"Failed to create cards: {e}"))