Merge pull request #107 from arabcoders/dev

Added option to archive failing download from WebUI
This commit is contained in:
Abdulmohsen 2024-07-11 14:58:49 +03:00 committed by GitHub
commit 7d34eeb3a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 24 deletions

View file

@ -9,7 +9,7 @@ import selectors
import time
from Config import Config
from DownloadQueue import DownloadQueue
from Utils import ObjectSerializer, Notifier, load_file
from Utils import ObjectSerializer, Notifier, isDownloaded, load_file
from aiohttp import web, client
from aiohttp.web import Request, Response
from Webhooks import Webhooks
@ -550,6 +550,25 @@ class Main:
})
await self.sio.emit('cli_close', {'exitcode': -1})
@self.sio.event()
async def archive_item(sid, data):
if not isinstance(data, dict) or 'url' not in data or not self.config.keep_archive:
return
file: str = self.config.ytdl_options.get('download_archive', None)
if not file:
return
exists, idDict = isDownloaded(file, data['url'])
if exists or 'archive_id' not in idDict or idDict['archive_id'] is None:
return
with open(file, 'a') as f:
f.write(f"{idDict['archive_id']}\n")
LOG.info(f'Archiving item: {data["url"]=}')
@self.sio.event()
async def connect(sid, environ):
await self.connect(sid, environ)

View file

@ -9,7 +9,7 @@
<pageTasks v-if="showTasks" :tasks="config.tasks" />
<DownloadingList :config="config" :queue="downloading" @deleteItem="deleteItem" />
<PageCompleted :config="config" :completed="completed" @deleteItem="deleteItem" @addItem="addItem"
@playItem="playItem" />
@playItem="playItem" @archiveItem="archiveItem" />
</template>
<div class="modal is-active" v-if="video_link">
@ -64,6 +64,18 @@ const runCommand = (args) => {
socket.value.emit('cli_post', args);
}
const sendData = (type, data, stringify = false) => {
if (!socket.value) {
return;
}
if (true === Boolean(stringify)) {
data = JSON.stringify(data);
}
socket.value.emit(type, data);
}
onMounted(() => {
socket.value = io(process.env.VUE_APP_BASE_URL, {
path: document.location.pathname + 'socket.io',
@ -141,12 +153,17 @@ onMounted(() => {
});
socket.value.on('cli_close', () => cli_isLoading.value = false);
socket.value.on('cli_output', stream => {
cli_output.value.push(stream)
console.log(stream);
});
socket.value.on('cli_output', s => cli_output.value.push(s));
});
const archiveItem = (type, item) => {
if (!confirm(`Archive '${item.title ?? item.id ?? item.url ?? '??'}'?`)){
return
}
sendData('archive_item', item);
deleteItem(type, item._id);
}
const deleteItem = (type, item) => {
const items = []
@ -234,5 +251,4 @@ bus.on((event, data) => {
setTimeout(() => bus.emit('task_edit', data), 500);
}
});
</script>

View file

@ -77,15 +77,22 @@
<div class="columns is-multiline">
<LazyLoader :unrender="true" :min-height="210" class="column is-6" v-for="item in sortCompleted" :key="item._id">
<div class="card" :class="{ 'is-bordered-danger': item.status === 'error', 'is-bordered-info': item.live_in || item.is_live }">
<header class="card-header has-tooltip" v-tooltip="item.title">
<div class="card-header-title has-text-centered is-text-overflow is-block">
<div class="card"
:class="{ 'is-bordered-danger': item.status === 'error', 'is-bordered-info': item.live_in || item.is_live }">
<header class="card-header has-tooltip">
<div class="card-header-title is-text-overflow is-block" v-tooltip="item.title">
<a v-if="item.filename" referrerpolicy="no-referrer" :href="makeDownload(config, item, 'm3u8')"
@click.prevent="$emit('playItem', item)">
{{ item.title }}
</a>
<span v-else>{{ item.title }}</span>
</div>
<div class="card-header-icon" v-if="item.filename">
<a :href="makeDownload(config, item)" :download="item.filename?.split('/').reverse()[0]" class="has-text-primary"
v-tooltip="'Download item.'">
<span class="icon"><font-awesome-icon icon="fa-solid fa-download" /></span>
</a>
</div>
</header>
<div class="card-content">
<div class="columns is-mobile is-multiline">
@ -154,17 +161,6 @@
</span>
</a>
</div>
<div class="column is-half-mobile" v-if="item.filename">
<a class="button is-fullwidth is-primary" :href="makeDownload(config, item)"
:download="item.filename?.split('/').reverse()[0]">
<span class="icon-text is-block">
<span class="icon">
<font-awesome-icon icon="fa-solid fa-download" />
</span>
<span>Download</span>
</span>
</a>
</div>
<div class="column is-half-mobile">
<a class="button is-danger is-fullwidth" @click="$emit('deleteItem', 'completed', item._id)">
<span class="icon-text is-block">
@ -175,6 +171,17 @@
</span>
</a>
</div>
<div class="column is-half-mobile" v-if="config.app?.keep_archive && item.status != 'finished'">
<a class="button is-danger is-light is-fullwidth" v-tooltip="'Add link to archive.'"
@click="$emit('archiveItem', 'completed', item)">
<span class="icon-text is-block">
<span class="icon">
<font-awesome-icon icon="fa-solid fa-box-archive" />
</span>
<span>Archive</span>
</span>
</a>
</div>
<div class="column is-half-mobile">
<a referrerpolicy="no-referrer" class="button is-link is-fullwidth" target="_blank" :href="item.url">
<span class="icon-text is-block">
@ -218,7 +225,7 @@ import moment from "moment";
import { useStorage } from '@vueuse/core'
import LazyLoader from './Lazy-Loader'
const emits = defineEmits(['deleteItem', 'addItem', 'playItem']);
const emits = defineEmits(['deleteItem', 'addItem', 'playItem', 'archiveItem']);
const props = defineProps({
completed: {

View file

@ -11,7 +11,8 @@ import {
faBroom,
faServer,
faPowerOff,
faPaperPlane
faPaperPlane,
faBoxArchive
} from '@fortawesome/free-solid-svg-icons'
import { faSquare, faSquareCheck } from '@fortawesome/free-regular-svg-icons'
@ -24,7 +25,7 @@ import 'floating-vue/dist/style.css'
library.add(faCog, faTrash, faLink, faPlus, faTrashCan, faCircleXmark, faCircleCheck, faRotateRight, faDownload,
faUpRightFromSquare, faSquare, faSquareCheck, faSpinner, faArrowUp, faArrowDown, faTasks, faCalendar, faArrowUpAZ,
faArrowDownAZ, faEject, faGlobe, faMoon, faSun, faTerminal, faBroom, faServer, faPowerOff, faBroom, faServer,
faPowerOff, faPaperPlane)
faPowerOff, faPaperPlane, faBoxArchive)
const app = createApp(App);
app.config.globalProperties.capitalize = s => s && s[0].toUpperCase() + s.slice(1);