Files
watchstate/FAQ.md
2022-07-07 15:47:52 +03:00

18 KiB

FAQ

Q: How to sync play state to a new backend without overwriting current play state?

Add the backend and when asked, answer no for allow import. when you finish, then run the following command:

$ docker exec -ti watchstate console state:export -vv --ignore-date --force-full --select-backends [BACKEND_NAME]

this command will force export your current local play state to the selected media backend. If the operation is successful you can then enable the import feature if you want.


Q: Is there support for Multi-user setup?

No, The tool is designed to work for single user. However, It's possible to run container for each user. You can use single container for all users, however it's not really easy refer to issue #136.

Note

Note: for Plex home/managed users run the following command to extract each managed user access token.

$ docker exec -ti console backend:users:list --with-tokens -- [BACKEND_NAME]

For Jellyfin/Emby, you can just generate new API tokens.


Q: How to get library id?

Run the following command to get list of backend libraries.

$ docker exec -ti watchstate console backend:library:list [BACKEND_NAME] 

it should display something like

Id Title Type Ignored Supported
2 Movies movie No Yes
1 shows show No Yes
17 Audio Books artist Yes No

The id column refers to backend side id.


Q: Can this tool run without docker?

Yes, if you have the required PHP version and the needed extensions. to run this tool you need the following php8.1, php8.1-fpm and redis-server and the following extensions php8.1-pdo, php8.1-mbstring, php8.1-ctype , php8.1-curl,php8.1-sqlite3, php8.1-redis, and composer. once you have the required runtime dependencies, for first time run:

cd ~/watchstate
composer install --optimize-autoloader

after that you can start using the tool via this command.

$ php console

The app should save your data into ./var directory. If you want to change the directory you can export the environment variable WS_DATA_PATH for console and browser. you can add a file called .env in main tool directory with the environment variables. take look at the files inside docker/files directory to know how to run the scheduled tasks and if you want a webhook support you would need a frontend proxy for php8.1-fpm like nginx, caddy or apache.


Q: Some records keep getting updated even when the state did not change?

This most likely means your media backends have conflicting external ids for the reported items, and thus triggering an update as the tool see different external ids on each event from the backends. In our testing we noticed that at least few hundred records in thetvdb that get reported by plex have incorrect imdb external id, which in turns conflicts sometimes with jellyfin/emby there is nothing we can do beside have the problematic records reported to thetvdb site mods to fix their db entries.


Q: I keep on seeing "No valid/supported external ids." in logs?

This most likely means that the item is not matched in your media backend

  • jellyfin/emby: Edit metadata and make sure there are external ids listed in the metadata.
  • For plex click the (...), and click Fix match. after that refresh metadata.

For episodes, we support both external ids like movies and relative unique ids, To make episodes sync work at least one of the following conditions has to be true:

  • The episode should have external ids.
  • The parent show should have external ids, to make relative unique id works.

Q: Does this tool require webhooks to work?

No, You can use the task scheduler or on demand sync if you want.


Q: How to see my data?

$ docker exec -ti watchstate console db:list

This command will give you access to see the database entries. by default, it will show the last 20 events, however you can run the same command with [-h, --help] to see more options to extend the list or to filter the results.


Q: How to ignore specific libraries from being processed?

Run the following command:

$ docker exec -ti watchstate console servers:edit --key options.ignore --set 'id1,id2,id3' -- [BACKEND_NAME] 

where id1,id2,id3 refers to backend library id

If you ignored a library by mistake you can run the same command again and omit the id, or you can just delete the key entirely by running the following command

$ docker exec -ti watchstate console servers:edit --delete --key options.ignore -- [BACKEND_NAME] 
Note

While this feature works for manual/task scheduler for all supported backends, Jellyfin/Emby does not report library id on webhook event. So, this feature will not work for them in webhook context and the items will be processed.


Q: I get tired of writing the whole command everytime is there an easy way run the commands?

Since there is no way to access the command interface outside docker, you can create small shell script to at least omit part of command that you have to write for example, to create shortcut for docker command do the following:

$ echo 'docker exec -ti watchstate console "$@"' > ws
$ chmod +x ws

after that you can do ./ws command for example, ./ws db:list


Sometimes there are problems related to HTTP/2, so before reporting bug please try running the following command:

$ docker exec -ti watchstate console servers:edit --key options.client.http_version --set 1.0 -- [BACKEND_NAME] 

This will force set the internal http client to use http v1 if it does not fix your problem, please open bug report about it.


Q: Sync operations are failing due to request timeout?

If you want to increase the timeout for specific backend you can run the following command:

$ docker exec -ti watchstate console servers:edit --key options.client.timeout --set 600 -- [BACKEND_NAME] 

where 600 is the number of secs before the timeout handler kill the request.


Q: How to perform search on backend libraries?

Use the following command:

$ docker exec -ti console backend:search:query [BACKEND_NAME] '[QUERY_STRING]'

where [QUERY_STRING] is the keyword that you want to search for

Optional flags

  • [-l, --limit] To limit returned results. Default to 25.
  • [-o, --output] Set output style, it can be yaml, json or table. Default to table.
  • [--include-raw-response] will include backend response in main response body with raw key.

Q: How to get metadata about specific item id?

Use the following command:

$ docker exec -ti watchstate console backend:search:id [BACKEND_NAME] [BACKEND_ITEM_ID]

where [BACKEND_ITEM_ID] refers to backend item id

Optional flags

  • [-o, --output] Set output style, it can be yaml, json or table. Default to table.
  • [--include-raw-response] will include backend response in main response body with raw key.

Q: How to look for mis-identified items?

Use the backend:library:mismatch command. For example,

$ docker exec -ti watchstate console backend:library:mismatch [BACKEND_NAME] [LIBRARY_ID]

where [LIBRARY_ID] refers to backend library id

Optional flags

  • [-p, --percentage] How much in percentage the title has to be in path to be marked as matched item. Default to 50.0%.
  • [-o, --output] Set output mode, it can be yaml, json or table. Default to table.
  • [-m, --method] Which method to use, it can be similarity, or levenshtein. Default to similarity.
  • [--include-raw-response] Will include backend response in main response body with raw key.

Q: How to look for unmatched items?

Use the backend:library:unmatched command. For example,

$ docker exec -ti watchstate console backend:library:unmatched [BACKEND_NAME] [LIBRARY_ID]

where [LIBRARY_ID] refers to backend library id

Optional flags

  • [-o, --output] Set output mode, it can be yaml, json or table. Defaults to table.
  • [--show-all] Will show all library items regardless of the match status.
  • [--include-raw-response] Will include backend response in main response body with raw key.

Q: Which external ids supported for Plex?

  • tvdb://(id) New Plex Agent
  • imdb://(id) New Plex Agent
  • tmdb://(id) New Plex Agent
  • com.plexapp.agents.imdb://(id)?lang=en (Lagecy plex agent)
  • com.plexapp.agents.tmdb://(id)?lang=en (Lagecy plex agent)
  • com.plexapp.agents.themoviedb://(id)?lang=en (Lagecy plex agent)
  • com.plexapp.agents.thetvdb://(seriesId)?lang=en (Lagecy plex agent)
  • com.plexapp.agents.xbmcnfo://(id)?lang=en (XBMC NFO parser agent)
  • com.plexapp.agents.xbmcnfotv://(id)?lang=en (XBMC NFO parser agent for tv)
  • com.plexapp.agents.hama://(db)\d?-(id)?lang=en (hama agent is multi db source agent)

Q: Which external ids supported for Jellyfin/Emby?

  • imdb://(id)
  • tvdb://(id)
  • tmdb://(id)
  • tvmaze://(id)
  • tvrage://(id)
  • anidb://(id)

Q: What does mapper mean?

A Mapper is class that have list of all external ids that point to record in database. think of it as dictionary that reference to specific item.

Memory Mapper (Default)

Memory mapper is the Default mapper, it uses memory to load the entire state table into memory, which in turn leads to better performance. you shouldn't use the other mapper unless you are running into memory problems.

Direct Mapper

Direct mapper is suitable for more memory constraint systems, it just loads the external ids mapping into memory, however it does not keep the state into memory, thus uses less memory compared to MemoryMapper, But the trade-off is it's slower than MemoryMapper.

Comparison between mappers

Operation Memory Mapper Direct Mapper
Memory Usage (✗) Higher (✓) Lower
Matching Speed (✓) Faster (✗) Slower
DB Operations (✓) Faster (✗) Slower

Q: What environment variables supported?

