Merge pull request #51 from arabcoders/dev

Restructured the python code.
This commit is contained in:
Abdulmohsen 2023-12-31 23:06:16 +03:00 committed by GitHub
commit 65e9f316c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 76 additions and 76 deletions

View file

@ -4,6 +4,7 @@ import os
import re
import sys
import coloredlogs
from version import APP_VERSION
class Config:
@ -33,7 +34,10 @@ class Config:
logging_level: str = 'info'
_boolean_vars: tuple = ('keep_archive', 'ytdl_debug')
version: str = APP_VERSION
_boolean_vars: tuple = ('keep_archive', 'ytdl_debug',)
_immutable: tuple = ('version',)
def __init__(self):
baseDefualtPath: str = os.path.dirname(os.path.dirname(__file__))
@ -46,6 +50,11 @@ class Config:
if k.startswith('_'):
continue
# If the variable is not updateable, set it to the default value.
if k in self._immutable:
setattr(self, k, v)
continue
lookUpKey: str = f'YTP_{k}'.upper()
setattr(
self, k,
@ -53,7 +62,7 @@ class Config:
)
for k, v in self.__dict__.items():
if k.startswith('_'):
if k.startswith('_') or k in self._immutable:
continue
if isinstance(v, str) and '{' in v and '}' in v:

View file

@ -4,10 +4,10 @@ from datetime import datetime, timezone
from email.utils import formatdate
import json
import sqlite3
from src.Utils import calcDownloadPath
from src.Config import Config
from src.Download import Download
from src.DTO.ItemDTO import ItemDTO
from Utils import calcDownloadPath
from Config import Config
from Download import Download
from ItemDTO import ItemDTO
class DataStore:

View file

@ -7,9 +7,8 @@ import os
import re
import shutil
import yt_dlp
from src.Utils import get_format, get_opts, jsonCookie, mergeConfig
from src.DTO.ItemDTO import ItemDTO
from src.Notifier import Notifier
from Utils import Notifier, get_format, get_opts, jsonCookie, mergeConfig
from ItemDTO import ItemDTO
log = logging.getLogger('download')

View file

@ -5,12 +5,11 @@ import os
import time
import yt_dlp
from sqlite3 import Connection
from src.Config import Config
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, mergeConfig
from Config import Config
from Download import Download
from ItemDTO import ItemDTO
from DataStore import DataStore
from Utils import Notifier, ObjectSerializer, calcDownloadPath, ExtractInfo, mergeConfig
from datetime import datetime, timezone
log = logging.getLogger('DownloadQueue')

View file

@ -5,6 +5,7 @@ import logging
import os
from typing import Any
import yt_dlp
from socketio import AsyncServer
log = logging.getLogger('Utils')
@ -274,3 +275,31 @@ class ObjectSerializer(json.JSONEncoder):
def default(self, obj):
return obj.__dict__ if isinstance(obj, object) else json.JSONEncoder.default(self, obj)
class Notifier:
'''
This class is used to send events to the frontend.
'''
def __init__(self, sio: AsyncServer, serializer: ObjectSerializer):
self.sio = sio
self.serializer = serializer
async def added(self, dl):
await self.emit('added', dl)
async def updated(self, dl):
await self.emit('updated', dl)
async def completed(self, dl):
await self.emit('completed', dl)
async def canceled(self, id):
await self.emit('canceled', id)
async def cleared(self, id):
await self.emit('cleared', id)
async def emit(self, event: str, data):
await self.sio.emit(event, self.serializer.encode(data))

View file

