update wk populate
This commit is contained in:
1 parent
292beabffe
commit
6d46308e78
5 files changed
+244
-242
No files matched your search
@@ -1,95 +1,9 @@
|
|||||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
import { readFileSync, writeFileSync } from 'fs';
|
||||||
|
|
||||||
import { IKanji, WaniKani } from '@/wanikani';
|
import { ILevelMap } from '@/level';
|
||||||
|
import { WaniKani } from '@/wanikani';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
interface ILevelMap {
|
|
||||||
[category: string]: {
|
|
||||||
[levelString: string]: string[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function makeWaniKaniKanjiLevels(
|
|
||||||
opts: { cache?: boolean; force?: boolean } = {},
|
|
||||||
) {
|
|
||||||
const FILENAME = 'cache/wanikani-kanji.yaml';
|
|
||||||
if (opts.cache && existsSync(FILENAME)) {
|
|
||||||
return yaml.load(readFileSync(FILENAME, 'utf-8')) as ILevelMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wkKanji = await new WaniKani()
|
|
||||||
.subjects({ force: !!opts.force })
|
|
||||||
.then((vs) => vs.filter((v) => v.object === 'kanji') as IKanji[]);
|
|
||||||
|
|
||||||
const levelMap: ILevelMap = {};
|
|
||||||
|
|
||||||
for (const k of wkKanji) {
|
|
||||||
const { level, characters } = k.data;
|
|
||||||
const label = WaniKani.getLevelLabel(level);
|
|
||||||
if (!label) throw new Error(`Invalid level: ${level}`);
|
|
||||||
|
|
||||||
const category = `${label.range}: ${
|
|
||||||
label.ja
|
|
||||||
} ${label.en.toLocaleUpperCase()}`;
|
|
||||||
|
|
||||||
const catMap = levelMap[category] || {};
|
|
||||||
const levelString = level.toString().padStart(2, '0');
|
|
||||||
|
|
||||||
const ks = catMap[levelString] || [];
|
|
||||||
ks.push(characters);
|
|
||||||
catMap[levelString] = ks;
|
|
||||||
|
|
||||||
levelMap[category] = catMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeFileSync(
|
|
||||||
FILENAME,
|
|
||||||
yaml.dump(levelMap, {
|
|
||||||
sortKeys: true,
|
|
||||||
flowLevel: 2,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return levelMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function makeKanjiLevels(opts: { useBeyond: boolean }) {
|
|
||||||
const wk = await makeWaniKaniKanjiLevels({ cache: true });
|
|
||||||
const beyond = opts.useBeyond
|
|
||||||
? (yaml.load(readFileSync('assets/beyond.yaml', 'utf-8')) as ILevelMap)
|
|
||||||
: {};
|
|
||||||
|
|
||||||
const kanjiToLevel = new Map<
|
|
||||||
string,
|
|
||||||
{
|
|
||||||
level: number;
|
|
||||||
deckName: string;
|
|
||||||
}
|
|
||||||
>();
|
|
||||||
|
|
||||||
const setKanjiToLevel = (lvMap: ILevelMap) => {
|
|
||||||
Object.entries(lvMap).map(([cat, map]) => {
|
|
||||||
Object.entries(map).map(([levelString, ks]) => {
|
|
||||||
const level = Number(levelString);
|
|
||||||
ks.map((k) => {
|
|
||||||
let prev = kanjiToLevel.get(k);
|
|
||||||
if (!prev || prev.level > level) {
|
|
||||||
prev = {
|
|
||||||
level,
|
|
||||||
deckName: cat + '::' + levelString,
|
|
||||||
};
|
|
||||||
kanjiToLevel.set(k, prev);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
setKanjiToLevel(wk);
|
|
||||||
setKanjiToLevel(beyond);
|
|
||||||
|
|
||||||
return kanjiToLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function repairBeyond() {
|
export async function repairBeyond() {
|
||||||
const beyond = yaml.load(
|
const beyond = yaml.load(
|
||||||
readFileSync('cache/beyond.yaml', 'utf-8'),
|
readFileSync('cache/beyond.yaml', 'utf-8'),
|
||||||
@@ -119,7 +33,7 @@ export async function repairBeyond() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
'assets/beyond.yaml',
|
WaniKani.files.beyond,
|
||||||
yaml.dump(levelMap, {
|
yaml.dump(levelMap, {
|
||||||
sortKeys: true,
|
sortKeys: true,
|
||||||
flowLevel: 2,
|
flowLevel: 2,
|
||||||
|
|||||||
@@ -1,22 +1,29 @@
|
|||||||
import { WaniKani } from '@/wanikani';
|
import { WaniKani } from '@/wanikani';
|
||||||
|
|
||||||
if (require.main === module) {
|
async function main() {
|
||||||
// new WaniKani().populateSound(
|
const wk = new WaniKani();
|
||||||
// 'note:jp.takoboto',
|
|
||||||
// { ja: 'Japanese', audio: 'JapaneseAudio' },
|
await wk.sortByLevels('Takoboto', { ja: 'Japanese' }, { useBeyond: true });
|
||||||
// { mode: { online: true } },
|
await wk.populateSound(
|
||||||
// );
|
'note:jp.takoboto',
|
||||||
// new WaniKani().populateSentence(
|
{ ja: 'Japanese', audio: 'JapaneseAudio' },
|
||||||
// 'note:jp.takoboto',
|
{ mode: { online: true } },
|
||||||
// {
|
);
|
||||||
// vocabJa: 'Japanese',
|
await wk.populateSentence(
|
||||||
// sentenceJa: 'Sentence',
|
'note:jp.takoboto',
|
||||||
// sentenceAudio: 'SentenceAudio',
|
{
|
||||||
// sentenceEn: 'SentenceMeaning',
|
vocabJa: 'Japanese',
|
||||||
// },
|
sentenceJa: 'Sentence',
|
||||||
// { overwrite: true },
|
sentenceAudio: 'SentenceAudio',
|
||||||
// );
|
sentenceEn: 'SentenceMeaning',
|
||||||
new WaniKani().addTags('note:jp.takoboto', {
|
},
|
||||||
|
{ overwrite: true },
|
||||||
|
);
|
||||||
|
await wk.addTags('note:jp.takoboto', {
|
||||||
ja: 'Japanese',
|
ja: 'Japanese',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
main();
|
||||||
|
}
|
||||||
+3
-132
@@ -1,6 +1,4 @@
|
|||||||
import { AnkiConnect, IAnkiConnectActions } from '@/ankiconnect';
|
import { WaniKani } from '@/wanikani';
|
||||||
|
|
||||||
import { makeKanjiLevels } from './get-kanji-level';
|
|
||||||
|
|
||||||
const DECK = 'Takoboto';
|
const DECK = 'Takoboto';
|
||||||
const KANJI_FIELD = 'Japanese';
|
const KANJI_FIELD = 'Japanese';
|
||||||
@@ -12,135 +10,8 @@ const KANJI_FIELD = 'Japanese';
|
|||||||
const USE_BEYOND = true;
|
const USE_BEYOND = true;
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const anki = new AnkiConnect();
|
const wk = new WaniKani();
|
||||||
|
await wk.sortByLevels(DECK, { ja: KANJI_FIELD }, { useBeyond: USE_BEYOND });
|
||||||
const deckConfig = await anki.api('getDeckConfig', {
|
|
||||||
deck: DECK,
|
|
||||||
});
|
|
||||||
|
|
||||||
const deckQuery = `deck:${DECK} -deck:${DECK}::*`;
|
|
||||||
const kanjiLevels = await makeKanjiLevels({ useBeyond: USE_BEYOND });
|
|
||||||
|
|
||||||
await anki
|
|
||||||
.api('findCards', {
|
|
||||||
query: deckQuery,
|
|
||||||
})
|
|
||||||
.then((cards) => anki.api('cardsInfo', { cards }))
|
|
||||||
.then(async (rs) => {
|
|
||||||
const modelToSubdecks = new Map<
|
|
||||||
string,
|
|
||||||
{
|
|
||||||
[subdeck: string]: number[];
|
|
||||||
}
|
|
||||||
>();
|
|
||||||
rs.map((r) => {
|
|
||||||
const vs = modelToSubdecks.get(r.modelName) || {};
|
|
||||||
const { value } = r.fields[KANJI_FIELD] || {};
|
|
||||||
if (value) {
|
|
||||||
// Get the subdeck names from Kanji
|
|
||||||
let subdeck = '';
|
|
||||||
let level = 0;
|
|
||||||
|
|
||||||
Array.from(value).map((k) => {
|
|
||||||
const m = kanjiLevels.get(k);
|
|
||||||
if (m && m.level > level) {
|
|
||||||
level = m.level;
|
|
||||||
subdeck = m.deckName;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (subdeck) {
|
|
||||||
const cardIds = vs[subdeck] || [];
|
|
||||||
cardIds.push(r.cardId);
|
|
||||||
vs[subdeck] = cardIds;
|
|
||||||
|
|
||||||
modelToSubdecks.set(r.modelName, vs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(
|
|
||||||
Array.from(modelToSubdecks).map(([modelName, subdecks]) =>
|
|
||||||
anki.api('modelTemplates', { modelName }).then((templates) =>
|
|
||||||
Object.entries(subdecks).map(([subdeck, cardIds]) => ({
|
|
||||||
modelName,
|
|
||||||
templateNames: Object.keys(templates),
|
|
||||||
subdeck,
|
|
||||||
cardIdsSet: new Set(cardIds),
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then(async (rs) => {
|
|
||||||
const remaining: {
|
|
||||||
[templateName: string]: Set<number>;
|
|
||||||
} = {};
|
|
||||||
|
|
||||||
const cardsByTemplateName = {
|
|
||||||
data: new Map<string, number[]>(),
|
|
||||||
async get(templateName: string) {
|
|
||||||
let v = this.data.get(templateName);
|
|
||||||
if (!v) {
|
|
||||||
v = await anki.api('findCards', {
|
|
||||||
query: `${deckQuery} card:${templateName}`,
|
|
||||||
});
|
|
||||||
remaining[templateName] = new Set(v);
|
|
||||||
}
|
|
||||||
this.data.set(templateName, v);
|
|
||||||
return v;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const toChangeDeck: IAnkiConnectActions['changeDeck']['params'][] = [];
|
|
||||||
|
|
||||||
for (const { templateName, subdeck, cardIdsSet } of rs
|
|
||||||
.flat()
|
|
||||||
.flatMap((r) =>
|
|
||||||
r.templateNames.map((templateName) => ({
|
|
||||||
...r,
|
|
||||||
templateName,
|
|
||||||
})),
|
|
||||||
)) {
|
|
||||||
const cards = await cardsByTemplateName.get(templateName);
|
|
||||||
|
|
||||||
toChangeDeck.push({
|
|
||||||
cards: cards.filter((c) => {
|
|
||||||
const r = remaining[templateName];
|
|
||||||
if (r) {
|
|
||||||
r.delete(c);
|
|
||||||
}
|
|
||||||
return cardIdsSet.has(c);
|
|
||||||
}),
|
|
||||||
deck: `${DECK}::${subdeck}::${templateName}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.entries(remaining).map(([templateName, cards]) => {
|
|
||||||
if (cards.size) {
|
|
||||||
toChangeDeck.push({
|
|
||||||
cards: [...cards],
|
|
||||||
deck: `${DECK}::独習::${templateName}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (toChangeDeck.length) {
|
|
||||||
const batchSize = 20;
|
|
||||||
for (let i = 0; i < toChangeDeck.length; i += batchSize) {
|
|
||||||
await Promise.all(
|
|
||||||
toChangeDeck
|
|
||||||
.slice(i, i + batchSize)
|
|
||||||
.map((params) => anki.api('changeDeck', params)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await anki.api('setDeckConfigId', {
|
|
||||||
decks: toChangeDeck.map((r) => r.deck),
|
|
||||||
configId: deckConfig.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
|
|||||||
@@ -3,3 +3,9 @@ export interface ILevelLabel {
|
|||||||
ja: string;
|
ja: string;
|
||||||
en: string;
|
en: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ILevelMap {
|
||||||
|
[category: string]: {
|
||||||
|
[levelString: string]: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
+207
-3
@@ -1,15 +1,21 @@
|
|||||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||||
|
|
||||||
import axios, { AxiosInstance } from 'axios';
|
import axios, { AxiosInstance } from 'axios';
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
import { soundTag } from './anki';
|
import { soundTag } from './anki';
|
||||||
import { AnkiConnect, IAnkiConnectActions } from './ankiconnect';
|
import { AnkiConnect, IAnkiConnectActions } from './ankiconnect';
|
||||||
import { ILevelLabel } from './level';
|
import { ILevelLabel, ILevelMap } from './level';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
|
|
||||||
export class WaniKani {
|
export class WaniKani {
|
||||||
$axios: AxiosInstance;
|
$axios: AxiosInstance;
|
||||||
|
|
||||||
|
static files = {
|
||||||
|
wanikani: 'cache/wanikani.json',
|
||||||
|
beyond: 'assets/beyond.yaml',
|
||||||
|
};
|
||||||
|
|
||||||
constructor(public apiKey = process.env['WANIKANI_API_KEY']) {
|
constructor(public apiKey = process.env['WANIKANI_API_KEY']) {
|
||||||
this.$axios = axios.create({
|
this.$axios = axios.create({
|
||||||
baseURL: 'https://api.wanikani.com/v2/',
|
baseURL: 'https://api.wanikani.com/v2/',
|
||||||
@@ -68,7 +74,7 @@ export class WaniKani {
|
|||||||
} = {}) {
|
} = {}) {
|
||||||
const subjects = {
|
const subjects = {
|
||||||
data: [] as ISubject[],
|
data: [] as ISubject[],
|
||||||
filename: 'cache/wanikani.json',
|
filename: WaniKani.files.wanikani,
|
||||||
load() {
|
load() {
|
||||||
this.data = existsSync(this.filename)
|
this.data = existsSync(this.filename)
|
||||||
? JSON.parse(readFileSync(this.filename, 'utf-8'))
|
? JSON.parse(readFileSync(this.filename, 'utf-8'))
|
||||||
@@ -109,6 +115,204 @@ export class WaniKani {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async sortByLevels(
|
||||||
|
deck: string,
|
||||||
|
fields: { ja: string },
|
||||||
|
opts: {
|
||||||
|
/**
|
||||||
|
* Whether to use Level > 60, i.e. outside WaniKani
|
||||||
|
*
|
||||||
|
* @link https://community.wanikani.com/t/fake-levels-61-70-or-%E7%84%A1%E9%99%90-infinity/16399
|
||||||
|
*/
|
||||||
|
useBeyond?: boolean;
|
||||||
|
} = {},
|
||||||
|
) {
|
||||||
|
const anki = new AnkiConnect();
|
||||||
|
|
||||||
|
const deckConfig = await anki.api('getDeckConfig', {
|
||||||
|
deck,
|
||||||
|
});
|
||||||
|
|
||||||
|
const deckQuery = `deck:${deck} -deck:${deck}::*`;
|
||||||
|
|
||||||
|
const wkLevelMap: ILevelMap = {};
|
||||||
|
const wkKanji = await this.subjects().then(
|
||||||
|
(vs) => vs.filter((v) => v.object === 'kanji') as IKanji[],
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const k of wkKanji) {
|
||||||
|
const { level, characters } = k.data;
|
||||||
|
const label = WaniKani.getLevelLabel(level);
|
||||||
|
if (!label) throw new Error(`Invalid level: ${level}`);
|
||||||
|
|
||||||
|
const category = `${label.range}: ${
|
||||||
|
label.ja
|
||||||
|
} ${label.en.toLocaleUpperCase()}`;
|
||||||
|
|
||||||
|
const catMap = wkLevelMap[category] || {};
|
||||||
|
const levelString = level.toString().padStart(2, '0');
|
||||||
|
|
||||||
|
const ks = catMap[levelString] || [];
|
||||||
|
ks.push(characters);
|
||||||
|
catMap[levelString] = ks;
|
||||||
|
|
||||||
|
wkLevelMap[category] = catMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const beyond = opts.useBeyond
|
||||||
|
? (yaml.load(readFileSync(WaniKani.files.beyond, 'utf-8')) as ILevelMap)
|
||||||
|
: {};
|
||||||
|
|
||||||
|
const kanjiLevels = new Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
level: number;
|
||||||
|
deckName: string;
|
||||||
|
}
|
||||||
|
>();
|
||||||
|
|
||||||
|
const setKanjiToLevel = (lvMap: ILevelMap) => {
|
||||||
|
Object.entries(lvMap).map(([cat, map]) => {
|
||||||
|
Object.entries(map).map(([levelString, ks]) => {
|
||||||
|
const level = Number(levelString);
|
||||||
|
ks.map((k) => {
|
||||||
|
let prev = kanjiLevels.get(k);
|
||||||
|
if (!prev || prev.level > level) {
|
||||||
|
prev = {
|
||||||
|
level,
|
||||||
|
deckName: cat + '::' + levelString,
|
||||||
|
};
|
||||||
|
kanjiLevels.set(k, prev);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
setKanjiToLevel(wkLevelMap);
|
||||||
|
setKanjiToLevel(beyond);
|
||||||
|
|
||||||
|
await anki
|
||||||
|
.api('findCards', {
|
||||||
|
query: deckQuery,
|
||||||
|
})
|
||||||
|
.then((cards) => anki.api('cardsInfo', { cards }))
|
||||||
|
.then(async (rs) => {
|
||||||
|
const modelToSubdecks = new Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
[subdeck: string]: number[];
|
||||||
|
}
|
||||||
|
>();
|
||||||
|
rs.map((r) => {
|
||||||
|
const vs = modelToSubdecks.get(r.modelName) || {};
|
||||||
|
const { value } = r.fields[fields.ja] || {};
|
||||||
|
if (value) {
|
||||||
|
// Get the subdeck names from Kanji
|
||||||
|
let subdeck = '';
|
||||||
|
let level = 0;
|
||||||
|
|
||||||
|
Array.from(value).map((k) => {
|
||||||
|
const m = kanjiLevels.get(k);
|
||||||
|
if (m && m.level > level) {
|
||||||
|
level = m.level;
|
||||||
|
subdeck = m.deckName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (subdeck) {
|
||||||
|
const cardIds = vs[subdeck] || [];
|
||||||
|
cardIds.push(r.cardId);
|
||||||
|
vs[subdeck] = cardIds;
|
||||||
|
|
||||||
|
modelToSubdecks.set(r.modelName, vs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
Array.from(modelToSubdecks).map(([modelName, subdecks]) =>
|
||||||
|
anki.api('modelTemplates', { modelName }).then((templates) =>
|
||||||
|
Object.entries(subdecks).map(([subdeck, cardIds]) => ({
|
||||||
|
modelName,
|
||||||
|
templateNames: Object.keys(templates),
|
||||||
|
subdeck,
|
||||||
|
cardIdsSet: new Set(cardIds),
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.then(async (rs) => {
|
||||||
|
const remaining: {
|
||||||
|
[templateName: string]: Set<number>;
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
const cardsByTemplateName = {
|
||||||
|
data: new Map<string, number[]>(),
|
||||||
|
async get(templateName: string) {
|
||||||
|
let v = this.data.get(templateName);
|
||||||
|
if (!v) {
|
||||||
|
v = await anki.api('findCards', {
|
||||||
|
query: `${deckQuery} card:${templateName}`,
|
||||||
|
});
|
||||||
|
remaining[templateName] = new Set(v);
|
||||||
|
}
|
||||||
|
this.data.set(templateName, v);
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const toChangeDeck: IAnkiConnectActions['changeDeck']['params'][] = [];
|
||||||
|
|
||||||
|
for (const { templateName, subdeck, cardIdsSet } of rs
|
||||||
|
.flat()
|
||||||
|
.flatMap((r) =>
|
||||||
|
r.templateNames.map((templateName) => ({
|
||||||
|
...r,
|
||||||
|
templateName,
|
||||||
|
})),
|
||||||
|
)) {
|
||||||
|
const cards = await cardsByTemplateName.get(templateName);
|
||||||
|
|
||||||
|
toChangeDeck.push({
|
||||||
|
cards: cards.filter((c) => {
|
||||||
|
const r = remaining[templateName];
|
||||||
|
if (r) {
|
||||||
|
r.delete(c);
|
||||||
|
}
|
||||||
|
return cardIdsSet.has(c);
|
||||||
|
}),
|
||||||
|
deck: `${deck}::${subdeck}::${templateName}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.entries(remaining).map(([templateName, cards]) => {
|
||||||
|
if (cards.size) {
|
||||||
|
toChangeDeck.push({
|
||||||
|
cards: [...cards],
|
||||||
|
deck: `${deck}::独習::${templateName}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (toChangeDeck.length) {
|
||||||
|
const batchSize = 20;
|
||||||
|
for (let i = 0; i < toChangeDeck.length; i += batchSize) {
|
||||||
|
await Promise.all(
|
||||||
|
toChangeDeck
|
||||||
|
.slice(i, i + batchSize)
|
||||||
|
.map((params) => anki.api('changeDeck', params)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await anki.api('setDeckConfigId', {
|
||||||
|
decks: toChangeDeck.map((r) => r.deck),
|
||||||
|
configId: deckConfig.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async populateSound(
|
async populateSound(
|
||||||
query: string,
|
query: string,
|
||||||
fields: {
|
fields: {
|
||||||
@@ -236,7 +440,7 @@ export class WaniKani {
|
|||||||
|
|
||||||
query += ` -${fields.vocabJa}:`;
|
query += ` -${fields.vocabJa}:`;
|
||||||
if (fields.sentenceAudio) {
|
if (fields.sentenceAudio) {
|
||||||
query += ` -${fields.sentenceAudio}:`;
|
query += ` ${fields.sentenceAudio}:`;
|
||||||
}
|
}
|
||||||
if (!opts.overwrite) {
|
if (!opts.overwrite) {
|
||||||
query += ` -${fields.sentenceJa}: -${fields.sentenceEn}:`;
|
query += ` -${fields.sentenceJa}: -${fields.sentenceEn}:`;
|
||||||
|
|||||||
Reference in new issue
Block a user