diff --git a/.env.deploy.example b/.env.deploy.example index 064bbbb..44707ff 100644 --- a/.env.deploy.example +++ b/.env.deploy.example @@ -1,8 +1,10 @@ DISCORD_BOT_TOKEN=replace-with-your-discord-bot-token -DISCORD_CHANNEL_ID=1504278732070981683 DISCORD_GATEWAY_ENABLED=true ARCHIVE_STATUS_CONFIG=services.json ARCHIVE_STATUS_STATE=state/status-message.json +MEDIA_CATALOG_STATE=state/media-catalog.json +BOT_SETTINGS_STATE=state/bot-settings.json +MEDIA_CATALOG_MAX_ITEMS=240 CHECK_INTERVAL_SECONDS=60 HTTP_USER_AGENT=ArchiveStatusBot/1.0 DISCORD_DRY_RUN=false diff --git a/.env.example b/.env.example index 025ab7d..56c6665 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,10 @@ DISCORD_BOT_TOKEN=replace-with-your-discord-bot-token -DISCORD_CHANNEL_ID=1504278732070981683 DISCORD_GATEWAY_ENABLED=true ARCHIVE_STATUS_CONFIG=services.json ARCHIVE_STATUS_STATE=state/status-message.json +MEDIA_CATALOG_STATE=state/media-catalog.json +BOT_SETTINGS_STATE=state/bot-settings.json +MEDIA_CATALOG_MAX_ITEMS=240 CHECK_INTERVAL_SECONDS=60 HTTP_USER_AGENT=ArchiveStatusBot/1.0 DISCORD_DRY_RUN=false diff --git a/README.md b/README.md index 44a1d41..d84754c 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ It does not need Discord gateway intents or slash commands for the status module The bot also includes a small web dashboard for editing monitored services and forcing immediate Discord refreshes. +It also has a media catalog module. From the dashboard you can upload `Movies.csv` and/or `Shows.csv`, choose a Discord channel ID, and publish a formatted catalog embed set. + ## Discord Bot Setup Create a Discord application and bot in the Discord Developer Portal, then invite it with: @@ -16,18 +18,14 @@ Create a Discord application and bot in the Discord Developer Portal, then invit https://discord.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&permissions=84992&scope=bot ``` -Required channel permissions: +Required channel permissions for each dashboard-selected channel: - View Channel - Send Messages - Embed Links - Read Message History -The current `status` channel ID is: - -```text -1504278732070981683 -``` +Channel IDs are configured from the dashboard and stored in `state/bot-settings.json`. ## Local Setup @@ -95,6 +93,8 @@ http://127.0.0.1:8787 Sign in with `DASHBOARD_USERNAME` and the password you used when generating `DASHBOARD_PASSWORD_HASH`. +Set the Status and Media channel IDs from the dashboard before publishing Discord updates. + ## Docker Setup ```sh @@ -127,7 +127,7 @@ If `state/` or `services.json` were created by a previous container as another u sudo chown -R "$(id -u):$(id -g)" services.json state ``` -The bot stores the Discord message ID in `state/status-message.json`. Keep that file mounted so the bot edits the same message after restarts. +The bot stores channel settings in `state/bot-settings.json` and Discord message IDs in `state/status-message.json` and `state/media-catalog.json`. Keep `state/` mounted so the bot edits the same messages after restarts. The deploy compose joins your existing reverse-proxy network: @@ -181,13 +181,42 @@ http://127.0.0.1:8787 The dashboard currently supports: - viewing monitored services +- selecting the Discord channel used by the status updater - adding/removing service rows - editing check URL, display URL, expected statuses, timeout, and keyword - saving `services.json` - forcing an immediate check and Discord message update +- uploading `Movies.csv` and `Shows.csv` +- publishing a paginated media catalog to a selected Discord channel The sidebar leaves room for future modules like polls, webhooks, automations, and service integrations without changing the bot shape later. +## Media Catalog + +Open the dashboard and switch to `Media`. Set the target Discord channel ID, choose `Movies.csv`, `Shows.csv`, or both, then publish. + +Channel selections are stored in: + +```env +BOT_SETTINGS_STATE=state/bot-settings.json +``` + +The parser accepts common column names such as `title`, `name`, `year`, `genre`, `genres`, `rating`, `runtime`, `summary`, `overview`, `season`, and `episode`. Show exports that contain one row per episode are grouped by show title where possible. + +The bot stores media catalog message IDs in: + +```env +MEDIA_CATALOG_STATE=state/media-catalog.json +``` + +Republishing edits the previous catalog messages in place. If the catalog gets shorter, the bot attempts to delete old extra messages. + +By default, Discord output is capped at 240 movies and 240 shows to avoid flooding a channel. Change this with: + +```env +MEDIA_CATALOG_MAX_ITEMS=240 +``` + ## Service Config Each service supports: diff --git a/dashboard.html b/dashboard.html index bdeb167..2087cfb 100644 --- a/dashboard.html +++ b/dashboard.html @@ -107,9 +107,19 @@ display: flex; justify-content: space-between; gap: 12px; + width: 100%; + border: 0; border-radius: 6px; + background: transparent; padding: 8px 9px; color: var(--muted); + font-weight: 650; + text-align: left; + } + + .nav-item:hover { + background: #1b1d21; + border-color: transparent; } .nav-item.active { @@ -265,6 +275,63 @@ color: #fca5a5; } + .view[hidden] { + display: none; + } + + .media-form { + display: grid; + grid-template-columns: minmax(220px, 0.8fr) minmax(220px, 1fr) minmax(220px, 1fr); + gap: 12px; + padding: 14px; + border-bottom: 1px solid var(--line); + } + + .channel-form { + display: grid; + grid-template-columns: minmax(220px, 360px); + gap: 12px; + padding: 14px; + margin-bottom: 16px; + } + + .media-field label { + display: block; + color: var(--muted); + font-size: 12px; + font-weight: 650; + margin-bottom: 5px; + } + + .media-field input[type="file"] { + padding: 7px; + } + + .media-status { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 1px; + background: var(--line); + } + + .media-status div { + background: var(--panel); + padding: 14px; + min-height: 74px; + } + + .media-status span { + display: block; + color: var(--muted); + margin-bottom: 5px; + } + + .media-status strong { + display: block; + font-size: 16px; + overflow-wrap: anywhere; + } + .token-screen { max-width: 420px; margin: 80px auto; @@ -300,7 +367,9 @@ grid-template-columns: repeat(4, minmax(0, 1fr)); } - .service-row { + .service-row, + .channel-form, + .media-form { grid-template-columns: 1fr 1fr; } } @@ -321,7 +390,10 @@ } nav, - .service-row { + .service-row, + .channel-form, + .media-form, + .media-status { grid-template-columns: 1fr; } } @@ -343,50 +415,108 @@
-
-

Status Services

-
- - - - - +
+
+

Status Services

+
+ + + + + +
-
-
-
- Services - 0 -
-
- Online - 0 -
-
- Issues - 0 -
-
- Last check - Never -
+
+
+ + +
+
+ +
+
+ Services + 0 +
+
+ Online + 0 +
+
+ Issues + 0 +
+
+ Last check + Never +
+
+ +
+
+
Monitored Links
+
+
+
+
-
-
-
Monitored Links
-
+
@@ -394,13 +524,17 @@