#507 WIP MaxErrors

This commit is contained in:
Tommy Mikkelsen 2022-11-27 15:18:24 +01:00
parent aea2915524
commit 7a5fbf38c0
7 changed files with 158 additions and 38 deletions

View file

@ -594,8 +594,9 @@
"Description": "Here you can define the settings for @:Modules.Download.Name",
"Return": "Return to @:Modules.Download.Name",
"DownloadMaxBandWidth": "Maximum bandwidth to use",
"ttDownloadMaxBandWidth": "Here you select the maximum bandwith to use when downloading. Don't use maximum, unless you want to lose your friend. Also note, that maximum bandwidth can not exceed what the server owner has set"
"DownloadMaxErrors": "Maximum errors allowed",
"ttDownloadMaxBandWidth": "Here you select the maximum bandwith to use when downloading. Don't use maximum, unless you want to lose your friend. Also note, that maximum bandwidth can not exceed what the server owner has set",
"ttDownloadMaxErrors": "Maximum errors allowed before showing a warning"
}
}
}

View file

@ -194,6 +194,7 @@ ipcMain.on('downloadMedia', function (event, data) {
maxrateLimit * 1024 * 1024 , // upload limit,
maxrateLimit * 1024 * 1024 // download limit
],
timeout: 2,
onDownloadProgress: progressEvent => {
const downloadData = {};
downloadData['Downloaded'] = progressEvent.loaded;
@ -219,8 +220,11 @@ ipcMain.on('downloadMedia', function (event, data) {
})
}).catch((error) => {
log.error(`[background.js] (downloadFile) - ${error}`);
event.sender.send('downloadMediaError', error.message);
console.log('Ged 88-3', error.code)
console.log('Ged 88-3-1', error.message)
console.log('Ged 88-3-2', error.stack)
targetStream.end();
event.sender.send('downloadMediaError', error);
})
})

View file

