mirror of
https://github.com/WebTools-NG/WebTools-NG
synced 2024-11-22 19:13:19 +00:00
Merge branch 'master' into #440-DVR-Module
This commit is contained in:
commit
f412fc001b
20 changed files with 1958 additions and 850 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,6 +1,19 @@
|
|||
# ![Logo](https://github.com/WebTools-NG/WebTools-NG/blob/master/src/assets/WebTools-48x48.png) WebTools-ng Change log
|
||||
|
||||
## V0.3.14 (Not yet released)
|
||||
## V0.3.15 (Not released yet)
|
||||
|
||||
**Note**: This version is an Beta version
|
||||
|
||||
**Note 2**: In this version, the following is disabled:
|
||||
|
||||
* Export to xlsx format ([See #331](https://github.com/WebTools-NG/WebTools-NG/issues/331))
|
||||
* Photo export
|
||||
|
||||
**Changes**:
|
||||
|
||||
* [#453 Kickstart Butler Scheduled tasks](https://github.com/WebTools-NG/WebTools-NG/issues/453)
|
||||
|
||||
## V0.3.14 (20220323)
|
||||
|
||||
**Note**: This version is an Beta version
|
||||
|
||||
|
@ -14,6 +27,7 @@
|
|||
* [#429 Allow setting the LogNumFiles from Settings](https://github.com/WebTools-NG/WebTools-NG/issues/429)
|
||||
* [#435 Showing Rel Notes should only show current version](https://github.com/WebTools-NG/WebTools-NG/issues/435)
|
||||
* [#424 Export for severs with special charters in server name](https://github.com/WebTools-NG/WebTools-NG/issues/424)
|
||||
* [#444 ET: Suggest better naming for movies only](https://github.com/WebTools-NG/WebTools-NG/issues/444)
|
||||
|
||||
## V0.3.13 (20220102)
|
||||
|
||||
|
|
2020
package-lock.json
generated
2020
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "webtools-ng",
|
||||
"productName": "WebTools-NG",
|
||||
"version": "0.3.14",
|
||||
"version": "0.3.15",
|
||||
"description": "WebTools Next Generation 4 Plex",
|
||||
"author": "dane22 & CPSO",
|
||||
"license": "MPL-2.0",
|
||||
|
@ -45,7 +45,7 @@
|
|||
"levenary": "^1.1.1",
|
||||
"minimist": "^1.2.5",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-sass": "^6.0.0",
|
||||
"node-sass": "^7.0.0",
|
||||
"popper.js": "^1.16.1",
|
||||
"rimraf": "^2.7.1",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
|
@ -66,7 +66,7 @@
|
|||
"@vue/cli-plugin-vuex": "^4.5.10",
|
||||
"@vue/cli-service": "~4.3.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"electron": "^11.2.3",
|
||||
"electron": "^13.6.6",
|
||||
"electron-devtools-installer": "^3.1.1",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
|
|
|
@ -111,7 +111,8 @@
|
|||
"NavTitle": "Global Settings"
|
||||
},
|
||||
"PMS": {
|
||||
"Settings": "Settings"
|
||||
"Settings": "Settings",
|
||||
"Butler": "Butler scheduled tasks"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -143,6 +144,8 @@
|
|||
"TimeOut": "Timeout when requesting info from PMS in sec (Global setting)",
|
||||
"OrgTitleNull": "Default \"Original Title\" to \"Title\", if empty",
|
||||
"SortTitleNull": "Default \"Sort Title\" to \"Title\", if empty",
|
||||
"suggestedFileNoExtra": "For suggested filename strip extra info from filenames so only essential info is kept",
|
||||
"suggestedUseOrigenTitle": "When suggesting file or foldername, use original title",
|
||||
"AutoXLSCol": "Autosize column (xlsx only)",
|
||||
"AutoXLSRow": "Autosize row (xlsx only)",
|
||||
"ExportToExcel": "Export to xlsx",
|
||||
|
@ -156,8 +159,14 @@
|
|||
"ChReturn": "Replace Return character with",
|
||||
"ChReturn_TT": "Leave blank to not replace",
|
||||
"ChNewLine": "Replace NewLine character with",
|
||||
"ChNewLine_TT": "Leave blank to not replace"
|
||||
"ChNewLine_TT": "Leave blank to not replace",
|
||||
"MoviesUseId": "Default Id for suggested folder and filename for movies",
|
||||
"ttMoviesUseId": "If exporting Suggested Filename or Folder for movies, default to selected naming if available. Fallback to IMDB if not",
|
||||
"ShowsUseId": "Default Id for suggested folder and filename for shows",
|
||||
"ttShowsUseId": "If exporting Suggested Filename or Folder for shows, default to selected naming if available. Fallback to TMDB if not"
|
||||
},
|
||||
"FolderNameOK": "** Folder named correctly **",
|
||||
"FileNameOK": "** File named correctly **",
|
||||
"LevelInfo": "Export level determines which data are going to be exported.",
|
||||
"SelectLevel": "Select level",
|
||||
"BuildInLevels": "*** Built-in levels ***",
|
||||
|
@ -318,6 +327,29 @@
|
|||
"Description": "@:Modules.PMS.Name module allows you to manage your server",
|
||||
"ErrorNoServerSelectedTitle": "No server selected",
|
||||
"ErrorNoServerSelectedMsg": "You need to select a server on the top of the screen",
|
||||
"Butler": {
|
||||
"Title": "Butler Scheduled Tasks",
|
||||
"Description": "Here you can kickstart a scheduled task",
|
||||
"SelectTask": "Select the scheduled task to run now",
|
||||
"TTSelectTask": "Here you select among the scheduled tasks that kan be started now",
|
||||
"BackupDatabase": "Backup your database",
|
||||
"BuildGracenoteCollections": "Build Gracenote Collections",
|
||||
"CheckForUpdates": "Check for updates",
|
||||
"CleanOldBundles": "Clean old bundles",
|
||||
"CleanOldCacheFiles": "Clean old Cache Files",
|
||||
"DeepMediaAnalysis": "Deep Media Analysis",
|
||||
"GenerateAutoTags": "Generate Auto Tags",
|
||||
"GenerateChapterThumbs": "Generate Chapter Thumbs",
|
||||
"GenerateMediaIndexFiles": "Generate Media Index Files",
|
||||
"OptimizeDatabase": "Optimize Database",
|
||||
"RefreshLibraries": "Refresh Libraries",
|
||||
"RefreshLocalMedia": "Refresh Local Media",
|
||||
"RefreshPeriodicMetadata": "Refresh Periodic Metadata",
|
||||
"UpgradeMediaAnalysis": "Upgrade Media Analysis",
|
||||
"RunTask": "Run selected task",
|
||||
"TaskStarted": "The selected task has been started",
|
||||
"TaskDetails": "To follow progress, see Plex WebClient Dashboard"
|
||||
},
|
||||
"Settings": {
|
||||
"Settings": "Settings",
|
||||
"Description": "Here you can define the settings for the selected server",
|
||||
|
|
|
@ -69,6 +69,11 @@
|
|||
href: '/pms/settings',
|
||||
title: this.$t("Common.Menu.Sidebar.PMS.Settings"),
|
||||
icon: 'fa fa-cog'
|
||||
},
|
||||
{
|
||||
href: '/pms/butler',
|
||||
title: this.$t("Common.Menu.Sidebar.PMS.Butler"),
|
||||
icon: 'fa fa-tasks'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -46,6 +46,19 @@
|
|||
v-model="cbSelected"
|
||||
@change.native="filterTable">
|
||||
</b-form-checkbox-group>
|
||||
</b-form-group>
|
||||
<b-form-group id="etSugMovieID" v-bind:label="$t('Modules.ET.Settings.MoviesUseId')" label-size="lg" label-class="font-weight-bold pt-0">
|
||||
<b-tooltip target="etSugMovieID" triggers="hover">
|
||||
{{ $t('Modules.ET.Settings.ttMoviesUseId') }}
|
||||
</b-tooltip>
|
||||
<b-form-select
|
||||
class="form-control"
|
||||
v-model="SelectedMoviesID"
|
||||
id="SelectedMoviesID"
|
||||
:options="SelectedMoviesIDOptions"
|
||||
@change="SelectedMoviesIDChanged"
|
||||
name="SugMovieID">
|
||||
</b-form-select>
|
||||
</b-form-group>
|
||||
</div>
|
||||
</b-container>
|
||||
|
@ -54,12 +67,11 @@
|
|||
<script>
|
||||
const log = require("electron-log");
|
||||
import {wtutils, wtconfig, dialog} from '../../General/wtutils'
|
||||
|
||||
log, wtutils, wtconfig, dialog
|
||||
import i18n from '../../../../i18n'
|
||||
export default {
|
||||
created() {
|
||||
this.getcbDefaults();
|
||||
this.getDefaults();
|
||||
if (wtconfig.get('ET.ColumnSep') == '\t')
|
||||
{
|
||||
this.ColumnSep = '{TAB}';
|
||||
|
@ -83,24 +95,34 @@
|
|||
{ text: i18n.t('Modules.ET.Settings.ExportToCSV'), value: 'ExpCSV' },
|
||||
{ text: i18n.t('Modules.ET.Settings.ExportToExcel'), value: 'ExpXLSX', disabled: true },
|
||||
{ text: i18n.t('Modules.ET.Settings.OrgTitleNull'), value: 'OrgTitleNull' },
|
||||
{ text: i18n.t('Modules.ET.Settings.SortTitleNull'), value: 'SortTitleNull' }
|
||||
{ text: i18n.t('Modules.ET.Settings.SortTitleNull'), value: 'SortTitleNull' },
|
||||
{ text: i18n.t('Modules.ET.Settings.suggestedFileNoExtra'), value: 'suggestedFileNoExtra' },
|
||||
{ text: i18n.t('Modules.ET.Settings.suggestedUseOrigenTitle'), value: 'suggestedUseOrigenTitle' }
|
||||
],
|
||||
ChReturn: wtconfig.get('ET.ChReturn', '<RETURN>'),
|
||||
ChNewLine: wtconfig.get('ET.ChNewLine', '<NEWLINE>')
|
||||
ChNewLine: wtconfig.get('ET.ChNewLine', '<NEWLINE>'),
|
||||
SelectedMoviesIDOptions: ['imdb', 'tmdb'],
|
||||
SelectedMoviesID: '',
|
||||
SelectedShowsIDOptions: ['tmdb', 'tvdb'],
|
||||
SelectedShowsID: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getcbDefaults(){
|
||||
const cbItems = ["ExpCSV","ExpXLSX", "OrgTitleNull", "SortTitleNull"];
|
||||
getDefaults(){
|
||||
const cbItems = ["ExpCSV","ExpXLSX", "OrgTitleNull", "SortTitleNull", "suggestedFileNoExtra", "suggestedUseOrigenTitle"];
|
||||
for(let i = 0; i < cbItems.length; i++){
|
||||
if (wtconfig.get("ET." + cbItems[i], false)){
|
||||
this.cbSelected.push(cbItems[i]);
|
||||
}
|
||||
}
|
||||
this.SelectedMoviesID = wtconfig.get("ET.SelectedMoviesID", "imdb");
|
||||
},
|
||||
SelectedMoviesIDChanged(){
|
||||
wtconfig.set("ET.SelectedMoviesID", this.SelectedMoviesID);
|
||||
},
|
||||
filterTable(){
|
||||
this.$nextTick(()=>{console.log(this.cbSelected);})
|
||||
for( var cbItem of ["ExpCSV","ExpXLSX","OrgTitleNull", "SortTitleNull", "AutoXLSCol", "AutoXLSRow"]){
|
||||
for( var cbItem of ["ExpCSV","ExpXLSX","OrgTitleNull", "SortTitleNull", "AutoXLSCol", "AutoXLSRow", "suggestedFileNoExtra", "suggestedUseOrigenTitle"]){
|
||||
wtconfig.set("ET." + cbItem, (this.cbSelected.includes(cbItem)))
|
||||
}
|
||||
},
|
||||
|
|
|
@ -505,6 +505,12 @@
|
|||
"type": "array-count",
|
||||
"include": "includeExtras=1"
|
||||
},
|
||||
"File Path":
|
||||
{
|
||||
"key": "$.Media[0].Part[0].file",
|
||||
"call": 1,
|
||||
"type": "string"
|
||||
},
|
||||
"Filters":
|
||||
{
|
||||
"key": "$.filters",
|
||||
|
@ -1195,6 +1201,20 @@
|
|||
"subtype": "string",
|
||||
"subkey": "$.title"
|
||||
},
|
||||
"Suggested File Name":
|
||||
{
|
||||
"key": "$.title",
|
||||
"call": 1,
|
||||
"type": "string",
|
||||
"postProcess": true
|
||||
},
|
||||
"Suggested Folder Name":
|
||||
{
|
||||
"key": "$.title",
|
||||
"call": 1,
|
||||
"type": "string",
|
||||
"postProcess": true
|
||||
},
|
||||
"Summary":
|
||||
{
|
||||
"key": "$.summary",
|
||||
|
|
|
@ -47,20 +47,21 @@
|
|||
"levels": {
|
||||
"Level 1": "level1",
|
||||
"Level 2": "level2",
|
||||
"All": "all"
|
||||
"All": "all",
|
||||
"Suggest Naming": "suggestnaming"
|
||||
},
|
||||
"LevelCount": {
|
||||
"Level 1": 1,
|
||||
"Level 2": 1,
|
||||
"Suggest Naming": 1,
|
||||
"All": 2,
|
||||
"all": 2
|
||||
},
|
||||
"Include": {
|
||||
"Level 11": "",
|
||||
"Level 21": "",
|
||||
"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",
|
||||
"Missing1": "includeAllConcerts=1&includeChildren=1&includeConcerts=1&includeFields=1&includeGeolocation=1&includeLoudnessRamps=1&includeMarkers=1&includeOnDeck=1&includePopularLeaves=1&includePreferences=1&includeRelated=1&includeRelatedCount=1&includeReviews=1&includeStations=1",
|
||||
"Everything1": "checkFiles=1&includeAllConcerts=1&includeBandwidths=1&includeChapters=1&includeChildren=1&includeConcerts=1&includeExtras=1&includeFields=1&includeGeolocation=1&includeLoudnessRamps=1&includeMarkers=1&includeOnDeck=1&includePopularLeaves=1&includePreferences=1&includeRelated=1&includeRelatedCount=1&includeReviews=1&includeStations=1"
|
||||
"GED SLET Missing1": "includeAllConcerts=1&includeChildren=1&includeConcerts=1&includeFields=1&includeGeolocation=1&includeLoudnessRamps=1&includeMarkers=1&includeOnDeck=1&includePopularLeaves=1&includePreferences=1&includeRelated=1&includeRelatedCount=1&includeReviews=1&includeStations=1",
|
||||
"GED SLET Everything1": "checkFiles=1&includeAllConcerts=1&includeBandwidths=1&includeChapters=1&includeChildren=1&includeConcerts=1&includeExtras=1&includeFields=1&includeGeolocation=1&includeLoudnessRamps=1&includeMarkers=1&includeOnDeck=1&includePopularLeaves=1&includePreferences=1&includeRelated=1&includeRelatedCount=1&includeReviews=1&includeStations=1"
|
||||
}
|
||||
|
||||
},
|
||||
|
|
|
@ -35,6 +35,13 @@
|
|||
"Audience Rating",
|
||||
"User Rating"
|
||||
],
|
||||
"suggestnaming": [
|
||||
"Title",
|
||||
"Year",
|
||||
"File Path",
|
||||
"Suggested Folder Name",
|
||||
"Suggested File Name"
|
||||
],
|
||||
"all": [
|
||||
"Added",
|
||||
"Art url",
|
||||
|
|
|
@ -60,10 +60,259 @@ function setQualifier( {str:str})
|
|||
{
|
||||
result = `${wtconfig.get('ET.TextQualifierCSV', 'N/A')}${str}${wtconfig.get('ET.TextQualifierCSV', 'N/A')}`
|
||||
}
|
||||
log.debug(`etHelper (setQualifier): Got: _WTNG_${str}_WTNG_ and returning ${result}`);
|
||||
log.debug(`etHelper (setQualifier) - Got: _WTNG_${str}_WTNG_ and returning ${result}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clean up tmpFileName for suggested files/folders
|
||||
// Remove leading and trailing spaces, as well as special characters
|
||||
function cleanupSuggestedFile( tmpFileName )
|
||||
{
|
||||
const unWantedChars = '.-*_[](){}';
|
||||
log.verbose(`etHelper (cleanupSuggestedFile) - starting Param: ${tmpFileName}`);
|
||||
// Now replace square brackets if present with a dot
|
||||
tmpFileName = tmpFileName.replaceAll("[", ".");
|
||||
tmpFileName = tmpFileName.replaceAll("]", ".");
|
||||
// Start by trimming the string
|
||||
tmpFileName = tmpFileName.trim();
|
||||
while ( unWantedChars.indexOf(tmpFileName.charAt(0)) > -1)
|
||||
{
|
||||
tmpFileName = tmpFileName.slice(1).trim();
|
||||
if ( tmpFileName.length === 0 ) break;
|
||||
}
|
||||
// Remove from end of the string
|
||||
while ( unWantedChars.indexOf(tmpFileName.charAt(tmpFileName.length-1)) > -1)
|
||||
{
|
||||
tmpFileName = tmpFileName.slice(0,-1).trim();
|
||||
if ( tmpFileName.length === 0 ) break;
|
||||
}
|
||||
// Now replace double dots if present with a single dot
|
||||
tmpFileName = tmpFileName.replaceAll("..", ".");
|
||||
// Now delete empty brackets
|
||||
tmpFileName = tmpFileName.replaceAll("()", "");
|
||||
tmpFileName = tmpFileName.replaceAll("{}", "");
|
||||
log.verbose(`etHelper (cleanupSuggestedFile) - Returning: ${tmpFileName}`);
|
||||
return tmpFileName;
|
||||
}
|
||||
|
||||
// Returns a suggested title for a media
|
||||
function getSuggestedTitle( data )
|
||||
{
|
||||
let title;
|
||||
if (wtconfig.get('ET.suggestedUseOrigenTitle', false))
|
||||
{
|
||||
title = String(JSONPath({path: '$.data.originalTitle', json: data})).replace(/[/\\?%*:|"<>]/g, '').replace(' ', ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
title = String(JSONPath({path: '$.data.title', json: data})).replace(/[/\\?%*:|"<>]/g, '').replace(' ', ' ');
|
||||
}
|
||||
// Original selected, but none exist, we default to named title
|
||||
if ( title === '')
|
||||
{
|
||||
title = String(JSONPath({path: '$.data.title', json: data})).replace(/[/\\?%*:|"<>]/g, '').replace(' ', ' ');
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
// Returns a suggested year for a media
|
||||
function getSuggestedYear( data )
|
||||
{
|
||||
return String(JSONPath({path: '$.data.year', json: data}));
|
||||
}
|
||||
|
||||
// Returns a suggested id for a media
|
||||
function getSuggestedId( data )
|
||||
{
|
||||
log.verbose(`etHelper (getSuggestedId) - Started. To see Param, switch to Silly logging`);
|
||||
log.silly(`etHelper (getSuggestedId) - Starting with param: ${JSON.stringify(data)}`);
|
||||
let imdb = String(JSONPath({path: "$.data.Guid[?(@.id.startsWith('imdb'))].id", json: data}));
|
||||
let tmdb = String(JSONPath({path: "$.data.Guid[?(@.id.startsWith('tmdb'))].id", json: data}));
|
||||
let tvdb = String(JSONPath({path: "$.data.Guid[?(@.id.startsWith('tvdb'))].id", json: data}));
|
||||
if (imdb === ''){
|
||||
imdb = "imdb://" + String(JSONPath({path: "$.data.guid", json: data})).substring(26,).split('?')[0];
|
||||
}
|
||||
// Fallback to imdb, if tmdb is not present
|
||||
if (tmdb === '')
|
||||
{
|
||||
tmdb = imdb;
|
||||
}
|
||||
// Fallback to imdb, if tvdb is not present
|
||||
if (tvdb === '')
|
||||
{
|
||||
tvdb = imdb;
|
||||
}
|
||||
let selId;
|
||||
if ( etHelper.Settings.libType === 1)
|
||||
{
|
||||
selId = wtconfig.get("ET.SelectedMoviesID", "imdb");
|
||||
}
|
||||
else
|
||||
{
|
||||
selId = wtconfig.get("ET.SelectedShowsID", "tmdb");
|
||||
}
|
||||
log.silly(`etHelper (getSuggestedId) - imdb ID: ${imdb}`);
|
||||
log.silly(`etHelper (getSuggestedId) - tmdb ID: ${tmdb}`);
|
||||
log.silly(`etHelper (getSuggestedId) - tvdb ID: ${tvdb}`);
|
||||
|
||||
let Id;
|
||||
switch(selId) {
|
||||
case 'imdb':
|
||||
Id = `{imdb-${imdb.slice(7)}}`;
|
||||
break;
|
||||
case 'tmdb':
|
||||
if (tmdb === '')
|
||||
{
|
||||
Id = `{imdb-${imdb.slice(7)}}`;
|
||||
}
|
||||
else
|
||||
{
|
||||
Id = `{tmdb-${tmdb.slice(7)}}`;
|
||||
}
|
||||
break;
|
||||
case 'tvdb':
|
||||
if (tvdb === '')
|
||||
{
|
||||
Id = `{imdb-${imdb.slice(7)}}`;
|
||||
}
|
||||
else
|
||||
{
|
||||
Id = `{tvdb-${tvdb.slice(7)}}`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
log.debug(`etHelper (getSuggestedId) - Returning: "imdb": ${imdb}, "tmdb": ${tmdb}, "tvdb": ${tvdb}, "selId": ${Id}`);
|
||||
return {"imdb": imdb, "tmdb": tmdb, "tvdb": tvdb, "selId": Id};
|
||||
}
|
||||
|
||||
// Returns a string stripped for Year
|
||||
function stripYearFromFileName( tmpFileName, year ){
|
||||
const re = new RegExp(`\\b${year}\\b`, 'gi');
|
||||
return tmpFileName.replace(re, "").trim();
|
||||
}
|
||||
|
||||
// Returns a string stripped for ID's
|
||||
function stripIdFromFileName( param ){
|
||||
log.debug(`etHelper (stripIdFromFileName) - starting function with param as: ${JSON.stringify(param)}`);
|
||||
let tmpFileName = param.tmpFileName;
|
||||
let re;
|
||||
const imdb = param.imdb.slice(7);
|
||||
const tmdb = param.tmdb.slice(7);
|
||||
const tvdb = param.tvdb.slice(7);
|
||||
// Remove IMDB id
|
||||
log.debug(`etHelper (stripIdFromFileName) - Imdb string is : ${imdb}`);
|
||||
re = new RegExp(`\\b${imdb}\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
log.debug(`etHelper (stripIdFromFileName) - After imdb id is removed: ${tmpFileName}`);
|
||||
tmpFileName = tmpFileName.replace(/imdb-/i, '');
|
||||
log.debug(`etHelper (stripIdFromFileName) - After imdb string is removed: ${tmpFileName}`);
|
||||
// Remove TMDB id
|
||||
re = new RegExp(`\\b${tmdb}\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
// Remove TVDB id
|
||||
re = new RegExp(`\\b${tvdb}\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
const idProviders = ['imdb', 'tmdb', 'tvdb'];
|
||||
idProviders.forEach(element => {
|
||||
re = new RegExp(`\\b${element}\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
});
|
||||
return tmpFileName.replace(`{-}`, "").trim();
|
||||
}
|
||||
|
||||
// Returns a filename without the title
|
||||
function stripTitleFromFileName( tmpFileName, title )
|
||||
{
|
||||
let re;
|
||||
// Title in filename separated with dots
|
||||
let titleArray = tmpFileName.split(".");
|
||||
for (let titleElement of titleArray) {
|
||||
if (title.toUpperCase().indexOf(titleElement.toUpperCase()) > -1) {
|
||||
re = new RegExp(`\\b${titleElement}\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
}
|
||||
if (titleElement.toUpperCase() === 'AND')
|
||||
{
|
||||
titleElement = '&'
|
||||
if (title.toUpperCase().indexOf(titleElement.toUpperCase()) > -1) {
|
||||
re = new RegExp(`\\band\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Title in filename separated with spaces
|
||||
titleArray = tmpFileName.split(" ");
|
||||
for (let titleElement of titleArray) {
|
||||
if (title.toUpperCase().indexOf(titleElement.toUpperCase()) > -1) {
|
||||
re = new RegExp(`\\b${titleElement}\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
}
|
||||
if (titleElement == '&')
|
||||
{
|
||||
titleElement = 'AND'
|
||||
if (title.toUpperCase().indexOf(titleElement.toUpperCase()) > -1) {
|
||||
re = new RegExp(`\\b${titleElement}\\b`, 'gi');
|
||||
tmpFileName = tmpFileName.replace(re, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpFileName = tmpFileName.trim();
|
||||
return tmpFileName;
|
||||
}
|
||||
|
||||
// Strip parts from a filename, and return multiple values
|
||||
function stripPartsFromFileName( tmpFileName, title ) {
|
||||
log.verbose(`etHelper (stripPartsFromFileName) - looking at ${tmpFileName}`);
|
||||
let partName = '';
|
||||
// Find stacked item if present
|
||||
etHelper.StackedFilesName.forEach(element => {
|
||||
// Got a hit?
|
||||
if (tmpFileName.toLowerCase().indexOf(element) > -1) {
|
||||
// Get index again
|
||||
const idx = tmpFileName.toLowerCase().indexOf(element);
|
||||
// Got a stacked identifier, so make sure next character is a number in [1-8] range
|
||||
const numStacked = tmpFileName.charAt(idx + element.length);
|
||||
if (isNaN(numStacked)) {
|
||||
log.info(`etHelper (stripPartsFromFileName) - for the media with the title: "${title}" looking at the string: "${tmpFileName}" for stacked element: "${element}" but found next character not a number so ignorring`)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parseInt(numStacked, 10) < 9 && parseInt(numStacked, 10) > 0)
|
||||
{
|
||||
// Extract element part, but add one char more for the counter
|
||||
partName = tmpFileName.substring(idx, idx + element.length + 1).toLowerCase();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn(`etHelper (stripPartsFromFileName) - for the media with the title: "${title}" looking at the string: "${tmpFileName}" for stacked element: "${element}" but found entry not in range [1-8] so ignorring`)
|
||||
log.warn(`etHelper (stripPartsFromFileName) - See: https://support.plex.tv/articles/naming-and-organizing-your-movie-media-files/`)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Remove partName from tmpFile
|
||||
// Get index of partName
|
||||
const idx = tmpFileName.toUpperCase().indexOf(partName.toUpperCase());
|
||||
tmpFileName = tmpFileName.slice(0, idx) + tmpFileName.slice(idx + partName.length);
|
||||
// Remove white spaces
|
||||
tmpFileName = tmpFileName.trim();
|
||||
if (tmpFileName.length === 1)
|
||||
{
|
||||
if (tmpFileName === '.'){
|
||||
tmpFileName = '';
|
||||
}
|
||||
if (tmpFileName === '-'){
|
||||
tmpFileName = '';
|
||||
}
|
||||
}
|
||||
log.verbose(`etHelper (stripPartsFromFileName) - Returning tmpFileName as: ${tmpFileName} *** Returning partName as: ${partName}`);
|
||||
return {
|
||||
fileName: tmpFileName,
|
||||
partName: partName
|
||||
};
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
const etHelper = new class ETHELPER {
|
||||
|
@ -110,7 +359,9 @@ const etHelper = new class ETHELPER {
|
|||
selType: null,
|
||||
fileMajor: null,
|
||||
fileMinor: null,
|
||||
element: null
|
||||
element: null,
|
||||
SelectedMoviesID: null,
|
||||
SelectedShowsID: wtconfig.get("ET.SelectedShowsID", "tmdb")
|
||||
};
|
||||
|
||||
this.PMSHeader = wtutils.PMSHeader;
|
||||
|
@ -175,6 +426,7 @@ const etHelper = new class ETHELPER {
|
|||
'TimeElapsed': 8,
|
||||
'RunningTime': 9
|
||||
};
|
||||
this.StackedFilesName = ['cd', 'disc', 'dvd', 'part', 'pt'];
|
||||
}
|
||||
|
||||
resetETHelper() {
|
||||
|
@ -208,10 +460,125 @@ const etHelper = new class ETHELPER {
|
|||
}
|
||||
}
|
||||
|
||||
async postProcess( {name, val, title=""} ){
|
||||
log.debug(`ETHelper(postProcess): Val is: ${JSON.stringify(val)}`);
|
||||
log.debug(`ETHelper(postProcess): name is: ${name}`);
|
||||
log.debug(`ETHelper(postProcess): title is: ${title}`);
|
||||
/// This will return a suggested foldername, following Plex naming std
|
||||
async getSuggestedFolderName( data )
|
||||
{
|
||||
log.verbose(`etHelper (getSuggestedFolderName) - Starting function. To see param, use Silly log level`);
|
||||
log.silly(`etHelper (getSuggestedFolderName) - Data pased over as: ${JSON.stringify(data)}`);
|
||||
const title = getSuggestedTitle( data );
|
||||
const year = getSuggestedYear( data );
|
||||
const Id = getSuggestedId( data ).selId;
|
||||
// Get current folder name
|
||||
const curFolderName = path.basename(path.dirname(String(JSONPath({path: "$.data.Media[0].Part[0].file", json: data}))))
|
||||
// Compute suggested foldername
|
||||
let foldername = `${title} (${year}) ${Id}`;
|
||||
log.debug(`etHelper (getSuggestedFolderName) - Suggested folderName is: ${foldername}`);
|
||||
if (curFolderName === foldername) {
|
||||
return i18n.t("Modules.ET.FolderNameOK")
|
||||
}
|
||||
else {
|
||||
return foldername
|
||||
}
|
||||
}
|
||||
|
||||
/// This will return a suggested filename, following Plex naming std
|
||||
async getSuggestedFileName( data )
|
||||
{
|
||||
const title = getSuggestedTitle( data );
|
||||
const year = getSuggestedYear( data );
|
||||
const Ids = getSuggestedId( data );
|
||||
const Id = Ids.selId;
|
||||
const imdb = Ids.imdb;
|
||||
const tmdb = Ids.tmdb;
|
||||
const tvdb = Ids.tvdb;
|
||||
|
||||
// Get current filename
|
||||
const curFileName = path.parse(String(JSONPath({path: '$.data.Media[0].Part[0].file', json: data}))).name;
|
||||
|
||||
// Compute suggested filename, and start by stripping known info from existing name
|
||||
|
||||
// Start with the title
|
||||
let tmpFileName = stripTitleFromFileName( curFileName, title );
|
||||
// Strip Year from fileName
|
||||
tmpFileName = stripYearFromFileName( tmpFileName, year );
|
||||
// Strip ID from fileName
|
||||
tmpFileName = stripIdFromFileName( {tmpFileName: tmpFileName, imdb: imdb, tmdb: tmdb, tvdb: tvdb} );
|
||||
tmpFileName = cleanupSuggestedFile(tmpFileName);
|
||||
// Get parts, if a stacked media
|
||||
const parts = stripPartsFromFileName( tmpFileName, title );
|
||||
tmpFileName = parts.fileName;
|
||||
const partName = parts.partName;
|
||||
tmpFileName = cleanupSuggestedFile(tmpFileName);
|
||||
|
||||
//cleanupSuggestedFile(tmpFileName);
|
||||
|
||||
/*
|
||||
// Remove empty brackets if present
|
||||
tmpFileName = tmpFileName.replaceAll("()", "");
|
||||
// Remove empty curly brackets if present
|
||||
tmpFileName = tmpFileName.replaceAll("{}", "");
|
||||
// Now replace square brackets if present with a dot
|
||||
tmpFileName = tmpFileName.replaceAll("[", ".");
|
||||
tmpFileName = tmpFileName.replaceAll("]", ".");
|
||||
// Remove double dots if present
|
||||
tmpFileName = tmpFileName.replaceAll("..", ".");
|
||||
tmpFileName = tmpFileName.trim();
|
||||
// Remove leading dots if present
|
||||
while(tmpFileName.charAt(0) === '.')
|
||||
{
|
||||
tmpFileName = tmpFileName.substring(1);
|
||||
}
|
||||
// Remove trailing dots if present
|
||||
while(tmpFileName.slice(-1) === '.')
|
||||
{
|
||||
tmpFileName = tmpFileName.substring(0, tmpFileName.length - 1);
|
||||
}
|
||||
// Remove double square brackets if present
|
||||
tmpFileName = tmpFileName.replaceAll("[]", "");
|
||||
// Remove double square brackets with a space if present
|
||||
tmpFileName = tmpFileName.replaceAll("[ ]", "");
|
||||
// Remove double space if present
|
||||
tmpFileName = tmpFileName.replaceAll(" ", " ");
|
||||
// Remove space dot if present, and replace with dot
|
||||
tmpFileName = tmpFileName.replaceAll(" .", ".");
|
||||
|
||||
|
||||
|
||||
|
||||
tmpFileName = tmpFileName.trim();
|
||||
|
||||
*/
|
||||
// Get filename part of remaining filename
|
||||
if (tmpFileName.length >= 1)
|
||||
{
|
||||
tmpFileName = `[${tmpFileName}]`
|
||||
}
|
||||
let suggestedFileName;
|
||||
if (wtconfig.get("ET.suggestedFileNoExtra", false))
|
||||
{
|
||||
suggestedFileName = `${title} (${year}) ${Id} ${partName}`.trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
suggestedFileName = `${title} (${year}) ${Id} ${tmpFileName} ${partName}`.trim();
|
||||
}
|
||||
// Remove double space if present
|
||||
suggestedFileName = suggestedFileName.replaceAll(" ", " ");
|
||||
const fileNameExt = path.parse(String(JSONPath({path: '$.data.Media[0].Part[0].file', json: data}))).ext;
|
||||
suggestedFileName = `${suggestedFileName}${fileNameExt}`;
|
||||
log.debug(`etHelper (getSuggestedFileName) - returning ${suggestedFileName}`);
|
||||
if (curFileName === path.parse(suggestedFileName).name) {
|
||||
return i18n.t("Modules.ET.FileNameOK")
|
||||
}
|
||||
else {
|
||||
return suggestedFileName
|
||||
}
|
||||
}
|
||||
|
||||
async postProcess( {name, val, title="", data} ){
|
||||
log.debug(`ETHelper(postProcess) - Val is: ${JSON.stringify(val)}`);
|
||||
log.debug(`ETHelper(postProcess) - name is: ${name}`);
|
||||
log.debug(`ETHelper(postProcess) - title is: ${title}`);
|
||||
let retArray = [];
|
||||
let guidArr;
|
||||
let x, retVal, start, strStart, end, result;
|
||||
|
@ -228,6 +595,12 @@ const etHelper = new class ETHELPER {
|
|||
retVal = val.substring(0, 3);
|
||||
break;
|
||||
}
|
||||
case "Suggested File Name":
|
||||
retVal = await this.getSuggestedFileName( {data: data} );
|
||||
break;
|
||||
case "Suggested Folder Name":
|
||||
retVal = await this.getSuggestedFolderName( {data: data} );
|
||||
break;
|
||||
case "Part File":
|
||||
for (x=0; x<valArray.length; x++) {
|
||||
retArray.push(path.basename(valArray[x]).slice(0, -1));
|
||||
|
@ -457,7 +830,7 @@ const etHelper = new class ETHELPER {
|
|||
}
|
||||
} catch (error) {
|
||||
retVal = 'ERROR'
|
||||
log.error(`ETHelper(postProcess): We had an error as: ${error} . So postProcess retVal set to ERROR`);
|
||||
log.error(`ETHelper(postProcess) - We had an error as: ${error} . So postProcess retVal set to ERROR`);
|
||||
}
|
||||
return await retVal;
|
||||
}
|
||||
|
@ -592,8 +965,8 @@ const etHelper = new class ETHELPER {
|
|||
if ( doPostProc )
|
||||
{
|
||||
const title = JSONPath({path: String('$.title'), json: data})[0];
|
||||
log.debug(`ETHelper(addRowToTmp doPostProc): Name is: ${name} - Title is: ${title} - Val is: ${val}`)
|
||||
val = await this.postProcess( {name: name, val: val, title: title} );
|
||||
log.debug(`ETHelper(addRowToTmp doPostProc) - Name is: ${name} - Title is: ${title} - Val is: ${val}`)
|
||||
val = await this.postProcess( {name: name, val: val, title: title, data: data} );
|
||||
}
|
||||
// Here we add qualifier, if not a number
|
||||
if (!['array-count', 'int'].includes(type))
|
||||
|
@ -676,7 +1049,7 @@ const etHelper = new class ETHELPER {
|
|||
}
|
||||
|
||||
async populateExpFiles(){
|
||||
log.info('etHelper(populateExpFiles): Populating export files');
|
||||
log.info('etHelper(populateExpFiles) - Populating export files');
|
||||
// Current item counter in the chunck
|
||||
//let idx = 0;
|
||||
let idx = this.Settings.startItem;
|
||||
|
@ -697,7 +1070,7 @@ const etHelper = new class ETHELPER {
|
|||
//chunck = await this.getItemData({postURI: postURI + idx});
|
||||
chunck = await this.getSectionData();
|
||||
size = JSONPath({path: '$.MediaContainer.size', json: chunck});
|
||||
log.debug(`etHelper(populateExpFiles): Fetched a chunck with number of items as ${size} and contained: ${JSON.stringify(chunck)}`);
|
||||
log.debug(`etHelper(populateExpFiles) - Fetched a chunck with number of items as ${size} and contained: ${JSON.stringify(chunck)}`);
|
||||
if ( this.Settings.libType == this.ETmediaType.Libraries)
|
||||
{
|
||||
chunckItems = JSONPath({path: '$.MediaContainer.Directory.*', json: chunck});
|
||||
|
@ -750,13 +1123,13 @@ const etHelper = new class ETHELPER {
|
|||
}
|
||||
idx = Number(idx) + Number(step);
|
||||
} while (this.Settings.count < this.Settings.endItem);
|
||||
log.info('etHelper(populateExpFiles): Populating export files ended');
|
||||
log.info('etHelper(populateExpFiles) - Populating export files ended');
|
||||
}
|
||||
|
||||
async getSectionSize()
|
||||
{
|
||||
log.debug(`etHelper (getSectionSize): selType: ${this.Settings.selType}`)
|
||||
log.debug(`etHelper (getSectionSize): libTypeSec: ${this.Settings.libTypeSec}`)
|
||||
log.debug(`etHelper (getSectionSize) - selType: ${this.Settings.selType}`)
|
||||
log.debug(`etHelper (getSectionSize) - libTypeSec: ${this.Settings.libTypeSec}`)
|
||||
let url = '';
|
||||
switch(this.Settings.selType) {
|
||||
case this.ETmediaType.Playlist_Video:
|
||||
|
@ -802,14 +1175,14 @@ const etHelper = new class ETHELPER {
|
|||
|
||||
async getSectionData()
|
||||
{
|
||||
log.debug(`etHelper (getSectionData): Element is: ${this.Settings.element}`)
|
||||
log.debug(`etHelper (getSectionData) - Element is: ${this.Settings.element}`)
|
||||
//const url = this.Settings.baseURL + this.Settings.element + '?' + this.getPostURI() + this.Settings.count;
|
||||
const url = this.Settings.baseURL + this.Settings.element + this.getPostURI() + this.Settings.count;
|
||||
this.PMSHeader["X-Plex-Token"] = this.Settings.accessToken;
|
||||
log.verbose(`etHelper (getSectionData): Calling url in getSectionData: ${url}`)
|
||||
log.verbose(`etHelper (getSectionData) - Calling url in getSectionData: ${url}`)
|
||||
let response = await fetch(url, { method: 'GET', headers: this.PMSHeader});
|
||||
let resp = await response.json();
|
||||
log.debug(`etHelper (getSectionData): Response in getSectionData: ${JSON.stringify(resp)}`)
|
||||
log.debug(`etHelper (getSectionData) - Response in getSectionData: ${JSON.stringify(resp)}`)
|
||||
return resp
|
||||
}
|
||||
|
||||
|
@ -818,7 +1191,7 @@ const etHelper = new class ETHELPER {
|
|||
{
|
||||
this.Settings.libType = this.Settings.libTypeSec;
|
||||
}
|
||||
log.debug(`etHelper (getLevelCall): LibType: ${this.Settings.libTypeSec} * LevelName: ${this.Settings.levelName}`);
|
||||
log.debug(`etHelper (getLevelCall) - LibType: ${this.Settings.libTypeSec} * LevelName: ${this.Settings.levelName}`);
|
||||
let count = await defLevels[this.Settings.libTypeSec]['LevelCount'][this.Settings.levelName]
|
||||
if (count == undefined)
|
||||
{
|
||||
|
@ -1112,20 +1485,6 @@ const etHelper = new class ETHELPER {
|
|||
// [{"title":"DVR Movies","key":31,"type":"movie"}]
|
||||
const result = [];
|
||||
let url = address + '/library/sections/all'
|
||||
|
||||
console.log('Ged 5-4 Type: ' + this.Settings.selType)
|
||||
|
||||
/*
|
||||
if ([this.ETmediaType.Playlist_Audio, this.ETmediaType.Playlist_Video].includes(this.Settings.selType))
|
||||
{
|
||||
url = address + '/library/sections/all?type=15&sort=lastViewedAt:desc&playlistType=video,audio'
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
|
@ -1170,7 +1529,6 @@ const etHelper = new class ETHELPER {
|
|||
|
||||
getElement(){
|
||||
let element
|
||||
console.log('Ged 11 SecType: ' + this.Settings.libTypeSec)
|
||||
switch (this.Settings.libTypeSec) {
|
||||
case this.ETmediaType.Playlist_Photo:
|
||||
element = `/playlists/${this.Settings.selLibKey}/items`;
|
||||
|
@ -1199,6 +1557,7 @@ const etHelper = new class ETHELPER {
|
|||
|
||||
getIncludeInfo(){
|
||||
let includeInfo;
|
||||
log.debug(`etHelper (getIncludeInfo) - Started. libTypeSec is: ${this.Settings.libTypeSec} and levelName is: ${this.Settings.levelName}`);
|
||||
try {
|
||||
includeInfo = defLevels[this.Settings.libTypeSec]['Include'][this.Settings.levelName];
|
||||
}
|
||||
|
@ -1213,7 +1572,7 @@ const etHelper = new class ETHELPER {
|
|||
{
|
||||
includeInfo = ''
|
||||
}
|
||||
log.debug(`etHelper (getInclude): returning: ${includeInfo}`);
|
||||
log.debug(`etHelper (getInclude) - returning: ${includeInfo}`);
|
||||
return includeInfo;
|
||||
}
|
||||
|
||||
|
@ -1221,9 +1580,9 @@ const etHelper = new class ETHELPER {
|
|||
let postURI, includeInfo;
|
||||
// Find LibType steps
|
||||
const step = wtconfig.get("PMS.ContainerSize." + this.Settings.libType, 20);
|
||||
log.debug(`etHelper (getPostURI): Got Step size as: ${step}`);
|
||||
log.debug(`etHelper (getPostURI): libType is: ${this.Settings.libType}`);
|
||||
log.debug(`etHelper (getPostURI): libTypeSec is: ${this.Settings.libTypeSec}`);
|
||||
log.debug(`etHelper (getPostURI) - Got Step size as: ${step}`);
|
||||
log.debug(`etHelper (getPostURI) - libType is: ${this.Settings.libType}`);
|
||||
log.debug(`etHelper (getPostURI) - libTypeSec is: ${this.Settings.libTypeSec}`);
|
||||
switch (this.Settings.libType) {
|
||||
case this.ETmediaType.Photo:
|
||||
postURI = `?addedAt>>=-2208992400&X-Plex-Container-Size=${step}&type=${this.Settings.libTypeSec}&${this.uriParams}&X-Plex-Container-Start=`;
|
||||
|
@ -1248,7 +1607,7 @@ const etHelper = new class ETHELPER {
|
|||
break;
|
||||
default:
|
||||
includeInfo = this.getIncludeInfo();
|
||||
log.debug(`etHelper (getPostURI): includeInfo is: ${includeInfo}`);
|
||||
log.debug(`etHelper (getPostURI) - includeInfo is: ${includeInfo}`);
|
||||
if (includeInfo != '')
|
||||
{
|
||||
postURI = `?X-Plex-Container-Size=${step}&type=${this.Settings.libTypeSec}&${includeInfo}&X-Plex-Container-Start=`;
|
||||
|
@ -1258,7 +1617,7 @@ const etHelper = new class ETHELPER {
|
|||
postURI = `?X-Plex-Container-Size=${step}&type=${this.Settings.libTypeSec}&X-Plex-Container-Start=`;
|
||||
}
|
||||
}
|
||||
log.debug(`etHelper (getPostURI): Got postURI as ${postURI}`);
|
||||
log.debug(`etHelper (getPostURI) - Returning postURI as ${postURI}`);
|
||||
return postURI;
|
||||
}
|
||||
|
||||
|
@ -1378,29 +1737,29 @@ const etHelper = new class ETHELPER {
|
|||
|
||||
// Public methode to get the Header
|
||||
async getFieldHeader() {
|
||||
log.info('etHelper (getFieldHeader): FieldHeader requested');
|
||||
log.info('etHelper (getFieldHeader) - FieldHeader requested');
|
||||
try{
|
||||
if (isEmptyObj(this.#_FieldHeader))
|
||||
{
|
||||
log.verbose(`etHelper(getFieldHeader): Need to generate the header`);
|
||||
log.verbose(`etHelper(getFieldHeader) - Need to generate the header`);
|
||||
this.#_FieldHeader = await etHelper.#SetFieldHeader()
|
||||
}
|
||||
else
|
||||
{
|
||||
log.verbose(`etHelper(getFieldHeader): Returning cached headers`);
|
||||
log.verbose(`etHelper(getFieldHeader) - Returning cached headers`);
|
||||
}
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
log.error(`etHelper(getFieldHeader): ${error}`);
|
||||
log.error(`etHelper(getFieldHeader) - ${error}`);
|
||||
}
|
||||
log.verbose(`etHelper(getFieldHeader): Field header is: ${JSON.stringify(this.#_FieldHeader)}`);
|
||||
log.verbose(`etHelper(getFieldHeader) - Field header is: ${JSON.stringify(this.#_FieldHeader)}`);
|
||||
return this.#_FieldHeader;
|
||||
}
|
||||
|
||||
// Private methode to set the header
|
||||
async #SetFieldHeader(){
|
||||
log.verbose(`etHelper (SetFieldHeader): GetFieldHeader level: ${this.Settings.Level} - libType: ${this.Settings.libType}`);
|
||||
log.verbose(`etHelper (SetFieldHeader) - GetFieldHeader level: ${this.Settings.Level} - libType: ${this.Settings.libType}`);
|
||||
return await this.getLevelFields();
|
||||
}
|
||||
//#endregion
|
||||
|
|
|
@ -136,7 +136,8 @@ export default {
|
|||
this.ver = releases['relver'];
|
||||
this.beta = false;
|
||||
}
|
||||
if (wtutils.AppVersion != this.ver && this.ver)
|
||||
const compVer = wtutils.AppVersion.substr(0, wtutils.AppVersion.lastIndexOf("."));
|
||||
if (compVer != this.ver && this.ver)
|
||||
{
|
||||
// Show an update is present
|
||||
if (this.ver == wtconfig.get('Update.SkipVer', ''))
|
||||
|
|
152
src/components/modules/PMS/Butler/butler.vue
Normal file
152
src/components/modules/PMS/Butler/butler.vue
Normal file
|
@ -0,0 +1,152 @@
|
|||
<template>
|
||||
<b-container fluid>
|
||||
<div class="col-lg-10 col-md-12 col-xs-12">
|
||||
<h1>{{ $t("Modules.PMS.Butler.Title") }}</h1>
|
||||
<p>{{ $t("Modules.PMS.Butler.Description") }}</p>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<b-form-group id="ButlerGroup" v-bind:label="$t('Modules.PMS.Butler.SelectTask')" label-size="lg" label-class="font-weight-bold pt-0">
|
||||
<b-tooltip target="ButlerGroup" triggers="hover">
|
||||
{{ $t('Modules.PMS.Butler.TTSelectTask') }}
|
||||
</b-tooltip>
|
||||
<b-form-select
|
||||
v-model="selTask"
|
||||
id="selTask"
|
||||
:options="selTaskOptions"
|
||||
name="selTask">
|
||||
</b-form-select>
|
||||
</b-form-group>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class="buttons">
|
||||
<!-- Buttons -->
|
||||
<div id="buttons" class="text-center">
|
||||
<b-button-group >
|
||||
<b-button variant="success" class="mr-1" :disabled="this.selTask == ''" @click="executeButlerTask"> {{ $t('Modules.PMS.Butler.RunTask') }} </b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</b-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const log = require("electron-log");
|
||||
import i18n from '../../../../i18n';
|
||||
import store from '../../../../store';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selTaskOptions: [
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.BackupDatabase'),
|
||||
"value": "BackupDatabase"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.BuildGracenoteCollections'),
|
||||
"value": "BuildGracenoteCollections"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.CheckForUpdates'),
|
||||
"value": "CheckForUpdates"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.CleanOldBundles'),
|
||||
"value": "CleanOldBundles"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.CleanOldCacheFiles'),
|
||||
"value": "CleanOldCacheFiles"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.DeepMediaAnalysis'),
|
||||
"value": "DeepMediaAnalysis"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.GenerateAutoTags'),
|
||||
"value": "GenerateAutoTags"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.GenerateChapterThumbs'),
|
||||
"value": "GenerateChapterThumbs"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.GenerateMediaIndexFiles'),
|
||||
"value": "GenerateMediaIndexFiles"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.OptimizeDatabase'),
|
||||
"value": "OptimizeDatabase"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.RefreshLibraries'),
|
||||
"value": "RefreshLibraries"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.RefreshLocalMedia'),
|
||||
"value": "RefreshLocalMedia"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.RefreshPeriodicMetadata'),
|
||||
"value": "RefreshPeriodicMetadata"
|
||||
},
|
||||
{
|
||||
"text": i18n.t('Modules.PMS.Butler.UpgradeMediaAnalysis'),
|
||||
"value": "UpgradeMediaAnalysis"
|
||||
}
|
||||
],
|
||||
selTask : "",
|
||||
};
|
||||
},
|
||||
created() {
|
||||
log.info("PMS Butler Created");
|
||||
this.serverSelected();
|
||||
},
|
||||
computed: {
|
||||
selectedServerAddress: function(){
|
||||
return this.$store.getters.getSelectedServerAddress;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async executeButlerTask() {
|
||||
log.debug(`Starting Butler Task: ${this.selTask}`);
|
||||
await store.dispatch('startButlerTask', {
|
||||
Token: this.$store.getters.getAuthToken,
|
||||
Address: this.$store.getters.getSelectedServerAddress,
|
||||
Job: this.selTask});
|
||||
this.$bvToast.toast(this.$t("Modules.PMS.Butler.TaskDetails"), {
|
||||
title: this.$t("Modules.PMS.Butler.TaskStarted"),
|
||||
autoHideDelay: 4000,
|
||||
solid: true,
|
||||
variant: 'primary',
|
||||
toaster: 'b-toaster-bottom-right'
|
||||
});
|
||||
},
|
||||
async serverSelected() {
|
||||
let serverCheck = this.$store.getters.getSelectedServer;
|
||||
if (serverCheck == "none") {
|
||||
log.debug("serverCheck is none");
|
||||
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>
|
||||
<style scoped>
|
||||
.outDirbox{
|
||||
margin-right:10px;
|
||||
}
|
||||
#b-form-group{
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -150,7 +150,6 @@
|
|||
this.serverSelected();
|
||||
this.getFilterSettings();
|
||||
this.getServerSettings();
|
||||
this.getcbDefaults();
|
||||
},
|
||||
computed: {
|
||||
selectedServerAddress: function(){
|
||||
|
|
|
@ -8,6 +8,7 @@ import ExportCustom from '../components/modules/ExportTools/Custom/custom';
|
|||
import PlexTV from '../components/modules/PlexTV/PlexTV';
|
||||
import PMS from '../components/modules/PMS/PMS';
|
||||
import PMSSettings from '../components/modules/PMS/Settings/settings';
|
||||
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/DVR/DVR';
|
||||
|
@ -69,6 +70,12 @@ Vue.use(VueRouter)
|
|||
component: PMSSettings,
|
||||
meta: {requiresAuth: true}
|
||||
},
|
||||
{
|
||||
path: '/pms/butler',
|
||||
name: "butler",
|
||||
component: Butler,
|
||||
meta: {requiresAuth: true}
|
||||
},
|
||||
{
|
||||
path: '/plextv',
|
||||
name: "plextv",
|
||||
|
|
|
@ -20,6 +20,35 @@ const getters = {
|
|||
}
|
||||
|
||||
const actions = {
|
||||
async startButlerTask({ commit }, payload) {
|
||||
|
||||
commit
|
||||
|
||||
let header = wtutils.PMSHeader;
|
||||
header['X-Plex-Token'] = payload.Token;
|
||||
const url = `${payload.Address}/butler/${payload.Job}`;
|
||||
log.debug(`Setting new setting with url ${url}`);
|
||||
await axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
headers: header
|
||||
})
|
||||
.then((response) => {
|
||||
log.debug('Response from startButlerTask recieved')
|
||||
response
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (error.response) {
|
||||
log.error('startButlerTask: ' + error.response.data)
|
||||
alert(error.response.data.errors[0].code + " " + error.response.data.errors[0].message)
|
||||
} else if (error.request) {
|
||||
log.error('startButlerTask: ' + error.request)
|
||||
} else {
|
||||
log.error('startButlerTask: ' + error.message)
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
async setPMSSetting({ commit }, payload) {
|
||||
|
||||
commit
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.7 KiB |
BIN
wiki/modules/exporttools/ET-LevelSelect3.png
Normal file
BIN
wiki/modules/exporttools/ET-LevelSelect3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
wiki/modules/exporttools/ExportSettings10.png
Normal file
BIN
wiki/modules/exporttools/ExportSettings10.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
Before Width: | Height: | Size: 36 KiB |
Loading…
Reference in a new issue