mirror of
https://github.com/nsieg/MMM-piwigo-photo-wheel.git
synced 2025-04-18 17:14:41 -04:00
Initial commit
This commit is contained in:
commit
3994a1ca63
9 changed files with 2387 additions and 0 deletions
61
MMM-piwigo-photo-wheel.js
Normal file
61
MMM-piwigo-photo-wheel.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
Module.register("MMM-piwigo-photo-wheel", {
|
||||
defaults: {
|
||||
updateInterval: 60 * 60 * 1000,
|
||||
switchInterval: 10 * 1000,
|
||||
maxWidth: "250px",
|
||||
maxHeight: "333px",
|
||||
piwigoBaseUrl: "",
|
||||
piwigoUsername: "",
|
||||
piwigoPassword: "",
|
||||
piwigoSize: "large",
|
||||
loadingText: "Loading...",
|
||||
},
|
||||
|
||||
start: function () {
|
||||
this.imageFileNames = [];
|
||||
this.imageIndex = 0;
|
||||
setInterval(this.updateImages, this.config.updateInterval);
|
||||
setInterval(() => {
|
||||
this.imageIndex = (this.imageIndex + 1) % this.imageFileNames.length;
|
||||
this.updateDom();
|
||||
}, this.config.switchInterval);
|
||||
this.updateImages();
|
||||
},
|
||||
|
||||
socketNotificationReceived: function (notification, payload) {
|
||||
this.imageFileNames = payload;
|
||||
this.imageIndex = 0;
|
||||
this.updateDom();
|
||||
},
|
||||
|
||||
getDom: function () {
|
||||
const photoDiv = document.createElement("div");
|
||||
photoDiv.className = "piwigo-photo";
|
||||
photoDiv.style.width = this.config.maxWidth;
|
||||
photoDiv.style.height = this.config.maxHeight;
|
||||
|
||||
if (this.imageFileNames && this.imageFileNames.length) {
|
||||
const curImage = this.imageFileNames[this.imageIndex];
|
||||
photoDiv.textContent = "";
|
||||
photoDiv.style.backgroundImage =
|
||||
"url('" + this.file("images/" + curImage) + "')";
|
||||
} else {
|
||||
photoDiv.textContent = this.config.loadingText;
|
||||
}
|
||||
|
||||
return photoDiv;
|
||||
},
|
||||
|
||||
getStyles: function () {
|
||||
return [this.file("css/style.css")];
|
||||
},
|
||||
|
||||
updateImages: function () {
|
||||
this.sendSocketNotification("UPDATE", {
|
||||
username: this.config.piwigoUsername,
|
||||
password: this.config.piwigoPassword,
|
||||
url: this.config.piwigoBaseUrl,
|
||||
size: this.config.piwigoSize,
|
||||
});
|
||||
},
|
||||
});
|
6
css/style.css
Normal file
6
css/style.css
Normal file
|
@ -0,0 +1,6 @@
|
|||
div.piwigo-photo {
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
box-shadow: 0px 0px 10px 10px black inset;
|
||||
}
|
0
images/.gitkeep
Normal file
0
images/.gitkeep
Normal file
58
loader.js
Normal file
58
loader.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
const fsprom = require("fs").promises;
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const superagent = require("superagent");
|
||||
|
||||
async function getImages(rootPath) {
|
||||
const content = await fsprom.readdir(rootPath, { withFileTypes: true });
|
||||
const images = content
|
||||
.filter((x) => !x.isDirectory())
|
||||
.map((x) => x.name)
|
||||
.filter((x) => x !== ".gitkeep");
|
||||
return images;
|
||||
}
|
||||
|
||||
async function deleteImages(rootPath, fileNamesLocal, fileNamesServer) {
|
||||
const diff = fileNamesLocal.filter((x) => !fileNamesServer.includes(x));
|
||||
try {
|
||||
for (fileName of diff) {
|
||||
//console.log("delete " + path.join("/", rootPath, fileName));
|
||||
await fsprom.unlink(path.join("/", rootPath, fileName));
|
||||
}
|
||||
} catch (err) {
|
||||
// do not propagate errors so that failed delete will not lead to failed download
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadImages(rootPath, config) {
|
||||
const localFileNames = await getImages(rootPath);
|
||||
const agent = superagent.agent();
|
||||
await agent
|
||||
.post(config.url + "?format=json&method=pwg.session.login")
|
||||
.field("username", config.username)
|
||||
.field("password", config.password);
|
||||
const data = await agent.get(
|
||||
config.url + "?format=json&method=pwg.categories.getImages"
|
||||
);
|
||||
respText = JSON.parse(data.res.text);
|
||||
images = respText.result.images;
|
||||
serverFileNames = [];
|
||||
for (img of images) {
|
||||
const fileName = img.file;
|
||||
serverFileNames.push(fileName);
|
||||
// Only download if file does not yet exist
|
||||
if (!localFileNames.some((x) => x === fileName)) {
|
||||
await new Promise((resolve) =>
|
||||
agent
|
||||
.get(img.derivatives[config.size].url)
|
||||
.pipe(fs.createWriteStream(path.join("/", rootPath, fileName)))
|
||||
.on("finish", resolve)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await deleteImages(rootPath, localFileNames, serverFileNames);
|
||||
}
|
||||
|
||||
module.exports = { getImages, downloadImages };
|
26
node_helper.js
Normal file
26
node_helper.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const NodeHelper = require("node_helper");
|
||||
const path = require("path");
|
||||
const _ = require("lodash");
|
||||
const { getImages, downloadImages } = require("./loader");
|
||||
const Log = require("logger");
|
||||
|
||||
module.exports = NodeHelper.create({
|
||||
socketNotificationReceived: function (notification, payload) {
|
||||
this.syncImages(payload);
|
||||
},
|
||||
|
||||
syncImages: function (config) {
|
||||
const imagePath = path.join("/", __dirname, "images");
|
||||
downloadImages(imagePath, config)
|
||||
.then(() => {
|
||||
getImages(imagePath).then((images) => {
|
||||
shuffledImages = _.shuffle(images);
|
||||
this.sendSocketNotification("IMAGES_UPDATED", shuffledImages);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
Log.error("Could not download images from piwigo! Error was: ");
|
||||
Log.error(err);
|
||||
});
|
||||
},
|
||||
});
|
2050
package-lock.json
generated
Normal file
2050
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
18
package.json
Normal file
18
package.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "mmm-piwigo-photo-wheel",
|
||||
"version": "1.0.0",
|
||||
"main": "MMM-piwigo-photo-wheel.js",
|
||||
"scripts": {
|
||||
"test": "mocha",
|
||||
"start": "node test_manual/serve.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"chai": "^4.3.6",
|
||||
"mocha": "^10.1.0",
|
||||
"superagent": "^8.0.3",
|
||||
"superagent-mock": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "2.7.1"
|
||||
}
|
||||
}
|
118
test/superagent-mock-config.js
Normal file
118
test/superagent-mock-config.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
module.exports = [
|
||||
{
|
||||
pattern: "https://piwigo.example(.*)",
|
||||
|
||||
fixtures: function (match, params, headers, context) {
|
||||
if (
|
||||
match[1] === "/i.php?/upload/2022/11/01/20221101211408-9a0c06b1-la.jpg"
|
||||
) {
|
||||
return {
|
||||
image: "test",
|
||||
};
|
||||
}
|
||||
|
||||
if (match[1] === "?format=json&method=pwg.session.login") {
|
||||
return {
|
||||
stat: "ok",
|
||||
result: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (match[1] === "?format=json&method=pwg.categories.getImages") {
|
||||
return {
|
||||
stat: "ok",
|
||||
result: {
|
||||
paging: {
|
||||
page: 0,
|
||||
per_page: 100,
|
||||
count: 1,
|
||||
total_count: "1",
|
||||
},
|
||||
images: [
|
||||
{
|
||||
is_favorite: false,
|
||||
id: 1,
|
||||
width: 4016,
|
||||
height: 5197,
|
||||
hit: 0,
|
||||
file: "matthew-brodeur-DH_u2aV3nGM-unsplash.jpg",
|
||||
name: "matthew-brodeur-DH u2aV3nGM-unsplash",
|
||||
comment: null,
|
||||
date_creation: null,
|
||||
date_available: "2022-11-01 21:14:08",
|
||||
page_url: "https://piwigo.example/picture.php?/1",
|
||||
element_url:
|
||||
"https://piwigo.example/upload/2022/11/01/20221101211408-9a0c06b1.jpg",
|
||||
derivatives: {
|
||||
square: {
|
||||
url: "https://piwigo.example/_data/i/upload/2022/11/01/20221101211408-9a0c06b1-sq.jpg",
|
||||
width: 120,
|
||||
height: 120,
|
||||
},
|
||||
thumb: {
|
||||
url: "https://piwigo.example/i.php?/upload/2022/11/01/20221101211408-9a0c06b1-th.jpg",
|
||||
width: 111,
|
||||
height: 144,
|
||||
},
|
||||
"2small": {
|
||||
url: "https://piwigo.example/_data/i/upload/2022/11/01/20221101211408-9a0c06b1-2s.jpg",
|
||||
width: 185,
|
||||
height: 240,
|
||||
},
|
||||
xsmall: {
|
||||
url: "https://piwigo.example/i.php?/upload/2022/11/01/20221101211408-9a0c06b1-xs.jpg",
|
||||
width: 250,
|
||||
height: 324,
|
||||
},
|
||||
small: {
|
||||
url: "https://piwigo.example/_data/i/upload/2022/11/01/20221101211408-9a0c06b1-sm.jpg",
|
||||
width: 333,
|
||||
height: 432,
|
||||
},
|
||||
medium: {
|
||||
url: "https://piwigo.example/_data/i/upload/2022/11/01/20221101211408-9a0c06b1-me.jpg",
|
||||
width: 459,
|
||||
height: 594,
|
||||
},
|
||||
large: {
|
||||
url: "https://piwigo.example/i.php?/upload/2022/11/01/20221101211408-9a0c06b1-la.jpg",
|
||||
width: 584,
|
||||
height: 756,
|
||||
},
|
||||
xlarge: {
|
||||
url: "https://piwigo.example/i.php?/upload/2022/11/01/20221101211408-9a0c06b1-xl.jpg",
|
||||
width: 709,
|
||||
height: 918,
|
||||
},
|
||||
xxlarge: {
|
||||
url: "https://piwigo.example/i.php?/upload/2022/11/01/20221101211408-9a0c06b1-xx.jpg",
|
||||
width: 959,
|
||||
height: 1242,
|
||||
},
|
||||
},
|
||||
categories: [
|
||||
{
|
||||
id: 1,
|
||||
url: "https://piwigo.example/index.php?/category/1",
|
||||
page_url:
|
||||
"https://piwigo.example/picture.php?/1/category/1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
get: function (match, data) {
|
||||
return {
|
||||
body: data,
|
||||
};
|
||||
},
|
||||
post: function (match, data) {
|
||||
return {
|
||||
status: 201,
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
50
test/test.js
Normal file
50
test/test.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
const path = require("path");
|
||||
const fs = require("fs").promises;
|
||||
const os = require("os");
|
||||
const chai = require("chai");
|
||||
const expect = chai.expect;
|
||||
const request = require("superagent");
|
||||
const mockConfig = require("./superagent-mock-config");
|
||||
|
||||
const { getImages, downloadImages } = require("./../loader");
|
||||
|
||||
describe("Loader", function () {
|
||||
describe("getImages()", function () {
|
||||
it("should return array of file names", async () => {
|
||||
// Given
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "foo-"));
|
||||
await fs.appendFile(dir + "/mynewfile1.txt", "Hello content!");
|
||||
// When
|
||||
const data = await getImages(dir);
|
||||
// Then
|
||||
expect(data).to.eql(["mynewfile1.txt"]);
|
||||
});
|
||||
it("should ignore .gitkeep", async () => {
|
||||
// Given
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "foo-"));
|
||||
await fs.appendFile(dir + "/mynewfile1.txt", "Hello content!");
|
||||
await fs.appendFile(dir + "/.gitkeep", "Hello content!");
|
||||
await fs.appendFile(dir + "/.gitbla", "Hello content!");
|
||||
// When
|
||||
const data = await getImages(dir);
|
||||
// Then
|
||||
expect(data).to.eql([".gitbla", "mynewfile1.txt"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Loader", function () {
|
||||
describe("downloadImages()", function () {
|
||||
it("should connect", async () => {
|
||||
const config = {
|
||||
username: "tester",
|
||||
password: "secret",
|
||||
url: "https://piwigo.example",
|
||||
size: "large",
|
||||
};
|
||||
var superagentMock = require("superagent-mock")(request, mockConfig);
|
||||
await downloadImages(path.join("/", __dirname, "../images"), config);
|
||||
superagentMock.unset();
|
||||
}).timeout(30000);
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue