From: Elias Fleckenstein Date: Sat, 4 Jun 2022 14:58:22 +0000 (+0200) Subject: Generic stats and select X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=HEAD;p=local-nhentai.git Generic stats and select --- diff --git a/README.md b/README.md index 0ae9f18..7f08e47 100644 --- a/README.md +++ b/README.md @@ -16,25 +16,22 @@ Remember to install NPM deps: `npm install` `nhentai --id ${id}`: Download a doujin. -`node symlinks.js`: Updates symlinks. Must be run whenever new doujins have been added, otherwise they will not be seen by the other scripts. - -`node select.js`: Open fzf/überzug menu to select a doujin. Shows a list of tags first. When a tag is selected, shows all doujins with that tag and lets the user select one, displaying the thumbnails of the doujins at the side. The "\*" tag can be used to search/select from all doujins. +`node select.js`: Open fzf/überzug menu to select a doujin. `node multiple-tags.js ...`: Open fzf/überzug menu with doujins that match all given tags (tags separated by whitespace). `node stats-doujins.js`: Displays number of downloaded doujins, total size and average size per doujin -`node stats-tags.js`: Displays tags sorted by how many doujins are available for each tag. May produce long output, you might want to pipe it into `head`, `grep` or `less`. +`node stats.js `: Displays tags, artists, characters, parodies or groups sorted by how many doujins are available for each. May produce long output, you might want to pipe it into `head`, `grep` or `less`. `node scrape-wholesome.js`: Scrapes [wholesome hentais](https://wholesomelist.com/list). This takes a long time since it's about 2700 hentais in total (consumes about 32GB of disk space), but you can abort it any time (and resume it later). -`node scrape.js `: Scrapes doujins by criterium, where criterium can be tag, artist, character, parody or group and value is the value. E.g. `node scrape.js tag full-color` scrapes fully colored doujins. +`node scrape-links.js `: Scrapes doujins by criterium, where criterium can be tag, artist, character, parody or group and value is the value. E.g. `node scrape-links.js tag full-color` scrapes fully colored doujins. Note: you might want to create a subdirectory and put the doujins into there, they will all be put into the current working directory. (Run the scripts from a different directory to prevent spamming this directory) -Of course, you can also run these scripts in a directory where you already downloaded doujins using the `nhentai` tool, but make sure to run the symlinks script to "register" them all in the system. - +Of course, you can also run these scripts in a directory where you already downloaded doujins using the `nhentai` tool. # Notes `./fzf-previews` taken from [fzf-ueberzogen](https://github.com/seebye/fzf-ueberzogen) with slight modifications. -Happy scraping and jerking! +Happy scraping! diff --git a/fzf.js b/fzf.js index ce9c9b4..27bb7c2 100644 --- a/fzf.js +++ b/fzf.js @@ -25,4 +25,3 @@ module.exports.fzf = (options, binary = "fzf") => { module.exports.doujin = doujins => module.exports.fzf(doujins.sort(), __dirname + "/fzf-previews") .then(doujin => child.spawn("firefox", [`file://${process.cwd()}/${doujin}/index.html`])) - .catch(_ => {}) diff --git a/info.js b/info.js index 95813b6..2d8382e 100644 --- a/info.js +++ b/info.js @@ -1,30 +1,34 @@ const fs = require("fs").promises +const criteriaKeys = ["tag", "group", "artist", "character", "parody"] module.exports.doujins = shortNames => fs.readdir(".", {encoding: "utf8", withFileTypes: true}) .then(doujins => doujins .map(dirent => fs.readFile(`${dirent.name}/metadata.json`) .then(data => JSON.parse(data.toString())) + .then(data => {data.title = dirent.name; return data}) .then(data => [dirent.name, data]) .catch(_ => []))) .then(promises => Promise.all(promises)) .then(doujins => doujins - .filter(([title, data]) => title && data) - .filter(([title, data]) => (title == data.title) == !shortNames)) + .filter(([title, data]) => title && data)) + //.filter(([title, data]) => (title == data.title) == !shortNames)) .then(doujins => Object.fromEntries(doujins)) -module.exports.tags = _ => { - const tags = {"*": []} +module.exports.criteria = _ => { + const criteria = Object.fromEntries(criteriaKeys.map(key => [key, {["*"]: []}])) return module.exports.doujins() .then(doujins => Object.values(doujins)) .then(doujins => doujins - .forEach(doujin => { - tags["*"].push(doujin.title) + .forEach(doujin => + criteriaKeys.forEach(crit => { + criteria[crit]["*"].push(doujin.title) - doujin.tag && doujin.tag.forEach(tag => { - tags[tag] = tags[tag] || [] - tags[tag].push(doujin.title) + doujin[crit] && doujin[crit].forEach(val => { + criteria[crit][val] = criteria[crit][val] || [] + criteria[crit][val].push(doujin.title) + }) }) - })) - .then(_ => tags) + )) + .then(_ => criteria) } diff --git a/select.js b/select.js index f8ec511..bf4c4f7 100644 --- a/select.js +++ b/select.js @@ -2,13 +2,26 @@ const fzf = require("./fzf") const info = require("./info") ;(async _ => { - const tags = await info.tags() + const criteria = await info.criteria() + let stage = 0 + let crt, val, dou - do { + while (true) { try { - tag = await fzf.fzf(Object.keys(tags).sort()) + switch (stage) { + case 0: + crt = await fzf.fzf(Object.keys(criteria).sort()); break + case 1: + val = await fzf.fzf(Object.keys(criteria[crt]).sort()); break + case 2: + dou = await fzf.doujin(Object.values(criteria[crt][val]).sort()); break + default: + return + } + + stage++ } catch { - return + stage-- } - } while (!await fzf.doujin(Object.values(tags[tag]).sort())) + } })() diff --git a/stats-doujins.js b/stats-doujins.js index 943c17c..47a25a1 100644 --- a/stats-doujins.js +++ b/stats-doujins.js @@ -1,7 +1,7 @@ const info = require("./info") const du = require("./du") -const fmt = (num, size) => +const fmt = (num, size) => `Number of doujins: ${num} Total size: ${(size / 1e9).toFixed(2)}GB Average size per doujin: ${(size / num / 1e6).toFixed(2)}MB` diff --git a/stats-tags.js b/stats-tags.js deleted file mode 100644 index 4278e27..0000000 --- a/stats-tags.js +++ /dev/null @@ -1,6 +0,0 @@ -require("./info").tags() - .then(tags => Object.entries(tags) - .sort((a, b) => b[1].length - a[1].length) - .forEach(elem => console.log(elem[1].length, elem[0])) - ) - .then(_ => {}) diff --git a/stats.js b/stats.js new file mode 100644 index 0000000..4cd97bd --- /dev/null +++ b/stats.js @@ -0,0 +1,7 @@ +require("./info").criteria() + .then(crits => crits[process.argv[2]]) + .then(crit => Object.entries(crit) + .sort((a, b) => b[1].length - a[1].length) + .forEach(elem => console.log(elem[1].length, elem[0])) + ) + .then(_ => {}) diff --git a/symlinks.js b/symlinks.js deleted file mode 100644 index e7ef204..0000000 --- a/symlinks.js +++ /dev/null @@ -1,10 +0,0 @@ -const fs = require("fs").promises -const info = require("./info") - -info.doujins(true) - .then(doujins => Object.entries(doujins)) - .then(doujins => doujins - .map(([dirname, data]) => - fs.symlink(dirname, data.title, "dir") - .then(_ => console.log(data.title)) - .catch(_ => {})))