-
-
Save galopyz/c3a40839fbafe99350673b10a313a67b to your computer and use it in GitHub Desktop.
My Dialog
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import os, json, urllib, pymupdf | |
| from typing import * | |
| from fastcore.utils import * | |
| from fasthtml.common import * | |
| from monsterui.all import * | |
| from httpx import get as xget | |
| from PIL import Image | |
| import matplotlib.pyplot as plt | |
| ANKI_API_KEY = os.environ.get('ANKI_API_KEY') | |
| HOME_URL = os.environ.get('HOME_URL') | |
| def extract_text_by_pages(pdf_path: str) -> List[str]: | |
| "Extract text from PDF pages using pymupdf" | |
| doc = pymupdf.open(pdf_path) | |
| pages = [page.get_text() for page in doc] | |
| doc.close() | |
| return pages | |
| def view_page(pages: List[str], page_num: int, chars: Optional[int] = None) -> str: | |
| "View content of a specific page with optional character limit" | |
| if page_num < 1 or page_num > len(pages): return f"Error: Page number must be between 1 and {len(pages)}" | |
| return pages[page_num-1][:chars] if chars else pages[page_num-1] | |
| def request(action: str, params: Dict = None) -> dict: | |
| "Create AnkiConnect API request with action and parameters" | |
| if params is None: params = {} | |
| return dict(action=action, params=params, version=6, key=ANKI_API_KEY) | |
| def invoke(action: str, params: Dict = None) -> Any: | |
| "Send AnkiConnect API request and return result" | |
| if params is None: params = {} | |
| requestJson = json.dumps(request(action, params)).encode('utf-8') | |
| response = json.load(urllib.request.urlopen(urllib.request.Request(HOME_URL, requestJson))) | |
| if len(response) != 2: raise Exception('response has an unexpected number of fields') | |
| if 'error' not in response: raise Exception('response is missing required error field') | |
| if 'result' not in response: raise Exception('response is missing required result field') | |
| if response['error'] is not None: raise Exception(response['error']) | |
| return response['result'] | |
| class AnkiCard: | |
| "Anki flashcard with front/back content and deck management" | |
| def __init__(self, front: str, back: str, deck: str = "test1", tags: Optional[List[str]] = None, card_id: Optional[int] = None): | |
| self.front,self.back,self.deck,self.tags,self.card_id = front,back,deck,tags or [],card_id | |
| def add_to_anki(self) -> int: | |
| "Add this card to Anki and update with assigned ID" | |
| note = dict(deckName=self.deck, modelName="Basic", fields=dict(Front=self.front, Back=self.back), tags=self.tags) | |
| self.card_id = invoke('addNote', note=note) | |
| return self.card_id | |
| def update(self) -> None: | |
| "Update an existing card in Anki" | |
| if not self.card_id: raise ValueError("Card hasn't been added to Anki yet") | |
| note = dict(id=self.card_id, fields=dict(Front=self.front, Back=self.back), tags=self.tags) | |
| invoke('updateNote', note=note) | |
| def delete(self) -> None: | |
| "Delete this card from Anki" | |
| if not self.card_id: raise ValueError("Card hasn't been added to Anki yet") | |
| invoke('deleteNotes', notes=[self.card_id]) | |
| self.card_id = None | |
| def get_deck_cards(deck_name: str) -> List[Dict]: | |
| "Get all cards from a deck with their front/back content" | |
| card_ids = invoke('findCards', dict(query=f'deck:"{deck_name}"')) | |
| return invoke('cardsInfo', dict(cards=card_ids)) | |
| @classmethod | |
| def from_anki_data(cls, card_data: Dict) -> 'Card': | |
| "Create Card object from Anki card data" | |
| front = card_data['fields']['Front']['value'] | |
| back = card_data['fields']['Back']['value'] | |
| deck = card_data['deckName'] | |
| card_id = card_data['cardId'] | |
| return cls(front, back, deck, card_id=card_id) | |
| AnkiCard.from_anki_data = from_anki_data | |
| @patch | |
| def __repr__(self:AnkiCard) -> str: | |
| "String representation showing card status and preview" | |
| status = "saved" if self.card_id else "unsaved" | |
| return f"AnkiCard(front='{self.front[:120]}...',\n back='{self.back[:120]}...',\n deck='{self.deck},\n status={status}')" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment