Merge pull request #133 from arabcoders/dev

Minor changes to frontend
This commit is contained in:
Abdulmohsen 2024-11-03 22:26:55 +03:00 committed by GitHub
commit 2515f4edd6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 105 additions and 48 deletions

View file

@ -4,6 +4,8 @@ from datetime import datetime, timezone
import json
import logging
import os
import pathlib
import re
from typing import Any
import yt_dlp
from socketio import AsyncServer
@ -388,3 +390,32 @@ def load_file(file: str, check_type=None) -> tuple[dict | list, bool, str]:
return ({}, False, f"Failed to assert that the contents '{type(opts)}' are of type '{check_type}'.",)
except Exception as e:
return ({}, False, f'{e}',)
def checkId(basePath: str, file: pathlib.Path) -> bool | str:
"""
Check if we are able to get an id from the file name.
if so check if any video file with the same id exists.
:param basePath: Base path to strip.
:param file: File to check.
:return: False if no id found, otherwise the id.
"""
match = re.search(r'(?<=\[)(?:youtube-)?(?P<id>[a-zA-Z0-9\-_]{11})(?=\])', file.stem, re.IGNORECASE)
if not match:
return False
id = match.groupdict().get('id')
for f in file.parent.iterdir():
if id not in f.stem:
continue
if f.suffix not in ('.mp4', '.mkv', '.webm', '.m4v', '.m4a', '.mp3', '.aac', '.ogg',):
continue
return f.absolute()
return False

View file

@ -465,6 +465,8 @@ class Main:
download_path=self.config.download_path,
file=file
)
if isinstance(text, Response):
return text
except Exception as e:
return web.HTTPNotFound(reason=str(e))
@ -519,9 +521,11 @@ class Main:
sd: int = request.query.get('sd')
vc: int = int(request.query.get('vc', 0))
ac: int = int(request.query.get('ac', 0))
file_path: str = os.path.normpath(os.path.join(self.config.download_path, file))
if not file_path.startswith(self.config.download_path):
raise web.HTTPBadRequest(reason='Invalid file path.')
if request.if_modified_since:
file_path = os.path.join(self.config.download_path, file)
if os.path.exists(file_path) and request.if_modified_since.timestamp() == os.path.getmtime(file_path):
return web.Response(status=304)
@ -546,9 +550,7 @@ class Main:
'Access-Control-Allow-Origin': '*',
'Pragma': 'public',
'Cache-Control': f'public, max-age={time.time() + 31536000}',
'Last-Modified': time.strftime('%a, %d %b %Y %H:%M:%S GMT', datetime.fromtimestamp(
os.path.getmtime(os.path.join(self.config.download_path, file))).timetuple()
),
'Last-Modified': time.strftime('%a, %d %b %Y %H:%M:%S GMT', datetime.fromtimestamp(os.path.getmtime(file_path)).timetuple()),
'Expires': time.strftime('%a, %d %b %Y %H:%M:%S GMT', datetime.fromtimestamp(time.time() + 31536000).timetuple()),
}
)
@ -556,12 +558,13 @@ class Main:
@self.routes.get(self.config.url_prefix + 'player/subtitle/{file:.*}.vtt')
async def subtitles(request: Request) -> Response:
file: str = request.match_info.get('file')
file_path: str = os.path.normpath(os.path.join(self.config.download_path, file))
if not file_path.startswith(self.config.download_path):
raise web.HTTPBadRequest(reason='Invalid file path.')
if request.if_modified_since:
file_path = os.path.join(self.config.download_path, file)
lastMod = time.strftime('%a, %d %b %Y %H:%M:%S GMT', datetime.fromtimestamp(
os.path.getmtime(os.path.join(self.config.download_path, file))).timetuple()
)
os.path.getmtime(file_path)).timetuple())
if os.path.exists(file_path) and request.if_modified_since.timestamp() == os.path.getmtime(file_path):
return web.Response(status=304, headers={'Last-Modified': lastMod})
@ -576,9 +579,7 @@ class Main:
'Access-Control-Allow-Origin': '*',
'Pragma': 'public',
'Cache-Control': f'public, max-age={time.time() + 31536000}',
'Last-Modified': time.strftime('%a, %d %b %Y %H:%M:%S GMT', datetime.fromtimestamp(
os.path.getmtime(os.path.join(self.config.download_path, file))).timetuple()
),
'Last-Modified': time.strftime('%a, %d %b %Y %H:%M:%S GMT', datetime.fromtimestamp(os.path.getmtime(file_path)).timetuple()),
'Expires': time.strftime('%a, %d %b %Y %H:%M:%S GMT', datetime.fromtimestamp(time.time() + 31536000).timetuple()),
}
)

View file

