diff --git a/package.json b/package.json index 33c03c7..3b2671a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,8 @@ "request": "^2.88.0", "sanitize-filename": "^1.6.1", "sanitize-html": "^1.18.5", - "tippy.js": "^2.1.1" + "tippy.js": "^2.1.1", + "webp-converter": "^2.3.3" }, "devDependencies": { "autoprefixer": "^8.1.0", diff --git a/public/app/js/basic.js b/public/app/js/basic.js index cc80a53..305b6c0 100644 --- a/public/app/js/basic.js +++ b/public/app/js/basic.js @@ -27,7 +27,8 @@ const xhr = function(options, callback) { } callback(null, { statusCode: this.status, - requestUrl: url + requestUrl: url, + contentType: req.getResponseHeader('Content-Type') }, response); }; @@ -39,7 +40,6 @@ const xhr = function(options, callback) { }; req.open("get", url, true); - if (headers) { for (key in headers) { req.setRequestHeader(key, headers[key]) diff --git a/public/app/js/cbus-data.js b/public/app/js/cbus-data.js index 6021856..f00488e 100644 --- a/public/app/js/cbus-data.js +++ b/public/app/js/cbus-data.js @@ -187,13 +187,16 @@ cbus.data.subscribeFeeds = function(datas, options) { var doneCount = 0; - function gotPodcastImage(data, imageBuffer) { - Jimp.read(Buffer.from(imageBuffer), function(err, image) { - if (err) throw err + function resizePodcastImage(data, imageObject) { + Jimp.read(imageObject, function(err, image) { + if (err) { + console.log("Error with resizePodcastImage", err, err.name); + throw err; + } image.resize(cbus.const.PODCAST_ART_SIZE, cbus.const.PODCAST_ART_SIZE).write( path.join(cbus.const.PODCAST_IMAGES_DIR.replace(/\\/g,"/"), sha1(data.url) + ".png"), function(err) { - if (err) throw err + if (err) throw err; cbus.data.feeds.push({ image: cbus.const.IMAGE_ON_DISK_PLACEHOLDER, title: data.title, @@ -251,6 +254,29 @@ cbus.data.subscribeFeeds = function(datas, options) { }); } + function gotPodcastImage(data, imageBuffer, contentType) { + // Jimp can't handle image/webp, and it's not always possible to retrieve another image content type. + // So use webp-converter to convert it to PNG first. + if (contentType === "image/webp") { + fs.writeFile(__dirname+"/tmp.webp", Buffer.from(imageBuffer), function(err) { + if (err) { + console.log("Error unable to write ", __dirname+"/tmp.webp"); + throw err; + } + }); + const webp = require('webp-converter'); + let result = webp.dwebp(__dirname+"/tmp.webp", __dirname+"/tmp.png", "-o"); // Convert to tmp.webp -> tmp.png + result.then((response) => { + fs.unlink(__dirname+"/tmp.webp", () => {}); // Remove tmp.webp + resizePodcastImage(data, __dirname+'/tmp.png'); // Read tmp.png for jimp + fs.unlink(__dirname+"/tmp.png", () => {}); // Remove tmp.png + }); + } + else { + resizePodcastImage(data, Buffer.from(imageBuffer)); + } + } + for (let i = 0; i < datas.length; i++) { let data = datas[i]; @@ -267,6 +293,7 @@ cbus.data.subscribeFeeds = function(datas, options) { if (!isDuplicate) { xhr({ url: data.image, + headers: {'Accept': 'image/png, image/jpg'}, responseType: "arraybuffer" }, (err, response, imageBuffer) => { if (err || statusCodeNotOK(response.statusCode) || !imageBuffer) { @@ -274,10 +301,10 @@ cbus.data.subscribeFeeds = function(datas, options) { url: cbus.const.IMAGE_MISSING_PLACEHOLDER_PATH, responseType: "arraybuffer" }, (err, response, imageBuffer) => { - gotPodcastImage(data, imageBuffer); + gotPodcastImage(data, imageBuffer, response.contentType); }); } else { - gotPodcastImage(data, imageBuffer); + gotPodcastImage(data, imageBuffer, response.contentType); } }); } else if (showModal) { @@ -812,7 +839,7 @@ cbus.broadcast.listen("updateFeedArtworks", function(e) { doneCount++; if (doneCount === end - start) { localforage.setItem("cbus_feeds", cbus.data.feeds); - if (e.data.callback) { + if (e.data && e.data.callback) { e.data.callback(cbus.data.feeds.slice(start, end)); } } diff --git a/public/licenses.html b/public/licenses.html index c6abbc4..294c0ae 100644 --- a/public/licenses.html +++ b/public/licenses.html @@ -849,6 +849,32 @@
The MIT License (MIT) + +Copyright (c) 2021 Sai Kumar Yava + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +