|
|
@ -1,5 +1,5 @@ |
|
|
|
import { soundTag } from '@/anki'; |
|
|
|
import { AnkiConnect } from '@/ankiconnect'; |
|
|
|
import { AnkiConnect, IAnkiConnectActions } from '@/ankiconnect'; |
|
|
|
|
|
|
|
export async function listTags( |
|
|
|
query = 'deck:Takoboto -Takoboto: tag:common -tag:reading-challenge -tag:favorites -tag:death-note -tag:ハピネス -tag:https://www.bunka.go.jp/seisaku/bunkashingikai/kokugo/hokoku/pdf/ijidokun_140221.pdf', |
|
|
@ -63,6 +63,90 @@ export async function addSoundTag(query: string, fieldNames: string[]) { |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
export async function fixCloze( |
|
|
|
query: string, |
|
|
|
fields: { vocabJa: string; sentenceCloze: string }, |
|
|
|
) { |
|
|
|
const anki = new AnkiConnect(); |
|
|
|
anki |
|
|
|
.api('findNotes', { |
|
|
|
query, |
|
|
|
}) |
|
|
|
.then((notes) => anki.api('notesInfo', { notes })) |
|
|
|
.then(async (notes) => { |
|
|
|
const notesToUpdate: IAnkiConnectActions['updateNoteFields']['params']['note'][] = |
|
|
|
[]; |
|
|
|
|
|
|
|
const badJa: string[] = []; |
|
|
|
|
|
|
|
for (const n of notes) { |
|
|
|
const { value: ja } = n.fields[fields.vocabJa] || {}; |
|
|
|
const { value: sent } = n.fields[fields.sentenceCloze] || {}; |
|
|
|
if (ja && sent) { |
|
|
|
const clozeChar = '__'; |
|
|
|
|
|
|
|
if ( |
|
|
|
sent |
|
|
|
.split('<br>') |
|
|
|
.filter((_, i) => i % 2 === 0) |
|
|
|
.every((s) => s.includes(clozeChar)) |
|
|
|
) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
const cleanJa = ja.replace(/\[.+?\]/g, '').replace(/ /g, ''); |
|
|
|
let newSent = sent.replace(cleanJa, clozeChar); |
|
|
|
|
|
|
|
const jaNoOkuri = cleanJa.replace(/[\p{sc=Hiragana}]/gu, ''); |
|
|
|
if (cleanJa !== jaNoOkuri && newSent.includes(jaNoOkuri)) { |
|
|
|
const s2 = newSent.replace(jaNoOkuri, clozeChar); |
|
|
|
if (s2 !== newSent) { |
|
|
|
newSent = s2; |
|
|
|
} else { |
|
|
|
badJa.push(ja); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!sent.includes(clozeChar) && sent !== newSent) { |
|
|
|
notesToUpdate.push({ |
|
|
|
id: n.noteId, |
|
|
|
fields: { |
|
|
|
[fields.sentenceCloze]: newSent, |
|
|
|
}, |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
while (badJa.length) { |
|
|
|
console.log( |
|
|
|
query + |
|
|
|
' tag:wanikani card:EJ (' + |
|
|
|
badJa |
|
|
|
.splice(0, 20) |
|
|
|
.map((ja) => `${fields.vocabJa}:${ja}`) |
|
|
|
.join(' OR ') + |
|
|
|
')', |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
if (!notesToUpdate.length) return; |
|
|
|
|
|
|
|
await anki.multi<'updateNoteFields'[]>({ |
|
|
|
actions: notesToUpdate.map((note) => ({ |
|
|
|
action: 'updateNoteFields', |
|
|
|
params: { |
|
|
|
note, |
|
|
|
}, |
|
|
|
})), |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
if (require.main === module) { |
|
|
|
addSoundTag('note:jp.takoboto', ['SentenceAudio', 'JapaneseAudio']); |
|
|
|
// addSoundTag('note:jp.takoboto', ['SentenceAudio', 'JapaneseAudio']);
|
|
|
|
fixCloze('deck:Takoboto', { |
|
|
|
vocabJa: 'Japanese', |
|
|
|
sentenceCloze: 'MeaningQuiz', |
|
|
|
}); |
|
|
|
} |