Skip to content

Commit f025a2b

Browse files
committed
Merge testing: recently-added DateCreated and *arr imports
2 parents 8af2a38 + 047506b commit f025a2b

9 files changed

Lines changed: 500 additions & 145 deletions

File tree

‎classes/arr/radarr.js‎

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,111 @@ class Radarr {
228228

229229
return csrCards;
230230
}
231+
232+
/**
233+
* Movies imported/added in the last N days (movieFile.dateAdded, else movie.added).
234+
* Uses *arr artwork (not media-server poster cache).
235+
*/
236+
async GetRecentlyAdded(days, hasArt) {
237+
const cards = [];
238+
const dayCount = Math.max(0, Number(days) || 0);
239+
if (dayCount <= 0) return cards;
240+
241+
const from = new Date();
242+
from.setDate(from.getDate() - dayCount);
243+
from.setHours(0, 0, 0, 0);
244+
245+
let raw;
246+
try {
247+
raw = await axios.get(
248+
this.radarrUrl + "/api/v3/movie?apikey=" + this.radarrToken
249+
);
250+
} catch (err) {
251+
const d = new Date();
252+
console.log(
253+
d.toLocaleString() + " *Radarr - Get recently added:",
254+
err.message
255+
);
256+
throw err;
257+
}
258+
259+
const movies = Array.isArray(raw.data) ? raw.data : [];
260+
for (const md of movies) {
261+
if (!md || md.hasFile !== true) continue;
262+
const addedRaw =
263+
(md.movieFile && (md.movieFile.dateAdded || md.movieFile.DateAdded)) ||
264+
md.added ||
265+
md.Added ||
266+
"";
267+
if (!addedRaw) continue;
268+
const added = new Date(addedRaw);
269+
if (Number.isNaN(added.getTime()) || added < from) continue;
270+
271+
const medCard = new mediaCard();
272+
const addedDay = added.toISOString().split("T")[0];
273+
medCard.tagLine = md.title + " (" + addedDay + ")";
274+
medCard.title = md.title;
275+
medCard.DBID = md.tmdbId;
276+
medCard.runTime = md.runtime;
277+
medCard.genre = md.genres;
278+
medCard.summary = await util.emptyIfNull(md.overview);
279+
medCard.mediaType = "movie";
280+
medCard.cardType = cType.CardTypeEnum.RecentlyAdded;
281+
medCard.studio = md.studio || "";
282+
medCard.theme = "";
283+
medCard.posterAR = 1.47;
284+
285+
let contentRating = "NR";
286+
if (!(await util.isEmpty(md.certification))) {
287+
contentRating = md.certification;
288+
}
289+
medCard.contentRating = contentRating;
290+
medCard.ratingColour = "badge-dark";
291+
const cr = String(contentRating).toLowerCase();
292+
if (cr === "g" || cr === "tv-g" || cr === "tv-y") medCard.ratingColour = "badge-success";
293+
else if (cr === "pg" || cr === "tv-pg" || cr === "tv-y7") medCard.ratingColour = "badge-info";
294+
else if (cr === "pg-13" || cr === "tv-14") medCard.ratingColour = "badge-warning";
295+
else if (cr === "r" || cr === "nc-17" || cr === "tv-ma") medCard.ratingColour = "badge-danger";
296+
297+
let posterUrl;
298+
const images = Array.isArray(md.images) ? md.images : [];
299+
images.forEach((i) => {
300+
if (i.coverType === "poster") posterUrl = i.remoteUrl;
301+
});
302+
const fileName = "arr-radarr-ra-" + md.tmdbId + ".jpg";
303+
if (posterUrl) {
304+
await core.CacheArrImage(posterUrl, fileName);
305+
medCard.posterURL = "/imagecache/" + fileName;
306+
} else {
307+
medCard.posterURL = "/images/no-poster-available.png";
308+
}
309+
310+
if (hasArt === "true") {
311+
let fanUrl;
312+
images.forEach((i) => {
313+
if (i.coverType === "fanart") fanUrl = i.remoteUrl;
314+
});
315+
if (fanUrl) {
316+
const artName = "arr-radarr-ra-" + md.tmdbId + "-art.jpg";
317+
await core.CacheArrImage(fanUrl, artName);
318+
medCard.posterArtURL = "/imagecache/" + artName;
319+
}
320+
}
321+
322+
cards.push(medCard);
323+
}
324+
325+
const now = new Date();
326+
console.log(
327+
now.toLocaleString() +
328+
" *Radarr — Recently added last " +
329+
dayCount +
330+
" day(s): " +
331+
cards.length +
332+
" movie(s)"
333+
);
334+
return cards;
335+
}
231336
}
232337

233338
module.exports = Radarr;