@ -60,6 +60,7 @@
:data="tableData"
:bordered="tableAttribute.bordered"
:minWidth="tableAttribute.minWidth"
:height="tableAttribute.height"
:language="tableAttribute.language">
</vue-virtual-table>
<b-modal size="lg" ref="MediaInfo" hide-footer v-bind:title=this.mediaInfoTitle>
@ -130,14 +131,14 @@
{ prop: 'mediaKey', isHidden: true },
{ prop: 'Key', isHidden: true },
{ prop: 'Title',searchable: true,sortable: true, width: 80 },
{ prop: 'Released',searchable: true,sortable: true, width: 30 },
{ prop: 'Added',searchable: true,sortable: true, width: 30 },
{ prop: 'Updated',searchable: true,sortable: true, width: 30 },
{ prop: 'Released',searchable: false,sortable: true, width: 30 },
{ prop: 'Added',searchable: false,sortable: true, width: 30 },
{ prop: 'Updated',searchable: false,sortable: true, width: 30 },
{ prop: 'Type', isHidden: true }
],
tableData: [],
tableAttribute: {
height: 1000,
height: 250,
itemHeight: 42,
minWidth: 10,
selectable: true,
@ -297,7 +298,7 @@
this.isLoading = true;
await this.getMediaInfo(myarg['Key']);
this.selMediaTitle = myarg['Title'];
this.mediaInfoTitle = `${i18n.t("Modules.Download.mediaInfo.mediaInfoTitle")} - ${myarg['Title']}`
this.mediaInfoTitle = `${i18n.t("Modules.Download.mediaInfo.title")} - ${myarg['Title']}`
// Stop Spinner
this.isLoading = false;
this.$refs['MediaInfo'].show();

View file

@ -17,7 +17,7 @@
:selectable="tableAttribute.selectable"
:itemHeight="tableAttribute.itemHeight">
<template slot-scope="scope" slot="actionCommon">
<button @click="up(scope.index, scope.row)" :disabled="queueRunning"><i class="fas fa-arrow-up"></i></button>
<button @click="up(scope.index, scope.row)" :disabled="queueStatus"><i class="fas fa-arrow-up"></i></button>
<button @click="down(scope.index, scope.row)" :disabled="queueRunning"><i class="fas fa-arrow-down"></i></button>
<button @click="del(scope.index, scope.row)" :disabled="queueRunning"><i class="fas fa-trash"></i></button>
<button @click="info(scope.index, scope.row)"><i class="fas fa-info"></i></button>
@ -40,7 +40,9 @@
{{ this.btnQueueLabel }}</b-button>
</div>
</div>
{{ this.queueRunning }}
<!--{{ download.queueRunning }} -->
QueueStatus local: {{ queueRunning }}
QueueStatus store: {{ queueStatus }}
<br>
<statusDiv /> <!-- Status Div -->
</b-container>
@ -66,9 +68,9 @@
tableConfig: [
{ prop: '_action', name: 'Action', actionName: 'actionCommon', width: 80 },
{ prop: 'title', name: i18n.t('Modules.Download.mediaInfo.title'), searchable: true,sortable: true, width: 80 },
{ prop: 'file', name: i18n.t('Modules.Download.mediaInfo.file'), searchable: true,sortable: true, width: 80 },
{ prop: 'type', name: i18n.t('Modules.Download.mediaInfo.type'), searchable: true,sortable: true, width: 30 },
{ prop: 'status', name: i18n.t('Modules.Download.mediaInfo.status'), searchable: true,sortable: true, width: 30 },
{ prop: 'file', name: i18n.t('Modules.Download.mediaInfo.file'), searchable: false,sortable: true, width: 80 },
{ prop: 'type', name: i18n.t('Modules.Download.mediaInfo.type'), searchable: false,sortable: true, width: 30 },
{ prop: 'status', name: i18n.t('Modules.Download.mediaInfo.status'), searchable: false,sortable: true, width: 30 },
{ prop: 'hash', isHidden: true },
{ prop: 'key', isHidden: true },
{ prop: 'serverID', isHidden: true },
@ -100,17 +102,28 @@
created() {
log.info(`[Queue.vue] (created) - Download Queue Created`);
this.GetQueue();
this.setCreatedStatus();
// this.setCreatedStatus();
},
watch: {
WatchQueue: async function(){
this.GetQueue();
},
queueStatus:async function(){
if (this.$store.getters.getQueueStatus){
this.btnQueueLabel = i18n.t('Modules.Download.Queue.btnStopQueue');
} else {
this.btnQueueLabel = i18n.t('Modules.Download.Queue.btnStartQueue');
}
}
},
computed: {
WatchQueue: function(){
return this.$store.getters.getQueue
},
queueStatus: function(){
return this.$store.getters.getQueueStatus
}
},
methods: {
up( index ){
@ -129,28 +142,39 @@
wtconfig.set('Download.Queue', this.tableData);
}
},
/*
setCreatedStatus(){
this.queueRunning = wtconfig.get( 'Download.Status', false);
},
btnToggleQueue(){
if ( this.queueRunning ){
this.stopQueue();
*/
btnToggleQueue(){
if ( download.queueRunning ){
//this.stopQueue();
download.stopProcess();
this.btnQueueLabel = i18n.t('Modules.Download.Queue.btnStartQueue');
}
else {
this.startQueue();
//this.startQueue();
download.startProcess();
this.btnQueueLabel = i18n.t('Modules.Download.Queue.btnStopQueue');
}
wtconfig.set('Download.Status', this.queueRunning);
//wtconfig.set('Download.Status', this.queueRunning);
},
/*
stopQueue(){
this.queueRunning = false;
download.stopProcess();
},
startQueue(){
this.queueRunning = true;
download.startProcess();
},
*/
info(index, row){
this.mediaInfo.mediaInfoTitle = `${i18n.t("Modules.Download.mediaInfo.title")}: ${row['title']} - ${row['type']}`
this.mediaInfoItems = [];
@ -176,8 +200,6 @@
log.info(`[Queue.vue] (GetQueue) - Get the queue`);
this.tableData = wtconfig.get('Download.Queue');
}
}
}

