mirror of
https://github.com/WebTools-NG/WebTools-NG
synced 2024-11-27 05:20:22 +00:00
Merge pull request #510 from WebTools-NG/#505-FindMedia
#505 find media
This commit is contained in:
commit
55931e349e
15 changed files with 877 additions and 133 deletions
|
@ -13,6 +13,8 @@
|
|||
|
||||
* [#498 Add preferences to shows export](https://github.com/WebTools-NG/WebTools-NG/issues/498)
|
||||
* [#500 Library Path Mapping](https://github.com/WebTools-NG/WebTools-NG/issues/500)
|
||||
* [#505 FindMedia](https://github.com/WebTools-NG/WebTools-NG/issues/505)
|
||||
|
||||
|
||||
## V0.3.17 (20220601)
|
||||
|
||||
|
|
32
package-lock.json
generated
32
package-lock.json
generated
|
@ -1,16 +1,16 @@
|
|||
{
|
||||
"name": "webtools-ng",
|
||||
"version": "0.3.17",
|
||||
"version": "0.3.18",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "webtools-ng",
|
||||
"version": "0.3.17",
|
||||
"version": "0.3.18",
|
||||
"hasInstallScript": true,
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.2",
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"axios": "^0.21.1",
|
||||
"bootstrap": "^4.5.3",
|
||||
"bootstrap-vue": "^2.20.1",
|
||||
|
@ -4595,14 +4595,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001291",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001291.tgz",
|
||||
"integrity": "sha512-roMV5V0HNGgJ88s42eE70sstqGW/gwFndosYrikHthw98N5tLnOTxFqMLQjZVRxTWFlJ4rn+MsgXrR7MDPY4jA==",
|
||||
"version": "1.0.30001357",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001357.tgz",
|
||||
"integrity": "sha512-b+KbWHdHePp+ZpNj+RDHFChZmuN+J5EvuQUlee9jOQIUAdhv9uvAZeEtUeLAknXbkiu1uxjQ9NLp1ie894CuWg==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/browserslist"
|
||||
}
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/browserslist"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/case-sensitive-paths-webpack-plugin": {
|
||||
"version": "2.4.0",
|
||||
|
@ -25155,9 +25161,9 @@
|
|||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001291",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001291.tgz",
|
||||
"integrity": "sha512-roMV5V0HNGgJ88s42eE70sstqGW/gwFndosYrikHthw98N5tLnOTxFqMLQjZVRxTWFlJ4rn+MsgXrR7MDPY4jA==",
|
||||
"version": "1.0.30001357",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001357.tgz",
|
||||
"integrity": "sha512-b+KbWHdHePp+ZpNj+RDHFChZmuN+J5EvuQUlee9jOQIUAdhv9uvAZeEtUeLAknXbkiu1uxjQ9NLp1ie894CuWg==",
|
||||
"dev": true
|
||||
},
|
||||
"case-sensitive-paths-webpack-plugin": {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
},
|
||||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.2",
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"axios": "^0.21.1",
|
||||
"bootstrap": "^4.5.3",
|
||||
"bootstrap-vue": "^2.20.1",
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
"Name": "ExportTools",
|
||||
"ErrorServer": "No server",
|
||||
"Settings": {
|
||||
"Settings": "Settings",
|
||||
"Name": "@:Modules.ET.Name Settings",
|
||||
"Description": "Here you can define the settings for @:Modules.ET.Name",
|
||||
"ArraySep": "Delimiter for multiple info in same field",
|
||||
"ColumnSep": "Delimiter between columns in CSV file (Use 9 for TAB)",
|
||||
|
@ -460,15 +460,33 @@
|
|||
"lblBtnCopy": "Copy",
|
||||
"genRep": "Generate a report"
|
||||
},
|
||||
"FindMissing": {
|
||||
"Name": "Find Missing",
|
||||
"Description": "@:Modules.PMS.FindMissing.Name module allows you search both filesystem and Plex database to locate medias missing"
|
||||
"FindMedia": {
|
||||
"Name": "Find Media",
|
||||
"Description": "@:Modules.PMS.FindMedia.Name module allows you search both filesystem and Plex database to locate medias missing from either of them",
|
||||
"RunTask": "Run",
|
||||
"MissingMapTitle": "Missing a mapped path",
|
||||
"MissingMapDesc": "One or more defined paths for library is not defined. Goto '@:Modules.PMS.LibMapping.Name' to correct",
|
||||
"ttSettings": "Settings for @:Modules.PMS.FindMedia.Name module",
|
||||
"ScanningFS": "Scanning File System",
|
||||
"ScanningLib": "Scanning Library",
|
||||
"Settings": {
|
||||
"Name": "Find Media Settings",
|
||||
"Description": "@:Modules.PMS.FindMedia.Name settings allows you to customize how @:Modules.PMS.FindMedia.Name works",
|
||||
"Note": "Note: After changing a setting, please restart @:Common.AppName",
|
||||
"Ext": "Comma separated file extensions to look for",
|
||||
"ignoreDirs": "Comma separated list of directories to skip",
|
||||
"Return": "Save & Return",
|
||||
"Reset": "Reset to factory standard",
|
||||
"IgnoreHidden": "Ignore Hidden files/directories on Linux/Mac",
|
||||
"IgnoreExtras": "Ignore local extras"
|
||||
}
|
||||
},
|
||||
"LibMapping": {
|
||||
"Name": "Library Mapping",
|
||||
"Description": "@:Modules.PMS.LibMapping.Name allows you map the defined Library folders path to match a path for this workstation",
|
||||
"ClickToDefine": "Click to define",
|
||||
"SelectMapDirPath": "Select mapped path"
|
||||
"SelectMapDirPath": "Select mapped path",
|
||||
"TTSelectLibrary": "Here you select the library to map"
|
||||
}
|
||||
},
|
||||
"PlexTV": {
|
||||
|
|
|
@ -101,22 +101,22 @@
|
|||
icon: 'fas fa-tv',
|
||||
},
|
||||
{
|
||||
href: { path: '/pms/findmissing' },
|
||||
title: this.$t("Modules.PMS.FindMissing.Name"),
|
||||
hidden: wtutils.hideMenu('pmsFindMissing'),
|
||||
icon: 'fas fa-tv'
|
||||
href: { path: '/pms/findmedia' },
|
||||
title: this.$t("Modules.PMS.FindMedia.Name"),
|
||||
hidden: wtutils.hideMenu('pmsFindMedia'),
|
||||
icon: 'fas fa-search'
|
||||
},
|
||||
{
|
||||
href: '/pms/libmapping',
|
||||
hidden: wtutils.hideMenu('pmsLibMapping'),
|
||||
title: this.$t("Common.Menu.Sidebar.PMS.LibMapping"),
|
||||
icon: 'fa fa-cog'
|
||||
icon: 'fas fa-hdd'
|
||||
},
|
||||
{
|
||||
href: '/pms/settings',
|
||||
hidden: wtutils.hideMenu('pmsSettings'),
|
||||
title: this.$t("Common.Menu.Sidebar.PMS.Settings"),
|
||||
icon: 'fa fa-cog'
|
||||
icon: 'fas fa-cog'
|
||||
},
|
||||
{
|
||||
href: { path: '/pms/viewstate' },
|
||||
|
@ -136,13 +136,13 @@
|
|||
title: this.$t("Common.Menu.Sidebar.Language.NavTitle"),
|
||||
hidden: wtutils.hideMenu('Language'),
|
||||
//icon: 'fas fa-language'
|
||||
icon: 'fa fa-globe'
|
||||
icon: 'fas fa-globe'
|
||||
},
|
||||
{
|
||||
href: '/settings',
|
||||
title: this.$t("Common.Menu.Sidebar.Settings.NavTitle"),
|
||||
hidden: wtutils.hideMenu('Settings'),
|
||||
icon: 'fa fa-cog'
|
||||
icon: 'fas fa-cog'
|
||||
},
|
||||
{
|
||||
href: { path: '/about' },
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
"Suggest Naming": "includeGuids=1&checkFiles=0&includeRelated=0&includeExtras=0&includeBandwidths=0&includeChapters=0&excludeElements=Actor,Collection,Country,Director,Genre,Label,Mood,Producer,Similar,Writer,Role&excludeFields=summary,tagline",
|
||||
"all": "checkFiles=1&includeExtras=1&includeBandwidths=1&includeChapters=1"
|
||||
}
|
||||
|
||||
},
|
||||
"2": {
|
||||
"levels": {
|
||||
|
|
48
src/components/modules/General/pms.js
Normal file
48
src/components/modules/General/pms.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
This file contains different functions and methods
|
||||
that we use fo PMS.
|
||||
*/
|
||||
|
||||
const log = require('electron-log');
|
||||
console.log = log.log;
|
||||
const {JSONPath} = require('jsonpath-plus');
|
||||
|
||||
import store from '../../../store';
|
||||
|
||||
const pms = new class PMS {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
async getPMSSections( libTypes ){
|
||||
/*
|
||||
This function will return an array of libraries of specified types
|
||||
Param: libTypes Like: ['movie', 'show']
|
||||
*/
|
||||
await store.dispatch('fetchSections');
|
||||
const sections = await store.getters.getPmsSections;
|
||||
const result = [];
|
||||
this.selLib = "";
|
||||
if (Array.isArray(sections) && sections.length) {
|
||||
sections.forEach(req => {
|
||||
if ( libTypes.includes(req.type)){
|
||||
log.debug(`[pms.js] (getPMSSections) - pushing library: ${req.title} to results`);
|
||||
let item = [];
|
||||
let itemVal = {};
|
||||
itemVal['key'] = JSONPath({path: '$..key', json: req})[0];
|
||||
itemVal['location'] = JSONPath({path: '$..path', json: req.location});
|
||||
itemVal['type'] = JSONPath({path: '$..type', json: req})[0];
|
||||
item['text']=req.title;
|
||||
//item['value']=JSONPath({path: '$..path', json: req.location});
|
||||
item['value']=itemVal;
|
||||
result.push(Object.assign({}, item));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.error("[pms.js] (getPMSSections) - No Library found");
|
||||
}
|
||||
log.debug(`[pms.js] (getPMSSections) - reslut: ${JSON.stringify(result)}`);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export { pms };
|
|
@ -235,6 +235,12 @@ const wtutils = new class WTUtils {
|
|||
}
|
||||
}
|
||||
|
||||
async sleep(ms) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
hideMenu(menu)
|
||||
{
|
||||
let retVal = false;
|
||||
|
@ -289,11 +295,6 @@ const wtutils = new class WTUtils {
|
|||
if ( wtconfig.get('Menu.About', 'N/A') == 'N/A' ){
|
||||
wtconfig.set('Menu.About', false)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// General section
|
||||
if ( wtconfig.get('General.username', 'N/A') == 'N/A' ){
|
||||
wtconfig.set('General.username', '')
|
||||
|
@ -351,6 +352,19 @@ const wtutils = new class WTUtils {
|
|||
if ( wtconfig.get('PMS.ContainerSize.3001', 'N/A') == 'N/A' ){
|
||||
wtconfig.set('PMS.ContainerSize.3001', 20)
|
||||
}
|
||||
if ( wtconfig.get('PMS.FindMedia.Settings.Ext', 'N/A') == 'N/A' ){
|
||||
wtconfig.set('PMS.FindMedia.Settings.Ext', [
|
||||
"3g2","3gp","asf","asx","avc",
|
||||
"avi","avs","bivx","bup","divx",
|
||||
"dv","dvr-ms","evo","fli","flv",
|
||||
"m2t","m2ts","m2v","m4v","mkv",
|
||||
"mov","mp4","mpeg","mpg","mts",
|
||||
"nsv","nuv","ogm","ogv","tp",
|
||||
"pva","qt","rm","rmvb","sdp",
|
||||
"svq3","strm","ts","ty","vdr",
|
||||
"viv","vob","vp3","wmv","wpl",
|
||||
"wtv","xsp","xvid","webm"])
|
||||
}
|
||||
// ET Settings
|
||||
if ( wtconfig.get('ET.ChReturn', 'N/A') == 'N/A' ){
|
||||
wtconfig.set('ET.ChReturn', '<RETURN>')
|
||||
|
|
162
src/components/modules/PMS/FindMedia/FindMedia.vue
Normal file
162
src/components/modules/PMS/FindMedia/FindMedia.vue
Normal file
|
@ -0,0 +1,162 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- Settings button -->
|
||||
<div class="text-right">
|
||||
<div class="buttons">
|
||||
<!-- Buttons -->
|
||||
<div id="buttons">
|
||||
<b-button-group id="settings">
|
||||
<b-tooltip target="settings" triggers="hover">
|
||||
{{ $t('Modules.PMS.FindMedia.ttSettings') }}
|
||||
</b-tooltip>
|
||||
<button class="btn btn-outline-success" @click="showSettings"><i class="fa fa-cog"></i></button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Main view -->
|
||||
<b-container fluid>
|
||||
<div class="col-lg-10 col-md-12 col-xs-12">
|
||||
<h1>{{ $t("Modules.PMS.FindMedia.Name") }}</h1>
|
||||
<p>{{ $t("Modules.PMS.FindMedia.Description") }}</p>
|
||||
</div>
|
||||
<!-- Select Lib -->
|
||||
<div class="d-flex align-items-center">
|
||||
<b-form-group id="SelLibGroup" v-bind:label="$t('Modules.ET.optExpType.lblSelectSelection')" label-size="lg" label-class="font-weight-bold pt-0">
|
||||
<b-tooltip target="SelLibGroup" triggers="hover">
|
||||
{{ $t('Modules.PMS.LibMapping.TTSelectLibrary') }}
|
||||
</b-tooltip>
|
||||
<b-form-select
|
||||
v-model="selLib"
|
||||
id="selLib"
|
||||
:options="selLibOptions"
|
||||
name="selLib">
|
||||
</b-form-select>
|
||||
</b-form-group>
|
||||
</div>
|
||||
<br>
|
||||
<!-- Buttons -->
|
||||
<div class="buttons">
|
||||
<!-- Buttons -->
|
||||
<div id="buttons" class="text-center">
|
||||
<b-button-group >
|
||||
<b-button variant="success" class="mr-1" :disabled="this.selLib == ''" @click="runFM"> {{ $t('Modules.PMS.FindMedia.RunTask') }} </b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<statusDiv /> <!-- Status Div -->
|
||||
</b-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from '../../../../i18n';
|
||||
//import store from '../../../store';
|
||||
import { dialog } from '../../General/wtutils';
|
||||
import { pms } from '../../General/pms';
|
||||
import { findMedia } from './scripts/FindMedia.js';
|
||||
import statusDiv from '../../General/status.vue';
|
||||
import { status } from '../../General/status';
|
||||
|
||||
|
||||
i18n
|
||||
|
||||
const log = require("electron-log");
|
||||
export default {
|
||||
components: {
|
||||
statusDiv
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
serverIsSelected: false,
|
||||
selLibOptions: [],
|
||||
selLib: "",
|
||||
selLibraryWait: true
|
||||
};
|
||||
},
|
||||
created() {
|
||||
log.info("FindMedia Created");
|
||||
this.serverSelected();
|
||||
this.getPMSSections();
|
||||
},
|
||||
watch: {
|
||||
// Watch for when selected server address is updated
|
||||
selectedServerAddress: async function(){
|
||||
// Changed, so we need to update the libraries
|
||||
this.selLibraryWait = true;
|
||||
await this.getPMSSections();
|
||||
this.selLibraryWait = true;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// We need this computed, for watching for changes to selected server
|
||||
selectedServerAddress: function(){
|
||||
return this.$store.getters.getSelectedServerAddress
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// Show Settings
|
||||
showSettings(){
|
||||
this.$router.push({ name: 'FindMediaSettings' })
|
||||
},
|
||||
// Run FindMedia
|
||||
async runFM() {
|
||||
log.info(`[FindMedia.vue] (runFM) starting`);
|
||||
|
||||
// Check if we have all lib paths mapped
|
||||
const mappedPathOK = await findMedia.checkPathMapping( this.selLib["location"] );
|
||||
if ( mappedPathOK === 'WTNG_ERROR_WTNG')
|
||||
{
|
||||
log.error(`[FindMedia.vue] (runFM) - Missing mapped path for: ${mappedPathOK}`);
|
||||
dialog.ShowMsgBox(i18n.t("Modules.PMS.FindMedia.MissingMapDesc"), 'error', i18n.t("Modules.PMS.FindMedia.MissingMapTitle"), [i18n.t("Common.Ok")]);
|
||||
}
|
||||
else{
|
||||
log.info(`[FindMedia.vue] (runFM) mappedPath is okay`);
|
||||
await status.clearStatus();
|
||||
await status.updateStatusMsg( status.RevMsgType.Status, i18n.t('Common.Status.Msg.Processing'));
|
||||
// Wait a short moment, so status can update
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
await findMedia.findMedia( this.selLib["location"], this.selLib["key"], this.selLib["type"] );
|
||||
}
|
||||
|
||||
},
|
||||
// Get Library list
|
||||
getPMSSections: async function(){
|
||||
this.selLibrary = "";
|
||||
this.selLibOptions = await pms.getPMSSections(['movie', 'show']);
|
||||
},
|
||||
/* Check if a server is selected, and if not
|
||||
tell user, and disable backup */
|
||||
async serverSelected() {
|
||||
let serverCheck = this.$store.getters.getSelectedServer;
|
||||
this.serverIsSelected = ( this.$store.getters.getSelectedServer != "none" );
|
||||
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>
|
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<b-container fluid>
|
||||
<div class="col-lg-10 col-md-12 col-xs-12">
|
||||
<br>
|
||||
<br>
|
||||
<h1>{{ $t("Modules.PMS.FindMedia.Settings.Name") }}</h1>
|
||||
<p>{{ $t("Modules.PMS.FindMedia.Settings.Description") }}</p>
|
||||
<br>
|
||||
<p>{{ $t("Modules.PMS.FindMedia.Settings.Note") }}</p>
|
||||
</div>
|
||||
<b-input-group id="ExtGrp" :prepend="$t('Modules.PMS.FindMedia.Settings.Ext')" class="mt-3">
|
||||
<b-form-textarea
|
||||
id="Ext" name="Ext" type="text" class="form-control" v-model="Ext" @change="setExt"
|
||||
rows="3"
|
||||
max-rows="3"
|
||||
>
|
||||
</b-form-textarea>
|
||||
</b-input-group>
|
||||
<b-input-group id="ignoreDirsGrp" :prepend="$t('Modules.PMS.FindMedia.Settings.ignoreDirs')" class="mt-3">
|
||||
<b-form-textarea
|
||||
id="ignoreDirs" name="ignoreDirs" type="text" class="form-control" v-model="ignoreDirs" @change="setIgnoreDirs"
|
||||
rows="3"
|
||||
max-rows="3"
|
||||
>
|
||||
</b-form-textarea>
|
||||
</b-input-group>
|
||||
<br>
|
||||
<div>
|
||||
<b-form-checkbox
|
||||
id="IgnoreHidden"
|
||||
v-model="IgnoreHidden"
|
||||
name="IgnoreHidden"
|
||||
value=true
|
||||
unchecked-value=false
|
||||
@change="setIgnoreHidden"
|
||||
>
|
||||
{{ $t('Modules.PMS.FindMedia.Settings.IgnoreHidden') }}
|
||||
</b-form-checkbox>
|
||||
</div>
|
||||
<div>
|
||||
<b-form-checkbox
|
||||
id="IgnoreExtras"
|
||||
v-model="IgnoreExtras"
|
||||
name="IgnoreExtras"
|
||||
value=true
|
||||
unchecked-value=false
|
||||
@change="setIgnoreExtras"
|
||||
>
|
||||
{{ $t('Modules.PMS.FindMedia.Settings.IgnoreExtras') }}
|
||||
</b-form-checkbox>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<!-- Buttons -->
|
||||
<div class="buttons">
|
||||
<!-- Buttons -->
|
||||
<div id="buttons" class="text-center">
|
||||
<b-button-group >
|
||||
<b-button variant="danger" class="mr-1" @click="reset"> {{ $t('Modules.PMS.FindMedia.Settings.Reset') }} </b-button>
|
||||
<b-button variant="success" class="mr-1" @click="jumpToFM"> {{ $t('Modules.PMS.FindMedia.Settings.Return') }} </b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</b-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { wtconfig } from '../../../General/wtutils';
|
||||
import { findMedia } from '../scripts/FindMedia';
|
||||
|
||||
const log = require("electron-log");
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
Ext: "",
|
||||
IgnoreHidden: true,
|
||||
IgnoreExtras: true,
|
||||
ignoreDirs: ""
|
||||
}
|
||||
},
|
||||
created() {
|
||||
log.info(`[FindMediaSettings.vue] (Created) - FMSettings created`);
|
||||
this.getSettings();
|
||||
},
|
||||
methods: {
|
||||
setIgnoreHidden( value ){
|
||||
wtconfig.set('PMS.FindMedia.Settings.IgnoreHidden', value);
|
||||
},
|
||||
setIgnoreExtras( value ){
|
||||
wtconfig.set('PMS.FindMedia.Settings.IgnoreExtras', value);
|
||||
},
|
||||
getSettings(){
|
||||
this.Ext = wtconfig.get('PMS.FindMedia.Settings.Ext').toString();
|
||||
this.IgnoreHidden = wtconfig.get('PMS.FindMedia.Settings.IgnoreHidden', true);
|
||||
this.IgnoreExtras = wtconfig.get('PMS.FindMedia.Settings.IgnoreExtras', true);
|
||||
this.ignoreDirs = wtconfig.get('PMS.FindMedia.Settings.ignoreDirs', findMedia.ignoreDirs).toString();
|
||||
},
|
||||
setExt( value ){
|
||||
// Remove spaces, and force to lower case
|
||||
let ext = value.trimStart().trimEnd().toLowerCase();
|
||||
// Update form
|
||||
this.Ext = ext;
|
||||
// Update conf file
|
||||
wtconfig.set('PMS.FindMedia.Settings.Ext', ext.split(','));
|
||||
},
|
||||
setIgnoreDirs( value ){
|
||||
let ignoreDirsArr = value.split(',');
|
||||
let newIgnoreDirsArr = [];
|
||||
ignoreDirsArr.forEach(element => {
|
||||
newIgnoreDirsArr.push(element.trimStart().trimEnd().toLowerCase());
|
||||
});
|
||||
// Update form
|
||||
this.ignoreDirs = newIgnoreDirsArr.toString();
|
||||
// Update conf file
|
||||
wtconfig.set('PMS.FindMedia.Settings.ignoreDirs', newIgnoreDirsArr);
|
||||
},
|
||||
// Return to FindMedia
|
||||
jumpToFM(){
|
||||
this.$router.push({ name: 'FindMedia' })
|
||||
},
|
||||
// Reset to factory Std
|
||||
reset(){
|
||||
this.Ext = findMedia.validExt.toString();
|
||||
wtconfig.set('PMS.FindMedia.Settings.Ext', findMedia.validExt);
|
||||
this.ignoreDirs = findMedia.ignoreDirs.toString();
|
||||
wtconfig.set('PMS.FindMedia.Settings.ignoreDirs', findMedia.ignoreDirs);
|
||||
this.IgnoreHidden = true;
|
||||
wtconfig.set('PMS.FindMedia.Settings.IgnoreHidden', true);
|
||||
wtconfig.set('PMS.FindMedia.Settings.IgnoreExtras', true);
|
||||
this.IgnoreExtras = true;
|
||||
log.info(`[FindMediaSettings.vue] (reset) - FMSettings factory reset done`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
#sync-button {
|
||||
margin-left: 1em;
|
||||
}
|
||||
</style>
|
413
src/components/modules/PMS/FindMedia/scripts/FindMedia.js
Normal file
413
src/components/modules/PMS/FindMedia/scripts/FindMedia.js
Normal file
|
@ -0,0 +1,413 @@
|
|||
// This file holds generic FM functions
|
||||
|
||||
const log = require('electron-log');
|
||||
console.log = log.log;
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const {JSONPath} = require('jsonpath-plus');
|
||||
var sanitize = require("sanitize-filename");
|
||||
|
||||
import store from '../../../../../store';
|
||||
import { wtutils,wtconfig } from '../../../General/wtutils';
|
||||
import { status } from '../../../General/status';
|
||||
import i18n from '../../../../../i18n';
|
||||
import { resolve } from 'path';
|
||||
import axios from 'axios';
|
||||
import {csv} from '../../../ExportTools/scripts/csv';
|
||||
|
||||
|
||||
const validDir = function( dirName ) {
|
||||
/* Will check if directory is not hidden or should be ignored
|
||||
returns true or false */
|
||||
log.silly(`Checking if ${dirName} is valid`);
|
||||
// Got a hidden one?
|
||||
if ( wtconfig.get('PMS.FindMedia.Settings.IgnoreHidden', true) === 'true' ){
|
||||
if ( dirName.startsWith('.') ){
|
||||
log.silly(`We do not allow hidden dirs like: ${dirName}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Got an Extra dir?
|
||||
if ( findMedia.settingsIgnoreExtras ){
|
||||
if ( findMedia.ExtraDirs.includes( dirName )){
|
||||
log.silly(`We do not allow extra dirs like: ${dirName}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Got a dir to ignore?
|
||||
if ( findMedia.settingsIgnoreDirs.includes( dirName ) ){
|
||||
log.silly(`We do not allow ignore dirs like: ${dirName}`);
|
||||
return false;
|
||||
}
|
||||
log.silly(`${dirName} is valid`);
|
||||
return true;
|
||||
}
|
||||
|
||||
const validFile = function( fileName ) {
|
||||
/* Will check if file is valid or not
|
||||
returns true or false */
|
||||
log.silly(`[FindMedia.js] (validFile) - Checking file: ${fileName}`)
|
||||
if ( findMedia.validExt.includes(path.extname(fileName).toLowerCase().slice(1))){
|
||||
log.silly(`[FindMedia.js] (validFile) - Valid ext for file: ${fileName}`);
|
||||
if ( findMedia.settingsIgnoreExtras ){
|
||||
log.silly(`[FindMedia.js] (validFile) - Checking IgnoreExtras for file: ${fileName}`)
|
||||
for (let eFile of findMedia.Extrafiles) {
|
||||
if ( path.parse(fileName).name.endsWith(eFile) ){
|
||||
log.silly(`We ignore extra file: ${fileName}`)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else { return true }
|
||||
} else {
|
||||
log.silly(`[FindMedia.js] (validFile) - Ext not valid for file: ${fileName}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const getAllFiles = function( dirPath, orgDirPath, arrayOfFiles ) {
|
||||
/*
|
||||
Recursive scanning of a filepath
|
||||
Takes dirPath and orgDirPath as parameter
|
||||
for the starting dir. (Should be the same)
|
||||
Will return an raw array, as well as populate
|
||||
findMedia.filesFound array
|
||||
*/
|
||||
var files = fs.readdirSync(dirPath);
|
||||
// Set array if needed
|
||||
arrayOfFiles = arrayOfFiles || [];
|
||||
files.forEach(function(curFile) {
|
||||
// Is this a directory?
|
||||
if (fs.statSync(dirPath + "/" + curFile).isDirectory()) {
|
||||
// Check if valid dir, then call req.
|
||||
if ( validDir( curFile ) ){
|
||||
arrayOfFiles = getAllFiles(path.join(dirPath, curFile), orgDirPath, arrayOfFiles)
|
||||
}
|
||||
} else {
|
||||
// We found a file
|
||||
if ( validFile( curFile ) ){
|
||||
// Force forward slash
|
||||
let lookupPath = path.join(dirPath, curFile).replaceAll('\\', '/');
|
||||
log.silly(`[FindMedia.js] (getAllFiles) - Adding ${lookupPath.slice(orgDirPath.length + 1)}: ${ path.join(dirPath, curFile) }`);
|
||||
//status.updateStatusMsg( status.RevMsgType.Item, `GED Found file: ${curFile}`);
|
||||
findMedia.filesFound[lookupPath.slice(orgDirPath.length + 1)] = path.join(dirPath, curFile);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return arrayOfFiles
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const findMedia = new class FINDMEDIA {
|
||||
constructor() {
|
||||
this.validExt = [
|
||||
'3g2','3gp','asf','asx','avc','avi','avs','bivx','bup','divx','dv','dvr-ms',
|
||||
'evo','fli','flv','m2t','m2ts','m2v','m4v',
|
||||
'mkv','mov','mp4','mpeg','mpg','mts','nsv','nuv','ogm','ogv','tp','pva','qt','rm','rmvb','sdp','svq3',
|
||||
'strm','ts','ty','vdr','viv','vob','vp3','wmv','wpl','wtv','xsp','xvid','webm'
|
||||
];
|
||||
this.ExtraDirs = [
|
||||
'Behind The Scenes', 'Deleted Scenes', 'Featurettes',
|
||||
'Interviews', 'Scenes', 'Shorts', 'Trailers', 'Other'
|
||||
];
|
||||
this.Extrafiles = [
|
||||
'-behindthescenes', '-deleted', '-featurette',
|
||||
'-interview', '-scene', '-short', '-trailer', '-other'
|
||||
];
|
||||
this.ignoreDirs = [
|
||||
'lost+found'
|
||||
];
|
||||
this.libPaths = [];
|
||||
this.filePath = [];
|
||||
this.validExt = [];
|
||||
this.currentLibPathLength;
|
||||
this.filesFound = {};
|
||||
this.libFiles = [];
|
||||
this.PMSLibPaths = [];
|
||||
this.csvFile = '';
|
||||
this.libName = '';
|
||||
this.csvStream;
|
||||
this.settingsIgnoreExtras;
|
||||
this.ignoreDirs;
|
||||
|
||||
}
|
||||
|
||||
// Generate the filename for an export
|
||||
async getFileName({ Type, libKey }){
|
||||
const dateFormat = require('dateformat');
|
||||
const OutDir = wtconfig.get('General.ExportPath');
|
||||
const timeStamp = dateFormat(new Date(), "yyyy.mm.dd_h.MM.ss");
|
||||
const path = require('path');
|
||||
let arrFile = [];
|
||||
arrFile.push(store.getters.getSelectedServer.name); //PMSName
|
||||
arrFile.push(JSONPath({path: `$.[?(@.key==${libKey})].title`, json: store.getters.getPmsSections})); //libName
|
||||
arrFile.push(timeStamp + '.' + Type + '.tmp');
|
||||
let outFile = sanitize(arrFile.join('_'));
|
||||
const targetDir = path.join(OutDir, wtutils.AppName, i18n.t('Modules.PMS.Name'), i18n.t('Modules.PMS.FindMedia.Name'));
|
||||
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(`[FindMedia.js] (getFileName) - OutFile is: ${outFileWithPath}`);
|
||||
return outFileWithPath;
|
||||
}
|
||||
|
||||
async makeOutFile( libKey ){
|
||||
let csvFile;
|
||||
const intSep = '{*WTNG-ET*}';
|
||||
// Get Header fields
|
||||
let fields = ['Title', 'PMS file', 'Filesystem'];
|
||||
var fs = require('fs');
|
||||
csvFile = await this.getFileName({ Type: 'csv', libKey: libKey });
|
||||
this.csvStream = fs.createWriteStream(csvFile, {flags:'a'});
|
||||
await csv.addHeaderToTmp({ stream: this.csvStream, item: fields});
|
||||
const NA = wtconfig.get('ET.NotAvail', 'N/A');
|
||||
// Add only on File System
|
||||
for(var key in this.filesFound){
|
||||
//console.log(key+": "+this.filesFound[key]);
|
||||
let row = NA + intSep + NA + intSep + this.filesFound[key];
|
||||
row = row.replaceAll(intSep, wtconfig.get("ET.ColumnSep", '|'));
|
||||
csv.addRowToTmp({ stream: this.csvStream, item: row});
|
||||
}
|
||||
// Add only in PMS
|
||||
for( key in this.libFiles){
|
||||
console.log( JSON.stringify(this.libFiles[key]));
|
||||
let row = this.libFiles[key]['title'] + intSep + this.libFiles[key]['file'] + intSep + NA;
|
||||
row = row.replaceAll(intSep, wtconfig.get("ET.ColumnSep", '|'));
|
||||
csv.addRowToTmp({ stream: this.csvStream, item: row});
|
||||
}
|
||||
// Close filestream
|
||||
this.csvStream.end();
|
||||
// Rename outFile to real name
|
||||
let newFile;
|
||||
newFile = csvFile.replace('.tmp', '')
|
||||
fs.renameSync(csvFile, newFile);
|
||||
return newFile;
|
||||
}
|
||||
|
||||
async findMedia( libpaths, libKey, libType ){
|
||||
status.updateStatusMsg( status.RevMsgType.Status, i18n.t('Common.Status.Msg.Processing'));
|
||||
// Get settings needed
|
||||
this.validExt = await wtconfig.get('PMS.FindMedia.Settings.Ext');
|
||||
this.settingsIgnoreExtras = await wtconfig.get('PMS.FindMedia.Settings.IgnoreExtras');
|
||||
this.settingsIgnoreDirs = await wtconfig.get('PMS.FindMedia.Settings.ignoreDirs');
|
||||
|
||||
|
||||
// Scan file system
|
||||
this.filesFound = [];
|
||||
await findMedia.scanFileSystemPaths( libpaths );
|
||||
// Scan library
|
||||
await findMedia.scanPMSLibrary(libKey, libType);
|
||||
// Create output file
|
||||
let outFile = await this.makeOutFile( libKey );
|
||||
|
||||
status.clearStatus();
|
||||
status.updateStatusMsg( status.RevMsgType.Status, i18n.t('Common.Status.Msg.Finished'));
|
||||
status.updateStatusMsg( status.RevMsgType.OutFile, outFile);
|
||||
|
||||
libType
|
||||
|
||||
}
|
||||
|
||||
async checkPathMapping( paths ){
|
||||
/*
|
||||
This will check paths if mapped
|
||||
will return 'ok' if all is good, or
|
||||
else the path that needs a mapping
|
||||
*/
|
||||
return new Promise((resolve) => {
|
||||
let gotError = false;
|
||||
log.info(`[FindMedia.js] (checkPathMapping) Starting`);
|
||||
log.verbose(`[FindMedia.js] (checkPathMapping) We will check the following filePaths: ${ JSON.stringify(paths)}`);
|
||||
// First we need to check if libPath Mappings has been defined, and if not, alert user
|
||||
// To do this, we need the selected servers ID
|
||||
// Get ServerID
|
||||
let retVal = 'ok'
|
||||
const serverID = store.getters.getSelectedServer.clientIdentifier;
|
||||
paths.forEach(libPath => {
|
||||
// Escape . in libPath
|
||||
libPath = libPath.replace('.', '\\.');
|
||||
let mappedLibPath = wtconfig.get(`PMS.LibMapping.${serverID}.${libPath}`, 'WTNG_ERROR_WTNG');
|
||||
if ( mappedLibPath === 'WTNG_ERROR_WTNG'){
|
||||
log.error(`[FindMedia.js] (checkPathMapping) - missing: ${libPath}`);
|
||||
gotError = true;
|
||||
}
|
||||
});
|
||||
log.info(`[FindMedia.js] (checkPathMapping) All done`);
|
||||
if ( gotError){
|
||||
retVal = 'WTNG_ERROR_WTNG';
|
||||
}
|
||||
resolve (retVal);
|
||||
});
|
||||
}
|
||||
|
||||
async scanFileSystemPaths( paths ){
|
||||
/// This will scan the filesystem for medias
|
||||
status.updateStatusMsg( status.RevMsgType.Info, i18n.t('Modules.PMS.FindMedia.ScanningFS'));
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
return new Promise((resolve) => {
|
||||
log.info(`[FindMedia.js] (scanFileSystemPaths) - Starting`);
|
||||
log.debug(`[FindMedia.js] (scanFileSystemPaths) - We will scan the following filePaths: ${ JSON.stringify(paths)}`);
|
||||
// Reset output
|
||||
findMedia.filePath = [];
|
||||
this.filesFound = {};
|
||||
const serverID = store.getters.getSelectedServer.clientIdentifier;
|
||||
//Walk each paths
|
||||
paths.forEach(async libPath => {
|
||||
let mappedLibPath = wtconfig.get(`PMS.LibMapping.${serverID}.${libPath.replace('.', '\\.')}`, 'WTNG_ERROR_WTNG');
|
||||
status.updateStatusMsg( status.RevMsgType.Info, `Now Scanning ${mappedLibPath}`);
|
||||
log.debug(`[FindMedia.js] (scanFileSystemPaths) - PMS path is: ${libPath}`);
|
||||
log.debug(`[FindMedia.js] (scanFileSystemPaths) - Wkstn path is: ${mappedLibPath}`);
|
||||
//findMedia.filePath.push(...getAllFiles( mappedLibPath, mappedLibPath ));
|
||||
findMedia.filePath.push(...getAllFiles( mappedLibPath, mappedLibPath ));
|
||||
});
|
||||
log.info(`[FindMedia.js] (scanFileSystemPaths) - End`);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
async scanPMSLibrary( library, libType ){
|
||||
/*
|
||||
This will scan the PMS library, and add result to this.libPaths,
|
||||
if not present in this.filePath.
|
||||
If present, then pop it from this.filePath
|
||||
*/
|
||||
log.info(`[FindMedia.js] (scanPMSLibrary) - Starting`);
|
||||
log.verbose(`[FindMedia.js] (scanPMSLibrary) - We will scan library with a key of: ${ library } and a type of: ${libType}`);
|
||||
status.updateStatusMsg( status.RevMsgType.Info, i18n.t('Modules.PMS.FindMedia.ScanningLib'));
|
||||
await findMedia.getPMSPathArr();
|
||||
findMedia.libFiles = [];
|
||||
// We need to find type of lib, and total count as well
|
||||
let index = 0;
|
||||
let step = 0;
|
||||
let size = 0;
|
||||
let totalSize = 0;
|
||||
let mediaType = 1;
|
||||
if ( libType === 'show'){
|
||||
mediaType = 4;
|
||||
}
|
||||
let url = `${store.getters.getSelectedServerAddress}/library/sections/${library}/all?excludeElements=Genre,Director,Writer,Country,Role,Producer,Collections&excludeFields=summary,tagline,rating,contentRating,audienceRatingImage&X-Plex-Container-Start=${index}&X-Plex-Container-Size=${step}&type=${mediaType}`
|
||||
let header = wtutils.PMSHeader;
|
||||
header['X-Plex-Token'] = store.getters.getSelectedServer.accessToken;
|
||||
await axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
headers: header
|
||||
})
|
||||
.then((response) => {
|
||||
log.debug('[FindMedia.js] (scanPMSLibrary) - Response recieved');
|
||||
log.silly(`[FindMedia.js] (scanPMSLibrary) - Response returned as: ${JSON.stringify(response.data)}`);
|
||||
totalSize = JSONPath({path: `$.MediaContainer.totalSize`, json: response.data})[0];
|
||||
if ( JSONPath({path: `$.MediaContainer.viewGroup`, json: response.data})[0] === 'show'){
|
||||
mediaType = 4;
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (error.response) {
|
||||
log.error(`[FindMedia.js] (scanPMSLibrary) - ${JSON.stringify(error.response.data)}`);
|
||||
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
|
||||
} else if (error.request) {
|
||||
log.error(`[FindMedia.js] (scanPMSLibrary) - ${JSON.stringify(error.request)}`);
|
||||
} else {
|
||||
log.error(`[FindMedia.js] (scanPMSLibrary) - ${JSON.stringify(error.message)}`);
|
||||
}
|
||||
});
|
||||
|
||||
// totalSize, size
|
||||
// resolve();
|
||||
|
||||
|
||||
step = wtconfig.get("PMS.ContainerSize." + mediaType, 20);
|
||||
let metaData;
|
||||
do {
|
||||
url = `${store.getters.getSelectedServerAddress}/library/sections/${library}/all?excludeElements=Genre,Director,Writer,Country,Role,Producer,Collections&excludeFields=summary,tagline,rating,contentRating,audienceRatingImage&X-Plex-Container-Start=${index}&X-Plex-Container-Size=${step}&type=${mediaType}`;
|
||||
status.updateStatusMsg( status.RevMsgType.Items, i18n.t('Common.Status.Msg.ProcessItem_0_1', {count: index, total: totalSize}));
|
||||
log.verbose(`[FindMedia.js] (scanPMSLibrary) - Calling url: ${ url } `);
|
||||
await axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
headers: header
|
||||
})
|
||||
.then((response) => {
|
||||
log.debug('[FindMedia.js] (scanPMSLibrary) - Response recieved');
|
||||
log.silly(`[FindMedia.js] (scanPMSLibrary) - Response returned as: ${JSON.stringify(response.data)}`);
|
||||
size = JSONPath({path: `$.MediaContainer.size`, json: response.data})[0];
|
||||
metaData = JSONPath({path: `$.MediaContainer.Metadata`, json: response.data})[0];
|
||||
for (var idxMetaData in metaData)
|
||||
{
|
||||
var title = JSONPath({path: `$..title`, json: metaData[parseInt(idxMetaData)]})[0];
|
||||
var files = JSONPath({path: `$..Part[*].file`, json: metaData[parseInt(idxMetaData)]});
|
||||
for (var idxFiles in files){
|
||||
if (this.validExt.includes(path.extname(files[idxFiles]).toLowerCase().slice(1))){
|
||||
for (var idxPMSLibPaths in this.PMSLibPaths){
|
||||
if (files[idxFiles].startsWith(this.PMSLibPaths[idxPMSLibPaths])){
|
||||
// Slice to lookup in files found
|
||||
var lookup = files[idxFiles].slice(this.PMSLibPaths[idxPMSLibPaths].length + 1)
|
||||
lookup = lookup.replaceAll('\\', '/');
|
||||
if ( Object.prototype.hasOwnProperty.call(this.filesFound, lookup)) {
|
||||
// We need to remove from detected files, since we found it
|
||||
delete this.filesFound[lookup];
|
||||
}
|
||||
else {
|
||||
// Not found, so only in PMS
|
||||
let entry = {}
|
||||
entry['title'] = title;
|
||||
entry['file'] = files[idxFiles]
|
||||
this.libFiles.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
index += step;
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (error.response) {
|
||||
log.error(`[FindMedia.js] (scanPMSLibrary) - ${JSON.stringify(error.response.data)}`);
|
||||
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message);
|
||||
return
|
||||
} else if (error.request) {
|
||||
log.error(`[FindMedia.js] (scanPMSLibrary) - ${JSON.stringify(error.request)}`);
|
||||
return
|
||||
} else {
|
||||
log.error(`[FindMedia.js] (scanPMSLibrary) - ${JSON.stringify(error.message)}`);
|
||||
return
|
||||
}
|
||||
});
|
||||
} while ( size == step );
|
||||
log.info(`[FindMedia.js] (scanPMSLibrary) - End`);
|
||||
resolve();
|
||||
}
|
||||
|
||||
async getPMSPathArr(){
|
||||
/*
|
||||
This will populate this.PMSLibPaths
|
||||
with an array of library paths used
|
||||
*/
|
||||
log.info(`[FindMedia.js] (getPMSPathArr) - Start`);
|
||||
// Reset property
|
||||
this.PMSLibPaths = [];
|
||||
// Start by getting Server ID
|
||||
const serverID = store.getters.getSelectedServer.clientIdentifier;
|
||||
// Now lookup defined mappings, so we can add them to the array
|
||||
let mappedLibPaths = wtconfig.get(`PMS.LibMapping.${serverID}`, 'WTNG_ERROR_WTNG');
|
||||
for (var idxPath in Object.keys(mappedLibPaths)){
|
||||
this.PMSLibPaths.push(Object.keys(mappedLibPaths)[idxPath]);
|
||||
}
|
||||
log.debug(`[FindMedia.js] (getPMSPathArr) - PMSLibPaths is ${this.PMSLibPaths}`);
|
||||
log.info(`[FindMedia.js] (getPMSPathArr) - End`);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
||||
export { findMedia };
|
|
@ -1,62 +0,0 @@
|
|||
<template>
|
||||
<b-container fluid>
|
||||
<div class="col-lg-10 col-md-12 col-xs-12">
|
||||
<h1>{{ $t("Modules.PMS.FindMissing.Name") }}</h1>
|
||||
<p>{{ $t("Modules.PMS.FindMissing.Description") }}</p>
|
||||
</div>
|
||||
</b-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import i18n from '../../../../i18n';
|
||||
//import store from '../../../store';
|
||||
//import { wtconfig } from '../General/wtutils';
|
||||
//import { dvr } from "./scripts/dvr";
|
||||
|
||||
i18n
|
||||
|
||||
const log = require("electron-log");
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
serverIsSelected: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
log.info("FindMissing Created");
|
||||
this.serverSelected();
|
||||
},
|
||||
computed: {
|
||||
// We need this computed, for watching for changes to selected server
|
||||
selectedServerAddress: function(){
|
||||
return this.$store.getters.getSelectedServerAddress
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/* Check if a server is selected, and if not
|
||||
tell user, and disable backup */
|
||||
async serverSelected() {
|
||||
let serverCheck = this.$store.getters.getSelectedServer;
|
||||
this.serverIsSelected = ( this.$store.getters.getSelectedServer != "none" );
|
||||
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>
|
|
@ -6,10 +6,11 @@
|
|||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<!-- Select Lib -->
|
||||
<div class="d-flex align-items-center">
|
||||
<b-form-group id="SelLibGroup" v-bind:label="$t('Modules.ET.optExpType.lblSelectSelection')" label-size="lg" label-class="font-weight-bold pt-0">
|
||||
<b-tooltip target="SelLibGroup" triggers="hover">
|
||||
{{ $t('Modules.PMS.Butler.TTSelectTask') }}
|
||||
{{ $t('Modules.PMS.LibMapping.TTSelectLibrary') }}
|
||||
</b-tooltip>
|
||||
<b-form-select
|
||||
v-model="selLib"
|
||||
|
@ -38,10 +39,7 @@
|
|||
import i18n from '../../../../i18n';
|
||||
import store from '../../../../store';
|
||||
import { wtconfig, dialog } from '../../General/wtutils';
|
||||
//import { dvr } from "./scripts/dvr";
|
||||
const {JSONPath} = require('jsonpath-plus');
|
||||
|
||||
i18n
|
||||
import { pms } from '../../General/pms';
|
||||
|
||||
const log = require("electron-log");
|
||||
export default {
|
||||
|
@ -57,6 +55,7 @@
|
|||
created() {
|
||||
log.info("LibraryMapping Created");
|
||||
this.serverSelected();
|
||||
this.getPMSSections();
|
||||
},
|
||||
watch: {
|
||||
// Watch for when selected server address is updated
|
||||
|
@ -83,38 +82,25 @@
|
|||
{
|
||||
let curVal = {};
|
||||
curVal['PMS'] = this.items[index]['PMS'];
|
||||
// If a dot is present in the path, we need to escape it
|
||||
curVal['PMS'] = curVal['PMS'].replace('.', '\\.');
|
||||
curVal['Workstation'] = mapDir[0];
|
||||
curVal['_rowVariant'] = "success";
|
||||
this.items[index] = curVal;
|
||||
// Update view
|
||||
this.$refs.table.refresh();
|
||||
// Get ServerID
|
||||
const serverID = store.getters.getSelectedServer.clientIdentifier;
|
||||
// Save setting
|
||||
wtconfig.set(`PMS.LibMapping.${serverID}.${curVal['PMS']}`, curVal['Workstation']);
|
||||
// Remove escape char for viewing
|
||||
curVal['PMS'] = curVal['PMS'].replace('\\.', '.');
|
||||
this.items[index] = curVal;
|
||||
// Update view
|
||||
this.$refs.table.refresh();
|
||||
|
||||
}
|
||||
},
|
||||
getPMSSections: async function(){
|
||||
this.selLibrary = "";
|
||||
await this.$store.dispatch('fetchSections')
|
||||
const sections = await this.$store.getters.getPmsSections;
|
||||
const result = [];
|
||||
this.selLib = "";
|
||||
if (Array.isArray(sections) && sections.length) {
|
||||
sections.forEach(req => {
|
||||
if ( ['movie', 'show'].includes(req.type)){
|
||||
log.debug(`[LibraryMapping.vue] (getPMSSections) - pushing library: ${req.title} to results`);
|
||||
let item = [];
|
||||
item['text']=req.title;
|
||||
item['value']=JSONPath({path: '$..path', json: req.location});
|
||||
result.push(Object.assign({}, item));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.error("[LibraryMapping.vue] (getPMSSections) - No Library found");
|
||||
result.push["No Library found"];
|
||||
}
|
||||
this.selLibOptions = result;
|
||||
this.selLibOptions = await pms.getPMSSections(['movie', 'show']);
|
||||
},
|
||||
/* Check if a server is selected, and if not
|
||||
tell user, and disable backup */
|
||||
|
@ -138,24 +124,30 @@
|
|||
const serverID = store.getters.getSelectedServer.clientIdentifier;
|
||||
log.info(`[LibraryMapping.vue] (getLibPath) ServerID is: ${serverID}`);
|
||||
const fs = require("fs");
|
||||
arguments[0].forEach(element => {
|
||||
let entry;
|
||||
const wkstnPath = wtconfig.get(`PMS.LibMapping.${serverID}.${element}`, this.$t("Modules.PMS.LibMapping.ClickToDefine"));
|
||||
arguments[0]['location'].forEach(element => {
|
||||
let entry, virtualElement;
|
||||
virtualElement = element.replace('.', '\\.');
|
||||
//const wkstnPath = wtconfig.get(`PMS.LibMapping.${serverID}.${element}`, this.$t("Modules.PMS.LibMapping.ClickToDefine"));
|
||||
const wkstnPath = wtconfig.get(`PMS.LibMapping.${serverID}.${virtualElement}`, this.$t("Modules.PMS.LibMapping.ClickToDefine"));
|
||||
log.info(`[LibraryMapping.vue] (getLibPath) Saved path is: ${wkstnPath}`);
|
||||
// Check if path exists
|
||||
if (fs.existsSync(wkstnPath)) {
|
||||
log.debug(`[LibraryMapping.vue] (getLibPath) Saved path existed`);
|
||||
//element = element.replace('\\.', '.')
|
||||
entry = {PMS: element, Workstation: wkstnPath, _rowVariant: 'success'};
|
||||
//entry = {PMS: virtualElement, Workstation: wkstnPath, _rowVariant: 'success'};
|
||||
} else {
|
||||
log.debug(`[LibraryMapping.vue] (getLibPath) Saved path not defined`);
|
||||
if (fs.existsSync(element)) {
|
||||
log.debug(`[LibraryMapping.vue] (getLibPath) PMS path existed`);
|
||||
wtconfig.set(`PMS.LibMapping.${serverID}.${element}`, element);
|
||||
entry = {PMS: element, Workstation: element, _rowVariant: 'success'};
|
||||
//entry = {PMS: virtualElement, Workstation: element, _rowVariant: 'success'};
|
||||
}
|
||||
else {
|
||||
log.error(`[LibraryMapping.vue] (getLibPath) PMS path unknown`);
|
||||
entry = {PMS: element, Workstation: wkstnPath, _rowVariant: 'danger'};
|
||||
//entry = {PMS: virtualElement, Workstation: wkstnPath, _rowVariant: 'danger'};
|
||||
}
|
||||
}
|
||||
arrPath.push(entry);
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
<br />
|
||||
* {{ $t("Modules.PMS.DVR.Description") }}</p>
|
||||
</div>
|
||||
<div v-if="showFindMissing">
|
||||
<p><b>{{ $t("Modules.PMS.FindMissing.Name") }}</b>
|
||||
<div v-if="showFindMedia">
|
||||
<p><b>{{ $t("Modules.PMS.FindMedia.Name") }}</b>
|
||||
<br />
|
||||
* {{ $t("Modules.PMS.FindMissing.Description") }}</p>
|
||||
* {{ $t("Modules.PMS.FindMedia.Description") }}</p>
|
||||
</div>
|
||||
<div v-if="showLibMapping">
|
||||
<p><b>{{ $t("Modules.PMS.LibMapping.Name") }}</b>
|
||||
|
@ -64,7 +64,7 @@
|
|||
selLevel: "",
|
||||
showButler: !(wtutils.hideMenu('pmsButler')),
|
||||
showDVR: !(wtutils.hideMenu('pmsDVR')),
|
||||
showFindMissing: !(wtutils.hideMenu('pmsFindMissing')),
|
||||
showFindMedia: !(wtutils.hideMenu('pmsFindMedia')),
|
||||
showLibMapping: !(wtutils.hideMenu('pmsLibMapping')),
|
||||
showSettings: !(wtutils.hideMenu('pmsSettings')),
|
||||
showViewState: !(wtutils.hideMenu('pmsViewState'))
|
||||
|
|
|
@ -12,7 +12,8 @@ import Butler from '../components/modules/PMS/Butler/butler';
|
|||
import Language from '../components/modules/Main/Language.vue';
|
||||
import GlobalSettings from '../components/modules/Main/GlobalSettings';
|
||||
import DVR from '../components/modules/PMS/DVR/DVR';
|
||||
import FindMissing from '../components/modules/PMS/FindMissing/FindMissing';
|
||||
import FindMedia from '../components/modules/PMS/FindMedia/FindMedia';
|
||||
import FindMediaSettings from '../components/modules/PMS/FindMedia/Settings/FindMediaSettings';
|
||||
import LibraryMapping from '../components/modules/PMS/LibraryMapping/LibraryMapping';
|
||||
import ViewState from '../components/modules/PMS/ViewState/ViewState';
|
||||
import About from '../components/modules/Main/About';
|
||||
|
@ -97,9 +98,15 @@ Vue.use(VueRouter)
|
|||
meta: {requiresAuth: true}
|
||||
},
|
||||
{
|
||||
path: '/pms/findmissing',
|
||||
name: "FindMissing",
|
||||
component: FindMissing,
|
||||
path: '/pms/findmedia',
|
||||
name: "FindMedia",
|
||||
component: FindMedia,
|
||||
meta: {requiresAuth: true}
|
||||
},
|
||||
{
|
||||
path: '/pms/findmedia/Settings',
|
||||
name: "FindMediaSettings",
|
||||
component: FindMediaSettings,
|
||||
meta: {requiresAuth: true}
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue