Skip to content

Commit

Permalink
Implement log levels, more logs
Browse files Browse the repository at this point in the history
  • Loading branch information
BartBucknill committed Apr 18, 2020
1 parent 06e40a1 commit 00c29b6
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 34 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

Create quiz entries inside Joplin notes and auto import them as notes into Anki. Currently WIP.

**Known Issues**
## Known Issues

- Anki note browser should be closed during import; if open, _updates to note fields_ will not appear as expected.
- Anki note browser should be closed during import; if open, **updates to note fields will not appear as expected**
- For markdown to render in the Default template `Answer` field a newline is needed after the `</summary>` tag
- Syncing images included in questions into Anki is slow

**TODO**
## TODO

- [x] Convert markdown from Joplin to HTML in Anki.
- [x] Implement basic cli for configuring with params: urls, Joplin token, last export date. Store as config.
- [x] Get/update last export date as config.
- [ ] Improve logging: log levels exposed in cli, log summary of export / import.
- [x] Improve logging: log levels exposed in cli, log summary of export / import.
- [ ] Document usage.
9 changes: 4 additions & 5 deletions anki-client.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
const rp = require("request-promise-native");
const { newLogger } = require("./log");
const { levelApplication, levelVerbose, levelDebug } = require("./log");

const healthyPingResponse = "AnkiConnect v.6";
//TODO: these should not be at the client level
const modelName = "Joplin to Anki";
const deckName = "Joplin to Anki";

const newClient = (url, debug) => {
const newClient = (url, log) => {
return {
url,
log: newLogger(debug),
log,

formatTag(string) {
return string.replace(/ /g, "_");
Expand Down Expand Up @@ -190,7 +189,7 @@ const newClient = (url, debug) => {
`Did not receive expected response from Anki Connect API at ${env.ANKI_URL}\nResponse: ${result}\nExiting.`
);
}
this.log("Anki Connect API Healthy");
this.log(levelVerbose, "Anki Connect API Healthy");
},
};
};
Expand Down
10 changes: 7 additions & 3 deletions cli.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { program } = require("commander");
const jta = require("./joplin-to-anki");
const configStore = require("./config");
const { levelApplication, levelVerbose, levelDebug } = require("./log");

program.version("0.0.0");

Expand All @@ -24,10 +25,12 @@ program
"-a, --ankiurl <URL>",
"URL for Anki Connect API",
configStore.getWithFallback("ankiURL")
)
.option(
`-l, --loglevel <one of ${levelApplication}, ${levelVerbose}, ${levelDebug}>`,
"Enable verbose logs",
levelApplication
);
//TODO
// .option("-v, --verbose", "Enable verbose logs")
// .option("--debug", "Enable debug logs (verbose logs and more)")

