mirror of
https://github.com/WebTools-NG/WebTools-NG
synced 2025-02-16 19:38:26 +00:00
#440 Backup done
This commit is contained in:
parent
2fff17ed86
commit
27c3e3605c
11 changed files with 358 additions and 361 deletions
|
@ -327,6 +327,8 @@
|
||||||
"Description": "@:Modules.PMS.Name module allows you to manage your server",
|
"Description": "@:Modules.PMS.Name module allows you to manage your server",
|
||||||
"ErrorNoServerSelectedTitle": "No server selected",
|
"ErrorNoServerSelectedTitle": "No server selected",
|
||||||
"ErrorNoServerSelectedMsg": "You need to select a server on the top of the screen",
|
"ErrorNoServerSelectedMsg": "You need to select a server on the top of the screen",
|
||||||
|
"ExportDoneBody": "Check {0}",
|
||||||
|
"ExportDoneTitle": "Export finished",
|
||||||
"Butler": {
|
"Butler": {
|
||||||
"Title": "Butler Scheduled Tasks",
|
"Title": "Butler Scheduled Tasks",
|
||||||
"Description": "Here you can kickstart a scheduled task",
|
"Description": "Here you can kickstart a scheduled task",
|
||||||
|
@ -388,8 +390,14 @@
|
||||||
"Value": "Value"
|
"Value": "Value"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ExportDoneBody": "Check {0}",
|
"DVR": {
|
||||||
"ExportDoneTitle": "Export finished"
|
"Name": "DVR",
|
||||||
|
"Description": "@:Modules.PMS.DVR.Name module allows you to backup and restore your DVR settings",
|
||||||
|
"selDVR": "Select DVR to backup",
|
||||||
|
"ttselDVR": "Here you select the DVR you want to make a backup of",
|
||||||
|
"lblBtnBackup": "Backup",
|
||||||
|
"BackupDone": "DVR has been saved"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"PlexTV": {
|
"PlexTV": {
|
||||||
"Name": "Plex.TV",
|
"Name": "Plex.TV",
|
||||||
|
@ -407,14 +415,6 @@
|
||||||
"ExportUsr": "Export user to CSV",
|
"ExportUsr": "Export user to CSV",
|
||||||
"ExportAllUsr": "Export all users to CSV",
|
"ExportAllUsr": "Export all users to CSV",
|
||||||
"Settings": "To configure column separator and 'Not Avail', use @:Modules.ET.Name settings"
|
"Settings": "To configure column separator and 'Not Avail', use @:Modules.ET.Name settings"
|
||||||
},
|
}
|
||||||
"DVR": {
|
|
||||||
"Name": "DVR",
|
|
||||||
"Description": "@:Modules.DVR.Name module allows you to backup and restore your DVR settings",
|
|
||||||
"selDVR": "Select DVR to backup",
|
|
||||||
"ttselDVR": "Here you select the DVR you want to make a backup of",
|
|
||||||
"lblBtnBackup": "Backup"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB |
|
@ -1,18 +0,0 @@
|
||||||
# Release Note
|
|
||||||
|
|
||||||
For a complete manual, see the [Wiki](https://github.com/WebTools-NG/WebTools-NG/wiki)
|
|
||||||
|
|
||||||
What's new:
|
|
||||||
|
|
||||||
Please see the [Change Log](https://github.com/WebTools-NG/WebTools-NG/blob/master/CHANGELOG.md)
|
|
||||||
|
|
||||||
This is a BETA release
|
|
||||||
|
|
||||||
Note that the binaries are not signed, since we cannot afford a signing certificate nor a dev membership with Apple
|
|
||||||
* See [Special MAC Work Around](https://github.com/WebTools-NG/WebTools-NG/wiki/Known-Issues#-mac-os)
|
|
||||||
|
|
||||||
Depending on your workstation OS, grab the following file from the assets below:
|
|
||||||
|
|
||||||
Windows: Use the exe file
|
|
||||||
Mac: Use the dmg file
|
|
||||||
Linux: Use the AppImage file
|
|
|
@ -12,8 +12,7 @@
|
||||||
import '@fortawesome/fontawesome-free/css/all.css';
|
import '@fortawesome/fontawesome-free/css/all.css';
|
||||||
import etIcon from '@/assets/ET-256.png';
|
import etIcon from '@/assets/ET-256.png';
|
||||||
import pmsIcon from '@/assets/plex-pms-icon.png';
|
import pmsIcon from '@/assets/plex-pms-icon.png';
|
||||||
import plextvIcon from '@/assets/plex-app-icon.png';
|
import plextvIcon from '@/assets/plex-app-icon.png';
|
||||||
import plexDVRIcon from '@/assets/dvr-256.png';
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -66,14 +65,9 @@
|
||||||
icon: 'fa fa-tasks'
|
icon: 'fa fa-tasks'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: { path: '/dvr' },
|
href: { path: '/pms/dvr' },
|
||||||
title: this.$t("Modules.DVR.Name"),
|
title: this.$t("Modules.PMS.DVR.Name"),
|
||||||
// icon: 'fas fa-file-export',
|
icon: 'fas fa-tv',
|
||||||
icon: {
|
|
||||||
//adjust element
|
|
||||||
element: 'img',
|
|
||||||
attributes: { src: plexDVRIcon },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -84,7 +78,7 @@
|
||||||
icon: {
|
icon: {
|
||||||
//adjust element
|
//adjust element
|
||||||
element: 'img',
|
element: 'img',
|
||||||
attributes: { src: etIcon },
|
attributes: { src: etIcon },
|
||||||
},
|
},
|
||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="col-lg-10 col-md-12 col-xs-12">
|
|
||||||
<h3>{{ $t("Modules.DVR.Name") }} <br>
|
|
||||||
</h3>
|
|
||||||
{{ $t("Modules.DVR.Description") }}
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<b-form-row> <!-- Select Export type -->
|
|
||||||
<b-col> <!-- Main type -->
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
|
|
||||||
<b-form-group id="dvrSelDVRGroup" v-bind:label="$t('Modules.DVR.selDVR')" label-size="lg" label-class="font-weight-bold pt-0" name="dvrSelDVRGroup">
|
|
||||||
<b-tooltip target="dvrSelDVRGroup" triggers="hover">
|
|
||||||
{{ $t('Modules.DVR.ttselDVR') }}
|
|
||||||
</b-tooltip>
|
|
||||||
<b-form-select
|
|
||||||
v-model="selDVR"
|
|
||||||
id="selDVR"
|
|
||||||
:options="optSelDVR"
|
|
||||||
name="selDVR">
|
|
||||||
</b-form-select>
|
|
||||||
</b-form-group>
|
|
||||||
|
|
||||||
<b-button
|
|
||||||
type="is-primary"
|
|
||||||
@click="dvrBackup"
|
|
||||||
icon-left="fas fa-file-download"
|
|
||||||
icon-pack="fas"
|
|
||||||
:disabled="btnDisable == true"
|
|
||||||
variant="success"
|
|
||||||
>
|
|
||||||
{{ $t("Modules.DVR.lblBtnBackup") }}
|
|
||||||
</b-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</b-col>
|
|
||||||
|
|
||||||
</b-form-row>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import i18n from '../../../i18n';
|
|
||||||
//import store from '../../../store';
|
|
||||||
//import { wtconfig } from '../General/wtutils';
|
|
||||||
import { dvr } from "./scripts/dvr";
|
|
||||||
|
|
||||||
i18n, dvr
|
|
||||||
|
|
||||||
const log = require("electron-log");
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
optSelDVR: [],
|
|
||||||
selDVR: "",
|
|
||||||
|
|
||||||
selLibraryWait: true,
|
|
||||||
btnDisable: false,
|
|
||||||
selMediaType: "movie",
|
|
||||||
selLibrary: "",
|
|
||||||
selLibraryOptions: [],
|
|
||||||
selLevel: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
log.info("DVR Created");
|
|
||||||
this.serverSelected();
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
// Watch for when selected server address is updated
|
|
||||||
selectedServerAddress: async function(){
|
|
||||||
log.info("DVR Selected server changed");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
// We need this computed, for watching for changes to selected server
|
|
||||||
selectedServerAddress: function(){
|
|
||||||
return this.$store.getters.getSelectedServerAddress
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async dvrBackup() {
|
|
||||||
log.info("DVR Backup started");
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Check if a server is selected, and if not
|
|
||||||
tell user, and disable backup */
|
|
||||||
async serverSelected() {
|
|
||||||
let serverCheck = this.$store.getters.getSelectedServer;
|
|
||||||
if (serverCheck == "none") {
|
|
||||||
log.debug("serverCheck is none");
|
|
||||||
this.btnDisable = true;
|
|
||||||
this.$bvToast.toast(this.$t("Modules.PMS.ErrorNoServerSelectedMsg"), {
|
|
||||||
title: this.$t("Modules.PMS.ErrorNoServerSelectedTitle"),
|
|
||||||
autoHideDelay: 4000,
|
|
||||||
solid: true,
|
|
||||||
variant: 'primary',
|
|
||||||
toaster: 'b-toaster-bottom-right'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.btnDisable = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped>
|
|
||||||
#sync-button {
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,15 +0,0 @@
|
||||||
// Helper file for dvr.tv module
|
|
||||||
const log = require('electron-log');
|
|
||||||
console.log = log.log;
|
|
||||||
|
|
||||||
|
|
||||||
import {wtconfig, wtutils} from '../../General/wtutils';
|
|
||||||
import i18n from '../../../../i18n';
|
|
||||||
import store from '../../../../store';
|
|
||||||
|
|
||||||
i18n, wtconfig, wtutils, store
|
|
||||||
|
|
||||||
const dvr = new class DVR {
|
|
||||||
}
|
|
||||||
|
|
||||||
dvr
|
|
|
@ -151,59 +151,6 @@ const et = new class ET {
|
||||||
this.OutFile = null
|
this.OutFile = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async GEDDELETE_getSectionData()
|
|
||||||
{
|
|
||||||
const sectionData = []
|
|
||||||
// Find LibType steps
|
|
||||||
const step = wtconfig.get("PMS.ContainerSize." + this.expSettings.libType, 20)
|
|
||||||
log.debug(`!!!! et (getSectionData): Got Step size as: ${step}`)
|
|
||||||
let element
|
|
||||||
// Now read the fields and level defs
|
|
||||||
// Current item
|
|
||||||
let idx = 0
|
|
||||||
// Now let's walk the section
|
|
||||||
let chuncks, postURI
|
|
||||||
let size
|
|
||||||
do {
|
|
||||||
switch (this.expSettings.libType) {
|
|
||||||
case et.ETmediaType.Photo:
|
|
||||||
element = '/library/sections/' + this.expSettings.selLibKey + '/all';
|
|
||||||
postURI = `?addedAt>>=-2208992400&X-Plex-Container-Start=${idx}&X-Plex-Container-Size=${step}&type=${this.expSettings.libTypeSec}&${this.uriParams}`;
|
|
||||||
break;
|
|
||||||
case et.ETmediaType.Playlist:
|
|
||||||
element = '/playlists/' + this.expSettings.selLibKey;
|
|
||||||
postURI = `/items?X-Plex-Container-Start=${idx}&X-Plex-Container-Size=${step}`;
|
|
||||||
break;
|
|
||||||
case et.ETmediaType.Libraries:
|
|
||||||
element = '/library/sections/all';
|
|
||||||
postURI = `?X-Plex-Container-Start=${idx}&X-Plex-Container-Size=${step}`;
|
|
||||||
break;
|
|
||||||
case et.ETmediaType.Playlists:
|
|
||||||
element = '/playlists/all';
|
|
||||||
postURI = `?X-Plex-Container-Start=${idx}&X-Plex-Container-Size=${step}`;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
element = '/library/sections/' + this.expSettings.selLibKey + '/all';
|
|
||||||
postURI = `?X-Plex-Container-Start=${idx}&X-Plex-Container-Size=${step}&type=${this.expSettings.libTypeSec}&${this.uriParams}`;
|
|
||||||
}
|
|
||||||
log.info(`Calling getSectionData url ${this.expSettings.baseURL + element + postURI}`);
|
|
||||||
|
|
||||||
chuncks = await et.getItemData({baseURL: this.expSettings.baseURL, accessToken: this.expSettings.accessToken, element: element, postURI: postURI});
|
|
||||||
size = JSONPath({path: '$.MediaContainer.size', json: chuncks});
|
|
||||||
const totalSize = JSONPath({path: '$.MediaContainer.totalSize', json: chuncks});
|
|
||||||
log.info(`getSectionData chunck size is ${size} and idx is ${idx} and totalsize is ${totalSize}`)
|
|
||||||
// et.updateStatusMsg(et.rawMsgType.Info, i18n.t('Modules.ET.Status.GetSectionItems', {idx: idx, chunck: size, totalSize: totalSize}))
|
|
||||||
et.updateStatusMsg(et.rawMsgType.Info, i18n.t('Modules.ET.Status.GetSectionItems', {chunck: step, totalSize: totalSize}))
|
|
||||||
sectionData.push(chuncks)
|
|
||||||
log.debug(`Pushed chunk as ${JSON.stringify(chuncks)}`)
|
|
||||||
idx = idx + step;
|
|
||||||
} while (size > 1);
|
|
||||||
log.debug(`SectionData to return is:`);
|
|
||||||
log.debug(JSON.stringify(sectionData));
|
|
||||||
return sectionData;
|
|
||||||
}
|
|
||||||
|
|
||||||
getRealLevelName(level, libType) {
|
getRealLevelName(level, libType) {
|
||||||
// First get the real name of the level, and not just the display name
|
// First get the real name of the level, and not just the display name
|
||||||
let levelName
|
let levelName
|
||||||
|
@ -228,47 +175,6 @@ const et = new class ET {
|
||||||
return levelName;
|
return levelName;
|
||||||
}
|
}
|
||||||
|
|
||||||
async DELOLD_getSections(address, accessToken)
|
|
||||||
{
|
|
||||||
// Returns an array of json, as:
|
|
||||||
// [{"title":"DVR Movies","key":31,"type":"movie"}]
|
|
||||||
const result = [];
|
|
||||||
let url = address + '/library/sections/all'
|
|
||||||
this.PMSHeader["X-Plex-Token"] = accessToken;
|
|
||||||
let response = await fetch(url, { method: 'GET', headers: this.PMSHeader});
|
|
||||||
let resp = await response.json();
|
|
||||||
let respJSON = await Promise.resolve(resp);
|
|
||||||
let sections = await JSONPath({path: '$..Directory', json: respJSON})[0];
|
|
||||||
let section;
|
|
||||||
for (section of sections){
|
|
||||||
const subItem = {}
|
|
||||||
subItem['title'] = JSONPath({path: '$..title', json: section})[0];
|
|
||||||
subItem['key'] = parseInt(JSONPath({path: '$..key', json: section})[0]);
|
|
||||||
subItem['type'] = JSONPath({path: '$..type', json: section})[0];
|
|
||||||
subItem['scanner'] = JSONPath({path: '$..scanner', json: section})[0];
|
|
||||||
subItem['agent'] = JSONPath({path: '$..agent', json: section})[0];
|
|
||||||
result.push(subItem)
|
|
||||||
}
|
|
||||||
await Promise.resolve(result);
|
|
||||||
url = address + '/playlists';
|
|
||||||
response = await fetch(url, { method: 'GET', headers: this.PMSHeader});
|
|
||||||
resp = await response.json();
|
|
||||||
respJSON = await Promise.resolve(resp);
|
|
||||||
if (JSONPath({path: '$..size', json: respJSON})[0] > 0)
|
|
||||||
{
|
|
||||||
sections = await JSONPath({path: '$..Metadata', json: respJSON})[0];
|
|
||||||
for (section of sections){
|
|
||||||
const subItem = {}
|
|
||||||
subItem['title'] = JSONPath({path: '$..title', json: section})[0];
|
|
||||||
subItem['key'] = parseInt(JSONPath({path: '$..ratingKey', json: section})[0]);
|
|
||||||
subItem['type'] = JSONPath({path: '$..type', json: section})[0];
|
|
||||||
subItem['playlistType'] = JSONPath({path: '$..playlistType', json: section})[0];
|
|
||||||
result.push(subItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
getLevelDisplayName(level, libType){
|
getLevelDisplayName(level, libType){
|
||||||
// return displayname for the buildin levels
|
// return displayname for the buildin levels
|
||||||
if (libType == et.ETmediaType.Playlist)
|
if (libType == et.ETmediaType.Playlist)
|
||||||
|
|
129
src/components/modules/PMS/DVR/DVR.vue
Normal file
129
src/components/modules/PMS/DVR/DVR.vue
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
<template>
|
||||||
|
<b-container fluid>
|
||||||
|
<div class="col-lg-10 col-md-12 col-xs-12">
|
||||||
|
<h1>{{ $t("Modules.PMS.DVR.Name") }}</h1>
|
||||||
|
<p>{{ $t("Modules.PMS.DVR.Description") }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<b-form-group id="dvrSelDVRGroup" v-bind:label="$t('Modules.PMS.DVR.selDVR')" label-size="lg" label-class="font-weight-bold pt-0" name="dvrSelDVRGroup">
|
||||||
|
<b-tooltip target="dvrSelDVRGroup" triggers="hover">
|
||||||
|
{{ $t('Modules.PMS.DVR.ttselDVR') }}
|
||||||
|
</b-tooltip>
|
||||||
|
<b-form-select
|
||||||
|
v-model="selDVR"
|
||||||
|
id="selDVR"
|
||||||
|
:options="optSelDVR"
|
||||||
|
name="selDVR">
|
||||||
|
</b-form-select>
|
||||||
|
</b-form-group>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<div class="buttons">
|
||||||
|
<!-- Buttons -->
|
||||||
|
<div id="buttons" class="text-center">
|
||||||
|
<b-button-group >
|
||||||
|
<b-button
|
||||||
|
type="is-primary"
|
||||||
|
@click="dvrBackup"
|
||||||
|
icon-left="fas fa-file-download"
|
||||||
|
icon-pack="fas"
|
||||||
|
:disabled="this.selDVR == ''"
|
||||||
|
variant="success"
|
||||||
|
>
|
||||||
|
{{ $t("Modules.PMS.DVR.lblBtnBackup") }}
|
||||||
|
</b-button>
|
||||||
|
</b-button-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</b-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import i18n from '../../../../i18n';
|
||||||
|
//import store from '../../../store';
|
||||||
|
//import { wtconfig } from '../General/wtutils';
|
||||||
|
import { dvr } from "./scripts/dvr";
|
||||||
|
|
||||||
|
i18n, dvr
|
||||||
|
|
||||||
|
const log = require("electron-log");
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
optSelDVR: [],
|
||||||
|
selDVR: ""
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
log.info("DVR Created");
|
||||||
|
this.serverSelected();
|
||||||
|
this.optSelDVR = this.getDVRList();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// Watch for when selected server address is updated
|
||||||
|
selectedServerAddress: async function(){
|
||||||
|
log.info("DVR Selected server changed");
|
||||||
|
this.optSelDVR = this.getDVRList();
|
||||||
|
},
|
||||||
|
doneDVRBackup: async function(){
|
||||||
|
if (this.$store.getters.doneDVRBackup!='')
|
||||||
|
{
|
||||||
|
this.$bvToast.toast(this.$t(this.$store.getters.doneDVRBackup), {
|
||||||
|
title: this.$t("Modules.PMS.DVR.BackupDone"),
|
||||||
|
autoHideDelay: 4000,
|
||||||
|
solid: true,
|
||||||
|
variant: 'primary',
|
||||||
|
toaster: 'b-toaster-bottom-right'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// We need this computed, for watching for changes to selected server
|
||||||
|
selectedServerAddress: function(){
|
||||||
|
return this.$store.getters.getSelectedServerAddress
|
||||||
|
},
|
||||||
|
doneDVRBackup: function(){
|
||||||
|
return this.$store.getters.doneDVRBackup
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async dvrBackup() {
|
||||||
|
log.info("DVR Backup started");
|
||||||
|
dvr.backupDVR( {'dvrName': this.selDVR} );
|
||||||
|
},
|
||||||
|
async getDVRList() {
|
||||||
|
this.optSelDVR = await dvr.getDVRList();
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Check if a server is selected, and if not
|
||||||
|
tell user, and disable backup */
|
||||||
|
async serverSelected() {
|
||||||
|
let serverCheck = this.$store.getters.getSelectedServer;
|
||||||
|
if (serverCheck == "none") {
|
||||||
|
log.debug("serverCheck is none");
|
||||||
|
this.selDVR = "";
|
||||||
|
this.$bvToast.toast(this.$t("Modules.PMS.ErrorNoServerSelectedMsg"), {
|
||||||
|
title: this.$t("Modules.PMS.ErrorNoServerSelectedTitle"),
|
||||||
|
autoHideDelay: 4000,
|
||||||
|
solid: true,
|
||||||
|
variant: 'primary',
|
||||||
|
toaster: 'b-toaster-bottom-right'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
#sync-button {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
113
src/components/modules/PMS/DVR/scripts/dvr.js
Normal file
113
src/components/modules/PMS/DVR/scripts/dvr.js
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
// Helper file for dvr.tv module
|
||||||
|
const log = require('electron-log');
|
||||||
|
const {JSONPath} = require('jsonpath-plus');
|
||||||
|
console.log = log.log;
|
||||||
|
|
||||||
|
|
||||||
|
import {wtconfig, wtutils} from '../../../General/wtutils';
|
||||||
|
import i18n from '../../../../../i18n';
|
||||||
|
import store from '../../../../../store';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
i18n, wtconfig
|
||||||
|
|
||||||
|
const dvr = new class DVR {
|
||||||
|
async getDVRList(){
|
||||||
|
log.info(`Getting list of DVRs`);
|
||||||
|
// Placeholder for return value
|
||||||
|
let arrDVR = [];
|
||||||
|
let header = wtutils.PMSHeader;
|
||||||
|
header['X-Plex-Token'] = store.getters.getSelectedServerToken;
|
||||||
|
const url = `${store.getters.getSelectedServerAddress}/livetv/dvrs`;
|
||||||
|
log.verbose(`Url to query is: ${url}`);
|
||||||
|
let DVRs;
|
||||||
|
await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: url,
|
||||||
|
headers: header
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
log.debug('Response from getDVRList recieved');
|
||||||
|
DVRs = JSONPath({path: '$..Dvr[*]', json: response.data});
|
||||||
|
// Save to store
|
||||||
|
store.commit('UPDATE_DVR_SETTINGS', DVRs);
|
||||||
|
log.verbose('DVRs added to store')
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
if (error.response) {
|
||||||
|
log.error('getDVRList: ' + error.response.data);
|
||||||
|
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
|
||||||
|
} else if (error.request) {
|
||||||
|
log.error('getDVRList: ' + error.request);
|
||||||
|
} else {
|
||||||
|
log.error('getDVRList: ' + error.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
DVRs.forEach(dvr => {
|
||||||
|
arrDVR.push({
|
||||||
|
"value": JSONPath({path: '$.uuid', json: dvr}),
|
||||||
|
"text": JSONPath({path: '$.lineupTitle', json: dvr})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return arrDVR;
|
||||||
|
}
|
||||||
|
|
||||||
|
async backupDVR( { dvrName } ){
|
||||||
|
let fileName = await this.getFileName( {'dvrName': dvrName} );
|
||||||
|
const fs = require('fs');
|
||||||
|
let data = await this.getDVR( dvrName );
|
||||||
|
fs.writeFileSync(fileName, JSON.stringify(data, null, 2));
|
||||||
|
store.commit('UPDATE_doneDVRBackup', fileName);
|
||||||
|
log.debug(`DVR backedup to ${fileName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDVR( uuid ){
|
||||||
|
let DVRs = store.getters.getDVRs;
|
||||||
|
let retVal='';
|
||||||
|
DVRs.forEach( dvr => {
|
||||||
|
if (dvr['uuid']==uuid){
|
||||||
|
retVal = dvr;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDVRName( { uuid } ){
|
||||||
|
let DVRs = store.getters.getDVRs;
|
||||||
|
let retVal='';
|
||||||
|
DVRs.forEach( dvr => {
|
||||||
|
if (dvr['uuid']==uuid){
|
||||||
|
retVal = dvr['lineupTitle'];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFileName( { dvrName } ){
|
||||||
|
/*
|
||||||
|
Will create the output directory if it doesn't exists
|
||||||
|
Will return a string with the filename to use
|
||||||
|
*/
|
||||||
|
const realDVRName = await this.getDVRName( { 'uuid': dvrName })
|
||||||
|
const path = require('path');
|
||||||
|
const Module = path.join('Plex Media Server', 'DVR');
|
||||||
|
const dateFormat = require('dateformat');
|
||||||
|
const OutDir = wtconfig.get('General.ExportPath');
|
||||||
|
const timeStamp=dateFormat(new Date(), "yyyy.mm.dd_h.MM.ss");
|
||||||
|
let outFile = store.getters.getSelectedServer['name'] + '_' + realDVRName + '_' + timeStamp + '.json';
|
||||||
|
const targetDir = path.join(
|
||||||
|
OutDir, wtutils.AppName, Module);
|
||||||
|
const outFileWithPath = path.join(
|
||||||
|
targetDir, outFile);
|
||||||
|
// Make sure target dir exists
|
||||||
|
const fs = require('fs')
|
||||||
|
if (!fs.existsSync(targetDir)) {
|
||||||
|
fs.mkdirSync(targetDir, { recursive: true });
|
||||||
|
}
|
||||||
|
log.info(`OutFile is ${outFileWithPath}`)
|
||||||
|
return outFileWithPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export { dvr };
|
|
@ -11,7 +11,7 @@ import PMSSettings from '../components/modules/PMS/Settings/settings';
|
||||||
import Butler from '../components/modules/PMS/Butler/butler';
|
import Butler from '../components/modules/PMS/Butler/butler';
|
||||||
import Language from '../components/modules/Main/Language.vue';
|
import Language from '../components/modules/Main/Language.vue';
|
||||||
import GlobalSettings from '../components/modules/Main/GlobalSettings';
|
import GlobalSettings from '../components/modules/Main/GlobalSettings';
|
||||||
import DVR from '../components/modules/DVR/DVR';
|
import DVR from '../components/modules/PMS/DVR/DVR';
|
||||||
import About from '../components/modules/Main/About';
|
import About from '../components/modules/Main/About';
|
||||||
import Store from '../store/index.js';
|
import Store from '../store/index.js';
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ Vue.use(VueRouter)
|
||||||
meta: {requiresAuth: true}
|
meta: {requiresAuth: true}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/dvr',
|
path: '/pms/dvr',
|
||||||
name: "dvr",
|
name: "dvr",
|
||||||
component: DVR,
|
component: DVR,
|
||||||
meta: {requiresAuth: true}
|
meta: {requiresAuth: true}
|
||||||
|
|
|
@ -6,17 +6,27 @@ const log = require('electron-log');
|
||||||
const {JSONPath} = require('jsonpath-plus');
|
const {JSONPath} = require('jsonpath-plus');
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
settings: {}
|
settings: {},
|
||||||
|
DVRs: {},
|
||||||
|
doneDVRBackup: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
UPDATE_PMS_SETTINGS(state, payload) {
|
UPDATE_PMS_SETTINGS(state, payload) {
|
||||||
state.settings = payload;
|
state.settings = payload;
|
||||||
}
|
},
|
||||||
|
UPDATE_DVR_SETTINGS(state, payload) {
|
||||||
|
state.DVRs = payload;
|
||||||
|
},
|
||||||
|
UPDATE_doneDVRBackup(state, payload) {
|
||||||
|
state.doneDVRBackup = payload;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
getPMSSettings: state => state.settings
|
getPMSSettings: state => state.settings,
|
||||||
|
getDVRs: state => state.DVRs,
|
||||||
|
doneDVRBackup: state => state.doneDVRBackup
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
@ -78,97 +88,94 @@ const actions = {
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
async fetchPMSSettings({ commit }, payload) {
|
||||||
async fetchPMSSettings({ commit }, payload) {
|
let header = wtutils.PMSHeader;
|
||||||
let header = wtutils.PMSHeader;
|
header['X-Plex-Token'] = payload.Token;
|
||||||
header['X-Plex-Token'] = payload.Token;
|
const url = payload.Address + '/:/prefs';
|
||||||
const url = payload.Address + '/:/prefs';
|
await axios({
|
||||||
await axios({
|
method: 'get',
|
||||||
method: 'get',
|
url: url,
|
||||||
url: url,
|
headers: header
|
||||||
headers: header
|
})
|
||||||
|
.then((response) => {
|
||||||
|
log.debug('Response from fetchPlexServers recieved')
|
||||||
|
var filteredResult = {}
|
||||||
|
// Filtered result based on hidden, adv or all
|
||||||
|
var curFilter = wtconfig.get('PMS.FilterSetting', 'AllSettings');
|
||||||
|
log.verbose(`Filter set to ${curFilter}`);
|
||||||
|
if (curFilter == 'AllSettings'){
|
||||||
|
filteredResult = JSONPath({path: '$..Setting', json: response.data})[0];
|
||||||
|
}
|
||||||
|
else if (curFilter == 'OnlyHidden'){
|
||||||
|
filteredResult = JSONPath({path: '$..Setting[?(@.hidden==true)]', json: response.data});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filteredResult = JSONPath({path: '$..Setting[?(@.advanced==true)]', json: response.data});
|
||||||
|
}
|
||||||
|
// Reset PMSSettings
|
||||||
|
var PMSSettings = {};
|
||||||
|
// Create Array for undefined
|
||||||
|
PMSSettings[i18n.t('Modules.PMS.Settings.Undefined')] = [];
|
||||||
|
// Create Arrays for other categories
|
||||||
|
filteredResult.forEach(group => {
|
||||||
|
group = JSONPath({path: '$.group', json: group})[0]
|
||||||
|
if (group !== "") {
|
||||||
|
PMSSettings[group] = [];
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then((response) => {
|
// Get the single items
|
||||||
log.debug('Response from fetchPlexServers recieved')
|
filteredResult.forEach(element => {
|
||||||
var filteredResult = {}
|
var id = JSONPath({path: '$.id', json: element});
|
||||||
// Filtered result based on hidden, adv or all
|
var itemGroup = JSONPath({path: '$.group', json: element});
|
||||||
var curFilter = wtconfig.get('PMS.FilterSetting', 'AllSettings');
|
if (itemGroup == "")
|
||||||
log.verbose(`Filter set to ${curFilter}`);
|
|
||||||
if (curFilter == 'AllSettings'){
|
|
||||||
filteredResult = JSONPath({path: '$..Setting', json: response.data})[0];
|
|
||||||
}
|
|
||||||
else if (curFilter == 'OnlyHidden'){
|
|
||||||
filteredResult = JSONPath({path: '$..Setting[?(@.hidden==true)]', json: response.data});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filteredResult = JSONPath({path: '$..Setting[?(@.advanced==true)]', json: response.data});
|
|
||||||
}
|
|
||||||
// Reset PMSSettings
|
|
||||||
var PMSSettings = {};
|
|
||||||
// Create Array for undefined
|
|
||||||
PMSSettings[i18n.t('Modules.PMS.Settings.Undefined')] = [];
|
|
||||||
// Create Arrays for other categories
|
|
||||||
filteredResult.forEach(group => {
|
|
||||||
group = JSONPath({path: '$.group', json: group})[0]
|
|
||||||
if (group !== "") {
|
|
||||||
PMSSettings[group] = [];
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// Get the single items
|
|
||||||
filteredResult.forEach(element => {
|
|
||||||
var id = JSONPath({path: '$.id', json: element});
|
|
||||||
var itemGroup = JSONPath({path: '$.group', json: element});
|
|
||||||
if (itemGroup == "")
|
|
||||||
{
|
|
||||||
itemGroup = i18n.t('Modules.PMS.Settings.Undefined');
|
|
||||||
}
|
|
||||||
var PMSSettingsItem = {}
|
|
||||||
var jNode = {};
|
|
||||||
jNode['label'] = JSONPath({path: '$.label', json: element})[0];
|
|
||||||
jNode['summary'] = JSONPath({path: '$.summary', json: element})[0];
|
|
||||||
jNode['type'] = JSONPath({path: '$.type', json: element})[0];
|
|
||||||
jNode['default'] = JSONPath({path: '$.default', json: element})[0];
|
|
||||||
jNode['value'] = JSONPath({path: '$.value', json: element})[0];
|
|
||||||
PMSSettingsItem[id] = jNode;
|
|
||||||
PMSSettings[itemGroup].push(PMSSettingsItem);
|
|
||||||
});
|
|
||||||
// Remove undefined category, if empty
|
|
||||||
if (Object.keys(PMSSettings[i18n.t('Modules.PMS.Settings.Undefined')]).length === 0){
|
|
||||||
delete PMSSettings[i18n.t('Modules.PMS.Settings.Undefined')];
|
|
||||||
}
|
|
||||||
log.verbose(`PMS Settings are: ${JSON.stringify(PMSSettings)}`);
|
|
||||||
// Workaround for issue #429
|
|
||||||
if ( !JSON.stringify(PMSSettings).includes('LogNumFiles') )
|
|
||||||
{
|
{
|
||||||
// Put into undefined, since the only one we know the name of
|
itemGroup = i18n.t('Modules.PMS.Settings.Undefined');
|
||||||
var itemGroup = i18n.t('Modules.PMS.Settings.Undefined');
|
|
||||||
var PMSSettingsItem = {}
|
|
||||||
var jNode = {};
|
|
||||||
jNode['label'] = 'Amount of log files';
|
|
||||||
jNode['summary'] = 'Amount of log files to keep before rolling over. Server must be restarted for changes to take effect';
|
|
||||||
jNode['type'] = 'int';
|
|
||||||
jNode['default'] = 5;
|
|
||||||
jNode['value'] = 5;
|
|
||||||
PMSSettingsItem['LogNumFiles'] = jNode;
|
|
||||||
PMSSettings[itemGroup].push(PMSSettingsItem);
|
|
||||||
}
|
}
|
||||||
commit('UPDATE_PMS_SETTINGS', PMSSettings);
|
var PMSSettingsItem = {}
|
||||||
})
|
var jNode = {};
|
||||||
.catch(function (error) {
|
jNode['label'] = JSONPath({path: '$.label', json: element})[0];
|
||||||
if (error.response) {
|
jNode['summary'] = JSONPath({path: '$.summary', json: element})[0];
|
||||||
log.error('fetchPMSSettings: ' + error.response.data)
|
jNode['type'] = JSONPath({path: '$.type', json: element})[0];
|
||||||
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message)
|
jNode['default'] = JSONPath({path: '$.default', json: element})[0];
|
||||||
} else if (error.request) {
|
jNode['value'] = JSONPath({path: '$.value', json: element})[0];
|
||||||
log.error('fetchPMSSettings: ' + error.request)
|
PMSSettingsItem[id] = jNode;
|
||||||
} else {
|
PMSSettings[itemGroup].push(PMSSettingsItem);
|
||||||
log.error('fetchPMSSettings: ' + error.message)
|
});
|
||||||
}
|
// Remove undefined category, if empty
|
||||||
});
|
if (Object.keys(PMSSettings[i18n.t('Modules.PMS.Settings.Undefined')]).length === 0){
|
||||||
}
|
delete PMSSettings[i18n.t('Modules.PMS.Settings.Undefined')];
|
||||||
|
}
|
||||||
|
log.verbose(`PMS Settings are: ${JSON.stringify(PMSSettings)}`);
|
||||||
|
// Workaround for issue #429
|
||||||
|
if ( !JSON.stringify(PMSSettings).includes('LogNumFiles') )
|
||||||
|
{
|
||||||
|
// Put into undefined, since the only one we know the name of
|
||||||
|
var itemGroup = i18n.t('Modules.PMS.Settings.Undefined');
|
||||||
|
var PMSSettingsItem = {}
|
||||||
|
var jNode = {};
|
||||||
|
jNode['label'] = 'Amount of log files';
|
||||||
|
jNode['summary'] = 'Amount of log files to keep before rolling over. Server must be restarted for changes to take effect';
|
||||||
|
jNode['type'] = 'int';
|
||||||
|
jNode['default'] = 5;
|
||||||
|
jNode['value'] = 5;
|
||||||
|
PMSSettingsItem['LogNumFiles'] = jNode;
|
||||||
|
PMSSettings[itemGroup].push(PMSSettingsItem);
|
||||||
|
}
|
||||||
|
commit('UPDATE_PMS_SETTINGS', PMSSettings);
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
if (error.response) {
|
||||||
|
log.error('fetchPMSSettings: ' + error.response.data)
|
||||||
|
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message)
|
||||||
|
} else if (error.request) {
|
||||||
|
log.error('fetchPMSSettings: ' + error.request)
|
||||||
|
} else {
|
||||||
|
log.error('fetchPMSSettings: ' + error.message)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const serverModule = {
|
const serverModule = {
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
|
|
Loading…
Add table
Reference in a new issue