Files
watchstate/README.md
2022-05-10 07:49:19 +03:00

344 lines
12 KiB
Markdown

# WatchState
WatchState is a CLI based tool to sync your watch state between different media servers, without relying on 3rd parties
services, like trakt.tv, This tool support `Plex Media Server`, `Emby` and `Jellyfin` out of the box currently, with
plans for future expansion for other media servers.
# Breaking Change
If you are using old version of the tool i.e. before (2022-05-08) you need to run manual import to populate the new
database. We had massive code/db changes. The new database name should be `watchstate_v0.db`, if you don't have a
database named `watchstate.db` then there is nothing to do.
to manually import the run this command with --force-full flag to get all previous records.
```bash
$ docker exec -ti watchstate console state:import --force-full -vvrm
```
# Install
create your `docker-compose.yaml` file:
```yaml
version: '3.3'
services:
watchstate:
image: arabcoders/watchstate:latest
container_name: watchstate
restart: unless-stopped
environment:
# For more environment variables please read at the bottom of this page.
WS_UID: ${UID:-1000} # Set container operation user id.
WS_GID: ${GID:-1000} # Set container operation group id.
ports:
- "8081:80" # webhook listener port
volumes:
- ${PWD}/:/config:rw # mount current directory to container /config directory.
```
After creating your docker-compose file, start the container.
```bash
$ docker-compose up -d
```
# First time
Run the following command to see all available commands you can also run help on each command to get more info.
```bash
# Show all commands.
$ docker exec -ti watchstate console list
# Show help document for each command.
$ docker exec -ti watchstate console help state:import
```
---
After starting the container, you have to add your media servers, to do so run the following command
```bash
$ docker exec -ti watchstate console servers:manage --add -- [SERVER_NAME]
```
This command will ask you for some questions to add your servers, you can run the command as many times as you want, if
you want to edit the config again or if you made mistake just run the same command without `--add` flag.
After adding your servers, You should import your current watch state by running the following command.
```bash
$ docker exec -ti watchstate console state:import -vvrm
```
---
# Pulling watch state.
now that you have imported your watch state, you can stop manually running the command again. and rely on the webhooks
to update the watch state. To start receiving webhook events from servers you need to do few more steps.
### Enable webhooks events for specific server.
To see the server specific api key run the following command
```bash
$ docker exec -ti watchstate console servers:view --servers-filter [SERVER_NAME] -- webhook.token
```
If you see 'Not configured, or invalid key.' or empty value. run the following command
```bash
$ docker exec -ti watchstate console servers:edit --regenerate-api-key -- [SERVER_NAME]
```
---
#### TIP:
If you have multiple plex servers and use the same plex account for all of them, you have to unify the API key, by
running the following command
```bash
$ docker exec -ti watchstate console servers:unify plex
Plex global webhook API key is: [random_string]
```
The reason is due to the way plex handle webhooks, And to know which webhook request belong to which server we have to
identify the servers, The unify command will do the necessary adjustments to handle multi plex server setup. for more
information run.
```bash
$ docker exec -ti watchstate console help servers:unify
```
This command is not limited to plex, you can unify API key for all supported backend servers.
---
If you don't want to use webhooks and want to rely only on scheduled task for importing, then set the value
of `WS_CRON_IMPORT` to `1`. By default, we run the import command every hour. However, you can change the scheduled task
timer by adding another variable `WS_CRON_IMPORT_AT` and set its value to valid cron expression. for
example, `0 */2 * * *` it will run every two hours instead of 1 hour. beware, this operation is somewhat costly as it's
pulls the entire server library.
---
#### TIP
You should still have `WS_CRON_IMPORT` enabled as sometimes plex does not really report new items, or report them in a
way that is not compatible with the way we handle webhooks events. running the import command regularly helps keep
healthy `GUIDS <> serverInternalID mapping` relations.
---
# Export watch state
To manually export your watch state back to servers you can run the following command
```bash
$ docker exec -ti watchstate console state:export -vvr
```
to sync specific server/s, use the `--servers-filter` which accept comma seperated list of server names.
```bash
$ docker exec -ti watchstate console state:export -vvr --servers-filter 'server1,server2'
```
To enable the export scheduled task set the value of `WS_CRON_EXPORT` to `1`. By default, we run export every 90
minutes. However, you can change the schedule by adding another variable called `WS_CRON_EXPORT_AT` and set its value to
valid cron expression. for example, `0 */3 * * *` it will run every three hours instead of 90 minutes.
# Start receiving webhook events.
By default, the official container includes a small http server exposed at port `80`, we officially don't support HTTPS
inside the container for the HTTP server. However, for the adventurous people we expose port 443 as well, as such you
can customize the `docker/files/nginx.conf` to support SSL. and do the necessary adjustments. However, do not expect us
to help with it.
#### Example nginx reverse proxy.
```nginx
server {
server_name watchstate.domain.example;
location / {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_pass http://localhost:8081/;
}
}
```
### Adding webhook to server
to your server the url will be dependent on how you expose the server, but typically it will be like this:
#### Webhook URL
Via reverse proxy : `https://watchstate.domain.example/?apikey=[WEBHOOK_TOKEN]`.
Directly to container: `https://localhost:8081/?apikey=[WEBHOOK_TOKEN]`
If your server support sending headers then omit the query parameter '?apikey=[WEBHOOK_TOKEN]', and add new this header
```http request
X-apikey: [WEBHOOK_TOKEN]
```
it's more secure that way.
#### [WEBHOOK_TOKEN]
Should match the server specific ``webhook.token`` value. Refer to the steps described
at **[Steps to enable webhook servers](#enable-webhooks-events-for-specific-server)**.
# Configuring Media servers to send webhook events.
#### Jellyfin (Free)
go to your jellyfin dashboard > plugins > Catalog > install: Notifications > Webhook, restart your jellyfin. After that
go back again to dashboard > plugins > webhook. Add A `Add Generic Destination`,
##### Webhook Name:
Choose whatever name you want.
##### Webhook Url:
`http://localhost:8081`
##### Notification Type:
Select the following events
* Item Added
* User Data Saved
* Playback Start
* Playback Stop
##### Item Type:
* Movies
* Episodes
### Send All Properties (ignores template)
Toggle this checkbox.
### Add Request Header
Key: `X-apikey`
Value: `[YOUR_API_KEY]`
Click `save`
#### Emby (you need emby premiere to use webhooks)
Go to your Manage Emby Server > Server > Webhooks > (Click Add Webhook)
##### Webhook Url:
`http://localhost:8081/?apikey=[YOUR_API_KEY]`
##### Webhook Events
Select the following events
* Playback events
* User events
Click `Add Webhook`
#### Plex (you need PlexPass to use webhooks)
Go to your plex WebUI > Settings > Your Account > Webhooks > (Click ADD WEBHOOK)
##### URL:
`http://localhost:8081/?apikey=[YOUR_API_KEY]`
Click `Save Changes`
# Webhook limitations
# Plex
Does not send webhooks events for "marked as watched/unwatched", or you added more than 1 item at time i.e. folder
import.
If you have multi-user setup, Plex will still report the admin account user id as 1 even though when you get the list
of users ids it shows completely different user ID, so when you initially set up your server for multi-user, select your
admin account and after finishing you have to set the value manually to `1`. to do so please do the following
```bash
$ docker exec -ti watchstate console servers:edit --key user --set 1 -- [SERVER_NAME]
```
This only for the main admin account, other managed/home/external users, you should leave the user as it is reported by
plex.
# Emby
Emby does not send webhooks events for newly added items.
# Jellyfin
If you don't select a user id there, sometimes the plugin will send itemAdd event without user info, and thus will fail
the check if you happen to enable `match user id`.
# Tool specific environment variables.
- (string) `WS_DATA_PATH` Where key data stored (config|db).
- (string) `WS_TMP_DIR` Where temp data stored. (logs|cache). Defaults to `WS_DATA_PATH` if not set.
- (string) `WS_TZ` Set timezone for example, `UTC`
- (bool) `WS_WEBHOOK_DEBUG` enable debug mode for webhook events.
- (bool) `WS_REQUEST_DEBUG` enable debug mode for pre webhook request.
- (integer) `WS_WEBHOOK_TOKEN_LENGTH` how many bits for the webhook api key generator.
- (bool) `WS_LOGGER_STDERR_ENABLED` enable stderr output logging.
- (string) `WS_LOGGER_STDERR_LEVEL` level to log (DEBUG|INFO|NOTICE|WARNING|ERROR|CRITICAL|ALERT|EMERGENCY).
- (bool) `WS_LOGGER_FILE_ENABLE` enable file logging.
- (string) `WS_LOGGER_FILE_LEVEL` level to log (DEBUG|INFO|NOTICE|WARNING|ERROR|CRITICAL|ALERT|EMERGENCY).
- (string) `WS_LOGGER_FILE` full path for log file. By default, it's stored at `$(WS_TMP_DIR)/logs/app.log`
- (bool) `WS_LOGGER_SYSLOG_ENABLED` enable syslog logger.
- (int) `WS_LOGGER_SYSLOG_FACILITY` syslog logging facility
- (string) `WS_LOGGER_SYSLOG_LEVEL` level to log (DEBUG|INFO|NOTICE|WARNING|ERROR|CRITICAL|ALERT|EMERGENCY).
- (string) `WS_LOGGER_SYSLOG_NAME` What name should logs be under.
- (int) `WS_CRON_IMPORT` enable import scheduled task.
- (string) `WS_CRON_IMPORT_AT` cron expression timer.
- (string) `WS_CRON_IMPORT_DEBUG_LEVEL` set debug level, to see unmatched items set to `-vv`. Defaults to `-v`
- (int) `WS_CRON_EXPORT` enable export scheduled task.
- (string) `WS_CRON_EXPORT_AT` cron expression timer.
- (string) `WS_CRON_EXPORT_DEBUG_LEVEL` set debug level. Defaults to `-v`
- (int) `WS_CRON_PUSH` enable push scheduled task.
- (string) `WS_CRON_PUSH_AT` cron expression timer.
- (string) `WS_CRON_PUSH_DEBUG_LEVEL` set debug level. Defaults to `-v`
- (int) `WS_CRON_CACHE` enable caching of GUIDs relations.
- (string) `WS_CRON_CACHE_AT` cron expression timer.
- (string) `WS_CRON_CACHE_DEBUG_LEVEL` set debug level. Defaults to `-v`
- (string) `WS_LOGS_PRUNE_AFTER` Delete logs older than specified time, set to `disable` to disable logs pruning. it
follows php [strtotime](https://www.php.net/strtotime) function rules.
- (bool) `WS_DEBUG_IMPORT` Whether to log invalid GUID items from server in `${WS_TMP_DIR}/debug`.
# Container specific environment variables.
- (int) `WS_NO_CHOWN` do not change ownership needed paths inside container.
- (int) `WS_DISABLE_HTTP` disable included HTTP Server.
- (int) `WS_DISABLE_CRON` disable included Task Scheduler.
- (int) `WS_UID` Container app user ID.
- (int) `WS_GID` Container app group ID.
---
# FAQ
For some common questions, Take look at this [frequently asked questions](FAQ.md) page.