program
.command("run")
Expand All @@ -40,6 +43,7 @@ program
.action(async () => {
const now = new Date().toISOString();
await jta.run(
program.loglevel,
program.joplinurl,
program.joplintoken,
program.date,
Expand Down
6 changes: 4 additions & 2 deletions integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ const dotenv = require("dotenv");

const assert = require("assert");
const { parsed: env } = dotenv.config();
const jClient = joplin.newClient(env.JOPLIN_URL, env.JOPLIN_TOKEN, true);
const aClient = anki.newClient(env.ANKI_URL, true);
const { newLogger, levelDebug } = require("./log");
const log = newLogger(levelDebug);
const jClient = joplin.newClient(env.JOPLIN_URL, env.JOPLIN_TOKEN, log);
const aClient = anki.newClient(env.ANKI_URL, log);
const fromDate = new Date().toISOString();

describe("Joplin to Anki integration", function () {
Expand Down
10 changes: 5 additions & 5 deletions joplin-client.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const rp = require("request-promise-native");
const { newLogger } = require("./log");
const { levelApplication, levelVerbose, levelDebug } = require("./log");

const healthyPingResponse = "JoplinClipperServer";

const newClient = (url, token, debug) => {
const newClient = (url, token, log) => {
if (!url) {
throw new Error("No url for Joplin Api provided");
}
Expand All @@ -13,7 +13,7 @@ const newClient = (url, token, debug) => {
return {
url,
token,
log: newLogger(debug),
log,
ping() {
return rp(this.urlGen("ping"));
},
Expand All @@ -34,7 +34,7 @@ const newClient = (url, token, debug) => {
request(url, method, body, fields, parseJSON = true, encoding) {
const params = this.paramsGen(fields);
const options = { method, uri: url + params, json: parseJSON };
this.log(`Request options: ${JSON.stringify(options)}`);
this.log(levelDebug, `Request options: ${JSON.stringify(options)}`);
if (body) {
options.body = body;
}
Expand All @@ -51,7 +51,7 @@ const newClient = (url, token, debug) => {
`Did not receive expected response from Joplin Web Clipper API at ${this.url}/ping\nResponse: ${response}\nExiting.`
);
}
this.log("Joplin API Healthy");
this.log(levelVerbose, "Joplin API Healthy");
},
};
};
Expand Down
1 change: 0 additions & 1 deletion joplin-exporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ async function* exporter(client, datetime) {
yield {
type: typeResource,
data: {
//TODO: use combo of id and filename to avoid risk from images with same filename
fileName: resource.fileName,
data: Buffer.from(file, "binary").toString("base64"),
},
Expand Down
64 changes: 54 additions & 10 deletions joplin-to-anki.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,23 @@ const {
const { importer } = require("./anki-importer");
const joplin = require("./joplin-client");
const anki = require("./anki-client");
const { newLogger } = require("./log");
const log = newLogger(true);
const {
newLogger,
levelApplication,
levelVerbose,
levelDebug,
} = require("./log");

const run = async (joplinURL, joplinToken, exportFromDate, ankiURL) => {
const jClient = joplin.newClient(joplinURL, joplinToken, true);
const aClient = anki.newClient(ankiURL, true);
const run = async (
logLevel,
joplinURL,
joplinToken,
exportFromDate,
ankiURL
) => {
const log = newLogger(logLevel);
const jClient = joplin.newClient(joplinURL, joplinToken, log);
const aClient = anki.newClient(ankiURL, log);
await jClient.health();
await aClient.health();

Expand All @@ -27,9 +38,21 @@ const run = async (joplinURL, joplinToken, exportFromDate, ankiURL) => {
}

const gen = exporter(jClient, exportFromDate);
const summary = {
items: 0,
itemsSuccess: 0,
resources: 0,
resourcesSuccess: 0,
errorCount: 0,
};
for await (const value of gen) {
switch (value.type) {
case typeItem:
summary.items++;
log(
levelVerbose,
`Syncing question \"${value.data.question}\" from note \"${value.data.title}\"`
);
try {
await importer(
aClient,
Expand All @@ -40,29 +63,50 @@ const run = async (joplinURL, joplinToken, exportFromDate, ankiURL) => {
value.data.notebook,
value.data.tags
);
summary.itemsSuccess++;
} catch (error) {
log(`Problem importing note to Anki: ${error}`);
log(levelApplication, `Problem importing note to Anki: ${error}`);
}
break;
case typeResource:
summary.resources++;
log(levelVerbose, `Syncing resource \"${value.data.fileName}\"`);
try {
await aClient.storeMedia(value.data.fileName, value.data.data);
summary.resourcesSuccess++;
} catch (error) {
log(`Problem importing media to Anki: ${error}`);
log(levelApplication, `Problem importing media to Anki: ${error}`);
}
break;
case typeError:
log(`Problem occurred exporting a note from Joplin: ${value.data}`);
summary.errorCount++;
log(
levelApplication,
`Problem occurred exporting a note from Joplin: ${value.data}`
);
break;
default:
log(
levelDebug,
`Hit default case in exporter which should not happen! Item: ${value}`
);
break;
}
}

console.log("DONE");
log(
levelApplication,
`
Found ${summary.items} JTA items in Joplin notes updated since last run.
Imported ${summary.itemsSuccess} to Anki; ${
summary.itemsSuccess - summary.items
} failures.
Found ${summary.resources} resources attached to JTA items.
Imported ${summary.resourcesSuccess} to Anki; ${
summary.resourcesSuccess - summary.resources
} failures.
`
);
log(levelApplication, "DONE");
};

module.exports = {
Expand Down
23 changes: 19 additions & 4 deletions log.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
const newLogger = function (debug) {
return (msg) => {
if (!!debug) {
const levelDebug = "debug";
const levelVerbose = "verbose";
const levelApplication = "application";
function newLogger(logLevel) {
return (level, msg) => {
if (level == logLevel) {
console.log(msg);
return;
}
if (logLevel == levelVerbose && level == levelApplication) {
console.log(msg);
return;
}
if (logLevel == levelDebug) {
console.log(msg);
return;
}
};
};
}

module.exports = {
newLogger,
levelDebug,
levelVerbose,
levelApplication,
};

0 comments on commit 00c29b6

Please sign in to comment.