Merge pull request #51 from arabcoders/dev
Restructured the python code.
This commit is contained in:
commit
65e9f316c4
11 changed files with 76 additions and 76 deletions
|
|
@ -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:
|
||||
|
|
@ -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:
|
||||
|
|
@ -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')
|
||||
|
||||
|
|
@ -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')
|
||||
|
|
@ -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))
|
||||
25
app/main.py
25
app/main.py
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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()])
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -6,7 +6,6 @@ import json
|
|||
import operator
|
||||
import os
|
||||
import pipes
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
|
|
@ -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))
|
||||
Loading…
Reference in a new issue