UNPKG

@iptv/xtream-api

Version:

Standardized access to Xtream compatible player API

452 lines (451 loc) 11.6 kB
import h from "camelcase-keys"; import { defineSerializers as H } from "./index.js"; const W = H("JSON:API", { profile: (e) => { const { auth: n, expDate: s, maxConnections: i, activeCons: d, createdAt: a, ...t } = h(e); return { data: { type: "user-profile", id: t.username, attributes: { ...t, isTrial: t.isTrial === "1", maxConnections: Number(i), activeConnections: Number(d), createdAt: new Date(Number(a) * 1e3), expiresAt: new Date(Number(s) * 1e3) } } }; }, serverInfo: (e) => { const { timestampNow: n, ...s } = h(e); return { data: { type: "server-info", id: e.url, attributes: { ...s, timeNow: new Date(Number(n) * 1e3) } } }; }, channelCategories: (e) => x(e, "channel-category"), movieCategories: (e) => x(e, "movie-category"), showCategories: (e) => x(e, "show-category"), channels: (e) => ({ data: h(e).map((s) => { const { added: i, num: d, streamId: a, categoryIds: t, streamIcon: m, epgChannelId: p, tvArchive: u, name: l, tvArchiveDuration: b, url: v } = s; return { type: "channel", id: a.toString(), attributes: { name: l, number: d, tvArchive: u === 1, tvArchiveDuration: b, logo: m, epgId: p, createdAt: new Date(Number(i) * 1e3), url: v }, ...t.length > 0 && { relationships: { categories: { data: t.map((y) => ({ type: "channel-category", id: y.toString() })) } } } }; }) }), movies: (e) => ({ data: h(e).map((s) => { const { streamIcon: i, streamId: d, releaseDate: a, rating: t, added: m, categoryIds: p, episodeRunTime: u, genre: l, cast: b, director: v, youtubeTrailer: y, title: w, plot: N, url: D } = s; return { type: "movie", id: d.toString(), attributes: { name: w, plot: N, genre: l?.split(",").map((o) => o.trim()) ?? [], cast: b?.split(",").map((o) => o.trim()) ?? [], director: v?.split(",").map((o) => o.trim()) ?? [], poster: i, voteAverage: Number(t), duration: Number(u) * 60, youtubeId: y, releaseDate: a ? new Date(a) : null, createdAt: new Date(Number(m) * 1e3), url: D }, ...p.length > 0 && { relationships: { categories: { data: p.map((o) => ({ type: "movie-category", id: o.toString() })) } } } }; }) }), movie: (e) => { const n = h(e, { deep: !0 }), { director: s, actors: i, genre: d, cast: a, oName: t, releaseDate: m, mpaaRating: p, age: u, rating: l, duration: b, durationSecs: v, backdropPath: y, movieImage: w, kinopoiskUrl: N, youtubeTrailer: D, tmdbId: o, name: f, description: T, plot: S, country: k, subtitles: r, bitrate: I } = n.info, { categoryIds: g, streamId: C, added: A } = n.movieData; return { data: { type: "movie", id: C.toString(), attributes: { name: f, originalName: t, description: T, plot: S, informationUrl: N, cover: y[0], poster: w, duration: v, durationFormatted: b, country: k, voteAverage: l, director: s?.split(",").map((c) => c.trim()) ?? [], actors: i?.split(",").map((c) => c.trim()) ?? [], cast: a?.split(",").map((c) => c.trim()) ?? [], genre: d?.split(",").map((c) => c.trim()) ?? [], youtubeId: D, tmdbId: o?.toString(), rating: { mpaa: p, age: Number(u) }, subtitles: r, bitrate: I, releaseDate: m ? new Date(m) : null, createdAt: new Date(Number(A) * 1e3) }, ...g.length > 0 && { relationships: { categories: { data: g.map((c) => ({ type: "movie-category", id: c.toString() })) } } } } }; }, shows: (e) => ({ data: h(e).map((s) => { const { rating: i, seriesId: d, cover: a, categoryIds: t, backdropPath: m, releaseDate: p, episodeRunTime: u, lastModified: l, cast: b, director: v, genre: y, youtubeTrailer: w, title: N, plot: D } = s; return { type: "show", id: d.toString(), attributes: { name: N, plot: D, cast: b?.split(",").map((o) => o.trim()) ?? [], director: v?.split(",").map((o) => o.trim()) ?? [], genre: y?.split(",").map((o) => o.trim()) ?? [], voteAverage: Number(i), poster: a, cover: m[0], duration: Number(u) * 60, youtubeId: w, releaseDate: p ? new Date(p) : null, updatedAt: new Date(Number(l) * 1e3) }, ...t.length > 0 && { relationships: { categories: { data: t.map((o) => ({ type: "show-category", id: o.toString() })) } } } }; }) }), show: (e) => { const { seasons: n, info: s, episodes: i } = h(e, { deep: !0 }), { rating: d, seriesId: a, cover: t, categoryIds: m, backdropPath: p, releaseDate: u, episodeRunTime: l, lastModified: b, cast: v, director: y, genre: w, youtubeTrailer: N, title: D, plot: o } = s; if (typeof a > "u") throw new Error("seriesId is required"); const f = Object.values(i).flat(), T = f.map((r) => { const { id: I, season: g, title: C, subtitles: A, url: c, episodeNum: O, added: P, info: E } = r, { releaseDate: B, rating: J, movieImage: M, coverBig: R, durationSecs: j, duration: z, tmdbId: F, plot: G, video: L, audio: U, bitrate: q } = E, K = n.find(($) => $.seasonNumber === g)?.id.toString() || g.toString(); return { type: "episode", id: I, attributes: { number: Number(O), title: C, plot: G, tmdbId: F?.toString(), poster: M, cover: R, voteAverage: Number(J), duration: j, durationFormatted: z, releaseDate: B ? new Date(B) : null, createdAt: new Date(Number(P) * 1e3), subtitles: A, url: c, video: L, audio: U, bitrate: q }, relationships: { season: { data: { type: "season", id: K } }, show: { data: { type: "show", id: a.toString() } } } }; }); let S = n; S.length === 0 && (S = Object.keys(i).map((r) => { const I = r, g = i[r][0]; return { id: Number(I), name: `Season ${I}`, episodeCount: i[r].length, overview: "", airDate: g.info.releaseDate, cover: g.info.movieImage, seasonNumber: Number(I), voteAverage: Number(g.info.rating), coverBig: g.info.movieImage }; })); const k = S.map((r) => { const { id: I, seasonNumber: g, cover: C, coverBig: A, airDate: c, ...O } = r; return { type: "season", id: I.toString(), attributes: { ...O, releaseDate: c ? new Date(c) : null, number: g, cover: A }, relationships: { show: { data: { type: "show", id: a.toString() } }, episodes: { data: f.filter((P) => P.season === g).map((P) => ({ type: "episode", id: P.id.toString() })) } } }; }); return { data: { type: "show", id: a.toString(), attributes: { name: D, plot: o, voteAverage: Number(d), poster: t, cover: p[0], duration: Number(l) * 60, cast: v?.split(",").map((r) => r.trim()) ?? [], director: y?.split(",").map((r) => r.trim()) ?? [], genre: w?.split(",").map((r) => r.trim()) ?? [], youtubeId: N, releaseDate: u ? new Date(u) : null, updatedAt: new Date(Number(b) * 1e3) }, relationships: { categories: { data: m.map((r) => ({ type: "show-category", id: r.toString() })) }, seasons: { data: S.map((r) => ({ type: "season", id: r.id.toString() })) }, episodes: { data: f.map((r) => ({ type: "episode", id: r.id.toString() })) } } }, included: [...k, ...T] }; }, shortEPG: (e) => { const { epgListings: n } = h(e, { deep: !0 }); return { data: n.map((s) => { const { id: i, channelId: d, lang: a, start: t, end: m, title: p, description: u, epgId: l } = s; return { type: "epg-listing", id: i.toString(), attributes: { epgId: l, start: new Date(t), end: new Date(Number(m) * 1e3), title: atob(p), description: atob(u), language: a }, relationships: { channel: { data: { type: "channel", id: d.toString() } } } }; }) }; }, fullEPG: (e) => { const { epgListings: n } = h(e, { deep: !0 }); return { data: n.map((s) => { const { id: i, channelId: d, start: a, end: t, title: m, description: p, nowPlaying: u, hasArchive: l, lang: b, epgId: v } = s; return { type: "epg-listing", id: i.toString(), attributes: { epgId: v, start: new Date(a), end: new Date(t), title: atob(m), description: atob(p), language: b, nowPlaying: !!u, hasArchive: !!l }, relationships: { channel: { data: { type: "channel", id: d.toString() } } } }; }) }; } }); function x(e, n) { return { data: h(e).map((i) => { const { categoryId: d, categoryName: a, parentId: t } = i; return { type: n, id: d.toString(), attributes: { name: a }, ...t && { relationships: { parent: { data: { type: n, id: t.toString() } } } } }; }) }; } export { W as JSONAPISerializer };