‎classes/arr/sonarr.js‎

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,150 @@ class Sonarr {
271271
}
272272
return csCards;
273273
}
274+
275+
/**
276+
* Series with episode imports in the last N days (history downloadFolderImported).
277+
* Uses *arr artwork (not media-server poster cache).
278+
*/
279+
async GetRecentlyAdded(days, playThemes, hasArt) {
280+
const cards = [];
281+
const dayCount = Math.max(0, Number(days) || 0);
282+
if (dayCount <= 0) return cards;
283+
284+
const from = new Date();
285+
from.setDate(from.getDate() - dayCount);
286+
from.setHours(0, 0, 0, 0);
287+
288+
let hist;
289+
try {
290+
hist = await axios.get(
291+
this.sonarrUrl +
292+
"/api/v3/history?page=1&pageSize=250&sortKey=date&sortDirection=descending" +
293+
"&eventType=3&includeSeries=true&includeEpisode=true&apikey=" +
294+
this.sonarrToken
295+
);
296+
} catch (err) {
297+
const d = new Date();
298+
console.log(
299+
d.toLocaleString() + " *Sonarr - Get recently added history:",
300+
err.message
301+
);
302+
throw err;
303+
}
304+
305+
const records =
306+
hist && hist.data && Array.isArray(hist.data.records)
307+
? hist.data.records
308+
: Array.isArray(hist.data)
309+
? hist.data
310+
: [];
311+
312+
const bySeries = new Map();
313+
for (const rec of records) {
314+
if (!rec) continue;
315+
const when = rec.date ? new Date(rec.date) : null;
316+
if (!when || Number.isNaN(when.getTime()) || when < from) continue;
317+
const series = rec.series || {};
318+
const seriesId = series.id || rec.seriesId;
319+
if (!seriesId) continue;
320+
const key = String(seriesId);
321+
const prev = bySeries.get(key);
322+
if (!prev || when > prev.when) {
323+
bySeries.set(key, { when, series, episode: rec.episode || {} });
324+
}
325+
}
326+
327+
for (const { when, series, episode } of bySeries.values()) {
328+
let rawSeries = { data: series };
329+
if (!series.images || !series.tvdbId) {
330+
try {
331+
rawSeries = await this.GetSeriesRawData(series.id || series.Id);
332+
} catch (e) {
333+
continue;
334+
}
335+
}
336+
const sd = rawSeries.data || series;
337+
const tvdbId = sd.tvdbId || sd.TvdbId;
338+
if (!tvdbId) continue;
339+
340+
const medCard = new mediaCard();
341+
const addedDay = when.toISOString().split("T")[0];
342+
const epLabel =
343+
episode && episode.seasonNumber != null && episode.episodeNumber != null
344+
? "S" +
345+
String(episode.seasonNumber).padStart(2, "0") +
346+
"E" +
347+
String(episode.episodeNumber).padStart(2, "0")
348+
: "";
349+
medCard.tagLine =
350+
(sd.title || series.title || "") +
351+
(epLabel ? " — " + epLabel : "") +
352+
" (" +
353+
addedDay +
354+
")";
355+
medCard.title = episode.title || sd.title || series.title || "";
356+
medCard.DBID = tvdbId;
357+
medCard.year = addedDay;
358+
medCard.runTime = sd.runtime;
359+
medCard.genre = sd.genres;
360+
medCard.summary = await util.emptyIfNull(sd.overview);
361+
medCard.mediaType = "episode";
362+
medCard.cardType = cType.CardTypeEnum.RecentlyAdded;
363+
medCard.network = sd.network || "";
364+
medCard.posterAR = 1.47;
365+
366+
let contentRating = "NR";
367+
if (!(await util.isEmpty(sd.certification))) {
368+
contentRating = sd.certification;
369+
}
370+
medCard.contentRating = contentRating;
371+
medCard.ratingColour = "badge-dark";
372+
373+
if (playThemes == "true") {
374+
const mp3 = tvdbId + ".mp3";
375+
await core.CacheMP3(mp3);
376+
medCard.theme = "/mp3cache/" + mp3;
377+
}
378+
379+
let posterUrl;
380+
const images = Array.isArray(sd.images) ? sd.images : [];
381+
images.forEach((i) => {
382+
if (i.coverType === "poster") posterUrl = i.remoteUrl;
383+
});
384+
const fileName = "arr-sonarr-ra-" + tvdbId + ".jpg";
385+
if (posterUrl) {
386+
await core.CacheArrImage(posterUrl, fileName);
387+
medCard.posterURL = "/imagecache/" + fileName;
388+
} else {
389+
medCard.posterURL = "/images/no-poster-available.png";
390+
}
391+
392+
if (hasArt == "true") {
393+
let fanUrl;
394+
images.forEach((i) => {
395+
if (i.coverType === "fanart") fanUrl = i.remoteUrl;
396+
});
397+
if (fanUrl) {
398+
const artName = "arr-sonarr-ra-" + tvdbId + "-art.jpg";
399+
await core.CacheArrImage(fanUrl, artName);
400+
medCard.posterArtURL = "/imagecache/" + artName;
401+
}
402+
}
403+
404+
cards.push(medCard);
405+
}
406+
407+
const now = new Date();
408+
console.log(
409+
now.toLocaleString() +
410+
" *Sonarr — Recently added last " +
411+
dayCount +
412+
" day(s): " +
413+
cards.length +
414+
" series import(s)"
415+
);
416+
return cards;
417+
}
274418
}
275419

276420
module.exports = Sonarr;

‎classes/core/utility.js‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,7 @@ class utility {
166166
if (options && options.includeAll === true) {
167167
return Array.isArray(mediaCards) ? mediaCards.slice() : [];
168168
}
169-
if (recentlyAdded > 0) {
170-
return mediaCards;
171-
}
169+
// Recently-added pool: still honor Number to Display as a cap (0 = all matching).
172170
const pool = Array.isArray(mediaCards) ? mediaCards.slice() : [];
173171
if (pool.length === 0) {
174172
return [];

0 commit comments

Comments
 (0)