Expand Discord download and Jellyfin notifications
This commit is contained in:
+129
@@ -531,6 +531,7 @@ class DownloadQueueWorkerFailureTests(unittest.TestCase):
|
||||
self.assertEqual(send_webhook.call_args.args[1], "download_completed")
|
||||
self.assertEqual(send_webhook.call_args.args[2]["title"], "Queue Show")
|
||||
self.assertEqual(send_webhook.call_args.args[2]["category"], "finished")
|
||||
self.assertEqual(send_webhook.call_args.args[2]["moved_files"], ["/tmp/example/Queue Show - S01E01.mp4"])
|
||||
|
||||
|
||||
class WatchlistRefreshAllTests(unittest.TestCase):
|
||||
@@ -1320,6 +1321,82 @@ class JellyfinSyncTests(unittest.TestCase):
|
||||
self.assertTrue(target_file.exists())
|
||||
self.assertFalse((download_root / "tv" / "Jelly Show").exists())
|
||||
|
||||
def test_trigger_jellyfin_sync_for_item_sends_success_notification(self):
|
||||
self.seed_watchlist_item()
|
||||
item = APP.WATCHLIST.get("show-jelly-1")
|
||||
with tempfile.TemporaryDirectory() as temp_root:
|
||||
download_root = Path(temp_root) / "downloads"
|
||||
source_file = download_root / "tv" / "Jelly Show" / "Season 01" / "Jelly Show - S01E01.mp4"
|
||||
source_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
source_file.write_bytes(b"episode-data")
|
||||
jellyfin_tv = Path(temp_root) / "jellyfin-tv"
|
||||
with mock.patch.object(APP, "send_discord_webhook_event") as send_webhook:
|
||||
result = APP.trigger_jellyfin_sync_for_item(
|
||||
item,
|
||||
automatic=True,
|
||||
config={
|
||||
"download_dir": str(download_root),
|
||||
"jellyfin_sync_enabled": True,
|
||||
"jellyfin_tv_dir": str(jellyfin_tv),
|
||||
"jellyfin_movie_dir": "",
|
||||
"discord_webhook_url": "https://discord.example/webhook",
|
||||
"discord_webhook_events": ["jellyfin_sync_success"],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(result["moved"])
|
||||
send_webhook.assert_called_once()
|
||||
self.assertEqual(send_webhook.call_args.args[1], "jellyfin_sync_success")
|
||||
self.assertEqual(send_webhook.call_args.args[2]["title"], "Jelly Show")
|
||||
self.assertEqual(send_webhook.call_args.args[2]["source"], "automatic")
|
||||
|
||||
def test_trigger_jellyfin_sync_for_item_sends_failure_notification(self):
|
||||
self.seed_watchlist_item()
|
||||
item = APP.WATCHLIST.get("show-jelly-1")
|
||||
with mock.patch.object(APP, "send_discord_webhook_event") as send_webhook:
|
||||
result = APP.trigger_jellyfin_sync_for_item(
|
||||
item,
|
||||
automatic=True,
|
||||
config={
|
||||
"download_dir": "/tmp/example",
|
||||
"jellyfin_sync_enabled": True,
|
||||
"jellyfin_tv_dir": "",
|
||||
"jellyfin_movie_dir": "",
|
||||
"discord_webhook_url": "https://discord.example/webhook",
|
||||
"discord_webhook_events": ["jellyfin_sync_failed"],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertFalse(result["moved"])
|
||||
self.assertEqual(result["reason"], "target_missing")
|
||||
send_webhook.assert_called_once()
|
||||
self.assertEqual(send_webhook.call_args.args[1], "jellyfin_sync_failed")
|
||||
self.assertEqual(send_webhook.call_args.args[2]["reason"], "target_missing")
|
||||
|
||||
def test_trigger_jellyfin_sync_for_item_skips_already_moved_notification(self):
|
||||
self.seed_watchlist_item()
|
||||
item = APP.WATCHLIST.get("show-jelly-1")
|
||||
with tempfile.TemporaryDirectory() as temp_root:
|
||||
jellyfin_tv = Path(temp_root) / "jellyfin-tv" / "Jelly Show"
|
||||
jellyfin_tv.mkdir(parents=True, exist_ok=True)
|
||||
with mock.patch.object(APP, "send_discord_webhook_event") as send_webhook:
|
||||
result = APP.trigger_jellyfin_sync_for_item(
|
||||
item,
|
||||
automatic=False,
|
||||
config={
|
||||
"download_dir": str(Path(temp_root) / "downloads"),
|
||||
"jellyfin_sync_enabled": True,
|
||||
"jellyfin_tv_dir": str(Path(temp_root) / "jellyfin-tv"),
|
||||
"jellyfin_movie_dir": "",
|
||||
"discord_webhook_url": "https://discord.example/webhook",
|
||||
"discord_webhook_events": ["jellyfin_sync_failed", "jellyfin_sync_success"],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertFalse(result["moved"])
|
||||
self.assertEqual(result["reason"], "already_moved")
|
||||
send_webhook.assert_not_called()
|
||||
|
||||
def test_trigger_jellyfin_sync_for_item_skips_incomplete_series(self):
|
||||
self.seed_watchlist_item(expected_count=24, downloaded_sub_episodes_json=APP.encode_episode_values([str(index) for index in range(1, 13)]))
|
||||
item = APP.WATCHLIST.get("show-jelly-1")
|
||||
@@ -1686,6 +1763,58 @@ class WatchlistAutoRefreshSchedulerTests(unittest.TestCase):
|
||||
self.assertEqual(send_webhook.call_args_list[1].args[1], "watchlist_refresh_failed")
|
||||
self.assertEqual(send_webhook.call_args_list[1].args[2]["items"][0]["title"], "Show B")
|
||||
|
||||
|
||||
class DiscordWebhookFormattingTests(unittest.TestCase):
|
||||
def test_download_completed_webhook_sends_full_file_list_across_embeds(self):
|
||||
payloads = []
|
||||
with mock.patch.object(APP.app_support, "_post_discord_webhook", side_effect=lambda url, payload, attachments=None, timeout=10: payloads.append(payload)):
|
||||
result = APP.app_support.send_discord_webhook_event(
|
||||
{
|
||||
"discord_webhook_url": "https://discord.example/webhook",
|
||||
"discord_webhook_events": ["download_completed"],
|
||||
},
|
||||
"download_completed",
|
||||
{
|
||||
"title": "Big Download",
|
||||
"mode": "sub",
|
||||
"episodes": "1-12",
|
||||
"category": "finished",
|
||||
"moved_files": [f"/tmp/downloads/Big Download/File {index:02d}.mp4" for index in range(1, 130)],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(result["sent"])
|
||||
self.assertGreaterEqual(len(payloads), 1)
|
||||
all_descriptions = "\n".join(
|
||||
embed.get("description", "")
|
||||
for payload in payloads
|
||||
for embed in payload.get("embeds", [])
|
||||
)
|
||||
self.assertIn("/tmp/downloads/Big Download/File 01.mp4", all_descriptions)
|
||||
self.assertIn("/tmp/downloads/Big Download/File 129.mp4", all_descriptions)
|
||||
|
||||
def test_jellyfin_success_webhook_includes_moved_files(self):
|
||||
payloads = []
|
||||
with mock.patch.object(APP.app_support, "_post_discord_webhook", side_effect=lambda url, payload, attachments=None, timeout=10: payloads.append(payload)):
|
||||
result = APP.app_support.send_discord_webhook_event(
|
||||
{
|
||||
"discord_webhook_url": "https://discord.example/webhook",
|
||||
"discord_webhook_events": ["jellyfin_sync_success"],
|
||||
},
|
||||
"jellyfin_sync_success",
|
||||
{
|
||||
"title": "Jelly Show",
|
||||
"media_type": "tv",
|
||||
"source": "automatic",
|
||||
"target": "/srv/jellyfin/Jelly Show",
|
||||
"moved_files": ["/srv/jellyfin/Jelly Show/Season 01/Jelly Show - S01E01.mp4"],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertTrue(result["sent"])
|
||||
self.assertEqual(payloads[0]["content"], "ani-cli-web moved a finished library into Jellyfin.")
|
||||
self.assertIn("/srv/jellyfin/Jelly Show/Season 01/Jelly Show - S01E01.mp4", payloads[0]["embeds"][1]["description"])
|
||||
|
||||
def test_tick_resets_timer_when_schedule_changes(self):
|
||||
config = {
|
||||
"watchlist_auto_refresh_enabled": True,
|
||||
|
||||
Reference in New Issue
Block a user