Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/markdown2anki/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import markdown2anki.logger as log
import markdown2anki.output_handler as out
import markdown2anki.version_check as ver
import markdown2anki.ankiconnect as ankiconnect
import markdown2anki.config.configs_handle as config_handle
from markdown2anki.markdown_handler import MarkdownHandler

Expand Down Expand Up @@ -76,6 +77,8 @@ def main():
out.copy_images_to_folder(images_to_copy, config["images out-folder"])

if success_cards:
ankiconnect.send_to_anki(cards_with_info)

logger.info(f"🔥 Successfully created a total of {success_cards} card/s!")
out.write_cards_to_csv(
cards_to_write,
Expand Down
94 changes: 94 additions & 0 deletions src/markdown2anki/ankiconnect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import logging

import requests

logger = logging.getLogger(__name__)


def ankiconnect_send_request(action: str, params: dict) -> (bool, str):
"""
Send HTTP request to the AnkiConnect plugin.

Return tuple, where:
success: If True, the request was successfully processed by the AnkiConnect
plugin.
error: Contains error message returned by the AnkiConnect plugin. Valid only if
success is False.

For AnkiConnect API refer to the:
https://github.com/FooSoft/anki-connect#supported-actions
"""
request = {
"action": action,
"params": params,
# We want to use the latest AnkiConnect API version.
"version": 6,
}
response = requests.post("http://localhost:8765", json=request).json()

return (False if response["result"] is None else True, response["error"])


def create_note(deck_name: str, model_name: str, fields: str) -> dict:
"""
Create note field, required by the addNote API call.
"""
return {
"note": {
"deckName": deck_name,
"modelName": model_name,
"fields": fields,
"options": {
"allowDuplicate": False,
"duplicateScope": "all",
"duplicateScopeOptions": {
"deckName": deck_name,
"checkChildren": True,
"checkAllModels": True,
},
},
},
}


def send_to_anki(cards: dict):
""" """
logger.info("📡 Sending cards to Anki...")

# TODO: Creation of notes below is quite ugly for now but it works.
# We need a way to get deck_name and notetype, they should be provided by the caller.
# When that is done, the hardcoded values can be removed
def basic_note(note_fields):
return create_note("Work notes", "Markdown2Anki - Basic", note_fields)

def cloze_note(note_fields):
return create_note("Work notes", "Markdown2Anki - Cloze", note_fields)

notes = []
notes += list(map(basic_note, cards["cards"]))
notes += list(map(cloze_note, cards["cards_with_clozes"]))

# TODO: There are many reasons why the ankiconnect_send_request would fail.
# We need some general direction on:
# - Are there some validation steps that should be done before starting to send
# things? (like to check if the deck and note type even exist?)
# - How should errors be handled? Should be we abort on an error, or keep going?

for index, note in enumerate(notes):
sent, error = ankiconnect_send_request("addNote", note)
if sent:
logger.info(f"|--- ✅ Sent card number {index + 1}")
else:
logger.info(f"|--- ❌ Failed to send the card number {index + 1}...")
logger.error(f"|------- ERROR: {error}")

logger.info("📺 Sending images to Anki...")
for index, image in enumerate(cards["images_to_copy"].items()):
sent, error = ankiconnect_send_request(
"storeMediaFile", {"filename": image[0], "path": image[1]}
)
if sent:
logger.info(f"|--- ✅ Sent image item number {index + 1}")
else:
logger.info(f"|--- ❌ Failed to send the media number {index + 1}...")
logger.error(f"|------- ERROR: {error}")