Mochitto / Markdown2Anki

A CLI tool and an apkg template to allow you to create flashcards from markdown and have a better experience while using anki for your studies. 🌸
104 stars 3 forks source link

Use Anki's API to send cards to Anki #3

Open Mochitto opened 1 year ago

Mochitto commented 1 year ago

Using CSV/manual import is a bit annoying; it would be nice if you could use the Anki API (it would require you to add the path to the collection file to the config) to send the cards automatically to anki. Maybe it can also send images automatically (would remove the need of manually adding the media folder).

MarkoSagadin commented 1 year ago

I have looked a bit into the AnkiConnect and tried to make something. I documented the findings below.

Here are the things that learned:

The setup

Naturally, the user needs to install AnkiConnect plugin and have Anki running. AnkiConnect exposes a ton of functionality via HTTP API.

Structure of API

HTTP requests needs to contain a JSON-encoded object, with specific fields:

{
    "action": "forgetCards",
    "version": 6,
    "params": {
        "cards": [1498938915662, 1502098034048]
    }
}

Where:

HTTP responses look like this:

{
    "result": ["Default", "Filtered Deck 1"], 
    "error": null
}

Where:

What I tried to do

I played a bit with the provided Python snippet and tried a few of the API methods.

addNote

As the name says, this is the action for adding notes.

I could create a test note with the following JSON, I think that the most fields are self-explanatory. There are also possible audio and video fields with the same content as the picture key.

{
    "action": "addNote",
    "version": 6,
    "params": {
        "note": {
            "deckName": "Work Notes",
            "modelName": "Basic",
            "fields": {
                "Front": "front content",
                "Back": "back content"
            },
            "options": {
                "allowDuplicate": false,
                "duplicateScope": "deck",
                "duplicateScopeOptions": {
                    "deckName": "Work Notes",
                    "checkChildren": true,
                    "checkAllModels": true
                }
            },
            "picture": [{
                "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/A_black_cat_named_Tilly.jpg/220px-A_black_cat_named_Tilly.jpg", 
                "filename": "black_cat.jpg", 
                "skipHash": "8d6e4646dfae812bf39651b59d7429ce", 
                "fields": [ 
                    "Back" 
                ]
            }],
            "tags": [
                "testinput"
            ]
        }
    }
}

Some remarks:

updateNote

Same fields as above, with addition of id field. That's the way to tell Anki which note you want to update.

{
    "action": "updateNote",
    "version": 6,
    "params": {
        "note": {
            "id": 1514547547030,
            "fields": {
                "Front": "new front content",
                "Back": "new back content"
            },
            "tags": ["new", "tags"]
        }
    }
}

Some remarks:

Topics to discuss and do.

  1. I want try to pass the examples that are in the project's readme (the example notes with code and the cat) via above API and see what happens. I want to see how this works with a more realistic note and if there are any drawback.
  2. If we want to support the "update note" usecase (user does not wish to delete the notes once they are imported, as he wants a way to update them via Markdown and run the md2anki again and again), then we need some way of storing and tracking the id number in the markdown. The logic could then such that you would write the id number in the markdown file, next to the note that created it, and whenever a note with id number would be encountered, then it would try to find that note via API and update it. That is not hard to implement.
  3. There is addNote and addNotes API methods. Latter one takes an array of addNote compatible objects and creates multiple notes them. The docs do not indicate that there is any other special behavior going on. If I have 100 notes, what difference does it matter if I create 100 addNote requests or 1 addNotes requests with all 100 notes in the body? Is there anything HTTP related that could affect this?
MarkoSagadin commented 1 month ago

Hello after quite some time!

I would like to get back to working on this, since I have some free time in the coming months :)

I looked again code that I wrote in the #16 and would like some input where to take this.