UNPKG

8.28 kBJavaScriptView Raw
1/*jslint node: true, esversion: 6 */
2"use strict";
3
4const Path = require("path");
5
6const debug = require('debug')('upnpserver:contentHandlers:AFMetas');
7const logger = require('../logger');
8
9const Abstract_Metas = require('./abstract_metas');
10
11const Movie = require('../class/object.item.videoItem.movie');
12const VideoAlbum = require('../class/object.container.album.videoAlbum');
13
14const AC_JSON = "a" + "l" + "l" + "o" + "c" + "i" + "n" + "e" + ".json";
15const POSTER = "poster.jpg";
16const TRAILER = "trailer.mp4";
17
18const MOVIE_KEY_REGEXP = /.*__AF([a-z0-9]+)\.[^.]*$/i;
19const MOVIE_ALBUM_KEY_REGEXP = /.*__AS([a-z0-9]+)\.[^.]*$/i;
20
21class Allo extends Abstract_Metas {
22 constructor(configuration) {
23 super(configuration);
24
25 this._basePath = this._configuration.basePath || process.env.AF_METAS_PATH;
26
27 debug("AF_Metas", "BASE path=", this._basePath);
28 }
29
30 initialize(contentDirectoryService, callback) {
31
32 if (this._basePath) {
33 this._baseURL = contentDirectoryService.newURL(this._basePath);
34
35 debug("AF_Metas", "BASE URL=", this._baseURL);
36
37 if (!this._baseURL) {
38 this.enabled = false;
39 }
40 }
41
42 super.initialize(contentDirectoryService, callback);
43 }
44
45 /**
46 *
47 */
48 get name() {
49 return "allo";
50 }
51
52 /**
53 *
54 */
55 getTrailerURL(contentURL, key, callback) {
56 var path = this._baseURL.join(key, TRAILER);
57 callback(null, path);
58 }
59
60 /**
61 *
62 */
63 getPosterURL(contentURL, key, callback) {
64 var path = this._baseURL.join(key, POSTER);
65 callback(null, path);
66 }
67
68 /**
69 *
70 */
71 prepareMetas(contentInfos, context, callback) {
72 if (this.enabled === false) {
73 return callback();
74 }
75
76 var contentURL = contentInfos.contentURL;
77
78 var reg = MOVIE_KEY_REGEXP.exec(contentURL.basename);
79
80 debug("prepareMetas", "Prepare metas of", contentURL, "=>", reg);
81
82 if (!reg) {
83 return callback();
84 }
85
86 var afKey = reg[1];
87
88 var url = this._baseURL.join(afKey);
89
90 url.stat((error, stats) => {
91 if (error) {
92 logger.info("prepareMetas: Unknown KEY", afKey, error);
93 return callback();
94 }
95 if (!stats.isDirectory()) {
96 logger.warn("Not a directory !", url, error);
97 return callback();
98 }
99
100 var metas = {};
101
102 this.loadJSON(metas, afKey, url, (error, jsonContext) => {
103 if (error) {
104 logger.warn("Can not load JSON of key", afKey, error);
105
106 } else {
107 debug("prepareMetas", "JSON of key", afKey, "is loaded");
108 }
109
110 this.refPoster(metas, contentURL, afKey, (error) => {
111 if (error) {
112 logger.error("Can not ref Poster of key", afKey, error);
113
114 } else {
115 debug("prepareMetas", "Ref Poster of key", afKey, "detected");
116 }
117
118 this.refTrailer(metas, contentURL, afKey, (error) => {
119 if (error) {
120 logger.error("Can not ref Trailer of key", afKey, error);
121
122 } else {
123 debug("prepareMetas", "Trailer of key", afKey, "detected");
124 }
125
126 callback(null, metas);
127 });
128 });
129 });
130 });
131 }
132
133 /**
134 *
135 */
136 loadJSON(attributes, afKey, url, callback) {
137 var jsonURL = url.join(AC_JSON);
138
139 debug("loadJSON", "Load json", jsonURL);
140
141 jsonURL.readContent("utf8", (error, content) => {
142 debug("loadJSON", "JSON=", content);
143 if (error) {
144 return callback(error);
145 }
146
147 var j;
148 try {
149 j = JSON.parse(content);
150 } catch (x) {
151 logger.error("Can not parse JSON ", x);
152 return callback("Can not parse JSON");
153 }
154
155 if (false && debug.enabled) {
156 debug("loadJSON", "JSON=", j);
157 }
158
159 var movie = j.movie;
160 if (!movie) {
161 return callback();
162 }
163
164 if (movie.title) {
165 attributes.title = movie.title;
166 attributes.titleAlsoKnownAs = movie.title;
167 }
168 if (movie.originalTitle) {
169 attributes.originalTitle = movie.originalTitle;
170 }
171 if (movie.region) {
172 attributes.region = movie.nationality;
173 }
174 if (movie.productionYear) {
175 attributes.year = movie.productionYear;
176 }
177 if (movie.releaseDate) {
178 var ds = /([0-9]{4})-([0-9]{2})-([0-9]{2})/.exec(movie.releaseDate);
179 if (ds) {
180 attributes.releaseDate = ds[0]; // 0 index !
181 }
182 }
183
184 function normalizeText(text) {
185 if (!text) {
186 return text;
187 }
188
189 text = text.replace(/<br\W*\/?>/gi, '\n');
190
191 return text.replace(/<(?:.|\n)*?>/gm, '');
192 }
193
194 if (movie.synopsisShort) {
195 attributes.description = normalizeText(movie.synopsisShort);
196 }
197 if (movie.synopsis) {
198 attributes.longDescription = normalizeText(movie.synopsis);
199
200 if (!attributes.description) {
201 attributes.description = attributes.longDescription;
202 delete attributes.longDescription;
203 }
204 }
205 if (movie.movieType) {
206 attributes.type = movie.movieType.$;
207 }
208
209 var castMembers = movie.castMember;
210 if (castMembers) {
211 castMembers.forEach((c) => {
212 switch (c.activity.code) {
213
214 case 8001:
215 attributes.actors = attributes.actors || [];
216 let actor = {
217 key: c.person.code,
218 name: normalizeText(c.person.name)
219 };
220 if (c.role) {
221 actor.role = normalizeText(c.role);
222 }
223 attributes.actors.push(actor);
224 break;
225
226 case 8002:
227 attributes.directors = attributes.directors || [];
228 attributes.directors.push({
229 key: c.person.code,
230 name: normalizeText(c.person.name)
231 });
232 break;
233
234 case 8003:
235 case 8004:
236 attributes.authors = attributes.authors || [];
237
238 let author = {
239 key: c.person.code,
240 name: normalizeText(c.person.name)
241 };
242 if (c.activity.name) {
243 author.role = normalizeText(c.activity.name);
244 }
245 attributes.authors.push(author);
246 break;
247
248 /*
249 * No too many data in XML default:
250 * attributes.artists = attributes.artists || []; attributes.artists.push({ key :
251 * c.person.code, name : c.person.name, role : c.activity.name }); break;
252 */
253 }
254 });
255 }
256 var genres = movie.genre;
257 if (genres) {
258 attributes.genres = attributes.genres || [];
259
260 genres.forEach((genre) => {
261 attributes.genres.push({
262 id: "af_key" + genre.code,
263 name: genre.$
264 });
265 });
266 }
267
268 var statistics = movie.statistics;
269 if (statistics) {
270 attributes.ratings = attributes.ratings || [];
271
272 if (statistics.pressRating) {
273 attributes.ratings.push({
274 type: "af_press",
275 rating: statistics.pressRating
276 });
277 }
278
279 if (statistics.userRating) {
280 attributes.ratings.push({
281 type: "af_user",
282 rating: statistics.userRating
283 });
284 }
285 }
286
287 var movieCertificate = movie.movieCertificate;
288 if (movieCertificate) {
289 var cert = movieCertificate.certificate;
290 var certificate;
291 if (cert && cert.code) {
292 switch (cert.code) {
293 case 14001:
294 case 14044:
295 certificate = "-12";
296 break;
297 case 14002:
298 case 14045:
299 certificate = "-16";
300 break;
301 case 14004:
302 certificate = "-18";
303 break;
304 case 14005:
305 certificate = "X";
306 break;
307 case 14029:
308 certificate = "3+";
309 break;
310 case 14030:
311 certificate = "6+";
312 break;
313 case 14031:
314 certificate = "-10";
315 break;
316 case 14035:
317 certificate = "!";
318 // Avertissement : des scènes, des propos ou des images peuvent heurter la sensibilité des
319 // spectateurs
320 break;
321 }
322 }
323
324 if (certificate) {
325 attributes.certificate = certificate;
326 }
327 }
328
329 callback();
330 });
331 }
332
333 /**
334 *
335 */
336 searchUpnpClass(fileInfos, callback) {
337 var contentURL = fileInfos.contentURL;
338 var basename = contentURL.basename;
339
340 var reg = MOVIE_KEY_REGEXP.exec(basename);
341 if (reg) {
342 return callback(null, {
343 upnpClass: this.service.upnpClasses[Movie.UPNP_CLASS],
344 priority: 30
345 });
346 }
347
348 reg = MOVIE_ALBUM_KEY_REGEXP.exec(basename);
349 if (reg) {
350 return callback(null, {
351 upnpClass: this.service.upnpClasses[VideoAlbum.UPNP_CLASS],
352 priority: 30
353 });
354 }
355
356 callback();
357 }
358}
359
360module.exports = Allo;