Key Type Description Default
WS_DATA_PATH string Where to store main data. (config, db). ${BASE_PATH}/var
WS_TMP_DIR string Where to store temp data. (logs, cache) ${WS_DATA_PATH}
WS_TZ string Set timezone. UTC
WS_CRON_IMPORT bool Enable import task. Value casted to bool. false
WS_CRON_IMPORT_AT string When to run import task. Valid Cron Expression Expected. 0 */1 * * * (Every 1h)
WS_CRON_IMPORT_ARGS string Flags to pass to the import command. -v
WS_CRON_EXPORT bool Enable export task. Value casted to bool. false
WS_CRON_EXPORT_AT string When to run export task. Valid Cron Expression Expected. 30 */1 * * * (Every 1h 30m)
WS_CRON_EXPORT_ARGS string Flags to pass to the export command. -v
WS_CRON_PUSH bool Enable push task. Value casted to bool. false
WS_CRON_PUSH_AT string When to run push task. Valid Cron Expression Expected. */10 * * * * (Every 10m)
WS_CRON_PUSH_ARGS string Flags to pass to the push command. -v
WS_CRON_PRUNE string Enable prune task. Value is casted to bool. true
WS_CRON_PRUNE_AT string When to run prune task. Valid Cron Expression Expected. 0 */12 * * * (Every 12h)
WS_LOGS_CONTEXT bool Add context to console output messages. false
WS_LOGGER_FILE_ENABLE bool Save logs to file. true
WS_LOGGER_FILE_LEVEL string File Logger Level. ERROR
WS_WEBHOOK_DEBUG bool If enabled, allow dumping request/webhook using rdump & wdump parameters. false
WS_EPISODES_DISABLE_GUID bool Disable external id parsing for episodes and rely on relative ids. false

Container specific environment variables.

Key Type Description Default
WS_DISABLE_CHOWN integer Do not change ownership for needed directories inside the container. 0
WS_DISABLE_HTTP integer Disable included HTTP Server. 0
WS_DISABLE_CRON integer Disable included Task Scheduler. 0
WS_DISABLE_CACHE integer Disable included Cache Server. 0
WS_UID integer Set container user id. 1000
WS_GID integer Set container group id. 1000

Q: How to add webhooks?

To add webhook for your backend the URL will be dependent on how you exposed webhook frontend, but typically it will be like this:

Directly to container: http://localhost:8081/?apikey=[WEBHOOK_TOKEN]

Via reverse proxy : https://watchstate.domain.example/?apikey=[WEBHOOK_TOKEN].

If your media backend support sending headers then remove query parameter ?apikey=[WEBHOOK_TOKEN], and add this header

X-apikey: [WEBHOOK_TOKEN]

where [WEBHOOK_TOKEN] Should match the backend specific webhook.token value. to see the token for each backend run

$ docker exec -ti watchstate console servers:view --select-backends [BACKEND_NAME] -- webhook.token

If you see 'Not configured, or invalid key.' or empty value. run the following command

$ docker exec -ti watchstate console servers:edit --regenerate-webhook-token -- [BACKEND_NAME] 

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=[WEBHOOK_TOKEN]

Webhook Events

Select the following events

  • Playback events
  • User events

Click Add Webhook

Plex (you need "PlexPass" to use webhooks)

Go to your plex Web UI > Settings > Your Account > Webhooks > (Click ADD WEBHOOK)

URL:

http://localhost:8081/?apikey=[WEBHOOK_TOKEN]

Click Save Changes

Note:

If you have multiple plex backends and use the same PlexPass account for all of them, you have to unify the API key, by running the following command:

$ 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 backend we have to identify the backends, The unify command will do the necessary adjustments to handle multi plex backend setup. for more information run.

$ docker exec -ti watchstate console help servers:unify 

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 Add Generic Destination,

Webhook Name:

Choose whatever name you want. For example, Watchstate-Webhook

Webhook Url:

http://localhost:8081

Notification Type:

Select the following events

  • Item Added
  • User Data Saved
  • Playback Start
  • Playback Stop
User Filter:
  • Select your user.
Item Type:
  • Movies
  • Episodes

Send All Properties (ignores template)

Toggle this checkbox.

Add Request Header

Key: x-apikey

Value: [WEBHOOK_TOKEN]

Click save


Q: What are the webhook limitations?

Those are some Webhook limitations we discovered for the following media backends.

Plex

  • Plex does not send webhooks events for "marked as Played/Unplayed".
  • Sometimes does not send events if you add more than one item at time.
  • If you have multi-user setup, Plex will still report the admin account user id as 1.
  • When you mark items as unwatched, Plex reset the date on the object.

Emby

  • Emby does not send webhooks events for newly added items. See feature request
  • Emby webhook test event does not contain data. To test if your setup works, play something or do mark an item as played or unplayed you should see changes reflected in docker exec -ti watchstate console db:list.

Jellyfin

  • If you don't select a user id, the Plugin will send itemAdd event without user data, and will fail the check if you happen to enable webhook.match.user for jellyfin.
  • Sometimes jellyfin will fire webhook itemAdd event without the item being matched.
  • Even if you select user id, sometimes itemAdd event will fire without user data.

Q: Sometimes newly added episodes or movies don't make it to webhook endpoint?

As stated in webhook limitation section sometimes media backends don't make it easy to receive those events, as such, to complement webhooks, you should enable import/export tasks by settings their respective environment variables in your docker-compose.yaml file.