···11+MIT License
22+33+Copyright (c) 2023 Matt Foxx
44+55+Permission is hereby granted, free of charge, to any person obtaining a copy
66+of this software and associated documentation files (the "Software"), to deal
77+in the Software without restriction, including without limitation the rights
88+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+copies of the Software, and to permit persons to whom the Software is
1010+furnished to do so, subject to the following conditions:
1111+1212+The above copyright notice and this permission notice shall be included in all
1313+copies or substantial portions of the Software.
1414+1515+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+SOFTWARE.
+248-4
README.md
···11# tautuilli-notification-digest
2233-Create "digest" notifications for discord using [Tautulli's](https://tautulli.com/) discord [notification agent](https://github.com/Tautulli/Tautulli/wiki/Notification-Agents-Guide#discord).
33+tautuilli-notification-digest (TND) creates "digest" (timed summary) notifications of **Media Added** events for discord using [Tautulli's](https://tautulli.com/) discord [notification agent](https://github.com/Tautulli/Tautulli/wiki/Notification-Agents-Guide#discord).
4455-## What Does It Do?
55+# What Does It Do?
6677Tautulli already provides an email "newsletter" that compiles triggered events (media added) from Plex and then sends it as one email at a set time.
8899-This same functionality **does not exist** for notifications. This [functionality](tautulli newsletter discord) is often requested for [discord](https://www.reddit.com/r/PleX/comments/tzadtv/guide_for_setting_up_discord_andor_tautulli/) and there are even some [existing guides](https://forums.serverbuilds.net/t/guide-timed-summary-plex-to-discord-notifications-with-tautulli/4505) but they are quite involved.
99+This same functionality **does not exist** for notifications. This functionality is often requested for [discord](https://www.reddit.com/r/PleX/comments/tzadtv/guide_for_setting_up_discord_andor_tautulli/) and there are even some [existing guides](https://forums.serverbuilds.net/t/guide-timed-summary-plex-to-discord-notifications-with-tautulli/4505) but they are quite involved.
10101111**This app provides a drop-in solution for timed notifications that compile all of your "Recently Added" Tautulli events into one notification.**
12121313-<img src="/docs/assets/thumbnail.png"
1313+<img src="/docs/assets/thumbnail-multiple.png"
1414alt="thumbnail view" width="400">
1515+1616+# Install
1717+1818+## Docker
1919+2020+* [Dockerhub](https://hub.docker.com/r/foxxmd/tautulli-notification-digest) - `docker.io/foxxmd/tautulli-notification-digest`
2121+* [GHCR](https://github.com/foxxmd/context-mod/pkgs/container/tautulli-notification-digest) - `ghcr.io/foxxmd/tautulli-notification-digest`
2222+2323+## Local (Node)
2424+2525+```shell
2626+clone https://github.com/FoxxMD/tautulli-notification-digest.git .
2727+cd tautulli-notification-digest
2828+yarn install
2929+```
3030+3131+# Setup
3232+3333+## Tautulli
3434+3535+You must first configure a [Tautulli discord notification agent.](https://github.com/Tautulli/Tautulli/wiki/Notification-Agents-Guide#discord)
3636+3737+In your agent ensure these settings are used:
3838+3939+* Configuration
4040+ * Discord Webhook Url
4141+ * **TND location + Slug (see below)**
4242+ * ✅ Include Rich Metadata Info
4343+ * ✅ Include Summary
4444+ * ✅ Include Link to Plex Web (optional)
4545+* Triggers
4646+ * ✅ Recently Added
4747+4848+If you already have an existing agent you will re-use the Webhook url for TND so save it!
4949+5050+Your **Discord Webhook URL** for Tautuilli will be the **location of the TND server + your configured slug.**
5151+5252+Example:
5353+5454+* TND and Tautulli on the same computer, using ENV setup => `http://localhost:8078/my-digest`
5555+* TND on a different machine (192.168.0.180) than Tautulli, using ENV setup => `http://192.168.0.180:8078/my-digest`
5656+* TND on a different machine (192.168.0.180) than Tautulli, using config setup with slug `test` => `http://192.168.0.180:8078/test`
5757+5858+## Configuration
5959+6060+TND can be run using either [environmental variables](#env) or a [configuration file.](#file) If you want to customize how TND behaves you will need to use a configuration file.
6161+6262+### ENV
6363+6464+If you are fine with all default settings then TND can be configured using only environmental variables.
6565+6666+| Environmental Variable | Required? | Example | Description |
6767+|------------------------|-----------|----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
6868+| DISCORD_WEBHOOK | Yes | `https://discord.com/api/webhooks/606873513` | The [discord webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) for a channel you want to post to. This would be the same hook you used when [setting up Tautulli notifications.](https://github.com/Tautulli/Tautulli/wiki/Notification-Agents-Guide#discord) |
6969+| CRON | Yes | `0 17 * * *` | A [cron expression](https://crontab.guru) for when TND should send notifications. The example sends a notification once a day at 5:00pm local time. |
7070+| FORMAT | No | | Always use the specified embed format instead of collapsing for space. Options are: poster, thumbnail, text, list |
7171+| PORT | No | 8078 | The port the web server will listen for incoming events from Tautuilli |
7272+#### Docker
7373+7474+Add [environmental variables](https://docs.docker.com/engine/reference/commandline/run/#env) using the `-e flag` to your run command:
7575+7676+```shell
7777+docker run -e DISCORD_WEBHOOK="https://discord.com/api/webhooks/606873513" -e CRON="0 17 * * *" ... ghcr.io/foxxmd/tautuilli-notification-digest
7878+```
7979+8080+#### Local
8181+8282+Export your variables before the run command or use a [.env file](https://www.codementor.io/@parthibakumarmurugesan/what-is-env-how-to-set-up-and-run-a-env-file-in-node-1pnyxw9yxj)
8383+8484+```shell
8585+DISCORD_WEBHOOK="https://discord.com/api/webhooks/606873513" -e CRON="0 17 * * *" yarn run start
8686+```
8787+8888+### File
8989+9090+An example config file with all options [can be found here.](/config/config.yaml.example)
9191+9292+#### Docker
9393+9494+Mount a directory containing your `config.yaml` file to the `/config` directory in the container:
9595+9696+```shell
9797+docker run -v /host/path/folder:/config ... ghcr.io/foxxmd/tautuilli-notification-digest
9898+```
9999+100100+#### Local
101101+102102+Add your `config.yaml` to a new folder named `data` in the project directory.
103103+104104+# Run
105105+106106+Make sure you have:
107107+108108+* Setup a [Tautuilli discord notification agent](#tautulli)
109109+* Are using **either** [environmental variables](#env) or a [file configuration](#file)
110110+111111+The below run examples will send one summary digest notification a day to discord at 5pm local time.
112112+113113+## Docker
114114+115115+**Note:** When using a `bridge` network (docker default) make sure you map the correct server port (8078 by default) from the container to host.
116116+117117+```shell
118118+docker -e DISCORD_WEBHOOK="https://discord.com/api/webhooks/606873513" -e CRON="0 17 * * *" -p 8078:8078 ghcr.io/foxxmd/tautuilli-notification-digest
119119+```
120120+121121+## Local
122122+123123+```shell
124124+DISCORD_WEBHOOK="https://discord.com/api/webhooks/606873513" -e CRON="0 17 * * *" yarn run start
125125+```
126126+127127+# Options
128128+129129+This section will cover major options for the [file configuration](#file) but is not exhaustive. For a more complete example reference the [**example configuration**](/config/config.yaml.example) or [**the entire config schema can be explored here.**](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Ftautulli-notification-digest%2Fmain%2Fsrc%2Fcommon%2Fschema%2Foperator.json) Use the `Example (YAML)` tab to see examples of individual objects.
130130+131131+## Embed Formats
132132+133133+TND can display notifications in several formats with increasing levels of compactness:
134134+135135+### Poster
136136+137137+The default and same way Tautuilli displays notifications.
138138+139139+<img src="/docs/assets/poster-multiple.png"
140140+alt="thumbnail view" width="400">
141141+142142+### Thumbnail
143143+144144+Display post image as a thumbnail
145145+146146+<img src="/docs/assets/thumbnail-multiple.png"
147147+alt="thumbnail view" width="400">
148148+149149+### Text
150150+151151+Does not include any images but still includes linkable title, summary, and other links.
152152+153153+<img src="/docs/assets/text-multiple.png"
154154+alt="thumbnail view" width="400">
155155+156156+### List
157157+158158+Only includes title of the notification (media name)
159159+160160+<img src="/docs/assets/list-multiple.png"
161161+alt="thumbnail view" width="400">
162162+163163+### Embed Format Collapse
164164+165165+You can configure what [format](#embed-formats) TND will render notifications in based on the number of notifications that have been collected since the last time it posted a digest.
166166+167167+These thresholds are configured in the config file like this:
168168+169169+```yaml
170170+digests:
171171+ - cron: '...'
172172+ discord:
173173+ webhook: '...'
174174+ options:
175175+ list: false
176176+ text: false
177177+ thumbnail: 2
178178+ poster: 0
179179+```
180180+181181+TND determines which format to use by checking for format type threshold by increasing compactness:
182182+183183+List -> Text -> Thumbnail -> Poster
184184+185185+Example:
186186+187187+* 10 pending notifications
188188+* `list: 15 | text: 9 | thumbnail: 8 | poster: 1`
189189+* `text` will be chosen because 10 > 9
190190+ * Note: TND will not consider any "larger" format sizes if a smaller format (`text`) condition is true, even if larger formats have higher thresholds
191191+192192+**Note:** Setting a format to `false` disables it from ever being used.
193193+194194+#### Default Collapse Settings
195195+196196+The default thresholds are:
197197+198198+```
199199+list: false
200200+text: false
201201+thumbnail: 2
202202+poster: 0
203203+```
204204+205205+IE
206206+207207+* If any pending notifications exist, `poster` is used
208208+* If 2 or more pending notifications, `thumbnail` is used
209209+210210+#### Overflow
211211+212212+Discord only allows [10 embeds per message](https://discordjs.guide/popular-topics/embeds.html#embed-limits). If your digest would render more than 9 embeds then TND will automatically create an **overflow** embed that renders as a [list](#list).
213213+214214+<img src="/docs/assets/overflow.png"
215215+alt="thumbnail view" width="400">
216216+217217+The number of notifications shown in the overflow list is truncated after `overflowTruncate` number of notifications and a remaining count is shown.
218218+219219+```yaml
220220+digests:
221221+ - cron: '...'
222222+ discord:
223223+ webhook: '...'
224224+ options:
225225+ overflowTruncate: 20 # defaults to 20
226226+```
227227+228228+## Deduplication Behavior
229229+230230+TND can prevent duplicate, or already seen notifications, from being rendered in a digest. This is useful if Tautulli sends identical notifications after an initial notification which can occur for things like:
231231+232232+* New metadata is added (summary or iamges are fetched from plex agent)
233233+* Adding multiple episodes to a season at different time periods
234234+* A newer/better quality version of an existing movie/episode is added (replaced) in Plex
235235+236236+TND detects duplicates by comparing the **title of the message sent by Tautuilli.** EX: `Season 1 of Show x was added to Plex` or `New Movie (2023) was added to Plex`.
237237+238238+Behavior options are:
239239+240240+* `'all'` - Prevent **any** notification that has been processed by TND before from being future digests
241241+* `'sessions'` (default) - Prevent duplicate notifications within one session IE only unique pending notifications -- if a duplicate is detected it is used instead of the original b/c we assume metadata may have changed
242242+* `'never'` - Always allow duplicates
243243+244244+# API
245245+246246+## Tautuilli Webhook
247247+248248+Any `POST` request to a URL NOT starting with `/api` will be treated as a Tautulli Discord Notification request.
249249+250250+## Run Pending Notifications
251251+252252+Using the **slug** defined for your digest (ENV defaults to `my-digest`) make a `POST` request to
253253+254254+```
255255+http://SERVER_IP:8078/api/SLUG
256256+```
257257+258258+and TND will immediately process any pending notifications
+28
config/config.yaml.example
···11logging:
22+ # default logging level ot console and file
23 level: 'debug'
44+ # specify a different log level for file logging
35 file: 'warn'
66+digests:
77+ # URL ending Tautulli uses for Webhook URL
88+ # Use this if setting up multiple digests
99+ # EX slug: 'my-digest' => Tautulli Webhook Url 'http://localhost:8078/my-digest'
1010+ - slug: 'my-digest'
1111+ # run at 5pm
1212+ # https://crontab.guru
1313+ cron: '0 17,0 * * *'
1414+ # cron can also be a list of expression to set up different jobs for
1515+# cron:
1616+# - '0 17,0 * * *'
1717+# # every hour
1818+# - '0 */1 * * *'
1919+2020+ # don't allow duplicate notifications for any pending notifications
2121+ dedup: 'session'
2222+ discord:
2323+ webhook: 'https://discord.com/api/webhooks/6068898134543123/sLjg0poVgpzWUpXf3_Cn05wL6i7FvoPL6ihUxrl8oeOelPrO'
2424+ options:
2525+ # number of items in the overflow embed before truncating and displaying remainder as a count
2626+ overflowTruncate: 15
2727+ # See README -> Embed Formats
2828+ list: 20
2929+ text: 15
3030+ thumbnail: 6
3131+ poster: 0