@ -2,10 +2,11 @@ import glob
import pathlib
import re
from urllib.parse import quote
from Utils import calcDownloadPath
from Utils import calcDownloadPath, checkId
import pathlib
from .ffprobe import FFProbe
from .Subtitle import Subtitle
from aiohttp.web import Response
class Playlist:
@ -14,11 +15,17 @@ class Playlist:
def __init__(self, url: str):
self.url = url
async def make(self, download_path: str, file: str):
async def make(self, download_path: str, file: str) -> str | Response:
rFile = pathlib.Path(calcDownloadPath(basePath=download_path, folder=file, createPath=False))
if not rFile.exists():
raise Exception(f"File '{rFile}' does not exist.")
possibleFile = checkId(download_path, rFile)
if not possibleFile:
raise Exception(f"File '{rFile}' does not exist.")
return Response(status=302, headers={
'Location': f"{self.url}player/playlist/{quote(str(possibleFile).replace(download_path, '').strip('/'))}.m3u8"
})
try:
ffprobe = FFProbe(rFile)

View file

@ -2239,6 +2239,17 @@
"@types/json-schema": "*"
}
},
"node_modules/@types/eslint-scope": {
"version": "3.7.7",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
"integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/eslint": "*",
"@types/estree": "*"
}
},
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@ -2331,9 +2342,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.8.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz",
"integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==",
"version": "22.8.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz",
"integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2435,9 +2446,9 @@
"license": "MIT"
},
"node_modules/@types/ws": {
"version": "8.5.12",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
"integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==",
"version": "8.5.13",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
"integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -3468,16 +3479,6 @@
"node": ">=0.4.0"
}
},
"node_modules/acorn-import-attributes": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"acorn": "^8"
}
},
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
@ -4164,9 +4165,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001676",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz",
"integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==",
"version": "1.0.30001677",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz",
"integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==",
"dev": true,
"funding": [
{
@ -8174,9 +8175,9 @@
}
},
"node_modules/mini-css-extract-plugin": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.1.tgz",
"integrity": "sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ==",
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz",
"integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -11203,9 +11204,9 @@
"license": "MIT"
},
"node_modules/tslib": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
@ -11675,19 +11676,19 @@
"license": "BSD-2-Clause"
},
"node_modules/webpack": {
"version": "5.95.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz",
"integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==",
"version": "5.96.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
"integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.5",
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
"@webassemblyjs/ast": "^1.12.1",
"@webassemblyjs/wasm-edit": "^1.12.1",
"@webassemblyjs/wasm-parser": "^1.12.1",
"acorn": "^8.7.1",
"acorn-import-attributes": "^1.9.5",
"browserslist": "^4.21.10",
"acorn": "^8.14.0",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.17.1",
"es-module-lexer": "^1.2.1",

View file

@ -16,7 +16,7 @@
<div class="modal-background"></div>
<div class="modal-content">
<VideoPlayer type="default" :link="video_link" :isMuted="false" autoplay="true" :isControls="true"
class="is-fullwidth" @closeModel="video_link = ''" />
:title="video_title" class="is-fullwidth" @closeModel="video_link = ''; video_title = ''" />
</div>
<button class="modal-close is-large" aria-label="close" @click="video_link = ''"></button>
</div>
@ -53,6 +53,7 @@ const socket = ref()
const downloading = reactive({})
const completed = reactive({})
const video_link = ref('')
const video_title = ref('')
const addForm = useStorage('addForm', true)
const showTasks = useStorage('showTasks', false)
const cli_output = ref([])
@ -231,7 +232,10 @@ const addItem = (item) => {
});
};
const playItem = item => video_link.value = makeDownload(config, item, 'm3u8');
const playItem = item => {
video_link.value = makeDownload(config, item, 'm3u8');
video_title.value = item.title;
}
const reloadWindow = () => window.location.reload();

View file

@ -77,7 +77,13 @@ onUnmounted(() => {
if (hls) {
hls.destroy()
}
window.removeEventListener('keydown', eventFunc)
if (props.title) {
window.document.title = 'YTPTube'
}
})
const prepareVideoPlayer = () => {
@ -97,6 +103,7 @@ const prepareVideoPlayer = () => {
enabled: true,
key: 'plyr'
},
title: props.title,
mediaMetadata: {
title: props.title
},
@ -118,5 +125,11 @@ const prepareVideoPlayer = () => {
if (video.value) {
hls.attachMedia(video.value)
}
if (props.title) {
window.document.title = `YTPTube - Playing: ${props.title}`
}
}
</script>

View file

@ -41,7 +41,7 @@ app.config.globalProperties.makeDownload = (config, item, base = 'download') =>
let baseDir = 'download' === base ? `${base}/` : 'player/playlist/';
if (item.folder) {
item.folder = item.folder.replace('#', '%23');
item.folder = item.folder.replace(/#/g, '%23');
baseDir += item.folder + '/';
}