Small bug fixes and added time to objects.

This commit is contained in:
ArabCoders 2023-11-25 00:23:29 +03:00
parent 10a31b5ee8
commit b7bf9627a1
13 changed files with 82 additions and 26 deletions

3
.vscode/launch.json vendored
View file

@ -33,8 +33,7 @@
"YTP_DOWNLOAD_PATH": "${workspaceFolder}/var/downloads",
"YTP_TEMP_PATH": "${workspaceFolder}/var/tmp",
"YTP_YTDL_OPTIONS_FILE": "${workspaceFolder}/var/config/ytdlp.json",
"YTP_URL_HOST": "http://localhost:8081",
"YTP_KEEP_ARCHIVE": "true",
"YTP_URL_HOST": "http://localhost:8081"
}
}
]

View file

@ -23,6 +23,7 @@ class Config:
ytdl_options: dict | str = {}
ytdl_options_file: str = ''
ytdl_debug: bool = False
host: str = '0.0.0.0'
port: int = 8081
@ -31,7 +32,7 @@ class Config:
base_path: str = ''
_boolean_vars: tuple = ('keep_archive')
_boolean_vars: tuple = ('keep_archive', 'ytdl_debug')
def __init__(self):
baseDefualtPath: str = os.path.dirname(os.path.dirname(__file__))

View file

@ -19,7 +19,7 @@ class ItemDTO:
ytdlp_cookies: str = None
ytdlp_config: dict = field(default_factory=dict)
output_template: str = None
timestamp: int = time.time_ns()
timestamp: float = time.time_ns()
is_live: bool = None
# yt-dlp injected fields.

View file

@ -50,7 +50,7 @@ class DataStore:
with sqlite3.connect(self.db_file) as db:
db.row_factory = sqlite3.Row
cursor = db.execute(
'SELECT "id", "data" FROM "history" WHERE "type" = ? ORDER BY "created_at" ASC',
f'SELECT "id", "data" FROM "history" WHERE "type" = ? ORDER BY "created_at" ASC',
(self.type,)
)

View file

@ -22,6 +22,7 @@ class Download:
ytdl_opts: dict = None
info: ItemDTO = None
default_ytdl_opts: dict = None
debug: bool = False
_ytdlp_fields: tuple = (
'tmpfilename',
@ -41,16 +42,19 @@ class Download:
download_dir: str,
temp_dir: str,
output_template_chapter: str,
default_ytdl_opts: dict
default_ytdl_opts: dict,
debug: bool = False
):
self.download_dir = download_dir
self.temp_dir = temp_dir
self.output_template_chapter = output_template_chapter
self.output_template = info.output_template
self.format = get_format(info.format, info.quality)
self.ytdl_opts = get_opts(info.format, info.quality, info.ytdlp_config if info.ytdlp_config else {})
self.ytdl_opts = get_opts(
info.format, info.quality, info.ytdlp_config if info.ytdlp_config else {})
self.info = info
self.default_ytdl_opts = default_ytdl_opts
self.debug = debug
self.canceled = False
self.tmpfilename = None
@ -82,7 +86,6 @@ class Download:
)
params: dict = {
'quiet': True,
'no_color': True,
'format': self.format,
'paths': {
@ -99,6 +102,12 @@ class Download:
**mergeConfig(self.default_ytdl_opts, self.ytdl_opts),
}
if self.debug:
params['verbose'] = True
params['logger'] = logging.getLogger('YTPTube-ytdl')
else:
params['quiet'] = True
if self.info.ytdlp_cookies:
try:
data = jsonCookie(json.loads(self.info.ytdlp_cookies))
@ -113,6 +122,8 @@ class Download:
logging.error(
f'Invalid cookies: was provided for {self.info.title} - {str(e)}')
logging.debug(
f'Downloading {self.info._id} {self.info.title}... {params}')
ret = yt_dlp.YoutubeDL(params=params).download([self.info.url])
self.status_queue.put(

View file

@ -8,7 +8,7 @@ from src.Notifier import Notifier
from src.Download import Download
from src.DTO.ItemDTO import ItemDTO
from src.DataStore import DataStore
from src.Utils import ObjectSerializer, calcDownloadPath, ExtractInfo
from src.Utils import ObjectSerializer, calcDownloadPath, ExtractInfo, mergeConfig
from datetime import datetime, timezone
log = logging.getLogger('DownloadQueue')
@ -129,6 +129,7 @@ class DownloadQueue:
temp_dir=self.config.temp_path,
output_template_chapter=output_chapter,
default_ytdl_opts=self.config.ytdl_options,
debug=bool(self.config.ytdl_debug)
)
)
@ -163,6 +164,8 @@ class DownloadQueue:
output_template: str = '',
already=None
):
ytdlp_config = ytdlp_config if ytdlp_config else {}
log.info(
f'adding {url}: {quality=} {format=} {folder=} {output_template=} {ytdlp_cookies=} {ytdlp_config=}')
@ -173,7 +176,19 @@ class DownloadQueue:
else:
already.add(url)
try:
entry = await asyncio.get_running_loop().run_in_executor(None, ExtractInfo, self.config.ytdl_options, url)
entry = await asyncio.get_running_loop().run_in_executor(
None,
ExtractInfo,
mergeConfig(self.config.ytdl_options, ytdlp_config),
url,
bool(self.config.ytdl_debug)
)
if not entry:
return {
'status': 'error',
'msg': 'No metadata, most likely video has been downloaded before.' if self.config.keep_archive else 'Unable to extract info check logs.'
}
logging.debug(f'entry: extract info says: {entry}')
except yt_dlp.utils.YoutubeDLError as exc:
return {'status': 'error', 'msg': str(exc)}