View file

@ -20,6 +20,18 @@
</b-form-select>
<WTNGtt tt="Modules.Download.Settings.ttDownloadMaxBandWidth" size="20px"></WTNGtt>
</b-form-group>
<b-form-group id="grpDownloadMaxErrors" v-bind:label="$t('Modules.Download.Settings.DownloadMaxErrors')" label-size="lg" label-class="font-weight-bold pt-0">
<b-form-select
class="form-control"
v-model="DownloadMaxErrors"
id="DownloadMaxErrors"
:options="DownloadMaxErrorsOptions"
@change="DownloadMaxErrorsChanged"
style="width: 50%"
name="DownloadMaxErrors">
</b-form-select>
<WTNGtt tt="Modules.Download.Settings.ttDownloadMaxErrors" size="20px"></WTNGtt>
</b-form-group>
<br>
<br>
<!-- Buttons -->
@ -63,6 +75,15 @@
{text: '5Mb/s', value: 5},
{text: '3Mb/s', value: 3},
{text: '1Mb/s', value: 1}
],
DownloadMaxErrors: '',
DownloadMaxErrorsOptions: [
{text: '15', value: 15},
{text: '10', value: 10},
{text: '7', value: 7},
{text: '5', value: 5},
{text: '3', value: 3},
{text: '1', value: 1}
]
};
},
@ -74,8 +95,12 @@
DownloadMaxBandWidthChanged(){
wtconfig.set("Download.DownloadMaxBandWidth", this.DownloadMaxBandWidth);
},
DownloadMaxErrorsChanged(){
wtconfig.set("Download.DownloadMaxErrors", this.DownloadMaxErrors);
},
getDefaults(){
this.DownloadMaxBandWidth = wtconfig.get("Download.DownloadMaxBandWidth", 7);
this.DownloadMaxErrors = wtconfig.get("Download.DownloadMaxErrors", 5);
}
}
};

View file

@ -25,6 +25,9 @@ const download = new class DOWNLOAD {
this.controller = null;
this.queueRunning = false;
this.lastError = null;
this.downloadError = false;
this.queueCount = 0;
this.lastErrMsg = ""
}
async createOutDir(){ // Force create OutDir
@ -48,7 +51,7 @@ const download = new class DOWNLOAD {
this.accessToken = allPMSSrv[idx]['accessToken'];
}
getFirstEntry(){ // Get first entry in the queue
GEDgetFirstEntry(){ // Get first entry in the queue
this.item = this.queue[0];
}
@ -57,21 +60,23 @@ const download = new class DOWNLOAD {
wtconfig.set('Download.Queue', this.queue);
}
getNextEntry(){ // Get first entry in the queue
this.item = this.queue[this.queueCount];
}
formatBytes(bytes, decimals = 2) {
if (!+bytes) return '0 Bytes'
const k = 1024
const dm = decimals < 0 ? 0 : decimals
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
if (!+bytes) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}
async downloadItem(){ // Download the actual item
log.info(`[Download.js] (downloadItem) Started download of file: ${this.item.targetFile}`);
let header = wtutils.PMSHeader;
this.downloadError = false;
// Add Auth Token
header['X-Plex-Token'] = this.accessToken;
// Start by checking, if media is already partially downloaded
@ -127,7 +132,7 @@ const download = new class DOWNLOAD {
{
log.info(`[Download.js] (downloadItem) - Download finished for ${this.item.targetFile} ok`);
ipcRenderer.removeAllListeners('downloadMediaEnd');
//ipcRenderer.removeAllListeners('downloadError');
ipcRenderer.removeAllListeners('downloadMediaError');
ipcRenderer.removeAllListeners('downloadMediaProgress');
// Rename to real file name
const newFile = this.item.targetFile.replace('.tmp', '')
@ -141,6 +146,26 @@ const download = new class DOWNLOAD {
log.error(`[Download.js] (downloadItem) - downloading "${this.item.title}" caused an exception as: ${error}`);
}
})
ipcRenderer.on('downloadMediaError', (event, data) => {
console.log('Ged 13 HELLO')
this.downloadError = true;
try
{
log.error(`[Download.js] (downloadItem) - Download had an error for ${this.item.targetFile}`);
console.log('Ged 99-3', JSON.stringify(data))
this.lastErrMsg = JSON.stringify(data);
//log.error(`[Download.js] (downloadItem) - Error code ${this.item.targetFile}`);
ipcRenderer.removeAllListeners('downloadMediaEnd');
ipcRenderer.removeAllListeners('downloadMediaError');
ipcRenderer.removeAllListeners('downloadMediaProgress');
resolve(this.item.targetFile);
}
catch (error)
{
log.error(`[Download.js] (downloadItem) - downloading "${this.item.title}" caused an exception as: ${error}`);
}
})
})
}
@ -149,28 +174,65 @@ const download = new class DOWNLOAD {
status.clearStatus();
status.updateStatusMsg( status.RevMsgType.Status, i18n.t('Common.Status.Msg.Idle'));
this.queueRunning = true;
store.commit("UPDATE_QueueStatus", false);
ipcRenderer.send('downloadMediaAbort');
}
async startProcess(){ // Start download Queue
log.info(`[Download.js] (startProcess) - Starting the download Queue`);
store.commit("UPDATE_QueueStatus", true);
status.updateStatusMsg( status.RevMsgType.Status, i18n.t('Common.Status.Msg.Processing'));
this.queueRunning = true;
this.queueCount = 0;
this.queue = wtconfig.get('Download.Queue');
this.getFirstEntry();
this.getNextEntry();
console.log('Ged 77-3', JSON.stringify(this.item), this.queueRunning)
while (this.item && this.queueRunning){
this.getFirstEntry();
await this.getSrvInfo();
await this.createOutDir();
await this.downloadItem();
console.log('Ged 15', this.downloadError, JSON.stringify(this.item))
if (!this.lastError){ // Remove from queue if no error
if (!this.downloadError){ // Remove from queue if no error
this.removeFirstEntry();
// Update timestamp for the queue
store.commit("UPDATE_Queue");
} else {
// We had an error
console.log('Ged 13-3 We had an error')
let idx = 0;
for (let item of this.queue) {
if (item.hash === this.item.hash) {
console.log('Ged 13-4 found item as', JSON.stringify(item), idx)
if (item.error) {
let error = {};
error = this.queue[idx]["error"];
error[Object.keys(error).length + 1] = this.lastErrMsg;
this.queue[idx]["error"] = error;
wtconfig.set("Download.Queue", this.queue);
} else {
let error = {};
error[1] = this.lastErrMsg;
this.queue[idx]["error"] = error;
wtconfig.set("Download.Queue", this.queue);
}
break;
}
idx += 1;
}
//let errCount = wtconfig.get("Download.")
}
this.queueCount += 1;
this.getNextEntry();
}
console.log('Ged 99-5 all done')
this.queueRunning = false;
store.commit("UPDATE_QueueStatus", false);
log.info(`[Download.js] (startProcess) - Download completed`);
status.clearStatus();
status.updateStatusMsg(status.RevMsgType.Status, i18n.t('Common.Status.Msg.Idle'))
}
}

View file

@ -4,18 +4,23 @@ console.log = log.log;
import { wtconfig } from '../../components/modules/General/wtutils';
const state = {
queue:{}
queue:{},
queueStatus: false
};
const mutations = {
UPDATE_Queue(state) {
state.queue = wtconfig.get('Download.Queue');
},
UPDATE_QueueStatus(state, payload) {
state.queueStatus = payload;
}
};
const getters = {
getQueue: state => state.queue
getQueue: state => state.queue,
getQueueStatus: state => state.queueStatus
};
const downloadQueue = {