add how to populate from wanikani
This commit is contained in:
1 parent
92c1de3d1f
commit
45232b33fc
4 files changed
+130
-28
No files matched your search
@@ -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);
|
||||||
|
});
|
||||||
|
}
|
||||||
+1
-20
@@ -1,3 +1,4 @@
|
|||||||
|
import { soundTag } from '@/anki';
|
||||||
import { AnkiConnect } from '@/ankiconnect';
|
import { AnkiConnect } from '@/ankiconnect';
|
||||||
|
|
||||||
export async function listTags(
|
export async function listTags(
|
||||||
@@ -14,26 +15,6 @@ export async function listTags(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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[]) {
|
export async function addSoundTag(query: string, fieldNames: string[]) {
|
||||||
query +=
|
query +=
|
||||||
' (' + fieldNames.map((f) => `(-${f}: -${f}:[sound:*)`).join(' OR ') + ')';
|
' (' + fieldNames.map((f) => `(-${f}: -${f}:[sound:*)`).join(' OR ') + ')';
|
||||||
|
|||||||
+20
@@ -46,3 +46,23 @@ export interface IAnkiTemplate {
|
|||||||
export interface IAnkiDeckConfig {
|
export interface IAnkiDeckConfig {
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export 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;
|
||||||
|
},
|
||||||
|
};
|
||||||
+20
-8
@@ -99,14 +99,25 @@ interface ISubjectBase<
|
|||||||
export type IRadical = ISubjectBase<
|
export type IRadical = ISubjectBase<
|
||||||
'radical',
|
'radical',
|
||||||
{
|
{
|
||||||
character_images: {
|
character_images: ({
|
||||||
url: string;
|
url: string;
|
||||||
metadata: {
|
} & (
|
||||||
inline_styles?: boolean;
|
| {
|
||||||
dimensions?: string;
|
metadata: {
|
||||||
};
|
inline_styles?: boolean;
|
||||||
content_type: string;
|
dimensions?: string;
|
||||||
}[];
|
};
|
||||||
|
content_type: 'image/svg+xml';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
metadata: {
|
||||||
|
color: string;
|
||||||
|
dimensions: string;
|
||||||
|
style_name: string;
|
||||||
|
};
|
||||||
|
content_type: 'image/png';
|
||||||
|
}
|
||||||
|
))[];
|
||||||
amalgamation_subject_ids: SubjectID[];
|
amalgamation_subject_ids: SubjectID[];
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
@@ -117,7 +128,8 @@ export type IKanji = ISubjectBase<
|
|||||||
readings: {
|
readings: {
|
||||||
reading: string;
|
reading: string;
|
||||||
primary: boolean;
|
primary: boolean;
|
||||||
type: 'kunyomi' | 'onyomi';
|
accepted_answer: boolean;
|
||||||
|
type: 'kunyomi' | 'onyomi' | 'nanori';
|
||||||
}[];
|
}[];
|
||||||
component_subject_ids: SubjectID[];
|
component_subject_ids: SubjectID[];
|
||||||
visually_similar_subject_ids: SubjectID[];
|
visually_similar_subject_ids: SubjectID[];
|
||||||
|
|||||||
Reference in new issue
Block a user