From 07d157604d02aad6e3a0614bbafafb7adf1e486a Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Wed, 11 Sep 2024 05:16:53 +0200 Subject: [PATCH] Saving EXIF data for jpegs. --- config/default.js | 17 ++++++----- package-lock.json | 61 ++++++++++++++++++++++++++++++++++++ package.json | 2 ++ src/fetch/content.js | 73 ++++++++++++++++++++++++++++++-------------- src/interpolate.js | 11 ++++--- 5 files changed, 129 insertions(+), 35 deletions(-) diff --git a/config/default.js b/config/default.js index 4671ddc..3757a17 100644 --- a/config/default.js +++ b/config/default.js @@ -1,17 +1,17 @@ module.exports = { library: { base: 'output/$user/', - image: '$postDate - $itemId - $postTitle$ext', - video: '$postDate - $itemId - $postTitle$ext', - text: '$postDate - $postId - $postTitle', + image: '$base$postDate - $itemId - $postTitle$ext', + video: '$base$postDate - $itemId - $postTitle$ext', + text: '$base$postDate - $postId - $postTitle', album: { extractSingleItem: true, - image: '$postDate - $albumId - $postTitle/$itemIndex - $itemId$ext', - video: '$postDate - $albumId - $postTitle/$itemIndex - $itemId$ext' + image: '$base$postDate - $albumId - $postTitle/$itemIndex - $itemId$ext', + video: '$base$postDate - $albumId - $postTitle/$itemIndex - $itemId$ext' }, profile: { - image: '$userCreated - profile$ext', - description: '$userCreated - profile ($userVerified$userVerifiedEmail$userGold$profileOver18)' + image: '$base$userCreated - profile$ext', + description: '$base$userCreated - profile ($userVerified$userVerifiedEmail$userGold$profileOver18)' }, booleans: { extracted: 'extracted-', @@ -20,6 +20,9 @@ module.exports = { gold: '★', over18: '♥' }, + meta: { + comment: '$itemDescription' + }, dateFormat: 'YYYYMMDD', titleLength: 200, indexOffset: 1, diff --git a/package-lock.json b/package-lock.json index f943f67..88c976e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -87,6 +87,11 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "catchment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/catchment/-/catchment-1.0.0.tgz", + "integrity": "sha1-MGH3G+AQJxC+hDKNL5Q2OhZfjEs=" + }, "cheerio": { "version": "1.0.0-rc.2", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", @@ -209,6 +214,16 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "dist-exiftool": { + "version": "10.53.0", + "resolved": "https://registry.npmjs.org/dist-exiftool/-/dist-exiftool-10.53.0.tgz", + "integrity": "sha1-i9F7rB5D3qzYHZrazQ8eJMaQEA8=", + "requires": { + "exiftool.exe": "10.53.0", + "exiftool.pl": "10.53.0", + "platform-dependent-modules": "0.0.14" + } + }, "dom-serializer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", @@ -275,6 +290,18 @@ "strip-eof": "1.0.0" } }, + "exiftool.exe": { + "version": "10.53.0", + "resolved": "https://registry.npmjs.org/exiftool.exe/-/exiftool.exe-10.53.0.tgz", + "integrity": "sha1-IrHOYPuNtYlGnRqlsKH+CaNbxFQ=", + "optional": true + }, + "exiftool.pl": { + "version": "10.53.0", + "resolved": "https://registry.npmjs.org/exiftool.pl/-/exiftool.pl-10.53.0.tgz", + "integrity": "sha1-Y8FkazrQrtHOExPXtdB9pNexPYQ=", + "optional": true + }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", @@ -525,6 +552,11 @@ "yallist": "2.1.2" } }, + "makepromise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/makepromise/-/makepromise-1.0.0.tgz", + "integrity": "sha1-vGu2o+Bv1wbfUcKSO2k2+r1wqn8=" + }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", @@ -551,6 +583,16 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, + "node-exiftool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-exiftool/-/node-exiftool-2.3.0.tgz", + "integrity": "sha1-1RQtNN5vFoO0ZVGYtkjn4+5ugKw=", + "requires": { + "is-stream": "1.1.0", + "restream": "1.2.0", + "wrote": "0.6.1" + } + }, "node-fetch": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", @@ -651,6 +693,11 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "platform-dependent-modules": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/platform-dependent-modules/-/platform-dependent-modules-0.0.14.tgz", + "integrity": "sha1-PFPQQV2BziLc/eFWZdDP1UHUFhc=" + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -742,6 +789,11 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, + "restream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/restream/-/restream-1.2.0.tgz", + "integrity": "sha1-/ROwMaVOgMxl0YeMQxSfGzpA77s=" + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -952,6 +1004,15 @@ } } }, + "wrote": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/wrote/-/wrote-0.6.1.tgz", + "integrity": "sha1-7/Ee/dbxhCSnC66i30Mirzdbj74=", + "requires": { + "catchment": "1.0.0", + "makepromise": "1.0.0" + } + }, "ws": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", diff --git a/package.json b/package.json index 3bbe7fe..f38377d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,9 @@ "cheerio": "^1.0.0-rc.2", "config": "^1.30.0", "date-fns": "^1.29.0", + "dist-exiftool": "^10.53.0", "fs-extra": "^5.0.0", + "node-exiftool": "^2.3.0", "node-fetch": "^2.1.2", "snoowrap": "^1.15.2", "url-pattern": "^1.0.3", diff --git a/src/fetch/content.js b/src/fetch/content.js index ebbd4be..5ac2b04 100644 --- a/src/fetch/content.js +++ b/src/fetch/content.js @@ -8,32 +8,59 @@ const fetchItem = require('./item.js'); const interpolate = require('../interpolate.js'); const save = require('../save/save.js'); const textToStream = require('../save/textToStream.js'); +const saveMeta = require('../save/meta.js'); + +const exiftool = require('node-exiftool'); +const exiftoolBin = require('dist-exiftool'); + +const ep = new exiftool.ExiftoolProcess(exiftoolBin); module.exports = function(posts, user) { - return Promise.all(posts.map(post => { - return Promise.resolve().then(() => { - return Promise.all(post.content.items.map((item, index) => { - item.index = index; + return Promise.resolve().then(() => { + return ep.open(); + }).then(() => { + return Promise.all(posts.map(post => { + return Promise.resolve().then(() => { + return Promise.all(post.content.items.map((item, index) => { + item.index = index; - if(item.self) { - return Object.assign({}, item, {stream: textToStream(item.text)}); - } + if(item.self) { + return Object.assign({}, item, {stream: textToStream(item.text)}); + } - return fetchItem(item.url, 0).then(stream => { - return Object.assign({}, item, {stream}); - }); - })); - }).then(items => { - return Promise.all(items.map(item => { - const type = item.type.split('/')[0]; - const filepath = post.content.album ? interpolate(config.library.album[type], user, post, item) : interpolate(config.library[type], user, post, item); + return fetchItem(item.url, 0).then(stream => { + return Object.assign({}, item, {stream}); + }); + })); + }).then(items => { + return Promise.all(items.map(item => { + const type = item.type.split('/')[0]; + const filepath = post.content.album ? interpolate(config.library.album[type], user, post, item) : interpolate(config.library[type], user, post, item); - return Promise.resolve().then(() => { - return fs.ensureDir(path.dirname(filepath)); - }).then(() => { - return save(filepath, item.stream) - }); - })); - }); - })); + return Promise.resolve().then(() => { + return fs.ensureDir(path.dirname(filepath)); + }).then(() => { + return save(filepath, item.stream); + }).then(() => { + const interpolatedMeta = Object.entries(config.library.meta).reduce((acc, [key, value]) => { + acc[key] = interpolate(value, user, post, item); + + return acc; + }, {}); + + if(Object.keys(interpolatedMeta).length > 0) { + return saveMeta(filepath, { + comment: item.description + }, ep); + } + }); + })); + }); + })); + }).then(() => { + console.log('closing...'); + return ep.close(); + }).catch(error => { + return ep.close(); + }); }; diff --git a/src/interpolate.js b/src/interpolate.js index cfa746a..70e3755 100644 --- a/src/interpolate.js +++ b/src/interpolate.js @@ -14,11 +14,10 @@ const extensions = { function interpolate(pattern, user, post, item) { const dateFormat = config.library.dateFormat || 'YYYYMMDD'; - const vars = {}; - if(config.library.base) { - pattern = path.join(config.library.base, pattern); - } + const vars = { + $base: config.library.base + }; if(user) { Object.assign(vars, { @@ -76,7 +75,9 @@ function interpolate(pattern, user, post, item) { return Object.entries(vars).reduce((acc, [key, value], index) => { // substitute slashes for filesystem compatability - value = (value || '').toString().replace(/\//g, config.library.slashSubstitute); + if(key !== '$base') { + value = (value || '').toString().replace(/\//g, config.library.slashSubstitute); + } return acc.replace(key, value); }, pattern);