|
|
@ -1,12 +1,86 @@ |
|
|
|
import { AnkiConnect } from '@/ankiconnect'; |
|
|
|
|
|
|
|
const anki = new AnkiConnect(); |
|
|
|
anki |
|
|
|
.api('findNotes', { |
|
|
|
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', |
|
|
|
}) |
|
|
|
.then((notes) => anki.api('notesInfo', { notes })) |
|
|
|
.then((notes) => { |
|
|
|
console.log(new Set(notes.flatMap((n) => n.tags))); |
|
|
|
}); |
|
|
|
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', |
|
|
|
) { |
|
|
|
const anki = new AnkiConnect(); |
|
|
|
return anki |
|
|
|
.api('findNotes', { |
|
|
|
query, |
|
|
|
}) |
|
|
|
.then((notes) => anki.api('notesInfo', { notes })) |
|
|
|
.then((notes) => { |
|
|
|
return new Set(notes.flatMap((n) => n.tags)); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
const soundTag = { |
|
|
|
pre: '[sound:', |
|
|
|
post: ']', |
|
|
|
is(src: string) { |
|
|
|
return src.startsWith(this.pre) && src.endsWith(this.post); |
|
|
|
}, |
|
|
|
add(src: string) { |
|
|
|
if (soundTag.is(src)) return src; |
|
|
|
return this.pre + src + this.post; |
|
|
|
}, |
|
|
|
remove(src: string) { |
|
|
|
if (!soundTag.is(src)) return src; |
|
|
|
if (this.isEmpty(src)) return src; |
|
|
|
return src.substring(this.pre.length, src.length - this.post.length); |
|
|
|
}, |
|
|
|
isEmpty(src: string) { |
|
|
|
return src === this.pre + this.post; |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
export async function addSoundTag(query: string, fieldNames: string[]) { |
|
|
|
query += ' (' + fieldNames.map((f) => `-${f}:`).join(' OR ') + ')'; |
|
|
|
|
|
|
|
const anki = new AnkiConnect(); |
|
|
|
anki |
|
|
|
.api('findNotes', { |
|
|
|
query, |
|
|
|
}) |
|
|
|
.then((notes) => anki.api('notesInfo', { notes })) |
|
|
|
.then((notes) => { |
|
|
|
const notesToUpdate: { |
|
|
|
id: number; |
|
|
|
fields: Record<string, string>; |
|
|
|
}[] = []; |
|
|
|
|
|
|
|
for (const n of notes) { |
|
|
|
let toUpdate: typeof notesToUpdate[0] | undefined; |
|
|
|
|
|
|
|
fieldNames.map((fieldName: string) => { |
|
|
|
const field = n.fields[fieldName]; |
|
|
|
if (field) { |
|
|
|
const { value } = field; |
|
|
|
if (!soundTag.is(value)) { |
|
|
|
toUpdate = toUpdate || { id: n.noteId, fields: {} }; |
|
|
|
toUpdate.fields[fieldName] = soundTag.add(value); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
if (toUpdate) { |
|
|
|
notesToUpdate.push(toUpdate); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!notesToUpdate.length) return; |
|
|
|
|
|
|
|
return anki.multi<'updateNoteFields'[]>({ |
|
|
|
actions: notesToUpdate.map((note) => ({ |
|
|
|
action: 'updateNoteFields', |
|
|
|
params: { |
|
|
|
note, |
|
|
|
}, |
|
|
|
})), |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
if (require.main === module) { |
|
|
|
addSoundTag('jp.takoboto', ['SentenceAudio', 'JapaneseAudio']); |
|
|
|
} |