tubearchivist/tubearchivist/home/tasks.py

344 lines
11 KiB
Python
Raw Normal View History

2021-09-05 17:10:14 +00:00
"""
Functionality:
- initiate celery app
- collect tasks
- user config changes won't get applied here
because tasks are initiated at application start
2021-09-05 17:10:14 +00:00
"""
import os
2023-03-13 03:09:48 +00:00
from celery import Celery, Task, shared_task
2022-01-22 15:13:37 +00:00
from home.src.download.queue import PendingList
from home.src.download.subscriptions import (
2023-03-02 05:30:48 +00:00
SubscriptionHandler,
2023-03-01 12:12:27 +00:00
SubscriptionScanner,
)
2022-08-10 14:03:54 +00:00
from home.src.download.thumbnails import ThumbFilesystem, ThumbValidator
2022-01-22 15:13:37 +00:00
from home.src.download.yt_dlp_handler import VideoDownloader
from home.src.es.backup import ElasticBackup
from home.src.es.index_setup import ElasitIndexWrap
2022-01-22 15:13:37 +00:00
from home.src.index.channel import YoutubeChannel
2023-03-16 06:18:26 +00:00
from home.src.index.filesystem import Filesystem
from home.src.index.manual import ImportFolderScanner
from home.src.index.reindex import Reindex, ReindexManual, ReindexPopulate
2022-12-21 07:24:24 +00:00
from home.src.ta.config import AppConfig, ReleaseVersion, ScheduleBuilder
2023-03-23 04:28:42 +00:00
from home.src.ta.ta_redis import RedisArchivist
2023-03-01 12:12:27 +00:00
from home.src.ta.task_manager import TaskManager
2023-04-22 04:57:09 +00:00
from home.src.ta.urlparser import Parser
2021-09-05 17:10:14 +00:00
CONFIG = AppConfig().config
2021-09-30 11:03:23 +00:00
REDIS_HOST = os.environ.get("REDIS_HOST")
REDIS_PORT = os.environ.get("REDIS_PORT") or 6379
2021-09-05 17:10:14 +00:00
2021-12-02 08:54:29 +00:00
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
2023-03-01 08:31:17 +00:00
app = Celery(
"tasks",
broker=f"redis://{REDIS_HOST}:{REDIS_PORT}",
backend=f"redis://{REDIS_HOST}:{REDIS_PORT}",
result_extended=True,
)
2021-10-27 11:07:35 +00:00
app.config_from_object("django.conf:settings", namespace="ta:")
2021-09-05 17:10:14 +00:00
app.autodiscover_tasks()
app.conf.timezone = os.environ.get("TZ") or "UTC"
2021-09-05 17:10:14 +00:00
2023-03-13 03:09:48 +00:00
class BaseTask(Task):
"""base class to inherit each class from"""
# pylint: disable=abstract-method
2023-03-13 03:09:48 +00:00
TASK_CONFIG = {
"update_subscribed": {
"title": "Rescan your Subscriptions",
2023-03-18 13:24:28 +00:00
"group": "download:scan",
"api-start": True,
2023-03-22 10:01:34 +00:00
"api-stop": True,
2023-03-13 03:09:48 +00:00
},
"download_pending": {
"title": "Downloading",
2023-03-18 13:24:28 +00:00
"group": "download:run",
"api-start": True,
"api-stop": True,
2023-03-13 03:09:48 +00:00
},
"extract_download": {
"title": "Add to download queue",
2023-03-18 13:24:28 +00:00
"group": "download:add",
2023-03-30 11:20:53 +00:00
"api-stop": True,
2023-03-13 03:09:48 +00:00
},
"check_reindex": {
2023-03-15 09:59:20 +00:00
"title": "Reindex Documents",
2023-03-18 13:24:28 +00:00
"group": "reindex:run",
2023-03-13 03:09:48 +00:00
},
"manual_import": {
"title": "Manual video import",
2023-03-18 13:24:28 +00:00
"group": "setting:import",
"api-start": True,
2023-03-13 03:09:48 +00:00
},
"run_backup": {
"title": "Index Backup",
2023-03-18 13:24:28 +00:00
"group": "setting:backup",
"api-start": True,
2023-03-13 03:09:48 +00:00
},
"restore_backup": {
"title": "Restore Backup",
2023-03-18 13:24:28 +00:00
"group": "setting:restore",
2023-03-13 03:09:48 +00:00
},
"rescan_filesystem": {
"title": "Rescan your Filesystem",
2023-03-18 13:24:28 +00:00
"group": "setting:filesystemscan",
"api-start": True,
2023-03-13 03:09:48 +00:00
},
"thumbnail_check": {
"title": "Check your Thumbnails",
2023-03-18 13:24:28 +00:00
"group": "setting:thumbnailcheck",
"api-start": True,
2023-03-13 03:09:48 +00:00
},
"resync_thumbs": {
"title": "Sync Thumbnails to Media Files",
2023-03-18 13:24:28 +00:00
"group": "setting:thumbnailsync",
"api-start": True,
2023-03-13 03:09:48 +00:00
},
"index_playlists": {
"title": "Index Channel Playlist",
2023-03-18 13:24:28 +00:00
"group": "channel:indexplaylist",
},
"subscribe_to": {
"title": "Add Subscription",
"group": "subscription:add",
2023-03-13 03:09:48 +00:00
},
}
def on_failure(self, exc, task_id, args, kwargs, einfo):
"""callback for task failure"""
print(f"{task_id} Failed callback")
2023-03-23 03:57:15 +00:00
message, key = self._build_message(level="error")
message.update({"messages": ["Task failed"]})
RedisArchivist().set_message(key, message, expire=20)
2023-03-13 03:09:48 +00:00
def on_success(self, retval, task_id, args, kwargs):
"""callback task completed successfully"""
print(f"{task_id} success callback")
message, key = self._build_message()
message.update({"messages": ["Task completed successfully"]})
2023-03-13 03:09:48 +00:00
RedisArchivist().set_message(key, message, expire=5)
def before_start(self, task_id, args, kwargs):
"""callback before initiating task"""
print(f"{self.name} create callback")
message, key = self._build_message()
message.update({"messages": ["New task received."]})
2023-03-13 03:09:48 +00:00
RedisArchivist().set_message(key, message)
2023-03-15 06:28:19 +00:00
def send_progress(self, message_lines, progress=False, title=False):
"""send progress message"""
message, key = self._build_message()
message.update(
{
"messages": message_lines,
"progress": progress,
}
)
2023-03-15 06:28:19 +00:00
if title:
message["title"] = title
RedisArchivist().set_message(key, message)
2023-03-13 03:09:48 +00:00
def _build_message(self, level="info"):
2023-03-13 03:09:48 +00:00
"""build message dict"""
task_id = self.request.id
2023-04-10 03:25:09 +00:00
message = self.TASK_CONFIG.get(self.name).copy()
message.update({"level": level, "id": task_id})
2023-03-24 03:41:33 +00:00
task_result = TaskManager().get_task(task_id)
if task_result:
command = task_result.get("command", False)
message.update({"command": command})
2023-03-24 03:41:33 +00:00
key = f"message:{message.get('group')}:{task_id.split('-')[0]}"
2023-03-13 03:09:48 +00:00
return message, key
2023-03-22 10:01:34 +00:00
def is_stopped(self):
"""check if task is stopped"""
return TaskManager().is_stopped(self.request.id)
2023-03-13 03:09:48 +00:00
@shared_task(name="update_subscribed", bind=True, base=BaseTask)
2023-03-01 12:12:27 +00:00
def update_subscribed(self):
2021-09-21 09:25:22 +00:00
"""look for missing videos and add to pending"""
2023-03-01 12:12:27 +00:00
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] rescan already running")
self.send_progress("Rescan already in progress.")
2023-03-01 12:12:27 +00:00
return
manager.init(self)
2023-04-16 11:30:39 +00:00
handler = SubscriptionScanner(task=self)
missing_videos = handler.scan()
auto_start = handler.auto_start
2023-03-14 09:40:05 +00:00
if missing_videos:
print(missing_videos)
2023-04-16 11:30:39 +00:00
extrac_dl.delay(missing_videos, auto_start=auto_start)
2023-03-01 12:12:27 +00:00
2023-03-15 06:28:19 +00:00
@shared_task(name="download_pending", bind=True, base=BaseTask)
2023-04-21 09:11:37 +00:00
def download_pending(self, auto_only=False):
2021-09-21 09:25:22 +00:00
"""download latest pending videos"""
2023-03-01 12:12:27 +00:00
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] download queue already running")
self.send_progress("Download Queue is already running.")
2023-03-01 12:12:27 +00:00
return
manager.init(self)
2023-04-29 05:55:12 +00:00
VideoDownloader(task=self).run_queue(auto_only=auto_only)
2021-09-05 17:10:14 +00:00
2023-03-14 09:40:05 +00:00
@shared_task(name="extract_download", bind=True, base=BaseTask)
2023-04-16 11:30:39 +00:00
def extrac_dl(self, youtube_ids, auto_start=False):
2021-09-21 09:25:22 +00:00
"""parse list passed and add to pending"""
2023-03-30 11:20:53 +00:00
TaskManager().init(self)
2023-04-22 04:57:09 +00:00
if isinstance(youtube_ids, str):
to_add = Parser(youtube_ids).parse()
else:
to_add = youtube_ids
pending_handler = PendingList(youtube_ids=to_add, task=self)
2022-03-18 11:27:25 +00:00
pending_handler.parse_url_list()
2023-04-16 11:30:39 +00:00
pending_handler.add_to_pending(auto_start=auto_start)
2023-04-29 05:55:12 +00:00
if auto_start:
download_pending.delay(auto_only=True)
2023-03-15 09:59:20 +00:00
@shared_task(bind=True, name="check_reindex", base=BaseTask)
def check_reindex(self, data=False, extract_videos=False):
2021-09-21 09:25:22 +00:00
"""run the reindex main command"""
if data:
# started from frontend through API
print(f"[task][{self.name}] reindex {data}")
2023-03-15 09:59:20 +00:00
self.send_progress("Add items to the reindex Queue.")
ReindexManual(extract_videos=extract_videos).extract_data(data)
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] reindex queue is already running")
self.send_progress("Reindex Queue is already running.")
return
manager.init(self)
if not data:
# started from scheduler
populate = ReindexPopulate()
print(f"[task][{self.name}] reindex outdated documents")
self.send_progress("Add recent documents to the reindex Queue.")
populate.add_recent()
2023-03-15 09:59:20 +00:00
self.send_progress("Add outdated documents to the reindex Queue.")
populate.add_outdated()
2023-03-15 09:59:20 +00:00
Reindex(task=self).reindex_all()
2021-09-13 15:17:36 +00:00
2023-03-15 10:39:37 +00:00
@shared_task(bind=True, name="manual_import", base=BaseTask)
def run_manual_import(self):
2021-09-21 09:25:22 +00:00
"""called from settings page, to go through import folder"""
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] manual import is already running")
self.send_progress("Manual import is already running.")
return
manager.init(self)
2023-03-15 10:39:37 +00:00
ImportFolderScanner(task=self).scan()
2021-09-18 13:02:54 +00:00
2023-03-16 03:11:10 +00:00
@shared_task(bind=True, name="run_backup", base=BaseTask)
def run_backup(self, reason="auto"):
2021-09-21 09:25:22 +00:00
"""called from settings page, dump backup to zip file"""
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] backup is already running")
self.send_progress("Backup is already running.")
return
2022-08-12 05:03:09 +00:00
manager.init(self)
2023-03-16 03:11:10 +00:00
ElasticBackup(reason=reason, task=self).backup_all_indexes()
2023-03-16 03:11:10 +00:00
@shared_task(bind=True, name="restore_backup", base=BaseTask)
def run_restore_backup(self, filename):
2021-09-21 09:25:22 +00:00
"""called from settings page, dump backup to zip file"""
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] restore is already running")
self.send_progress("Restore is already running.")
return
manager.init(self)
2023-03-16 03:11:10 +00:00
self.send_progress(["Reset your Index"])
ElasitIndexWrap().reset()
2023-03-16 03:11:10 +00:00
ElasticBackup(task=self).restore(filename)
2021-09-21 09:25:22 +00:00
print("index restore finished")
2021-09-24 16:37:26 +00:00
2023-03-16 06:18:26 +00:00
@shared_task(bind=True, name="rescan_filesystem", base=BaseTask)
def rescan_filesystem(self):
2021-10-08 08:10:44 +00:00
"""check the media folder for mismatches"""
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] filesystem rescan already running")
self.send_progress("Filesystem Rescan is already running.")
return
manager.init(self)
2023-03-16 06:18:26 +00:00
Filesystem(task=self).process()
2023-03-16 10:12:50 +00:00
ThumbValidator(task=self).validate()
2023-03-16 10:12:50 +00:00
@shared_task(bind=True, name="thumbnail_check", base=BaseTask)
def thumbnail_check(self):
2021-12-02 08:54:29 +00:00
"""validate thumbnails"""
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] thumbnail check is already running")
self.send_progress("Thumbnail check is already running.")
return
manager.init(self)
2023-03-16 10:12:50 +00:00
ThumbValidator(task=self).validate()
2021-12-02 08:54:29 +00:00
2023-03-16 11:13:37 +00:00
@shared_task(bind=True, name="resync_thumbs", base=BaseTask)
def re_sync_thumbs(self):
"""sync thumbnails to mediafiles"""
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] thumb re-embed is already running")
self.send_progress("Thumbnail re-embed is already running.")
return
manager.init(self)
2023-03-16 11:13:37 +00:00
ThumbFilesystem(task=self).embed()
2023-03-18 10:46:51 +00:00
@shared_task(bind=True, name="subscribe_to", base=BaseTask)
def subscribe_to(self, url_str):
"""take a list of urls to subscribe to"""
2023-03-18 10:46:51 +00:00
SubscriptionHandler(url_str, task=self).subscribe()
@shared_task(bind=True, name="index_playlists", base=BaseTask)
def index_channel_playlists(self, channel_id):
"""add all playlists of channel to index"""
channel = YoutubeChannel(channel_id, task=self)
channel.index_channel_playlists()
2021-12-02 08:54:29 +00:00
2022-12-21 07:24:24 +00:00
@shared_task(name="version_check")
def version_check():
"""check for new updates"""
ReleaseVersion().check()
# start schedule here
app.conf.beat_schedule = ScheduleBuilder().build_schedule()