add tag adder
This commit is contained in:
1 parent
e178881b37
commit
16d1307744
4 files changed
+148
-26
No files matched your search
@@ -25,24 +25,12 @@ async function makeWaniKaniKanjiLevels(
|
|||||||
|
|
||||||
for (const k of wkKanji) {
|
for (const k of wkKanji) {
|
||||||
const { level, characters } = k.data;
|
const { level, characters } = k.data;
|
||||||
|
const label = WaniKani.getLevelLabel(level);
|
||||||
let category: string;
|
const category = `${label.range}: ${
|
||||||
if (level < 11) {
|
label.ja
|
||||||
category = '01-10: 快 PLEASANT';
|
} ${label.en.toLocaleUpperCase()}`;
|
||||||
} else if (level < 21) {
|
|
||||||
category = '11-21: 苦 PAINFUL';
|
|
||||||
} else if (level < 31) {
|
|
||||||
category = '21-30: 死 DEATH';
|
|
||||||
} else if (level < 41) {
|
|
||||||
category = '31-40: 地獄 HELL';
|
|
||||||
} else if (level < 51) {
|
|
||||||
category = '41-50: 天国 PARADISE';
|
|
||||||
} else {
|
|
||||||
category = '51-60: 現実 REALITY';
|
|
||||||
}
|
|
||||||
|
|
||||||
const catMap = levelMap[category] || {};
|
const catMap = levelMap[category] || {};
|
||||||
|
|
||||||
const levelString = level.toString().padStart(2, '0');
|
const levelString = level.toString().padStart(2, '0');
|
||||||
|
|
||||||
const ks = catMap[levelString] || [];
|
const ks = catMap[levelString] || [];
|
||||||
|
|||||||
@@ -6,14 +6,7 @@ if (require.main === module) {
|
|||||||
// { ja: 'Japanese', audio: 'JapaneseAudio' },
|
// { ja: 'Japanese', audio: 'JapaneseAudio' },
|
||||||
// { mode: { online: true } },
|
// { mode: { online: true } },
|
||||||
// );
|
// );
|
||||||
new WaniKani().populateSentence(
|
new WaniKani().addTags('note:jp.takoboto', {
|
||||||
'note:jp.takoboto',
|
ja: 'Japanese',
|
||||||
{
|
});
|
||||||
vocabJa: 'Japanese',
|
|
||||||
sentenceJa: 'Sentence',
|
|
||||||
sentenceAudio: 'SentenceAudio',
|
|
||||||
sentenceEn: 'SentenceMeaning',
|
|
||||||
},
|
|
||||||
{ overwrite: true },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export interface ILevelLabel {
|
||||||
|
range: string;
|
||||||
|
ja: string;
|
||||||
|
en: string;
|
||||||
|
}
|
||||||
+136
@@ -4,6 +4,7 @@ import axios, { AxiosInstance } from 'axios';
|
|||||||
|
|
||||||
import { soundTag } from './anki';
|
import { soundTag } from './anki';
|
||||||
import { AnkiConnect, IAnkiConnectActions } from './ankiconnect';
|
import { AnkiConnect, IAnkiConnectActions } from './ankiconnect';
|
||||||
|
import { ILevelLabel } from './level';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
|
|
||||||
export class WaniKani {
|
export class WaniKani {
|
||||||
@@ -18,6 +19,48 @@ export class WaniKani {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getLevelLabel(level: number): ILevelLabel {
|
||||||
|
if (level < 11) {
|
||||||
|
return {
|
||||||
|
range: '01-10',
|
||||||
|
ja: '快',
|
||||||
|
en: 'PLEASANT',
|
||||||
|
};
|
||||||
|
} else if (level < 21) {
|
||||||
|
return {
|
||||||
|
range: '11-20',
|
||||||
|
ja: '苦',
|
||||||
|
en: 'PAINFUL',
|
||||||
|
};
|
||||||
|
} else if (level < 31) {
|
||||||
|
return {
|
||||||
|
range: '21-30',
|
||||||
|
ja: '死',
|
||||||
|
en: 'DEATH',
|
||||||
|
};
|
||||||
|
} else if (level < 41) {
|
||||||
|
return {
|
||||||
|
range: '31-40',
|
||||||
|
ja: '地獄',
|
||||||
|
en: 'HELL',
|
||||||
|
};
|
||||||
|
} else if (level < 51) {
|
||||||
|
return {
|
||||||
|
range: '41-50',
|
||||||
|
ja: '天国',
|
||||||
|
en: 'PARADISE',
|
||||||
|
};
|
||||||
|
} else if (level < 61) {
|
||||||
|
return {
|
||||||
|
range: '51-60',
|
||||||
|
ja: '現実',
|
||||||
|
en: 'REALITY',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`invalid level: ${level}`);
|
||||||
|
}
|
||||||
|
|
||||||
async subjects({
|
async subjects({
|
||||||
force,
|
force,
|
||||||
}: {
|
}: {
|
||||||
@@ -239,6 +282,99 @@ export class WaniKani {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addTags(
|
||||||
|
query: string,
|
||||||
|
fields: {
|
||||||
|
ja: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const subjects = await this.subjects();
|
||||||
|
|
||||||
|
const vocabularies = subjects.filter(
|
||||||
|
(s) => s.object === 'vocabulary',
|
||||||
|
) as IVocabulary[];
|
||||||
|
const vocabMap = new Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
level: number;
|
||||||
|
label: ILevelLabel;
|
||||||
|
}
|
||||||
|
>();
|
||||||
|
vocabularies.map((v) => {
|
||||||
|
if (vocabMap.has(v.data.characters)) return;
|
||||||
|
vocabMap.set(v.data.characters, {
|
||||||
|
level: v.data.level,
|
||||||
|
label: WaniKani.getLevelLabel(v.data.level),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (!vocabMap.size) return;
|
||||||
|
|
||||||
|
query += ` -${fields.ja}:`;
|
||||||
|
|
||||||
|
const anki = new AnkiConnect();
|
||||||
|
anki
|
||||||
|
.api('findNotes', {
|
||||||
|
query,
|
||||||
|
})
|
||||||
|
.then((notes) => anki.api('notesInfo', { notes }))
|
||||||
|
.then(async (notes) => {
|
||||||
|
const notesToUpdate: {
|
||||||
|
id: SubjectID;
|
||||||
|
tags: string[];
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
for (const n of notes) {
|
||||||
|
const { value: ja } = n.fields[fields.ja] || {};
|
||||||
|
if (ja) {
|
||||||
|
const vocab = vocabMap.get(
|
||||||
|
ja.replace(/\[.+?\]/g, '').replace(/ /g, ''),
|
||||||
|
);
|
||||||
|
if (vocab) {
|
||||||
|
notesToUpdate.push({
|
||||||
|
id: n.noteId,
|
||||||
|
tags: [
|
||||||
|
'wanikani',
|
||||||
|
`level-${vocab.level}`,
|
||||||
|
`wanikani-level-${vocab.level}`,
|
||||||
|
`wanikani-level-${vocab.label.range}-${vocab.label.ja}`,
|
||||||
|
`wanikani-level-${
|
||||||
|
vocab.label.range
|
||||||
|
}-${vocab.label.en.toLocaleLowerCase()}`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!notesToUpdate.length) return;
|
||||||
|
|
||||||
|
const addTagsMap = new Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
notes: SubjectID[];
|
||||||
|
tags: string;
|
||||||
|
}
|
||||||
|
>();
|
||||||
|
|
||||||
|
notesToUpdate.map(({ id, tags }) => {
|
||||||
|
const identifier = JSON.stringify(tags);
|
||||||
|
const v = addTagsMap.get(identifier) || {
|
||||||
|
notes: [],
|
||||||
|
tags: tags.join(' '),
|
||||||
|
};
|
||||||
|
v.notes.push(id);
|
||||||
|
addTagsMap.set(identifier, v);
|
||||||
|
});
|
||||||
|
|
||||||
|
await anki.multi<'addTags'[]>({
|
||||||
|
actions: Array.from(addTagsMap.values()).map((params) => ({
|
||||||
|
action: 'addTags',
|
||||||
|
params,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type WaniKaniDate = string;
|
type WaniKaniDate = string;
|
||||||
|
|||||||
Reference in new issue
Block a user