mirror of
https://github.com/chibicitiberiu/ytsm.git
synced 2024-02-24 05:43:31 +00:00
Merged changes from master
This commit is contained in:
41
app/YtManagerApp/management/appconfig.py
Normal file
41
app/YtManagerApp/management/appconfig.py
Normal file
@ -0,0 +1,41 @@
|
||||
from dynamic_preferences.registries import global_preferences_registry
|
||||
from YtManagerApp.dynamic_preferences_registry import Initialized, YouTubeAPIKey, AllowRegistrations, SyncSchedule, SchedulerConcurrency
|
||||
|
||||
|
||||
class AppConfig(object):
|
||||
# Properties
|
||||
props = {
|
||||
'initialized': Initialized,
|
||||
'youtube_api_key': YouTubeAPIKey,
|
||||
'allow_registrations': AllowRegistrations,
|
||||
'sync_schedule': SyncSchedule,
|
||||
'concurrency': SchedulerConcurrency
|
||||
}
|
||||
|
||||
# Init
|
||||
def __init__(self, pref_manager):
|
||||
self.__pref_manager = pref_manager
|
||||
|
||||
def __getattr__(self, item):
|
||||
prop_class = AppConfig.props[item]
|
||||
prop_full_name = prop_class.section.name + "__" + prop_class.name
|
||||
return self.__pref_manager[prop_full_name]
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key in AppConfig.props:
|
||||
prop_class = AppConfig.props[key]
|
||||
prop_full_name = prop_class.section.name + "__" + prop_class.name
|
||||
self.__pref_manager[prop_full_name] = value
|
||||
else:
|
||||
super().__setattr__(key, value)
|
||||
|
||||
def for_sub(self, subscription, pref: str):
|
||||
value = getattr(subscription, pref)
|
||||
if value is None:
|
||||
value = subscription.user.preferences[pref]
|
||||
|
||||
return value
|
||||
|
||||
|
||||
global_prefs = global_preferences_registry.manager()
|
||||
appconfig = AppConfig(global_prefs)
|
@ -1,6 +1,6 @@
|
||||
from YtManagerApp.appconfig import settings
|
||||
from YtManagerApp.management.jobs.download_video import schedule_download_video
|
||||
from YtManagerApp.models import Video, Subscription, VIDEO_ORDER_MAPPING
|
||||
from YtManagerApp.utils import first_non_null
|
||||
from django.conf import settings as srv_settings
|
||||
import logging
|
||||
import requests
|
||||
@ -12,17 +12,12 @@ log = logging.getLogger('downloader')
|
||||
|
||||
|
||||
def __get_subscription_config(sub: Subscription):
|
||||
enabled = settings.getboolean_sub(sub, 'user', 'AutoDownload')
|
||||
user = sub.user
|
||||
|
||||
global_limit = -1
|
||||
if len(settings.get_sub(sub, 'user', 'DownloadGlobalLimit')) > 0:
|
||||
global_limit = settings.getint_sub(sub, 'user', 'DownloadGlobalLimit')
|
||||
|
||||
limit = -1
|
||||
if len(settings.get_sub(sub, 'user', 'DownloadSubscriptionLimit')) > 0:
|
||||
limit = settings.getint_sub(sub, 'user', 'DownloadSubscriptionLimit')
|
||||
|
||||
order = settings.get_sub(sub, 'user', 'DownloadOrder')
|
||||
enabled = first_non_null(sub.auto_download, user.preferences['auto_download'])
|
||||
global_limit = user.preferences['download_global_limit']
|
||||
limit = first_non_null(sub.download_limit, user.preferences['download_subscription_limit'])
|
||||
order = first_non_null(sub.download_order, user.preferences['download_order'])
|
||||
order = VIDEO_ORDER_MAPPING[order]
|
||||
|
||||
return enabled, global_limit, limit, order
|
||||
|
@ -1,12 +1,14 @@
|
||||
from YtManagerApp.models import Video
|
||||
from YtManagerApp import scheduler
|
||||
from YtManagerApp.appconfig import settings
|
||||
import os
|
||||
import youtube_dl
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from string import Template
|
||||
from threading import Lock
|
||||
|
||||
import youtube_dl
|
||||
|
||||
from YtManagerApp import scheduler
|
||||
from YtManagerApp.models import Video
|
||||
|
||||
log = logging.getLogger('video_downloader')
|
||||
log_youtube_dl = log.getChild('youtube_dl')
|
||||
|
||||
@ -25,9 +27,8 @@ def __get_valid_path(path):
|
||||
return value
|
||||
|
||||
|
||||
def __build_youtube_dl_params(video: Video):
|
||||
# resolve path
|
||||
pattern_dict = {
|
||||
def __build_template_dict(video: Video):
|
||||
return {
|
||||
'channel': video.subscription.channel_name,
|
||||
'channel_id': video.subscription.channel_id,
|
||||
'playlist': video.subscription.name,
|
||||
@ -37,22 +38,30 @@ def __build_youtube_dl_params(video: Video):
|
||||
'id': video.video_id,
|
||||
}
|
||||
|
||||
download_path = settings.get_sub(video.subscription, 'user', 'DownloadPath')
|
||||
output_pattern = __get_valid_path(settings.get_sub(
|
||||
video.subscription, 'user', 'DownloadFilePattern', vars=pattern_dict))
|
||||
|
||||
def __build_youtube_dl_params(video: Video):
|
||||
|
||||
sub = video.subscription
|
||||
user = sub.user
|
||||
|
||||
# resolve path
|
||||
download_path = user.preferences['download_path']
|
||||
|
||||
template_dict = __build_template_dict(video)
|
||||
output_pattern = Template(user.preferences['download_file_pattern']).safe_substitute(template_dict)
|
||||
|
||||
output_path = os.path.join(download_path, output_pattern)
|
||||
output_path = os.path.normpath(output_path)
|
||||
|
||||
youtube_dl_params = {
|
||||
'logger': log_youtube_dl,
|
||||
'format': settings.get_sub(video.subscription, 'user', 'DownloadFormat'),
|
||||
'format': user.preferences['download_format'],
|
||||
'outtmpl': output_path,
|
||||
'writethumbnail': True,
|
||||
'writedescription': True,
|
||||
'writesubtitles': settings.getboolean_sub(video.subscription, 'user', 'DownloadSubtitles'),
|
||||
'writeautomaticsub': settings.getboolean_sub(video.subscription, 'user', 'DownloadAutogeneratedSubtitles'),
|
||||
'allsubtitles': settings.getboolean_sub(video.subscription, 'user', 'DownloadSubtitlesAll'),
|
||||
'writesubtitles': user.preferences['download_subtitles'],
|
||||
'writeautomaticsub': user.preferences['download_autogenerated_subtitles'],
|
||||
'allsubtitles': user.preferences['download_subtitles_all'],
|
||||
'postprocessors': [
|
||||
{
|
||||
'key': 'FFmpegMetadata'
|
||||
@ -60,12 +69,12 @@ def __build_youtube_dl_params(video: Video):
|
||||
]
|
||||
}
|
||||
|
||||
sub_langs = settings.get_sub(video.subscription, 'user', 'DownloadSubtitlesLangs').split(',')
|
||||
sub_langs = user.preferences['download_subtitles_langs'].split(',')
|
||||
sub_langs = [i.strip() for i in sub_langs]
|
||||
if len(sub_langs) > 0:
|
||||
youtube_dl_params['subtitleslangs'] = sub_langs
|
||||
|
||||
sub_format = settings.get_sub(video.subscription, 'user', 'DownloadSubtitlesFormat')
|
||||
sub_format = user.preferences['download_subtitles_format']
|
||||
if len(sub_format) > 0:
|
||||
youtube_dl_params['subtitlesformat'] = sub_format
|
||||
|
||||
@ -74,6 +83,8 @@ def __build_youtube_dl_params(video: Video):
|
||||
|
||||
def download_video(video: Video, attempt: int = 1):
|
||||
|
||||
user = video.subscription.user
|
||||
|
||||
log.info('Downloading video %d [%s %s]', video.id, video.video_id, video.name)
|
||||
|
||||
# Issue: if multiple videos are downloaded at the same time, a race condition appears in the mkdirs() call that
|
||||
@ -82,7 +93,7 @@ def download_video(video: Video, attempt: int = 1):
|
||||
_lock.acquire()
|
||||
|
||||
try:
|
||||
max_attempts = settings.getint_sub(video.subscription, 'user', 'DownloadMaxAttempts', fallback=3)
|
||||
max_attempts = user.preferences['max_download_attempts']
|
||||
|
||||
youtube_dl_params, output_path = __build_youtube_dl_params(video)
|
||||
with youtube_dl.YoutubeDL(youtube_dl_params) as yt:
|
||||
|
@ -4,8 +4,8 @@ from threading import Lock
|
||||
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
|
||||
from YtManagerApp import scheduler
|
||||
from YtManagerApp.appconfig import settings
|
||||
from YtManagerApp.scheduler import scheduler
|
||||
from YtManagerApp.management.appconfig import appconfig
|
||||
from YtManagerApp.management.downloader import fetch_thumbnail, downloader_process_all, downloader_process_subscription
|
||||
from YtManagerApp.models import *
|
||||
from YtManagerApp.utils import youtube
|
||||
@ -45,6 +45,8 @@ def __check_new_videos_sub(subscription: Subscription, yt_api: youtube.YoutubeAP
|
||||
|
||||
def __detect_deleted(subscription: Subscription):
|
||||
|
||||
user = subscription.user
|
||||
|
||||
for video in Video.objects.filter(subscription=subscription, downloaded_path__isnull=False):
|
||||
found_video = False
|
||||
files = []
|
||||
@ -73,7 +75,7 @@ def __detect_deleted(subscription: Subscription):
|
||||
video.downloaded_path = None
|
||||
|
||||
# Mark watched?
|
||||
if settings.getboolean_sub(subscription, 'user', 'MarkDeletedAsWatched'):
|
||||
if user.preferences['mark_deleted_as_watched']:
|
||||
video.watched = True
|
||||
|
||||
video.save()
|
||||
@ -153,17 +155,29 @@ def synchronize_subscription(subscription: Subscription):
|
||||
__lock.release()
|
||||
|
||||
|
||||
__global_sync_job = None
|
||||
|
||||
|
||||
def schedule_synchronize_global():
|
||||
trigger = CronTrigger.from_crontab(settings.get('global', 'SynchronizationSchedule'))
|
||||
job = scheduler.scheduler.add_job(synchronize, trigger, max_instances=1, coalesce=True)
|
||||
log.info('Scheduled synchronize job job=%s', job.id)
|
||||
global __global_sync_job
|
||||
|
||||
trigger = CronTrigger.from_crontab(appconfig.sync_schedule)
|
||||
|
||||
if __global_sync_job is None:
|
||||
trigger = CronTrigger.from_crontab(appconfig.sync_schedule)
|
||||
__global_sync_job = scheduler.add_job(synchronize, trigger, max_instances=1, coalesce=True)
|
||||
|
||||
else:
|
||||
__global_sync_job.reschedule(trigger, max_instances=1, coalesce=True)
|
||||
|
||||
log.info('Scheduled synchronize job job=%s', __global_sync_job.id)
|
||||
|
||||
|
||||
def schedule_synchronize_now():
|
||||
job = scheduler.scheduler.add_job(synchronize, max_instances=1, coalesce=True)
|
||||
job = scheduler.add_job(synchronize, max_instances=1, coalesce=True)
|
||||
log.info('Scheduled synchronize now job job=%s', job.id)
|
||||
|
||||
|
||||
def schedule_synchronize_now_subscription(subscription: Subscription):
|
||||
job = scheduler.scheduler.add_job(synchronize_subscription, args=[subscription])
|
||||
job = scheduler.add_job(synchronize_subscription, args=[subscription])
|
||||
log.info('Scheduled synchronize subscription job subscription=(%s), job=%s', subscription, job.id)
|
||||
|
Reference in New Issue
Block a user