From e178881b375f64253fac7205d7c34b5334e29c9a Mon Sep 17 00:00:00 2001 From: Pacharapol Withayasakpunt Date: Thu, 28 Apr 2022 14:42:42 +0700 Subject: [PATCH] add wanikani sentence to Anki --- scripts/populate-from-wanikani.ts | 16 +++++- src/wanikani.ts | 93 ++++++++++++++++++++++++++++--- 2 files changed, 99 insertions(+), 10 deletions(-) diff --git a/scripts/populate-from-wanikani.ts b/scripts/populate-from-wanikani.ts index def664a..92c0005 100644 --- a/scripts/populate-from-wanikani.ts +++ b/scripts/populate-from-wanikani.ts @@ -1,9 +1,19 @@ import { WaniKani } from '@/wanikani'; if (require.main === module) { - new WaniKani().populateSound( + // new WaniKani().populateSound( + // 'note:jp.takoboto', + // { ja: 'Japanese', audio: 'JapaneseAudio' }, + // { mode: { online: true } }, + // ); + new WaniKani().populateSentence( 'note:jp.takoboto', - { ja: 'Japanese', audio: 'JapaneseAudio' }, - { mode: { online: true } }, + { + vocabJa: 'Japanese', + sentenceJa: 'Sentence', + sentenceAudio: 'SentenceAudio', + sentenceEn: 'SentenceMeaning', + }, + { overwrite: true }, ); } diff --git a/src/wanikani.ts b/src/wanikani.ts index 6117c59..07bdb50 100644 --- a/src/wanikani.ts +++ b/src/wanikani.ts @@ -122,17 +122,15 @@ export class WaniKani { ja.replace(/\[.+?\]/g, '').replace(/ /g, ''), ); if (audio) { - notesToUpdate.push( - opts.mode?.online + notesToUpdate.push({ + id: n.noteId, + ...(opts.mode?.online ? { - id: n.noteId, fields: { [fields.audio]: soundTag.make(audio.url), }, } : { - id: n.noteId, - fields: {}, audio: [ { url: audio.url, @@ -140,8 +138,8 @@ export class WaniKani { fields: [fields.audio], }, ], - }, - ); + }), + }); } } } @@ -160,6 +158,87 @@ export class WaniKani { } }); } + + async populateSentence( + query: string, + fields: { + vocabJa: string; + sentenceJa: string; + sentenceAudio?: string; + sentenceEn: string; + }, + opts: { + overwrite?: boolean; + } = {}, + ) { + const subjects = await this.subjects(); + + const vocabularies = subjects.filter( + (s) => s.object === 'vocabulary', + ) as IVocabulary[]; + const sentenceMap = new Map< + string, + { + ja: string; + en: string; + } + >(); + vocabularies.map((v) => { + if (sentenceMap.has(v.data.characters)) return; + const sent = v.data.context_sentences[0]; + if (!sent || !sent.ja.trim()) return; + sentenceMap.set(v.data.characters, sent); + }); + if (!sentenceMap.size) return; + + query += ` -${fields.vocabJa}:`; + if (fields.sentenceAudio) { + query += ` -${fields.sentenceAudio}:`; + } + if (!opts.overwrite) { + query += ` -${fields.sentenceJa}: -${fields.sentenceEn}:`; + } + + const anki = new AnkiConnect(); + anki + .api('findNotes', { + query, + }) + .then((notes) => anki.api('notesInfo', { notes })) + .then(async (notes) => { + const notesToUpdate: IAnkiConnectActions['updateNoteFields']['params']['note'][] = + []; + + for (const n of notes) { + const { value: ja } = n.fields[fields.vocabJa] || {}; + if (ja) { + const sent = sentenceMap.get( + ja.replace(/\[.+?\]/g, '').replace(/ /g, ''), + ); + if (sent) { + notesToUpdate.push({ + id: n.noteId, + fields: { + [fields.sentenceJa]: sent.ja, + [fields.sentenceEn]: sent.en, + }, + }); + } + } + } + + if (!notesToUpdate.length) return; + + await anki.multi<'updateNoteFields'[]>({ + actions: notesToUpdate.map((note) => ({ + action: 'updateNoteFields', + params: { + note, + }, + })), + }); + }); + } } type WaniKaniDate = string;