add apprise notifications
This commit is contained in:
parent
75a63c4828
commit
4473e9c5b2
|
@ -47,8 +47,11 @@
|
||||||
},
|
},
|
||||||
"scheduler": {
|
"scheduler": {
|
||||||
"update_subscribed": false,
|
"update_subscribed": false,
|
||||||
|
"update_subscribed_notify": false,
|
||||||
"download_pending": false,
|
"download_pending": false,
|
||||||
|
"download_pending_notify": false,
|
||||||
"check_reindex": {"minute": "0", "hour": "12", "day_of_week": "*"},
|
"check_reindex": {"minute": "0", "hour": "12", "day_of_week": "*"},
|
||||||
|
"check_reindex_notify": false,
|
||||||
"check_reindex_days": 90,
|
"check_reindex_days": 90,
|
||||||
"thumbnail_check": {"minute": "0", "hour": "17", "day_of_week": "*"},
|
"thumbnail_check": {"minute": "0", "hour": "17", "day_of_week": "*"},
|
||||||
"run_backup": false,
|
"run_backup": false,
|
||||||
|
|
|
@ -191,6 +191,8 @@ class VideoDownloader:
|
||||||
self._add_subscribed_channels()
|
self._add_subscribed_channels()
|
||||||
DownloadPostProcess(self).run()
|
DownloadPostProcess(self).run()
|
||||||
|
|
||||||
|
return self.videos
|
||||||
|
|
||||||
def _notify(self, video_data, message):
|
def _notify(self, video_data, message):
|
||||||
"""send progress notification to task"""
|
"""send progress notification to task"""
|
||||||
if not self.task:
|
if not self.task:
|
||||||
|
|
|
@ -157,9 +157,41 @@ class ApplicationSettingsForm(forms.Form):
|
||||||
class SchedulerSettingsForm(forms.Form):
|
class SchedulerSettingsForm(forms.Form):
|
||||||
"""handle scheduler settings"""
|
"""handle scheduler settings"""
|
||||||
|
|
||||||
|
HELP_TEXT = "Add Apprise notification URLs, one per line"
|
||||||
|
|
||||||
update_subscribed = forms.CharField(required=False)
|
update_subscribed = forms.CharField(required=False)
|
||||||
|
update_subscribed_notify = forms.CharField(
|
||||||
|
label=False,
|
||||||
|
widget=forms.Textarea(
|
||||||
|
attrs={
|
||||||
|
"rows": 2,
|
||||||
|
"placeholder": HELP_TEXT,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
download_pending = forms.CharField(required=False)
|
download_pending = forms.CharField(required=False)
|
||||||
|
download_pending_notify = forms.CharField(
|
||||||
|
label=False,
|
||||||
|
widget=forms.Textarea(
|
||||||
|
attrs={
|
||||||
|
"rows": 2,
|
||||||
|
"placeholder": HELP_TEXT,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
check_reindex = forms.CharField(required=False)
|
check_reindex = forms.CharField(required=False)
|
||||||
|
check_reindex_notify = forms.CharField(
|
||||||
|
label=False,
|
||||||
|
widget=forms.Textarea(
|
||||||
|
attrs={
|
||||||
|
"rows": 2,
|
||||||
|
"placeholder": HELP_TEXT,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
check_reindex_days = forms.IntegerField(required=False)
|
check_reindex_days = forms.IntegerField(required=False)
|
||||||
thumbnail_check = forms.CharField(required=False)
|
thumbnail_check = forms.CharField(required=False)
|
||||||
run_backup = forms.CharField(required=False)
|
run_backup = forms.CharField(required=False)
|
||||||
|
|
|
@ -227,6 +227,11 @@ class Reindex(ReindexBase):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.task = task
|
self.task = task
|
||||||
self.all_indexed_ids = False
|
self.all_indexed_ids = False
|
||||||
|
self.processed = {
|
||||||
|
"videos": 0,
|
||||||
|
"channels": 0,
|
||||||
|
"playlists": 0,
|
||||||
|
}
|
||||||
|
|
||||||
def reindex_all(self):
|
def reindex_all(self):
|
||||||
"""reindex all in queue"""
|
"""reindex all in queue"""
|
||||||
|
@ -316,6 +321,7 @@ class Reindex(ReindexBase):
|
||||||
thumb_handler.download_video_thumb(video.json_data["vid_thumb_url"])
|
thumb_handler.download_video_thumb(video.json_data["vid_thumb_url"])
|
||||||
|
|
||||||
Comments(youtube_id, config=self.config).reindex_comments()
|
Comments(youtube_id, config=self.config).reindex_comments()
|
||||||
|
self.processed["videos"] += 1
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -327,8 +333,7 @@ class Reindex(ReindexBase):
|
||||||
new_path = os.path.join(videos, media_url_should)
|
new_path = os.path.join(videos, media_url_should)
|
||||||
os.rename(old_path, new_path)
|
os.rename(old_path, new_path)
|
||||||
|
|
||||||
@staticmethod
|
def _reindex_single_channel(self, channel_id):
|
||||||
def _reindex_single_channel(channel_id):
|
|
||||||
"""refresh channel data and sync to videos"""
|
"""refresh channel data and sync to videos"""
|
||||||
# read current state
|
# read current state
|
||||||
channel = YoutubeChannel(channel_id)
|
channel = YoutubeChannel(channel_id)
|
||||||
|
@ -354,6 +359,7 @@ class Reindex(ReindexBase):
|
||||||
|
|
||||||
channel.upload_to_es()
|
channel.upload_to_es()
|
||||||
ChannelFullScan(channel_id).scan()
|
ChannelFullScan(channel_id).scan()
|
||||||
|
self.processed["channels"] += 1
|
||||||
|
|
||||||
def _reindex_single_playlist(self, playlist_id):
|
def _reindex_single_playlist(self, playlist_id):
|
||||||
"""refresh playlist data"""
|
"""refresh playlist data"""
|
||||||
|
@ -369,6 +375,7 @@ class Reindex(ReindexBase):
|
||||||
|
|
||||||
playlist.json_data["playlist_subscribed"] = subscribed
|
playlist.json_data["playlist_subscribed"] = subscribed
|
||||||
playlist.upload_to_es()
|
playlist.upload_to_es()
|
||||||
|
self.processed["playlists"] += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
def _get_all_videos(self):
|
def _get_all_videos(self):
|
||||||
|
@ -390,6 +397,18 @@ class Reindex(ReindexBase):
|
||||||
valid = CookieHandler(self.config).validate()
|
valid = CookieHandler(self.config).validate()
|
||||||
return valid
|
return valid
|
||||||
|
|
||||||
|
def build_message(self):
|
||||||
|
"""build progress message"""
|
||||||
|
message = ""
|
||||||
|
for key, value in self.processed.items():
|
||||||
|
if value:
|
||||||
|
message = message + f"{value} {key}, "
|
||||||
|
|
||||||
|
if message:
|
||||||
|
message = f"reindexed {message.rstrip(', ')}"
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
|
|
||||||
class ReindexProgress(ReindexBase):
|
class ReindexProgress(ReindexBase):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -184,6 +184,11 @@ class ScheduleBuilder:
|
||||||
"version_check": "0 11 *",
|
"version_check": "0 11 *",
|
||||||
}
|
}
|
||||||
CONFIG = ["check_reindex_days", "run_backup_rotate"]
|
CONFIG = ["check_reindex_days", "run_backup_rotate"]
|
||||||
|
NOTIFY = [
|
||||||
|
"update_subscribed_notify",
|
||||||
|
"download_pending_notify",
|
||||||
|
"check_reindex_notify",
|
||||||
|
]
|
||||||
MSG = "message:setting"
|
MSG = "message:setting"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -213,6 +218,13 @@ class ScheduleBuilder:
|
||||||
redis_config["scheduler"][key] = to_write
|
redis_config["scheduler"][key] = to_write
|
||||||
if key in self.CONFIG and value:
|
if key in self.CONFIG and value:
|
||||||
redis_config["scheduler"][key] = int(value)
|
redis_config["scheduler"][key] = int(value)
|
||||||
|
if key in self.NOTIFY and value:
|
||||||
|
if value == "0":
|
||||||
|
to_write = False
|
||||||
|
else:
|
||||||
|
to_write = value
|
||||||
|
redis_config["scheduler"][key] = to_write
|
||||||
|
|
||||||
RedisArchivist().set_message("config", redis_config)
|
RedisArchivist().set_message("config", redis_config)
|
||||||
mess_dict = {
|
mess_dict = {
|
||||||
"status": self.MSG,
|
"status": self.MSG,
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
"""send notifications using apprise"""
|
||||||
|
|
||||||
|
import apprise
|
||||||
|
from home.src.ta.config import AppConfig
|
||||||
|
from home.src.ta.task_manager import TaskManager
|
||||||
|
|
||||||
|
|
||||||
|
class Notifications:
|
||||||
|
"""notification handler"""
|
||||||
|
|
||||||
|
def __init__(self, name, task_id, task_title):
|
||||||
|
self.name = name
|
||||||
|
self.task_id = task_id
|
||||||
|
self.task_title = task_title
|
||||||
|
|
||||||
|
def send(self):
|
||||||
|
"""send notifications"""
|
||||||
|
apobj = apprise.Apprise()
|
||||||
|
hooks: str | None = self.get_url()
|
||||||
|
if not hooks:
|
||||||
|
return
|
||||||
|
|
||||||
|
hook_list: list[str] = self.parse_hooks(hooks=hooks)
|
||||||
|
title, body = self.build_message()
|
||||||
|
|
||||||
|
if not body:
|
||||||
|
return
|
||||||
|
|
||||||
|
for hook in hook_list:
|
||||||
|
apobj.add(hook)
|
||||||
|
|
||||||
|
apobj.notify(body=body, title=title)
|
||||||
|
|
||||||
|
def get_url(self) -> str | None:
|
||||||
|
"""get apprise urls for task"""
|
||||||
|
config = AppConfig().config
|
||||||
|
hooks: str = config["scheduler"].get(f"{self.name}_notify")
|
||||||
|
|
||||||
|
return hooks
|
||||||
|
|
||||||
|
def parse_hooks(self, hooks: str) -> list[str]:
|
||||||
|
"""create list of hooks"""
|
||||||
|
|
||||||
|
hook_list: list[str] = [i.strip() for i in hooks.split()]
|
||||||
|
|
||||||
|
return hook_list
|
||||||
|
|
||||||
|
def build_message(self) -> tuple[str, str | None]:
|
||||||
|
"""build message to send notification"""
|
||||||
|
task = TaskManager().get_task(self.task_id)
|
||||||
|
status = task.get("status")
|
||||||
|
title: str = f"[TA] {self.task_title} process ended with {status}"
|
||||||
|
body: str | None = task.get("result")
|
||||||
|
|
||||||
|
return title, body
|
|
@ -23,6 +23,7 @@ from home.src.index.filesystem import Scanner
|
||||||
from home.src.index.manual import ImportFolderScanner
|
from home.src.index.manual import ImportFolderScanner
|
||||||
from home.src.index.reindex import Reindex, ReindexManual, ReindexPopulate
|
from home.src.index.reindex import Reindex, ReindexManual, ReindexPopulate
|
||||||
from home.src.ta.config import AppConfig, ReleaseVersion, ScheduleBuilder
|
from home.src.ta.config import AppConfig, ReleaseVersion, ScheduleBuilder
|
||||||
|
from home.src.ta.notify import Notifications
|
||||||
from home.src.ta.ta_redis import RedisArchivist
|
from home.src.ta.ta_redis import RedisArchivist
|
||||||
from home.src.ta.task_manager import TaskManager
|
from home.src.ta.task_manager import TaskManager
|
||||||
from home.src.ta.urlparser import Parser
|
from home.src.ta.urlparser import Parser
|
||||||
|
@ -130,6 +131,12 @@ class BaseTask(Task):
|
||||||
message.update({"messages": ["New task received."]})
|
message.update({"messages": ["New task received."]})
|
||||||
RedisArchivist().set_message(key, message)
|
RedisArchivist().set_message(key, message)
|
||||||
|
|
||||||
|
def after_return(self, status, retval, task_id, args, kwargs, einfo):
|
||||||
|
"""callback after task returns"""
|
||||||
|
print(f"{task_id} return callback")
|
||||||
|
task_title = self.TASK_CONFIG.get(self.name).get("title")
|
||||||
|
Notifications(self.name, task_id, task_title).send()
|
||||||
|
|
||||||
def send_progress(self, message_lines, progress=False, title=False):
|
def send_progress(self, message_lines, progress=False, title=False):
|
||||||
"""send progress message"""
|
"""send progress message"""
|
||||||
message, key = self._build_message()
|
message, key = self._build_message()
|
||||||
|
@ -169,7 +176,7 @@ def update_subscribed(self):
|
||||||
if manager.is_pending(self):
|
if manager.is_pending(self):
|
||||||
print(f"[task][{self.name}] rescan already running")
|
print(f"[task][{self.name}] rescan already running")
|
||||||
self.send_progress("Rescan already in progress.")
|
self.send_progress("Rescan already in progress.")
|
||||||
return
|
return None
|
||||||
|
|
||||||
manager.init(self)
|
manager.init(self)
|
||||||
handler = SubscriptionScanner(task=self)
|
handler = SubscriptionScanner(task=self)
|
||||||
|
@ -178,6 +185,10 @@ def update_subscribed(self):
|
||||||
if missing_videos:
|
if missing_videos:
|
||||||
print(missing_videos)
|
print(missing_videos)
|
||||||
extrac_dl.delay(missing_videos, auto_start=auto_start)
|
extrac_dl.delay(missing_videos, auto_start=auto_start)
|
||||||
|
message = f"Found {len(missing_videos)} videos to add to the queue."
|
||||||
|
return message
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@shared_task(name="download_pending", bind=True, base=BaseTask)
|
@shared_task(name="download_pending", bind=True, base=BaseTask)
|
||||||
|
@ -187,10 +198,16 @@ def download_pending(self, auto_only=False):
|
||||||
if manager.is_pending(self):
|
if manager.is_pending(self):
|
||||||
print(f"[task][{self.name}] download queue already running")
|
print(f"[task][{self.name}] download queue already running")
|
||||||
self.send_progress("Download Queue is already running.")
|
self.send_progress("Download Queue is already running.")
|
||||||
return
|
return None
|
||||||
|
|
||||||
manager.init(self)
|
manager.init(self)
|
||||||
VideoDownloader(task=self).run_queue(auto_only=auto_only)
|
downloader = VideoDownloader(task=self)
|
||||||
|
videos_downloaded = downloader.run_queue(auto_only=auto_only)
|
||||||
|
|
||||||
|
if videos_downloaded:
|
||||||
|
return f"downloaded {len(videos_downloaded)} videos."
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@shared_task(name="extract_download", bind=True, base=BaseTask)
|
@shared_task(name="extract_download", bind=True, base=BaseTask)
|
||||||
|
@ -235,7 +252,10 @@ def check_reindex(self, data=False, extract_videos=False):
|
||||||
self.send_progress("Add outdated documents to the reindex Queue.")
|
self.send_progress("Add outdated documents to the reindex Queue.")
|
||||||
populate.add_outdated()
|
populate.add_outdated()
|
||||||
|
|
||||||
Reindex(task=self).reindex_all()
|
handler = Reindex(task=self)
|
||||||
|
handler.reindex_all()
|
||||||
|
|
||||||
|
return handler.build_message()
|
||||||
|
|
||||||
|
|
||||||
@shared_task(bind=True, name="manual_import", base=BaseTask)
|
@shared_task(bind=True, name="manual_import", base=BaseTask)
|
||||||
|
|
|
@ -250,6 +250,11 @@
|
||||||
<p>Periodically rescan your subscriptions:</p>
|
<p>Periodically rescan your subscriptions:</p>
|
||||||
{{ scheduler_form.update_subscribed }}
|
{{ scheduler_form.update_subscribed }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settings-item">
|
||||||
|
<p>Send notification on task completed:</p>
|
||||||
|
<p>Current notification urls: <span class="settings-current">{{ config.scheduler.update_subscribed_notify }}</span></p>
|
||||||
|
{{ scheduler_form.update_subscribed_notify }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-group">
|
<div class="settings-group">
|
||||||
<h2>Start download</h2>
|
<h2>Start download</h2>
|
||||||
|
@ -266,6 +271,11 @@
|
||||||
<p>Automatic video download schedule:</p>
|
<p>Automatic video download schedule:</p>
|
||||||
{{ scheduler_form.download_pending }}
|
{{ scheduler_form.download_pending }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settings-item">
|
||||||
|
<p>Send notification on task completed:</p>
|
||||||
|
<p>Current notification urls: <span class="settings-current">{{ config.scheduler.download_pending_notify }}</span></p>
|
||||||
|
{{ scheduler_form.download_pending_notify }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-group">
|
<div class="settings-group">
|
||||||
<h2>Refresh Metadata</h2>
|
<h2>Refresh Metadata</h2>
|
||||||
|
@ -287,6 +297,11 @@
|
||||||
<p>Refresh older than x days, recommended 90:</p>
|
<p>Refresh older than x days, recommended 90:</p>
|
||||||
{{ scheduler_form.check_reindex_days }}
|
{{ scheduler_form.check_reindex_days }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settings-item">
|
||||||
|
<p>Send notification on task completed:</p>
|
||||||
|
<p>Current notification urls: <span class="settings-current">{{ config.scheduler.check_reindex_notify }}</span></p>
|
||||||
|
{{ scheduler_form.check_reindex_notify }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-group">
|
<div class="settings-group">
|
||||||
<h2>Thumbnail check</h2>
|
<h2>Thumbnail check</h2>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
apprise==1.4.5
|
||||||
celery==5.3.1
|
celery==5.3.1
|
||||||
Django==4.2.3
|
Django==4.2.3
|
||||||
django-auth-ldap==4.4.0
|
django-auth-ldap==4.4.0
|
||||||
|
|
Loading…
Reference in New Issue