View file

@ -165,9 +165,8 @@ def calcDownloadPath(basePath: str, folder: str = None) -> str:
return download_path
def ExtractInfo(config: dict, url: str) -> dict:
def ExtractInfo(config: dict, url: str, debug: bool = False) -> dict:
params: dict = {
'quiet': True,
'no_color': True,
'extract_flat': True,
'skip_download': True,
@ -176,6 +175,12 @@ def ExtractInfo(config: dict, url: str) -> dict:
**config,
}
if debug:
params['verbose'] = True
params['logger'] = logging.getLogger('YTPTube-ytdl')
else:
params['quiet'] = True
return yt_dlp.YoutubeDL(params=params).extract_info(url, download=False)

View file

@ -1,16 +1,17 @@
{
"name": "frontend",
"name": "YTPTube",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "frontend",
"name": "YTPTube",
"version": "0.1.0",
"dependencies": {
"@vueuse/core": "^10.6.1",
"bulma": "^0.9.4",
"core-js": "^3.8.3",
"moment": "^2.29.4",
"socket.io-client": "^4.7.2",
"vue": "^3.2.13",
"vue-toastification": "^2.0.0-rc.5"
@ -8021,6 +8022,14 @@
"integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
"dev": true
},
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": {
"node": "*"
}
},
"node_modules/mrmime": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",

View file

@ -12,6 +12,7 @@
"@vueuse/core": "^10.6.1",
"bulma": "^0.9.4",
"core-js": "^3.8.3",
"moment": "^2.29.4",
"socket.io-client": "^4.7.2",
"vue": "^3.2.13",
"vue-toastification": "^2.0.0-rc.5"

View file