@ -5,24 +5,19 @@ from datetime import datetime
import json
import os
import random
from src.Config import Config
from version import APP_VERSION
from src.Notifier import Notifier
from src.DownloadQueue import DownloadQueue
from src.Utils import ObjectSerializer
from Config import Config
from DownloadQueue import DownloadQueue
from Utils import ObjectSerializer, Notifier
from aiohttp import web
from aiohttp.web import Request, Response
from src.M3u8 import M3u8
from src.Segments import Segments
from player.M3u8 import M3u8
from player.Segments import Segments
import socketio
import logging
import caribou
import sqlite3
from aiocron import crontab
log: logging.Logger = None
class Main:
config: Config = None
serializer: ObjectSerializer = None
@ -36,7 +31,6 @@ class Main:
def __init__(self):
self.config = Config()
self.config.version = APP_VERSION
self.logger = logging.getLogger('main')
try:
@ -113,6 +107,7 @@ class Main:
)
async def connect(self, sid, _):
self.logger.info(f'Config [{self.config.__dict__}].')
data: dict = {
**self.dqueue.get(),
"config": self.config,
@ -285,7 +280,10 @@ class Main:
raise web.HTTPBadRequest(reason='file is required')
return web.Response(
text=M3u8(self.config).make_stream(file),
text=M3u8(url=f"{self.config.url_host}{self.config.url_prefix}").make_stream(
download_path=self.config.download_path,
file=file
),
headers={
'Content-Type': 'application/x-mpegURL',
'Cache-Control': 'no-cache',
@ -308,7 +306,6 @@ class Main:
raise web.HTTPBadRequest(reason='segment is required')
segmenter = Segments(
config=self.config,
segment_index=int(segment),
segment_duration=float('{:.6f}'.format(
float(sd if sd else M3u8.segment_duration))),
@ -317,7 +314,7 @@ class Main:
)
return web.Response(
body=await segmenter.stream(file),
body=await segmenter.stream(download_path=self.config.download_path, file=file),
headers={
'Content-Type': 'video/mpegts',
'Connection': 'keep-alive',

View file

@ -1,9 +1,8 @@
import math
import os
from urllib.parse import quote
from src.Utils import calcDownloadPath
from src.ffprobe import FFProbe
from src.Config import Config
from Utils import calcDownloadPath
from .ffprobe import FFProbe
class M3u8:
@ -11,17 +10,15 @@ class M3u8:
ok_acodecs: tuple = ('aac', 'mp3',)
segment_duration: float = 10.000000
config: Config = None
download_path: str = None
url: str = None
def __init__(self, config: Config, segment_duration: float = 6.000000):
self.config = config
self.download_path = self.config.download_path
def __init__(self, url: str, segment_duration: float = 6.000000):
self.url = url
self.segment_duration = float(segment_duration)
def make_stream(self, file: str):
def make_stream(self, download_path: str, file: str):
realFile: str = calcDownloadPath(
basePath=self.download_path,
basePath=download_path,
folder=file,
createPath=False
)
@ -68,7 +65,7 @@ class M3u8:
else:
m3u8 += f"#EXTINF:{segmentSize}, nodesc\n"
m3u8 += f"{self.config.url_host}{self.config.url_prefix}segments/{i}/{quote(file)}"
m3u8 += f"{self.url}segments/{i}/{quote(file)}"
if len(segmentParams) > 0:
m3u8 += '?'+'&'.join([f"{key}={value}" for key,
value in segmentParams.items()])

View file

@ -3,30 +3,27 @@ import logging
import os
import subprocess
import tempfile
from src.Utils import calcDownloadPath
from src.Config import Config
from Utils import calcDownloadPath
from Config import Config
log = logging.getLogger('segments')
class Segments:
config: Config = None
download_path: str = None
segment_duration: int
segment_index: int
vconvert: bool
aconvert: bool
def __init__(self, config: Config, segment_index: int, segment_duration: float, vconvert: bool, aconvert: bool):
self.config = config
self.download_path = self.config.download_path
def __init__(self, segment_index: int, segment_duration: float, vconvert: bool, aconvert: bool):
self.segment_duration = float(segment_duration)
self.segment_index = int(segment_index)
self.vconvert = bool(vconvert)
self.aconvert = bool(aconvert)
async def stream(self, file: str) -> bytes:
async def stream(self, download_path: str, file: str) -> bytes:
realFile: str = calcDownloadPath(
basePath=self.download_path,
basePath=download_path,
folder=file,
createPath=False
)

View file

@ -6,7 +6,6 @@ import json
import operator
import os
import pipes
import re
import subprocess

View file

@ -1,26 +0,0 @@
from socketio import AsyncServer
from src.Utils import ObjectSerializer
class Notifier:
def __init__(self, sio: AsyncServer, serializer: ObjectSerializer):
self.sio = sio
self.serializer = serializer
async def added(self, dl):
await self.emit('added', dl)
async def updated(self, dl):
await self.emit('updated', dl)
async def completed(self, dl):
await self.emit('completed', dl)
async def canceled(self, id):
await self.emit('canceled', id)
async def cleared(self, id):
await self.emit('cleared', id)
async def emit(self, event: str, data):
await self.sio.emit(event, self.serializer.encode(data))