When adding media from plex, the UI will now use dizqueTV as a proxy to connect to Plex. Thanks to this the 'ui route' is no longer necessary. Connection to plex through UI is still in use for authenticating with plex when adding the servers.
This commit is contained in:
parent
4cdf87121a
commit
7daad9e33f
36
index.js
36
index.js
@ -32,6 +32,8 @@ const ProgrammingService = require("./src/services/programming-service");
|
||||
const ActiveChannelService = require('./src/services/active-channel-service')
|
||||
const ProgramPlayTimeDB = require('./src/dao/program-play-time-db')
|
||||
const FfmpegSettingsService = require('./src/services/ffmpeg-settings-service')
|
||||
const PlexProxyService = require('./src/services/plex-proxy-service')
|
||||
const PlexServerDB = require('./src/dao/plex-server-db');
|
||||
|
||||
const onShutdown = require("node-graceful-shutdown").onShutdown;
|
||||
|
||||
@ -107,6 +109,9 @@ fillerDB = new FillerDB( path.join(process.env.DATABASE, 'filler') , channelServ
|
||||
customShowDB = new CustomShowDB( path.join(process.env.DATABASE, 'custom-shows') );
|
||||
let programPlayTimeDB = new ProgramPlayTimeDB( path.join(process.env.DATABASE, 'play-cache') );
|
||||
let ffmpegSettingsService = new FfmpegSettingsService(db, unlockPath);
|
||||
let plexServerDB = new PlexServerDB(channelService, fillerDB, customShowDB, db);
|
||||
let plexProxyService = new PlexProxyService(plexServerDB);
|
||||
|
||||
|
||||
async function initializeProgramPlayTimeDB() {
|
||||
try {
|
||||
@ -251,6 +256,35 @@ channelService.on("channel-update", (data) => {
|
||||
|
||||
let hdhr = HDHR(db, channelDB)
|
||||
let app = express()
|
||||
|
||||
const responseInterceptor = (
|
||||
req,
|
||||
res,
|
||||
next
|
||||
) => {
|
||||
|
||||
let t0 = new Date().getTime();
|
||||
|
||||
const originalSend = res.send;
|
||||
let responseSent = false;
|
||||
console.log(`${req.method} ${req.url} ...`);
|
||||
|
||||
res.send = function (body) {
|
||||
|
||||
if (!responseSent) {
|
||||
let t1 = new Date().getTime();
|
||||
let dt = t1 - t0;
|
||||
console.log(`${req.method} ${req.url} ${res.statusCode} in ${dt}ms`);
|
||||
responseSent = true;
|
||||
}
|
||||
|
||||
return originalSend.call(this, body);
|
||||
};
|
||||
|
||||
next();
|
||||
};
|
||||
app.use(responseInterceptor);
|
||||
|
||||
eventService.setup(app);
|
||||
|
||||
app.use(
|
||||
@ -290,7 +324,7 @@ app.use('/favicon.svg', express.static(
|
||||
app.use('/custom.css', express.static(path.join(process.env.DATABASE, 'custom.css')))
|
||||
|
||||
// API Routers
|
||||
app.use(api.router(db, channelService, fillerDB, customShowDB, xmltvInterval, guideService, m3uService, eventService, ffmpegSettingsService))
|
||||
app.use(api.router(db, channelService, fillerDB, customShowDB, xmltvInterval, guideService, m3uService, eventService, ffmpegSettingsService, plexServerDB, plexProxyService))
|
||||
app.use('/api/cache/images', cacheImageService.apiRouters())
|
||||
app.use('/' + fontAwesome, express.static(path.join(process.env.DATABASE, fontAwesome)))
|
||||
app.use('/' + bootstrap, express.static(path.join(process.env.DATABASE, bootstrap)))
|
||||
|
||||
13
src/api.js
13
src/api.js
@ -24,10 +24,9 @@ function safeString(object) {
|
||||
}
|
||||
|
||||
module.exports = { router: api }
|
||||
function api(db, channelService, fillerDB, customShowDB, xmltvInterval, guideService, _m3uService, eventService, ffmpegSettingsService ) {
|
||||
function api(db, channelService, fillerDB, customShowDB, xmltvInterval, guideService, _m3uService, eventService, ffmpegSettingsService, plexServerDB, plexProxyService ) {
|
||||
let m3uService = _m3uService;
|
||||
const router = express.Router()
|
||||
const plexServerDB = new PlexServerDB(channelService, fillerDB, customShowDB, db);
|
||||
|
||||
router.get('/api/version', async (req, res) => {
|
||||
try {
|
||||
@ -216,7 +215,15 @@ function api(db, channelService, fillerDB, customShowDB, xmltvInterval, guideSe
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
router.get('/api/plex-server/:serverName64/:path(*)', async (req, res) => {
|
||||
try {
|
||||
let result = await plexProxyService.get(req.params.serverName64, req.params.path);
|
||||
res.status(200).send(result);
|
||||
} catch (err) {
|
||||
console.error("Could not use plex proxy.", err);
|
||||
res.status(404).send("Could not call plex server.");
|
||||
}
|
||||
});
|
||||
|
||||
// Channels
|
||||
router.get('/api/channels', async (req, res) => {
|
||||
|
||||
@ -15,6 +15,17 @@ class PlexServerDB
|
||||
this.showDB = showDB;
|
||||
}
|
||||
|
||||
async getPlexServerByName(name) {
|
||||
let servers = this.db['plex-servers'].find()
|
||||
let server = servers.sort( (a,b) => { return a.index - b.index } )
|
||||
.filter( (server) => name === server.name )
|
||||
[0];
|
||||
if (typeof(server) === "undefined") {
|
||||
return null;
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
async fixupAllChannels(name, newServer) {
|
||||
let channelNumbers = await this.channelService.getAllChannelNumbers();
|
||||
let report = await Promise.all( channelNumbers.map( async (i) => {
|
||||
|
||||
30
src/services/plex-proxy-service.js
Normal file
30
src/services/plex-proxy-service.js
Normal file
@ -0,0 +1,30 @@
|
||||
const Plex = require('../plex.js')
|
||||
const events = require('events')
|
||||
|
||||
class PlexProxyService extends events.EventEmitter {
|
||||
|
||||
constructor(plexServerDB) {
|
||||
super();
|
||||
this.plexServerDB = plexServerDB;
|
||||
}
|
||||
|
||||
async get(serverName64, path) {
|
||||
let plexServer = await getPlexServer(this.plexServerDB, serverName64);
|
||||
let client = new Plex(plexServer);
|
||||
return { MediaContainer: await client.Get("/" + path) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function getPlexServer(plexServerDB, serverName64) {
|
||||
let serverKey = Buffer.from(serverName64, 'base64').toString('utf-8');
|
||||
let server = await plexServerDB.getPlexServerByName(serverKey);
|
||||
if (server == null) {
|
||||
throw Error("server not found");
|
||||
}
|
||||
return server;
|
||||
|
||||
}
|
||||
|
||||
module.exports = PlexProxyService
|
||||
@ -31,13 +31,7 @@ module.exports = function (plex, dizquetv, $timeout, commonProgramTools) {
|
||||
});
|
||||
}
|
||||
scope.selectOrigin = function (origin) {
|
||||
if ( origin.type === 'plex' ) {
|
||||
scope.plexServer = origin.server;
|
||||
updateLibrary(scope.plexServer);
|
||||
} else {
|
||||
scope.plexServer = undefined;
|
||||
updateCustomShows();
|
||||
}
|
||||
updateLibrary(origin);
|
||||
}
|
||||
scope._onFinish = (s, insertPoint) => {
|
||||
if (s.length > scope.limit) {
|
||||
@ -99,20 +93,31 @@ module.exports = function (plex, dizquetv, $timeout, commonProgramTools) {
|
||||
"type" : "plex",
|
||||
"name" : `Plex - ${s.name}`,
|
||||
"server": s,
|
||||
"loaded" : false,
|
||||
}
|
||||
} );
|
||||
scope.currentOrigin = scope.origins[0];
|
||||
scope.plexServer = scope.currentOrigin.server;
|
||||
scope.origins.push( {
|
||||
"type": "dizquetv",
|
||||
"name" : "dizqueTV - Custom Shows",
|
||||
"loaded" : false,
|
||||
} );
|
||||
updateLibrary(scope.plexServer)
|
||||
updateLibrary(scope.origins[0])
|
||||
})
|
||||
|
||||
let updateLibrary = async(server) => {
|
||||
let updateLibrary = async(origin) => {
|
||||
scope.currentOrigin = origin;
|
||||
origin.loaded = false;
|
||||
if ( origin.type !== 'plex' ) {
|
||||
scope.plexServer = undefined;
|
||||
await updateCustomShows();
|
||||
origin.loaded = true;
|
||||
return;
|
||||
}
|
||||
let server = scope.currentOrigin.server;
|
||||
let lib = await plex.getLibrary(server);
|
||||
let play = await plex.getPlaylists(server);
|
||||
scope.currentOrigin.loaded = true;
|
||||
scope.plexServer = server;
|
||||
|
||||
play.forEach( p => {
|
||||
p.type = "playlist";
|
||||
|
||||
@ -20,12 +20,9 @@ module.exports = function (plex, dizquetv, $timeout) {
|
||||
scope.servers = servers;
|
||||
if(servers) {
|
||||
for (let i = 0; i < scope.servers.length; i++) {
|
||||
scope.servers[i].uiStatus = 0;
|
||||
scope.servers[i].backendStatus = 0;
|
||||
let t = (new Date()).getTime();
|
||||
scope.servers[i].uiPending = t;
|
||||
scope.servers[i].backendPending = t;
|
||||
scope.refreshUIStatus(t, i);
|
||||
scope.refreshBackendStatus(t, i);
|
||||
}
|
||||
}
|
||||
@ -51,22 +48,6 @@ module.exports = function (plex, dizquetv, $timeout) {
|
||||
scope.refreshServerList();
|
||||
}
|
||||
|
||||
scope.isAnyUIBad = () => {
|
||||
let t = (new Date()).getTime();
|
||||
if(scope.servers) {
|
||||
for (let i = 0; i < scope.servers.length; i++) {
|
||||
let s = scope.servers[i];
|
||||
if (
|
||||
(s.uiStatus == -1)
|
||||
|| ( (s.uiStatus == 0) && (s.uiPending + 30000 < t) )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
scope.isAnyBackendBad = () => {
|
||||
let t = (new Date()).getTime();
|
||||
if(scope.servers) {
|
||||
@ -84,15 +65,6 @@ module.exports = function (plex, dizquetv, $timeout) {
|
||||
};
|
||||
|
||||
|
||||
scope.refreshUIStatus = async (t, i) => {
|
||||
let s = await plex.check(scope.servers[i]);
|
||||
if (scope.servers[i].uiPending == t) {
|
||||
// avoid updating for a previous instance of the row
|
||||
scope.servers[i].uiStatus = s;
|
||||
}
|
||||
scope.$apply();
|
||||
};
|
||||
|
||||
scope.refreshBackendStatus = async (t, i) => {
|
||||
let s = await dizquetv.checkExistingPlexServer(scope.servers[i].name);
|
||||
if (scope.servers[i].backendPending == t) {
|
||||
|
||||
@ -19,12 +19,10 @@
|
||||
"minutes_to_sign_plex": "You have 2 minutes to sign into your Plex Account.",
|
||||
"name": "Name",
|
||||
"uri": "URI",
|
||||
"ui_route": "UI Route",
|
||||
"backend_route": "Backend Route",
|
||||
"routeStatus": "Route Status",
|
||||
"ok": "ok",
|
||||
"error": "error",
|
||||
"ui_bad": "If a Plex server configuration has problems with the UI route, the channel editor won't be able to access its content.",
|
||||
"backend_bad": "If a Plex server configuration has problems with the backend route, dizqueTV won't be able to play its content.",
|
||||
"backend_bad": "A route problem means the dizqueTV server can't establish a connection with the configured Plex server.",
|
||||
"plex_transcoder_settings": "Plex Transcoder Settings",
|
||||
"update": "Update",
|
||||
"reset_options": "Reset Options",
|
||||
|
||||
@ -43,7 +43,13 @@
|
||||
</button>
|
||||
Content:
|
||||
</label>
|
||||
<ul ng-show="currentOrigin.type=='plex' " class="list-group list-group-root plex-panel" ng-init="setHeight = {'height': height + 'px'}" ng-style="setHeight" lazy-img-container>
|
||||
|
||||
<ul ng-show="currentOrigin.loaded!==true" class="list-group list-group-root plex-panel" ng-init="setHeight = {'height': height + 'px'}" ng-style="setHeight" lazy-img-container>
|
||||
|
||||
<li class="list-group-item"><div class="loader"></div> <div>Loading Library Contents...</div></li>
|
||||
|
||||
</ul>
|
||||
<ul ng-show="currentOrigin.type=='plex' && currentOrigin.loaded===true " class="list-group list-group-root plex-panel" ng-init="setHeight = {'height': height + 'px'}" ng-style="setHeight" lazy-img-container>
|
||||
<li class="list-group-item" ng-repeat="a in libraries">
|
||||
<div class="flex-container library-item-hover {{ displayImages ? 'w_images' : 'wo_images' }}" ng-click="getNested(a, true);">
|
||||
<span class="fa {{ a.collapse ? 'fa-chevron-down' : 'fa-chevron-right' }} tab"></span>
|
||||
@ -122,7 +128,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul ng-show="currentOrigin.type=='dizquetv' " class="list-group list-group-root plex-panel" ng-init="setHeight = {'height': height + 'px'}" ng-style="setHeight" lazy-img-container>
|
||||
<ul ng-show="currentOrigin.type=='dizquetv' && currentOrigin.loaded===true" class="list-group list-group-root plex-panel" ng-init="setHeight = {'height': height + 'px'}" ng-style="setHeight" lazy-img-container>
|
||||
<li class="list-group-item" ng-repeat="x in customShows">
|
||||
<div class="flex-container" ng-click="addCustomShow(x);">
|
||||
<span class="fa fa-plus-circle tab"></span>
|
||||
|
||||
@ -16,8 +16,7 @@
|
||||
<tr>
|
||||
<th>{{'settings_server.name' | i18next}}</th>
|
||||
<th>{{'settings_server.uri' | i18next}}</th>
|
||||
<th>{{'settings_server.ui_route' | i18next}}</th>
|
||||
<th>{{'settings_server.backend_route' | i18next}}</th>
|
||||
<th>{{'settings_server.routeStatus' | i18next}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr ng-if="servers.length === 0">
|
||||
@ -31,11 +30,6 @@
|
||||
<tr ng-repeat="x in servers" ng-hide="serversPending" >
|
||||
<td>{{ x.name }}</td>
|
||||
<td><span class='text-secondary text-small'>{{ x.uri }}</span></td>
|
||||
<td>
|
||||
<div class='loader' ng-if="x.uiStatus == 0"></div>
|
||||
<div class='text-success' ng-if="x.uiStatus == 1"><i class='fa fa-check'></i>{{'settings_server.ok' | i18next}}</div>
|
||||
<div class='text-danger' ng-if="x.uiStatus == -1"><i class='fa fa-exclamation-triangle'></i>{{'settings_server.error' | i18next}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class='loader' ng-if="x.backendStatus == 0"></div>
|
||||
<div class='text-success' ng-if="x.backendStatus == 1"><i class='fa fa-check'></i>{{'settings_server.ok' | i18next}}</div>
|
||||
@ -51,11 +45,6 @@
|
||||
<p class="text-center text-danger small">{{serverError}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="isAnyUIBad()">
|
||||
<td colspan="5">
|
||||
<p class="text-center text-danger small">{{'settings_server.ui_bad' | i18next}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="isAnyBackendBad()">
|
||||
<td colspan="5">
|
||||
<p class="text-center text-danger small">{{'settings_server.server_bad' | i18next}}</p>
|
||||
|
||||
@ -49,6 +49,15 @@ module.exports = function ($http, $q) {
|
||||
});
|
||||
return d.data;
|
||||
},
|
||||
getFromPlexProxy: async (serverName, path) => {
|
||||
let serverName64 = Buffer.from(serverName, 'utf-8').toString('base64');
|
||||
let tmp = await ($http({
|
||||
method: 'GET',
|
||||
url : `api/plex-server/${serverName64}${path}`,
|
||||
headers: { "Cache-Control": "no-cache"},
|
||||
}))
|
||||
return tmp.data.MediaContainer;
|
||||
},
|
||||
getPlexSettings: () => {
|
||||
return $http.get('/api/plex-settings').then((d) => { return d.data })
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const Plex = require('../../src/plex');
|
||||
|
||||
module.exports = function ($http, $window, $interval) {
|
||||
module.exports = function (dizquetv, $http, $window, $interval) {
|
||||
let exported = {
|
||||
login: async () => {
|
||||
const headers = {
|
||||
@ -108,14 +108,13 @@ module.exports = function ($http, $window, $interval) {
|
||||
},
|
||||
|
||||
getLibrary: async (server) => {
|
||||
var client = new Plex(server)
|
||||
const res = await client.Get('/library/sections')
|
||||
const res = await dizquetv.getFromPlexProxy(server.name, '/library/sections')
|
||||
var sections = []
|
||||
for (let i = 0, l = typeof res.Directory !== 'undefined' ? res.Directory.length : 0; i < l; i++)
|
||||
if (res.Directory[i].type === 'movie' || res.Directory[i].type === 'show' || res.Directory[i].type === 'artist' ) {
|
||||
var genres = []
|
||||
if (res.Directory[i].type === 'movie') {
|
||||
const genresRes = await client.Get(`/library/sections/${res.Directory[i].key}/genre`)
|
||||
const genresRes = await dizquetv.getFromPlexProxy(server.name,`/library/sections/${res.Directory[i].key}/genre`)
|
||||
for (let q = 0, k = typeof genresRes.Directory !== 'undefined' ? genresRes.Directory.length : 0; q < k; q++) {
|
||||
if (genresRes.Directory[q].type === 'genre') {
|
||||
genres.push({
|
||||
@ -138,8 +137,7 @@ module.exports = function ($http, $window, $interval) {
|
||||
return sections
|
||||
},
|
||||
getPlaylists: async (server) => {
|
||||
var client = new Plex(server)
|
||||
const res = await client.Get('/playlists')
|
||||
const res = await dizquetv.getFromPlexProxy(server.name, '/playlists');
|
||||
var playlists = []
|
||||
for (let i = 0, l = typeof res.Metadata !== 'undefined' ? res.Metadata.length : 0; i < l; i++)
|
||||
if (
|
||||
@ -157,8 +155,7 @@ module.exports = function ($http, $window, $interval) {
|
||||
return playlists
|
||||
},
|
||||
getStreams: async (server, key) => {
|
||||
var client = new Plex(server)
|
||||
return client.Get(key).then((res) => {
|
||||
return dizquetv.getFromPlexProxy(server.name, key).then((res) => {
|
||||
let streams = res.Metadata[0].Media[0].Part[0].Stream
|
||||
for (let i = 0, l = streams.length; i < l; i++) {
|
||||
if (typeof streams[i].key !== 'undefined') {
|
||||
@ -169,9 +166,9 @@ module.exports = function ($http, $window, $interval) {
|
||||
})
|
||||
},
|
||||
getNested: async (server, lib, includeCollections, errors) => {
|
||||
var client = new Plex(server)
|
||||
|
||||
const key = lib.key
|
||||
const res = await client.Get(key)
|
||||
const res = await dizquetv.getFromPlexProxy(server.name, key)
|
||||
|
||||
const size = (typeof(res.Metadata) !== 'undefined') ? res.Metadata.length : 0;
|
||||
var nested = []
|
||||
@ -191,7 +188,8 @@ module.exports = function ($http, $window, $interval) {
|
||||
albumKeys = Object.keys( albumKeys );
|
||||
await Promise.all( albumKeys.map( async(albumKey) => {
|
||||
try {
|
||||
let album = await client.Get(albumKey);
|
||||
let album = await dizquetv.getFromPlexProxy(
|
||||
server.name, albumKey);
|
||||
if ( (typeof(album)!=='undefined') && album.size == 1) {
|
||||
album = album.Metadata[0];
|
||||
}
|
||||
@ -287,7 +285,7 @@ module.exports = function ($http, $window, $interval) {
|
||||
let k = res.librarySectionID;
|
||||
|
||||
k = `/library/sections/${k}/collections`;
|
||||
let collections = await client.Get(k);
|
||||
let collections = await dizquetv.getFromPlexProxy(server.name, k);
|
||||
if ( typeof(collections.Metadata) === 'undefined') {
|
||||
collections.Metadata = [];
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user