@ -156,12 +156,13 @@ const selectedQuality = useStorage('selectedQuality', '')
const ytdlpConfig = useStorage('ytdlp_config', '')
const ytdlpCookies = useStorage('ytdlp_cookies', '')
const output_template = useStorage('output_template', null)
const qualities = ref([])
const url = ref('')
const downloadPath = ref('')
const addInProgress = ref(false)
const downloadPath = useStorage('downloadPath', null)
const url = useStorage('downloadUrl', null)
const showAdvanced = useStorage('show_advanced', false)
const qualities = ref([])
const addInProgress = ref(false)
const updateQualities = () => {
for (const key in downloadFormats) {
const item = downloadFormats[key];
@ -190,7 +191,7 @@ const addDownload = () => {
url: url.value,
format: selectedFormat.value,
quality: selectedQuality.value,
path: downloadPath.value,
folder: downloadPath.value,
ytdlp_config: ytdlpConfig.value,
ytdlp_cookies: ytdlpCookies.value,
output_template: output_template.value,
@ -206,6 +207,8 @@ const resetStorage = () => {
ytdlpConfig.value = '';
ytdlpCookies.value = '';
output_template.value = null;
url.value = '';
downloadPath.value = '';
}
bus.on((event, data) => {

View file

@ -74,7 +74,7 @@
<div class="column is-12" v-if="item.error">
<span class="has-text-danger">{{ item.error }}</span>
</div>
<div class="column is-half has-text-centered">
<div class="column is-4 has-text-centered">
<span class="icon-text">
<span class="icon">
<i v-if="item.status == 'finished'" class="has-text-success fa-solid fa-circle-check"></i>
@ -83,7 +83,12 @@
<span>{{ capitalize(item.status) }}</span>
</span>
</div>
<div class="column is-half has-text-centered">
<div class="column is-4 has-text-centered">
<span :data-tooltip="moment(item.timestamp / 1000000).format('MMMM Do YYYY, h:mm:ss a')">
{{ moment(item.timestamp / 1000000).fromNow() }}
</span>
</div>
<div class="column is-4 has-text-centered">
<label class="checkbox is-block">
<input class="completed-checkbox" type="checkbox" v-model="selectedElms" :id="'checkbox-' + item._id"
:value="item._id">
@ -159,6 +164,7 @@
<script setup>
import { defineProps, computed, ref, watch, defineEmits } from 'vue';
import moment from "moment";
const emits = defineEmits(['deleteItem', 'addItem']);
@ -287,7 +293,7 @@ const reQueueItem = (id, item) => {
url: item.url,
format: item.format,
quality: item.quality,
path: item.folder,
folder: item.folder,
ytdlp_config: item.ytdlp_config,
ytdlp_cookies: item.ytdlp_cookies,
output_template: item.output_template,

View file

@ -43,7 +43,7 @@
:value="item.percent ? percentPipe(item.percent) : ''" max="100">
</progress>
</div>
<div class="column is-half has-text-centered">
<div class="column is-4 has-text-centered">
<span class="icon-text">
<span class="icon">
<i v-if="item.status == 'finished'" class="has-text-success fa-solid fa-circle-check"></i>
@ -52,7 +52,12 @@
<span>{{ capitalize(item.status) }}</span>
</span>
</div>
<div class="column is-half has-text-centered">
<div class="column is-4 has-text-centered">
<span :data-tooltip="moment(item.timestamp / 1000000).format('MMMM Do YYYY, h:mm:ss a')">
{{ moment(item.timestamp / 1000000).fromNow() }}
</span>
</div>
<div class="column is-4 has-text-centered">
<label class="checkbox is-block">
<input class="completed-checkbox" type="checkbox" v-model="selectedElms" :value="item._id">
Select
@ -61,8 +66,7 @@
</div>
<div class="columns">
<div class="column">
<a class="button is-danger is-fullwidth"
@click="$emit('deleteItem', 'queue', item._id)">
<a class="button is-danger is-fullwidth" @click="$emit('deleteItem', 'queue', item._id)">
<span class="icon-text">
<span class="icon">
<i class="fa-solid fa-trash-can"></i>
@ -107,6 +111,7 @@
<script setup>
import { defineProps, defineEmits, ref, watch, computed } from 'vue';
import moment from "moment";
defineEmits(['deleteItem']);

View file

@ -21,6 +21,7 @@ app.config.globalProperties.makeDownload = (config, item) => {
app.use(Toast, {
transition: "Vue-Toastification__bounce",
position: "bottom-right",
maxToasts: 5,
newestOnTop: true
});