diff options
| author | navewindre <boneyaard@gmail.com> | 2025-04-05 02:59:37 +0200 |
|---|---|---|
| committer | navewindre <boneyaard@gmail.com> | 2025-04-05 02:59:37 +0200 |
| commit | b24463f3d045783b8f4e72926054d53b908e150f (patch) | |
| tree | 036f976e217128b9e4acf3854f72908c27dec17b /config/mpv/scripts/subs2srsa/ankiconnect.lua | |
| parent | 398e41be4daf339bd55862520c528a7d93b83fb6 (diff) | |
a
Diffstat (limited to 'config/mpv/scripts/subs2srsa/ankiconnect.lua')
| -rw-r--r-- | config/mpv/scripts/subs2srsa/ankiconnect.lua | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/config/mpv/scripts/subs2srsa/ankiconnect.lua b/config/mpv/scripts/subs2srsa/ankiconnect.lua new file mode 100644 index 0000000..f9c87d8 --- /dev/null +++ b/config/mpv/scripts/subs2srsa/ankiconnect.lua @@ -0,0 +1,241 @@ +--[[ +Copyright: Ren Tatsumoto and contributors +License: GNU GPL, version 3 or later; http://www.gnu.org/licenses/gpl.html + +AnkiConnect requests +]] + +local utils = require('mp.utils') +local msg = require('mp.msg') +local h = require('helpers') +local self = {} + +self.execute = function(request, completion_fn) + -- utils.format_json returns a string + -- On error, request_json will contain "null", not nil. + local request_json, error = utils.format_json(request) + + if error ~= nil or request_json == "null" then + return completion_fn and completion_fn() + else + return self.platform.curl_request(self.config.ankiconnect_url, request_json, completion_fn) + end +end + +self.parse_result = function(curl_output) + -- there are two values that we actually care about: result and error + -- but we need to crawl inside to get them. + + if curl_output == nil then + return nil, "Failed to format json or no args passed" + end + + if curl_output.status ~= 0 then + return nil, "Ankiconnect isn't running" + end + + local stdout_json = utils.parse_json(curl_output.stdout) + + if stdout_json == nil then + return nil, "Fatal error from Ankiconnect" + end + + if stdout_json.error ~= nil then + return nil, tostring(stdout_json.error) + end + + return stdout_json.result, nil +end + +self.get_media_dir_path = function() + -- Ask AnkiConnect where to store media files. + -- If AnkiConnect isn't running, returns nil. + + local ret = self.execute({ + action = "getMediaDirPath", + version = 6, + }) + local dir_path, error = self.parse_result(ret) + if not error then + return dir_path + else + msg.error(string.format("Couldn't retrieve path to collection.media folder: %s", error)) + return nil + end +end + +self.create_deck = function(deck_name) + local args = { + action = "changeDeck", + version = 6, + params = { + cards = {}, + deck = deck_name + } + } + local result_notify = function(_, result, _) + local _, error = self.parse_result(result) + if not error then + msg.info(string.format("Deck %s: check completed.", deck_name)) + else + msg.warn(string.format("Deck %s: check failed. Reason: %s.", deck_name, error)) + end + end + self.execute(args, result_notify) +end + +self.add_note = function(note_fields, tag, gui) + local action = gui and 'guiAddCards' or 'addNote' + local args = { + action = action, + version = 6, + params = { + note = { + deckName = self.config.deck_name, + modelName = self.config.model_name, + fields = note_fields, + options = { + allowDuplicate = self.config.allow_duplicates, + duplicateScope = "deck", + }, + tags = h.is_empty(tag) and {} or { tag, }, + } + } + } + local result_notify = function(_, result, _) + local note_id, error = self.parse_result(result) + if not error then + h.notify(string.format("Note added. ID = %s.", note_id)) + else + h.notify(string.format("Error: %s.", error), "error", 2) + end + end + self.execute(args, result_notify) +end + +self.get_last_note_ids = function(n_cards) + local ret = self.execute { + action = "findNotes", + version = 6, + params = { + query = "added:1" -- find all notes added today + } + } + + local note_ids, _ = self.parse_result(ret) + + if not h.is_empty(note_ids) then + return h.get_last_n_added_notes(note_ids, n_cards) + else + return {} + end +end + +self.get_note_fields = function(note_id) + local ret = self.execute { + action = "notesInfo", + version = 6, + params = { + notes = { note_id } + } + } + + local result, error = self.parse_result(ret) + + if error == nil then + result = result[1].fields + for key, value in pairs(result) do + result[key] = value.value + end + return result + else + return nil + end +end + +self.get_first_field = function(model_name) + local ret = self.execute { + action = "findModelsByName", + version = 6, + params = { + modelNames = { model_name } + } + } + + local result, error = self.parse_result(ret) + + if error == nil then + for _, field in pairs(result[1].flds) do + if field.ord == 0 then + return field.name + end + end + else + msg.error(string.format("Couldn't retrieve the first field's name of note type %s: %s", model_name, error)) + return nil + end +end + +self.gui_browse = function(query) + if not self.config.disable_gui_browse then + self.execute { + action = 'guiBrowse', + version = 6, + params = { + query = query + } + } + end +end + +self.add_tag = function(note_id, tag) + if not h.is_empty(tag) then + self.execute { + action = 'addTags', + version = 6, + params = { + notes = { note_id }, + tags = tag + } + } + end +end + +self.append_media = function(note_id, fields, create_media_fn, tag) + -- AnkiConnect will fail to update the note if it's selected in the Anki Browser. + -- https://github.com/FooSoft/anki-connect/issues/82 + -- Switch focus from the current note to avoid it. + self.gui_browse("nid:1") -- impossible nid + + local args = { + action = "updateNoteFields", + version = 6, + params = { + note = { + id = note_id, + fields = fields, + } + } + } + + local on_finish = function(_, result, _) + local _, error = self.parse_result(result) + if not error then + create_media_fn() + self.add_tag(note_id, tag) + self.gui_browse(string.format("nid:%s", note_id)) -- select the updated note in the card browser + h.notify(string.format("Note #%s updated.", note_id)) + else + h.notify(string.format("Error: %s.", error), "error", 2) + end + end + + self.execute(args, on_finish) +end + +self.init = function(config, platform) + self.config = config + self.platform = platform +end + +return self |
