-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnode_helper.js
More file actions
123 lines (109 loc) · 3.77 KB
/
node_helper.js
File metadata and controls
123 lines (109 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
var NodeHelper = require("node_helper");
var fs = require("fs");
var path = require("path");
var express = require("express");
module.exports = NodeHelper.create({
start() {
this.registeredRoutes = new Set();
this.instances = {};
this.rescanTimers = {};
},
socketNotificationReceived(notification, payload) {
if (notification !== "PHOTOSTACK_REGISTER") return;
if (!payload || !payload.identifier) return;
const identifier = payload.identifier;
this.instances[identifier] = payload;
const paths = Array.isArray(payload.paths) ? payload.paths : [];
for (let i = 0; i < paths.length; i++) {
const dir = paths[i];
if (!dir) continue;
const routeKey = identifier + "|" + i;
if (!this.registeredRoutes.has(routeKey)) {
let stat;
try { stat = fs.statSync(dir); } catch (e) { continue; }
if (!stat.isDirectory()) continue;
const routeBase = "/MMM-PhotoStack/photo/" + identifier + "/" + i;
this.expressApp.use(routeBase, express.static(dir));
this.registeredRoutes.add(routeKey);
}
}
this.scan(identifier);
const rescanInterval = payload.rescanInterval;
if (rescanInterval > 0) {
if (this.rescanTimers[identifier]) clearInterval(this.rescanTimers[identifier]);
this.rescanTimers[identifier] = setInterval(() => this.scan(identifier), rescanInterval);
}
},
scan(identifier) {
const payload = this.instances[identifier];
if (!payload) return;
const paths = Array.isArray(payload.paths) ? payload.paths : [];
const recursive = payload.recursive !== false;
const extensions = (payload.extensions || []).map((e) => e.toLowerCase().replace(/^\./, ""));
const randomize = payload.randomize !== false;
const urls = [];
for (let i = 0; i < paths.length; i++) {
const dir = paths[i];
if (!dir) continue;
let stat;
try {
stat = fs.statSync(dir);
} catch (err) {
console.error("[MMM-PhotoStack] Path does not exist or is not accessible: " + dir);
continue;
}
if (!stat.isDirectory()) {
console.error("[MMM-PhotoStack] Path is not a directory: " + dir);
continue;
}
const routeBase = "/MMM-PhotoStack/photo/" + identifier + "/" + i;
const files = this.collectFiles(dir, dir, recursive, extensions);
for (const rel of files) {
const encoded = rel
.split("/")
.map((seg) => encodeURIComponent(seg))
.join("/");
urls.push(routeBase + "/" + encoded);
}
}
if (randomize) this.shuffle(urls);
this.sendSocketNotification("PHOTOSTACK_IMAGES", {
identifier: identifier,
urls: urls
});
},
collectFiles(root, dir, recursive, extensions) {
const out = [];
let entries;
try {
entries = fs.readdirSync(dir, { withFileTypes: true });
} catch (err) {
console.error("[MMM-PhotoStack] Could not read directory: " + dir + " (" + err.message + ")");
return out;
}
for (const entry of entries) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
if (recursive) {
const sub = this.collectFiles(root, full, recursive, extensions);
for (const s of sub) out.push(s);
}
} else if (entry.isFile()) {
const ext = path.extname(entry.name).toLowerCase().replace(/^\./, "");
if (extensions.length === 0 || extensions.indexOf(ext) !== -1) {
const rel = path.relative(root, full).split(path.sep).join("/");
out.push(rel);
}
}
}
return out;
},
shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
});