|
|
@ -0,0 +1,89 @@ |
|
|
|
import { soundTag } from '@/anki'; |
|
|
|
import { AnkiConnect, IAnkiConnectActions } from '@/ankiconnect'; |
|
|
|
import { ISubject, IVocabulary, WaniKani } from '@/wanikani'; |
|
|
|
|
|
|
|
export async function populateSounds( |
|
|
|
query: string, |
|
|
|
jaField: string, |
|
|
|
audioField: string, |
|
|
|
subjects: ISubject[], |
|
|
|
) { |
|
|
|
const vocabularies = subjects.filter( |
|
|
|
(s) => s.object === 'vocabulary', |
|
|
|
) as IVocabulary[]; |
|
|
|
const audioMap = new Map< |
|
|
|
string, |
|
|
|
{ |
|
|
|
url: string; |
|
|
|
filename: string; |
|
|
|
} |
|
|
|
>(); |
|
|
|
vocabularies.map((v) => { |
|
|
|
if (audioMap.has(v.data.characters)) return; |
|
|
|
const audio = v.data.pronunciation_audios[0]; |
|
|
|
if (!audio) return; |
|
|
|
audioMap.set(v.data.characters, { |
|
|
|
url: audio.url, |
|
|
|
filename: `wanikani_${v.data.characters}_${audio.metadata.source_id}${ |
|
|
|
audio.content_type === 'audio/ogg' ? '.ogg' : '.mp3' |
|
|
|
}`,
|
|
|
|
}); |
|
|
|
}); |
|
|
|
if (!audioMap.size) return; |
|
|
|
|
|
|
|
query += ` -${jaField}: ${audioField}:`; |
|
|
|
|
|
|
|
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[jaField] || {}; |
|
|
|
if (ja) { |
|
|
|
const audio = audioMap.get( |
|
|
|
ja.replace(/\[.+?\]/g, '').replace(/ /g, ''), |
|
|
|
); |
|
|
|
if (audio) { |
|
|
|
notesToUpdate.push({ |
|
|
|
id: n.noteId, |
|
|
|
fields: { |
|
|
|
[audioField]: soundTag.add(audio.filename), |
|
|
|
}, |
|
|
|
audio: [ |
|
|
|
{ |
|
|
|
url: audio.url, |
|
|
|
filename: audio.filename, |
|
|
|
fields: [audioField], |
|
|
|
}, |
|
|
|
], |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!notesToUpdate.length) return; |
|
|
|
|
|
|
|
while (notesToUpdate.length) { |
|
|
|
await anki.multi<'updateNoteFields'[]>({ |
|
|
|
actions: notesToUpdate.splice(0, 100).map((note) => ({ |
|
|
|
action: 'updateNoteFields', |
|
|
|
params: { |
|
|
|
note, |
|
|
|
}, |
|
|
|
})), |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
if (require.main === module) { |
|
|
|
new WaniKani().subjects().then((subjects) => { |
|
|
|
populateSounds('note:jp.takoboto', 'Japanese', 'JapaneseAudio', subjects); |
|
|
|
}); |
|
|
|
} |