From 63c2eb4887b42a18da6a2e68844c8e92d4a83bbf Mon Sep 17 00:00:00 2001 From: ReneBrals Date: Sat, 6 Jan 2018 20:48:25 +0100 Subject: [PATCH 1/7] Added API endpoint to retrieve card/note information. --- AnkiConnect.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/AnkiConnect.py b/AnkiConnect.py index 56465d4..8c752fe 100644 --- a/AnkiConnect.py +++ b/AnkiConnect.py @@ -29,6 +29,7 @@ import socket import sys from time import time from unicodedata import normalize +from operator import itemgetter # @@ -706,6 +707,80 @@ class AnkiBridge: else: return [] + def cardsInfo(self,cards): + result = [] + for cid in cards: + try: + card = self.collection().getCard(cid) + model = card.model() + note = card.note() + fields = {} + for info in model['flds']: + order = info['ord'] + name = info['name'] + fields[name] = note.fields[order] + + result.append({ + 'cardId': card.id, + 'fields': fields, + 'fieldOrder': card.ord, + 'question': card._getQA()['q'], + 'answer': card._getQA()['a'], + 'modelName': model['name'], + 'deckName': self.deckNameFromId(card.did), + 'css': model['css'], + 'factor': card.factor, + #This factor is 10 times the ease percentage, + # so an ease of 310% would be reported as 3100 + 'interval': card.ivl, + 'type': card.type, + #new = 0, learning = 1, review = 2 + 'queue': card.queue, + # same as type, plus: + # suspended = -1, user buried = -2, sched buried = -3 + 'due': card.due, + # does different things depending on queue, + # new: position in queue + # learning: integer timestamp + # review: integer days (since first review) + 'note': card.nid + }) + except TypeError as e: + # Anki will give a TypeError if the card ID does not exist. + # Best behavior is probably to add an "empty card" to the + # returned result, so that the items of the input and return + # lists correspond. + result.append({}) + + return result + + def notesInfo(self,notes): + result = [] + for nid in notes: + try: + note = self.collection().getNote(nid) + model = note.model() + + fields = {} + for info in model['flds']: + order = info['ord'] + name = info['name'] + fields[name] = note.fields[order] + + result.append({ + 'noteId': note.id, + 'tags' : note.tags, + 'fields': fields, + 'modelName': model['name'], + }) + except TypeError as e: + # Anki will give a TypeError if the note ID does not exist. + # Best behavior is probably to add an "empty card" to the + # returned result, so that the items of the input and return + # lists correspond. + result.append({}) + return result + def getDecks(self, cards): decks = {} @@ -1196,6 +1271,13 @@ class AnkiConnect: def guiExitAnki(self): return self.anki.guiExitAnki() + @webApi() + def cardsInfo(self, cards): + return self.anki.cardsInfo(cards) + + @webApi() + def notesInfo(self, notes): + return self.anki.notesInfo(notes) # # Entry From cd6dd8479c381d15ef18fe6f55d81360c01fe98a Mon Sep 17 00:00:00 2001 From: ReneBrals Date: Tue, 9 Jan 2018 14:09:38 +0100 Subject: [PATCH 2/7] Make note/card endpoints more like existing endpoints, removing some Anki-internal fields from it card.type, card.queue and card.due seem difficult to use to me, maybe card due date should be introduced when it's represented in a more meaningful way (like an actual date instead of an integer day). --- AnkiConnect.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/AnkiConnect.py b/AnkiConnect.py index 8c752fe..8997f9a 100644 --- a/AnkiConnect.py +++ b/AnkiConnect.py @@ -718,7 +718,7 @@ class AnkiBridge: for info in model['flds']: order = info['ord'] name = info['name'] - fields[name] = note.fields[order] + fields[name] = {'value': note.fields[order], 'order': order} result.append({ 'cardId': card.id, @@ -733,16 +733,6 @@ class AnkiBridge: #This factor is 10 times the ease percentage, # so an ease of 310% would be reported as 3100 'interval': card.ivl, - 'type': card.type, - #new = 0, learning = 1, review = 2 - 'queue': card.queue, - # same as type, plus: - # suspended = -1, user buried = -2, sched buried = -3 - 'due': card.due, - # does different things depending on queue, - # new: position in queue - # learning: integer timestamp - # review: integer days (since first review) 'note': card.nid }) except TypeError as e: @@ -765,13 +755,14 @@ class AnkiBridge: for info in model['flds']: order = info['ord'] name = info['name'] - fields[name] = note.fields[order] + fields[name] = {'value': note.fields[order], 'order': order} result.append({ 'noteId': note.id, 'tags' : note.tags, 'fields': fields, 'modelName': model['name'], + 'cards': note.cards() }) except TypeError as e: # Anki will give a TypeError if the note ID does not exist. From 2d051c67c1196cae31e797f452022bf13534f6c1 Mon Sep 17 00:00:00 2001 From: ReneBrals Date: Tue, 9 Jan 2018 14:24:56 +0100 Subject: [PATCH 3/7] Fixed notesInfo fetching card IDs belonging to note --- AnkiConnect.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AnkiConnect.py b/AnkiConnect.py index 8997f9a..e051c16 100644 --- a/AnkiConnect.py +++ b/AnkiConnect.py @@ -762,7 +762,8 @@ class AnkiBridge: 'tags' : note.tags, 'fields': fields, 'modelName': model['name'], - 'cards': note.cards() + 'cards': self.collection().db.list( + "select id from cards where nid = ? order by ord", self.id) }) except TypeError as e: # Anki will give a TypeError if the note ID does not exist. From 150c49d273889554782b4ac17e8fff09a757b1da Mon Sep 17 00:00:00 2001 From: ReneBrals Date: Tue, 9 Jan 2018 18:40:07 +0100 Subject: [PATCH 4/7] Updated README to include notesInfo and cardsInfo --- README.md | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/README.md b/README.md index 6e1c676..3b45ecf 100644 --- a/README.md +++ b/README.md @@ -1065,6 +1065,92 @@ guarantee that your application continues to function properly in the future. } ``` +* **cardsInfo** + + Returns a list of objects containing for each card ID the card fields, front and back sides including CSS, note type, the note that the card belongs to, and deck name, as well as ease and interval. + + *Sample request*: + ```json + { + "action": "cardsInfo", + "version": 5, + "params": { + "cards": [1498938915662, 1502098034048] + } + } + ``` + + *Sample result*: + ```json + { + "result": [ + { + "answer": "back content", + "question": "front content", + "deckName": "Default", + "modelName": "Basic", + "fieldOrder": 1, + "fields": { + "Front": {"value": "front content", "order": 0}, + "Back": {"value": "back content", "order": 1} + }, + "css":"p {font-family:Arial;}", + "cardId": 1498938915662, + "interval": 16 + "note":1502298033753 + }, + { + "answer": "back content", + "question": "front content", + "deckName": "Default", + "modelName": "Basic", + "fieldOrder": 0, + "fields": { + "Front": {"value": "front content", "order": 0}, + "Back": {"value": "back content", "order": 1} + }, + "css":"p {font-family:Arial;}", + "cardId": 1502098034048, + "interval": 23 + "note":1502298033753 + } + ], + "error": null + } + ``` + +* **notesInfo** + + Returns a list of objects containing for each note ID the note fields, tags, note type and the cards belonging to the note. + + *Sample request*: + ```json + { + "action": "notesInfo", + "version": 5, + "params": { + } + } + ``` + + *Sample result*: + ```json + { + "result": [ + { + "noteId":1502298033753, + "modelName": "Basic", + "tags":['tag','another_tag'] + "fields": { + "Front": {"value": "front content", "order": 0}, + "Back": {"value": "back content", "order": 1} + }, + } + ], + "error": null + } + ``` + #### Media File Storage #### * **storeMediaFile** From 4411c4969f92cd54dc16398764146a6182d55981 Mon Sep 17 00:00:00 2001 From: ReneBrals Date: Tue, 9 Jan 2018 18:40:44 +0100 Subject: [PATCH 5/7] Fixed Typo --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3b45ecf..42f87f4 100644 --- a/README.md +++ b/README.md @@ -1129,6 +1129,7 @@ guarantee that your application continues to function properly in the future. "action": "notesInfo", "version": 5, "params": { + "notes": [1502298033753] } } ``` From 6d7b525bad2ffac70adec219ec60b3761e102924 Mon Sep 17 00:00:00 2001 From: ReneBrals Date: Tue, 9 Jan 2018 18:44:50 +0100 Subject: [PATCH 6/7] Fixed another typo --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 42f87f4..489dd82 100644 --- a/README.md +++ b/README.md @@ -1096,7 +1096,7 @@ guarantee that your application continues to function properly in the future. }, "css":"p {font-family:Arial;}", "cardId": 1498938915662, - "interval": 16 + "interval": 16, "note":1502298033753 }, { @@ -1111,7 +1111,7 @@ guarantee that your application continues to function properly in the future. }, "css":"p {font-family:Arial;}", "cardId": 1502098034048, - "interval": 23 + "interval": 23, "note":1502298033753 } ], @@ -1141,7 +1141,6 @@ guarantee that your application continues to function properly in the future. { "noteId":1502298033753, "modelName": "Basic", - "tags":['tag','another_tag'] "fields": { "Front": {"value": "front content", "order": 0}, "Back": {"value": "back content", "order": 1} From 05b4e9ab8ddb184a4e5542d00ce6df1e9f6dfc4c Mon Sep 17 00:00:00 2001 From: ReneBrals Date: Tue, 9 Jan 2018 18:46:23 +0100 Subject: [PATCH 7/7] Missed a typo --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 489dd82..1634948 100644 --- a/README.md +++ b/README.md @@ -1141,6 +1141,7 @@ guarantee that your application continues to function properly in the future. { "noteId":1502298033753, "modelName": "Basic", + "tags":["tag","another_tag"], "fields": { "Front": {"value": "front content", "order": 0}, "Back": {"value": "back content", "order": 1}