forked from devbab/plex-ttp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plex-ttp.js
executable file
·191 lines (156 loc) · 5.49 KB
/
plex-ttp.js
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
const fs = require("fs");
const argv = require("minimist")(process.argv.slice(2));
const events = require("events");
const ev = new events.EventEmitter();
const plex = require("./plex.js");
const exif = require("./exif.js");
const usage = `
usage node plex-ttp.js [-h] [-c] [-l tag] [-d tag] [-s [-t date-YYYY-MM-DD]]
-h : show this help
-s : scan images and put face tags into Plex
-t : start date to update pictures from
-f : force scan ALL images and put face tags into Plex
-c : clean Lone Tags
-l [tag] : list matching tags
-d tag: delete the tag
`;
let exifProcessing = 0, // processing EXIF ongoing
statProcessing = 0, // stat file ongoing
nbUpdate = 0; // number of updates
let fullScan = false;
let updateDate = "";
// Need to track when to end EXIF process and close DB connection
// emitted when change in exifProcessing or statProcessing
const evHandler = function () {
if (argv.debug)
console.log(`exifProcessing ${exifProcessing} statProcessing ${statProcessing}`); // eslint-disable-line no-console
if (exifProcessing <= 0 && statProcessing <= 0) {
plex.cleanLoneTTPTags();
exif.end();
plex.createTriggers();
plex.end();
console.log(`Done : ${nbUpdate} update(s)`); // eslint-disable-line no-console
}
};
function DoMainScan() {
plex.init();
// backup and clean triggers
plex.storeTriggers()
plex.deleteTriggers();
// add a column to bear datetime of TTP tag update and place update
plex.addColumnTTPUpdate();
plex.addColumnPlaceUpdate();
// read list des tags TTP existants
plex.scanTTPTags();
let recs = plex.scanPhotos();
// eslint-disable-next-line no-console
console.log("Total photos", recs.length, "\n");
if (recs.length == 0)
return;
function doTheUpdate(rec) {
// console.log("doTheUpdate: ", rec.file);
exifProcessing++;
exif.getFromImage(rec.file)
.then(data => {
nbUpdate++;
if (data.faces.length == 0) {
console.log(`Skipping. No tags in ${rec.file}: `, data.faces);
plex.addTTPTags(rec.mid, data.faces); // update UpdatedAt
}
else
{
plex.deleteTTPTags(rec.mid); // delete any existing tags of the photo
plex.addTTPTags(rec.mid, data.faces); // add new tags
// eslint-disable-next-line no-console
console.log(`Adding ${rec.file}:`, data.faces);
// console.log("full ", data.tags);
}
exifProcessing--;
ev.emit("exif");
})
.catch((err) => {
console.log(`Exception!`, err);
exifProcessing--;
ev.emit("exif");
});
}
recs.forEach(rec => {
//console.log(rec.file);
if (!rec.FaceUpdateTime) rec.FaceUpdateTime = 0;
let dateTTPUpdate = Date.parse(rec.FaceUpdateTime);
statProcessing++;
fs.stat(rec.file, (err, stat) => {
statProcessing--;
// here we avoid updating older pictures, unless full scan
if (updateDate != "") {
dateTTPUpdate = updateDate;
}
if (fullScan || (stat && stat.mtimeMs > dateTTPUpdate))
doTheUpdate(rec);
ev.emit("stat");
});
});
//Assign the event handler to an event:
ev.on("stat", evHandler);
ev.on("exif", evHandler);
}
/******************** So what do we do with all that ?********* */
const reader = require("readline-sync"); //npm install readline-sync
let username = reader.question("Please confirm that Plex is not running, and that the database is backed up. Type 'yes' to continue. ");
if (username != "yes") {
console.log("Exiting.");
return;
}
if (argv.h || process.argv.length == 2)
console.log(usage); // eslint-disable-line no-console
if (argv.c) {
plex.init();
// backup and clean triggers
plex.storeTriggers()
plex.deleteTriggers();
// eslint-disable-next-line no-console
console.log("cleaning Lone tags");
plex.cleanLoneTTPTags();
plex.createTriggers();
plex.end();
}
if (argv.l) {
if (argv.l === true)
argv.l = "";
plex.init();
let res = plex.listTag(argv.l);
const nb = res.length;
res = res.map(elt => elt.tag).sort().join(", ");
//res = res.sort((a, b) => a.tag < b.tag ? -1 : a.tag > b.tag ? 1 : 0);
// eslint-disable-next-line no-console
console.log(res);
// eslint-disable-next-line no-console
console.log(`\n${nb} entries`);
plex.end();
}
// delete all matching tags
if (argv.d) {
plex.init();
// backup and clean triggers
plex.storeTriggers()
plex.deleteTriggers();
const res = plex.listTag(argv.d);
// eslint-disable-next-line no-console
console.log("deleting", res);
const ids = res.map(elt => elt.id);
ids.forEach(id => plex.deleteTTPTags(id));
plex.cleanLoneTTPTags();
plex.createTriggers();
plex.end();
}
if (argv.f) {
fullScan = true;
DoMainScan();
}
if (argv.s) {
if (argv.t) {
console.log("Updating photos added after: ", argv.t);
updateDate = Date.parse(argv.t);
}
DoMainScan();
}