Compare commits

...

288 Commits

Author SHA1 Message Date
TOomaAh
668a6ae0f8 refactor(settings): remove metadata providers logo 2025-09-01 00:19:20 +02:00
TOomaAh
d7655e520d refactor(tvdb): replace indexer by metadata providers 2025-09-01 00:13:53 +02:00
TOomaAh
82d81fd1d1 style(logs): update error log label from "Metadata" to "MetadataProvider" 2025-08-29 01:01:36 +02:00
TOomaAh
9c072e49d7 style(settings): clarify navigation label from "Metadata" to "Metadata Providers" 2025-08-29 00:51:27 +02:00
TOomaAh
ca52a3e130 fix(scanner): correct metadata provider ID from Tmdb to Tvdb 2025-08-28 23:49:06 +02:00
TOomaAh
c0cc109aab feat(i18n): add missing translations 2025-08-28 23:36:51 +02:00
TOomaAh
be3454ca1e refactor(tvdb): remove unnecessary try/catch block 2025-08-28 23:26:56 +02:00
TOomaAh
04f0506e90 docs(comments): translate from French to English 2025-08-28 23:23:28 +02:00
TOomaAh
04c22ef266 style(wording): standardize naming to "Metadata Provider" in UI text 2025-08-28 23:16:51 +02:00
TOomaAh
61b764b502 chore(i18n): remove french translation + apply i18n:extract 2025-08-28 23:12:27 +02:00
TOomaAh
7814fffc11 style(cypress): fix anime name variable 2025-08-23 00:36:05 +02:00
TOomaAh
ac24c37973 fix(test): fix test with default provider tmdb anime 2025-08-23 00:36:05 +02:00
fallenbagel
d762123a01 chore: add correct application-wide key 2025-08-23 00:36:05 +02:00
fallenbagel
da84b16410 chore: add project-wide apikey for tvdb 2025-08-23 00:36:05 +02:00
TOomaAh
bade7f5139 fix(tests): fix cypress test 2025-08-23 00:36:05 +02:00
TOomaAh
b26689b2da feat(provider): replace indexer by provider 2025-08-23 00:36:05 +02:00
TOomaAh
09d68e6f12 feat(metadata): replace fetch with axios for API calls 2025-08-23 00:36:05 +02:00
TOomaAh
503d8b1c0c refactor(tvdb): remove logger info 2025-08-23 00:36:05 +02:00
TOomaAh
df9921fda1 refactor(tmdb): apply prettier 2025-08-23 00:36:05 +02:00
TOomaAh
e52cb4a7f8 refactor(tvdb): fix apikey 2025-08-23 00:36:05 +02:00
TOomaAh
227533a691 fix(tests): fix all cypress tests 2025-08-23 00:36:05 +02:00
TOomaAh
1618eb954c style(provider): remove french comment 2025-08-23 00:36:05 +02:00
TOomaAh
6e27efcaa7 style(provider): full provider name in select 2025-08-23 00:36:05 +02:00
TOomaAh
c24eebafc0 style(provider): change provider name in info section 2025-08-23 00:36:05 +02:00
TOomaAh
3c310f2319 fix(scanner): fix plex scanner tvdb provider 2025-08-23 00:36:05 +02:00
TOomaAh
3952312884 fix(scanner): fix jellyfin scanner with tvdb provider 2025-08-23 00:36:05 +02:00
TOomaAh
5232950ac8 style(prettier): run prettier 2025-08-23 00:36:05 +02:00
TOomaAh
25c2788047 refactor(metadata): refactor tvdb api calls 2025-08-23 00:36:05 +02:00
TOomaAh
07e8c4698a refactor(metadata): remove french comments 2025-08-23 00:36:05 +02:00
TOomaAh
56f33fe383 refactor(metadata): refactor metadata routes 2025-08-23 00:36:05 +02:00
TOomaAh
4b0652d7ba refactor(metadata): rewrite metadata settings 2025-08-23 00:36:05 +02:00
TOomaAh
4104f3dadd refactor(medata): add tvdb settings 2025-08-23 00:36:05 +02:00
TOomaAh
be91a3f20a fix(tvdb): rename tvdb to medatada 2025-08-23 00:36:05 +02:00
TOomaAh
3c9ed469a8 refactor(tvdb): use tvdb api 2025-08-23 00:36:02 +02:00
TOomaAh
ac76be5014 refactor(tvdb): remove skyhook api 2025-08-23 00:35:17 +02:00
TOomaAh
4dcb308955 fix(scanner): add tvdb indexer for scanner 2025-08-23 00:35:17 +02:00
TOomaAh
5f49a978a9 refactor(swagger): fix /tvdb/test response 2025-08-23 00:35:17 +02:00
TOomaAh
a4ef53e7f1 fix(tvdb): ensure that seasons contain data 2025-08-23 00:35:17 +02:00
TOomaAh
f755a5f1f3 fix(build): revert package.json 2025-08-23 00:35:17 +02:00
TOomaAh
b1548b7e76 fix(tmdb): fix build
fix build after rebase
2025-08-23 00:35:17 +02:00
TOomaAh
9b2c8899da test(tvdb): change 'use' to 'tvdb' condition check 2025-08-23 00:35:17 +02:00
TOomaAh
b45898665e refactor(tmdb): reduce still path condition 2025-08-23 00:35:17 +02:00
TOomaAh
1fb1dc9e1b refactor(settings): replace tvdb object to boolean type 2025-08-23 00:35:17 +02:00
TOomaAh
a54d3c5a65 refactor(indexer): remove unused getSeasonIdentifier method 2025-08-23 00:35:17 +02:00
TOomaAh
5b216abe8d style(tvdb): rename pokemon to correct tv show 2025-08-23 00:35:17 +02:00
TOomaAh
f4997d0aa0 test(tvdb): add tvdb tests 2025-08-23 00:35:17 +02:00
TOomaAh
c5987e2275 fix(test): wrong url tv-details 2025-08-23 00:35:17 +02:00
TOomaAh
3b908af0fe fix(test): fix discover test 2025-08-23 00:35:17 +02:00
TOomaAh
bedc8c4579 style: tvdb.login to tvdb.test 2025-08-23 00:35:17 +02:00
TOomaAh
f912783878 style: replace avalaible to available 2025-08-23 00:35:17 +02:00
TOomaAh
4a19c81e11 fix: wrong language with tmdb indexer 2025-08-23 00:35:17 +02:00
TOomaAh
1fbe4d2031 refactor: clean tvdb indexer code 2025-08-23 00:35:17 +02:00
TOomaAh
7107f1e91f fix: error if tmdb poster is null 2025-08-23 00:35:17 +02:00
TOomaAh
377c6a40a8 fix: error during get episodes 2025-08-23 00:35:16 +02:00
TOomaAh
b88606a1df refactor(tvdb): replace tvdb api by skyhook 2025-08-23 00:35:16 +02:00
TOomaAh
aa7de132be fix(usersettings): remove unused column tvdbtoken 2025-08-23 00:35:16 +02:00
TOomaAh
3906430875 fix: fix rate limiter index tvdb indexer 2025-08-23 00:35:16 +02:00
TOomaAh
26e22e9dba feat(tvdb): get tv seasons/episodes with tvdb 2025-08-23 00:35:16 +02:00
Gauthier
368ecf8771 fix(dnscaching): display stats for DNS caching (#1858)
* fix(dnscaching): display stats for DNS caching

* fix: add missing translation
2025-08-20 17:32:59 +08:00
Georgy
d3fd5028dc feat: add IMDb rating votes count in tooltip (#1696)
* feat: add IMDb rating votes count in tooltip

* feat: add IMDb rating votes count in tooltip

* feat: add IMDb rating votes count in tooltip
2025-08-19 22:26:42 +02:00
Gauvain
c0fd81a5f0 fix: remove console warning (#1836)
* fix: remove a console warning

* fix: Adds id attribute to select element for accessibility

Fixes label association by adding missing id attribute to the select dropdown, ensuring proper accessibility compliance and screen reader functionality.
2025-08-19 21:49:06 +02:00
0xsysr3ll
af7ceaf7a2 feat(requests): add user's avatar next to Requested/Last Modified by icon (#1750)
* feat(requests): add user's avatar in front of Requested/Last Modified by

* refactor(requests): wrap both the avatar and the username in Link

* fix(requests): remove unnecessary margin between avatar and username
2025-08-20 03:43:51 +08:00
fallenbagel
b4adfd2ffa feat: dns caching manager (#1294)
* feat(dns): implement dns caching

* feat: simple implementation of dnscaching

* feat: dynamic ttl which is revalidated while using stale dns cache

This is done as tmdb ttl is very less like 40 seconds so to make sure
any issues wont be caused due to cached dns (previously we were caching
for 5 minutes no matter what ttl)

* feat(dns): improve DNS cache with multi-strategy fallback system

- multiple DNS resolution strategie
- graceful fallbacks between IPv6 and IPv4 addresses
- network error reporting in fetch fix
- compatibility with cypress testing (I HOPE)

* fix: typos

* feat: dns cache stats in jobs & cache page (and cleanup)

* feat(networksettings): cache dns off by default

* feat: make dnsCache optional and enable-able through network settings

* chore(i18n): extract translation keys

* test(cypress): fix cypress testing

* feat(dnscache): dns cache entries are now flushable

* style(cypress): run prettier

* chore(cypresssettings): git ignore cypress json settings

* chore: ignore cypress/config/settings.json

* fix(dnscache): use entry specific hits and misses not global

* refactor: clean up console logs

* fix(dnscache): fix miss counter

* feat(dnscache): global stats

* chore(i18n): extract translation keys

* refactor: use date-fns for formatting age and remove useless code

* refactor: remove cypress testing options in dnsCacheManager

* refactor: remove console logs

* refactor: removed useless condition when its always truthy

* fix: remove FetchAPI-related code

* fix: remove old ipv4first setting

* refactor: use our own dns-caching package instead

* fix: correct dns-caching module configuration

* fix: correct dns-caching module configuration

* fix: remove useless lru-cache dependency

* fix: update dns-caching to v0.2.0

* fix: add env variable for min/max ttl & update dns-caching

* fix: update dns-caching package

* fix: add force min/max TTL in network settings

* docs: add docs for dns caching

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2025-08-20 03:02:21 +08:00
0xsysr3ll
5c1583cf56 fix(UserProfile): handle optional chaining for recentlyWatched data (#1852)
This PR fixes a client-side TypeError in the "Recently Watched" section of user profiles. The issue occurred when recentlyWatched was undefined. The fix adds optional chaining (?.) to prevent the app from crashing.

Signed-off-by: 0xsysr3ll <0xsysr3ll@pm.me>
2025-08-19 19:00:09 +02:00
Gauthier
66d4cd63bb docs(notifications): add more documentation for notifications (#1856)
This PR adds more documentation methods for notifications. Most of it is taken from the Overseerr
documentation.
2025-08-20 00:46:04 +08:00
Ludovic Ortega
e8ec3473da chore(helm): bump jellyseerr to 2.7.3 (#1848)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-08-14 23:24:09 +02:00
0xsysr3ll
17d4f13afe fix(api): update Plex Watchlist URL (#1847) 2025-08-15 03:57:30 +08:00
0xsysr3ll
3292f11308 fix(MediaRequestSubscriber): use event manager to get fresh media state for MEDIA_AVAILABLE notifications (#1825)
* fix(MediaRequestSubscriber): use event manager to get fresh media state for MEDIA_AVAILABLE notifications

* refactor(MediaRequestSubscriber): streamline media availability notifications
2025-08-10 21:33:06 +02:00
0xsysr3ll
c86ee0ddb1 fix(api): make username field nullable in UserSettings API schema (#1835) 2025-08-06 06:22:21 +08:00
0xsysr3ll
e02ee24f70 fix(media): update delete media file logic to include is4k parameter (#1832)
* fix(media): update delete media file logic to include is4k parameter

* fix(media): revert to MANAGE_REQUESTS permission
2025-08-05 11:42:11 +02:00
0xsysr3ll
ca1686425b fix(blacklist): handle invalid keywords gracefully (#1815)
* fix(blacklist): handle invalid keywords gracefully

* fix(blacklist): only remove keywords on 404 errors

* fix(blacklist): remove non-null assertion and add proper type annotation

* refactor(blacklist): return null instead of 404 for missing keywords

* fix(blacklist): add type annotation for validKeywords

* fix(selector): update type annotation for validKeywords
2025-08-01 11:03:22 +02:00
0xsysr3ll
e52c63164f fix(api): add missing user settings' api docs (#1820)
This PR adds new fields to the UserSettings schema, including username, email, discordId, and various quota limits for movies and TV shows.

It also updates API paths to reference the new UserSettings schema.
2025-07-30 23:44:49 +02:00
Gauthier
e98f31e66c fix(proxy): initialize image proxies after the proxy is set up (#1794)
The ImageProxy for TMDB and TheTVDB were initialized before the proxy settings were set up, so they
were ignoring the proxy settings.

fix #1787
2025-07-24 10:33:53 +02:00
Gauthier
75a7279ea2 fix(proxy): modify the registration of the axios interceptors (#1791)
The previous way of adding Axios interceptors added a new interceptor each time, causing lags after
a while because of all the duplicate interceptors added.

fix #1787
2025-07-20 11:33:16 +02:00
Ludovic Ortega
d53ffca5db chore(helm): bump jellyseerr to 2.7.1 (#1785)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-07-15 22:06:29 +02:00
Ludovic Ortega
844b1abad9 fix: allow setting IPv6 as an IP address in hostname field (#1782)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-07-15 11:26:30 +00:00
Ludovic Ortega
c88a20f536 chore(deps): upgrade axios to support ipv6 (#1781)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-07-13 23:14:52 +02:00
0xsysr3ll
4c633d49c5 docs(database): update database configuration/migration instructions (#1777)
- Divided Docker and standalone installation methods in tabs
- Added some guidance for PostgreSQL socket paths, Docker networking requirements, and migration procedures
2025-07-13 13:47:16 +02:00
Ludovic Ortega
6be0c92d7b chore: upgrade semantic packages (#1779)
fix #1773
2025-07-13 13:40:11 +02:00
0xsysr3ll
3be920e74b docs(plex): add some Plex integration related documentation (#1662)
* docs(plex): add some Plex integration related documentation

* docs(plex): clarify watchlist auto-request permission requirements

* fix(docs): missing newline
2025-07-11 13:49:13 +02:00
RoboMagus
2e64f1344e chore(ci): migrate to 'semantic-release-docker' to enable semver docker tags (#1610) 2025-07-10 14:50:49 +02:00
Ludovic Ortega
8f9bc5f761 docs(docker): add healthcheck to documentation (#1748)
* docs(docker): add healthcheck to documentation

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: update docker cli healthcheck

---------

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-07-10 10:15:13 +02:00
Georgiy Sitnikov
d0bd134d88 docs: add Apache to reverse proxy (#1762)
* Update reverse-proxy.mdx

Add Apache2 configuration as per #1760

* Update reverse-proxy.mdx

Apache2 moved to the bottom.
Location update to sync with nginx docs
2025-07-09 16:03:55 +02:00
ionred
510108f9bb fix: remove LunaSea (#1759)
* refactor(lunasea-removal): remove LunaSea

fixes #1756

* chore(localization): undo localization changes in favor of weblate
2025-07-09 16:03:06 +02:00
0xsysr3ll
8c43db2abf fix(gotify): notifications blocked when priority set to 0 (#1763)
This PR fixes an issue where Gotify notifications would not be sent when the priority was configured to 0.
2025-07-04 22:25:18 +02:00
Gauthier
b83367cbf2 fix(proxy): apply all proxy settings to Axios (#1741) 2025-06-25 22:40:24 +08:00
Ludovic Ortega
0fd03f3848 chore(helm): bump jellyseerr to 2.7.0 (#1725)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-06-20 12:39:02 +00:00
Gauthier
9cb7e1495a fix: redirect the 'Request' button to the right page (#1711)
This PR change the link of the 'Request' button of the UserDropdown for user with no MANAGE_REQUEST
or REQUEST_VIEW permissions. These users can't see the /users/:ID/requests page, so there were
redirected to the home page. This PR also removes the /profile/request page which is the same as the
/request or the /users/:ID/requests page.

fix #1588
2025-06-18 03:00:48 +05:00
Gauthier
0357d17205 feat: add force ipv4 first setting (#1719)
This PR adds a 'Force IPv4' setting in the network settings, like the one that existed before we
migrated from Fetch API to Axios.
2025-06-17 21:35:52 +02:00
Gauthier
049bc59d2d chore: merge upstream (#1712)
* feat(pushover): attach image to pushover notification payload (#3701)

* fix: api language query parameter (#3720)

* docs: add j0srisk as a contributor for code (#3745) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(tooltip): add tooltip to display exact time on date hover (#3773)

Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>

* docs: add Loetwiek as a contributor for code (#3776) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): ensure title fits into the `view collection` box (#3696)

* fix(docs): correct openapi docs minor issues (#3648)

* docs: add Fuochi as a contributor for doc (#3826)

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: translations update from Hosted Weblate (#3597)

* feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (1232 of 1234 strings)

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/da/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/el/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 99.5% (1234 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 37.1% (461 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 37.0% (459 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 34.8% (432 of 1240 strings)

Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 57.4% (712 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 13.2% (164 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 4.8% (60 of 1240 strings)

feat(lang): added translation using Weblate (Bulgarian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 97.9% (1215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 82.0% (1017 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 71.3% (885 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.9% (805 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.4% (799 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.8% (792 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.7% (791 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 57.5% (714 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 49.9% (619 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 32.1% (399 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 24.6% (306 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 18.9% (235 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.5% (217 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.3% (215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 8.0% (100 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 3.3% (41 of 1240 strings)

feat(lang): added translation using Weblate (Ukrainian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Czech)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Czech)

Currently translated at 99.6% (1236 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/cs/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Croatian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.6% (1236 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 97.5% (1210 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.5% (1185 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 94.3% (1166 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hungarian)

Currently translated at 91.3% (1133 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 89.3% (1108 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hebrew)

Currently translated at 13.9% (172 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: osh <osh@osh.cc>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/he/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Polish)

Currently translated at 99.1% (1225 of 1236 strings)

Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 92.8% (1148 of 1236 strings)

Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ar/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.6% (33 of 1240 strings)

feat(lang): added translation using Weblate (Finnish)

Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Serbian)

Currently translated at 50.8% (630 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hans/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>

* feat(lang): add lang config for Bulgarian, Finnish, Ukrainian, Indonesian, Slovak, Turkish and Maori (#3834)

* fix: correct deeplinks on iPad (#3883)

* feat(studios): add a24 to studios list (#3902)

* docs: add demrich as a contributor for code (#3906) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(watchlist): Cache watchlist requests with matching E-Tags (#3901)

* perf(watchlist): add E-Tag caching to Plex watchlist requests

* refactor(watchlist): increase frequency of watchlist requests

* fix: sync watchlist every 3 min instead of 3 sec

* docs: add maxnatamo as a contributor for code (#3907) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(plex): refresh token schedule (#3875)

* feat: refresh token schedule

fix #3861

* fix(i18n): add i18n message

* refactor(plextv): use randomUUID crypto instead custom function

* docs: add DamsDev1 as a contributor for code (#3924) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: correct icon showing on certain phones when not pulled (#3939)

* feat: add support for requesting "Specials" for TV Shows (#3724)

* feat: add support for requesting "Specials" for TV Shows

This commit is responsible for adding support in Overseerr for requesting "Special" episodes for TV
Shows. This request has become especially pertinent when you consider shows like "Doctor Who". These
shows have Specials that are critical to understanding the plot of a TV show.

fix #779

* chore(yarn.lock): undo inappropriate changes to yarn.lock

I was informed by @sct in a comment on the #3724 PR that it was not appropriate to commit the
changes that ended up being made to the yarn.lock file. This commit is responsible, then, for
undoing the changes to the yarn.lock file that ended up being submitted.

* refactor: change loose equality to strict equality

I received a comment from OwsleyJr pointing out that we are using loose equality when we could
alternatively just be using strict equality to increase the robustness of our code. This commit
does exactly that by squashing out previous usages of loose equality in my commits and replacing
them with strict equality

* refactor: move 'Specials' string to a global message

Owsley pointed out that we are redefining the 'Specials' string multiple times throughout this PR.
Instead, we can just move it as a global message. This commit does exactly that. It squashes out and
previous declarations of the 'Specials' string inside the src files, and moves it directly to the
global messages file.

* docs: add AhmedNSidd as a contributor for code (#3964) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#3835)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.2% (1231 of 1240 strings)

Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Polish)

Currently translated at 98.8% (1227 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.9% (36 of 1240 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Albanian)

Currently translated at 95.8% (1189 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: W L <wl@mailhole.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sq/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Portugal))

Currently translated at 98.4% (1221 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_PT/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.9% (1239 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 98.2% (1219 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hant/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Norwegian Bokmål)

Currently translated at 89.9% (1115 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: exentler <gurandsrud@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nb_NO/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>

* feat(ui): prevent password manager interference & improve service links (#3989)

* docs: add s0up4200 as a contributor for code (#4047) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): update Plex Logo (#3955)

* docs: add JackW6809 as a contributor for code (#4048) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: requests/issues menu count (#3470)

* feat: request and issue count added to sidebar/mobile menu

* fix: added permission check for count visibility

* refactor: modified badge design for count

* fix: properly update issue and request counts in certain scenarios (#4051)

* fix: center count badge on sidebar and mobile menu (#4052)

* fix: request english trailers as a fallback when using other languages (#4009)

Co-authored-by: Stancu Florin <florin@stancu.me>

* docs: add StancuFlorin as a contributor for code (#4053) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: added the PWA badge indicator for requests pending (#3411)

refactor: removed unnecessary code when sending web push notification

fix: moved all notify user logic into webpush

refactor: n

refactor: remove all unnecessary prettier changes

fix: n

fix: n

fix: n

fix: n

fix: increment sw version

fix: n

* fix: improve count badge styling (#4056)

* fix: improved web push management (#3421)

refactor: organized placement of new button + added comments

fix: added api routes for push registration

fix: modified get request to confirm key identity

fix: added back notification types to always show

feat: added a manageable device list

refactor: modified device list to make it mobile friendly

fix: correct typo for enabling notifications

* Revert "fix: improved web push management (#3421)" (#4058)

* fix: manage webpush notifications (#4059)

* feat(lang): Translations update from Hosted Weblate (#4025)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rico <rico.jambor@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 40.8% (507 of 1240 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.9% (1239 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.7% (1237 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): added translation using Weblate (Slovenian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: sct <sctsnipe@gmail.com>

* fix: change localhost to process.env.HOST for client requests (#3839)

* Change localhost to process.env.HOST for client requests

* refactor: reformat

* docs: add lmiklosko as a contributor for code (#4063) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: set the correct TTL for the cookie store (#3946)

The time-to-live (TTL) of cookies stored in the database was incorrect because the connect-typeorm
library takes a TTL in seconds and not milliseconds, making cookies valid for ~82 years instead of
30 days.

Co-authored-by: Ryan Cohen <ryan@sct.dev>

* docs: add gauthier-th as a contributor for code (#4064) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: update migration script (#4065)

* fix: update migration script

fix: remove insert for new entities

* fix: correct migration name

* fix: correct name inside migration

* fix(servarr): merge series tags instead of overwriting them (#4019)

* Merge series tags instead of overwriting when adding a series that already exists

Currently, a request coming in for a series that already exists in sonarr nukes the tags in sonarr for the series in favor of the tags coming from overseerr. This change merges the two lists of tags and deduplicates them before sending them to sonarr.

* fix(servarr api): merge request media tags with servarr instead of overwriting

---------

Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>

* build(snap): update snap build actions

* build: temporarily disable snap builds (#4074)

* build: fix deploy docs action (#4076) [skip ci]

* fix: display request button when the show has requestable specials and is available (#4081)

* chore(deps): pin node.js (#4075)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(deps): pin dependencies (#4084)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#4060)

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1259 of 1259 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1258 of 1258 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: st7105 <st7105@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 50.6% (638 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.4% (509 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.3% (508 of 1259 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 94.2% (1187 of 1259 strings)

Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1259 of 1259 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 9.2% (117 of 1259 strings)

feat(lang): translated using Weblate (Finnish)

Currently translated at 8.6% (109 of 1259 strings)

Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>

* fix: correct specials affecting availability status (#4092)

* fix: remove specials affecting availability status

* refactor: add comments for scanner

* fix: prevent request badge showing when no related media (#4100)

* fix: availability sync requests (#3460)

* fix: modified media status handling when media has been deleted

fix: requests will now be updated to completed on scan

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: base scanner will set requests to completed correctly

fix: mark available button correctly sets requests as completed

fix: status will now stay deleted after declined request

refactor: request completion handling moved to entity

fix: prevented notifications from sending to old deleted requests

refactor: cleaned up code and added more detail to logs

refactor: updated to reflect latest availability sync changes

* fix: fetch requests only if necessary in db and remove unneeded code

* fix: update request button logic to accomodate specials

fix: remove completed filtering in tv details

* fix: correctly set seasons status when using the manual button

* refactor: improve reliability of season request completion

refactor: remove seasonrequest code

* fix: send notification for 4k movies

fix: same for shows

* feat: add completed filter to requests list

refactor: correct label

* fix: correct series setting to partially available (#4109)

* fix: correct edge case with deletion not updating requests (#4110)

* fix: correct notification sending for wrong status (#4113)

* fix(notifications): sending test-notifications for email now respects the allowSelfSigned value (#4112)

* docs: add vfaergestad as a contributor for code (#4114)

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: handle currently available non-completed media (#4115)

* fix: check media status has changed before modifying request

fix: refactor: code cleanup

* fix: manually load database entity seasons

* fix: handle partial seasons more reliably (#4116)

refactor: remove matchingOldSeason variable

* fix: pwa app badge (#4117)

* fix: clear app badge at zero without notification

* fix: correct users check sometimes failing when searching push subs

* fix: filter specials from modal all seasons and watchlist (#4108)

* fix: filter specials from modal all seasons and watchlist

* fix: skip specials when marking available

* fix: edge case where specials were marked as completed

* fix: bypass specials when partial requests is disabled (#4126)

* refactor(MediaRequest): consolidate lifecycle hooks into subscriber & restrict cascade to prevent recursion (#4124)

* fix(mediarequest entity): narrow cascade to insert & remove to prevent hook recursion

Restrict cascade options on the MediaRequest→Media relation to only `insert` and `remove`to avoid
nested subscriber/AfterUpdate recursion when saving entities.

* fix(mediarequest): move methods modifying MediaRequest to its Subscriber

* fix(mediasubscriber): use event.manager for parent media updates on remove

Replace `getRepository(Media)` calls with `event.manager` in the `afterRemove` hook so that
parent-media status resets run within the same transaction/QueryRunner (important for postgresql.
Doesnt affect sqlite).

* refactor(mediasubscriber): make afterInsert and afterUpdate async and await internal operations

This should prevent unhandled promise rejections and ensure sequential execution of lifecycle
actions

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>

* fix(mediaentity): change cascade from `update` to `remove` (#4135)

* fix(mediasubscriber): remove async from afterInsert and afterUpdate (#4136)

Asynchronous operations introduced in commit 3b9e195496c3db1f794549786b123a3ff55b08a0 caused issues
during media requests: the mediaId was not properly assigned and remained null.

* fix: better handling for active webpush subscription (#4146)

fix: remove yarn from package manager

fix: update openapi yml

---------

Co-authored-by: Isaac M <masesisaac@gmail.com>
Co-authored-by: Joseph Risk <j0srisk@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Loetwiek <79059734+Loetwiek@users.noreply.github.com>
Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>
Co-authored-by: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
Co-authored-by: Fuochi <ffuochi@hotmail.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Co-authored-by: Jordan Jones <me@jjones.tech>
Co-authored-by: Brandon Cohen <brandon@z3hn.dev>
Co-authored-by: David Emrich <demrich@me.com>
Co-authored-by: Max T. Kristiansen <me@maxtrier.dk>
Co-authored-by: Damien Fajole <60252259+DamsDev1@users.noreply.github.com>
Co-authored-by: Ahmed Siddiqui <36286128+AhmedNSidd@users.noreply.github.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>
Co-authored-by: soup <s0up4200@pm.me>
Co-authored-by: JackOXI <53652452+JackW6809@users.noreply.github.com>
Co-authored-by: Stancu Florin <StancuFlorin@users.noreply.github.com>
Co-authored-by: Stancu Florin <florin@stancu.me>
Co-authored-by: Brandon Cohen <cohbrandon@gmail.com>
Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Lukas Miklosko <44380311+lmiklosko@users.noreply.github.com>
Co-authored-by: Ryan Cohen <ryan@sct.dev>
Co-authored-by: Andrew Kennedy <andrew-kennedy@users.noreply.github.com>
Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Co-authored-by: vfaergestad <49147564+vfaergestad@users.noreply.github.com>
2025-06-17 16:09:59 +05:00
Gauthier
7c969f4235 fix(proxy): apply http proxy settings to axios (#1716)
This PR apply the HTTP(S) proxy settings defined in the Jellyseerr network tab to Axios because
Axios doesn't use the proxy settings from Undici.
2025-06-13 23:00:26 +02:00
fallenbagel
bb95c7009f fix: correct typing issue (#1715)
* fix(ntfy): display the current value of auth and fix types

When using the username/password as auth method, the saved value was not displayed properly because
of a wrong property name introduced by a missing type.

* fix: correct typing issue

---------

Co-authored-by: gauthier-th <mail@gauthierth.fr>
2025-06-14 01:14:12 +05:00
Gauthier
d4a6cb268a fix(blacklist): hide items from MediaSliders when hideBlacklisted is enabled (#1713)
This PR hides the blacklisted items from the MediaSliders appearing on the homepage when the
hideBlacklisted is enabled.
2025-06-14 00:48:26 +05:00
Gauthier
fb8677f29c fix(settings): add a tip for youtube URL setting (#1714)
This PR adds a tip explaining what is the purpose of the new 'Youtube URL' setting.
2025-06-14 00:47:56 +05:00
Gauthier
c7284f473c fix(jellyfin): use the same deviceId for admins (#1710)
* fix(jellyfin): use the same deviceId for admins

This PR will make Jellyseerr use the same deviceId for the admin user everytime he logins to
Jellyfin/Emby. The previous behavior with different deviceId was creating new entries on the media
at every request.

* fix: remove useless check
2025-06-12 23:52:01 +05:00
Ludovic Ortega
0bdc8a0334 chore(helm): bump jellyseerr to 2.6.0 (#1704)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-06-10 22:41:41 +02:00
Gauthier
c0dd2e5e27 fix(filters): display the right value when resetting the filter options (#1695)
* fix(filters): display the right value when resetting the filter options

When clearing the filters everything is reset but the sort option still display the previous value,
while the content has now the default value.

fix #1693

* fix: remove console.log
2025-06-04 17:15:09 +08:00
fallenbagel
6b8c0bd8f3 fix(mediarequests): properly sort season numbers in media requests (#1688)
Added an @AfterLoad() hook in MediaRequest to ensure seasons are always ordered by their ID.
Previously, joinedseasons could appear in arbitrary database order, leading to jumbled UI displays.
With this change,the seasons list is automatically re-sorted in ascending ID order as soon as
TypeORM hydrates theentity.

fix #1336
2025-05-31 11:23:15 +02:00
fallenbagel
ea7e68fc99 fix(usersettings): exclude current user when checking for existing email (#1689)
This update modifies the user settings endpoint so that, when validating email uniqueness, the query
excludes the current user’s own record (using id: Not(user.id))
2025-05-31 11:10:13 +02:00
Gauthier
110adfaf66 docs: add a troubleshooting section for lost admin access (#1678) 2025-05-22 21:31:19 +02:00
wolffman122
515124bab4 fix(issuecomment): fix issue display lists in IssueComment (#1638)
* fix(issuecomment): fix issue display lists in IssueComment

The IssueComment module was not displaying markdown list's ordered or unorderd.  Removing the
allowed elements so all markdowns are allowed seems to fix this issue and work similar to github's
comment  control with lists and markdown.

fix #1328

* fix #1328 Added back allowedElements, added the list elements to it also.

* feat(fixes formatting issue): fixes formating issue that was committed by mistake

fixes formatting issue that was comitted by mistake

fix #1328
2025-05-20 13:23:57 +02:00
fallenbagel
52e85e1404 chore(i18n): update translations from weblate (#1670)
* Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/

* Translated using Weblate (French)
Currently translated at 94.7% (1409 of 1487 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Ukrainian)
Currently translated at 91.0% (1354 of 1487 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (French)
Currently translated at 94.8% (1411 of 1487 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (French)
Currently translated at 95.0% (1414 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (French)
Currently translated at 99.9% (1486 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (French)
Currently translated at 99.9% (1486 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (German)
Currently translated at 98.6% (1467 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.6% (1066 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/nb_NO/

* Translated using Weblate (French)
Currently translated at 99.9% (1486 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.4% (1137 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/nb_NO/

* Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 86.8% (1291 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/zh_Hans/

* Translated using Weblate (Spanish)
Currently translated at 87.2% (1297 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/es/

* Translated using Weblate (Basque)
Currently translated at 93.8% (1395 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Polish)
Currently translated at 91.5% (1362 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Basque)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Russian)
Currently translated at 89.9% (1338 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Ukrainian)
Currently translated at 91.0% (1354 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Swedish)
Currently translated at 87.6% (1304 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 87.6% (1304 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Swedish)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Bulgarian)
Currently translated at 83.3% (1239 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/bg/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (French)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (French)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (German)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Hebrew)
Currently translated at 43.2% (643 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/he/

* Translated using Weblate (Hebrew)
Currently translated at 44.3% (659 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/he/

* Translated using Weblate (Bulgarian)
Currently translated at 85.5% (1272 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/bg/

* Translated using Weblate (Russian)
Currently translated at 100.0% (1487 of 1487 strings)
Translate-URL: http://translate.jellyseerr.dev/projects/jellyseerr/jellyseerr-frontend/ru/

---------

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: HanaO00 <greenmalkak@gmail.com>
Co-authored-by: michael <michaelvelosk@gmail.com>
Co-authored-by: Gökhan GÜRBÜZ <gkhn.gurbuz@hotmail.com>
Co-authored-by: Julien Cordeau <julien-cg@hotmail.fr>
Co-authored-by: Bas <910100490+weblate@proton.me>
Co-authored-by: Dennis van J <weblate@amsx.net>
Co-authored-by: 0xsysr3ll <0xsysr3ll@protonmail.com>
Co-authored-by: bogomil22 <bogomil22@users.noreply.translate.jellyseerr.dev>
Co-authored-by: Mikael Wessel <post@mikaelkw.online>
Co-authored-by: chenhui_li <lichenhui1997@gmail.com>
Co-authored-by: Miguel Pacheco <runway-venus-kung@duck.com>
Co-authored-by: Thadah <thadahdenyse+borgcube@protonmail.com>
Co-authored-by: zulimazuli <zulimazuli@gmail.com>
Co-authored-by: Stefan <dev.stafloker@gmail.com>
Co-authored-by: Blackflexxy <blackflexxy@gmail.com>
Co-authored-by: Nik <niklas@olofsson.cc>
Co-authored-by: Mattias Magnusson <mattish.91@gmail.com>
Co-authored-by: NilsKarlssonPyssling <nisse@users.noreply.translate.jellyseerr.dev>
Co-authored-by: Manu <mswiss@bluewin.ch>
Co-authored-by: Georgi Sariev <sariev_g@icloud.com>
Co-authored-by: big man <commandfns1@gmail.com>
Co-authored-by: Veselin <vesko2345@gmail.com>
Co-authored-by: Gallyam <gallyamb@gmail.com>
2025-05-19 10:05:01 +02:00
Gauthier
24e1e94747 fix(ui): make person media type filter consistent on mobile (#1669)
This PR fixes the media type filter on mobile
2025-05-19 11:45:12 +08:00
0xsysr3ll
b27dbd7a15 fix(jellyfin): clean up Jellyfin sessions on Jellyseerr logout (#1651)
* fix(jellyfin): clean up Jellyfin sessions on Jellyseerr logout

* refactor(auth): remove deleteUserDevice method and handle device deletion directly in logout process

* refactor(auth): optimize logout route for Jellyfin/Emby

Only query database for Jellyfin/Emby users during logout to avoid unnecessary database queries for Plex/local users. This improves performance by skipping the device deletion process when it's not needed.
2025-05-16 20:42:40 +08:00
fallenbagel
78afd02d3d docs: revert image change to dockerhub.io (#1663)
One of the previous prs changed it to ghcr.io. While we do support it, that's our secondary and dockerhub has always been our primary.
2025-05-14 19:56:08 +00:00
Gauthier
8949edea7e fix: add missing cache for some tmdb images (#1656)
This PR replaces some Images with CachedImage for missing TMDB-related images.
2025-05-13 03:28:12 +08:00
Gauthier
e69649d71d feat: add caching for TVDB images (#1655) 2025-05-12 16:50:24 +08:00
Gauthier
d226dbb9b4 fix(url validation): correct URL validation for empty fields (#1657)
The isValidURL function was returning false when the provided value was undefined/null/empty, but
needs to return true instead so it doesn't interfere with Yup validation.
2025-05-12 16:18:34 +08:00
fallenbagel
8da1c92923 fix(entity): use TIMESTAMPTZ in Postgres and sort issue comments oldest-first (#1654)
* fix(entity): use TIMESTAMPTZ in Postgres and sort issue comments oldest-first

Switch key datetime columns to TIMESTAMPTZ for proper UTC handling
(“just now”) and sort issue comments on load so the original
description stays first and in proper sorted order in fix-pgsql-timezone

fixes #1569, fixes #1568

* refactor(migration): manually rewrite pgsql migration to preserve existing data

Typeorm generated migration was dropping the entire column thus leading to data loss so this is an
attempt at manually rewriting the migration to preserve the data

* refactor(migrations): rename to be consistent with other migration files

* fix: use id to order instead of createdAt to avoid non-existant createdAt

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2025-05-10 03:38:22 +08:00
Gauthier
70a28dd1e3 chore: merge upstream (#1653)
* feat(pushover): attach image to pushover notification payload (#3701)

* fix: api language query parameter (#3720)

* docs: add j0srisk as a contributor for code (#3745) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(tooltip): add tooltip to display exact time on date hover (#3773)

Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>

* docs: add Loetwiek as a contributor for code (#3776) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): ensure title fits into the `view collection` box (#3696)

* fix(docs): correct openapi docs minor issues (#3648)

* docs: add Fuochi as a contributor for doc (#3826)

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: translations update from Hosted Weblate (#3597)

* feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (1232 of 1234 strings)

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/da/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/el/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 99.5% (1234 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 37.1% (461 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 37.0% (459 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 34.8% (432 of 1240 strings)

Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 57.4% (712 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 13.2% (164 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 4.8% (60 of 1240 strings)

feat(lang): added translation using Weblate (Bulgarian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 97.9% (1215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 82.0% (1017 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 71.3% (885 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.9% (805 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.4% (799 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.8% (792 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.7% (791 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 57.5% (714 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 49.9% (619 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 32.1% (399 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 24.6% (306 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 18.9% (235 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.5% (217 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.3% (215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 8.0% (100 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 3.3% (41 of 1240 strings)

feat(lang): added translation using Weblate (Ukrainian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Czech)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Czech)

Currently translated at 99.6% (1236 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/cs/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Croatian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.6% (1236 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 97.5% (1210 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.5% (1185 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 94.3% (1166 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hungarian)

Currently translated at 91.3% (1133 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 89.3% (1108 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hebrew)

Currently translated at 13.9% (172 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: osh <osh@osh.cc>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/he/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Polish)

Currently translated at 99.1% (1225 of 1236 strings)

Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 92.8% (1148 of 1236 strings)

Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ar/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.6% (33 of 1240 strings)

feat(lang): added translation using Weblate (Finnish)

Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Serbian)

Currently translated at 50.8% (630 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hans/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>

* feat(lang): add lang config for Bulgarian, Finnish, Ukrainian, Indonesian, Slovak, Turkish and Maori (#3834)

* fix: correct deeplinks on iPad (#3883)

* feat(studios): add a24 to studios list (#3902)

* docs: add demrich as a contributor for code (#3906) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(watchlist): Cache watchlist requests with matching E-Tags (#3901)

* perf(watchlist): add E-Tag caching to Plex watchlist requests

* refactor(watchlist): increase frequency of watchlist requests

* fix: sync watchlist every 3 min instead of 3 sec

* docs: add maxnatamo as a contributor for code (#3907) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(plex): refresh token schedule (#3875)

* feat: refresh token schedule

fix #3861

* fix(i18n): add i18n message

* refactor(plextv): use randomUUID crypto instead custom function

* docs: add DamsDev1 as a contributor for code (#3924) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: correct icon showing on certain phones when not pulled (#3939)

* feat: add support for requesting "Specials" for TV Shows (#3724)

* feat: add support for requesting "Specials" for TV Shows

This commit is responsible for adding support in Overseerr for requesting "Special" episodes for TV
Shows. This request has become especially pertinent when you consider shows like "Doctor Who". These
shows have Specials that are critical to understanding the plot of a TV show.

fix #779

* chore(yarn.lock): undo inappropriate changes to yarn.lock

I was informed by @sct in a comment on the #3724 PR that it was not appropriate to commit the
changes that ended up being made to the yarn.lock file. This commit is responsible, then, for
undoing the changes to the yarn.lock file that ended up being submitted.

* refactor: change loose equality to strict equality

I received a comment from OwsleyJr pointing out that we are using loose equality when we could
alternatively just be using strict equality to increase the robustness of our code. This commit
does exactly that by squashing out previous usages of loose equality in my commits and replacing
them with strict equality

* refactor: move 'Specials' string to a global message

Owsley pointed out that we are redefining the 'Specials' string multiple times throughout this PR.
Instead, we can just move it as a global message. This commit does exactly that. It squashes out and
previous declarations of the 'Specials' string inside the src files, and moves it directly to the
global messages file.

* docs: add AhmedNSidd as a contributor for code (#3964) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#3835)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.2% (1231 of 1240 strings)

Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Polish)

Currently translated at 98.8% (1227 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.9% (36 of 1240 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Albanian)

Currently translated at 95.8% (1189 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: W L <wl@mailhole.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sq/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Portugal))

Currently translated at 98.4% (1221 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_PT/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.9% (1239 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 98.2% (1219 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hant/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Norwegian Bokmål)

Currently translated at 89.9% (1115 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: exentler <gurandsrud@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nb_NO/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>

* feat(ui): prevent password manager interference & improve service links (#3989)

* docs: add s0up4200 as a contributor for code (#4047) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): update Plex Logo (#3955)

* docs: add JackW6809 as a contributor for code (#4048) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: requests/issues menu count (#3470)

* feat: request and issue count added to sidebar/mobile menu

* fix: added permission check for count visibility

* refactor: modified badge design for count

* fix: properly update issue and request counts in certain scenarios (#4051)

* fix: center count badge on sidebar and mobile menu (#4052)

* fix: request english trailers as a fallback when using other languages (#4009)

Co-authored-by: Stancu Florin <florin@stancu.me>

* docs: add StancuFlorin as a contributor for code (#4053) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: added the PWA badge indicator for requests pending (#3411)

refactor: removed unnecessary code when sending web push notification

fix: moved all notify user logic into webpush

refactor: n

refactor: remove all unnecessary prettier changes

fix: n

fix: n

fix: n

fix: n

fix: increment sw version

fix: n

* fix: improve count badge styling (#4056)

* fix: improved web push management (#3421)

refactor: organized placement of new button + added comments

fix: added api routes for push registration

fix: modified get request to confirm key identity

fix: added back notification types to always show

feat: added a manageable device list

refactor: modified device list to make it mobile friendly

fix: correct typo for enabling notifications

* Revert "fix: improved web push management (#3421)" (#4058)

* fix: manage webpush notifications (#4059)

* feat(lang): Translations update from Hosted Weblate (#4025)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rico <rico.jambor@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 40.8% (507 of 1240 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.9% (1239 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.7% (1237 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): added translation using Weblate (Slovenian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: sct <sctsnipe@gmail.com>

* fix: change localhost to process.env.HOST for client requests (#3839)

* Change localhost to process.env.HOST for client requests

* refactor: reformat

* docs: add lmiklosko as a contributor for code (#4063) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: set the correct TTL for the cookie store (#3946)

The time-to-live (TTL) of cookies stored in the database was incorrect because the connect-typeorm
library takes a TTL in seconds and not milliseconds, making cookies valid for ~82 years instead of
30 days.

Co-authored-by: Ryan Cohen <ryan@sct.dev>

* docs: add gauthier-th as a contributor for code (#4064) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: update migration script (#4065)

* fix: update migration script

fix: remove insert for new entities

* fix: correct migration name

* fix: correct name inside migration

* fix(servarr): merge series tags instead of overwriting them (#4019)

* Merge series tags instead of overwriting when adding a series that already exists

Currently, a request coming in for a series that already exists in sonarr nukes the tags in sonarr for the series in favor of the tags coming from overseerr. This change merges the two lists of tags and deduplicates them before sending them to sonarr.

* fix(servarr api): merge request media tags with servarr instead of overwriting

---------

Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>

* build(snap): update snap build actions

* build: temporarily disable snap builds (#4074)

* build: fix deploy docs action (#4076) [skip ci]

* fix: display request button when the show has requestable specials and is available (#4081)

* chore(deps): pin node.js (#4075)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(deps): pin dependencies (#4084)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#4060)

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1259 of 1259 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1258 of 1258 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: st7105 <st7105@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 50.6% (638 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.4% (509 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.3% (508 of 1259 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 94.2% (1187 of 1259 strings)

Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1259 of 1259 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 9.2% (117 of 1259 strings)

feat(lang): translated using Weblate (Finnish)

Currently translated at 8.6% (109 of 1259 strings)

Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>

* fix: correct specials affecting availability status (#4092)

* fix: remove specials affecting availability status

* refactor: add comments for scanner

* fix: prevent request badge showing when no related media (#4100)

* fix: availability sync requests (#3460)

* fix: modified media status handling when media has been deleted

fix: requests will now be updated to completed on scan

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: base scanner will set requests to completed correctly

fix: mark available button correctly sets requests as completed

fix: status will now stay deleted after declined request

refactor: request completion handling moved to entity

fix: prevented notifications from sending to old deleted requests

refactor: cleaned up code and added more detail to logs

refactor: updated to reflect latest availability sync changes

* fix: fetch requests only if necessary in db and remove unneeded code

* fix: update request button logic to accomodate specials

fix: remove completed filtering in tv details

* fix: correctly set seasons status when using the manual button

* refactor: improve reliability of season request completion

refactor: remove seasonrequest code

* fix: send notification for 4k movies

fix: same for shows

* feat: add completed filter to requests list

refactor: correct label

* fix: correct series setting to partially available (#4109)

* fix: correct edge case with deletion not updating requests (#4110)

* fix: correct notification sending for wrong status (#4113)

* fix(notifications): sending test-notifications for email now respects the allowSelfSigned value (#4112)

* docs: add vfaergestad as a contributor for code (#4114)

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: handle currently available non-completed media (#4115)

* fix: check media status has changed before modifying request

fix: refactor: code cleanup

* fix: manually load database entity seasons

* fix: handle partial seasons more reliably (#4116)

refactor: remove matchingOldSeason variable

* fix: pwa app badge (#4117)

* fix: clear app badge at zero without notification

* fix: correct users check sometimes failing when searching push subs

* fix: filter specials from modal all seasons and watchlist (#4108)

* fix: filter specials from modal all seasons and watchlist

* fix: skip specials when marking available

* fix: edge case where specials were marked as completed

* fix: bypass specials when partial requests is disabled (#4126)

* refactor(MediaRequest): consolidate lifecycle hooks into subscriber & restrict cascade to prevent recursion (#4124)

* fix(mediarequest entity): narrow cascade to insert & remove to prevent hook recursion

Restrict cascade options on the MediaRequest→Media relation to only `insert` and `remove`to avoid
nested subscriber/AfterUpdate recursion when saving entities.

* fix(mediarequest): move methods modifying MediaRequest to its Subscriber

* fix(mediasubscriber): use event.manager for parent media updates on remove

Replace `getRepository(Media)` calls with `event.manager` in the `afterRemove` hook so that
parent-media status resets run within the same transaction/QueryRunner (important for postgresql.
Doesnt affect sqlite).

* refactor(mediasubscriber): make afterInsert and afterUpdate async and await internal operations

This should prevent unhandled promise rejections and ensure sequential execution of lifecycle
actions

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>

* fix(mediaentity): change cascade from `update` to `remove` (#4135)

* fix(mediasubscriber): remove async from afterInsert and afterUpdate (#4136)

Asynchronous operations introduced in commit 3b9e195496c3db1f794549786b123a3ff55b08a0 caused issues
during media requests: the mediaId was not properly assigned and remained null.

---------

Co-authored-by: Isaac M <masesisaac@gmail.com>
Co-authored-by: Joseph Risk <j0srisk@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Loetwiek <79059734+Loetwiek@users.noreply.github.com>
Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>
Co-authored-by: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
Co-authored-by: Fuochi <ffuochi@hotmail.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Co-authored-by: Jordan Jones <me@jjones.tech>
Co-authored-by: Brandon Cohen <brandon@z3hn.dev>
Co-authored-by: David Emrich <demrich@me.com>
Co-authored-by: Max T. Kristiansen <me@maxtrier.dk>
Co-authored-by: Damien Fajole <60252259+DamsDev1@users.noreply.github.com>
Co-authored-by: Ahmed Siddiqui <36286128+AhmedNSidd@users.noreply.github.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>
Co-authored-by: soup <s0up4200@pm.me>
Co-authored-by: JackOXI <53652452+JackW6809@users.noreply.github.com>
Co-authored-by: Stancu Florin <StancuFlorin@users.noreply.github.com>
Co-authored-by: Stancu Florin <florin@stancu.me>
Co-authored-by: Brandon Cohen <cohbrandon@gmail.com>
Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Lukas Miklosko <44380311+lmiklosko@users.noreply.github.com>
Co-authored-by: Ryan Cohen <ryan@sct.dev>
Co-authored-by: Andrew Kennedy <andrew-kennedy@users.noreply.github.com>
Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Co-authored-by: vfaergestad <49147564+vfaergestad@users.noreply.github.com>
2025-05-10 01:14:36 +08:00
Gauthier
c067a03531 chore: merge upstream (#1652)
* feat(pushover): attach image to pushover notification payload (#3701)

* fix: api language query parameter (#3720)

* docs: add j0srisk as a contributor for code (#3745) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(tooltip): add tooltip to display exact time on date hover (#3773)

Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>

* docs: add Loetwiek as a contributor for code (#3776) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): ensure title fits into the `view collection` box (#3696)

* fix(docs): correct openapi docs minor issues (#3648)

* docs: add Fuochi as a contributor for doc (#3826)

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: translations update from Hosted Weblate (#3597)

* feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (1232 of 1234 strings)

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/da/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/el/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 99.5% (1234 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 37.1% (461 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 37.0% (459 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 34.8% (432 of 1240 strings)

Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 57.4% (712 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 13.2% (164 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 4.8% (60 of 1240 strings)

feat(lang): added translation using Weblate (Bulgarian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 97.9% (1215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 82.0% (1017 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 71.3% (885 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.9% (805 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.4% (799 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.8% (792 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.7% (791 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 57.5% (714 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 49.9% (619 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 32.1% (399 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 24.6% (306 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 18.9% (235 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.5% (217 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.3% (215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 8.0% (100 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 3.3% (41 of 1240 strings)

feat(lang): added translation using Weblate (Ukrainian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Czech)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Czech)

Currently translated at 99.6% (1236 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/cs/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Croatian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.6% (1236 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 97.5% (1210 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.5% (1185 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 94.3% (1166 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hungarian)

Currently translated at 91.3% (1133 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 89.3% (1108 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hebrew)

Currently translated at 13.9% (172 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: osh <osh@osh.cc>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/he/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Polish)

Currently translated at 99.1% (1225 of 1236 strings)

Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 92.8% (1148 of 1236 strings)

Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ar/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.6% (33 of 1240 strings)

feat(lang): added translation using Weblate (Finnish)

Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Serbian)

Currently translated at 50.8% (630 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hans/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>

* feat(lang): add lang config for Bulgarian, Finnish, Ukrainian, Indonesian, Slovak, Turkish and Maori (#3834)

* fix: correct deeplinks on iPad (#3883)

* feat(studios): add a24 to studios list (#3902)

* docs: add demrich as a contributor for code (#3906) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(watchlist): Cache watchlist requests with matching E-Tags (#3901)

* perf(watchlist): add E-Tag caching to Plex watchlist requests

* refactor(watchlist): increase frequency of watchlist requests

* fix: sync watchlist every 3 min instead of 3 sec

* docs: add maxnatamo as a contributor for code (#3907) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(plex): refresh token schedule (#3875)

* feat: refresh token schedule

fix #3861

* fix(i18n): add i18n message

* refactor(plextv): use randomUUID crypto instead custom function

* docs: add DamsDev1 as a contributor for code (#3924) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: correct icon showing on certain phones when not pulled (#3939)

* feat: add support for requesting "Specials" for TV Shows (#3724)

* feat: add support for requesting "Specials" for TV Shows

This commit is responsible for adding support in Overseerr for requesting "Special" episodes for TV
Shows. This request has become especially pertinent when you consider shows like "Doctor Who". These
shows have Specials that are critical to understanding the plot of a TV show.

fix #779

* chore(yarn.lock): undo inappropriate changes to yarn.lock

I was informed by @sct in a comment on the #3724 PR that it was not appropriate to commit the
changes that ended up being made to the yarn.lock file. This commit is responsible, then, for
undoing the changes to the yarn.lock file that ended up being submitted.

* refactor: change loose equality to strict equality

I received a comment from OwsleyJr pointing out that we are using loose equality when we could
alternatively just be using strict equality to increase the robustness of our code. This commit
does exactly that by squashing out previous usages of loose equality in my commits and replacing
them with strict equality

* refactor: move 'Specials' string to a global message

Owsley pointed out that we are redefining the 'Specials' string multiple times throughout this PR.
Instead, we can just move it as a global message. This commit does exactly that. It squashes out and
previous declarations of the 'Specials' string inside the src files, and moves it directly to the
global messages file.

* docs: add AhmedNSidd as a contributor for code (#3964) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#3835)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.2% (1231 of 1240 strings)

Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Polish)

Currently translated at 98.8% (1227 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.9% (36 of 1240 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Albanian)

Currently translated at 95.8% (1189 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: W L <wl@mailhole.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sq/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Portugal))

Currently translated at 98.4% (1221 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_PT/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.9% (1239 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 98.2% (1219 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hant/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Norwegian Bokmål)

Currently translated at 89.9% (1115 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: exentler <gurandsrud@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nb_NO/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>

* feat(ui): prevent password manager interference & improve service links (#3989)

* docs: add s0up4200 as a contributor for code (#4047) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): update Plex Logo (#3955)

* docs: add JackW6809 as a contributor for code (#4048) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: requests/issues menu count (#3470)

* feat: request and issue count added to sidebar/mobile menu

* fix: added permission check for count visibility

* refactor: modified badge design for count

* fix: properly update issue and request counts in certain scenarios (#4051)

* fix: center count badge on sidebar and mobile menu (#4052)

* fix: request english trailers as a fallback when using other languages (#4009)

Co-authored-by: Stancu Florin <florin@stancu.me>

* docs: add StancuFlorin as a contributor for code (#4053) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: added the PWA badge indicator for requests pending (#3411)

refactor: removed unnecessary code when sending web push notification

fix: moved all notify user logic into webpush

refactor: n

refactor: remove all unnecessary prettier changes

fix: n

fix: n

fix: n

fix: n

fix: increment sw version

fix: n

* fix: improve count badge styling (#4056)

* fix: improved web push management (#3421)

refactor: organized placement of new button + added comments

fix: added api routes for push registration

fix: modified get request to confirm key identity

fix: added back notification types to always show

feat: added a manageable device list

refactor: modified device list to make it mobile friendly

fix: correct typo for enabling notifications

* Revert "fix: improved web push management (#3421)" (#4058)

* fix: manage webpush notifications (#4059)

* feat(lang): Translations update from Hosted Weblate (#4025)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rico <rico.jambor@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 40.8% (507 of 1240 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.9% (1239 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.7% (1237 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): added translation using Weblate (Slovenian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: sct <sctsnipe@gmail.com>

* fix: change localhost to process.env.HOST for client requests (#3839)

* Change localhost to process.env.HOST for client requests

* refactor: reformat

* docs: add lmiklosko as a contributor for code (#4063) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: set the correct TTL for the cookie store (#3946)

The time-to-live (TTL) of cookies stored in the database was incorrect because the connect-typeorm
library takes a TTL in seconds and not milliseconds, making cookies valid for ~82 years instead of
30 days.

Co-authored-by: Ryan Cohen <ryan@sct.dev>

* docs: add gauthier-th as a contributor for code (#4064) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: update migration script (#4065)

* fix: update migration script

fix: remove insert for new entities

* fix: correct migration name

* fix: correct name inside migration

* fix(servarr): merge series tags instead of overwriting them (#4019)

* Merge series tags instead of overwriting when adding a series that already exists

Currently, a request coming in for a series that already exists in sonarr nukes the tags in sonarr for the series in favor of the tags coming from overseerr. This change merges the two lists of tags and deduplicates them before sending them to sonarr.

* fix(servarr api): merge request media tags with servarr instead of overwriting

---------

Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>

* build(snap): update snap build actions

* build: temporarily disable snap builds (#4074)

* build: fix deploy docs action (#4076) [skip ci]

* fix: display request button when the show has requestable specials and is available (#4081)

* chore(deps): pin node.js (#4075)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(deps): pin dependencies (#4084)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#4060)

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1259 of 1259 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1258 of 1258 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: st7105 <st7105@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 50.6% (638 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.4% (509 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.3% (508 of 1259 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 94.2% (1187 of 1259 strings)

Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1259 of 1259 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 9.2% (117 of 1259 strings)

feat(lang): translated using Weblate (Finnish)

Currently translated at 8.6% (109 of 1259 strings)

Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>

* fix: correct specials affecting availability status (#4092)

* fix: remove specials affecting availability status

* refactor: add comments for scanner

* fix: prevent request badge showing when no related media (#4100)

* fix: availability sync requests (#3460)

* fix: modified media status handling when media has been deleted

fix: requests will now be updated to completed on scan

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: base scanner will set requests to completed correctly

fix: mark available button correctly sets requests as completed

fix: status will now stay deleted after declined request

refactor: request completion handling moved to entity

fix: prevented notifications from sending to old deleted requests

refactor: cleaned up code and added more detail to logs

refactor: updated to reflect latest availability sync changes

* fix: fetch requests only if necessary in db and remove unneeded code

* fix: update request button logic to accomodate specials

fix: remove completed filtering in tv details

* fix: correctly set seasons status when using the manual button

* refactor: improve reliability of season request completion

refactor: remove seasonrequest code

* fix: send notification for 4k movies

fix: same for shows

* feat: add completed filter to requests list

refactor: correct label

* fix: correct series setting to partially available (#4109)

* fix: correct edge case with deletion not updating requests (#4110)

* fix: correct notification sending for wrong status (#4113)

* fix(notifications): sending test-notifications for email now respects the allowSelfSigned value (#4112)

* docs: add vfaergestad as a contributor for code (#4114)

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: handle currently available non-completed media (#4115)

* fix: check media status has changed before modifying request

fix: refactor: code cleanup

* fix: manually load database entity seasons

* fix: handle partial seasons more reliably (#4116)

refactor: remove matchingOldSeason variable

* fix: pwa app badge (#4117)

* fix: clear app badge at zero without notification

* fix: correct users check sometimes failing when searching push subs

* fix: filter specials from modal all seasons and watchlist (#4108)

* fix: filter specials from modal all seasons and watchlist

* fix: skip specials when marking available

* fix: edge case where specials were marked as completed

* fix: bypass specials when partial requests is disabled (#4126)

* refactor(MediaRequest): consolidate lifecycle hooks into subscriber & restrict cascade to prevent recursion (#4124)

* fix(mediarequest entity): narrow cascade to insert & remove to prevent hook recursion

Restrict cascade options on the MediaRequest→Media relation to only `insert` and `remove`to avoid
nested subscriber/AfterUpdate recursion when saving entities.

* fix(mediarequest): move methods modifying MediaRequest to its Subscriber

* fix(mediasubscriber): use event.manager for parent media updates on remove

Replace `getRepository(Media)` calls with `event.manager` in the `afterRemove` hook so that
parent-media status resets run within the same transaction/QueryRunner (important for postgresql.
Doesnt affect sqlite).

* refactor(mediasubscriber): make afterInsert and afterUpdate async and await internal operations

This should prevent unhandled promise rejections and ensure sequential execution of lifecycle
actions

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>

* fix(mediaentity): change cascade from `update` to `remove` (#4135)

---------

Co-authored-by: Isaac M <masesisaac@gmail.com>
Co-authored-by: Joseph Risk <j0srisk@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Loetwiek <79059734+Loetwiek@users.noreply.github.com>
Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>
Co-authored-by: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
Co-authored-by: Fuochi <ffuochi@hotmail.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Co-authored-by: Jordan Jones <me@jjones.tech>
Co-authored-by: Brandon Cohen <brandon@z3hn.dev>
Co-authored-by: David Emrich <demrich@me.com>
Co-authored-by: Max T. Kristiansen <me@maxtrier.dk>
Co-authored-by: Damien Fajole <60252259+DamsDev1@users.noreply.github.com>
Co-authored-by: Ahmed Siddiqui <36286128+AhmedNSidd@users.noreply.github.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>
Co-authored-by: soup <s0up4200@pm.me>
Co-authored-by: JackOXI <53652452+JackW6809@users.noreply.github.com>
Co-authored-by: Stancu Florin <StancuFlorin@users.noreply.github.com>
Co-authored-by: Stancu Florin <florin@stancu.me>
Co-authored-by: Brandon Cohen <cohbrandon@gmail.com>
Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Lukas Miklosko <44380311+lmiklosko@users.noreply.github.com>
Co-authored-by: Ryan Cohen <ryan@sct.dev>
Co-authored-by: Andrew Kennedy <andrew-kennedy@users.noreply.github.com>
Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Co-authored-by: vfaergestad <49147564+vfaergestad@users.noreply.github.com>
2025-05-09 23:39:55 +08:00
Gauthier
437bf0f4ee refactor(url validation): replace regex-based URL validation by the JavaScript URL constructor (#1650)
Replaced regex-based URL validation with the native JavaScript URL constructor to improve
reliability. This approach should be more robust and should help prevent bugs like the one we
previously encountered with malformed regex.

fix #1539
2025-05-09 13:15:18 +02:00
Gauthier
45f25408c6 fix(usediscover hook): detect end of pagination when totalSize is a multiple of pageSize (#1649)
Fixes a crash on the `/discover/watchlist` page that occurred when the number of items was exactly a
multiple of the page size (e.g., 80, 100, 120). The issue was caused by incorrect end-of-pagination
detection, leading to infinite data fetching. This update adjusts the `isReachingEnd` condition to
correctly handle these edge cases by checking if `totalResults` is less than or equal to the
expected total based on `size * pageSize`.

fix #1623
2025-05-09 13:15:05 +02:00
Gauthier
123894b475 fix(ui): correct seasons badge order (#1648)
This PR corrects the order of the seasons displayed on the request card, because it was not always
ordered if the pending request was edited with random clicks.
2025-05-09 13:14:50 +02:00
0xsysr3ll
6b9aedb970 fix(requestlist): remove unnecessary semicolon (#1647) 2025-05-09 15:11:16 +08:00
Gauthier
1651725665 docs: remove obsolete JELLYFIN_TYPE mentions (#1646) 2025-05-09 01:00:03 +08:00
allcontributors[bot]
cf9c33d124 docs: add 0xSysR3ll as a contributor for code (#1645)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-05-08 07:06:45 +08:00
0xsysr3ll
e8f1edc062 feat(requestlist): add requests list media type filtering (#1511)
* feat: add requests list media type filtering

* chore: some better indent

* fix(lint): missing break statements before case

* fix: yet another lint issue

* fix(lint): yet another lint issue

* Revert "fix(lint): yet another lint issue"

This reverts commit 24c3f90ed0.

* fix: lint issues
2025-05-07 22:41:06 +08:00
Danish Humair
d01f9a0580 feat: allow changing YouTube host for trailers (#643)
* feat(server settings, movie/tv/settings components): allow changing YouTube URL for trailers

* fix: add i18n messages

* fix(i18n): remove unwanted translation change

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2025-05-07 16:32:15 +02:00
allcontributors[bot]
c55da3da5f docs: add joelowrance as a contributor for code (#1643)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-05-07 02:06:04 +08:00
Joe Lowrance
a19dcaf5e5 feat: filter by media type on PersonDetails (#1566)
* feat: add person media type filtering

* feat: adjust filter to apply to cast and crew

* fix: fix layout issue

re #1513

* feat: revert unused server side api changes

* feat: move media type filtering to client side

Updates person details page to filter cast and crew sections by selected media type

re #1513
2025-05-07 02:04:53 +08:00
allcontributors[bot]
1870e637e4 docs: add JamsRepos as a contributor for code (#1642)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-05-07 02:02:27 +08:00
Jam
185167a0a7 feat(blacklist): hide blacklisted items from discover pages for admins (#1601)
* feat(blacklist): add 'Hide Blacklisted Items' setting to general settings and UI

* feat(migration): add HideBlacklistedItems migration for PostgreSQL and SQLite

* feat(settings): add hideBlacklisted option to application settings

* feat(settings): add tooltips for hideAvailable and hideBlacklisted options in settings

* chore(migration): remove HideBlacklistedItems migration files for PostgreSQL and SQLite

* docs(settings): clarify description of 'Hide Blacklisted Items' setting to specify it affects all users

* docs(settings): update tooltip and description for 'Hide Blacklisted Items' to clarify it applies to all users, including administrators

* docs(settings): clarify 'Hide Blacklisted Items' functionality to specify it applies only to administrators with the "Manage Blacklist" permission

* fix(hooks): update permission check for 'Hide Blacklisted Items' to include 'Manage Blacklist'

* fix(settings): update tooltip for 'Hide Blacklisted Items' to clarify it applies to all users with the "Manage Blacklist" permission

* feat(settings): add experimental badge to settings tooltip for 'Hide Available' option
2025-05-07 02:01:23 +08:00
allcontributors[bot]
2e4d14698f docs: add DillionLowry as a contributor for code (#1641)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-05-07 01:57:26 +08:00
Dillion
149d79e540 feat: add content certification/age-rating filter (#1418)
* feat(api): add TMDB certifications endpoint and discover certification params

re #501

* feat(discover): add certification/age-rating filter to movies and series

Add generic and US-only certification selector components, update Discover FilterSlideover, add
certification options to query constants

re #501

* fix(certificationselector): fix linter warning from useEffect missing dependency

* fix(jellyseerr-api.yml): prettier formatting

* chore(translation keys): run pnpm i18n:extract

* fix(certificationselector): change query destructure to Zod omit, fix translations, fix formatting

* style: fix whitespace with prettier
2025-05-07 01:55:02 +08:00
allcontributors[bot]
e5b77b2688 docs: add Schrottfresser as a contributor for code (#1640)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-05-07 01:36:56 +08:00
Schrottfresser
fc4db7fa00 feat(ntfy): add native ntfy notification support (#1599)
* feat(ntfy): add native ntfy notification

fix #499

* feat(ntfy): update translation keys

* feat(ntfy): append ntfy to cypress settings

* feat(ntfy): adjust ntfy agent shouldSend

* feat(ntfy): simplify ntfy post routes

* feat(ntfy): refactor ntfy agent from fetch to axios

* feat(ntfy): refactor ntfy frontend from fetch to axios
2025-05-07 01:30:32 +08:00
Gauthier
48dea32bd0 style(readme): fix merge issue with contributors (#1639)
* style(readme): fix merge issue with contributors

* style(readme): remove duplicate contributor
2025-05-06 18:44:22 +02:00
Gauthier
806cd9013a chore: merge upstream (#1631)
* feat(pushover): attach image to pushover notification payload (#3701)

* fix: api language query parameter (#3720)

* docs: add j0srisk as a contributor for code (#3745) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(tooltip): add tooltip to display exact time on date hover (#3773)

Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>

* docs: add Loetwiek as a contributor for code (#3776) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): ensure title fits into the `view collection` box (#3696)

* fix(docs): correct openapi docs minor issues (#3648)

* docs: add Fuochi as a contributor for doc (#3826)

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: translations update from Hosted Weblate (#3597)

* feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (1232 of 1234 strings)

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/da/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/el/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 99.5% (1234 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 37.1% (461 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 37.0% (459 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 34.8% (432 of 1240 strings)

Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 57.4% (712 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 13.2% (164 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 4.8% (60 of 1240 strings)

feat(lang): added translation using Weblate (Bulgarian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 97.9% (1215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 82.0% (1017 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 71.3% (885 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.9% (805 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.4% (799 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.8% (792 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.7% (791 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 57.5% (714 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 49.9% (619 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 32.1% (399 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 24.6% (306 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 18.9% (235 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.5% (217 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.3% (215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 8.0% (100 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 3.3% (41 of 1240 strings)

feat(lang): added translation using Weblate (Ukrainian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Czech)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Czech)

Currently translated at 99.6% (1236 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/cs/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Croatian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.6% (1236 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 97.5% (1210 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.5% (1185 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 94.3% (1166 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hungarian)

Currently translated at 91.3% (1133 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 89.3% (1108 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hebrew)

Currently translated at 13.9% (172 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: osh <osh@osh.cc>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/he/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Polish)

Currently translated at 99.1% (1225 of 1236 strings)

Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 92.8% (1148 of 1236 strings)

Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ar/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.6% (33 of 1240 strings)

feat(lang): added translation using Weblate (Finnish)

Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Serbian)

Currently translated at 50.8% (630 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hans/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>

* feat(lang): add lang config for Bulgarian, Finnish, Ukrainian, Indonesian, Slovak, Turkish and Maori (#3834)

* fix: correct deeplinks on iPad (#3883)

* feat(studios): add a24 to studios list (#3902)

* docs: add demrich as a contributor for code (#3906) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(watchlist): Cache watchlist requests with matching E-Tags (#3901)

* perf(watchlist): add E-Tag caching to Plex watchlist requests

* refactor(watchlist): increase frequency of watchlist requests

* fix: sync watchlist every 3 min instead of 3 sec

* docs: add maxnatamo as a contributor for code (#3907) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(plex): refresh token schedule (#3875)

* feat: refresh token schedule

fix #3861

* fix(i18n): add i18n message

* refactor(plextv): use randomUUID crypto instead custom function

* docs: add DamsDev1 as a contributor for code (#3924) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: correct icon showing on certain phones when not pulled (#3939)

* feat: add support for requesting "Specials" for TV Shows (#3724)

* feat: add support for requesting "Specials" for TV Shows

This commit is responsible for adding support in Overseerr for requesting "Special" episodes for TV
Shows. This request has become especially pertinent when you consider shows like "Doctor Who". These
shows have Specials that are critical to understanding the plot of a TV show.

fix #779

* chore(yarn.lock): undo inappropriate changes to yarn.lock

I was informed by @sct in a comment on the #3724 PR that it was not appropriate to commit the
changes that ended up being made to the yarn.lock file. This commit is responsible, then, for
undoing the changes to the yarn.lock file that ended up being submitted.

* refactor: change loose equality to strict equality

I received a comment from OwsleyJr pointing out that we are using loose equality when we could
alternatively just be using strict equality to increase the robustness of our code. This commit
does exactly that by squashing out previous usages of loose equality in my commits and replacing
them with strict equality

* refactor: move 'Specials' string to a global message

Owsley pointed out that we are redefining the 'Specials' string multiple times throughout this PR.
Instead, we can just move it as a global message. This commit does exactly that. It squashes out and
previous declarations of the 'Specials' string inside the src files, and moves it directly to the
global messages file.

* docs: add AhmedNSidd as a contributor for code (#3964) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#3835)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.2% (1231 of 1240 strings)

Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Polish)

Currently translated at 98.8% (1227 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.9% (36 of 1240 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Albanian)

Currently translated at 95.8% (1189 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: W L <wl@mailhole.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sq/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Portugal))

Currently translated at 98.4% (1221 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_PT/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.9% (1239 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 98.2% (1219 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hant/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Norwegian Bokmål)

Currently translated at 89.9% (1115 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: exentler <gurandsrud@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nb_NO/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>

* feat(ui): prevent password manager interference & improve service links (#3989)

* docs: add s0up4200 as a contributor for code (#4047) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): update Plex Logo (#3955)

* docs: add JackW6809 as a contributor for code (#4048) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: requests/issues menu count (#3470)

* feat: request and issue count added to sidebar/mobile menu

* fix: added permission check for count visibility

* refactor: modified badge design for count

* fix: properly update issue and request counts in certain scenarios (#4051)

* fix: center count badge on sidebar and mobile menu (#4052)

* fix: request english trailers as a fallback when using other languages (#4009)

Co-authored-by: Stancu Florin <florin@stancu.me>

* docs: add StancuFlorin as a contributor for code (#4053) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: added the PWA badge indicator for requests pending (#3411)

refactor: removed unnecessary code when sending web push notification

fix: moved all notify user logic into webpush

refactor: n

refactor: remove all unnecessary prettier changes

fix: n

fix: n

fix: n

fix: n

fix: increment sw version

fix: n

* fix: improve count badge styling (#4056)

* fix: improved web push management (#3421)

refactor: organized placement of new button + added comments

fix: added api routes for push registration

fix: modified get request to confirm key identity

fix: added back notification types to always show

feat: added a manageable device list

refactor: modified device list to make it mobile friendly

fix: correct typo for enabling notifications

* Revert "fix: improved web push management (#3421)" (#4058)

* fix: manage webpush notifications (#4059)

* feat(lang): Translations update from Hosted Weblate (#4025)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rico <rico.jambor@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 40.8% (507 of 1240 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.9% (1239 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.7% (1237 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): added translation using Weblate (Slovenian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: sct <sctsnipe@gmail.com>

* fix: change localhost to process.env.HOST for client requests (#3839)

* Change localhost to process.env.HOST for client requests

* refactor: reformat

* docs: add lmiklosko as a contributor for code (#4063) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: set the correct TTL for the cookie store (#3946)

The time-to-live (TTL) of cookies stored in the database was incorrect because the connect-typeorm
library takes a TTL in seconds and not milliseconds, making cookies valid for ~82 years instead of
30 days.

Co-authored-by: Ryan Cohen <ryan@sct.dev>

* docs: add gauthier-th as a contributor for code (#4064) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: update migration script (#4065)

* fix: update migration script

fix: remove insert for new entities

* fix: correct migration name

* fix: correct name inside migration

* fix(servarr): merge series tags instead of overwriting them (#4019)

* Merge series tags instead of overwriting when adding a series that already exists

Currently, a request coming in for a series that already exists in sonarr nukes the tags in sonarr for the series in favor of the tags coming from overseerr. This change merges the two lists of tags and deduplicates them before sending them to sonarr.

* fix(servarr api): merge request media tags with servarr instead of overwriting

---------

Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>

* build(snap): update snap build actions

* build: temporarily disable snap builds (#4074)

* build: fix deploy docs action (#4076) [skip ci]

* fix: display request button when the show has requestable specials and is available (#4081)

* chore(deps): pin node.js (#4075)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(deps): pin dependencies (#4084)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#4060)

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1259 of 1259 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1258 of 1258 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: st7105 <st7105@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 50.6% (638 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.4% (509 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.3% (508 of 1259 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 94.2% (1187 of 1259 strings)

Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1259 of 1259 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 9.2% (117 of 1259 strings)

feat(lang): translated using Weblate (Finnish)

Currently translated at 8.6% (109 of 1259 strings)

Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>

* fix: correct specials affecting availability status (#4092)

* fix: remove specials affecting availability status

* refactor: add comments for scanner

* fix: prevent request badge showing when no related media (#4100)

* fix: availability sync requests (#3460)

* fix: modified media status handling when media has been deleted

fix: requests will now be updated to completed on scan

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: base scanner will set requests to completed correctly

fix: mark available button correctly sets requests as completed

fix: status will now stay deleted after declined request

refactor: request completion handling moved to entity

fix: prevented notifications from sending to old deleted requests

refactor: cleaned up code and added more detail to logs

refactor: updated to reflect latest availability sync changes

* fix: fetch requests only if necessary in db and remove unneeded code

* fix: update request button logic to accomodate specials

fix: remove completed filtering in tv details

* fix: correctly set seasons status when using the manual button

* refactor: improve reliability of season request completion

refactor: remove seasonrequest code

* fix: send notification for 4k movies

fix: same for shows

* feat: add completed filter to requests list

refactor: correct label

* fix: correct series setting to partially available (#4109)

* fix: correct edge case with deletion not updating requests (#4110)

* fix: correct notification sending for wrong status (#4113)

* fix(notifications): sending test-notifications for email now respects the allowSelfSigned value (#4112)

* docs: add vfaergestad as a contributor for code (#4114)

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: handle currently available non-completed media (#4115)

* fix: check media status has changed before modifying request

fix: refactor: code cleanup

* fix: manually load database entity seasons

* fix: handle partial seasons more reliably (#4116)

refactor: remove matchingOldSeason variable

* fix: pwa app badge (#4117)

* fix: clear app badge at zero without notification

* fix: correct users check sometimes failing when searching push subs

* fix: filter specials from modal all seasons and watchlist (#4108)

* fix: filter specials from modal all seasons and watchlist

* fix: skip specials when marking available

* fix: edge case where specials were marked as completed

* fix: bypass specials when partial requests is disabled (#4126)

* refactor(MediaRequest): consolidate lifecycle hooks into subscriber & restrict cascade to prevent recursion (#4124)

* fix(mediarequest entity): narrow cascade to insert & remove to prevent hook recursion

Restrict cascade options on the MediaRequest→Media relation to only `insert` and `remove`to avoid
nested subscriber/AfterUpdate recursion when saving entities.

* fix(mediarequest): move methods modifying MediaRequest to its Subscriber

* fix(mediasubscriber): use event.manager for parent media updates on remove

Replace `getRepository(Media)` calls with `event.manager` in the `afterRemove` hook so that
parent-media status resets run within the same transaction/QueryRunner (important for postgresql.
Doesnt affect sqlite).

* refactor(mediasubscriber): make afterInsert and afterUpdate async and await internal operations

This should prevent unhandled promise rejections and ensure sequential execution of lifecycle
actions

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>

* fix: add missing translations

* fix: remove useless changes

---------

Co-authored-by: Isaac M <masesisaac@gmail.com>
Co-authored-by: Joseph Risk <j0srisk@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Loetwiek <79059734+Loetwiek@users.noreply.github.com>
Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>
Co-authored-by: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
Co-authored-by: Fuochi <ffuochi@hotmail.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Co-authored-by: Jordan Jones <me@jjones.tech>
Co-authored-by: Brandon Cohen <brandon@z3hn.dev>
Co-authored-by: David Emrich <demrich@me.com>
Co-authored-by: Max T. Kristiansen <me@maxtrier.dk>
Co-authored-by: Damien Fajole <60252259+DamsDev1@users.noreply.github.com>
Co-authored-by: Ahmed Siddiqui <36286128+AhmedNSidd@users.noreply.github.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>
Co-authored-by: soup <s0up4200@pm.me>
Co-authored-by: JackOXI <53652452+JackW6809@users.noreply.github.com>
Co-authored-by: Stancu Florin <StancuFlorin@users.noreply.github.com>
Co-authored-by: Stancu Florin <florin@stancu.me>
Co-authored-by: Brandon Cohen <cohbrandon@gmail.com>
Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Lukas Miklosko <44380311+lmiklosko@users.noreply.github.com>
Co-authored-by: Ryan Cohen <ryan@sct.dev>
Co-authored-by: Andrew Kennedy <andrew-kennedy@users.noreply.github.com>
Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Co-authored-by: vfaergestad <49147564+vfaergestad@users.noreply.github.com>
2025-05-06 17:57:33 +02:00
wolffman122
8a42fe16b5 feat(issuecomment): fix translation issue (#1635)
Fix the `Save Changes` and `Cancel` buttons so that their text will now translate

fix #1604
2025-05-06 13:49:17 +02:00
allcontributors[bot]
236d431fa3 docs: add wolffman122 as a contributor for code (#1632)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-05-06 02:17:38 +08:00
wolffman122
5fd65eb1ba fix(pushover notificatons): the sound setting will now be stored correctly (#1630)
fix #1614
2025-05-05 20:13:46 +02:00
Damien Guihal
c3b8574515 feat: make chart probes configurable (#1574)
* feat: make chart probes configurable

Allow to configure liveness/readiness probes + Add optional startup probe

* fix: pR fixes and cleanups

Fixes and cleanup after first review

* fix: push updated chart Readme

push updated chart Readme (with version update)

* refactor: refactor probe configuration

Refactor liveness and readiness probe configuration so they can't be removed

* docs: update readme

update readme
2025-04-30 17:11:44 +08:00
Gauthier
7c2444a65f chore: merge upstream (#1592)
* feat(pushover): attach image to pushover notification payload (#3701)

* fix: api language query parameter (#3720)

* docs: add j0srisk as a contributor for code (#3745) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(tooltip): add tooltip to display exact time on date hover (#3773)

Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>

* docs: add Loetwiek as a contributor for code (#3776) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): ensure title fits into the `view collection` box (#3696)

* fix(docs): correct openapi docs minor issues (#3648)

* docs: add Fuochi as a contributor for doc (#3826)

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: translations update from Hosted Weblate (#3597)

* feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (1232 of 1234 strings)

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/da/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/el/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 99.5% (1234 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 37.1% (461 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 37.0% (459 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 34.8% (432 of 1240 strings)

Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 57.4% (712 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 13.2% (164 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 4.8% (60 of 1240 strings)

feat(lang): added translation using Weblate (Bulgarian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 97.9% (1215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 82.0% (1017 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 71.3% (885 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.9% (805 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.4% (799 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.8% (792 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.7% (791 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 57.5% (714 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 49.9% (619 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 32.1% (399 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 24.6% (306 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 18.9% (235 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.5% (217 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.3% (215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 8.0% (100 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 3.3% (41 of 1240 strings)

feat(lang): added translation using Weblate (Ukrainian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Czech)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Czech)

Currently translated at 99.6% (1236 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/cs/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Croatian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.6% (1236 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 97.5% (1210 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.5% (1185 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 94.3% (1166 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hungarian)

Currently translated at 91.3% (1133 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 89.3% (1108 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hebrew)

Currently translated at 13.9% (172 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: osh <osh@osh.cc>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/he/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Polish)

Currently translated at 99.1% (1225 of 1236 strings)

Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 92.8% (1148 of 1236 strings)

Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ar/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.6% (33 of 1240 strings)

feat(lang): added translation using Weblate (Finnish)

Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Serbian)

Currently translated at 50.8% (630 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hans/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>

* feat(lang): add lang config for Bulgarian, Finnish, Ukrainian, Indonesian, Slovak, Turkish and Maori (#3834)

* fix: correct deeplinks on iPad (#3883)

* feat(studios): add a24 to studios list (#3902)

* docs: add demrich as a contributor for code (#3906) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(watchlist): Cache watchlist requests with matching E-Tags (#3901)

* perf(watchlist): add E-Tag caching to Plex watchlist requests

* refactor(watchlist): increase frequency of watchlist requests

* fix: sync watchlist every 3 min instead of 3 sec

* docs: add maxnatamo as a contributor for code (#3907) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(plex): refresh token schedule (#3875)

* feat: refresh token schedule

fix #3861

* fix(i18n): add i18n message

* refactor(plextv): use randomUUID crypto instead custom function

* docs: add DamsDev1 as a contributor for code (#3924) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: correct icon showing on certain phones when not pulled (#3939)

* feat: add support for requesting "Specials" for TV Shows (#3724)

* feat: add support for requesting "Specials" for TV Shows

This commit is responsible for adding support in Overseerr for requesting "Special" episodes for TV
Shows. This request has become especially pertinent when you consider shows like "Doctor Who". These
shows have Specials that are critical to understanding the plot of a TV show.

fix #779

* chore(yarn.lock): undo inappropriate changes to yarn.lock

I was informed by @sct in a comment on the #3724 PR that it was not appropriate to commit the
changes that ended up being made to the yarn.lock file. This commit is responsible, then, for
undoing the changes to the yarn.lock file that ended up being submitted.

* refactor: change loose equality to strict equality

I received a comment from OwsleyJr pointing out that we are using loose equality when we could
alternatively just be using strict equality to increase the robustness of our code. This commit
does exactly that by squashing out previous usages of loose equality in my commits and replacing
them with strict equality

* refactor: move 'Specials' string to a global message

Owsley pointed out that we are redefining the 'Specials' string multiple times throughout this PR.
Instead, we can just move it as a global message. This commit does exactly that. It squashes out and
previous declarations of the 'Specials' string inside the src files, and moves it directly to the
global messages file.

* docs: add AhmedNSidd as a contributor for code (#3964) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#3835)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.2% (1231 of 1240 strings)

Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Polish)

Currently translated at 98.8% (1227 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.9% (36 of 1240 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Albanian)

Currently translated at 95.8% (1189 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: W L <wl@mailhole.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sq/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Portugal))

Currently translated at 98.4% (1221 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_PT/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.9% (1239 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 98.2% (1219 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hant/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Norwegian Bokmål)

Currently translated at 89.9% (1115 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: exentler <gurandsrud@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nb_NO/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>

* feat(ui): prevent password manager interference & improve service links (#3989)

* docs: add s0up4200 as a contributor for code (#4047) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): update Plex Logo (#3955)

* docs: add JackW6809 as a contributor for code (#4048) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: requests/issues menu count (#3470)

* feat: request and issue count added to sidebar/mobile menu

* fix: added permission check for count visibility

* refactor: modified badge design for count

* fix: properly update issue and request counts in certain scenarios (#4051)

* fix: center count badge on sidebar and mobile menu (#4052)

* fix: request english trailers as a fallback when using other languages (#4009)

Co-authored-by: Stancu Florin <florin@stancu.me>

* docs: add StancuFlorin as a contributor for code (#4053) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: added the PWA badge indicator for requests pending (#3411)

refactor: removed unnecessary code when sending web push notification

fix: moved all notify user logic into webpush

refactor: n

refactor: remove all unnecessary prettier changes

fix: n

fix: n

fix: n

fix: n

fix: increment sw version

fix: n

* fix: improve count badge styling (#4056)

* fix: improved web push management (#3421)

refactor: organized placement of new button + added comments

fix: added api routes for push registration

fix: modified get request to confirm key identity

fix: added back notification types to always show

feat: added a manageable device list

refactor: modified device list to make it mobile friendly

fix: correct typo for enabling notifications

* Revert "fix: improved web push management (#3421)" (#4058)

* fix: manage webpush notifications (#4059)

* feat(lang): Translations update from Hosted Weblate (#4025)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rico <rico.jambor@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 40.8% (507 of 1240 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.9% (1239 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.7% (1237 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): added translation using Weblate (Slovenian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: sct <sctsnipe@gmail.com>

* fix: change localhost to process.env.HOST for client requests (#3839)

* Change localhost to process.env.HOST for client requests

* refactor: reformat

* docs: add lmiklosko as a contributor for code (#4063) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: set the correct TTL for the cookie store (#3946)

The time-to-live (TTL) of cookies stored in the database was incorrect because the connect-typeorm
library takes a TTL in seconds and not milliseconds, making cookies valid for ~82 years instead of
30 days.

Co-authored-by: Ryan Cohen <ryan@sct.dev>

* docs: add gauthier-th as a contributor for code (#4064) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: update migration script (#4065)

* fix: update migration script

fix: remove insert for new entities

* fix: correct migration name

* fix: correct name inside migration

* fix(servarr): merge series tags instead of overwriting them (#4019)

* Merge series tags instead of overwriting when adding a series that already exists

Currently, a request coming in for a series that already exists in sonarr nukes the tags in sonarr for the series in favor of the tags coming from overseerr. This change merges the two lists of tags and deduplicates them before sending them to sonarr.

* fix(servarr api): merge request media tags with servarr instead of overwriting

---------

Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>

* build(snap): update snap build actions

* build: temporarily disable snap builds (#4074)

* build: fix deploy docs action (#4076) [skip ci]

* fix: display request button when the show has requestable specials and is available (#4081)

* chore(deps): pin node.js (#4075)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix(deps): pin dependencies (#4084)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#4060)

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1259 of 1259 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1258 of 1258 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: st7105 <st7105@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 50.6% (638 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.4% (509 of 1259 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 40.3% (508 of 1259 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 94.2% (1187 of 1259 strings)

Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1259 of 1259 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 9.2% (117 of 1259 strings)

feat(lang): translated using Weblate (Finnish)

Currently translated at 8.6% (109 of 1259 strings)

Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>

* fix: correct specials affecting availability status (#4092)

* fix: remove specials affecting availability status

* refactor: add comments for scanner

* fix: prevent request badge showing when no related media (#4100)

* fix: availability sync requests (#3460)

* fix: modified media status handling when media has been deleted

fix: requests will now be updated to completed on scan

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: modified components to display deleted as a status

fix: corrected media status switching away from deleted

fix: base scanner will set requests to completed correctly

fix: mark available button correctly sets requests as completed

fix: status will now stay deleted after declined request

refactor: request completion handling moved to entity

fix: prevented notifications from sending to old deleted requests

refactor: cleaned up code and added more detail to logs

refactor: updated to reflect latest availability sync changes

* fix: fetch requests only if necessary in db and remove unneeded code

* fix: update request button logic to accomodate specials

fix: remove completed filtering in tv details

* fix: correctly set seasons status when using the manual button

* refactor: improve reliability of season request completion

refactor: remove seasonrequest code

* fix: send notification for 4k movies

fix: same for shows

* feat: add completed filter to requests list

refactor: correct label

* fix: correct series setting to partially available (#4109)

* fix: correct edge case with deletion not updating requests (#4110)

* fix: correct notification sending for wrong status (#4113)

* fix: add missing translations

* fix: update lockfile

* fix(notifications): sending test-notifications for email now respects the allowSelfSigned value (#4112)

* docs: add vfaergestad as a contributor for code (#4114)

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: handle currently available non-completed media (#4115)

* fix: check media status has changed before modifying request

fix: refactor: code cleanup

* fix: manually load database entity seasons

* fix: handle partial seasons more reliably (#4116)

refactor: remove matchingOldSeason variable

* fix: pwa app badge (#4117)

* fix: clear app badge at zero without notification

* fix: correct users check sometimes failing when searching push subs

* fix: filter specials from modal all seasons and watchlist (#4108)

* fix: filter specials from modal all seasons and watchlist

* fix: skip specials when marking available

* fix: edge case where specials were marked as completed

* fix: add proper migrations

* fix: remove undesirable i18n changes

---------

Co-authored-by: Isaac M <masesisaac@gmail.com>
Co-authored-by: Joseph Risk <j0srisk@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Loetwiek <79059734+Loetwiek@users.noreply.github.com>
Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>
Co-authored-by: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
Co-authored-by: Fuochi <ffuochi@hotmail.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Co-authored-by: Jordan Jones <me@jjones.tech>
Co-authored-by: Brandon Cohen <brandon@z3hn.dev>
Co-authored-by: David Emrich <demrich@me.com>
Co-authored-by: Max T. Kristiansen <me@maxtrier.dk>
Co-authored-by: Damien Fajole <60252259+DamsDev1@users.noreply.github.com>
Co-authored-by: Ahmed Siddiqui <36286128+AhmedNSidd@users.noreply.github.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>
Co-authored-by: soup <s0up4200@pm.me>
Co-authored-by: JackOXI <53652452+JackW6809@users.noreply.github.com>
Co-authored-by: Stancu Florin <StancuFlorin@users.noreply.github.com>
Co-authored-by: Stancu Florin <florin@stancu.me>
Co-authored-by: Brandon Cohen <cohbrandon@gmail.com>
Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Lukas Miklosko <44380311+lmiklosko@users.noreply.github.com>
Co-authored-by: Ryan Cohen <ryan@sct.dev>
Co-authored-by: Andrew Kennedy <andrew-kennedy@users.noreply.github.com>
Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: st7105 <st7105@gmail.com>
Co-authored-by: danieledu007 <danielguillen274@gmail.com>
Co-authored-by: lolo <laurent.brelle@gmail.com>
Co-authored-by: Aleksi T <aleksi.tuhkanen@gmail.com>
Co-authored-by: rijohi <risto.hirvilammi@gmail.com>
Co-authored-by: vfaergestad <49147564+vfaergestad@users.noreply.github.com>
2025-04-29 17:25:36 +02:00
fallenbagel
355b76de5c fix(imagecache): fix avatar cache folder creation (#1581)
This fixes a regression caused by #1520 which broke the file extension detection thereby breaking
avatars
2025-04-12 02:24:13 +08:00
fallenbagel
b7b05d31a5 Fix episode images url not allowed (#1580)
* fix: fix url parameter not allowed

* fix: use cached image for episode images

* refactor: remove console logs
2025-04-12 01:08:01 +08:00
allcontributors[bot]
f3a895fa7d docs: add benbeauchamp7 as a contributor for code (#1579)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-04-11 22:49:26 +08:00
Ben Beauchamp
4a5ac3cc42 feat(blacklist): Automatically add media with blacklisted tags to the blacklist (#1306)
* feat(blacklist): add blacktag settings to main settings page

* feat(blacklist): create blacktag logic and infrastructure

* feat(blacklist): add scheduling for blacktags job

* feat(blacklist): create blacktag ui badge for blacklist

* docs(blacklist): document blacktags in using-jellyseerr

* fix(blacklist): batch blacklist and media db removes to avoid expression tree too large error

* feat(blacklist): allow easy import and export of blacktag configuration

* fix(settings): don't copy the API key every time you press enter on the main settings

* fix(blacklist): move filter inline with page title to match all the other pages

* feat(blacklist): allow filtering between manually blacklisted and automatically blacklisted entries

* docs(blacklist): reword blacktag documentation a little

* refactor(blacklist): remove blacktag settings from public settings interfaces

There's no reason for it to be there

* refactor(blacklist): remove unused variable from processResults in blacktagsProcessor

* refactor(blacklist): change all instances of blacktag to blacklistedTag and update doc to match

* docs(blacklist): update general documentation for blacklisted tag settings

* fix(blacklist): update setting use of "blacklisted tag" to match between modals

* perf(blacklist): remove media type constraint from existing blacklist entry query

Doesn't make sense to keep it because tmdbid has a unique constraint on it

* fix(blacklist): remove whitespace line causing prettier to fail in CI

* refactor(blacklist): swap out some != and == for !s and _s

* fix(blacklist): merge back CopyButton changes, disable button when there's nothing to copy

* refactor(blacklist): use axios instead of fetch for blacklisted tag queries

* style(blacklist): use templated axios types and remove redundant try-catches
2025-04-11 22:48:44 +08:00
Gauthier
a488f850f3 refactor: switch from Fetch API to Axios (#1520)
* refactor: switch from Fetch API to Axios

* fix: remove unwanted changes

* fix: rewrite error handling for Axios and remove IPv4 first setting

* style: run prettier

* style: run prettier

* fix: add back custom proxy agent

* fix: add back custom proxy agent

* fix: correct rebase issue

* fix: resolve review comments
2025-04-08 13:20:10 +02:00
Nathan Lemmon
21400cecdc feat(gotify): added priority input for gotify (#1410)
* feat(gotify notification): added priority input for gotify

Added priority field for gotify messages on the gotify settings page

issue 562

* feat(gotify notification): added requested changes

fixed json end of file new line, removed unused code, added default priority for previous
configurations

* feat(gotify notifcation): fixed cypress/config/settings.cypress.json

fixed cypress/config/settings.cypress.json

* Update cypress/config/settings.cypress.json

Removed extra line from settings.cypress.json

Co-authored-by: Gauthier <mail@gauthierth.fr>

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2025-04-06 16:49:43 +02:00
allcontributors[bot]
5a6ff61f64 docs: add corentinnormand as a contributor for code (#1559)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-04-05 01:42:28 +08:00
Corentin Normand
14ee52e93e feat(discord.ts): adds a link to the pending approval discord notification (#436)
Co-authored-by: Corentin Normand <corentin.normand@swan.io>
2025-04-05 01:41:54 +08:00
allcontributors[bot]
4cf799d6eb docs: add brotaxt as a contributor for code (#1558)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-04-05 01:32:02 +08:00
allcontributors[bot]
bea57c330a docs: add jessielw as a contributor for code (#1556)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-04-05 01:29:00 +08:00
Jessie Wilson
7d36dc182b feat: now uses markdown linebreaks instead of relying purely on newlines (#1514)
refactor: displayUrl now applies an ellipsis if the url is longer than 40 characters

Co-authored-by: jesterr0 <jlw_4049@proton.me>
2025-04-05 01:27:30 +08:00
DominicKo
5865478a3b rebased on latest development branch (#1482)
Co-authored-by: a17f885 <{ID}+{username}@users.noreply.github.com>
2025-04-05 01:26:32 +08:00
Ludovic Ortega
90c58de9b2 chore(helm): bump jellyseerr to 2.5.2 (#1551)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-04-04 06:38:48 +08:00
Gauthier
2f6be955b5 fix(job): rename Plex Sync to Jellyfin Sync (#1549)
Some logs for the Jellyfin scanners were labelled 'Plex Sync' instead of 'Jellyfin Sync', leading to
confusion
2025-04-03 18:15:39 +02:00
Kugelstift
85bbc85714 fix(auth): Bitwarden autofill fix on local/Jellyfin login (2) (#1487)
* Update JellyfinLogin.tsx

* Update LocalLogin.tsx

* Update index.tsx

* Update index.tsx

prettier

* Update JellyfinLogin.tsx

* Update LocalLogin.tsx

* Update index.tsx
2025-04-02 19:34:06 +08:00
Gauthier
8dc1d8196c fix: correct "Remove from *arr" button (#1544)
This PR fixes the "Delete from *arr" button in the request list. It checks from the API whether the
*arr server corresponding to the request still exists before displaying the remove button, and fixes
a cache removal issue that could cause problems when deleting recently added media. This PR also
reverts #1476, which introduced problems during removal.

fix #1494
2025-04-01 02:06:33 +08:00
Gauthier
63dc27d400 fix(job): handle media removal for 4k on the same server (#1543)
This PR fixes a bug where the avaibility sync job was not removing properly 4k items when the same
Radarr server was used for both non-4k and 4k media.
2025-03-31 10:40:30 +02:00
fallenbagel
29034b350d fix(avatar): fix avatar cache busting by using avatarVersion (#1537)
* fix(avatar): fix avatar cache busting by using avatarVersion

Previously, avatar caching did not update the avatar when the remote image changed. This commit adds
logic to check if the avatar was modified remotely by comparing aremote last-modified timestamp with
a locally stored version (avatarVersion). If a change is detected, the cache is cleared, a new image
is fetched, and avatarVersionis updated. Otherwise, the cached image is retained.

* chore(db): add db migrations

* refactor: refactor imagehelpers util to where its used

* refactor: remove remnants from previous cache busting versions
2025-03-28 06:02:34 +08:00
fallenbagel
7438042757 fix(jellyfin): ensure deviceID is never empty (#1538)
If the deviceID becomes an empty string, login fails since jellyfin
requires a non-null deviceID. This commit adds a fallback to guarantee
that deviceID is always set, preventing accidental lockout.
2025-03-28 05:21:47 +08:00
Gauthier
0b0b76e58c fix(migrations): add missing Postgres migration and fix SQLite migration (#1532)
This PR adds the missing migration for PostgreSQL and fix the migration for SQLite.

re #1466
2025-03-28 04:27:07 +08:00
Ludovic Ortega
a5cb505609 chore(docs): use ghcr.io registry instead of dockerhub (#1531)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-03-27 05:26:06 +08:00
fallenbagel
7cb127ec3f chore: fix linting and formatting issues (#1530) 2025-03-27 00:19:05 +08:00
Gauthier
1635932375 chore: merge upstream (#1466)
* feat(pushover): attach image to pushover notification payload (#3701)

* fix: api language query parameter (#3720)

* docs: add j0srisk as a contributor for code (#3745) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(tooltip): add tooltip to display exact time on date hover (#3773)

Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>

* docs: add Loetwiek as a contributor for code (#3776) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): ensure title fits into the `view collection` box (#3696)

* fix(docs): correct openapi docs minor issues (#3648)

* docs: add Fuochi as a contributor for doc (#3826)

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: translations update from Hosted Weblate (#3597)

* feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (1232 of 1234 strings)

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/da/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/el/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 99.5% (1234 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 37.1% (461 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 37.0% (459 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 34.8% (432 of 1240 strings)

Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 57.4% (712 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 13.2% (164 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 4.8% (60 of 1240 strings)

feat(lang): added translation using Weblate (Bulgarian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 97.9% (1215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 82.0% (1017 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 71.3% (885 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.9% (805 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.4% (799 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.8% (792 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.7% (791 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 57.5% (714 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 49.9% (619 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 32.1% (399 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 24.6% (306 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 18.9% (235 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.5% (217 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.3% (215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 8.0% (100 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 3.3% (41 of 1240 strings)

feat(lang): added translation using Weblate (Ukrainian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Czech)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Czech)

Currently translated at 99.6% (1236 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/cs/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Croatian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.6% (1236 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 97.5% (1210 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.5% (1185 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 94.3% (1166 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hungarian)

Currently translated at 91.3% (1133 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 89.3% (1108 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hebrew)

Currently translated at 13.9% (172 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: osh <osh@osh.cc>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/he/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Polish)

Currently translated at 99.1% (1225 of 1236 strings)

Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 92.8% (1148 of 1236 strings)

Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ar/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.6% (33 of 1240 strings)

feat(lang): added translation using Weblate (Finnish)

Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Serbian)

Currently translated at 50.8% (630 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hans/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>

* feat(lang): add lang config for Bulgarian, Finnish, Ukrainian, Indonesian, Slovak, Turkish and Maori (#3834)

* fix: correct deeplinks on iPad (#3883)

* feat(studios): add a24 to studios list (#3902)

* docs: add demrich as a contributor for code (#3906) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(watchlist): Cache watchlist requests with matching E-Tags (#3901)

* perf(watchlist): add E-Tag caching to Plex watchlist requests

* refactor(watchlist): increase frequency of watchlist requests

* fix: sync watchlist every 3 min instead of 3 sec

* docs: add maxnatamo as a contributor for code (#3907) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(plex): refresh token schedule (#3875)

* feat: refresh token schedule

fix #3861

* fix(i18n): add i18n message

* refactor(plextv): use randomUUID crypto instead custom function

* docs: add DamsDev1 as a contributor for code (#3924) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: correct icon showing on certain phones when not pulled (#3939)

* feat: add support for requesting "Specials" for TV Shows (#3724)

* feat: add support for requesting "Specials" for TV Shows

This commit is responsible for adding support in Overseerr for requesting "Special" episodes for TV
Shows. This request has become especially pertinent when you consider shows like "Doctor Who". These
shows have Specials that are critical to understanding the plot of a TV show.

fix #779

* chore(yarn.lock): undo inappropriate changes to yarn.lock

I was informed by @sct in a comment on the #3724 PR that it was not appropriate to commit the
changes that ended up being made to the yarn.lock file. This commit is responsible, then, for
undoing the changes to the yarn.lock file that ended up being submitted.

* refactor: change loose equality to strict equality

I received a comment from OwsleyJr pointing out that we are using loose equality when we could
alternatively just be using strict equality to increase the robustness of our code. This commit
does exactly that by squashing out previous usages of loose equality in my commits and replacing
them with strict equality

* refactor: move 'Specials' string to a global message

Owsley pointed out that we are redefining the 'Specials' string multiple times throughout this PR.
Instead, we can just move it as a global message. This commit does exactly that. It squashes out and
previous declarations of the 'Specials' string inside the src files, and moves it directly to the
global messages file.

* docs: add AhmedNSidd as a contributor for code (#3964) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#3835)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.2% (1231 of 1240 strings)

Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Polish)

Currently translated at 98.8% (1227 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.9% (36 of 1240 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Albanian)

Currently translated at 95.8% (1189 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: W L <wl@mailhole.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sq/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Portugal))

Currently translated at 98.4% (1221 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_PT/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.9% (1239 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 98.2% (1219 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hant/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Norwegian Bokmål)

Currently translated at 89.9% (1115 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: exentler <gurandsrud@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nb_NO/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>

* feat(ui): prevent password manager interference & improve service links (#3989)

* docs: add s0up4200 as a contributor for code (#4047) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): update Plex Logo (#3955)

* docs: add JackW6809 as a contributor for code (#4048) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: requests/issues menu count (#3470)

* feat: request and issue count added to sidebar/mobile menu

* fix: added permission check for count visibility

* refactor: modified badge design for count

* fix: properly update issue and request counts in certain scenarios (#4051)

* fix: center count badge on sidebar and mobile menu (#4052)

* fix: request english trailers as a fallback when using other languages (#4009)

Co-authored-by: Stancu Florin <florin@stancu.me>

* docs: add StancuFlorin as a contributor for code (#4053) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: added the PWA badge indicator for requests pending (#3411)

refactor: removed unnecessary code when sending web push notification

fix: moved all notify user logic into webpush

refactor: n

refactor: remove all unnecessary prettier changes

fix: n

fix: n

fix: n

fix: n

fix: increment sw version

fix: n

* fix: improve count badge styling (#4056)

* fix: improved web push management (#3421)

refactor: organized placement of new button + added comments

fix: added api routes for push registration

fix: modified get request to confirm key identity

fix: added back notification types to always show

feat: added a manageable device list

refactor: modified device list to make it mobile friendly

fix: correct typo for enabling notifications

* Revert "fix: improved web push management (#3421)" (#4058)

* fix: manage webpush notifications (#4059)

* feat(lang): Translations update from Hosted Weblate (#4025)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rico <rico.jambor@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 40.8% (507 of 1240 strings)

Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.9% (1239 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.7% (1237 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

feat(lang): translated using Weblate (Italian)

Currently translated at 95.3% (1182 of 1240 strings)

Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): added translation using Weblate (Slovenian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: sct <sctsnipe@gmail.com>

* fix: change localhost to process.env.HOST for client requests (#3839)

* Change localhost to process.env.HOST for client requests

* refactor: reformat

* docs: add lmiklosko as a contributor for code (#4063) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: set the correct TTL for the cookie store (#3946)

The time-to-live (TTL) of cookies stored in the database was incorrect because the connect-typeorm
library takes a TTL in seconds and not milliseconds, making cookies valid for ~82 years instead of
30 days.

Co-authored-by: Ryan Cohen <ryan@sct.dev>

* docs: add gauthier-th as a contributor for code (#4064) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: update migration script (#4065)

* fix: update migration script

fix: remove insert for new entities

* fix: correct migration name

* fix: correct name inside migration

* fix(servarr): merge series tags instead of overwriting them (#4019)

* Merge series tags instead of overwriting when adding a series that already exists

Currently, a request coming in for a series that already exists in sonarr nukes the tags in sonarr for the series in favor of the tags coming from overseerr. This change merges the two lists of tags and deduplicates them before sending them to sonarr.

* fix(servarr api): merge request media tags with servarr instead of overwriting

---------

Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>

---------

Co-authored-by: Isaac M <masesisaac@gmail.com>
Co-authored-by: Joseph Risk <j0srisk@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Loetwiek <79059734+Loetwiek@users.noreply.github.com>
Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>
Co-authored-by: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
Co-authored-by: Fuochi <ffuochi@hotmail.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Co-authored-by: Jordan Jones <me@jjones.tech>
Co-authored-by: Brandon Cohen <brandon@z3hn.dev>
Co-authored-by: David Emrich <demrich@me.com>
Co-authored-by: Max T. Kristiansen <me@maxtrier.dk>
Co-authored-by: Damien Fajole <60252259+DamsDev1@users.noreply.github.com>
Co-authored-by: Ahmed Siddiqui <36286128+AhmedNSidd@users.noreply.github.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>
Co-authored-by: soup <s0up4200@pm.me>
Co-authored-by: JackOXI <53652452+JackW6809@users.noreply.github.com>
Co-authored-by: Stancu Florin <StancuFlorin@users.noreply.github.com>
Co-authored-by: Stancu Florin <florin@stancu.me>
Co-authored-by: Brandon Cohen <cohbrandon@gmail.com>
Co-authored-by: Felipe Garcia <garcia.o.felipe@gmail.com>
Co-authored-by: Rico <rico.jambor@gmail.com>
Co-authored-by: George L <lazugeorgem@gmail.com>
Co-authored-by: Yaroslav Buzko <yaroslav@buzko.com>
Co-authored-by: ugyes <ferenc.bodi@live.com>
Co-authored-by: Alberto Giardino <alberto.giardino@al-ce.it>
Co-authored-by: Lukas Miklosko <44380311+lmiklosko@users.noreply.github.com>
Co-authored-by: Ryan Cohen <ryan@sct.dev>
Co-authored-by: Andrew Kennedy <andrew-kennedy@users.noreply.github.com>
Co-authored-by: Danshil Kokil Mungur <me@danshilm.com>
2025-03-24 23:45:33 +08:00
fallenbagel
c1aeab9538 chore: update nextjs to 14.2.25 (#1521)
This updates nextjs to fix a security vulnerability.

fixes #1516
2025-03-24 23:14:59 +08:00
alorente
70fb1f2b00 ci: Add OCI Meta information to docker image (#1460)
* Add build version and date to docker build args

* Add OCI Meta information to Dockerfile

* Update ci.yml
2025-03-24 23:12:36 +08:00
0xsysr3ll
4cd02babba fix(ui): handle import-from-plex response as array (#1510) 2025-03-24 23:11:35 +08:00
Gauthier
f5b3a526cb fix(ui): resolve discover language dropdown overlap (#1497)
The discover language selection field is always in the foreground and overlaps other open dropdowns.

fix #1475
2025-03-18 20:47:08 +01:00
Nicolaj Vinholt
e5ab847547 fix(helm): apply annotations to pvc (#1489) 2025-03-17 16:32:17 +01:00
Ludovic Ortega
40539cc4b1 chore(helm): bump jellyseerr to 2.5.1 (#1488)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-03-17 14:59:56 +01:00
Ludovic Ortega
0bd6d57834 docs(helm): add contributing guidelines for helm chart (#1486)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-03-17 10:50:08 +01:00
Gauthier
f884ac9c66 fix(ui): correct seasons badge order (#1485)
This PR corrects the order of the seasons displayed on the request card, because it was not always
ordered.
2025-03-17 06:24:28 +08:00
Gauthier
c2d9d00b41 fix(mediarequest): correct download sync for Radarr (#1484)
This PR fixes a bug introduced by #1376, where `radarrSettings` was incorrectly replaced by
`radarrMovie`.
2025-03-16 22:44:25 +01:00
Gauthier
77a36f9714 fix(job): resolve edge case issue with season availability updates (#1483)
Ensure media availability updates correctly for shows marked as UNKNOWN and yet having AVAILABLE or
PARTIALLY_AVAILABLE seasons
2025-03-16 21:57:14 +01:00
Gauthier
f773e0fb2a fix: check if the file still exists in the service before deleting (#1476)
This PR add a check to verify if the item to be deleted inside the *arr service still exists before
actually sending the delete request.
2025-03-15 22:42:17 +01:00
Gauthier
767a24164d fix(ui): resolve streaming region dropdown overlap (#1477)
The streaming region selection field is always in the foreground and overlaps other open dropdowns.

fix #1475
2025-03-15 23:35:23 +08:00
fallenbagel
8394eb5ad4 revert(airdate): reverts airdate offset & changes relative time to only display date (not time) (#1467)
* revert(airdate): reverts airdate offset and changes relative time to only display date (not time)

This reverts #1390 as it created more confusion when we offsetted the air date in relevance to the
timezone. It also changes the relative time to use date instead of time (so it will say `aired
yesterday` `today` `5 days ago` instead of `aired x hours ago` since we dont really the airtime
data.

* fix: relate time in days instead of hours

* fix: relative time in days

* fix: relative time in days (but properly)
2025-03-14 20:49:54 +01:00
0xsysr3ll
b8425d6388 fix(smtp-notification-test): missing allowSelfSigned option in test function (#1461)
* fix(smtp-notification-test): missing allowSelfSigned option in test function

* fix: indent error
2025-03-13 19:52:30 +08:00
fallenbagel
ebb7f00305 docs: add more troubleshooting steps (#1468) 2025-03-13 09:22:24 +01:00
Ludovic Ortega
418d51590d chore(helm): upgrade jellyseerr app to 2.5.0 (#1464)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-03-13 05:20:19 +08:00
Gauthier
a6dd4a8fed fix(ui): move watch trailer button above the 4k request button (#1465)
Fix a z-index issue with the "Watch Trailer" button being under the "Request in 4k" button

fix #1462
2025-03-13 05:13:00 +08:00
Gauthier
4d1163c343 fix(blacklist): add back the blacklist button on TitleCard for Plex (#1463)
The PR #1398 introduced an issue where the blacklist button was not visible anymore on the
TitleCards for Plex. This PR fixes it.
2025-03-12 21:05:16 +01:00
Kugelstift
b085e12ff9 fix(auth): Bitwarden autofill fix on local/Jellyfin login (#1459)
* Update LocalLogin.tsx

remove data-bwignore="false" from attributes to let Bitwarden Autofill

* Update JellyfinLogin.tsx

remove data-bwignore="false" from attributes to let Bitwarden Autofill
2025-03-12 18:20:33 +08:00
Gauthier
33e7a153aa fix(requestlist): hide the remove from *arr button when no service exists (#1457)
This PR hide the "Remove from *arr" button in the request list when the service of the request
doesn't exist anymore.

fix #1449
2025-03-12 15:28:31 +08:00
Gauthier
9891a7577c fix(proxy): update http proxy to accept bypass list with undici v7 (#1456)
With the update of undici to v7, the bypass list of addresses (no_proxy addresses) was not ignored
anymore.

fix #1454
2025-03-12 15:25:54 +08:00
Ludovic Ortega
077e355c77 feat(helm): upgrade jellyseerr to 2.4.0 (#1438)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-03-11 09:33:58 +08:00
fallenbagel
21ab20bba9 revert: reverts csrf-csrf back to csurf (#1442)
* revert: reverts csrf-csrf back to csurf

This reverts csrf-csrf change brought on by `9e3119` in #1393 back to `csurf` that is maintained

* fix: type declarations for csurf
2025-03-11 09:33:40 +08:00
Mihkel
cdfb30ea16 docs: update steps for service installation with NSSM (#1446) 2025-03-11 07:48:43 +08:00
Gauthier
771ecdf781 fix(ui): correct media action icon size (#1444)
This PR fixes an UI issue with inconsistent size for media action icons.

fix #1440
2025-03-11 00:08:49 +01:00
fallenbagel
863b675c77 ci(cypress): always run the upload video files step (#1445) 2025-03-11 07:06:56 +08:00
Gauthier
5b998bef82 fix(users): correct user list for Postgres (#1443)
PostgreSQL requires that the ORDER BY expression must appear in the SELECT list when using DISTINCT.
Since we were using a computed expression in the ORDER BY clause, we need to include it in the
SELECT list as well.

re #1333
2025-03-10 23:59:42 +01:00
fallenbagel
0113612ced chore(i18n): merge weblate translations (#1437)
* Translated using Weblate (Korean)
Currently translated at 91.8% (1225 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ko/

* Translated using Weblate (Chinese (Simplified))
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/zh_Hans/

* Translated using Weblate (Ukrainian)
Currently translated at 96.1% (1282 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Italian)
Currently translated at 84.4% (1127 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/it/

* Translated using Weblate (Japanese)
Currently translated at 48.4% (646 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ja/

* Translated using Weblate (Spanish)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/es/

* Translated using Weblate (Croatian)
Currently translated at 91.1% (1216 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/hr/

* Translated using Weblate (Arabic)
Currently translated at 91.0% (1215 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ar/

* Translated using Weblate (Norwegian Bokmål)
Currently translated at 80.0% (1068 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nb_NO/

* Translated using Weblate (Danish)
Currently translated at 91.1% (1216 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/da/

* Translated using Weblate (Catalan)
Currently translated at 90.7% (1211 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ca/

* Translated using Weblate (Turkish)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Greek)
Currently translated at 91.3% (1218 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/el/

* Translated using Weblate (Chinese (Traditional))
Currently translated at 89.5% (1194 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/zh_Hant/

* Translated using Weblate (Swedish)
Currently translated at 96.1% (1282 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Polish)
Currently translated at 91.0% (1214 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Romanian)
Currently translated at 32.6% (435 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ro/

* Translated using Weblate (Albanian)
Currently translated at 76.3% (1018 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sq/

* Translated using Weblate (French)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Russian)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Lithuanian)
Currently translated at 54.1% (722 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/lt/

* Translated using Weblate (Dutch)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Hungarian)
Currently translated at 85.2% (1137 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/hu/

* Translated using Weblate (Portuguese (Portugal))
Currently translated at 89.9% (1200 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pt_PT/

* Translated using Weblate (Czech)
Currently translated at 91.4% (1220 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/cs/

* Translated using Weblate (Serbian)
Currently translated at 46.6% (622 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sr/

* Translated using Weblate (Portuguese (Brazil))
Currently translated at 92.5% (1234 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pt_BR/

* Translated using Weblate (Hebrew)
Currently translated at 25.7% (343 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/he/

* Translated using Weblate (German)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Hindi)
Currently translated at 10.7% (143 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/hi/

* Translated using Weblate (French)
Currently translated at 100.0% (1334 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Italian)
Currently translated at 94.3% (1259 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/it/

* Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/

* Translated using Weblate (Italian)
Currently translated at 94.4% (1260 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/it/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1334 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (German)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Spanish)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/es/

* Translated using Weblate (French)
Currently translated at 98.4% (1332 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Dutch)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Polish)
Currently translated at 89.5% (1212 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Russian)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Swedish)
Currently translated at 94.6% (1280 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Ukrainian)
Currently translated at 94.6% (1280 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Chinese (Simplified))
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/zh_Hans/

* Translated using Weblate (French)
Currently translated at 99.8% (1351 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Romanian)
Currently translated at 46.1% (624 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ro/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (German)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Russian)
Currently translated at 97.7% (1322 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.5% (1320 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pt_BR/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Swedish)
Currently translated at 95.4% (1291 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Polish)
Currently translated at 91.2% (1235 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Polish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (German)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Ukrainian)
Currently translated at 98.7% (1336 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/

* Translated using Weblate (Arabic)
Currently translated at 86.8% (1220 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ar/

* Translated using Weblate (French)
Currently translated at 96.2% (1353 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Finnish)
Currently translated at 17.2% (243 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fi/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (French)
Currently translated at 96.2% (1353 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (French)
Currently translated at 96.7% (1360 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Polish)
Currently translated at 97.8% (1375 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Ukrainian)
Currently translated at 96.8% (1361 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Added translation using Weblate (Basque)

* Translated using Weblate (Basque)
Currently translated at 16.7% (236 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Ukrainian)
Currently translated at 96.9% (1362 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Basque)
Currently translated at 18.0% (253 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (French)
Currently translated at 99.7% (1401 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (French)
Currently translated at 99.7% (1401 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Basque)
Currently translated at 30.1% (423 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Danish)
Currently translated at 86.7% (1219 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/da/

* Translated using Weblate (French)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (German)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (French)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Ukrainian)
Currently translated at 97.0% (1363 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Basque)
Currently translated at 30.1% (424 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Ukrainian)
Currently translated at 97.0% (1364 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Dutch)
Currently translated at 99.2% (1394 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Basque)
Currently translated at 30.3% (427 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (German)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Basque)
Currently translated at 31.1% (438 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (French)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Basque)
Currently translated at 33.0% (464 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Portuguese (Portugal))
Currently translated at 85.6% (1204 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pt_PT/

* Translated using Weblate (Basque)
Currently translated at 35.0% (493 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Basque)
Currently translated at 39.7% (558 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Basque)
Currently translated at 47.7% (671 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Basque)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* Translated using Weblate (Russian)
Currently translated at 95.1% (1337 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (French)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Czech)
Currently translated at 98.7% (1388 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/cs/

* Translated using Weblate (Czech)
Currently translated at 99.0% (1392 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/cs/

---------

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: jason54 <jason54700.jg@gmail.com>
Co-authored-by: Kristopher Roller <akjroller@gmail.com>
Co-authored-by: jellyseerr-weblate <155525085+jellyseerr-weblate@users.noreply.github.com>
Co-authored-by: N/A <me@puffin.icu>
Co-authored-by: pouley <pierre@bellemainp.fr>
Co-authored-by: Nuh uh <delayedartisticguppy@protonmail.com>
Co-authored-by: Gauthier <mail@gauthierth.fr>
Co-authored-by: madax <madax@users.noreply.jellyseerr.borgcube.de>
Co-authored-by: SoundwaveUwU <investing_squillitic@dojacat.ru>
Co-authored-by: Michel Heusschen <mh_jellyseerr@users.noreply.jellyseerr.borgcube.de>
Co-authored-by: Leo THIVILLON <leothivillon@gmail.com>
Co-authored-by: Uncle <Uncle-Tio@users.noreply.jellyseerr.borgcube.de>
Co-authored-by: Gökhan GÜRBÜZ <gkhn.gurbuz@hotmail.com>
Co-authored-by: Mattias Magnusson <mattish.91@gmail.com>
Co-authored-by: Radosław Adamczewski <radekadamczewski@gmail.com>
Co-authored-by: Alexander Mnich <alex@mnich.dev>
Co-authored-by: HanaO00 <greenmalkak@gmail.com>
Co-authored-by: michael <michaelvelosk@gmail.com>
Co-authored-by: Heni FAZZANI <heni.fazzani@gmail.com>
Co-authored-by: Matti Koponen <cshessu@gmail.com>
Co-authored-by: Gauvain Perchey <gauvain.perchey@gmail.com>
Co-authored-by: zulimazuli <zulimazuli@gmail.com>
Co-authored-by: Thadah <thadahdenyse+borgcube@protonmail.com>
Co-authored-by: Frank Jeager <frank.jeager76@gmail.com>
Co-authored-by: Mads K <madskelberg@tuta.com>
Co-authored-by: Bas <910100490+weblate@proton.me>
Co-authored-by: BlackSpirits <blackspirits@gmail.com>
Co-authored-by: Dennis van J <weblate@amsx.net>
Co-authored-by: Tomáš Holý <tmsholy@users.noreply.jellyseerr.borgcube.de>
2025-03-11 01:10:47 +08:00
allcontributors[bot]
f8c9689745 docs: add RankWeis as a contributor for code (#1434)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-03-09 22:40:22 +08:00
RankWeis
af8d6b475c fix(overriderules): allows every user to be added to the override rules (#1333)
* fix: allows every user to be added to the override rules

* chore: code cleanup

* fix(overriderules): displaying more than ten users at a time

* fix(overriderules): pageSize unaffected by duplicate includeIds

Co-authored-by: Gauthier <mail@gauthierth.fr>

* fix: allows every user to be added to the override rules

* chore(overriderules): readding override rules after rebase

* chore(overriderules): removing empty file

* chore(overriderules): fixing bad merge

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2025-03-09 15:37:47 +01:00
fallenbagel
dcc13080bc chore: update dependencies (#1393)
* chore: update sqlite3

* chore: update nextjs

* chore: update semver

* chore: update email-templates

* chore: update express and express-openapi-validator

* chore: override cross-spawn as the packages using it didnt update it

* chore: update undici

* feat: use csrf-csrf instead of deprecated csurf

* chore: override cookie

* chore: remove the overrides

* chore: update lockfile

* chore: revert cypress update

* chore: revert revert cypress update

* chore: update cypress

* ci(cypress): upload video artifacts for debugging

* chore(cypress): generate videos

* ci(cypress): remove unnecessary matrix.browser in the artifact name

* chore: update to es2021

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2025-03-08 02:45:14 +08:00
soup
e97a13e1e4 feat(ui): prevent password manager interference & improve service links (#1396)
* feat(ui): prevent password manager interference & improve service links (#3989)

(cherry picked from commit ef18b5d1de)

* feat(ui): prevent password manager autofill on Jellyfin setup form

* fix: rebase mess

* feat(ui): set data-form-type attribute

For Dashlane password manager

* feat(ui): add data attribs for dashlane

* feat(ui): set data-form-type to JellyfinLogin
2025-03-04 08:10:27 +08:00
Gauthier
1de518d915 fix(overriderules): correct disabled condition for override rule creation (#1419)
* fix(overriderules): correct disabled condition for override rule creation

* fix: remove useless console.log
2025-03-03 01:16:24 +01:00
Gauthier
4e44282387 fix(overriderules): enable override rules only when a service exists (#1417)
This PR disable the 'New Override Rule' button when no Radarr/Sonarr service exists.
2025-03-03 00:13:09 +01:00
Gauthier
67bd639a43 fix(emby): throw the right error message if no library exists (#1415)
This PR fixes a bug where the error message when no library exists was not displayed because of a
Jellyfin-specific check failing with Emby.
2025-03-02 23:46:31 +01:00
Gauthier
ada467ecf4 fix(settings): remove dns server option (#1416)
* fix(settings): remove dns server option

This PR removes the DNS Servers option added in #1266 because it doesn't seem to work reliably.

* style: remove whitespace change
2025-03-02 22:53:43 +01:00
fallenbagel
9cc6930fed fix(api): make item endpoints user-independent (#1413)
Fix Jellyfin/Emby item retrieval to work properly with api tokens by using user-independent item
endpoints. This will resolve the issue where disabled libraries for jellyseerr owner's would fail to
scan even when we migrated to API tokens due to using the user-dependent item view endpoints.
2025-03-03 05:45:59 +08:00
Gauthier
3b4d6bf5b8 chore: merge upstream (#1404)
* feat(pushover): attach image to pushover notification payload (#3701)

* fix: api language query parameter (#3720)

* docs: add j0srisk as a contributor for code (#3745) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(tooltip): add tooltip to display exact time on date hover (#3773)

Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>

* docs: add Loetwiek as a contributor for code (#3776) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): ensure title fits into the `view collection` box (#3696)

* fix(docs): correct openapi docs minor issues (#3648)

* docs: add Fuochi as a contributor for doc (#3826)

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: translations update from Hosted Weblate (#3597)

* feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (1232 of 1234 strings)

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_BR/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (German)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (Danish)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/da/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Greek)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/el/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 99.5% (1234 of 1240 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

feat(lang): translated using Weblate (Russian)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ru/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Romanian)

Currently translated at 37.1% (461 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 37.0% (459 of 1240 strings)

feat(lang): translated using Weblate (Romanian)

Currently translated at 34.8% (432 of 1240 strings)

Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ro/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 57.4% (712 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 13.2% (164 of 1240 strings)

feat(lang): translated using Weblate (Bulgarian)

Currently translated at 4.8% (60 of 1240 strings)

feat(lang): added translation using Weblate (Bulgarian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 97.9% (1215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 82.0% (1017 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 72.9% (905 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 71.3% (885 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.9% (805 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 64.4% (799 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.8% (792 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 63.7% (791 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 57.5% (714 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 49.9% (619 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 35.9% (446 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 32.1% (399 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 24.6% (306 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 18.9% (235 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.5% (217 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 17.3% (215 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 8.0% (100 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 3.3% (41 of 1240 strings)

feat(lang): added translation using Weblate (Ukrainian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Czech)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Czech)

Currently translated at 99.6% (1236 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/cs/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Croatian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.8% (1238 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.6% (1236 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.5% (1235 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 99.1% (1230 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 97.5% (1210 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.5% (1185 of 1240 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.6% (1182 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 95.2% (1177 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 94.3% (1166 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

feat(lang): translated using Weblate (Croatian)

Currently translated at 91.7% (1134 of 1236 strings)

Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hungarian)

Currently translated at 91.3% (1133 of 1240 strings)

feat(lang): translated using Weblate (Hungarian)

Currently translated at 89.3% (1108 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Hebrew)

Currently translated at 13.9% (172 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: osh <osh@osh.cc>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/he/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Polish)

Currently translated at 99.1% (1225 of 1236 strings)

Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Italian)

Currently translated at 92.8% (1148 of 1236 strings)

Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Arabic)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ar/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1236 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

feat(lang): translated using Weblate (French)

Currently translated at 99.9% (1235 of 1236 strings)

Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1236 of 1236 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.6% (33 of 1240 strings)

feat(lang): added translation using Weblate (Finnish)

Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: sct <sctsnipe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Serbian)

Currently translated at 50.8% (630 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sr/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (1234 of 1234 strings)

Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hans/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>

* feat(lang): add lang config for Bulgarian, Finnish, Ukrainian, Indonesian, Slovak, Turkish and Maori (#3834)

* fix: correct deeplinks on iPad (#3883)

* feat(studios): add a24 to studios list (#3902)

* docs: add demrich as a contributor for code (#3906) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(watchlist): Cache watchlist requests with matching E-Tags (#3901)

* perf(watchlist): add E-Tag caching to Plex watchlist requests

* refactor(watchlist): increase frequency of watchlist requests

* fix: sync watchlist every 3 min instead of 3 sec

* docs: add maxnatamo as a contributor for code (#3907) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(plex): refresh token schedule (#3875)

* feat: refresh token schedule

fix #3861

* fix(i18n): add i18n message

* refactor(plextv): use randomUUID crypto instead custom function

* docs: add DamsDev1 as a contributor for code (#3924) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix: correct icon showing on certain phones when not pulled (#3939)

* feat: add support for requesting "Specials" for TV Shows (#3724)

* feat: add support for requesting "Specials" for TV Shows

This commit is responsible for adding support in Overseerr for requesting "Special" episodes for TV
Shows. This request has become especially pertinent when you consider shows like "Doctor Who". These
shows have Specials that are critical to understanding the plot of a TV show.

fix #779

* chore(yarn.lock): undo inappropriate changes to yarn.lock

I was informed by @sct in a comment on the #3724 PR that it was not appropriate to commit the
changes that ended up being made to the yarn.lock file. This commit is responsible, then, for
undoing the changes to the yarn.lock file that ended up being submitted.

* refactor: change loose equality to strict equality

I received a comment from OwsleyJr pointing out that we are using loose equality when we could
alternatively just be using strict equality to increase the robustness of our code. This commit
does exactly that by squashing out previous usages of loose equality in my commits and replacing
them with strict equality

* refactor: move 'Specials' string to a global message

Owsley pointed out that we are redefining the 'Specials' string multiple times throughout this PR.
Instead, we can just move it as a global message. This commit does exactly that. It squashes out and
previous declarations of the 'Specials' string inside the src files, and moves it directly to the
global messages file.

* docs: add AhmedNSidd as a contributor for code (#3964) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat(lang): Translations update from Hosted Weblate (#3835)

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Bulgarian)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/bg/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Ukrainian)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/uk/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Catalan)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ca/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Hungarian)

Currently translated at 99.2% (1231 of 1240 strings)

Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/hu/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Polish)

Currently translated at 98.8% (1227 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Dutch)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nl/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Spanish)

Currently translated at 100.0% (1241 of 1241 strings)

Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (French)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

feat(lang): translated using Weblate (Swedish)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sv/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Finnish)

Currently translated at 2.9% (36 of 1240 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fi/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Albanian)

Currently translated at 95.8% (1189 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: W L <wl@mailhole.de>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/sq/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1241 of 1241 strings)

feat(lang): translated using Weblate (Korean)

Currently translated at 100.0% (1240 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/ko/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Portuguese (Portugal))

Currently translated at 98.4% (1221 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/pt_PT/
Translation: Overseerr/Overseerr Frontend

* feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.9% (1239 of 1240 strings)

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Chinese (Traditional Han script))

Currently translated at 98.2% (1219 of 1241 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: dtalens <databio@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/zh_Hant/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translation: Overseerr/Overseerr Frontend

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

feat(lang): translated using Weblate (Norwegian Bokmål)

Currently translated at 89.9% (1115 of 1240 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: exentler <gurandsrud@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/
Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/nb_NO/
Translation: Overseerr/Overseerr Frontend

---------

Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>

* feat(ui): prevent password manager interference & improve service links (#3989)

* docs: add s0up4200 as a contributor for code (#4047) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* fix(ui): update Plex Logo (#3955)

* docs: add JackW6809 as a contributor for code (#4048) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: requests/issues menu count (#3470)

* feat: request and issue count added to sidebar/mobile menu

* fix: added permission check for count visibility

* refactor: modified badge design for count

* fix: properly update issue and request counts in certain scenarios (#4051)

* fix: center count badge on sidebar and mobile menu (#4052)

* fix: request english trailers as a fallback when using other languages (#4009)

Co-authored-by: Stancu Florin <florin@stancu.me>

* docs: add StancuFlorin as a contributor for code (#4053) [skip ci]

* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>

* feat: added the PWA badge indicator for requests pending (#3411)

refactor: removed unnecessary code when sending web push notification

fix: moved all notify user logic into webpush

refactor: n

refactor: remove all unnecessary prettier changes

fix: n

fix: n

fix: n

fix: n

fix: increment sw version

fix: n

---------

Co-authored-by: Isaac M <masesisaac@gmail.com>
Co-authored-by: Joseph Risk <j0srisk@gmail.com>
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Loetwiek <79059734+Loetwiek@users.noreply.github.com>
Co-authored-by: Loetwiek <lodommerholtcm@gmail.com>
Co-authored-by: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
Co-authored-by: Fuochi <ffuochi@hotmail.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Cleiton Carvalho <cleitonsilvacarvalho@gmail.com>
Co-authored-by: Nandor Rusz <nandor.rusz@vodafone.de>
Co-authored-by: Thomas Schöneberg <ta.schoeneberg@gmail.com>
Co-authored-by: Anders Ecklon <aecklon@gmail.com>
Co-authored-by: Kenneth Hansen <erathor@live.dk>
Co-authored-by: BeardedWatermelon <BeardedWatermelon@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <SoundwaveUwU@users.noreply.hosted.weblate.org>
Co-authored-by: SoundwaveUwU <noreply@1000-7.space>
Co-authored-by: Димитър Мазнеков (Topper) <d.maznekov@gmail.com>
Co-authored-by: Кирилл Тюрин <1337soundwave1337@gmail.com>
Co-authored-by: Don Cezar <goldie.czr@gmail.com>
Co-authored-by: Dragos <themsk@yahoo.com>
Co-authored-by: Eduard Oancea <uberfly@420blaze.it>
Co-authored-by: sct <sctsnipe@gmail.com>
Co-authored-by: Michael Michael <michaelvelosk@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: Karel Krýda <karel.kryda@gmail.com>
Co-authored-by: Smexhy <roman.bartik@icloud.com>
Co-authored-by: Bruno Ševčenko <bs3vcenk@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: lpispek <lpispek@gmail.com>
Co-authored-by: Levente Szajkó <leviko112@gmail.com>
Co-authored-by: osh <osh@osh.cc>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Francesco <francy.ammirati@hotmail.com>
Co-authored-by: Fhd-pro <juve.11@msn.com>
Co-authored-by: Kobe <kobaubarr@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Baptiste <baptiste.nee@me.com>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Maxime Lafarie <maxime.lafarie@gmail.com>
Co-authored-by: Miguel <mig.mllr@gmail.com>
Co-authored-by: asurare <jonathan.biteau16@gmail.com>
Co-authored-by: Per Erik <urbanlolface@gmail.com>
Co-authored-by: Shjosan <shjosan@kakmix.co>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Eero Konttaniemi <eero.konttaniemi@gmail.com>
Co-authored-by: Milan Smudja <smudja@gmail.com>
Co-authored-by: Developer J <jshsakura@gmail.com>
Co-authored-by: Haohao Zhang <hyacz@foxmail.com>
Co-authored-by: lkw123 <lkw20010211@gmail.com>
Co-authored-by: Jordan Jones <me@jjones.tech>
Co-authored-by: Brandon Cohen <brandon@z3hn.dev>
Co-authored-by: David Emrich <demrich@me.com>
Co-authored-by: Max T. Kristiansen <me@maxtrier.dk>
Co-authored-by: Damien Fajole <60252259+DamsDev1@users.noreply.github.com>
Co-authored-by: Ahmed Siddiqui <36286128+AhmedNSidd@users.noreply.github.com>
Co-authored-by: Dargo <fuszi88@gmail.com>
Co-authored-by: senza <senza@users.noreply.hosted.weblate.org>
Co-authored-by: Robin Van de Vyvere <irazoxgames@gmail.com>
Co-authored-by: Frostar <dasangra@hotmail.com>
Co-authored-by: Nackophilz <zrv4flra@anonaddy.me>
Co-authored-by: TayZ3r <artimmo@hotmail.fr>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: W L <wl@mailhole.de>
Co-authored-by: Hyun Lee <hyun@yahoo.com>
Co-authored-by: cutiekeek <cutiekeek@gmail.com>
Co-authored-by: Rafael Souto <git@rafaelsouto.com>
Co-authored-by: Marc Lerno <mlerno1192@student.carlalbert.edu>
Co-authored-by: exentler <gurandsrud@gmail.com>
Co-authored-by: soup <s0up4200@pm.me>
Co-authored-by: JackOXI <53652452+JackW6809@users.noreply.github.com>
Co-authored-by: Stancu Florin <StancuFlorin@users.noreply.github.com>
Co-authored-by: Stancu Florin <florin@stancu.me>
Co-authored-by: Brandon Cohen <cohbrandon@gmail.com>
2025-02-27 19:13:14 +08:00
allcontributors[bot]
07e4662205 docs: add gauthier-th as a contributor for maintenance (#1408)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-02-27 16:40:13 +08:00
Gauthier
4eddbaa71b fix(watchlist): disable Jellyseerr's watchlist for Plex users (#1398)
This PR resolves a conflict between the Plex and Jellyseerr watchlists by deactivating the
Jellyseerr watchlist for Plex.

fix #1344
2025-02-26 10:47:11 +01:00
Gauthier
27112be933 refactor: rename some remaining Overseerr occurrences (#1397)
* refactor: rename some remaining Overseerr occurrences

This PR renames some remaining occurrences of Overseerr to Jellyseerr. This includes the OpenAPI
specification, log file names and some variables and console messages.

* fix(i18n): add missing translation
2025-02-26 13:08:00 +08:00
fallenbagel
a790b1abcc feat(airdatebadge): convert airDate from UTC to local timezone (#1390)
This PR will ensure that the airdate is in the user's local timezone so that its more user friendly and the relative time calculation would be consistent

fix #1373
2025-02-23 22:35:12 +01:00
Gauthier
f0a6055774 fix: add email requirement for local users (#1389)
* fix: add email requirement for local users

Because of a misunderstanding, and the requirement to have a mandatory email for local users was
removed, when it shouldn't have been.

re #900
fix #1367

* fix: add missing check for Emby
2025-02-23 11:25:25 +01:00
allcontributors[bot]
a3f4773a35 docs: add michaelhthomas as a contributor for code (#1388)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-02-23 00:42:33 +08:00
Michael Thomas
73d8efaa54 feat: revamp login page and support disabling media server login (#1286)
* feat: support disabling jellyfin login

* feat: revamp login screen

Update the login screen for better usability, especially with OpenID
Connect and Plex login, allowing one-click login and removing the
accordion layout. Additionally, ensures that media server login is
hidden when disabled in the settings.

* test: update cypress login command
2025-02-23 00:40:38 +08:00
Gauthier
9712f56054 fix: fix remove from *arr in item details (#1387)
Fix the "Remove From *arr" button in the slideover of the movie/series details page. The issue was
caused by an attempt to delete a file that didn't exist.
2025-02-23 00:18:27 +08:00
Gauthier
b1f07f0eb2 refactor(overriderules): move override rules out of the service modal (#1292)
* refactor(overriderules): move override rules out of the service modal

This PR moves override rules out of the service modal. This will make override rules more visible
than inside the service modal popup. This will also avoid having a modal inside a modal (override
rules modal inside of service modal)

* fix: resolve typing error
2025-02-23 00:17:19 +08:00
Michael Thomas
64f05bcad6 feat: add linked accounts page (#883)
* feat(linked-accounts): create page and display linked media server accounts

* feat(dropdown): add new shared Dropdown component

Adds a shared component for plain dropdown menus, based on the headlessui Menu component. Updates
the `ButtonWithDropdown` component to use the same inner components, ensuring that the only
difference between the two components is the trigger button, and both use the same components for
the actual dropdown menu.

* refactor(modal): add support for configuring button props

* feat(linked-accounts): add support for linking/unlinking jellyfin accounts

* feat(linked-accounts): support linking/unlinking plex accounts

* fix(linked-accounts): probibit unlinking accounts in certain cases

Prevents the primary administrator from unlinking their media server account (which would break
sync). Additionally, prevents users without a configured local email and password from unlinking
their accounts, which would render them unable to log in.

* feat(linked-accounts): support linking/unlinking emby accounts

* style(dropdown): improve style class application

* fix(server): improve error handling and API spec

* style(usersettings): improve syntax & performance of user password checks

* style(linkedaccounts): use applicationName in page description

* fix(linkedaccounts): resolve typo

* refactor(app): remove RequestError class
2025-02-23 00:16:25 +08:00
fallenbagel
80927b9705 fix(mediarequest): optimise more typeorm lifecycle triggers (#1376)
This is related to #1218. This should fix more typeorm lifcycle trigger issues

fix #513
2025-02-23 00:16:03 +08:00
Gauthier
d563b36186 fix: disable first page revalidation in useSWRInfinite (#1386)
By default, useSWRInfinite revalidates the first page every time a new page is loaded, resulting in
additional requests being sent. This PR disables this behavior.

fix #1380
2025-02-22 16:46:58 +01:00
Gauthier
117617188e feat(settings): add a disclaimer for dns servers and ipv4 first settings (#1375)
* feat(settings): add a disclaimer for dns servers and ipv4 first settings

This PR adds a disclaimer to warn the user that he should use the network settings of his
containers/system first instead of this one.

* fix: add missing translations

* feat: create a new Advanced Network Settings section

* Update src/components/Settings/SettingsNetwork/index.tsx

Co-authored-by: fallenbagel <98979876+fallenbagel@users.noreply.github.com>

* Update src/i18n/locale/en.json

Co-authored-by: fallenbagel <98979876+fallenbagel@users.noreply.github.com>

* fix: rename to Force IPv4 Resolution First

---------

Co-authored-by: fallenbagel <98979876+fallenbagel@users.noreply.github.com>
2025-02-22 16:46:47 +01:00
Gauthier
525a538f34 refactor(settings): move network settings to their own settings tab (#1287)
* refactor(settings): move network settings to their own settings tab

This PR moves the network settings out of the General Settings section to a new Netowrk Settings
tab.

* fix: add missing translations

* fix: fix cypress tests for network settings

* refactor: create a separate section for network settings
2025-02-20 18:27:18 +01:00
allcontributors[bot]
0d2273ff6e docs: add ishanjain28 as a contributor for code (#1369)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-02-18 05:00:10 +08:00
Ishan Jain
e035cd84ae fix: corrected spelling errors in function names (#1366) 2025-02-17 21:52:05 +01:00
Gauthier
438ccfe9c3 fix: assign the keep-alive value explicitly (#1368)
* fix: assign the keep-alive value explicitly

The Node.js documentation mentions that the default keep-alive value is not used when creating a
global agent manually, which is done in customProxyAgent.ts.

re #1365

* fix: typo
2025-02-18 03:48:37 +08:00
854562
c181cee328 feat: update Jellyfin logo (#1359)
* Replaced Jellyfin logo with new version

* Update jellyfin.svg
2025-02-16 11:37:59 +01:00
Gauthier
98a5b05816 ci: set the pnpm version number explicitly (#1357)
* ci: set the pnpm version number explicitly

pnpm latest version is now v10. We still use v9, and the latest version of pnpm was used in
Dockerfile instead of v9.

* ci: add missing pnpm v9
2025-02-14 17:21:08 +01:00
0xsysr3ll
b29959b063 fix: missing plex.tv url in images remotePatterns (#1356)
This fixes a 400 error while fetching user's avatar from plex api during user import.
2025-02-14 15:28:26 +01:00
Bryan J.
9a2c12e51c docs: update error message for various components (#1354) 2025-02-14 11:47:47 +01:00
Gauthier
620135aeac fix: resolve a vulnerability with admin token (#1345)
By default, the jellyfinAuthToken of every user was always retrieved from the database, and
sometimes sent back to the client. Any logged-in user could retrieve this token via a request
containing admin user information, and use it to gain full access to Jellyfin. This PR removes the
auth token and the device ID from the fields selected by default by TypeORM.
2025-02-10 00:17:11 +01:00
Gauthier
2dbd1096d2 fix: disallow admins to edit other admins in bulk edit (#1340)
This PR fixes a bug where admin users could edit the permissions of other admins in the bulk edit
modal.

fix #1309
2025-02-09 01:12:54 +08:00
Gauthier
24d3f523fc feat: add a robots.txt file (#1335)
This PR adds a `robots.txt` file to prevent crawlers to index the website

re #1323
2025-02-08 02:23:37 +08:00
Gauthier
2b7974fa06 fix(jobs): run plex/jellyfin jobs only for the relevant media server (#1331)
Due to merging issues with upstream, some jobs for the Plex media server where also running on
Jellyfin/Emby instances. This PR makes them run only when the media server is Plex.

fix #1329
2025-02-05 05:01:02 +08:00
Ben Haney
907ba6fdea feat(api): make rottentomatoes matching more robust (#1265) 2025-01-31 23:04:34 +08:00
fallenbagel
efaad21554 build: remove unnecessary files from final docker image (#1314)
* build: remove charts from final docker image

fix #1313

* build: remove docs too
2025-01-30 19:48:16 +08:00
Gauthier
6ab463285d fix(setup): resolve looping library validation error message (#1316)
This PR fixes a bug where the validation error message is displayed over and over because of a React
useEffect dependency issue. Previously, the `validateLibraries()` function was being called inside a
useEffect that depended on a state that this function was updating.
2025-01-30 11:22:23 +01:00
Ludovic Ortega
418f0c2eb8 fix(helm): no change, fixing OCI manifest corruption (#1310)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-01-27 15:49:24 +01:00
fallenbagel
002557d2d0 docs: changed the name to lowercase (#1296) 2025-01-21 17:20:33 +08:00
Ludovic Ortega
62c1a70b37 feat(helm): Add possibility to pass volumes and volume mounts (#1291)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-01-20 20:20:27 +08:00
allcontributors[bot]
1b325e7c32 docs: add andrewkolda as a contributor for design (#1293)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-01-20 06:41:25 +08:00
andrewkolda
f247642b76 fix: make watchlist buttons consistent (#1272)
fix #1270

Co-authored-by: andrewkolda <git@kolda.me>
2025-01-19 23:15:54 +01:00
Fallenbagel
396cd968ef ci: push individual arch digest only and merge from digest (#1284)
* ci: push individual arch digest only and merge from digest

* ci: correct syntax for docker manifest

* ci: add the missing id to the build step

* ci: set proper ids and output digest that is dependant on matrix.id

* ci: proper dynamic outputs by manually echoing it out

* ci: remove unnecessary test step
2025-01-19 03:41:25 +08:00
fallenbagel
ca739315b2 ci: remove cleanup steps since docker registry v2 doesnt support it 2025-01-18 22:28:58 +08:00
fallenbagel
9143a6c027 ci: push temp tags and create multi-arch from them and cleanup 2025-01-18 22:19:39 +08:00
fallenbagel
d7fc03650f ci: use direct docker manifest command to create and push manifest 2025-01-18 21:54:09 +08:00
fallenbagel
80fc5c1a78 ci: better manifest merging to only push final multi-arch manifest 2025-01-18 21:43:14 +08:00
fallenbagel
95737d36e6 ci: fix typo in create_manifest 2025-01-18 20:59:29 +08:00
fallenbagel
0fd6ca85a4 ci: fix missing version for create_manifest & discord notification after create_manifest 2025-01-18 20:53:09 +08:00
fallenbagel
7cee9b475d ci: fix multi-arch image creation workflow
use int128/docker-manifest-create-action to combine the images
2025-01-18 20:50:22 +08:00
fallenbagel
ff9af866f8 ci: use the proper action to merge manifests & pass in lowercase owner 2025-01-18 20:40:03 +08:00
fallenbagel
5ffe6419ee ci: remove sanitisation and hardcode platform tag depending on platform 2025-01-18 20:31:18 +08:00
fallenbagel
8afcf5a8d8 ci: attempt to sanitise the platfom and add to gh env 2025-01-18 20:25:06 +08:00
Fallenbagel
17d93a8cb9 ci: fix typo when passing sanitised platform to github env (#1282)
* ci: fix typo when passing sanitised platform to github env

* ci: hardcode a platform & owner for testing sanitation

* ci: fix typo

* ci: fix typo

* ci: fix yet another typo

* ci: fix yet another typo

* ci: another typo when echoing the tested variables fixed

* ci: properly echo the values from github env

* ci: attempt to echo out the sanitised variables

* ci: finalise the sanitation test and remove it from lint & test build
2025-01-18 20:23:03 +08:00
Fallenbagel
549082c53e ci: fix typo when sanitising platform (#1281) 2025-01-18 19:55:36 +08:00
Fallenbagel
fbef7e2c72 ci: seperate job to pass in sanitised platform (#1280)
This is done as github actions doesnt support inline replacement that was done on #1279
2025-01-18 19:49:58 +08:00
Fallenbagel
93d2e26ae9 ci: sanitise container tag (#1279)
* ci: sanitise container tag

Tags cant container `/` so this should sanitise them

* ci: use simple case owner name
2025-01-18 19:42:05 +08:00
Fallenbagel
f09a432635 ci: add a job to merge and create multi-arch image (#1278)
This has to be done now that arm64 and amd64 runs as two seperate jobs. Otherwise, whichever
finishes the last would override the other one when pushed
2025-01-18 19:34:36 +08:00
Fallenbagel
a8f84d4f74 ci: correct arm runner label (#1277)
The issue was all because of using the wrong label. 18 hours wasted waiting for a non-existent
runner to start. It is `ubuntu-24.04-arm`
https://github.com/orgs/community/discussions/148648#discussion-7793082
2025-01-18 19:07:45 +08:00
Fallenbagel
88e96fa163 ci: upgrade runner to ubuntu 24.04 to get arm64 runner working (#1276)
This is another attempt to get arm64 runner working by upgrading the runner to ubuntu-24-04, hoping it works better.

Related to #1275
2025-01-18 17:57:07 +08:00
Fallenbagel
2d814c1416 ci: attempt to fix arm64 runners with proper scoped caching (#1275)
Added platform specific cache scoping and turned off provenance to prevent manifest merging. In
addition we are now using ubuntu24.04 in an attempt to get the job to run as ubuntu-22.04 were
stalled for more than 18 hours.
2025-01-18 17:49:35 +08:00
Fallenbagel
2f4b848b2c ci: utilise the linux arm64 hosted runners (#1271)
* ci: utilise the linux arm64 hosted runners

This is an attempt to utilise the linux arm64 hosted runners which should reduce the build times
significantly. In addition, this should leverage the github's built-in caching.

* ci: fix typo
2025-01-18 05:14:33 +08:00
Ludovic Ortega
0ee3e69a61 feat: upgrade chart to 2.0.0 (#1268)
- upgrade jellyseerr to 2.3.0
- disable HPA as it's not documented and not useful
- migrate container image to ghcr.io registry

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-01-17 18:32:20 +08:00
Gauthier
7fcc0eb66d feat(settings): add settings for custom DNS servers and IPv4 resolution first (#1266)
* feat(settings): add settings for custom DNS servers and IPv4 resolution first

This PR adds settings to change the DNS servers Jellyseerr uses and to force Jellyseerr to resolve
DNS queries using IPv4 first. These settings aim to make it easier for less experienced users to fix
network errors related to DNS resolution.

* style: fix missing newline
2025-01-16 10:46:27 +01:00
Fallenbagel
5d9f613dd8 chore(i18n): update translations from weblate (#1263)
* Translated using Weblate (Korean)
Currently translated at 91.8% (1225 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ko/

* Translated using Weblate (Chinese (Simplified))
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/zh_Hans/

* Translated using Weblate (Ukrainian)
Currently translated at 96.1% (1282 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Italian)
Currently translated at 84.4% (1127 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/it/

* Translated using Weblate (Japanese)
Currently translated at 48.4% (646 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ja/

* Translated using Weblate (Spanish)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/es/

* Translated using Weblate (Croatian)
Currently translated at 91.1% (1216 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/hr/

* Translated using Weblate (Arabic)
Currently translated at 91.0% (1215 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ar/

* Translated using Weblate (Norwegian Bokmål)
Currently translated at 80.0% (1068 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nb_NO/

* Translated using Weblate (Danish)
Currently translated at 91.1% (1216 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/da/

* Translated using Weblate (Catalan)
Currently translated at 90.7% (1211 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ca/

* Translated using Weblate (Turkish)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Greek)
Currently translated at 91.3% (1218 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/el/

* Translated using Weblate (Chinese (Traditional))
Currently translated at 89.5% (1194 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/zh_Hant/

* Translated using Weblate (Swedish)
Currently translated at 96.1% (1282 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Polish)
Currently translated at 91.0% (1214 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Romanian)
Currently translated at 32.6% (435 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ro/

* Translated using Weblate (Albanian)
Currently translated at 76.3% (1018 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sq/

* Translated using Weblate (French)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Russian)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Lithuanian)
Currently translated at 54.1% (722 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/lt/

* Translated using Weblate (Dutch)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Hungarian)
Currently translated at 85.2% (1137 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/hu/

* Translated using Weblate (Portuguese (Portugal))
Currently translated at 89.9% (1200 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pt_PT/

* Translated using Weblate (Czech)
Currently translated at 91.4% (1220 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/cs/

* Translated using Weblate (Serbian)
Currently translated at 46.6% (622 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sr/

* Translated using Weblate (Portuguese (Brazil))
Currently translated at 92.5% (1234 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pt_BR/

* Translated using Weblate (Hebrew)
Currently translated at 25.7% (343 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/he/

* Translated using Weblate (German)
Currently translated at 96.2% (1284 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Hindi)
Currently translated at 10.7% (143 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/hi/

* Translated using Weblate (French)
Currently translated at 100.0% (1334 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Italian)
Currently translated at 94.3% (1259 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/it/

* Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/

* Translated using Weblate (Italian)
Currently translated at 94.4% (1260 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/it/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1334 of 1334 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (German)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Spanish)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/es/

* Translated using Weblate (French)
Currently translated at 98.4% (1332 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Dutch)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Polish)
Currently translated at 89.5% (1212 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Russian)
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Swedish)
Currently translated at 94.6% (1280 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Ukrainian)
Currently translated at 94.6% (1280 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Chinese (Simplified))
Currently translated at 94.7% (1282 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/zh_Hans/

* Translated using Weblate (French)
Currently translated at 99.8% (1351 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Romanian)
Currently translated at 46.1% (624 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ro/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (German)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (Russian)
Currently translated at 97.7% (1322 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ru/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (Dutch)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/nl/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.5% (1320 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pt_BR/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Swedish)
Currently translated at 95.4% (1291 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/sv/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Polish)
Currently translated at 91.2% (1235 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Polish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (German)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/de/

* Translated using Weblate (French)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1353 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Ukrainian)
Currently translated at 98.7% (1336 of 1353 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/

* Translated using Weblate (Arabic)
Currently translated at 86.8% (1220 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/ar/

* Translated using Weblate (French)
Currently translated at 96.2% (1353 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Finnish)
Currently translated at 17.2% (243 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fi/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (French)
Currently translated at 96.2% (1353 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Translated using Weblate (French)
Currently translated at 96.7% (1360 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/fr/

* Translated using Weblate (Polish)
Currently translated at 97.8% (1375 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/pl/

* Translated using Weblate (Ukrainian)
Currently translated at 96.8% (1361 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/uk/

* Translated using Weblate (Turkish)
Currently translated at 100.0% (1405 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/tr/

* Added translation using Weblate (Basque)

* Translated using Weblate (Basque)
Currently translated at 16.7% (236 of 1405 strings)
Translate-URL: http://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/eu/

* style(i18n): apply prettier

---------

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: jason54 <jason54700.jg@gmail.com>
Co-authored-by: Kristopher Roller <akjroller@gmail.com>
Co-authored-by: jellyseerr-weblate <155525085+jellyseerr-weblate@users.noreply.github.com>
Co-authored-by: N/A <me@puffin.icu>
Co-authored-by: pouley <pierre@bellemainp.fr>
Co-authored-by: Nuh uh <delayedartisticguppy@protonmail.com>
Co-authored-by: Gauthier <mail@gauthierth.fr>
Co-authored-by: madax <madax@users.noreply.jellyseerr.borgcube.de>
Co-authored-by: SoundwaveUwU <investing_squillitic@dojacat.ru>
Co-authored-by: Michel Heusschen <mh_jellyseerr@users.noreply.jellyseerr.borgcube.de>
Co-authored-by: Leo THIVILLON <leothivillon@gmail.com>
Co-authored-by: Uncle <Uncle-Tio@users.noreply.jellyseerr.borgcube.de>
Co-authored-by: Gökhan GÜRBÜZ <gkhn.gurbuz@hotmail.com>
Co-authored-by: Mattias Magnusson <mattish.91@gmail.com>
Co-authored-by: Radosław Adamczewski <radekadamczewski@gmail.com>
Co-authored-by: Alexander Mnich <alex@mnich.dev>
Co-authored-by: HanaO00 <greenmalkak@gmail.com>
Co-authored-by: michael <michaelvelosk@gmail.com>
Co-authored-by: Heni FAZZANI <heni.fazzani@gmail.com>
Co-authored-by: Matti Koponen <cshessu@gmail.com>
Co-authored-by: Gauvain Perchey <gauvain.perchey@gmail.com>
Co-authored-by: zulimazuli <zulimazuli@gmail.com>
Co-authored-by: Thadah <thadahdenyse+borgcube@protonmail.com>
2025-01-16 00:47:28 +08:00
allcontributors[bot]
ae1ee777fa docs: add methbkts as a contributor for infra (#1264)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-01-16 00:46:19 +08:00
Metin Bektas
b9dc9bceb5 feat: Add latest tag to ghcr container image (#1224)
* feat: Add latest tag to ghcr container image

* ci: add login action to GitHub Container Registry
2025-01-16 00:43:23 +08:00
Fallenbagel
1ffcea2065 docs: update the current list of features we offer (#1262)
* docs: update the current list of features we offer

* docs: add the missing `)`

Co-authored-by: Gauthier <mail@gauthierth.fr>

* docs: use proper acronym case

Co-authored-by: Gauthier <mail@gauthierth.fr>

* docs: add the missing `)`

Co-authored-by: Gauthier <mail@gauthierth.fr>

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2025-01-16 00:18:45 +08:00
Gauthier
ce1b39f73b fix(overriderules): allow override rules only when the service is created (#1259)
If you setup an override rule on a service that is not created yet, the override rule doesn't get
added to the service because it has no ID, but a record for that override rule is nonthless created.
This PR allows override rules only when the service is setup.
2025-01-15 17:08:31 +01:00
Fallenbagel
71143ca76b refactor(tmdb): replace apikey (#1261)
This change is done to adhere with the TMDB rule of having one apikey per app and since jellyseerr
has diverged from overseerr, it is best practice to use our own apikey so that TMDB can properly
identify any issues that could be caused by jellyseerr
2025-01-16 00:04:55 +08:00
Ludovic Ortega
bebad2d814 chore(docs): add documentation about which files/data should be back up (#1254)
* chore(docs): add documentation about which files/data should be back up

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: backups category.json

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: postgresql documentation

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: database backup command

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: moved backup to a single page

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: postgresql options (replace dbname by port)

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: remove lost+lost folder

---------

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-01-15 16:37:34 +08:00
Fallenbagel
1c6f5362d7 fix(settingsmigrator): prevent region migration from running multiple times (#1255)
Adds a guard clause to skip region migration if discoverRegion and
streamingRegion properties already exist in settings. This prevents
accidental overwrites of existing region settings during multiple runs
and ensures the migration only executes when needed.

Previously, the migration would run every time regardless of whether the
new region properties existed, potentially overwriting user preferences.

fix #1251
2025-01-14 12:01:42 +01:00
allcontributors[bot]
4f6192476b docs: add Wunderharke as a contributor for doc (#1258)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-01-14 14:49:54 +08:00
allcontributors[bot]
e97b3dfa9e docs: add benhaney as a contributor for code (#1257)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-01-14 14:48:18 +08:00
allcontributors[bot]
221397db71 docs: add GkhnGRBZ as a contributor for code (#1256)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-01-14 14:47:32 +08:00
Fallenbagel
9ecbd98230 chore: make the database required when creating bug report 2025-01-14 14:45:17 +08:00
Ludovic Ortega
3cc34b0db6 feat: Add release charts workflow (#1140)
* feat: Add release charts workflow

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: helm workflow

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: artifacthub file location

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* feat: bump chart to 1.2.0

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: documentation build

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: install oras in first job

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: release workflow

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: release workflow add package read permission

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: login to ghcr.io at the beginning of job

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: avoid exiting on oras discover

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: documentation typo

* feat: prepare for release

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

* fix: remove myself from codeowners

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>

---------

Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2025-01-12 22:44:38 +08:00
Fallenbagel
5a323324f8 refactor(postgres): add postgres socket (#1248)
* refactor: adds socket_path for unix socket support for postgres

* docs: add documentation for unix socket postgres connection
2025-01-12 22:40:46 +08:00
Fallenbagel
99e2e17b8a style(overriderule): optimises the override rules tile for mobile (#1246) 2025-01-12 10:02:59 +08:00
Fallenbagel
0f14cd9247 style(logs): apply break-words for appDataPath (#1247)
This should make sure that the ui doesnt break for users who has long appDataPaths
2025-01-12 09:57:00 +08:00
Fallenbagel
50db3ea27b refactor: resolve missing dependency warning for validateLibraries in useEffect (#1245) 2025-01-12 09:52:13 +08:00
Fallenbagel
131a5a2b0b fix: resolve plex user mismatch due to caching issues (#1242)
* fix: resolve plex user mismatch due to caching issues

This commit addresses an issue where cached responses for PlexTV API
requests could return incorrect user data when multiple users were logged in.
This was caused by a shared cache key that did not account for differences
in auth tokens, i.e `X-Plex-Token`. The `serializeCacheKey` method should
now include headers in the cache key generation to ensure unique cache keys.
This should fix the plex user mismatch that occurred due to the same
cache key being used without accounting for the difference in auth
token.

fix #1227

* fix: adds the default params and optional params, add the headers in all methods

* refactor: apply review commits and rename params to options in cachekey
2025-01-12 09:51:41 +08:00
Wunderharke
7d08f58c76 Fix missing paramenter for PUT /overrideRule/{ruleId} in overseerr-api.yml (#1244)
I added a missing parameter definition to PUT /overrideRule/{ruleId}.
2025-01-11 15:32:46 +01:00
Fallenbagel
425f0c854e docs: remove pgloader volume from db config
this is not needed as we are using the command directly anyways
2025-01-10 19:37:12 +08:00
Fallenbagel
b8dbfaaed0 fix(setup): plex library setting validation (#1233)
* fix(setup): plex library setting validation

* fix(setup): fixes plex continue button and scroll-to-top when clicked issue in setup
2025-01-10 00:05:13 +01:00
Fallenbagel
24c6208a3c chore: update nodejs to 22 in an attempt to fix undici errors (#1229)
* chore: update nodejs to 22 in an attempt to fix undici errors

This is an attempt to fix the undici errors introduced after the switch
from axios to native fetch. The decision was made as it native fetch on
node 20 seems to be "experimental" and
> since native fetch is no longer experimental since Node 21

* chore: increase the required node version

* build: update nodejs version to 22

* chore: update nodejs version to 22

* chore: update @types/node to v22

* chore(gen-docs): update the gen-docs node engine requirement to 22
2025-01-09 18:24:38 +08:00
Gauthier
d71ee58302 fix: specify cached image type (#1237) 2025-01-08 18:53:14 +01:00
Joaquin Olivero
1755877e66 refactor: replace streaming providers' names with their equivalent logos (#932)
* refactor: replace streaming providers' name with their corresponding logo

re #919

* refactor: change default image opacity and the on hover opacity as well to match the overall ui/ux

---------

Co-authored-by: JoaquinOlivero <joaquin.olivero@hotmail.com>
2025-01-08 18:23:30 +01:00
Fallenbagel
f84d752bca docs: add in missing part in windows docker 2025-01-05 23:45:58 +08:00
Fallenbagel
0b331ca579 fix(setup): fix continue button disabled on refresh in setup 3 (#1211)
This commit resolves an issue where the continue button in setup step 3 remained disabled after a
page refresh even when libraries are toggled. This was happening because
`mediaServerSettingsComplete` state was reset on refresh and not correctly re-initialized.
2025-01-03 12:22:16 +01:00
Fallenbagel
656cd91c9c fix: optimize media status update to avoid lifecycle hook triggers (#1218)
This change optimises the media updates to avoid unneccessary lifecycle hook executions which
results in potential recursion for POSTGRESQL compatibility. This should prevent an issue where
after a TV request, the tv request would get sent to sonarr and notification for it would get sent
over and over and over again
2025-01-03 12:14:39 +01:00
Fallenbagel
81d7473c05 docs: make it clear 2025-01-03 01:07:28 +08:00
Gauthier
f718cec23f fix(externalapi): clear cache after a request is made (#1217)
This PR clears the Radarr/Sonarr cache after a request has been made, because the media status on
Radarr/Sonarr will no longer be good. It also resolves a bug that prevented the media from being
deleted after a request had been sent to Radarr/Sonarr.

fix #1207
2025-01-02 16:44:46 +01:00
Gauthier
ac908026db fix(jellyfinlogin): add proper error message when no admin user exists (#1216)
This PR adds an error message when the database has no admin user and Jellyseerr has already been
set up (i.e. settings.json is filled in), instead of having a generic error message.
2025-01-02 16:03:45 +01:00
Gauthier
d67ec571c5 fix: prevent TypeORM subscribers from calling itself over and over (#1215)
When a series is requested, an event is triggered by TypeORM after the request status has been
updated. The function executed by this event updated the request status to "PROCESSING", even if the
request already had this status. This triggered the same function once again, which repeated the
update, in an endless loop.
2025-01-02 15:46:57 +01:00
Fallenbagel
f3ebf6028b fix(users): correct request count query for PostgreSQL compatibility (#1213)
The request count subquery was causing issues with some PostgreSQL
configurations due to case sensitivity in column aliases. Modified the
query to use an explicit subquery with a properly named alias to ensure
consistent behavior across different database setups.
2025-01-01 19:18:36 +01:00
Fallenbagel
465d42dd60 style(request-list): consistent styling of sort button with the rest (#1212) 2025-01-01 19:17:23 +01:00
Gauthier
2f0e493257 fix(ui): resolve streaming region dropdown overlap (#1210)
fix #1206
2024-12-31 17:08:14 +01:00
Gauthier
ebe7d11a53 fix: correct typos for the special episodes setting (#1209)
Some typos were introduced by #1193, enableSpecialEpisodes and partialRequestsEnabled were mixed up.

fix #1208
2024-12-31 14:15:10 +01:00
Gauthier
7e94ad7210 fix(usersettings): fix the streaming region setting toggling itself (#1203)
When the streaming region is set to another value than the default one, the setting starts toggling
itself from the default value to the new value and vice-versa constantly

fix #1200
2024-12-30 21:45:51 +08:00
Fallenbagel
814a7357c0 fix: properly fetch sonarr/radarr specific override rules (#1199)
* fix: properly fetch sonarr/radarr specific override rules and fix its application

- This will fetch the proper sonarr/radarr specific override rule to apply.
- This will skip override rules for anime TV shows unless the `overrideRule`
explicitly includes the anime keyword.
- Apply the most specific override rule first (e.g., rules with multiple
conditions like `genre`, `language`, and `keywords`)
- Debug logs to for override rules

* fix(overriderules): apply overrides to "auto_approve" permission users but not "advaned_request"

This decision is done because it makes no sense to give advanced request users who gets to choose
what values to choose but then the minute they request, it gets overridden, rendering the whole
modal completely useless. In addition, admin/manage_request permission users who modify requests,
the minute they modify it will get overridden as well so it makes no sense to override their
requests

* fix: use default service instance for override rules

---------

Co-authored-by: Gauthier <mail@gauthierth.fr>
2024-12-30 20:14:29 +08:00
Fallenbagel
f8a8ebdf76 fix(overriderules): apply override rules to tv shows during request (#1198)
Forgot to apply override rules to tv shows on #1197

fix #1195
2024-12-30 11:24:28 +08:00
348 changed files with 25838 additions and 12168 deletions

View File

@@ -7,7 +7,7 @@
"badgeTemplate": "<a href=\"#contributors-\"><img alt=\"All Contributors\" src=\"https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg\"/></a>",
"contributorsPerLine": 7,
"projectName": "jellyseerr",
"projectOwner": "Fallenbagel",
"projectOwner": "fallenbagel",
"repoType": "github",
"repoHost": "https://github.com",
"skipCi": true,
@@ -94,7 +94,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/345752?v=4",
"profile": "https://github.com/jab416171",
"contributions": [
"doc"
"doc",
"code"
]
},
{
@@ -248,7 +249,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/854646?v=4",
"profile": "http://www.piribisoft.com",
"contributions": [
"doc"
"doc",
"code"
]
},
{
@@ -275,7 +277,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/13810742?v=4",
"profile": "https://athfan.com",
"contributions": [
"doc"
"doc",
"code"
]
},
{
@@ -293,7 +296,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/13354331?v=4",
"profile": "https://github.com/xeruf",
"contributions": [
"doc"
"doc",
"code"
]
},
{
@@ -338,7 +342,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/37781713?v=4",
"profile": "https://gauthierth.fr/",
"contributions": [
"code"
"code",
"maintenance"
]
},
{
@@ -377,33 +382,6 @@
"code"
]
},
{
"login": "j0srisk",
"name": "Joseph Risk",
"avatar_url": "https://avatars.githubusercontent.com/u/18372584?v=4",
"profile": "http://josephrisk.com",
"contributions": [
"code"
]
},
{
"login": "Loetwiek",
"name": "Loetwiek",
"avatar_url": "https://avatars.githubusercontent.com/u/79059734?v=4",
"profile": "https://github.com/Loetwiek",
"contributions": [
"code"
]
},
{
"login": "Fuochi",
"name": "Fuochi",
"avatar_url": "https://avatars.githubusercontent.com/u/4720478?v=4",
"profile": "https://github.com/Fuochi",
"contributions": [
"doc"
]
},
{
"login": "mobihen",
"name": "Nir Israel Hen",
@@ -449,69 +427,6 @@
"security"
]
},
{
"login": "j0srisk",
"name": "Joseph Risk",
"avatar_url": "https://avatars.githubusercontent.com/u/18372584?v=4",
"profile": "http://josephrisk.com",
"contributions": [
"code"
]
},
{
"login": "Loetwiek",
"name": "Loetwiek",
"avatar_url": "https://avatars.githubusercontent.com/u/79059734?v=4",
"profile": "https://github.com/Loetwiek",
"contributions": [
"code"
]
},
{
"login": "Fuochi",
"name": "Fuochi",
"avatar_url": "https://avatars.githubusercontent.com/u/4720478?v=4",
"profile": "https://github.com/Fuochi",
"contributions": [
"doc"
]
},
{
"login": "demrich",
"name": "David Emrich",
"avatar_url": "https://avatars.githubusercontent.com/u/30092389?v=4",
"profile": "https://github.com/demrich",
"contributions": [
"code"
]
},
{
"login": "maxnatamo",
"name": "Max T. Kristiansen",
"avatar_url": "https://avatars.githubusercontent.com/u/5898152?v=4",
"profile": "https://maxtrier.dk",
"contributions": [
"code"
]
},
{
"login": "DamsDev1",
"name": "Damien Fajole",
"avatar_url": "https://avatars.githubusercontent.com/u/60252259?v=4",
"profile": "https://damsdev.me",
"contributions": [
"code"
]
},
{
"login": "AhmedNSidd",
"name": "Ahmed Siddiqui",
"avatar_url": "https://avatars.githubusercontent.com/u/36286128?v=4",
"profile": "https://github.com/AhmedNSidd",
"contributions": [
"code"
]
},
{
"login": "Zariel",
"name": "Chris Bannister",
@@ -556,6 +471,177 @@
"contributions": [
"code"
]
},
{
"login": "GkhnGRBZ",
"name": "GkhnGRBZ",
"avatar_url": "https://avatars.githubusercontent.com/u/127258824?v=4",
"profile": "https://github.com/GkhnGRBZ",
"contributions": [
"code"
]
},
{
"login": "benhaney",
"name": "Ben Haney",
"avatar_url": "https://avatars.githubusercontent.com/u/31331498?v=4",
"profile": "http://benhaney.com",
"contributions": [
"code"
]
},
{
"login": "Wunderharke",
"name": "Wunderharke",
"avatar_url": "https://avatars.githubusercontent.com/u/5105672?v=4",
"profile": "https://github.com/Wunderharke",
"contributions": [
"doc"
]
},
{
"login": "methbkts",
"name": "Metin Bektas",
"avatar_url": "https://avatars.githubusercontent.com/u/30674934?v=4",
"profile": "https://github.com/methbkts",
"contributions": [
"infra"
]
},
{
"login": "andrewkolda",
"name": "andrewkolda",
"avatar_url": "https://avatars.githubusercontent.com/u/158614532?v=4",
"profile": "https://github.com/andrewkolda",
"contributions": [
"design"
]
},
{
"login": "ishanjain28",
"name": "Ishan Jain",
"avatar_url": "https://avatars.githubusercontent.com/u/7921368?v=4",
"profile": "https://ishanjain.me",
"contributions": [
"code"
]
},
{
"login": "michaelhthomas",
"name": "Michael Thomas",
"avatar_url": "https://avatars.githubusercontent.com/u/18223295?v=4",
"profile": "http://michaelt.xyz",
"contributions": [
"code"
]
},
{
"login": "RankWeis",
"name": "RankWeis",
"avatar_url": "https://avatars.githubusercontent.com/u/733691?v=4",
"profile": "https://github.com/RankWeis",
"contributions": [
"code"
]
},
{
"login": "jessielw",
"name": "Jessie Wilson",
"avatar_url": "https://avatars.githubusercontent.com/u/48299282?v=4",
"profile": "http://www.linkedin.com/in/jessielwilson",
"contributions": [
"code"
]
},
{
"login": "brotaxt",
"name": "DominicKo",
"avatar_url": "https://avatars.githubusercontent.com/u/25477935?v=4",
"profile": "https://github.com/brotaxt",
"contributions": [
"code"
]
},
{
"login": "corentinnormand",
"name": "Corentin Normand",
"avatar_url": "https://avatars.githubusercontent.com/u/30508927?v=4",
"profile": "https://doctolib.com",
"contributions": [
"code"
]
},
{
"login": "benbeauchamp7",
"name": "Ben Beauchamp",
"avatar_url": "https://avatars.githubusercontent.com/u/43358492?v=4",
"profile": "https://github.com/benbeauchamp7",
"contributions": [
"code"
]
},
{
"login": "vfaergestad",
"name": "vfaergestad",
"avatar_url": "https://avatars.githubusercontent.com/u/49147564?v=4",
"profile": "https://github.com/vfaergestad",
"contributions": [
"code"
]
},
{
"login": "wolffman122",
"name": "wolffman122",
"avatar_url": "https://avatars.githubusercontent.com/u/19178872?v=4",
"profile": "https://github.com/wolffman122",
"contributions": [
"code"
]
},
{
"login": "Schrottfresser",
"name": "Schrottfresser",
"avatar_url": "https://avatars.githubusercontent.com/u/39998368?v=4",
"profile": "https://github.com/Schrottfresser",
"contributions": [
"code"
]
},
{
"login": "DillionLowry",
"name": "Dillion",
"avatar_url": "https://avatars.githubusercontent.com/u/91228469?v=4",
"profile": "https://github.com/DillionLowry",
"contributions": [
"code"
]
},
{
"login": "JamsRepos",
"name": "Jam",
"avatar_url": "https://avatars.githubusercontent.com/u/1347620?v=4",
"profile": "https://github.com/JamsRepos",
"contributions": [
"code"
]
},
{
"login": "joelowrance",
"name": "Joe Lowrance",
"avatar_url": "https://avatars.githubusercontent.com/u/63176?v=4",
"profile": "http://www.joelowrance.com",
"contributions": [
"code"
]
},
{
"login": "0xSysR3ll",
"name": "0xsysr3ll",
"avatar_url": "https://avatars.githubusercontent.com/u/31414959?v=4",
"profile": "https://github.com/0xSysR3ll",
"contributions": [
"code"
]
}
]
}

View File

@@ -63,6 +63,8 @@ body:
- PostgreSQL
label: Database
description: Which database backend are you using?
validations:
required: true
- type: input
id: device
attributes:

View File

@@ -12,8 +12,8 @@ jobs:
test:
name: Lint & Test Build
if: github.event_name == 'pull_request'
runs-on: ubuntu-22.04
container: node:20-alpine
runs-on: ubuntu-24.04
container: node:22-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -43,15 +43,23 @@ jobs:
- name: Build
run: pnpm build
build_and_push:
build:
name: Build & Publish Docker Images
if: github.ref == 'refs/heads/develop' && !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- runner: ubuntu-24.04
platform: linux/amd64
- runner: ubuntu-24.04-arm
platform: linux/arm64
runs-on: ${{ matrix.runner }}
outputs:
digest-amd64: ${{ steps.set_outputs.outputs.digest-amd64 }}
digest-arm64: ${{ steps.set_outputs.outputs.digest-arm64 }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
@@ -70,24 +78,79 @@ jobs:
echo "OWNER_LC=${OWNER,,}" >>${GITHUB_ENV}
env:
OWNER: ${{ github.repository_owner }}
- name: Build and push
- name: Docker metadata
id: meta
uses: docker/metadata-action@v4
with:
images: |
fallenbagel/jellyseerr
ghcr.io/${{ env.OWNER_LC }}/jellyseerr
tags: |
type=ref,event=branch
type=sha,prefix=,suffix=,format=short
- name: Build and push by digest
id: build
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
platforms: ${{ matrix.platform }}
push: true
build-args: |
COMMIT_TAG=${{ github.sha }}
tags: |
fallenbagel/jellyseerr:develop
ghcr.io/${{ env.OWNER_LC }}/jellyseerr:develop
BUILD_VERSION=develop
BUILD_DATE=${{ github.event.repository.updated_at }}
outputs: |
type=image,push-by-digest=true,name=fallenbagel/jellyseerr,push=true
type=image,push-by-digest=true,name=ghcr.io/${{ env.OWNER_LC }}/jellyseerr,push=true
cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
provenance: false
- name: Set outputs
id: set_outputs
run: |
platform="${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}"
echo "digest-${platform}=${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT
merge_and_push:
name: Create and Push Multi-arch Manifest
needs: build
runs-on: ubuntu-24.04
steps:
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set lower case owner name
run: |
echo "OWNER_LC=${OWNER,,}" >>${GITHUB_ENV}
env:
OWNER: ${{ github.repository_owner }}
- name: Create and push manifest
run: |
docker manifest create fallenbagel/jellyseerr:develop \
--amend fallenbagel/jellyseerr@${{ needs.build.outputs.digest-amd64 }} \
--amend fallenbagel/jellyseerr@${{ needs.build.outputs.digest-arm64 }}
docker manifest push fallenbagel/jellyseerr:develop
# GHCR manifest
docker manifest create ghcr.io/${{ env.OWNER_LC }}/jellyseerr:develop \
--amend ghcr.io/${{ env.OWNER_LC }}/jellyseerr@${{ needs.build.outputs.digest-amd64 }} \
--amend ghcr.io/${{ env.OWNER_LC }}/jellyseerr@${{ needs.build.outputs.digest-arm64 }}
docker manifest push ghcr.io/${{ env.OWNER_LC }}/jellyseerr:develop
discord:
name: Send Discord Notification
needs: build_and_push
needs: merge_and_push
if: always() && github.event_name != 'pull_request' && !contains(github.event.head_commit.message, '[skip ci]')
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Get Build Job Status
uses: technote-space/workflow-conclusion-action@v3

View File

@@ -17,7 +17,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
- name: Pnpm Setup
uses: pnpm/action-setup@v4
with:
@@ -36,3 +36,11 @@ jobs:
# Fix test titles in cypress dashboard
COMMIT_INFO_MESSAGE: ${{github.event.pull_request.title}}
COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha}}
- name: Upload video files
if: always()
uses: actions/upload-artifact@v4
with:
name: cypress-videos
path: |
cypress/videos
cypress/screenshots

135
.github/workflows/helm.yml vendored Normal file
View File

@@ -0,0 +1,135 @@
name: Release Charts
on:
push:
branches:
- develop
jobs:
package-helm-chart:
name: Package helm chart
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
outputs:
has_artifacts: ${{ steps.check-artifacts.outputs.has_artifacts }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install helm
uses: azure/setup-helm@v4
- name: Install Oras
uses: oras-project/setup-oras@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Package helm charts
run: |
mkdir -p ./.cr-release-packages
for chart_path in ./charts/*; do
if [ -d "$chart_path" ] && [ -f "$chart_path/Chart.yaml" ]; then
chart_name=$(grep '^name:' "$chart_path/Chart.yaml" | awk '{print $2}')
# get current version
current_version=$(grep '^version:' "$chart_path/Chart.yaml" | awk '{print $2}')
# try to get current release version
set +e
oras discover ghcr.io/${GITHUB_REPOSITORY@L}/${chart_name}:${current_version}
oras_exit_code=$?
set -e
if [ $oras_exit_code -ne 0 ]; then
helm dependency build "$chart_path"
helm package "$chart_path" --destination ./.cr-release-packages
else
echo "No version change for $chart_name. Skipping."
fi
else
echo "Skipping $chart_name: Not a valid Helm chart"
fi
done
- name: Check if artifacts exist
id: check-artifacts
run: |
if ls .cr-release-packages/* >/dev/null 2>&1; then
echo "has_artifacts=true" >> $GITHUB_OUTPUT
else
echo "has_artifacts=false" >> $GITHUB_OUTPUT
fi
- name: Upload artifacts
uses: actions/upload-artifact@v4
if: steps.check-artifacts.outputs.has_artifacts == 'true'
with:
name: artifacts
include-hidden-files: true
path: .cr-release-packages/
publish:
name: Publish to ghcr.io
runs-on: ubuntu-latest
permissions:
packages: write # needed for pushing to github registry
id-token: write # needed for signing the images with GitHub OIDC Token
needs: [package-helm-chart]
if: needs.package-helm-chart.outputs.has_artifacts == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install helm
uses: azure/setup-helm@v4
- name: Install Oras
uses: oras-project/setup-oras@v1
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Downloads artifacts
uses: actions/download-artifact@v4
with:
name: artifacts
path: .cr-release-packages/
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push charts to GHCR
env:
COSIGN_YES: true
run: |
for chart_path in `find .cr-release-packages -name '*.tgz' -print`; do
# push chart to OCI
chart_release_file=$(basename "$chart_path")
chart_name=${chart_release_file%-*}
helm push ${chart_path} oci://ghcr.io/${GITHUB_REPOSITORY@L} |& tee helm-push-output.log
chart_digest=$(awk -F "[, ]+" '/Digest/{print $NF}' < helm-push-output.log)
# sign chart
cosign sign "ghcr.io/${GITHUB_REPOSITORY@L}/${chart_name}@${chart_digest}"
# push artifacthub-repo.yml to OCI
oras push \
ghcr.io/${GITHUB_REPOSITORY@L}/${chart_name}:artifacthub.io \
--config /dev/null:application/vnd.cncf.artifacthub.config.v1+yaml \
charts/$chart_name/artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml \
|& tee oras-push-output.log
artifacthub_digest=$(grep "Digest:" oras-push-output.log | awk '{print $2}')
# sign artifacthub-repo.yml
cosign sign "ghcr.io/${GITHUB_REPOSITORY@L}/${chart_name}:artifacthub.io@${artifacthub_digest}"
done

View File

@@ -33,5 +33,7 @@ jobs:
push: true
build-args: |
COMMIT_TAG=${{ github.sha }}
BUILD_VERSION=${{ steps.get_version.outputs.VERSION }}
BUILD_DATE=${{ github.event.repository.updated_at }}
tags: |
fallenbagel/jellyseerr:${{ steps.get_version.outputs.VERSION }}

View File

@@ -16,7 +16,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
@@ -26,6 +26,12 @@ jobs:
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_TOKEN }}
- name: Pnpm Setup
uses: pnpm/action-setup@v4
with:

View File

@@ -4,6 +4,7 @@ dist/
config/
CHANGELOG.md
pnpm-lock.yaml
cypress/config/settings.cypress.json
# assets
src/assets/

View File

@@ -21,5 +21,11 @@ module.exports = {
rangeEnd: 0, // default: Infinity
},
},
{
files: 'cypress/config/settings.cypress.json',
options: {
rangeEnd: 0,
},
},
],
};

View File

@@ -19,5 +19,6 @@
"typescript.preferences.importModuleSpecifier": "non-relative",
"files.associations": {
"globals.css": "tailwindcss"
}
},
"i18n-ally.localesPaths": ["src/i18n/locale"]
}

View File

@@ -8,7 +8,7 @@ All help is welcome and greatly appreciated! If you would like to contribute to
- HTML/Typescript/Javascript editor
- [VSCode](https://code.visualstudio.com/) is recommended. Upon opening the project, a few extensions will be automatically recommended for install.
- [NodeJS](https://nodejs.org/en/download/) (Node 20.x)
- [NodeJS](https://nodejs.org/en/download/) (Node 22.x)
- [Pnpm](https://pnpm.io/cli/install)
- [Git](https://git-scm.com/downloads)
@@ -58,12 +58,27 @@ All help is welcome and greatly appreciated! If you would like to contribute to
- Be sure to follow both the [code](#contributing-code) and [UI text](#ui-text-style) guidelines.
- Should you need to update your fork, you can do so by rebasing from `upstream`:
```bash
git fetch upstream
git rebase upstream/develop
git push origin BRANCH_NAME -f
```
### Helm Chart
Tools Required:
- [Helm](https://helm.sh/docs/intro/install/)
- [helm-docs](https://github.com/norwoodj/helm-docs)
Steps:
1. Make the necessary changes.
2. Test your changes.
3. Update the `version` in `charts/jellyseerr-chart/Chart.yaml` following [Semantic Versioning (SemVer)](https://semver.org/).
4. Run the `helm-docs` command to regenerate the chart's README.
### Contributing Code
- If you are taking on an existing bug or feature ticket, please comment on the [issue](https://github.com/fallenbagel/jellyseerr/issues) to avoid multiple people working on the same thing.
@@ -97,7 +112,7 @@ When adding new UI text, please try to adhere to the following guidelines:
## Translation
We use [Weblate](https://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/) for our translations, and your help with localizing Overseerr would be greatly appreciated! If your language is not listed below, please [open a feature request](https://github.com/fallenbagel/jellyseerr/issues/new/choose).
We use [Weblate](https://jellyseerr.borgcube.de/projects/jellyseerr/jellyseerr-frontend/) for our translations, and your help with localizing Jellyseerr would be greatly appreciated! If your language is not listed below, please [open a feature request](https://github.com/fallenbagel/jellyseerr/issues/new/choose).
<a href="https://jellyseerr.borgcube.de/engage/jellysseerr/"><img src="https://jellyseerr.borgcube.de/widget/jellyseerr/multi-auto.svg" alt="Translation status" /></a>

View File

@@ -1,4 +1,4 @@
FROM node:20-alpine AS BUILD_IMAGE
FROM node:22-alpine AS BUILD_IMAGE
WORKDIR /app
@@ -14,7 +14,7 @@ RUN \
;; \
esac
RUN npm install --global pnpm
RUN npm install --global pnpm@9
COPY package.json pnpm-lock.yaml postinstall-win.js ./
RUN CYPRESS_INSTALL_BINARY=0 pnpm install --frozen-lockfile
@@ -29,23 +29,32 @@ RUN pnpm build
# remove development dependencies
RUN pnpm prune --prod --ignore-scripts
RUN rm -rf src server .next/cache
RUN rm -rf src server .next/cache charts gen-docs docs
RUN touch config/DOCKER
RUN echo "{\"commitTag\": \"${COMMIT_TAG}\"}" > committag.json
FROM node:20-alpine
FROM node:22-alpine
# Metadata for Github Package Registry
LABEL org.opencontainers.image.source="https://github.com/Fallenbagel/jellyseerr"
# OCI Meta information
ARG BUILD_DATE
ARG BUILD_VERSION
LABEL \
org.opencontainers.image.authors="Fallenbagel" \
org.opencontainers.image.source="https://github.com/fallenbagel/jellyseerr" \
org.opencontainers.image.created=${BUILD_DATE} \
org.opencontainers.image.version=${BUILD_VERSION} \
org.opencontainers.image.title="Jellyseerr" \
org.opencontainers.image.description="Open-source media request and discovery manager for Jellyfin, Plex, and Emby." \
org.opencontainers.image.licenses="MIT"
WORKDIR /app
RUN apk add --no-cache tzdata tini && rm -rf /tmp/*
RUN npm install -g pnpm
RUN npm install -g pnpm@9
# copy from build image
COPY --from=BUILD_IMAGE /app ./

View File

@@ -1,9 +1,9 @@
FROM node:20-alpine
FROM node:22-alpine
COPY . /app
WORKDIR /app
Run npm install --global pnpm
RUN npm install --global pnpm@9
RUN pnpm install

131
README.md
View File

@@ -11,17 +11,17 @@
<a href="http://translate.jellyseerr.dev/engage/jellyseerr/"><img src="http://translate.jellyseerr.dev/widget/jellyseerr/jellyseerr-frontend/svg-badge.svg" alt="Translation status" /></a>
<a href="https://github.com/fallenbagel/jellyseerr/blob/develop/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/fallenbagel/jellyseerr"></a>
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
<a href="#contributors-"><img alt="All Contributors" src="https://img.shields.io/badge/all_contributors-60-orange.svg"/></a>
<a href="#contributors-"><img alt="All Contributors" src="https://img.shields.io/badge/all_contributors-69-orange.svg"/></a>
<!-- ALL-CONTRIBUTORS-BADGE:END -->
**Jellyseerr** is a free and open source software application for managing requests for your media library.
It is a fork of [Overseerr](https://github.com/sct/overseerr) built to bring support for [Jellyfin](https://github.com/jellyfin/jellyfin) & [Emby](https://github.com/MediaBrowser/Emby) media servers!
**Jellyseerr** is a free and open source software application for managing requests for your media library. It integrates with the media server of your choice: [Jellyfin](https://jellyfin.org), [Plex](https://plex.tv), and [Emby](https://emby.media/). In addition, it integrates with your existing services, such as **[Sonarr](https://sonarr.tv/)**, **[Radarr](https://radarr.video/)**.
## Current Features
- Full Jellyfin/Emby/Plex integration including authentication with user import & management
- Supports Movies, Shows and Mixed Libraries
- Ability to change email addresses for smtp purposes
- Full Jellyfin/Emby/Plex integration including authentication with user import & management.
- Support for **PostgreSQL** and **SQLite** databases.
- Supports Movies, Shows and Mixed Libraries.
- Ability to change email addresses for SMTP purposes.
- Easy integration with your existing services. Currently, Jellyseerr supports Sonarr and Radarr. More to come!
- Jellyfin/Emby/Plex library scan, to keep track of the titles which are already available.
- Customizable request system, which allows users to request individual seasons or movies in a friendly, easy-to-use interface.
@@ -29,8 +29,7 @@ It is a fork of [Overseerr](https://github.com/sct/overseerr) built to bring sup
- Granular permission system.
- Support for various notification agents.
- Mobile-friendly design, for when you need to approve requests on the go!
(Upcoming Features include: Multiple Server Instances, and much more!)
- Support for watchlisting & blacklisting media.
With more features on the way! Check out our [issue tracker](https://github.com/fallenbagel/jellyseerr/issues) to see the features which have already been requested.
@@ -87,82 +86,93 @@ Thanks goes to these wonderful people from Overseerr ([emoji key](https://allcon
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fallenbagel"><img src="https://avatars.githubusercontent.com/u/98979876?v=4?s=100" width="100px;" alt="Fallenbagel"/><br /><sub><b>Fallenbagel</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Fallenbagel" title="Code">💻</a> <a href="#maintenance-Fallenbagel" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/seanzhang98"><img src="https://avatars.githubusercontent.com/u/34902361?v=4?s=100" width="100px;" alt="Sean"/><br /><sub><b>Sean</b></sub></a><br /><a href="#translation-seanzhang98" title="Translation">🌍</a> <a href="https://github.com/Fallenbagel/jellyseerr/commits?author=seanzhang98" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/notfakie"><img src="https://avatars.githubusercontent.com/u/103784113?v=4?s=100" width="100px;" alt="notfakie"/><br /><sub><b>notfakie</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=notfakie" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jumail"><img src="https://avatars.githubusercontent.com/u/7672055?v=4?s=100" width="100px;" alt="Mohamed Jumail"/><br /><sub><b>Mohamed Jumail</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/pulls?q=is%3Apr+reviewed-by%3AJumail" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.heywhale.com"><img src="https://avatars.githubusercontent.com/u/4048787?v=4?s=100" width="100px;" alt="Shilong Jiang"/><br /><sub><b>Shilong Jiang</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=jsl9208" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jinas.me"><img src="https://avatars.githubusercontent.com/u/28459081?v=4?s=100" width="100px;" alt="Boring Dragon"/><br /><sub><b>Boring Dragon</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=boring-dragon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sambartik"><img src="https://avatars.githubusercontent.com/u/63553146?v=4?s=100" width="100px;" alt="Samuel Bartík"/><br /><sub><b>Samuel Bartík</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=sambartik" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fallenbagel"><img src="https://avatars.githubusercontent.com/u/98979876?v=4?s=100" width="100px;" alt="Fallenbagel"/><br /><sub><b>Fallenbagel</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=Fallenbagel" title="Code">💻</a> <a href="#maintenance-Fallenbagel" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/seanzhang98"><img src="https://avatars.githubusercontent.com/u/34902361?v=4?s=100" width="100px;" alt="Sean"/><br /><sub><b>Sean</b></sub></a><br /><a href="#translation-seanzhang98" title="Translation">🌍</a> <a href="https://github.com/fallenbagel/jellyseerr/commits?author=seanzhang98" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/notfakie"><img src="https://avatars.githubusercontent.com/u/103784113?v=4?s=100" width="100px;" alt="notfakie"/><br /><sub><b>notfakie</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=notfakie" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jumail"><img src="https://avatars.githubusercontent.com/u/7672055?v=4?s=100" width="100px;" alt="Mohamed Jumail"/><br /><sub><b>Mohamed Jumail</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/pulls?q=is%3Apr+reviewed-by%3AJumail" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.heywhale.com"><img src="https://avatars.githubusercontent.com/u/4048787?v=4?s=100" width="100px;" alt="Shilong Jiang"/><br /><sub><b>Shilong Jiang</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=jsl9208" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jinas.me"><img src="https://avatars.githubusercontent.com/u/28459081?v=4?s=100" width="100px;" alt="Boring Dragon"/><br /><sub><b>Boring Dragon</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=boring-dragon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sambartik"><img src="https://avatars.githubusercontent.com/u/63553146?v=4?s=100" width="100px;" alt="Samuel Bartík"/><br /><sub><b>Samuel Bartík</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=sambartik" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CyferShepard"><img src="https://avatars.githubusercontent.com/u/24864904?v=4?s=100" width="100px;" alt="Thegan Govender"/><br /><sub><b>Thegan Govender</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=CyferShepard" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jab416171"><img src="https://avatars.githubusercontent.com/u/345752?v=4?s=100" width="100px;" alt="jab416171"/><br /><sub><b>jab416171</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=jab416171" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nvds.be"><img src="https://avatars.githubusercontent.com/u/5257222?v=4?s=100" width="100px;" alt="Nicolai Van der Storm"/><br /><sub><b>Nicolai Van der Storm</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=NicolaiVdS" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CyferShepard"><img src="https://avatars.githubusercontent.com/u/24864904?v=4?s=100" width="100px;" alt="Thegan Govender"/><br /><sub><b>Thegan Govender</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=CyferShepard" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jab416171"><img src="https://avatars.githubusercontent.com/u/345752?v=4?s=100" width="100px;" alt="jab416171"/><br /><sub><b>jab416171</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=jab416171" title="Documentation">📖</a> <a href="https://github.com/fallenbagel/jellyseerr/commits?author=jab416171" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nvds.be"><img src="https://avatars.githubusercontent.com/u/5257222?v=4?s=100" width="100px;" alt="Nicolai Van der Storm"/><br /><sub><b>Nicolai Van der Storm</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=NicolaiVdS" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Smexhy"><img src="https://avatars.githubusercontent.com/u/4880625?v=4?s=100" width="100px;" alt="Smexhy"/><br /><sub><b>Smexhy</b></sub></a><br /><a href="#translation-Smexhy" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dd06-dev.fr"><img src="https://avatars.githubusercontent.com/u/58089504?v=4?s=100" width="100px;" alt="dd060606"/><br /><sub><b>dd060606</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=dd060606" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://qwer.tz"><img src="https://avatars.githubusercontent.com/u/71837281?v=4?s=100" width="100px;" alt="Daniel"/><br /><sub><b>Daniel</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=darmiel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dd06-dev.fr"><img src="https://avatars.githubusercontent.com/u/58089504?v=4?s=100" width="100px;" alt="dd060606"/><br /><sub><b>dd060606</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=dd060606" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://qwer.tz"><img src="https://avatars.githubusercontent.com/u/71837281?v=4?s=100" width="100px;" alt="Daniel"/><br /><sub><b>Daniel</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=darmiel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/undone37"><img src="https://avatars.githubusercontent.com/u/10513808?v=4?s=100" width="100px;" alt="undone37"/><br /><sub><b>undone37</b></sub></a><br /><a href="#translation-undone37" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CheChu10"><img src="https://avatars.githubusercontent.com/u/32913133?v=4?s=100" width="100px;" alt="Chechu García"/><br /><sub><b>Chechu García</b></sub></a><br /><a href="#translation-CheChu10" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DimitriDR"><img src="https://avatars.githubusercontent.com/u/56969769?v=4?s=100" width="100px;" alt="Dimitri"/><br /><sub><b>Dimitri</b></sub></a><br /><a href="#translation-DimitriDR" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrey4korop"><img src="https://avatars.githubusercontent.com/u/24610708?v=4?s=100" width="100px;" alt="andrey4korop"/><br /><sub><b>andrey4korop</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=andrey4korop" title="Code">💻</a> <a href="#translation-andrey4korop" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrey4korop"><img src="https://avatars.githubusercontent.com/u/24610708?v=4?s=100" width="100px;" alt="andrey4korop"/><br /><sub><b>andrey4korop</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=andrey4korop" title="Code">💻</a> <a href="#translation-andrey4korop" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://geoffrey-coulaud.fr"><img src="https://avatars.githubusercontent.com/u/20744730?v=4?s=100" width="100px;" alt="Geoffrey Coulaud"/><br /><sub><b>Geoffrey Coulaud</b></sub></a><br /><a href="#translation-GeoffreyCoulaud" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Pikachu920"><img src="https://avatars.githubusercontent.com/u/28607612?v=4?s=100" width="100px;" alt="Pikachu920"/><br /><sub><b>Pikachu920</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Pikachu920" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yalagin"><img src="https://avatars.githubusercontent.com/u/12879142?v=4?s=100" width="100px;" alt="Maxim Yalagin"/><br /><sub><b>Maxim Yalagin</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=yalagin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jeaboswell"><img src="https://avatars.githubusercontent.com/u/11653068?v=4?s=100" width="100px;" alt="Jesse Boswell"/><br /><sub><b>Jesse Boswell</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=jeaboswell" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Pikachu920"><img src="https://avatars.githubusercontent.com/u/28607612?v=4?s=100" width="100px;" alt="Pikachu920"/><br /><sub><b>Pikachu920</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=Pikachu920" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yalagin"><img src="https://avatars.githubusercontent.com/u/12879142?v=4?s=100" width="100px;" alt="Maxim Yalagin"/><br /><sub><b>Maxim Yalagin</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=yalagin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jeaboswell"><img src="https://avatars.githubusercontent.com/u/11653068?v=4?s=100" width="100px;" alt="Jesse Boswell"/><br /><sub><b>Jesse Boswell</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=jeaboswell" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/d-fendrich"><img src="https://avatars.githubusercontent.com/u/27904138?v=4?s=100" width="100px;" alt="d-fendrich"/><br /><sub><b>d-fendrich</b></sub></a><br /><a href="#translation-d-fendrich" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/davidfdezalcoba"><img src="https://avatars.githubusercontent.com/u/15996018?v=4?s=100" width="100px;" alt="David Fernández Alcoba"/><br /><sub><b>David Fernández Alcoba</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=davidfdezalcoba" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/davidfdezalcoba"><img src="https://avatars.githubusercontent.com/u/15996018?v=4?s=100" width="100px;" alt="David Fernández Alcoba"/><br /><sub><b>David Fernández Alcoba</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=davidfdezalcoba" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Gauvino"><img src="https://avatars.githubusercontent.com/u/68083474?v=4?s=100" width="100px;" alt="Gauvino"/><br /><sub><b>Gauvino</b></sub></a><br /><a href="#translation-Gauvino" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/EthanArmbrust"><img src="https://avatars.githubusercontent.com/u/22754714?v=4?s=100" width="100px;" alt="EthanArmbrust"/><br /><sub><b>EthanArmbrust</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=EthanArmbrust" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.piribisoft.com"><img src="https://avatars.githubusercontent.com/u/854646?v=4?s=100" width="100px;" alt="Eduardo"/><br /><sub><b>Eduardo</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=SirMartin" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RickLuiken"><img src="https://avatars.githubusercontent.com/u/34110371?v=4?s=100" width="100px;" alt="RickLuiken"/><br /><sub><b>RickLuiken</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=RickLuiken" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/EthanArmbrust"><img src="https://avatars.githubusercontent.com/u/22754714?v=4?s=100" width="100px;" alt="EthanArmbrust"/><br /><sub><b>EthanArmbrust</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=EthanArmbrust" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.piribisoft.com"><img src="https://avatars.githubusercontent.com/u/854646?v=4?s=100" width="100px;" alt="Eduardo"/><br /><sub><b>Eduardo</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=SirMartin" title="Documentation">📖</a> <a href="https://github.com/fallenbagel/jellyseerr/commits?author=SirMartin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RickLuiken"><img src="https://avatars.githubusercontent.com/u/34110371?v=4?s=100" width="100px;" alt="RickLuiken"/><br /><sub><b>RickLuiken</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=RickLuiken" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Br33ce"><img src="https://avatars.githubusercontent.com/u/124933490?v=4?s=100" width="100px;" alt="Br33ce"/><br /><sub><b>Br33ce</b></sub></a><br /><a href="#translation-Br33ce" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://athfan.com"><img src="https://avatars.githubusercontent.com/u/13810742?v=4?s=100" width="100px;" alt="Athfan Khaleel"/><br /><sub><b>Athfan Khaleel</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=athphane" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://athfan.com"><img src="https://avatars.githubusercontent.com/u/13810742?v=4?s=100" width="100px;" alt="Athfan Khaleel"/><br /><sub><b>Athfan Khaleel</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=athphane" title="Documentation">📖</a> <a href="https://github.com/fallenbagel/jellyseerr/commits?author=athphane" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mdll23"><img src="https://avatars.githubusercontent.com/u/142844478?v=4?s=100" width="100px;" alt="Michael Dallinger"/><br /><sub><b>Michael Dallinger</b></sub></a><br /><a href="#translation-mdll23" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xeruf"><img src="https://avatars.githubusercontent.com/u/13354331?v=4?s=100" width="100px;" alt="Janek"/><br /><sub><b>Janek</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=xeruf" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xeruf"><img src="https://avatars.githubusercontent.com/u/13354331?v=4?s=100" width="100px;" alt="Janek"/><br /><sub><b>Janek</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=xeruf" title="Documentation">📖</a> <a href="https://github.com/fallenbagel/jellyseerr/commits?author=xeruf" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://aleksasiriski.dev"><img src="https://avatars.githubusercontent.com/u/31509435?v=4?s=100" width="100px;" alt="Aleksa Siriški"/><br /><sub><b>Aleksa Siriški</b></sub></a><br /><a href="#infra-aleksasiriski" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://danishhumair.com"><img src="https://avatars.githubusercontent.com/u/121830048?v=4?s=100" width="100px;" alt="Danish Humair"/><br /><sub><b>Danish Humair</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Danish-H" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://arm0.red"><img src="https://avatars.githubusercontent.com/u/16858514?v=4?s=100" width="100px;" alt="Stephen Harris"/><br /><sub><b>Stephen Harris</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=trackmastersteve" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.boniface.me"><img src="https://avatars.githubusercontent.com/u/4031396?v=4?s=100" width="100px;" alt="Joshua M. Boniface"/><br /><sub><b>Joshua M. Boniface</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=joshuaboniface" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://danishhumair.com"><img src="https://avatars.githubusercontent.com/u/121830048?v=4?s=100" width="100px;" alt="Danish Humair"/><br /><sub><b>Danish Humair</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=Danish-H" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://arm0.red"><img src="https://avatars.githubusercontent.com/u/16858514?v=4?s=100" width="100px;" alt="Stephen Harris"/><br /><sub><b>Stephen Harris</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=trackmastersteve" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.boniface.me"><img src="https://avatars.githubusercontent.com/u/4031396?v=4?s=100" width="100px;" alt="Joshua M. Boniface"/><br /><sub><b>Joshua M. Boniface</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=joshuaboniface" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://gauthierth.fr/"><img src="https://avatars.githubusercontent.com/u/37781713?v=4?s=100" width="100px;" alt="Gauthier"/><br /><sub><b>Gauthier</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=gauthier-th" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://gauthierth.fr/"><img src="https://avatars.githubusercontent.com/u/37781713?v=4?s=100" width="100px;" alt="Gauthier"/><br /><sub><b>Gauthier</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=gauthier-th" title="Code">💻</a> <a href="#maintenance-gauthier-th" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kara-Zor-El"><img src="https://avatars.githubusercontent.com/u/69772087?v=4?s=100" width="100px;" alt="Kara"/><br /><sub><b>Kara</b></sub></a><br /><a href="#infra-Kara-Zor-El" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://joaquinolivero.com"><img src="https://avatars.githubusercontent.com/u/66050823?v=4?s=100" width="100px;" alt="Joaquin Olivero"/><br /><sub><b>Joaquin Olivero</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=JoaquinOlivero" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://joaquinolivero.com"><img src="https://avatars.githubusercontent.com/u/66050823?v=4?s=100" width="100px;" alt="Joaquin Olivero"/><br /><sub><b>Joaquin Olivero</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=JoaquinOlivero" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Bretterteig"><img src="https://avatars.githubusercontent.com/u/47298401?v=4?s=100" width="100px;" alt="Julian Behr"/><br /><sub><b>Julian Behr</b></sub></a><br /><a href="#translation-Bretterteig" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ThowZzy"><img src="https://avatars.githubusercontent.com/u/61882536?v=4?s=100" width="100px;" alt="ThowZzy"/><br /><sub><b>ThowZzy</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=ThowZzy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://josephrisk.com"><img src="https://avatars.githubusercontent.com/u/18372584?v=4?s=100" width="100px;" alt="Joseph Risk"/><br /><sub><b>Joseph Risk</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=j0srisk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Loetwiek"><img src="https://avatars.githubusercontent.com/u/79059734?v=4?s=100" width="100px;" alt="Loetwiek"/><br /><sub><b>Loetwiek</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Loetwiek" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fuochi"><img src="https://avatars.githubusercontent.com/u/4720478?v=4?s=100" width="100px;" alt="Fuochi"/><br /><sub><b>Fuochi</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Fuochi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ThowZzy"><img src="https://avatars.githubusercontent.com/u/61882536?v=4?s=100" width="100px;" alt="ThowZzy"/><br /><sub><b>ThowZzy</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=ThowZzy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://mobihen.com"><img src="https://avatars.githubusercontent.com/u/35529491?v=4?s=100" width="100px;" alt="Nir Israel Hen"/><br /><sub><b>Nir Israel Hen</b></sub></a><br /><a href="#translation-mobihen" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XDark187"><img src="https://avatars.githubusercontent.com/u/39034192?v=4?s=100" width="100px;" alt="Baraa"/><br /><sub><b>Baraa</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=XDark187" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/franciscofsales"><img src="https://avatars.githubusercontent.com/u/7977645?v=4?s=100" width="100px;" alt="Francisco Sales"/><br /><sub><b>Francisco Sales</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=franciscofsales" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myselfolli"><img src="https://avatars.githubusercontent.com/u/37535998?v=4?s=100" width="100px;" alt="Oliver Laing"/><br /><sub><b>Oliver Laing</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=myselfolli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/XDark187"><img src="https://avatars.githubusercontent.com/u/39034192?v=4?s=100" width="100px;" alt="Baraa"/><br /><sub><b>Baraa</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=XDark187" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/franciscofsales"><img src="https://avatars.githubusercontent.com/u/7977645?v=4?s=100" width="100px;" alt="Francisco Sales"/><br /><sub><b>Francisco Sales</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=franciscofsales" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myselfolli"><img src="https://avatars.githubusercontent.com/u/37535998?v=4?s=100" width="100px;" alt="Oliver Laing"/><br /><sub><b>Oliver Laing</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=myselfolli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/M0NsTeRRR"><img src="https://avatars.githubusercontent.com/u/37785089?v=4?s=100" width="100px;" alt="Ludovic Ortega"/><br /><sub><b>Ludovic Ortega</b></sub></a><br /><a href="#security-M0NsTeRRR" title="Security">🛡️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://josephrisk.com"><img src="https://avatars.githubusercontent.com/u/18372584?v=4?s=100" width="100px;" alt="Joseph Risk"/><br /><sub><b>Joseph Risk</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=j0srisk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zariel"><img src="https://avatars.githubusercontent.com/u/2213?v=4?s=100" width="100px;" alt="Chris Bannister"/><br /><sub><b>Chris Bannister</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=Zariel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/C4J3"><img src="https://avatars.githubusercontent.com/u/13005453?v=4?s=100" width="100px;" alt="Joe"/><br /><sub><b>Joe</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=C4J3" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://me.garnx.fr"><img src="https://avatars.githubusercontent.com/u/37373941?v=4?s=100" width="100px;" alt="Guillaume ARNOUX"/><br /><sub><b>Guillaume ARNOUX</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=guillaumearnx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dr-carrot"><img src="https://avatars.githubusercontent.com/u/17272571?v=4?s=100" width="100px;" alt="dr-carrot"/><br /><sub><b>dr-carrot</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=dr-carrot" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Loetwiek"><img src="https://avatars.githubusercontent.com/u/79059734?v=4?s=100" width="100px;" alt="Loetwiek"/><br /><sub><b>Loetwiek</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Loetwiek" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fuochi"><img src="https://avatars.githubusercontent.com/u/4720478?v=4?s=100" width="100px;" alt="Fuochi"/><br /><sub><b>Fuochi</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Fuochi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/demrich"><img src="https://avatars.githubusercontent.com/u/30092389?v=4?s=100" width="100px;" alt="David Emrich"/><br /><sub><b>David Emrich</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=demrich" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://maxtrier.dk"><img src="https://avatars.githubusercontent.com/u/5898152?v=4?s=100" width="100px;" alt="Max T. Kristiansen"/><br /><sub><b>Max T. Kristiansen</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=maxnatamo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://damsdev.me"><img src="https://avatars.githubusercontent.com/u/60252259?v=4?s=100" width="100px;" alt="Damien Fajole"/><br /><sub><b>Damien Fajole</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=DamsDev1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AhmedNSidd"><img src="https://avatars.githubusercontent.com/u/36286128?v=4?s=100" width="100px;" alt="Ahmed Siddiqui"/><br /><sub><b>Ahmed Siddiqui</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=AhmedNSidd" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zariel"><img src="https://avatars.githubusercontent.com/u/2213?v=4?s=100" width="100px;" alt="Chris Bannister"/><br /><sub><b>Chris Bannister</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Zariel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gageorsburn"><img src="https://avatars.githubusercontent.com/u/4692734?v=4?s=100" width="100px;" alt="Gage Orsburn"/><br /><sub><b>Gage Orsburn</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=gageorsburn" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GkhnGRBZ"><img src="https://avatars.githubusercontent.com/u/127258824?v=4?s=100" width="100px;" alt="GkhnGRBZ"/><br /><sub><b>GkhnGRBZ</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=GkhnGRBZ" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://benhaney.com"><img src="https://avatars.githubusercontent.com/u/31331498?v=4?s=100" width="100px;" alt="Ben Haney"/><br /><sub><b>Ben Haney</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=benhaney" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Wunderharke"><img src="https://avatars.githubusercontent.com/u/5105672?v=4?s=100" width="100px;" alt="Wunderharke"/><br /><sub><b>Wunderharke</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=Wunderharke" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/methbkts"><img src="https://avatars.githubusercontent.com/u/30674934?v=4?s=100" width="100px;" alt="Metin Bektas"/><br /><sub><b>Metin Bektas</b></sub></a><br /><a href="#infra-methbkts" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrewkolda"><img src="https://avatars.githubusercontent.com/u/158614532?v=4?s=100" width="100px;" alt="andrewkolda"/><br /><sub><b>andrewkolda</b></sub></a><br /><a href="#design-andrewkolda" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ishanjain.me"><img src="https://avatars.githubusercontent.com/u/7921368?v=4?s=100" width="100px;" alt="Ishan Jain"/><br /><sub><b>Ishan Jain</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=ishanjain28" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/C4J3"><img src="https://avatars.githubusercontent.com/u/13005453?v=4?s=100" width="100px;" alt="Joe"/><br /><sub><b>Joe</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=C4J3" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://me.garnx.fr"><img src="https://avatars.githubusercontent.com/u/37373941?v=4?s=100" width="100px;" alt="Guillaume ARNOUX"/><br /><sub><b>Guillaume ARNOUX</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=guillaumearnx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dr-carrot"><img src="https://avatars.githubusercontent.com/u/17272571?v=4?s=100" width="100px;" alt="dr-carrot"/><br /><sub><b>dr-carrot</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=dr-carrot" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gageorsburn"><img src="https://avatars.githubusercontent.com/u/4692734?v=4?s=100" width="100px;" alt="Gage Orsburn"/><br /><sub><b>Gage Orsburn</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=gageorsburn" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://michaelt.xyz"><img src="https://avatars.githubusercontent.com/u/18223295?v=4?s=100" width="100px;" alt="Michael Thomas"/><br /><sub><b>Michael Thomas</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=michaelhthomas" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RankWeis"><img src="https://avatars.githubusercontent.com/u/733691?v=4?s=100" width="100px;" alt="RankWeis"/><br /><sub><b>RankWeis</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=RankWeis" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.linkedin.com/in/jessielwilson"><img src="https://avatars.githubusercontent.com/u/48299282?v=4?s=100" width="100px;" alt="Jessie Wilson"/><br /><sub><b>Jessie Wilson</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=jessielw" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brotaxt"><img src="https://avatars.githubusercontent.com/u/25477935?v=4?s=100" width="100px;" alt="DominicKo"/><br /><sub><b>DominicKo</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=brotaxt" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://doctolib.com"><img src="https://avatars.githubusercontent.com/u/30508927?v=4?s=100" width="100px;" alt="Corentin Normand"/><br /><sub><b>Corentin Normand</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=corentinnormand" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benbeauchamp7"><img src="https://avatars.githubusercontent.com/u/43358492?v=4?s=100" width="100px;" alt="Ben Beauchamp"/><br /><sub><b>Ben Beauchamp</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=benbeauchamp7" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vfaergestad"><img src="https://avatars.githubusercontent.com/u/49147564?v=4?s=100" width="100px;" alt="vfaergestad"/><br /><sub><b>vfaergestad</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=vfaergestad" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wolffman122"><img src="https://avatars.githubusercontent.com/u/19178872?v=4?s=100" width="100px;" alt="wolffman122"/><br /><sub><b>wolffman122</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=wolffman122" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Schrottfresser"><img src="https://avatars.githubusercontent.com/u/39998368?v=4?s=100" width="100px;" alt="Schrottfresser"/><br /><sub><b>Schrottfresser</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=Schrottfresser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DillionLowry"><img src="https://avatars.githubusercontent.com/u/91228469?v=4?s=100" width="100px;" alt="Dillion"/><br /><sub><b>Dillion</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=DillionLowry" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JamsRepos"><img src="https://avatars.githubusercontent.com/u/1347620?v=4?s=100" width="100px;" alt="Jam"/><br /><sub><b>Jam</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=JamsRepos" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.joelowrance.com"><img src="https://avatars.githubusercontent.com/u/63176?v=4?s=100" width="100px;" alt="Joe Lowrance"/><br /><sub><b>Joe Lowrance</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=joelowrance" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/0xSysR3ll"><img src="https://avatars.githubusercontent.com/u/31414959?v=4?s=100" width="100px;" alt="0xsysr3ll"/><br /><sub><b>0xsysr3ll</b></sub></a><br /><a href="https://github.com/fallenbagel/jellyseerr/commits?author=0xSysR3ll" title="Code">💻</a></td>
</tr>
</tbody>
</table>
@@ -280,7 +290,7 @@ Thanks goes to these wonderful people from Overseerr ([emoji key](https://allcon
<td align="center" valign="top" width="14.28%"><a href="https://github.com/byakurau"><img src="https://avatars.githubusercontent.com/u/1811683?v=4?s=100" width="100px;" alt="byakurau"/><br /><sub><b>byakurau</b></sub></a><br /><a href="#translation-byakurau" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/miknii"><img src="https://avatars.githubusercontent.com/u/109232569?v=4?s=100" width="100px;" alt="miknii"/><br /><sub><b>miknii</b></sub></a><br /><a href="#translation-miknii" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Eclipseop"><img src="https://avatars.githubusercontent.com/u/5846213?v=4?s=100" width="100px;" alt="Mackenzie"/><br /><sub><b>Mackenzie</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=Eclipseop" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/s0up4200"><img src="https://avatars.githubusercontent.com/u/18177310?v=4?s=100" width="100px;" alt="soup"/><br /><sub><b>soup</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=s0up4200" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/s0up4200"><img src="https://avatars.githubusercontent.com/u/18177310?v=4?s=100" width="100px;" alt="soup"/><br /><sub><b>soup</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=s0up4200" title="Documentation">📖</a> <a href="https://github.com/sct/overseerr/commits?author=s0up4200" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ceptonit"><img src="https://avatars.githubusercontent.com/u/12678743?v=4?s=100" width="100px;" alt="ceptonit"/><br /><sub><b>ceptonit</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=ceptonit" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aedelbro"><img src="https://avatars.githubusercontent.com/u/36162221?v=4?s=100" width="100px;" alt="aedelbro"/><br /><sub><b>aedelbro</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=aedelbro" title="Code">💻</a></td>
</tr>
@@ -297,7 +307,7 @@ Thanks goes to these wonderful people from Overseerr ([emoji key](https://allcon
<td align="center" valign="top" width="14.28%"><a href="https://izaacj.me"><img src="https://avatars.githubusercontent.com/u/711323?v=4?s=100" width="100px;" alt="Izaac Brånn"/><br /><sub><b>Izaac Brånn</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=IzaacJ" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SalmanTariq"><img src="https://avatars.githubusercontent.com/u/13284494?v=4?s=100" width="100px;" alt="Salman Tariq"/><br /><sub><b>Salman Tariq</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=SalmanTariq" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrew-kennedy"><img src="https://avatars.githubusercontent.com/u/2387159?v=4?s=100" width="100px;" alt="Andrew Kennedy"/><br /><sub><b>Andrew Kennedy</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=andrew-kennedy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fallenbagel"><img src="https://avatars.githubusercontent.com/u/98979876?v=4?s=100" width="100px;" alt="Fallenbagel"/><br /><sub><b>Fallenbagel</b></sub></a><br /><a href="https://github.com/Fallenbagel/jellyseerr/commits?author=Fallenbagel" title="Jellyseerr">🪼⌨️</a> <a href="https://github.com/sct/overseerr/commits?author=Fallenbagel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fallenbagel"><img src="https://avatars.githubusercontent.com/u/98979876?v=4?s=100" width="100px;" alt="Fallenbagel"/><br /><sub><b>Fallenbagel</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=Fallenbagel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://aidoge.xyz"><img src="https://avatars.githubusercontent.com/u/9427639?v=4?s=100" width="100px;" alt="Anton K. (ai Doge)"/><br /><sub><b>Anton K. (ai Doge)</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=scorp200" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://marcofaggian.com"><img src="https://avatars.githubusercontent.com/u/19221001?v=4?s=100" width="100px;" alt="Marco Faggian"/><br /><sub><b>Marco Faggian</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=marcofaggian" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://nemchik.com/"><img src="https://avatars.githubusercontent.com/u/725456?v=4?s=100" width="100px;" alt="Eric Nemchik"/><br /><sub><b>Eric Nemchik</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=nemchik" title="Code">💻</a></td>
@@ -313,6 +323,11 @@ Thanks goes to these wonderful people from Overseerr ([emoji key](https://allcon
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AhmedNSidd"><img src="https://avatars.githubusercontent.com/u/36286128?v=4?s=100" width="100px;" alt="Ahmed Siddiqui"/><br /><sub><b>Ahmed Siddiqui</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=AhmedNSidd" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JackW6809"><img src="https://avatars.githubusercontent.com/u/53652452?v=4?s=100" width="100px;" alt="JackOXI"/><br /><sub><b>JackOXI</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=JackW6809" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://indicus.ro"><img src="https://avatars.githubusercontent.com/u/1199404?v=4?s=100" width="100px;" alt="Stancu Florin"/><br /><sub><b>Stancu Florin</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=StancuFlorin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lmiklosko"><img src="https://avatars.githubusercontent.com/u/44380311?v=4?s=100" width="100px;" alt="Lukas Miklosko"/><br /><sub><b>Lukas Miklosko</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=lmiklosko" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://gauthierth.fr/"><img src="https://avatars.githubusercontent.com/u/37781713?v=4?s=100" width="100px;" alt="Gauthier"/><br /><sub><b>Gauthier</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=gauthier-th" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vfaergestad"><img src="https://avatars.githubusercontent.com/u/49147564?v=4?s=100" width="100px;" alt="vfaergestad"/><br /><sub><b>vfaergestad</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=vfaergestad" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -21,3 +21,5 @@
.idea/
*.tmproj
.vscode/
# go template
*.gotmpl

View File

@@ -1,10 +1,10 @@
apiVersion: v2
kubeVersion: ">=1.23.0-0"
name: Jellyseerr
name: jellyseerr-chart
description: Jellyseerr helm chart for Kubernetes
type: application
version: 1.1.0
appVersion: "2.1.0"
version: 2.6.2
appVersion: "2.7.3"
maintainers:
- name: Jellyseerr
url: https://github.com/Fallenbagel/jellyseerr

View File

@@ -1,6 +1,6 @@
# Jellyseerr
# jellyseerr-chart
![Version: 1.1.0](https://img.shields.io/badge/Version-1.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.1.0](https://img.shields.io/badge/AppVersion-2.1.0-informational?style=flat-square)
![Version: 2.6.2](https://img.shields.io/badge/Version-2.6.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.7.3](https://img.shields.io/badge/AppVersion-2.7.3-informational?style=flat-square)
Jellyseerr helm chart for Kubernetes
@@ -25,10 +25,6 @@ Kubernetes: `>=1.23.0-0`
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | |
| autoscaling.enabled | bool | `false` | |
| autoscaling.maxReplicas | int | `100` | |
| autoscaling.minReplicas | int | `1` | |
| autoscaling.targetCPUUtilizationPercentage | int | `80` | |
| config | object | `{"persistence":{"accessModes":["ReadWriteOnce"],"annotations":{},"name":"","size":"5Gi","volumeName":""}}` | Creating PVC to store configuration |
| config.persistence.accessModes | list | `["ReadWriteOnce"]` | Access modes of persistent disk |
| config.persistence.annotations | object | `{}` | Annotations for PVCs |
@@ -39,7 +35,7 @@ Kubernetes: `>=1.23.0-0`
| extraEnvFrom | list | `[]` | Environment variables from secrets or configmaps to add to the jellyseerr pods |
| fullnameOverride | string | `""` | |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.registry | string | `"docker.io"` | |
| image.registry | string | `"ghcr.io"` | |
| image.repository | string | `"fallenbagel/jellyseerr"` | |
| image.sha | string | `""` | |
| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
@@ -56,6 +52,9 @@ Kubernetes: `>=1.23.0-0`
| podAnnotations | object | `{}` | |
| podLabels | object | `{}` | |
| podSecurityContext | object | `{}` | |
| probes.livenessProbe | object | `{}` | Configure liveness probe |
| probes.readinessProbe | object | `{}` | Configure readiness probe |
| probes.startupProbe | string | `nil` | Configure startup probe |
| replicaCount | int | `1` | |
| resources | object | `{}` | |
| securityContext | object | `{}` | |
@@ -67,3 +66,5 @@ Kubernetes: `>=1.23.0-0`
| serviceAccount.name | string | `""` | If not set and create is true, a name is generated using the fullname template |
| strategy | object | `{"type":"Recreate"}` | Deployment strategy |
| tolerations | list | `[]` | |
| volumeMounts | list | `[]` | Additional volumeMounts on the output Deployment definition. |
| volumes | list | `[]` | Additional volumes on the output Deployment definition. |

View File

@@ -0,0 +1 @@
repositoryID: c6b3f2dc-444c-4e37-b397-6a5ff563ee8b

View File

@@ -5,9 +5,7 @@ metadata:
labels:
{{- include "jellyseerr.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
strategy:
type: {{ .Values.strategy.type }}
selector:
@@ -50,10 +48,44 @@ spec:
httpGet:
path: /
port: http
{{- if .Values.probes.livenessProbe.initialDelaySeconds }}
initialDelaySeconds: {{ .Values.probes.livenessProbe.initialDelaySeconds }}
{{- end }}
{{- if .Values.probes.livenessProbe.periodSeconds }}
periodSeconds: {{ .Values.probes.livenessProbe.periodSeconds }}
{{- end }}
{{- if .Values.probes.livenessProbe.timeoutSeconds }}
timeoutSeconds: {{ .Values.probes.livenessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.probes.livenessProbe.successThreshold }}
successThreshold: {{ .Values.probes.livenessProbe.successThreshold }}
{{- end }}
{{- if .Values.probes.livenessProbe.failureThreshold }}
failureThreshold: {{ .Values.probes.livenessProbe.failureThreshold }}
{{- end }}
readinessProbe:
httpGet:
path: /
port: http
{{- if .Values.probes.readinessProbe.initialDelaySeconds }}
initialDelaySeconds: {{ .Values.probes.readinessProbe.initialDelaySeconds }}
{{- end }}
{{- if .Values.probes.readinessProbe.periodSeconds }}
periodSeconds: {{ .Values.probes.readinessProbe.periodSeconds }}
{{- end }}
{{- if .Values.probes.readinessProbe.timeoutSeconds }}
timeoutSeconds: {{ .Values.probes.readinessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.probes.readinessProbe.successThreshold }}
successThreshold: {{ .Values.probes.readinessProbe.successThreshold }}
{{- end }}
{{- if .Values.probes.readinessProbe.failureThreshold }}
failureThreshold: {{ .Values.probes.readinessProbe.failureThreshold }}
{{- end }}
{{- if .Values.probes.startupProbe }}
startupProbe:
{{- toYaml .Values.probes.startupProbe | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.extraEnv }}
@@ -67,10 +99,16 @@ spec:
volumeMounts:
- name: config
mountPath: /app/config
{{- with .Values.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: config
persistentVolumeClaim:
claimName: {{ include "jellyseerr.configPersistenceName" . }}
{{- with .Values.volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}

View File

@@ -4,6 +4,10 @@ metadata:
name: {{ include "jellyseerr.configPersistenceName" . }}
labels:
{{- include "jellyseerr.labels" . | nindent 4 }}
{{- with .Values.config.persistence.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.config.persistence.accessModes }}
accessModes:

View File

@@ -1,7 +1,7 @@
replicaCount: 1
image:
registry: docker.io
registry: ghcr.io
repository: fallenbagel/jellyseerr
pullPolicy: IfNotPresent
# -- Overrides the image tag whose default is the chart appVersion.
@@ -16,6 +16,27 @@ fullnameOverride: ""
strategy:
type: Recreate
# Liveness / Readiness / Startup Probes
probes:
# -- Configure liveness probe
livenessProbe: {}
# initialDelaySeconds: 60
# periodSeconds: 30
# timeoutSeconds: 5
# successThreshold: 1
# failureThreshold: 5
# -- Configure readiness probe
readinessProbe: {}
# initialDelaySeconds: 60
# periodSeconds: 30
# timeoutSeconds: 5
# successThreshold: 1
# failureThreshold: 5
# -- Configure startup probe
startupProbe: null
# tcpSocket:
# port: http
# -- Environment variables to add to the jellyseerr pods
extraEnv: []
# -- Environment variables from secrets or configmaps to add to the jellyseerr pods
@@ -36,15 +57,15 @@ podAnnotations: {}
podLabels: {}
podSecurityContext: {}
# fsGroup: 2000
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
@@ -70,8 +91,8 @@ ingress:
enabled: false
ingressClassName: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
@@ -83,23 +104,29 @@ ingress:
# - chart-example.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
# -- Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
# -- Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: {}

View File

@@ -1,32 +0,0 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "jellyseerr.fullname" . }}
labels:
{{- include "jellyseerr.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "jellyseerr.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

View File

@@ -4,6 +4,7 @@ export default defineConfig({
projectId: 'xkm1b4',
e2e: {
baseUrl: 'http://localhost:5055',
video: true,
experimentalSessionAndOrigin: true,
},
env: {

View File

@@ -4,9 +4,8 @@
"vapidPublic": "BK_EpP8NDm9waor2zn6_S28o3ZYv4kCkJOfYpO3pt3W6jnPmxrgTLANUBNbbyaNatPnSQ12De9CeqSYQrqWzHTs",
"main": {
"apiKey": "testkey",
"applicationTitle": "Overseerr",
"applicationTitle": "Jellyseerr",
"applicationUrl": "",
"csrfProtection": false,
"cacheImages": false,
"defaultPermissions": 32,
"defaultQuotas": {
@@ -19,6 +18,8 @@
"discoverRegion": "",
"streamingRegion": "",
"originalLanguage": "",
"blacklistedTags": "",
"blacklistedTagsLimit": 50,
"trustProxy": false,
"mediaServerType": 1,
"partialRequestsEnabled": true,
@@ -69,7 +70,7 @@
"ignoreTls": false,
"requireTls": false,
"allowSelfSigned": false,
"senderName": "Overseerr"
"senderName": "Jellyseerr"
}
},
"discord": {
@@ -81,13 +82,6 @@
"enableMentions": true
}
},
"lunasea": {
"enabled": false,
"types": 0,
"options": {
"webhookUrl": ""
}
},
"slack": {
"enabled": false,
"types": 0,
@@ -137,7 +131,16 @@
"types": 0,
"options": {
"url": "",
"token": ""
"token": "",
"priority": 0
}
},
"ntfy": {
"enabled": false,
"types": 0,
"options": {
"url": "",
"topic": ""
}
}
}
@@ -176,5 +179,26 @@
"image-cache-cleanup": {
"schedule": "0 0 5 * * *"
}
},
"network": {
"csrfProtection": false,
"trustProxy": false,
"forceIpv4First": false,
"dnsServers": "",
"proxy": {
"enabled": false,
"hostname": "",
"port": 8080,
"useSsl": false,
"user": "",
"password": "",
"bypassFilter": "",
"bypassLocalAddresses": true
},
"dnsCache": {
"enabled": false,
"forceMinTtl": 0,
"forceMaxTtl": -1
}
}
}

View File

@@ -0,0 +1,148 @@
describe('TVDB Integration', () => {
// Constants for routes and selectors
const ROUTES = {
home: '/',
metadataSettings: '/settings/metadata',
tomorrowIsOursTvShow: '/tv/72879',
monsterTvShow: '/tv/225634',
dragonnBallZKaiAnime: '/tv/61709',
};
const SELECTORS = {
sidebarToggle: '[data-testid=sidebar-toggle]',
sidebarSettingsMobile: '[data-testid=sidebar-menu-settings-mobile]',
settingsNavDesktop: 'nav[data-testid="settings-nav-desktop"]',
metadataTestButton: 'button[type="button"]:contains("Test")',
metadataSaveButton: '[data-testid="metadata-save-button"]',
tmdbStatus: '[data-testid="tmdb-status"]',
tvdbStatus: '[data-testid="tvdb-status"]',
tvMetadataProviderSelector: '[data-testid="tv-metadata-provider-selector"]',
animeMetadataProviderSelector:
'[data-testid="anime-metadata-provider-selector"]',
seasonSelector: '[data-testid="season-selector"]',
season1: 'Season 1',
season2: 'Season 2',
season3: 'Season 3',
episodeList: '[data-testid="episode-list"]',
episode9: '9 - Hang Men',
};
// Reusable commands
const navigateToMetadataSettings = () => {
cy.visit(ROUTES.home);
cy.get(SELECTORS.sidebarToggle).click();
cy.get(SELECTORS.sidebarSettingsMobile).click();
cy.get(
`${SELECTORS.settingsNavDesktop} a[href="${ROUTES.metadataSettings}"]`
).click();
};
const testAndVerifyMetadataConnection = () => {
cy.intercept('POST', '/api/v1/settings/metadatas/test').as(
'testConnection'
);
cy.get(SELECTORS.metadataTestButton).click();
return cy.wait('@testConnection');
};
const saveMetadataSettings = (customBody = null) => {
if (customBody) {
cy.intercept('PUT', '/api/v1/settings/metadatas', (req) => {
req.body = customBody;
}).as('saveMetadata');
} else {
// Else just intercept without modifying body
cy.intercept('PUT', '/api/v1/settings/metadatas').as('saveMetadata');
}
cy.get(SELECTORS.metadataSaveButton).click();
return cy.wait('@saveMetadata');
};
beforeEach(() => {
// Perform login
cy.login(Cypress.env('ADMIN_EMAIL'), Cypress.env('ADMIN_PASSWORD'));
// Navigate to Metadata settings
navigateToMetadataSettings();
// Verify we're on the correct settings page
cy.contains('h3', 'Metadata Providers').should('be.visible');
// Configure TVDB as TV provider and test connection
cy.get(SELECTORS.tvMetadataProviderSelector).click();
// get id react-select-4-option-1
cy.get('[class*="react-select__option"]').contains('TheTVDB').click();
// Test the connection
testAndVerifyMetadataConnection().then(({ response }) => {
expect(response.statusCode).to.equal(200);
// Check TVDB connection status
cy.get(SELECTORS.tvdbStatus).should('contain', 'Operational');
});
// Save settings
saveMetadataSettings({
anime: 'tvdb',
tv: 'tvdb',
}).then(({ response }) => {
expect(response.statusCode).to.equal(200);
expect(response.body.tv).to.equal('tvdb');
});
});
it('should display "Tomorrow is Ours" show information with multiple seasons from TVDB', () => {
// Navigate to the TV show
cy.visit(ROUTES.tomorrowIsOursTvShow);
// Verify that multiple seasons are displayed (TMDB has only 1 season, TVDB has multiple)
// cy.get(SELECTORS.seasonSelector).should('exist');
cy.intercept('/api/v1/tv/225634/season/1').as('season1');
// Select Season 2 and verify it loads
cy.contains(SELECTORS.season2)
.should('be.visible')
.scrollIntoView()
.click();
// Verify that episodes are displayed for Season 2
cy.contains('260 - Episode 506').should('be.visible');
});
it('Should display "Monster" show information correctly when not existing on TVDB', () => {
// Navigate to the TV show
cy.visit(ROUTES.monsterTvShow);
// Intercept season 1 request
cy.intercept('/api/v1/tv/225634/season/1').as('season1');
// Select Season 1
cy.contains(SELECTORS.season1)
.should('be.visible')
.scrollIntoView()
.click();
// Wait for the season data to load
cy.wait('@season1');
// Verify specific episode exists
cy.contains(SELECTORS.episode9).should('be.visible');
});
it('should display "Dragon Ball Z Kai" show information with multiple only 2 seasons from TVDB', () => {
// Navigate to the TV show
cy.visit(ROUTES.dragonnBallZKaiAnime);
// Intercept season 1 request
cy.intercept('/api/v1/tv/61709/season/1').as('season1');
// Select Season 2 and verify it visible
cy.contains(SELECTORS.season2)
.should('be.visible')
.scrollIntoView()
.click();
// select season 3 and verify it not visible
cy.contains(SELECTORS.season3).should('not.exist');
});
});

View File

@@ -13,10 +13,10 @@ describe('General Settings', () => {
});
it('modifies setting that requires restart', () => {
cy.visit('/settings');
cy.visit('/settings/network');
cy.get('#trustProxy').click();
cy.get('[data-testid=settings-main-form]').submit();
cy.get('[data-testid=settings-network-form]').submit();
cy.get('[data-testid=modal-title]').should(
'contain',
'Server Restart Required'
@@ -26,7 +26,7 @@ describe('General Settings', () => {
cy.get('[data-testid=modal-title]').should('not.exist');
cy.get('[type=checkbox]#trustProxy').click();
cy.get('[data-testid=settings-main-form]').submit();
cy.get('[data-testid=settings-network-form]').submit();
cy.get('[data-testid=modal-title]').should('not.exist');
});
});

View File

@@ -6,7 +6,6 @@ Cypress.Commands.add('login', (email, password) => {
[email, password],
() => {
cy.visit('/login');
cy.contains('Use your Overseerr account').click();
cy.get('[data-testid=email]').type(email);
cy.get('[data-testid=password]').type(password);

View File

@@ -7,31 +7,34 @@ sidebar_position: 1
Welcome to the Jellyseerr Documentation.
**Jellyseerr** is a free and open source software application for managing requests for your media library. It integrates with the media server of your choice: [Jellyfin](https://jellyfin.org), [Plex](https://plex.tv), and [Emby](https://emby.media/). In addition, it integrates with your existing services, such as **[Sonarr](https://sonarr.tv/)**, **[Radarr](https://radarr.video/)**.
## Features
- **Full Jellyfin/Emby/Plex integration**. Login and manage user access with Jellyfin/Emby/Plex.
- **Syncs to your Jellyfin/Emby/Plex library** to show what titles you already have.
- Supports Movies, Shows and Mixed Libraries.
- **Integrates with Sonarr and Radarr**. With more services to come in the future.
- Optionally set **Override rules** for requests to match with your defined conditions.
- **Easy to use request system** allowing users to request individual seasons or movies in a friendly, clean UI.
- **Simple request management UI**. Don't dig through the app to approve recent requests.
- **Mobile-friendly design**, for when you need to approve requests on the go.
- Granular permission system.
- Localization into other languages.
- Support for PostgreSQL and SQLite databases.
- Support for **PostgreSQL** and **SQLite** databases.
- Support for various notification agents.
- Easily **Watchlist** or **Blacklist** media.
- More features to come!
## Motivation
The primary motivation for starting this project was to add support for Jellyfin and Emby to Overseerr. As Overseerr is an incredibly performant and easy-to-use application, we wanted to bring that same experience to Jellyfin and Emby users. Thus, **Jellyseerr** was born.
This application is designed to be a **one-stop-shop** for all your media requests. It is designed to be a **simple, easy-to-use** application that allows users to request media to be added to your Jellyfin/Emby/Plex server.
The primary motivation for starting Jellyseerr was to bring Jellyfin and Emby support to Overseerr. However, over time, **Jellyseerr** has evolved into its own distinct application with unique features. Designed as a one-stop shop for media requests, it offers a simple, easy-to-use experience for managing requests on Jellyfin, Emby, and Plex servers.
## We need your help!
[Jellyseerr](https://github.com/Fallenbagel/jellyseerr) is a fork of Overseerr, with a heavy focus on Jellyfin and Emby integration.
[Overseerr](https://github.com/sct/overseerr) is an ambitious project where the original developers/contributors have already poured a lot of work into, and we wanted to build on top of that.
[Jellyseerr](https://github.com/Fallenbagel/jellyseerr) is an ambitious project where developers/contributors poured a lot of work into, and that builds on top of [Overseerr](https://github.com/sct/overseerr). And we have a lot more to do as well.
We also have poured a lot of work into this project, and we have a lot more to do as well. We need your valuable feedback and help to find and fix bugs. Also, with Jellyseerr being an open-source project, anyone is welcome to contribute. We also encourage you to contribute to Overseerr as well.
We value your feedback and support in identifying and fixing bugs to make Jellyseerr even better. As an open-source project, we welcome contributions from everyone. While Jellyseerr has diverged from Overseerr and evolved into its own unique application, we still encourage contributions to Overseerr, as it played a crucial role in inspiring what Jellyseerr has become today.
Contribution includes building new features, patching bugs, translating the application, or even just writing documentation.

View File

@@ -9,25 +9,66 @@ Jellyseerr supports SQLite and PostgreSQL. The database connection can be config
## SQLite Options
If you want to use SQLite, you can simply set the `DB_TYPE` environment variable to `sqlite`. This is the default configuration so even if you don't set any other options, SQLite will be used.
```dotenv
DB_TYPE="sqlite" # Which DB engine to use, either "sqlite" or "postgres". The default is "sqlite".
DB_TYPE=sqlite # Which DB engine to use, either sqlite or postgres. The default is sqlite.
CONFIG_DIRECTORY="config" # (optional) The path to the config directory where the db file is stored. The default is "config".
DB_LOG_QUERIES="false" # (optional) Whether to log the DB queries for debugging. The default is "false".
```
## PostgreSQL Options
### TCP Connection
If your PostgreSQL server is configured to accept TCP connections, you can specify the host and port using the `DB_HOST` and `DB_PORT` environment variables. This is useful for remote connections where the server uses a network host and port.
```dotenv
DB_TYPE="postgres" # Which DB engine to use, either "sqlite" or "postgres". The default is "sqlite". To use postgres, this needs to be set to "postgres"
DB_HOST="localhost" # (optional) The host (url) of the database. The default is "localhost".
DB_TYPE=postgres # Which DB engine to use, either sqlite or postgres. The default is sqlite.
DB_HOST="localhost" # (optional) The host (URL) of the database. The default is "localhost".
DB_PORT="5432" # (optional) The port to connect to. The default is "5432".
DB_USER= # (required) Username used to connect to the database
DB_PASS= # (required) Password of the user used to connect to the database
DB_USER= # (required) Username used to connect to the database.
DB_PASS= # (required) Password of the user used to connect to the database.
DB_NAME="jellyseerr" # (optional) The name of the database to connect to. The default is "jellyseerr".
DB_LOG_QUERIES="false" # (optional) Whether to log the DB queries for debugging. The default is "false".
```
### Unix Socket Connection
If your PostgreSQL server is configured to accept Unix socket connections, you can specify the path to the socket directory using the `DB_SOCKET_PATH` environment variable. This is useful for local connections where the server uses a Unix socket.
```dotenv
DB_TYPE=postgres # Which DB engine to use, either sqlite or postgres. The default is sqlite.
DB_SOCKET_PATH="/var/run/postgresql" # (required) The path to the PostgreSQL Unix socket directory.
DB_USER= # (required) Username used to connect to the database.
DB_PASS= # (optional) Password of the user used to connect to the database, depending on the server's authentication configuration.
DB_NAME="jellyseerr" # (optional) The name of the database to connect to. The default is "jellyseerr".
DB_LOG_QUERIES="false" # (optional) Whether to log the DB queries for debugging. The default is "false".
```
:::info
**Finding Your PostgreSQL Socket Path**
The PostgreSQL socket path varies by operating system and installation method:
- **Ubuntu/Debian**: `/var/run/postgresql`
- **CentOS/RHEL/Fedora**: `/var/run/postgresql`
- **macOS (Homebrew)**: `/tmp` or `/opt/homebrew/var/postgresql`
- **macOS (Postgres.app)**: `/tmp`
- **Windows**: Not applicable (uses TCP connections)
You can find your socket path by running:
```bash
# Find PostgreSQL socket directory
find /tmp /var/run /run -name ".s.PGSQL.*" 2>/dev/null | head -1 | xargs dirname
# Or check PostgreSQL configuration
sudo -u postgres psql -c "SHOW unix_socket_directories;"
```
:::
### SSL configuration
The following options can be used to further configure ssl. Certificates can be provided as a string or a file path, with the string version taking precedence.
```dotenv
@@ -36,26 +77,89 @@ DB_SSL_REJECT_UNAUTHORIZED="true" # (optional) Whether to reject ssl connections
DB_SSL_CA= # (optional) The CA certificate to verify the connection, provided as a string. The default is "".
DB_SSL_CA_FILE= # (optional) The path to a CA certificate to verify the connection. The default is "".
DB_SSL_KEY= # (optional) The private key for the connection in PEM format, provided as a string. The default is "".
DB_SSL_KEY_FILE= # (optinal) Path to the private key for the connection in PEM format. The default is "".
DB_SSL_KEY_FILE= # (optional) Path to the private key for the connection in PEM format. The default is "".
DB_SSL_CERT= # (optional) Certificate chain in pem format for the private key, provided as a string. The default is "".
DB_SSL_CERT_FILE= # (optional) Path to certificate chain in pem format for the private key. The default is "".
```
---
### Migrating from SQLite to PostgreSQL
1. Set up your PostgreSQL database and configure Jellyseerr to use it
2. Run Jellyseerr to create the tables in the PostgreSQL database
3. Stop Jellyseerr
4. Run the following command to export the data from the SQLite database and import it into the PostgreSQL database:
:::info
Edit the postgres connection string to match your setup
Edit the postgres connection string (without the \{\{ and \}\} brackets) to match your setup.
If you don't have or don't want to use docker, you can build the working pgloader version [in this PR](https://github.com/dimitri/pgloader/pull/1531) from source and use the same options as below.
:::
:::caution
The most recent release of pgloader has an issue quoting the table columns. Use the version in the docker container to avoid this issue.
:::
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs>
<TabItem value="docker" label="Using pgloader Container (Recommended)" default>
**Recommended method**: Use the pgloader container even for standalone Jellyseerr installations. This avoids building from source and ensures compatibility.
```bash
docker run --rm -v config/db.sqlite3:/db.sqlite3:ro -v pgloader/pgloader.load:/pgloader.load ghcr.io/ralgar/pgloader:pr-1531 pgloader --with "quote identifiers" --with "data only" /db.sqlite3 postgresql://{{DB_USER}}:{{DB_PASS}}@{{DB_HOST}}:{{DB_PORT}}/{{DB_NAME}}
```
# For standalone installations (no Docker network needed)
docker run --rm \
-v /path/to/your/config/db.sqlite3:/db.sqlite3:ro \
ghcr.io/ralgar/pgloader:pr-1531 \
pgloader --with "quote identifiers" --with "data only" \
/db.sqlite3 postgresql://{{DB_USER}}:{{DB_PASS}}@{{DB_HOST}}:{{DB_PORT}}/{{DB_NAME}}
```
**For Docker Compose setups**: Add the network parameter if your PostgreSQL is also in a container:
```bash
docker run --rm \
--network your-jellyseerr-network \
-v /path/to/your/config/db.sqlite3:/db.sqlite3:ro \
ghcr.io/ralgar/pgloader:pr-1531 \
pgloader --with "quote identifiers" --with "data only" \
/db.sqlite3 postgresql://{{DB_USER}}:{{DB_PASS}}@{{DB_HOST}}:{{DB_PORT}}/{{DB_NAME}}
```
</TabItem>
<TabItem value="standalone" label="Building pgloader from Source">
For users who prefer not to use Docker or need a custom build:
```bash
# Clone the repository and checkout the working version
git clone https://github.com/dimitri/pgloader.git
cd pgloader
git fetch origin pull/1531/head:pr-1531
git checkout pr-1531
# Follow the official installation instructions
# See: https://github.com/dimitri/pgloader/blob/master/INSTALL.md
```
:::info
**Building pgloader from source requires following the complete installation process outlined in the [official pgloader INSTALL.md](https://github.com/dimitri/pgloader/blob/master/INSTALL.md).**
Please refer to the official documentation for detailed, up-to-date installation instructions.
:::
Once pgloader is built, run the migration:
```bash
# Run migration (adjust path to your config directory)
./pgloader --with "quote identifiers" --with "data only" \
/path/to/your/config/db.sqlite3 \
postgresql://{{DB_USER}}:{{DB_PASS}}@{{DB_HOST}}:{{DB_PORT}}/{{DB_NAME}}
```
</TabItem>
</Tabs>
5. Start Jellyseerr

View File

@@ -207,3 +207,62 @@ labels:
```
For more information, please refer to the [Traefik documentation](https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/).
## Apache2 HTTP Server
<Tabs groupId="apache2-reverse-proxy" queryString>
<TabItem value="subdomain" label="Subdomain">
Add the following Location block to your existing Server configuration.
```apache
# Jellyseerr
ProxyPreserveHost On
ProxyPass / http://localhost:5055 retry=0 connectiontimeout=5 timeout=30 keepalive=on
ProxyPassReverse http://localhost:5055 /
RequestHeader set Connection ""
```
</TabItem>
<TabItem value="subfolder" label="Subfolder">
:::warning
This Apache2 subfolder reverse proxy is an unsupported workaround, and only provided as an example. The filters may stop working when Jellyseerr is updated.
If you encounter any issues with Jellyseerr while using this workaround, we may ask you to try to reproduce the problem without the Apache2 proxy.
:::
Add the following Location block to your existing Server configuration.
```apache
# Jellyseerr
# We will use "/jellyseerr" as subfolder
# You can replace it with any that you like
<Location /jellyseerr>
ProxyPreserveHost On
ProxyPass http://localhost:5055 retry=0 connectiontimeout=5 timeout=30 keepalive=on
ProxyPassReverse http://localhost:5055
RequestHeader set Connection ""
# Header update, to support subfolder
# Please Replace "FQDN" with your domain
Header edit location ^/login https://FQDN/jellyseerr/login
Header edit location ^/setup https://FQDN/jellyseerr/setup
AddOutputFilterByType INFLATE;SUBSTITUTE text/html application/javascript application/json
SubstituteMaxLineLength 2000K
# This is HTML and JS update
# Please update "/jellyseerr" if needed
Substitute "s|href=\"|href=\"/jellyseerr|inq"
Substitute "s|src=\"|src=\"/jellyseerr|inq"
Substitute "s|/api/|/jellyseerr/api/|inq"
Substitute "s|\"/_next/|\"/jellyseerr/_next/|inq"
# This is JSON update
Substitute "s|\"/avatarproxy/|\"/jellyseerr/avatarproxy/|inq"
</Location>
```
</TabItem>
</Tabs>

View File

@@ -6,13 +6,15 @@ sidebar_position: 2
# Build from Source (Advanced)
:::warning
This method is not recommended for most users. It is intended for advanced users who are familiar with managing their own server infrastructure.
Refer to [Configuring Databases](/extending-jellyseerr/database-config#postgresql-options) for details on how to configure your database.
:::
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
### Prerequisites
- [Node.js 20.x](https://nodejs.org/en/download/)
- [Node.js 22.x](https://nodejs.org/en/download/)
- [Pnpm 9.x](https://pnpm.io/installation)
- [Git](https://git-scm.com/downloads)
@@ -253,7 +255,8 @@ To run jellyseerr as a service:
1. Download the [Non-Sucking Service Manager](https://nssm.cc/download)
2. Install NSSM:
```powershell
nssm install Jellyseerr "C:\Program Files\nodejs\node.exe" ["C:\jellyseerr\dist\index.js"]
nssm install Jellyseerr "C:\Program Files\nodejs\node.exe" "C:\jellyseerr\dist\index.js"
nssm set Jellyseerr AppDirectory "C:\jellyseerr"
nssm set Jellyseerr AppEnvironmentExtra NODE_ENV=production
```
3. Start the service:

View File

@@ -7,6 +7,8 @@ sidebar_position: 1
:::info
This is the recommended method for most users.
Details on how to install Docker can be found on the [official Docker website](https://docs.docker.com/get-docker/).
Refer to [Configuring Databases](/extending-jellyseerr/database-config#postgresql-options) for details on how to configure your database.
:::
## Unix (Linux, macOS)
@@ -31,17 +33,23 @@ docker run -d \
--name jellyseerr \
-e LOG_LEVEL=debug \
-e TZ=Asia/Tashkent \
-e PORT=5055 `#optional` \
-e PORT=5055 \
-p 5055:5055 \
-v /path/to/appdata/config:/app/config \
--restart unless-stopped \
fallenbagel/jellyseerr
```
:::tip
If you are using emby, make sure to set the `JELLYFIN_TYPE` environment variable to `emby`.
`-e JELLYFIN_TYPE=emby`
:::
The argument `-e PORT=5055` is optional.
If you want to add a healthcheck to the above command, you can add the following flags :
```
--health-cmd "wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status || exit 1" \
--health-start-period 20s \
--health-timeout 3s \
--health-interval 15s \
--health-retries 3 \
```
To run the container as a specific user/group, you may optionally add `--user=[ user | user:group | uid | uid:gid | user:gid | uid:group ]` to the above command.
@@ -49,7 +57,7 @@ To run the container as a specific user/group, you may optionally add `--user=[
Stop and remove the existing container:
```bash
docker stop jellyseerr && docker rm Jellyseerr
docker stop jellyseerr && docker rm jellyseerr
```
Pull the latest image:
```bash
@@ -86,11 +94,14 @@ services:
- 5055:5055
volumes:
- /path/to/appdata/config:/app/config
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status || exit 1
start_period: 20s
timeout: 3s
interval: 15s
retries: 3
restart: unless-stopped
```
:::tip
If you are using emby, make sure to set the `JELLYFIN_TYPE` environment variable to `emby`.
:::
Then, start all services defined in the Compose file:
```bash
@@ -119,8 +130,7 @@ You may alternatively use a third-party mechanism like [dockge](https://github.c
2. Inside the **Community Applications** app store, search for **Jellyseerr**.
3. Click the **Install Button**.
4. On the following **Add Container** screen, make changes to the **Host Port** and **Host Path 1** \(Appdata\) as needed.
5. If you want to use emby, make sure to set the `JELLYFIN_TYPE` environment variable to `emby`. Otherwise, remove the variable.
6. Click apply and access "Jellyseerr" at your `<ServerIP:HostPort>` in a web browser.
5. Click apply and access "Jellyseerr" at your `<ServerIP:HostPort>` in a web browser.
## Windows
@@ -144,7 +154,36 @@ Then, create and start the Jellyseerr container:
<Tabs groupId="docker-methods" queryString>
<TabItem value="docker-cli" label="Docker CLI">
```bash
docker run -d --name jellyseerr -e LOG_LEVEL=debug -e TZ=Asia/Tashkent -p 5055:5055 -v "jellyseerr-data:/app/config" --restart unless-stopped fallenbagel/jellyseerr:latest
docker run -d \
--name jellyseerr \
-e LOG_LEVEL=debug \
-e TZ=Asia/Tashkent \
-e PORT=5055 \
-p 5055:5055 \
-v jellyseerr-data:/app/config \
--restart unless-stopped \
fallenbagel/jellyseerr
```
The argument `-e PORT=5055` is optional.
If you want to add a healthcheck to the above command, you can add the following flags :
```
--health-cmd "wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status || exit 1" \
--health-start-period 20s \
--health-timeout 3s \
--health-interval 15s \
--health-retries 3 \
```
#### Updating:
Pull the latest image:
```bash
docker compose pull jellyseerr
```
Then, restart all services defined in the Compose file:
```bash
docker compose up -d
```
</TabItem>
@@ -162,21 +201,31 @@ services:
- 5055:5055
volumes:
- jellyseerr-data:/app/config
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status || exit 1
start_period: 20s
timeout: 3s
interval: 15s
retries: 3
restart: unless-stopped
volumes:
jellyseerr-data:
external: true
```
#### Updating:
Pull the latest image:
```bash
docker compose pull jellyseerr
```
Then, restart all services defined in the Compose file:
```bash
docker compose up -d
```
</TabItem>
</Tabs>
:::tip
If you are using a named volume, then you can safely **ignore** the warning about the `/app/config` folder being incorrectly mounted.
If you are using emby, make sure to set the `JELLYFIN_TYPE` environment variable to `emby`.
:::
To access the files inside the volume created above, navigate to `\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\jellyseerr-data\_data` using File Explorer.
:::info
@@ -185,3 +234,6 @@ Docker on Windows works differently than it does on Linux; it runs Docker inside
**If you must run Docker on Windows, you should put the `/app/config` directory mount inside the VM and not on the Windows host.** (This also applies to other containers with SQLite databases.)
Named volumes, like in the example commands above, are automatically mounted inside the VM. Therefore the warning on the setup about the `/app/config` folder being incorrectly mounted page should be ignored.
:::

View File

@@ -0,0 +1,21 @@
---
title: Kubernetes
description: Install Jellyseerr in Kubernetes
sidebar_position: 5
---
# Kubernetes
:::info
This method is not recommended for most users. It is intended for advanced users who are using Kubernetes.
:::
## Installation
```console
helm install jellyseerr oci://ghcr.io/fallenbagel/jellyseerr/jellyseerr-chart
```
Helm values can be found in the Jellyseerr repository under [charts/jellyseerr-chart/README.md](https://github.com/Fallenbagel/jellyseerr/tree/develop/charts/jellyseerr-chart).
Verify the signature with [cosign](https://docs.sigstore.dev/cosign/system_config/installation/) (replace [tag], with the TAG you want to verify) :
```console
cosign verify ghcr.io/fallenbagel/jellyseerr/jellyseerr-chart:[tag] --certificate-identity=https://github.com/Fallenbagel/jellyseerr/.github/workflows/helm.yml@refs/heads/main --certificate-oidc-issuer=https://token.ac
tions.githubusercontent.com
```

View File

@@ -6,6 +6,8 @@ sidebar_position: 3
import { JellyseerrVersion, NixpkgVersion } from '@site/src/components/JellyseerrVersion';
import Admonition from '@theme/Admonition';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Nix Package Manager (Advanced)
:::info
@@ -13,22 +15,55 @@ This method is not recommended for most users. It is intended for advanced users
:::
export const VersionMismatchWarning = () => {
const jellyseerrVersion = JellyseerrVersion();
const nixpkgVersion = NixpkgVersion();
let jellyseerrVersion = null;
let nixpkgVersions = null;
try {
jellyseerrVersion = JellyseerrVersion();
nixpkgVersions = NixpkgVersion();
} catch (err) {
return (
<Admonition type="error">
Failed to load version information. Error: {err.message || JSON.stringify(err)}
</Admonition>
);
}
const isUpToDate = jellyseerrVersion === nixpkgVersion;
if (!nixpkgVersions || nixpkgVersions.error) {
return (
<Admonition type="error">
Failed to fetch Nixpkg versions: {nixpkgVersions?.error || 'Unknown error'}
</Admonition>
);
}
const isUnstableUpToDate = jellyseerrVersion === nixpkgVersions.unstable;
const isStableUpToDate = jellyseerrVersion === nixpkgVersions.stable;
return (
<>
{!isUpToDate ? (
<Admonition type="warning">
The <a href="https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/servers/jellyseerr/default.nix#L14">upstream Jellyseerr Nix Package (v{nixpkgVersion})</a> is not <b>up-to-date</b>. If you want to use <b>Jellyseerr v{jellyseerrVersion}</b>, you will need to <a href="#overriding-the-package-derivation">override the package derivation</a>.
</Admonition>
) : (
<Admonition type="success">
The <a href="https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/servers/jellyseerr/default.nix#L14">upstream Jellyseerr Nix Package (v{nixpkgVersion})</a> is <b>up-to-date</b> with <b>Jellyseerr v{jellyseerrVersion}</b>.
</Admonition>
)}
<>
{!isStableUpToDate ? (
<Admonition type="warning">
The{' '}
<a href="https://github.com/NixOS/nixpkgs/blob/nixos-24.11/pkgs/servers/jellyseerr/default.nix#L14">
upstream Jellyseerr Nix Package (v{nixpkgVersions.stable})
</a>{' '}
is not <b>up-to-date</b>. If you want to use <b>Jellyseerr v{jellyseerrVersion}</b>,{' '}
{isUnstableUpToDate ? (
<>
consider using the{' '}
<a href="https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/by-name/je/jellyseerr/package.nix">
unstable package
</a>{' '}
instead.
</>
) : (
<>
you will need to{' '}
<a href="#overriding-the-package-derivation">override the package derivation</a>.
</>
)}
</Admonition>
) : null}
</>
);
};
@@ -48,6 +83,8 @@ To get up and running with jellyseerr using Nix, you can add the following to yo
If you want more advanced configuration options, you can use the following:
<Tabs groupId="nixpkg-methods" queryString>
<TabItem value="default" label="Default Configurations">
```nix
{ config, pkgs, ... }:
@@ -56,53 +93,20 @@ If you want more advanced configuration options, you can use the following:
enable = true;
port = 5055;
openFirewall = true;
package = pkgs.jellyseerr; # Use the unstable package if stable is not up-to-date
};
}
```
After adding the configuration to your `configuration.nix`, you can run the following command to install jellyseerr:
```bash
nixos-rebuild switch
```
After rebuild is complete jellyseerr should be running, verify that it is with the following command.
```bash
systemctl status jellyseerr
```
:::info
You can now access Jellyseerr by visiting `http://localhost:5055` in your web browser.
:::
import CodeBlock from '@theme/CodeBlock';
## Overriding the package derivation
export const VersionMatch = () => {
const jellyseerrVersion = JellyseerrVersion();
const nixpkgVersion = NixpkgVersion();
const code = `{ config, pkgs, ... }:
</TabItem>
<TabItem value="custom" label="Database Configurations">
In order to use postgres, you will need to add override the default module of jellyseerr with the following as the current default module is not compatible with postgres:
```nix
{
nixpkgs.config.packageOverrides = pkgs: {
jellyseerr = pkgs.jellyseerr.overrideAttrs (oldAttrs: rec {
version = "${jellyseerrVersion}";
src = pkgs.fetchFromGitHub {
rev = "v\${version}";
sha256 = pkgs.lib.fakeSha256;
};
offlineCache = pkgs.fetchYarnDeps {
sha256 = pkgs.lib.fakeSha256;
};
});
};
}`;
const module = `{ config, pkgs, lib, ... }:
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.services.jellyseerr;
@@ -113,28 +117,65 @@ in
disabledModules = [ "services/misc/jellyseerr.nix" ];
options.services.jellyseerr = {
enable = mkEnableOption (mdDoc ''Jellyseerr, a requests manager for Jellyfin'');
enable = mkEnableOption ''Jellyseerr, a requests manager for Jellyfin'';
openFirewall = mkOption {
type = types.bool;
default = false;
description = mdDoc ''Open port in the firewall for the Jellyseerr web interface.'';
description = ''Open port in the firewall for the Jellyseerr web interface.'';
};
port = mkOption {
type = types.port;
default = 5055;
description = mdDoc ''The port which the Jellyseerr web UI should listen to.'';
description = ''The port which the Jellyseerr web UI should listen to.'';
};
package = mkOption {
type = types.package;
default = pkgs.jellyseerr;
defaultText = literalExpression "pkgs.jellyseerr";
description = lib.mdDoc ''
Jellyseerr package to use.
'';
type = types.package;
default = pkgs.jellyseerr;
defaultText = literalExpression "pkgs.jellyseerr";
description = ''
Jellyseerr package to use.
'';
};
databaseConfig = mkOption {
type = types.attrsOf types.str;
default = {
type = "sqlite";
configDirectory = "config";
logQueries = "false";
};
description = ''
Database configuration. For "sqlite", only "type", "configDirectory", and "logQueries" are relevant.
For "postgres", include host, port, user, pass, name, and optionally socket.
Example:
{
type = "postgres";
socket = "/run/postgresql";
user = "jellyseerr";
name = "jellyseerr";
logQueries = "false";
}
or
{
type = "postgres";
host = "localhost";
port = "5432";
user = "dbuser";
pass = "password";
name = "jellyseerr";
logQueries = "false";
}
or
{
type = "sqlite";
configDirectory = "config";
logQueries = "false";
}
'';
};
};
config = mkIf cfg.enable {
@@ -142,14 +183,29 @@ in
description = "Jellyseerr, a requests manager for Jellyfin";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment.PORT = toString cfg.port;
environment =
let
dbConfig = cfg.databaseConfig;
in
{
PORT = toString cfg.port;
DB_TYPE = toString dbConfig.type;
CONFIG_DIRECTORY = toString dbConfig.configDirectory or "";
DB_LOG_QUERIES = toString dbConfig.logQueries;
DB_HOST = if dbConfig.type == "postgres" && !(hasAttr "socket" dbConfig) then toString dbConfig.host or "" else "";
DB_PORT = if dbConfig.type == "postgres" && !(hasAttr "socket" dbConfig) then toString dbConfig.port or "" else "";
DB_SOCKET_PATH = if dbConfig.type == "postgres" && hasAttr "socket" dbConfig then toString dbConfig.socket or "" else "";
DB_USER = if dbConfig.type == "postgres" then toString dbConfig.user or "" else "";
DB_PASS = if dbConfig.type == "postgres" then toString dbConfig.pass or "" else "";
DB_NAME = if dbConfig.type == "postgres" then toString dbConfig.name or "" else "";
};
serviceConfig = {
Type = "exec";
StateDirectory = "jellyseerr";
WorkingDirectory = "\${cfg.package}/libexec/jellyseerr/deps/jellyseerr";
WorkingDirectory = "${cfg.package}/libexec/jellyseerr";
DynamicUser = true;
ExecStart = "\${cfg.package}/bin/jellyseerr";
BindPaths = [ "/var/lib/jellyseerr/:\${cfg.package}/libexec/jellyseerr/deps/jellyseerr/config/" ];
ExecStart = "${cfg.package}/bin/jellyseerr";
BindPaths = [ "/var/lib/jellyseerr/:${cfg.package}/libexec/jellyseerr/config/" ];
Restart = "on-failure";
ProtectHome = true;
ProtectSystem = "strict";
@@ -169,57 +225,47 @@ in
};
};
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.port ];
};
networking.firewall = mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.port ]; };
};
}`;
const configuration = `{ config, pkgs, ... }:
}
```
Then, import the module into your `configuration.nix`:
```nix
{ config, pkgs, ... }:
{
imports = [ ./jellyseerr-module.nix ]
imports = [ ./modules/jellyseerr.nix ];
services.jellyseerr = {
enable = true;
port = 5055;
openFirewall = true;
package = (pkgs.callPackage (import ../../../pkgs/jellyseerr) { });
services.jellyseerr = {
enable = true;
port = 5055;
openFirewall = true;
package = pkgs.unstable.jellyseerr; # use the unstable package if stable is not up-to-date
databaseConfig = {
type = "postgres";
host = "localhost"; # or socket: "/run/postgresql"
port = "5432"; # if using socket, this is not needed
user = "jellyseerr";
pass = "jellyseerr";
name = "jellyseerr";
logQueries = "false";
};
}`;
}
}
```
</TabItem>
</Tabs>
const isUpToDate = jellyseerrVersion === nixpkgVersion;
After adding the configuration to your `configuration.nix`, you can run the following command to install jellyseerr:
return (
<>
{isUpToDate ? (
<>
<p>The latest version of Jellyseerr <strong>({jellyseerrVersion})</strong> and the Jellyseerr nixpkg package version <strong>({nixpkgVersion})</strong> is <strong>up-to-date</strong>.</p>
<p>There is no need to override the package derivation.</p>
</>
) : (
<>
<p>The latest version of Jellyseerr <strong>({jellyseerrVersion})</strong> and the Jellyseerr nixpkg version <strong>(v{nixpkgVersion})</strong> is <strong>out-of-date</strong>.
If you want to use <b>Jellyseerr v{jellyseerrVersion}</b>, you will need to override the package derivation.</p>
<p>In order to override the package derivation:</p>
<ol>
<li style={{ marginBottom: '1rem' }}>Grab the <a href="https://raw.githubusercontent.com/NixOS/nixpkgs/nixos-unstable/pkgs/servers/jellyseerr/default.nix">latest nixpkg derivation for Jellyseerr</a></li>
<li style={{ marginBottom: '1rem' }}>Grab the latest <a href="https://raw.githubusercontent.com/Fallenbagel/jellyseerr/main/package.json">package.json</a> for Jellyseerr</li>
<li style={{ marginBottom: '1rem' }}>Add it to the same directory as the nixpkg derivation</li>
<li style={{ marginBottom: '1rem' }}>Update the `src` and `offlineCache` attributes in the nixpkg derivation:</li>
<CodeBlock className="language-nix" style={{ marginBottom: '1rem' }}>{code}</CodeBlock>
<Admonition type="tip" style={{ marginBottom: '1rem' }}>You can replace the <b>sha256</b> with the actual hash that <b>nixos-rebuild</b> outputs when you run the command.</Admonition>
<li style={{ marginBottom: '1rem' }}>Grab this module and import it in your `configuration.nix`</li>
<CodeBlock className="language-nix" style={{ marginBottom: '1rem' }}>{module}</CodeBlock>
<Admonition type="tip" style={{ marginBottom: '1rem' }}>We are using a custom module because the upstream module does not have a package option.</Admonition>
<li style={{ marginBottom: '1rem' }}>Call the new package in your `configuration.nix`</li>
<CodeBlock className="language-nix" style={{ marginBottom: '1rem' }}>{configuration}</CodeBlock>
</ol>
</>
)}
</>
);
```bash
nixos-rebuild switch
```
After rebuild is complete jellyseerr should be running, verify that it is with the following command.
```bash
systemctl status jellyseerr
```
};
<VersionMatch />
:::info
You can now access Jellyseerr by visiting `http://localhost:5055` in your web browser.
:::

View File

@@ -24,6 +24,12 @@ or for Cloudflare's DNS:
```bash
--dns=1.1.1.1
```
or for Quad9 DNS:
```bash
--dns=9.9.9.9
```
You can try them all and see which one works for your network.
</TabItem>
@@ -45,6 +51,16 @@ services:
dns:
- 1.1.1.1
```
or for Quad9's DNS:
```yaml
---
services:
jellyseerr:
dns:
- 9.9.9.9
```
You can try them all and see which one works for your network.
</TabItem>
@@ -56,7 +72,7 @@ services:
4. Click on Change adapter settings.
5. Right-click the network interface connected to the internet and select Properties.
6. Select Internet Protocol Version 4 (TCP/IPv4) and click Properties.
7. Select Use the following DNS server addresses and enter `8.8.8.8` for Google's DNS or `1.1.1.1` for Cloudflare's DNS.
7. Select Use the following DNS server addresses and enter `8.8.8.8` for Google's DNS or `1.1.1.1` for Cloudflare's DNS or `9.9.9.9` for Quad9's DNS.
</TabItem>
@@ -73,41 +89,15 @@ services:
```bash
nameserver 1.1.1.1
```
or for Quad9's DNS:
```bash
nameserver 9.9.9.9
```
</TabItem>
</Tabs>
### Option 2: Force IPV4 resolution first
Sometimes there are configuration issues with IPV6 that prevent the hostname resolution from working correctly.
You can try to force the resolution to use IPV4 first by setting the `FORCE_IPV4_FIRST` environment variable to `true`:
<Tabs groupId="methods" queryString>
<TabItem value="docker-cli" label="Docker CLI">
Add the following to your `docker run` command:
```bash
-e "FORCE_IPV4_FIRST=true"
```
</TabItem>
<TabItem value="docker-compose" label="Docker Compose">
Add the following to your `compose.yaml`:
```yaml
---
services:
jellyseerr:
environment:
- FORCE_IPV4_FIRST=true
```
</TabItem>
</Tabs>
### Option 3: Use Jellyseerr through a proxy
### Option 2: Use Jellyseerr through a proxy
If you can't change your DNS servers or force IPV4 resolution, you can use Jellyseerr through a proxy.
@@ -115,6 +105,12 @@ In some places (like China), the ISP blocks not only the DNS resolution but also
You can configure Jellyseerr to use a proxy with the [HTTP(S) Proxy](/using-jellyseerr/settings/general#https-proxy) setting.
### Option 3: Force IPV4 resolution first
Sometimes there are configuration issues with IPV6 that prevent the hostname resolution from working correctly.
You can try to force the resolution to use IPV4 first by going to `Settings > Networking > Advanced Networking` and enabling `Force IPv4 Resolution First` setting and restarting Jellyseerr.
### Option 4: Check that your server can reach TMDB API
Make sure that your server can reach the TMDB API by running the following command:
@@ -156,3 +152,26 @@ In a PowerShell window:
If you can't get a response, then your server can't reach the TMDB API.
This is usually due to a network configuration issue or a firewall blocking the connection.
## Account does not have admin privileges
If your admin account no longer has admin privileges, this is typically because your Jellyfin/Emby user ID has changed on the server side.
This can happen if you have a new installation of Jellyfin/Emby or if you have changed the user ID of your admin account.
### Solution: Reset admin access
1. Back up your `settings.json` file (located in your Jellyseerr data directory)
2. Stop the Jellyseerr container/service
3. Delete the `settings.json` file
4. Start Jellyseerr again
5. This will force the setup page to appear
6. Go through the setup process with the same login details
7. You can skip the services setup
8. Once you reach the discover page, stop Jellyseerr
9. Restore your backed-up `settings.json` file
10. Start Jellyseerr again
This process should restore your admin privileges while preserving your settings.
If you still encounter issues, please reach out on our support channels.

View File

@@ -0,0 +1,93 @@
---
title: Backups
description: Understand which data you should back up.
sidebar_position: 4
---
# Which data does Jellyseerr save and where?
## Settings
All configurations from the **Settings** panel in the Jellyseerr web UI are saved, including integrations with Radarr, Sonarr, Jellyfin, Plex, and notification settings.
These settings are stored in the `settings.json` file located in the Jellyseerr data folder.
## User Data
Apart from the settings, all other data—including user accounts, media requests, blacklist etc. are stored in the database (either SQLite or PostgreSQL).
# Backup
### SQLite
If your backup system uses filesystem snapshots (such as Kubernetes with Volsync), you can directly back up the Jellyseerr data folder.
Otherwise, you need to stop the Jellyseerr application and back up the `config` folder.
For advanced users, it's possible to back up the database without stopping the application by using the [SQLite CLI](https://www.sqlite.org/download.html). Run the following command to create a backup:
```bash
sqlite3 db/db.sqlite3 ".backup '/tmp/jellyseerr_db.sqlite3.bak'"
```
Then, copy the `/tmp/jellyseerr_dump.sqlite3.bak` file to your desired backup location.
### PostgreSQL
You can back up the `config` folder and dump the PostgreSQL database without stopping the Jellyseerr application.
Install [postgresql-client](https://www.postgresql.org/download/) and run the following command to create a backup (just replace the placeholders):
:::info
Depending on how your PostgreSQL instance is configured, you may need to add these options to the command below.
-h, --host=HOSTNAME database server host or socket directory
-p, --port=PORT database server port number
:::
```bash
pg_dump -U <database_user> -d <database_name> -f /tmp/jellyseerr_db.sql
```
# Restore
### SQLite
After restoring your `db/db.sqlite3` file and, optionally, the `settings.json` file, the `config` folder structure should look like this:
```
.
├── cache <-- Optional
├── db
│ └── db.sqlite3
├── logs <-- Optional
└── settings.json <-- Optional (required if you want to avoid reconfiguring Jellyseerr)
```
Once the files are restored, start the Jellyseerr application.
### PostgreSQL
Install the [PostgreSQL client](https://www.postgresql.org/download/) and restore the PostgreSQL database using the following command (replace the placeholders accordingly):
:::info
Depending on how your PostgreSQL instance is configured, you may need to add these options to the command below.
-h, --host=HOSTNAME database server host or socket directory
-p, --port=PORT database server port number
:::
```bash
pg_restore -U <database_user> -d <database_name> /tmp/jellyseerr_db.sql
```
Optionally, restore the `settings.json` file. The `config` folder structure should look like this:
```
.
├── cache <-- Optional
├── logs <-- Optional
└── settings.json <-- Optional (required if you want to avoid reconfiguring Jellyseerr)
```
Once the database and files are restored, start the Jellyseerr application.

View File

@@ -0,0 +1,21 @@
---
title: Gotify
description: Configure Gotify notifications.
sidebar_position: 5
---
# Gotify
## Configuration
### Server URL
Set this to the URL of your Gotify server.
### Application Token
Add an application to your Gotify server, and set this field to the generated application token.
:::info
Please refer to the [Gotify API documentation](https://gotify.net/docs) for more details on configuring these notifications.
:::

View File

@@ -0,0 +1,29 @@
---
title: ntfy.sh
description: Configure ntfy.sh notifications.
sidebar_position: 6
---
# ntfy.sh
## Configuration
### Server Root URL
Set this to the URL of your ntfy.sh server.
### Topic
Set this to the topic you want to send notifications to.
### Username + Password authentication (optional)
Set this to the username and password for your ntfy.sh server.
### Token authentication (optional)
Set this to the token for your ntfy.sh server.
:::info
Please refer to the [ntfy.sh API documentation](https://docs.ntfy.sh/) for more details on configuring these notifications.
:::

View File

@@ -0,0 +1,23 @@
---
title: Pushbullet
description: Configure Pushbullet notifications.
sidebar_position: 7
---
# Pushbullet
:::info
Users can optionally configure personal notifications in their user settings.
User notifications are separate from system notifications, and the available notification types are dependent on user permissions.
:::
## Configuration
### Access Token
[Create an access token](https://www.pushbullet.com/#settings) and set it here to grant Jellyseerr access to the Pushbullet API.
### Channel Tag (optional)
Optionally, [create a channel](https://www.pushbullet.com/my-channel) to allow other users to follow the notification feed using the specified channel tag.

View File

@@ -0,0 +1,27 @@
---
title: Pushover
description: Configure Pushover notifications.
sidebar_position: 8
---
# Pushover
:::info
Users can optionally configure personal notifications in their user settings.
User notifications are separate from system notifications, and the available notification types are dependent on user permissions.
:::
## Configuration
### Application/API Token
[Register an application](https://pushover.net/apps/build) and enter the API token in this field. (You can use one of the [official icons in our GitHub repository](https://github.com/fallenbagel/jellyseerr/tree/develop/public) when configuring the application.)
For more details on registering applications or the API token, please see the [Pushover API documentation](https://pushover.net/api#registration).
### User Key
Set this to the user key for your Pushover account. Alternatively, you can set this to a group key to deliver notifications to multiple users.
For more details, please see the [Pushover API documentation](https://pushover.net/api#identifiers).

View File

@@ -0,0 +1,17 @@
---
title: Slack
description: Configure Slack notifications.
sidebar_position: 9
---
# Slack
## Configuration
### Webhook URL
Simply [create a webhook](https://my.slack.com/services/new/incoming-webhook/) and enter the URL in this field.
:::info
Please refer to the [Slack API documentation](https://api.slack.com/messaging/webhooks) for more details on configuring these notifications.
:::

View File

@@ -0,0 +1,39 @@
---
title: Telegram
description: Configure Telegram notifications.
sidebar_position: 10
---
# Telegram
:::info
Users can optionally configure personal notifications in their user settings.
User notifications are separate from system notifications, and the available notification types are dependent on user permissions.
:::
## Configuration
:::info
In order to configure Telegram notifications, you first need to [create a bot](https://telegram.me/BotFather).
Bots **cannot** initiate conversations with users, so users must have your bot added to a conversation in order to receive notifications.
:::
### Bot Username (optional)
If this value is configured, users will be able to click a link to start a chat with your bot and configure their own personal notifications.
The bot username should end with `_bot`, and the `@` prefix should be omitted.
### Bot Authentication Token
At the end of the bot creation process, [@BotFather](https://telegram.me/botfather) will provide an authentication token.
### Chat ID
To obtain your chat ID, simply create a new group chat, add [@get_id_bot](https://telegram.me/get_id_bot), and issue the `/my_id` command.
### Send Silently (optional)
Optionally, notifications can be sent silently. Silent notifications send messages without notification sounds.

View File

@@ -0,0 +1,138 @@
---
title: Webhook
description: Configure webhook notifications.
sidebar_position: 4
---
# Webhook
The webhook notification agent enables you to send a custom JSON payload to any endpoint for specific notification events.
## Configuration
### Webhook URL
The URL you would like to post notifications to. Your JSON will be sent as the body of the request.
### Authorization Header (optional)
:::info
This is typically not needed. Please refer to your webhook provider's documentation for details.
:::
This value will be sent as an `Authorization` HTTP header.
### JSON Payload
Customize the JSON payload to suit your needs. Jellyseerr provides several [template variables](#template-variables) for use in the payload, which will be replaced with the relevant data when the notifications are triggered.
## Template Variables
### General
| Variable | Value |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `{{notification_type}}` | The type of notification (e.g. `MEDIA_PENDING` or `ISSUE_COMMENT`) |
| `{{event}}` | A friendly description of the notification event |
| `{{subject}}` | The notification subject (typically the media title) |
| `{{message}}` | The notification message body (the media overview/synopsis for request notifications; the issue description for issue notificatons) |
| `{{image}}` | The notification image (typically the media poster) |
### Notify User
These variables are for the target recipient of the notification.
| Variable | Value |
| ---------------------------------------- | ------------------------------------------------------------- |
| `{{notifyuser_username}}` | The target notification recipient's username |
| `{{notifyuser_email}}` | The target notification recipient's email address |
| `{{notifyuser_avatar}}` | The target notification recipient's avatar URL |
| `{{notifyuser_settings_discordId}}` | The target notification recipient's Discord ID (if set) |
| `{{notifyuser_settings_telegramChatId}}` | The target notification recipient's Telegram Chat ID (if set) |
:::info
The `notifyuser` variables are not defined for the following request notification types, as they are intended for application administrators rather than end users:
- Request Pending Approval
- Request Automatically Approved
- Request Processing Failed
On the other hand, the `notifyuser` variables _will_ be replaced with the requesting user's information for the below notification types:
- Request Approved
- Request Declined
- Request Available
If you would like to use the requesting user's information in your webhook, please instead include the relevant variables from the [Request](#request) section below.
:::
### Special
The following variables must be used as a key in the JSON payload (e.g., `"{{extra}}": []`).
| Variable | Value |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `{{media}}` | The relevant media object |
| `{{request}}` | The relevant request object |
| `{{issue}}` | The relevant issue object |
| `{{comment}}` | The relevant issue comment object |
| `{{extra}}` | The "extra" array of additional data for certain notifications (e.g., season/episode numbers for series-related notifications) |
#### Media
The `{{media}}` will be `null` if there is no relevant media object for the notification.
These following special variables are only included in media-related notifications, such as requests.
| Variable | Value |
| -------------------- | -------------------------------------------------------------------------------------------------------------- |
| `{{media_type}}` | The media type (`movie` or `tv`) |
| `{{media_tmdbid}}` | The media's TMDB ID |
| `{{media_tvdbid}}` | The media's TheTVDB ID |
| `{{media_status}}` | The media's availability status (`UNKNOWN`, `PENDING`, `PROCESSING`, `PARTIALLY_AVAILABLE`, or `AVAILABLE`) |
| `{{media_status4k}}` | The media's 4K availability status (`UNKNOWN`, `PENDING`, `PROCESSING`, `PARTIALLY_AVAILABLE`, or `AVAILABLE`) |
#### Request
The `{{request}}` will be `null` if there is no relevant media object for the notification.
The following special variables are only included in request-related notifications.
| Variable | Value |
| ----------------------------------------- | ----------------------------------------------- |
| `{{request_id}}` | The request ID |
| `{{requestedBy_username}}` | The requesting user's username |
| `{{requestedBy_email}}` | The requesting user's email address |
| `{{requestedBy_avatar}}` | The requesting user's avatar URL |
| `{{requestedBy_settings_discordId}}` | The requesting user's Discord ID (if set) |
| `{{requestedBy_settings_telegramChatId}}` | The requesting user's Telegram Chat ID (if set) |
#### Issue
The `{{issue}}` will be `null` if there is no relevant media object for the notification.
The following special variables are only included in issue-related notifications.
| Variable | Value |
| ---------------------------------------- | ----------------------------------------------- |
| `{{issue_id}}` | The issue ID |
| `{{reportedBy_username}}` | The requesting user's username |
| `{{reportedBy_email}}` | The requesting user's email address |
| `{{reportedBy_avatar}}` | The requesting user's avatar URL |
| `{{reportedBy_settings_discordId}}` | The requesting user's Discord ID (if set) |
| `{{reportedBy_settings_telegramChatId}}` | The requesting user's Telegram Chat ID (if set) |
#### Comment
The `{{comment}}` will be `null` if there is no relevant media object for the notification.
The following special variables are only included in issue comment-related notifications.
| Variable | Value |
| ----------------------------------------- | ----------------------------------------------- |
| `{{comment_message}}` | The comment message |
| `{{commentedBy_username}}` | The commenting user's username |
| `{{commentedBy_email}}` | The commenting user's email address |
| `{{commentedBy_avatar}}` | The commenting user's avatar URL |
| `{{commentedBy_settings_discordId}}` | The commenting user's Discord ID (if set) |
| `{{commentedBy_settings_telegramChatId}}` | The commenting user's Telegram Chat ID (if set) |

View File

@@ -0,0 +1,10 @@
{
"label": "Plex Integration",
"position": 3,
"link": {
"type": "generated-index",
"title": "Plex Integration",
"description": "Learn about Jellyseerr's Plex integration features"
}
}

View File

@@ -0,0 +1,36 @@
---
title: Overview
description: Learn about Jellyseerr's Plex integration features
sidebar_position: 1
---
# Plex Features Overview
Jellyseerr provides integration features that connect with your Plex media server to automate media management tasks.
## Available Features
- [Watchlist Auto Request](./plex/watchlist-auto-request) - Automatically request media from your Plex Watchlist
- More features coming soon!
## Prerequisites
:::info Authentication Required
To use any Plex integration features, you must have logged into Jellyseerr at least once with your Plex account.
:::
**Requirements:**
- Plex account with access to the configured Plex server
- Jellyseerr configured with Plex as the media server
- User authentication via Plex login
- Appropriate user permissions for specific features
## Getting Started
1. Authenticate at least once using your Plex credentials
2. Verify you have the necessary permissions for desired features
3. Follow individual feature guides for setup instructions
:::note Server Configuration
Plex server configuration is handled by your administrator. If you cannot log in with your Plex account, contact your administrator to verify the server setup.
:::

View File

@@ -0,0 +1,95 @@
---
title: Watchlist Auto Request
description: Learn how to use the Plex Watchlist Auto Request feature
sidebar_position: 1
---
# Watchlist Auto Request
The Plex Watchlist Auto Request feature allows Jellyseerr to automatically create requests for media items you add to your Plex Watchlist. Simply add content to your Plex Watchlist, and Jellyseerr will automatically request it for you.
:::info
This feature is only available for Plex users. Local users cannot use the Watchlist Auto Request feature.
:::
## Prerequisites
- You must have logged into Jellyseerr at least once with your Plex account
- Your administrator must have granted you the necessary permissions
- Your Plex account must have access to the Plex server configured in Jellyseerr
## Permission System
The Watchlist Auto Request feature uses a two-tier permission system:
### Administrator Permissions (Required)
Your administrator must grant you these permissions in your user profile:
- **Auto-Request** (master permission)
- **Auto-Request Movies** (for movie auto-requests)
- **Auto-Request Series** (for TV series auto-requests)
### User Activation (Required)
You must enable the feature in your own profile settings:
- **Auto-Request Movies** toggle
- **Auto-Request Series** toggle
:::warning Two-Step Process
Both administrator permissions AND user activation are required. Having permissions doesn't automatically enable the feature - you must also activate it in your profile.
:::
## How to Enable
### Step 1: Check Your Permissions
Contact your administrator to verify you have been granted:
- `Auto-Request` permission
- `Auto-Request Movies` and/or `Auto-Request Series` permissions
### Step 2: Activate the Feature
1. Go to your user profile settings
2. Navigate to the "General" section
3. Find the "Auto-Request" options
4. Enable the toggles for:
- **Auto-Request Movies** - to automatically request movies from your watchlist
- **Auto-Request Series** - to automatically request TV series from your watchlist
### Step 3: Start Using
- Add movies and TV shows to your Plex Watchlist
- Jellyseerr will automatically create requests for new items
- You'll receive notifications when items are auto-requested
## How It Works
Once properly configured, Jellyseerr will:
1. Periodically checks your Plex Watchlist for new items
2. Verify if the content already exists in your media libraries
3. Automatically submits requests for new items that aren't already available
4. Only requests content types you have permissions for
5. Notifiy you when auto-requests are created
:::info Content Limitations
Auto-request only works for standard quality content. 4K content must be requested manually if you have 4K permissions.
:::
## For Administrators
### Granting Permissions
1. Navigate to **Users** > **[Select User]** > **Permissions**
2. Enable the required permissions:
- **Auto-Request** (master toggle)
- **Auto-Request Movies** (for movie auto-requests)
- **Auto-Request Series** (for TV series auto-requests)
3. Optionally enable **Auto-Approve** permissions for automatic approval
### Default Permissions
- Go to **Settings** > **Users** > **Default Permissions**
- Configure auto-request permissions for new users
- This sets the default permissions but users still need to activate the feature individually
## Limitations
- Local users cannot use this feature
- 4K content requires manual requests
- Users must have logged into Jellyseerr with their Plex account
- Respects user request limits and quotas
- Won't request content already in your libraries

View File

@@ -0,0 +1,16 @@
---
title: DNS Caching
description: Configure DNS caching settings.
sidebar_position: 7
---
# DNS Caching
Jellyseerr uses DNS caching to improve performance and reduce the number of DNS lookups required for external API calls. This can help speed up response times and reduce load on DNS servers, when something like a Pi-hole is used as a DNS resolver.
## Configuration
You can enable the DNS caching settings in the Network tab of the Jellyseerr settings. The default values follow the standard DNS caching behavior.
- **Force Minimum TTL**: Set a minimum time-to-live (TTL) in seconds for DNS cache entries. This ensures that frequently accessed DNS records are cached for a longer period, reducing the need for repeated lookups. Default is 0.
- **Force Maximum TTL**: Set a maximum time-to-live (TTL) in seconds for DNS cache entries. This prevents infrequently accessed DNS records from being cached indefinitely, allowing for more up-to-date information to be retrieved. Default is -1 (unlimited).

View File

@@ -62,6 +62,14 @@ Set the default display language for Jellyseerr. Users can override this setting
These settings filter content shown on the "Discover" home page based on regional availability and original language, respectively. The Streaming Region filters the available streaming providers on the media page. Users can override these global settings by configuring these same options in their user settings.
## Blacklist Content with Tags and Limit Content Blacklisted per Tag
These settings blacklist any TV shows or movies that have one of the entered tags. The "Process Blacklisted Tags" job adds entries to the blacklist based on the configured blacklisted tags. If a blacklisted tag is removed, any media blacklisted under that tag will be removed from the blacklist when the "Process Blacklisted Tags" job runs.
The limit setting determines how many pages per tag the job will process, with each page containing 20 entries. The job cycles through all 16 available discovery sort options, querying the defined number of pages to blacklist media that is most likely to appear at the top of each sort. Higher limits will create a more accurate blacklist, but will require more storage.
Blacklisted tags are disabled until at least one tag is entered. These settings cannot be overridden in user settings.
## Hide Available Media
When enabled, media which is already available will not appear on the "Discover" home page, or in the "Recommended" or "Similar" categories or other links on media detail pages.
@@ -70,6 +78,12 @@ Available media will still appear in search results, however, so it is possible
This setting is **disabled** by default.
## Hide Blacklisted Items
When enabled, media that has been blacklisted will not appear on the "Discover" home page, for all administrators. This can be useful to hide content that you don't want to see, such as content with specific tags or content that has been manually blacklisted when you have the "Manage Blacklist" permission.
This setting is **disabled** by default.
## Allow Partial Series Requests
When enabled, users will be able to submit requests for specific seasons of TV series. If disabled, users will only be able to submit requests for all unavailable seasons.

View File

@@ -1,6 +1,7 @@
---
title: Jobs & Cache
description: Configure jobs and cache settings.
sidebar_position: 6
---
# Jobs & Cache

View File

@@ -14,6 +14,14 @@ When disabled, your mediaserver OAuth becomes the only sign-in option, and any "
This setting is **enabled** by default.
## Enable Jellyfin/Emby/Plex Sign-In
When enabled, users will be able to sign in to Jellyseerr using their Jellyfin/Emby/Plex credentials, provided they have linked their media server accounts.
When disabled, users will only be able to sign in using their email address. Users without a password set will not be able to sign in to Jellyseerr.
This setting is **enabled** by default.
## Enable New Jellyfin/Emby/Plex Sign-In
When enabled, users with access to your media server will be able to sign in to Jellyseerr even if they have not yet been imported. Users will be automatically assigned the permissions configured in the [Default Permissions](#default-permissions) setting upon first sign-in.

View File

@@ -11,7 +11,7 @@ const config: Config = {
baseUrl: '/',
trailingSlash: false,
organizationName: 'Fallenbagel',
organizationName: 'fallenbagel',
projectName: 'Jellyseerr',
deploymentBranch: 'gh-pages',
@@ -32,7 +32,7 @@ const config: Config = {
routeBasePath: '/',
path: '../docs',
editUrl:
'https://github.com/Fallenbagel/jellyseerr/edit/develop/docs/',
'https://github.com/fallenbagel/jellyseerr/edit/develop/docs/',
},
blog: false,
pages: false,
@@ -70,7 +70,7 @@ const config: Config = {
},
items: [
{
href: 'https://github.com/Fallenbagel/jellyseerr',
href: 'https://github.com/fallenbagel/jellyseerr',
label: 'GitHub',
position: 'right',
},

View File

@@ -47,6 +47,6 @@
]
},
"engines": {
"node": ">=18.0"
"node": ">=22.0"
}
}

View File

@@ -26,25 +26,37 @@ export const JellyseerrVersion = () => {
};
export const NixpkgVersion = () => {
const [version, setVersion] = useState(null);
const [versions, setVersions] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchVersion = async () => {
try {
const url =
'https://raw.githubusercontent.com/NixOS/nixpkgs/nixos-unstable/pkgs/servers/jellyseerr/default.nix';
const response = await fetch(url);
const data = await response.text();
const unstableUrl =
'https://raw.githubusercontent.com/NixOS/nixpkgs/refs/heads/nixos-unstable/pkgs/by-name/je/jellyseerr/package.nix';
const stableUrl =
'https://raw.githubusercontent.com/NixOS/nixpkgs/refs/heads/nixos-24.11/pkgs/servers/jellyseerr/default.nix';
const [unstableResponse, stableResponse] = await Promise.all([
fetch(unstableUrl),
fetch(stableUrl),
]);
const unstableData = await unstableResponse.text();
const stableData = await stableResponse.text();
const versionRegex = /version\s*=\s*"([^"]+)"/;
const match = data.match(versionRegex);
if (match && match[1]) {
setVersion(match[1]);
} else {
setError('0.0.0');
}
const unstableMatch = unstableData.match(versionRegex);
const stableMatch = stableData.match(versionRegex);
const unstableVersion =
unstableMatch && unstableMatch[1] ? unstableMatch[1] : '0.0.0';
const stableVersion =
stableMatch && stableMatch[1] ? stableMatch[1] : '0.0.0';
setVersions({ unstable: unstableVersion, stable: stableVersion });
setLoading(false);
} catch (err) {
setError(err.message);
@@ -63,5 +75,5 @@ export const NixpkgVersion = () => {
return { error };
}
return version;
return versions;
};

File diff suppressed because it is too large Load Diff

2
next-env.d.ts vendored
View File

@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.

View File

@@ -4,13 +4,13 @@
module.exports = {
env: {
commitTag: process.env.COMMIT_TAG || 'local',
forceIpv4First: process.env.FORCE_IPV4_FIRST === 'true' ? 'true' : 'false',
},
images: {
remotePatterns: [
{ hostname: 'gravatar.com' },
{ hostname: 'image.tmdb.org' },
{ hostname: 'artworks.thetvdb.com' },
{ hostname: 'plex.tv' },
],
},
webpack(config) {

View File

@@ -5,7 +5,7 @@
"scripts": {
"preinstall": "npx only-allow pnpm",
"postinstall": "node postinstall-win.js",
"dev": "nodemon -e ts --watch server --watch overseerr-api.yml -e .json,.ts,.yml -x ts-node -r tsconfig-paths/register --files --project server/tsconfig.json server/index.ts",
"dev": "nodemon -e ts --watch server --watch jellyseerr-api.yml -e .json,.ts,.yml -x ts-node -r tsconfig-paths/register --files --project server/tsconfig.json server/index.ts",
"build:server": "tsc --project server/tsconfig.json && copyfiles -u 2 server/templates/**/*.{html,pug} dist/templates && tsc-alias -p server/tsconfig.json",
"build:next": "next build",
"build": "pnpm build:next && pnpm build:server",
@@ -32,6 +32,7 @@
},
"license": "MIT",
"dependencies": {
"@dr.pogodin/csurf": "^1.14.1",
"@formatjs/intl-displaynames": "6.2.6",
"@formatjs/intl-locale": "3.1.1",
"@formatjs/intl-pluralrules": "5.1.10",
@@ -42,36 +43,42 @@
"@supercharge/request-ip": "1.2.0",
"@svgr/webpack": "6.5.1",
"@tanem/react-nprogress": "5.0.30",
"@types/ua-parser-js": "^0.7.36",
"@types/wink-jaro-distance": "^2.0.2",
"ace-builds": "1.15.2",
"axios": "1.10.0",
"axios-rate-limit": "1.3.0",
"bcrypt": "5.1.0",
"bowser": "2.11.0",
"connect-typeorm": "1.1.4",
"cookie-parser": "1.4.6",
"cookie-parser": "1.4.7",
"copy-to-clipboard": "3.3.3",
"country-flag-icons": "1.5.5",
"cronstrue": "2.23.0",
"csurf": "1.11.0",
"date-fns": "2.29.3",
"dayjs": "1.11.7",
"email-templates": "9.0.0",
"dns-caching": "^0.2.5",
"email-templates": "12.0.1",
"email-validator": "2.0.4",
"express": "4.18.2",
"express": "4.21.2",
"express-openapi-validator": "4.13.8",
"express-rate-limit": "6.7.0",
"express-session": "1.17.3",
"formik": "^2.4.6",
"gravatar-url": "3.1.0",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.6",
"lodash": "4.17.21",
"mime": "3",
"next": "^14.2.4",
"next": "^14.2.25",
"node-cache": "5.1.2",
"node-gyp": "9.3.1",
"node-schedule": "2.1.1",
"nodemailer": "6.9.1",
"openpgp": "5.7.0",
"nodemailer": "6.10.0",
"openpgp": "5.11.2",
"pg": "8.11.0",
"plex-api": "5.3.2",
"pug": "3.0.2",
"pug": "3.0.3",
"react": "^18.3.1",
"react-ace": "10.1.0",
"react-animate-height": "2.1.2",
@@ -85,35 +92,38 @@
"react-spring": "9.7.1",
"react-tailwindcss-datepicker-sct": "1.3.4",
"react-toast-notifications": "2.5.1",
"react-transition-group": "^4.4.5",
"react-truncate-markup": "5.1.2",
"react-use-clipboard": "1.0.9",
"reflect-metadata": "0.1.13",
"secure-random-password": "0.2.3",
"semver": "7.3.8",
"semver": "7.7.1",
"sharp": "^0.33.4",
"sqlite3": "5.1.4",
"sqlite3": "5.1.7",
"swagger-ui-express": "4.6.2",
"swr": "2.2.5",
"typeorm": "0.3.11",
"undici": "^6.20.1",
"tailwind-merge": "^2.6.0",
"typeorm": "0.3.12",
"ua-parser-js": "^1.0.35",
"undici": "^7.3.0",
"web-push": "3.5.0",
"wink-jaro-distance": "^2.0.0",
"winston": "3.8.2",
"winston-daily-rotate-file": "4.7.1",
"xml2js": "0.4.23",
"yamljs": "0.3.0",
"yup": "0.32.11",
"zod": "3.20.6"
"zod": "3.24.2"
},
"devDependencies": {
"@codedependant/semantic-release-docker": "^5.1.0",
"@commitlint/cli": "17.4.4",
"@commitlint/config-conventional": "17.4.4",
"@semantic-release/changelog": "6.0.2",
"@semantic-release/commit-analyzer": "9.0.2",
"@semantic-release/exec": "6.0.3",
"@semantic-release/changelog": "6.0.3",
"@semantic-release/git": "10.0.1",
"@tailwindcss/aspect-ratio": "0.4.2",
"@tailwindcss/forms": "0.5.3",
"@tailwindcss/typography": "0.5.9",
"@tailwindcss/forms": "0.5.10",
"@tailwindcss/typography": "0.5.16",
"@types/bcrypt": "5.0.0",
"@types/cookie-parser": "1.4.3",
"@types/country-flag-icons": "1.2.0",
@@ -123,7 +133,7 @@
"@types/express-session": "1.17.6",
"@types/lodash": "4.14.191",
"@types/mime": "3",
"@types/node": "20.14.8",
"@types/node": "22.10.5",
"@types/node-schedule": "2.1.0",
"@types/nodemailer": "6.4.7",
"@types/react": "^18.3.3",
@@ -142,7 +152,7 @@
"commitizen": "4.3.0",
"copyfiles": "2.4.1",
"cy-mobile-commands": "0.3.0",
"cypress": "12.7.0",
"cypress": "14.1.0",
"cz-conventional-changelog": "3.3.0",
"eslint": "8.35.0",
"eslint-config-next": "^14.2.4",
@@ -155,13 +165,12 @@
"eslint-plugin-react-hooks": "4.6.0",
"husky": "8.0.3",
"lint-staged": "13.1.2",
"nodemon": "2.0.20",
"postcss": "8.4.21",
"nodemon": "3.1.9",
"postcss": "8.4.31",
"prettier": "2.8.4",
"prettier-plugin-organize-imports": "3.2.2",
"prettier-plugin-tailwindcss": "0.2.3",
"semantic-release": "19.0.5",
"semantic-release-docker-buildx": "1.0.1",
"semantic-release": "24.2.7",
"tailwindcss": "3.2.7",
"ts-node": "10.9.1",
"tsc-alias": "1.8.2",
@@ -169,7 +178,7 @@
"typescript": "4.9.5"
},
"engines": {
"node": "^20.0.0",
"node": "^22.0.0",
"pnpm": "^9.0.0"
},
"overrides": {
@@ -216,7 +225,49 @@
"message": "chore(release): ${nextRelease.version}"
}
],
"semantic-release-docker-buildx",
[
"@codedependant/semantic-release-docker",
{
"dockerArgs": {
"COMMIT_TAG": "$GIT_SHA"
},
"dockerLogin": false,
"dockerProject": "fallenbagel",
"dockerImage": "jellyseerr",
"dockerTags": [
"latest",
"{{major}}",
"{{major}}.{{minor}}",
"{{major}}.{{minor}}.{{patch}}"
],
"dockerPlatform": [
"linux/amd64",
"linux/arm64"
]
}
],
[
"@codedependant/semantic-release-docker",
{
"dockerArgs": {
"COMMIT_TAG": "$GIT_SHA"
},
"dockerLogin": false,
"dockerRegistry": "ghcr.io",
"dockerProject": "fallenbagel",
"dockerImage": "jellyseerr",
"dockerTags": [
"latest",
"{{major}}",
"{{major}}.{{minor}}",
"{{major}}.{{minor}}.{{patch}}"
],
"dockerPlatform": [
"linux/amd64",
"linux/arm64"
]
}
],
[
"@semantic-release/github",
{
@@ -229,19 +280,7 @@
],
"npmPublish": false,
"publish": [
{
"path": "semantic-release-docker-buildx",
"buildArgs": {
"COMMIT_TAG": "$GIT_SHA"
},
"imageNames": [
"fallenbagel/jellyseerr"
],
"platforms": [
"linux/amd64",
"linux/arm64"
]
},
"@codedependant/semantic-release-docker",
"@semantic-release/github"
]
}

5452
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

2
public/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow: /

View File

@@ -3,7 +3,7 @@
// previously cached resources to be updated from the network.
// This variable is intentionally declared and unused.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const OFFLINE_VERSION = 3;
const OFFLINE_VERSION = 4;
const CACHE_NAME = 'offline';
// Customize this with a different URL if needed.
const OFFLINE_URL = '/offline.html';
@@ -107,6 +107,25 @@ self.addEventListener('push', (event) => {
);
}
// Set the badge with the amount of pending requests
// Only update the badge if the payload confirms they are the admin
if (
(payload.notificationType === 'MEDIA_APPROVED' ||
payload.notificationType === 'MEDIA_DECLINED') &&
payload.isAdmin
) {
if ('setAppBadge' in navigator) {
navigator.setAppBadge(payload.pendingRequestsCount);
}
return;
}
if (payload.notificationType === 'MEDIA_PENDING') {
if ('setAppBadge' in navigator) {
navigator.setAppBadge(payload.pendingRequestsCount);
}
}
event.waitUntil(self.registration.showNotification(payload.subject, options));
});

View File

@@ -1,8 +1,7 @@
import logger from '@server/logger';
import fs, { promises as fsp } from 'node:fs';
import path from 'node:path';
import { Readable } from 'node:stream';
import type { ReadableStream } from 'node:stream/web';
import axios from 'axios';
import fs, { promises as fsp } from 'fs';
import path from 'path';
import xml2js from 'xml2js';
const UPDATE_INTERVAL_MSEC = 24 * 3600 * 1000; // how often to download new mapping in milliseconds
@@ -162,18 +161,14 @@ class AnimeListMapping {
label: 'Anime-List Sync',
});
try {
const response = await fetch(MAPPING_URL);
if (!response.ok) {
throw new Error(`Failed to fetch: ${response.statusText}`);
}
const response = await axios.get(MAPPING_URL, {
responseType: 'stream',
});
await new Promise<void>((resolve, reject) => {
const writer = fs.createWriteStream(LOCAL_PATH);
writer.on('finish', resolve);
writer.on('error', reject);
if (!response.body) return reject();
Readable.fromWeb(response.body as ReadableStream<Uint8Array>).pipe(
writer
);
response.data.pipe(writer);
});
} catch (e) {
throw new Error(`Failed to download Anime-List mapping: ${e.message}`);

View File

@@ -1,7 +1,7 @@
import { MediaServerType } from '@server/constants/server';
import { getSettings } from '@server/lib/settings';
import type { RateLimitOptions } from '@server/utils/rateLimit';
import rateLimit from '@server/utils/rateLimit';
import { requestInterceptorFunction } from '@server/utils/customProxyAgent';
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
import axios from 'axios';
import rateLimit from 'axios-rate-limit';
import type NodeCache from 'node-cache';
// 5 minute default TTL (in seconds)
@@ -10,226 +10,103 @@ const DEFAULT_TTL = 300;
// 10 seconds default rolling buffer (in ms)
const DEFAULT_ROLLING_BUFFER = 10000;
interface ExternalAPIOptions {
export interface ExternalAPIOptions {
nodeCache?: NodeCache;
headers?: Record<string, unknown>;
rateLimit?: RateLimitOptions;
rateLimit?: {
maxRPS: number;
maxRequests: number;
};
}
class ExternalAPI {
protected fetch: typeof fetch;
protected params: Record<string, string>;
protected defaultHeaders: { [key: string]: string };
protected axios: AxiosInstance;
private baseUrl: string;
private cache?: NodeCache;
constructor(
baseUrl: string,
params: Record<string, string> = {},
params: Record<string, unknown>,
options: ExternalAPIOptions = {}
) {
this.axios = axios.create({
baseURL: baseUrl,
params,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
...options.headers,
},
});
this.axios.interceptors.request.use(requestInterceptorFunction);
if (options.rateLimit) {
this.fetch = rateLimit(fetch, options.rateLimit);
} else {
this.fetch = fetch;
}
const url = new URL(baseUrl);
const settings = getSettings();
this.defaultHeaders = {
'Content-Type': 'application/json',
Accept: 'application/json',
...((url.username || url.password) && {
Authorization: `Basic ${Buffer.from(
`${url.username}:${url.password}`
).toString('base64')}`,
}),
...(settings.main.mediaServerType === MediaServerType.EMBY && {
'Accept-Encoding': 'gzip',
}),
...options.headers,
};
if (url.username || url.password) {
url.username = '';
url.password = '';
baseUrl = url.toString();
this.axios = rateLimit(this.axios, {
maxRequests: options.rateLimit.maxRequests,
maxRPS: options.rateLimit.maxRPS,
});
}
this.baseUrl = baseUrl;
this.params = params;
this.cache = options.nodeCache;
}
protected async get<T>(
endpoint: string,
params?: Record<string, string>,
ttl?: number,
config?: RequestInit
config?: AxiosRequestConfig,
ttl?: number
): Promise<T> {
const cacheKey = this.serializeCacheKey(endpoint, {
...this.params,
...params,
...config?.params,
headers: config?.headers,
});
const cachedItem = this.cache?.get<T>(cacheKey);
if (cachedItem) {
return cachedItem;
}
const url = this.formatUrl(endpoint, params);
const response = await this.fetch(url, {
...config,
headers: {
...this.defaultHeaders,
...config?.headers,
},
});
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const data = await this.getDataFromResponse(response);
const response = await this.axios.get<T>(endpoint, config);
if (this.cache && ttl !== 0) {
this.cache.set(cacheKey, data, ttl ?? DEFAULT_TTL);
this.cache.set(cacheKey, response.data, ttl ?? DEFAULT_TTL);
}
return data;
return response.data;
}
protected async post<T>(
endpoint: string,
data?: Record<string, unknown>,
params?: Record<string, string>,
ttl?: number,
config?: RequestInit
config?: AxiosRequestConfig,
ttl?: number
): Promise<T> {
const cacheKey = this.serializeCacheKey(endpoint, {
config: { ...this.params, ...params },
data,
config: config?.params,
...(data ? { data } : {}),
});
const cachedItem = this.cache?.get<T>(cacheKey);
if (cachedItem) {
return cachedItem;
}
const url = this.formatUrl(endpoint, params);
const response = await this.fetch(url, {
method: 'POST',
...config,
headers: {
...this.defaultHeaders,
...config?.headers,
},
body: data ? JSON.stringify(data) : undefined,
});
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const resData = await this.getDataFromResponse(response);
const response = await this.axios.post<T>(endpoint, data, config);
if (this.cache && ttl !== 0) {
this.cache.set(cacheKey, resData, ttl ?? DEFAULT_TTL);
this.cache.set(cacheKey, response.data, ttl ?? DEFAULT_TTL);
}
return resData;
}
protected async put<T>(
endpoint: string,
data: Record<string, unknown>,
params?: Record<string, string>,
ttl?: number,
config?: RequestInit
): Promise<T> {
const cacheKey = this.serializeCacheKey(endpoint, {
config: { ...this.params, ...params },
data,
});
const cachedItem = this.cache?.get<T>(cacheKey);
if (cachedItem) {
return cachedItem;
}
const url = this.formatUrl(endpoint, params);
const response = await this.fetch(url, {
method: 'PUT',
...config,
headers: {
...this.defaultHeaders,
...config?.headers,
},
body: JSON.stringify(data),
});
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const resData = await this.getDataFromResponse(response);
if (this.cache && ttl !== 0) {
this.cache.set(cacheKey, resData, ttl ?? DEFAULT_TTL);
}
return resData;
}
protected async delete<T>(
endpoint: string,
params?: Record<string, string>,
config?: RequestInit
): Promise<T> {
const url = this.formatUrl(endpoint, params);
const response = await this.fetch(url, {
method: 'DELETE',
...config,
headers: {
...this.defaultHeaders,
...config?.headers,
},
});
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const data = await this.getDataFromResponse(response);
return data;
return response.data;
}
protected async getRolling<T>(
endpoint: string,
params?: Record<string, string>,
ttl?: number,
config?: RequestInit,
overwriteBaseUrl?: string
config?: AxiosRequestConfig,
ttl?: number
): Promise<T> {
const cacheKey = this.serializeCacheKey(endpoint, {
...this.params,
...params,
...config?.params,
headers: config?.headers,
});
const cachedItem = this.cache?.get<T>(cacheKey);
@@ -241,112 +118,38 @@ class ExternalAPI {
keyTtl - (ttl ?? DEFAULT_TTL) * 1000 <
Date.now() - DEFAULT_ROLLING_BUFFER
) {
const url = this.formatUrl(endpoint, params, overwriteBaseUrl);
this.fetch(url, {
...config,
headers: {
...this.defaultHeaders,
...config?.headers,
},
}).then(async (response) => {
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${
text ? ': ' + text : ''
}`,
{
cause: response,
}
);
}
const data = await this.getDataFromResponse(response);
this.cache?.set(cacheKey, data, ttl ?? DEFAULT_TTL);
this.axios.get<T>(endpoint, config).then((response) => {
this.cache?.set(cacheKey, response.data, ttl ?? DEFAULT_TTL);
});
}
return cachedItem;
}
const url = this.formatUrl(endpoint, params, overwriteBaseUrl);
const response = await this.fetch(url, {
...config,
headers: {
...this.defaultHeaders,
...config?.headers,
},
});
if (!response.ok) {
const text = await response.text();
throw new Error(
`${response.status} ${response.statusText}${text ? ': ' + text : ''}`,
{
cause: response,
}
);
}
const data = await this.getDataFromResponse(response);
const response = await this.axios.get<T>(endpoint, config);
if (this.cache) {
this.cache.set(cacheKey, data, ttl ?? DEFAULT_TTL);
if (this.cache && ttl !== 0) {
this.cache.set(cacheKey, response.data, ttl ?? DEFAULT_TTL);
}
return data;
return response.data;
}
private formatUrl(
endpoint: string,
params?: Record<string, string>,
overwriteBaseUrl?: string
): string {
const baseUrl = overwriteBaseUrl || this.baseUrl;
const href =
baseUrl +
(baseUrl.endsWith('/') ? '' : '/') +
(endpoint.startsWith('/') ? endpoint.slice(1) : endpoint);
const searchParams = new URLSearchParams({
...this.params,
...params,
protected removeCache(endpoint: string, options?: Record<string, unknown>) {
const cacheKey = this.serializeCacheKey(endpoint, {
...options,
});
return (
href +
(searchParams.toString().length
? '?' + searchParams.toString()
: searchParams.toString())
);
this.cache?.del(cacheKey);
}
private serializeCacheKey(
endpoint: string,
params?: Record<string, unknown>
options?: Record<string, unknown>
) {
if (!params) {
if (!options) {
return `${this.baseUrl}${endpoint}`;
}
return `${this.baseUrl}${endpoint}${JSON.stringify(params)}`;
}
private async getDataFromResponse(response: Response) {
const contentType = response.headers.get('Content-Type');
if (contentType?.includes('application/json')) {
return await response.json();
} else if (
contentType?.includes('application/xml') ||
contentType?.includes('text/html') ||
contentType?.includes('text/plain')
) {
return await response.text();
} else {
try {
return await response.json();
} catch {
try {
return await response.blob();
} catch {
return null;
}
}
}
return `${this.baseUrl}${endpoint}${JSON.stringify(options)}`;
}
}

View File

@@ -1,6 +1,6 @@
import ExternalAPI from '@server/api/externalapi';
import cacheManager from '@server/lib/cache';
import logger from '@server/logger';
import ExternalAPI from './externalapi';
interface GitHubRelease {
url: string;
@@ -67,12 +67,16 @@ class GithubAPI extends ExternalAPI {
'https://api.github.com',
{},
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
nodeCache: cacheManager.getCache('github').data,
}
);
}
public async getOverseerrReleases({
public async getJellyseerrReleases({
take = 20,
}: {
take?: number;
@@ -81,21 +85,23 @@ class GithubAPI extends ExternalAPI {
const data = await this.get<GitHubRelease[]>(
'/repos/fallenbagel/jellyseerr/releases',
{
per_page: take.toString(),
params: {
per_page: take,
},
}
);
return data;
} catch (e) {
logger.warn(
"Failed to retrieve GitHub releases. This may be an issue on GitHub's end. Overseerr can't check if it's on the latest version.",
"Failed to retrieve GitHub releases. This may be an issue on GitHub's end. Jellyseerr can't check if it's on the latest version.",
{ label: 'GitHub API', errorMessage: e.message }
);
return [];
}
}
public async getOverseerrCommits({
public async getJellyseerrCommits({
take = 20,
branch = 'develop',
}: {
@@ -106,15 +112,17 @@ class GithubAPI extends ExternalAPI {
const data = await this.get<GithubCommit[]>(
'/repos/fallenbagel/jellyseerr/commits',
{
per_page: take.toString(),
branch,
params: {
per_page: take,
branch,
},
}
);
return data;
} catch (e) {
logger.warn(
"Failed to retrieve GitHub commits. This may be an issue on GitHub's end. Overseerr can't check if it's on the latest version.",
"Failed to retrieve GitHub commits. This may be an issue on GitHub's end. Jellyseerr can't check if it's on the latest version.",
{ label: 'GitHub API', errorMessage: e.message }
);
return [];

View File

@@ -1,7 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import ExternalAPI from '@server/api/externalapi';
import { ApiErrorCode } from '@server/constants/error';
import { MediaServerType } from '@server/constants/server';
import availabilitySync from '@server/lib/availabilitySync';
import { getSettings } from '@server/lib/settings';
import logger from '@server/logger';
import { ApiError } from '@server/types/error';
import { getAppVersion } from '@server/utils/appVersion';
@@ -20,6 +22,23 @@ export interface JellyfinUserResponse {
PrimaryImageTag?: string;
}
export interface JellyfinDevice {
Id: string;
Name: string;
LastUserName: string;
AppName: string;
AppVersion: string;
LastUserId: string;
DateLastActivity: string;
Capabilities: Record<string, unknown>;
}
export interface JellyfinDevicesResponse {
Items: JellyfinDevice[];
TotalRecordCount: number;
StartIndex: number;
}
export interface JellyfinLoginResponse {
User: JellyfinUserResponse;
AccessToken: string;
@@ -92,15 +111,32 @@ export interface JellyfinLibraryItemExtended extends JellyfinLibraryItem {
DateCreated?: string;
}
export interface JellyfinItemsReponse {
Items: JellyfinLibraryItemExtended[];
TotalRecordCount: number;
StartIndex: number;
}
class JellyfinAPI extends ExternalAPI {
private userId?: string;
private mediaServerType: MediaServerType;
constructor(
jellyfinHost: string,
authToken?: string | null,
deviceId?: string | null
) {
const settings = getSettings();
const safeDeviceId =
deviceId && deviceId.length > 0
? deviceId
: Buffer.from('BOT_jellyseerr').toString('base64');
constructor(jellyfinHost: string, authToken?: string, deviceId?: string) {
let authHeaderVal: string;
if (authToken) {
authHeaderVal = `MediaBrowser Client="Jellyseerr", Device="Jellyseerr", DeviceId="${deviceId}", Version="${getAppVersion()}", Token="${authToken}"`;
authHeaderVal = `MediaBrowser Client="Jellyseerr", Device="Jellyseerr", DeviceId="${safeDeviceId}", Version="${getAppVersion()}", Token="${authToken}"`;
} else {
authHeaderVal = `MediaBrowser Client="Jellyseerr", Device="Jellyseerr", DeviceId="${deviceId}", Version="${getAppVersion()}"`;
authHeaderVal = `MediaBrowser Client="Jellyseerr", Device="Jellyseerr", DeviceId="${safeDeviceId}", Version="${getAppVersion()}"`;
}
super(
@@ -109,9 +145,13 @@ class JellyfinAPI extends ExternalAPI {
{
headers: {
'X-Emby-Authorization': authHeaderVal,
'Content-Type': 'application/json',
Accept: 'application/json',
},
}
);
this.mediaServerType = settings.main.mediaServerType;
}
public async login(
@@ -120,7 +160,7 @@ class JellyfinAPI extends ExternalAPI {
ClientIP?: string
): Promise<JellyfinLoginResponse> {
const authenticate = async (useHeaders: boolean) => {
const headers: { [key: string]: string } =
const headers =
useHeaders && ClientIP ? { 'X-Forwarded-For': ClientIP } : {};
return this.post<JellyfinLoginResponse>(
@@ -129,8 +169,6 @@ class JellyfinAPI extends ExternalAPI {
Username,
Pw: Password,
},
{},
undefined,
{ headers }
);
};
@@ -140,36 +178,36 @@ class JellyfinAPI extends ExternalAPI {
} catch (e) {
logger.debug('Failed to authenticate with headers', {
label: 'Jellyfin API',
error: e.cause.message ?? e.cause.statusText,
error: e.response?.statusText,
ip: ClientIP,
});
if (!e.cause.status) {
if (!e.response?.status) {
throw new ApiError(404, ApiErrorCode.InvalidUrl);
}
if (e.cause.status === 401) {
throw new ApiError(e.cause.status, ApiErrorCode.InvalidCredentials);
if (e.response?.status === 401) {
throw new ApiError(e.response?.status, ApiErrorCode.InvalidCredentials);
}
}
try {
return await authenticate(false);
} catch (e) {
if (e.cause.status === 401) {
throw new ApiError(e.cause.status, ApiErrorCode.InvalidCredentials);
if (e.response?.status === 401) {
throw new ApiError(e.response?.status, ApiErrorCode.InvalidCredentials);
}
logger.error(
'Something went wrong while authenticating with the Jellyfin server',
`Something went wrong while authenticating with the Jellyfin server: ${e.message}`,
{
label: 'Jellyfin API',
error: e.cause.message ?? e.cause.statusText,
error: e.response?.status,
ip: ClientIP,
}
);
throw new ApiError(e.cause.status, ApiErrorCode.Unknown);
throw new ApiError(e.response?.status, ApiErrorCode.Unknown);
}
}
@@ -184,7 +222,7 @@ class JellyfinAPI extends ExternalAPI {
return systemInfoResponse;
} catch (e) {
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
@@ -197,11 +235,11 @@ class JellyfinAPI extends ExternalAPI {
return serverResponse.ServerName;
} catch (e) {
logger.error(
'Something went wrong while getting the server name from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting the server name from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.Unknown);
throw new ApiError(e.response?.status, ApiErrorCode.Unknown);
}
}
@@ -212,11 +250,11 @@ class JellyfinAPI extends ExternalAPI {
return { users: userReponse };
} catch (e) {
logger.error(
'Something went wrong while getting the account from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting the account from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
@@ -228,11 +266,11 @@ class JellyfinAPI extends ExternalAPI {
return userReponse;
} catch (e) {
logger.error(
'Something went wrong while getting the account from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting the account from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
@@ -252,10 +290,10 @@ class JellyfinAPI extends ExternalAPI {
return this.mapLibraries(mediaFolderResponse.Items);
} catch (e) {
logger.error(
'Something went wrong while getting libraries from the Jellyfin server',
`Something went wrong while getting libraries from the Jellyfin server: ${e.message}`,
{
label: 'Jellyfin API',
error: e.cause.message ?? e.cause.statusText,
error: e.response?.status,
}
);
@@ -293,16 +331,7 @@ class JellyfinAPI extends ExternalAPI {
public async getLibraryContents(id: string): Promise<JellyfinLibraryItem[]> {
try {
const libraryItemsResponse = await this.get<any>(
`/Users/${this.userId}/Items`,
{
SortBy: 'SortName',
SortOrder: 'Ascending',
IncludeItemTypes: 'Series,Movie,Others',
Recursive: 'true',
StartIndex: '0',
ParentId: id,
collapseBoxSetItems: 'false',
}
`/Items?SortBy=SortName&SortOrder=Ascending&IncludeItemTypes=Series,Movie,Others&Recursive=true&StartIndex=0&ParentId=${id}&collapseBoxSetItems=false`
);
return libraryItemsResponse.Items.filter(
@@ -310,32 +339,36 @@ class JellyfinAPI extends ExternalAPI {
);
} catch (e) {
logger.error(
'Something went wrong while getting library content from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting library content from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e?.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
public async getRecentlyAdded(id: string): Promise<JellyfinLibraryItem[]> {
try {
const endpoint =
this.mediaServerType === MediaServerType.JELLYFIN
? `/Items/Latest`
: `/Users/${this.userId}/Items/Latest`;
const itemResponse = await this.get<any>(
`/Users/${this.userId}/Items/Latest`,
{
Limit: '12',
ParentId: id,
}
`${endpoint}?Limit=12&ParentId=${id}${
this.mediaServerType === MediaServerType.JELLYFIN
? `&userId=${this.userId ?? 'Me'}`
: ''
}`
);
return itemResponse;
} catch (e) {
logger.error(
'Something went wrong while getting library content from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting library content from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
@@ -343,23 +376,26 @@ class JellyfinAPI extends ExternalAPI {
id: string
): Promise<JellyfinLibraryItemExtended | undefined> {
try {
const itemResponse = await this.get<any>(
`/Users/${this.userId}/Items/${id}`
);
const itemResponse = await this.get<JellyfinItemsReponse>(`/Items`, {
params: {
ids: id,
fields: 'ProviderIds,MediaSources,Width,Height,IsHD,DateCreated',
},
});
return itemResponse;
return itemResponse.Items?.[0];
} catch (e) {
if (availabilitySync.running) {
if (e.cause?.status === 500) {
if (e.response?.status === 500) {
return undefined;
}
}
logger.error(
'Something went wrong while getting library content from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting library content from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
@@ -370,11 +406,11 @@ class JellyfinAPI extends ExternalAPI {
return seasonResponse.Items;
} catch (e) {
logger.error(
'Something went wrong while getting the list of seasons from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting the list of seasons from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
@@ -384,10 +420,7 @@ class JellyfinAPI extends ExternalAPI {
): Promise<JellyfinLibraryItem[]> {
try {
const episodeResponse = await this.get<any>(
`/Shows/${seriesID}/Episodes`,
{
seasonId: seasonID,
}
`/Shows/${seriesID}/Episodes?seasonId=${seasonID}`
);
return episodeResponse.Items.filter(
@@ -395,11 +428,11 @@ class JellyfinAPI extends ExternalAPI {
);
} catch (e) {
logger.error(
'Something went wrong while getting the list of episodes from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while getting the list of episodes from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.cause?.status, ApiErrorCode.InvalidAuthToken);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);
}
}
@@ -412,8 +445,8 @@ class JellyfinAPI extends ExternalAPI {
).AccessToken;
} catch (e) {
logger.error(
'Something went wrong while creating an API key from the Jellyfin server',
{ label: 'Jellyfin API', error: e.cause.message ?? e.cause.statusText }
`Something went wrong while creating an API key from the Jellyfin server: ${e.message}`,
{ label: 'Jellyfin API', error: e.response?.status }
);
throw new ApiError(e.response?.status, ApiErrorCode.InvalidAuthToken);

39
server/api/metadata.ts Normal file
View File

@@ -0,0 +1,39 @@
import type { TvShowProvider } from '@server/api/provider';
import TheMovieDb from '@server/api/themoviedb';
import Tvdb from '@server/api/tvdb';
import { getSettings, MetadataProviderType } from '@server/lib/settings';
import logger from '@server/logger';
export const getMetadataProvider = async (
mediaType: 'movie' | 'tv' | 'anime'
): Promise<TvShowProvider> => {
try {
const settings = await getSettings();
if (mediaType == 'movie') {
return new TheMovieDb();
}
if (
mediaType == 'tv' &&
settings.metadataSettings.tv == MetadataProviderType.TVDB
) {
return await Tvdb.getInstance();
}
if (
mediaType == 'anime' &&
settings.metadataSettings.anime == MetadataProviderType.TVDB
) {
return await Tvdb.getInstance();
}
return new TheMovieDb();
} catch (e) {
logger.error('Failed to get metadata provider', {
label: 'Metadata',
message: e.message,
});
return new TheMovieDb();
}
};

View File

@@ -92,7 +92,7 @@ class PlexAPI {
plexSettings,
timeout,
}: {
plexToken?: string;
plexToken?: string | null;
plexSettings?: PlexSettings;
timeout?: number;
}) {
@@ -107,7 +107,7 @@ class PlexAPI {
port: settingsPlex.port,
https: settingsPlex.useSsl,
timeout: timeout,
token: plexToken,
token: plexToken ?? undefined,
authenticator: {
authenticate: (
_plexApi,
@@ -124,9 +124,9 @@ class PlexAPI {
// },
options: {
identifier: settings.clientId,
product: 'Overseerr',
deviceName: 'Overseerr',
platform: 'Overseerr',
product: 'Jellyseerr',
deviceName: 'Jellyseerr',
platform: 'Jellyseerr',
},
});
}

View File

@@ -1,10 +1,10 @@
import ExternalAPI from '@server/api/externalapi';
import type { PlexDevice } from '@server/interfaces/api/plexInterfaces';
import cacheManager from '@server/lib/cache';
import { getSettings } from '@server/lib/settings';
import logger from '@server/logger';
import { randomUUID } from 'node:crypto';
import xml2js from 'xml2js';
import ExternalAPI from './externalapi';
interface PlexAccountResponse {
user: PlexUser;
@@ -143,6 +143,8 @@ class PlexTvAPI extends ExternalAPI {
{
headers: {
'X-Plex-Token': authToken,
'Content-Type': 'application/json',
Accept: 'application/json',
},
nodeCache: cacheManager.getCache('plextv').data,
}
@@ -153,11 +155,15 @@ class PlexTvAPI extends ExternalAPI {
public async getDevices(): Promise<PlexDevice[]> {
try {
const devicesResp = await this.get('/api/resources', {
includeHttps: '1',
});
const devicesResp = await this.axios.get(
'/api/resources?includeHttps=1',
{
transformResponse: [],
responseType: 'text',
}
);
const parsedXml = await xml2js.parseStringPromise(
devicesResp as DeviceResponse
devicesResp.data as DeviceResponse
);
return parsedXml?.MediaContainer?.Device?.map((pxml: DeviceResponse) => ({
name: pxml.$.name,
@@ -205,11 +211,11 @@ class PlexTvAPI extends ExternalAPI {
public async getUser(): Promise<PlexUser> {
try {
const account = await this.get<PlexAccountResponse>(
const account = await this.axios.get<PlexAccountResponse>(
'/users/account.json'
);
return account.user;
return account.data.user;
} catch (e) {
logger.error(
`Something went wrong while getting the account from plex.tv: ${e.message}`,
@@ -249,10 +255,13 @@ class PlexTvAPI extends ExternalAPI {
}
public async getUsers(): Promise<UsersResponse> {
const data = await this.get('/api/users');
const response = await this.axios.get('/api/users', {
transformResponse: [],
responseType: 'text',
});
const parsedXml = (await xml2js.parseStringPromise(
data as string
response.data
)) as UsersResponse;
return parsedXml;
}
@@ -272,28 +281,26 @@ class PlexTvAPI extends ExternalAPI {
this.authToken
);
const params = new URLSearchParams({
'X-Plex-Container-Start': offset.toString(),
'X-Plex-Container-Size': size.toString(),
});
const response = await this.fetch(
`https://metadata.provider.plex.tv/library/sections/watchlist/all?${params.toString()}`,
const response = await this.axios.get<WatchlistResponse>(
'/library/sections/watchlist/all',
{
headers: {
...this.defaultHeaders,
...(cachedWatchlist?.etag
? { 'If-None-Match': cachedWatchlist.etag }
: {}),
params: {
'X-Plex-Container-Start': offset,
'X-Plex-Container-Size': size,
},
headers: {
'If-None-Match': cachedWatchlist?.etag,
},
baseURL: 'https://discover.provider.plex.tv',
validateStatus: (status) => status < 400, // Allow HTTP 304 to return without error
}
);
const data = (await response.json()) as WatchlistResponse;
// If we don't recieve HTTP 304, the watchlist has been updated and we need to update the cache.
if (response.status >= 200 && response.status <= 299) {
cachedWatchlist = {
etag: response.headers.get('etag') ?? '',
response: data,
etag: response.headers.etag,
response: response.data,
};
watchlistCache.data.set<PlexWatchlistCache>(
@@ -307,10 +314,9 @@ class PlexTvAPI extends ExternalAPI {
async (watchlistItem) => {
const detailedResponse = await this.getRolling<MetadataResponse>(
`/library/metadata/${watchlistItem.ratingKey}`,
{},
undefined,
{},
'https://metadata.provider.plex.tv'
{
baseURL: 'https://discover.provider.plex.tv',
}
);
const metadata = detailedResponse.MediaContainer.Metadata[0];
@@ -361,17 +367,12 @@ class PlexTvAPI extends ExternalAPI {
public async pingToken() {
try {
const data: { pong: unknown } = await this.get(
'/api/v2/ping',
{},
undefined,
{
headers: {
'X-Plex-Client-Identifier': randomUUID(),
},
}
);
if (!data?.pong) {
const response = await this.axios.get('/api/v2/ping', {
headers: {
'X-Plex-Client-Identifier': randomUUID(),
},
});
if (!response?.data?.pong) {
throw new Error('No pong response');
}
} catch (e) {

30
server/api/provider.ts Normal file
View File

@@ -0,0 +1,30 @@
import type {
TmdbSeasonWithEpisodes,
TmdbTvDetails,
} from '@server/api/themoviedb/interfaces';
export interface TvShowProvider {
getTvShow({
tvId,
language,
}: {
tvId: number;
language?: string;
}): Promise<TmdbTvDetails>;
getTvSeason({
tvId,
seasonNumber,
language,
}: {
tvId: number;
seasonNumber: number;
language?: string;
}): Promise<TmdbSeasonWithEpisodes>;
getShowByTvdbId({
tvdbId,
language,
}: {
tvdbId: number;
language?: string;
}): Promise<TmdbTvDetails>;
}

View File

@@ -1,4 +1,4 @@
import ExternalAPI from '@server/api/externalapi';
import ExternalAPI from './externalapi';
interface PushoverSoundsResponse {
sounds: {
@@ -26,13 +26,24 @@ export const mapSounds = (sounds: {
class PushoverAPI extends ExternalAPI {
constructor() {
super('https://api.pushover.net/1');
super(
'https://api.pushover.net/1',
{},
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
}
);
}
public async getSounds(appToken: string): Promise<PushoverSound[]> {
try {
const data = await this.get<PushoverSoundsResponse>('/sounds.json', {
token: appToken,
params: {
token: appToken,
},
});
return mapSounds(data.sounds);

View File

@@ -145,6 +145,7 @@ export interface IMDBRating {
title: string;
url: string;
criticsScore: number;
criticsScoreCount: number;
}
/**
@@ -155,13 +156,13 @@ export interface IMDBRating {
*/
class IMDBRadarrProxy extends ExternalAPI {
constructor() {
super(
'https://api.radarr.video/v1',
{},
{
nodeCache: cacheManager.getCache('imdb').data,
}
);
super('https://api.radarr.video/v1', {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
nodeCache: cacheManager.getCache('imdb').data,
});
}
/**
@@ -187,6 +188,7 @@ class IMDBRadarrProxy extends ExternalAPI {
title: data[0].Title,
url: `https://www.imdb.com/title/${data[0].ImdbId}`,
criticsScore: data[0].MovieRatings.Imdb.Value,
criticsScoreCount: data[0].MovieRatings.Imdb.Count,
};
} catch (e) {
throw new Error(

View File

@@ -1,6 +1,7 @@
import ExternalAPI from '@server/api/externalapi';
import cacheManager from '@server/lib/cache';
import { getSettings } from '@server/lib/settings';
import jaro from 'wink-jaro-distance';
interface RTAlgoliaSearchResponse {
results: {
@@ -15,7 +16,7 @@ interface RTAlgoliaHit {
tmsId: string;
type: string;
title: string;
titles: string[];
titles?: string[];
description: string;
releaseYear: number;
rating: string;
@@ -24,9 +25,9 @@ interface RTAlgoliaHit {
isEmsSearchable: boolean;
rtId: number;
vanity: string;
aka: string[];
aka?: string[];
posterImageUrl: string;
rottenTomatoes: {
rottenTomatoes?: {
audienceScore: number;
criticsIconUrl: string;
wantToSeeCount: number;
@@ -47,6 +48,47 @@ export interface RTRating {
url: string;
}
// Tunables
const INEXACT_TITLE_FACTOR = 0.25;
const ALTERNATE_TITLE_FACTOR = 0.8;
const PER_YEAR_PENALTY = 0.4;
const MINIMUM_SCORE = 0.175;
// Normalization for title comparisons.
// Lowercase and strip non-alphanumeric (unicode-aware).
const norm = (s: string): string =>
s.toLowerCase().replace(/[^\p{L}\p{N} ]/gu, '');
// Title similarity. 1 if exact, quarter-jaro otherwise.
const similarity = (a: string, b: string): number =>
a === b ? 1 : jaro(a, b).similarity * INEXACT_TITLE_FACTOR;
// Gets the best similarity score between the searched title and all alternate
// titles of the search result. Non-main titles are penalized.
const t_score = ({ title, titles, aka }: RTAlgoliaHit, s: string): number => {
const f = (t: string, i: number) =>
similarity(norm(t), norm(s)) * (i ? ALTERNATE_TITLE_FACTOR : 1);
return Math.max(...[title].concat(aka || [], titles || []).map(f));
};
// Year difference to score: 0 -> 1.0, 1 -> 0.6, 2 -> 0.2, 3+ -> 0.0
const y_score = (r: RTAlgoliaHit, y?: number): number =>
y ? Math.max(0, 1 - Math.abs(r.releaseYear - y) * PER_YEAR_PENALTY) : 1;
// Cut score in half if result has no ratings.
const extra_score = (r: RTAlgoliaHit): number => (r.rottenTomatoes ? 1 : 0.5);
// Score search result as product of all subscores
const score = (r: RTAlgoliaHit, name: string, year?: number): number =>
t_score(r, name) * y_score(r, year) * extra_score(r);
// Score each search result and return the highest scoring result, if any
const best = (rs: RTAlgoliaHit[], name: string, year?: number): RTAlgoliaHit =>
rs
.map((r) => ({ score: score(r, name, year), result: r }))
.filter(({ score }) => score > MINIMUM_SCORE)
.sort(({ score: a }, { score: b }) => b - a)[0]?.result;
/**
* This is a best-effort API. The Rotten Tomatoes API is technically
* private and getting access costs money/requires approval.
@@ -63,12 +105,15 @@ class RottenTomatoes extends ExternalAPI {
super(
'https://79frdp12pn-dsn.algolia.net/1/indexes/*',
{
'x-algolia-agent': 'Algolia for JavaScript (4.14.3); Browser (lite)',
'x-algolia-agent':
'Algolia%20for%20JavaScript%20(4.14.3)%3B%20Browser%20(lite)',
'x-algolia-api-key': '175588f6e5f8319b27702e4cc4013561',
'x-algolia-application-id': '79FRDP12PN',
},
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'x-algolia-usertoken': settings.clientId,
},
nodeCache: cacheManager.getCache('rt').data,
@@ -90,47 +135,21 @@ class RottenTomatoes extends ExternalAPI {
year: number
): Promise<RTRating | null> {
try {
const filters = encodeURIComponent('isEmsSearchable=1 AND type:"movie"');
const data = await this.post<RTAlgoliaSearchResponse>('/queries', {
requests: [
{
indexName: 'content_rt',
query: name,
params: 'filters=isEmsSearchable%20%3D%201&hitsPerPage=20',
query: name.replace(/\bthe\b ?/gi, ''),
params: `filters=${filters}&hitsPerPage=20`,
},
],
});
const contentResults = data.results.find((r) => r.index === 'content_rt');
const movie = best(contentResults?.hits || [], name, year);
if (!contentResults) {
return null;
}
// First, attempt to match exact name and year
let movie = contentResults.hits.find(
(movie) => movie.releaseYear === year && movie.title === name
);
// If we don't find a movie, try to match partial name and year
if (!movie) {
movie = contentResults.hits.find(
(movie) => movie.releaseYear === year && movie.title.includes(name)
);
}
// If we still dont find a movie, try to match just on year
if (!movie) {
movie = contentResults.hits.find((movie) => movie.releaseYear === year);
}
// One last try, try exact name match only
if (!movie) {
movie = contentResults.hits.find((movie) => movie.title === name);
}
if (!movie?.rottenTomatoes) {
return null;
}
if (!movie?.rottenTomatoes) return null;
return {
title: movie.title,
@@ -158,33 +177,21 @@ class RottenTomatoes extends ExternalAPI {
year?: number
): Promise<RTRating | null> {
try {
const filters = encodeURIComponent('isEmsSearchable=1 AND type:"tv"');
const data = await this.post<RTAlgoliaSearchResponse>('/queries', {
requests: [
{
indexName: 'content_rt',
query: name,
params: 'filters=isEmsSearchable%20%3D%201&hitsPerPage=20',
params: `filters=${filters}&hitsPerPage=20`,
},
],
});
const contentResults = data.results.find((r) => r.index === 'content_rt');
const tvshow = best(contentResults?.hits || [], name, year);
if (!contentResults) {
return null;
}
let tvshow: RTAlgoliaHit | undefined = contentResults.hits[0];
if (year) {
tvshow = contentResults.hits.find(
(series) => series.releaseYear === year
);
}
if (!tvshow || !tvshow.rottenTomatoes) {
return null;
}
if (!tvshow?.rottenTomatoes) return null;
return {
title: tvshow.title,

View File

@@ -113,9 +113,9 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
public getSystemStatus = async (): Promise<SystemStatus> => {
try {
const data = await this.get<SystemStatus>('/system/status');
const response = await this.axios.get<SystemStatus>('/system/status');
return data;
return response.data;
} catch (e) {
throw new Error(
`[${this.apiName}] Failed to retrieve system status: ${e.message}`
@@ -157,15 +157,16 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
public getQueue = async (): Promise<(QueueItem & QueueItemAppendT)[]> => {
try {
const data = await this.get<QueueResponse<QueueItemAppendT>>(
const response = await this.axios.get<QueueResponse<QueueItemAppendT>>(
`/queue`,
{
includeEpisode: 'true',
},
0
params: {
includeEpisode: true,
},
}
);
return data.records;
return response.data.records;
} catch (e) {
throw new Error(
`[${this.apiName}] Failed to retrieve queue: ${e.message}`
@@ -175,9 +176,9 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
public getTags = async (): Promise<Tag[]> => {
try {
const data = await this.get<Tag[]>(`/tag`);
const response = await this.axios.get<Tag[]>(`/tag`);
return data;
return response.data;
} catch (e) {
throw new Error(
`[${this.apiName}] Failed to retrieve tags: ${e.message}`
@@ -187,11 +188,11 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
public createTag = async ({ label }: { label: string }): Promise<Tag> => {
try {
const data = await this.post<Tag>(`/tag`, {
const response = await this.axios.post<Tag>(`/tag`, {
label,
});
return data;
return response.data;
} catch (e) {
throw new Error(`[${this.apiName}] Failed to create tag: ${e.message}`);
}
@@ -206,15 +207,10 @@ class ServarrBase<QueueItemAppendT> extends ExternalAPI {
options: Record<string, unknown>
): Promise<void> {
try {
await this.post(
`/command`,
{
name: commandName,
...options,
},
{},
0
);
await this.axios.post(`/command`, {
name: commandName,
...options,
});
} catch (e) {
throw new Error(`[${this.apiName}] Failed to run command: ${e.message}`);
}

View File

@@ -28,6 +28,39 @@ export interface RadarrMovie {
qualityProfileId: number;
added: string;
hasFile: boolean;
tags: number[];
movieFile?: {
id: number;
movieId: number;
relativePath?: string;
path?: string;
size: number;
dateAdded: string;
sceneName?: string;
releaseGroup?: string;
edition?: string;
indexerFlags?: number;
mediaInfo: {
id: number;
audioBitrate: number;
audioChannels: number;
audioCodec?: string;
audioLanguages?: string;
audioStreamCount: number;
videoBitDepth: number;
videoBitrate: number;
videoCodec?: string;
videoFps: number;
videoDynamicRange?: string;
videoDynamicRangeType?: string;
resolution?: string;
runTime?: string;
scanType?: string;
subtitles?: string;
};
originalFilePath?: string;
qualityCutoffNotMet: boolean;
};
}
class RadarrAPI extends ServarrBase<{ movieId: number }> {
@@ -37,9 +70,9 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
public getMovies = async (): Promise<RadarrMovie[]> => {
try {
const data = await this.get<RadarrMovie[]>('/movie');
const response = await this.axios.get<RadarrMovie[]>('/movie');
return data;
return response.data;
} catch (e) {
throw new Error(`[Radarr] Failed to retrieve movies: ${e.message}`);
}
@@ -47,9 +80,9 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
public getMovie = async ({ id }: { id: number }): Promise<RadarrMovie> => {
try {
const data = await this.get<RadarrMovie>(`/movie/${id}`);
const response = await this.axios.get<RadarrMovie>(`/movie/${id}`);
return data;
return response.data;
} catch (e) {
throw new Error(`[Radarr] Failed to retrieve movie: ${e.message}`);
}
@@ -57,15 +90,17 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
public async getMovieByTmdbId(id: number): Promise<RadarrMovie> {
try {
const data = await this.get<RadarrMovie[]>('/movie/lookup', {
term: `tmdb:${id}`,
const response = await this.axios.get<RadarrMovie[]>('/movie/lookup', {
params: {
term: `tmdb:${id}`,
},
});
if (!data[0]) {
if (!response.data[0]) {
throw new Error('Movie not found');
}
return data[0];
return response.data[0];
} catch (e) {
logger.error('Error retrieving movie by TMDB ID', {
label: 'Radarr API',
@@ -95,7 +130,7 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
// movie exists in Radarr but is neither downloaded nor monitored
if (movie.id && !movie.monitored) {
const data = await this.put<RadarrMovie>(`/movie`, {
const response = await this.axios.put<RadarrMovie>(`/movie`, {
...movie,
title: options.title,
qualityProfileId: options.qualityProfileId,
@@ -104,7 +139,7 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
minimumAvailability: options.minimumAvailability,
tmdbId: options.tmdbId,
year: options.year,
tags: options.tags,
tags: Array.from(new Set([...movie.tags, ...options.tags])),
rootFolderPath: options.rootFolderPath,
monitored: options.monitored,
addOptions: {
@@ -112,25 +147,25 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
},
});
if (data.monitored) {
if (response.data.monitored) {
logger.info(
'Found existing title in Radarr and set it to monitored.',
{
label: 'Radarr',
movieId: data.id,
movieTitle: data.title,
movieId: response.data.id,
movieTitle: response.data.title,
}
);
logger.debug('Radarr update details', {
label: 'Radarr',
movie: data,
movie: response.data,
});
if (options.searchNow) {
this.searchMovie(data.id);
this.searchMovie(response.data.id);
}
return data;
return response.data;
} else {
logger.error('Failed to update existing movie in Radarr.', {
label: 'Radarr',
@@ -148,7 +183,7 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
return movie;
}
const data = await this.post<RadarrMovie>(`/movie`, {
const response = await this.axios.post<RadarrMovie>(`/movie`, {
title: options.title,
qualityProfileId: options.qualityProfileId,
profileId: options.profileId,
@@ -164,11 +199,11 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
},
});
if (data.id) {
if (response.data.id) {
logger.info('Radarr accepted request', { label: 'Radarr' });
logger.debug('Radarr add details', {
label: 'Radarr',
movie: data,
movie: response.data,
});
} else {
logger.error('Failed to add movie to Radarr', {
@@ -177,22 +212,15 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
});
throw new Error('Failed to add movie to Radarr');
}
return data;
return response.data;
} catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error(
'Failed to add movie to Radarr. This might happen if the movie already exists, in which case you can safely ignore this error.',
{
label: 'Radarr',
errorMessage: e.message,
options,
response: errorData,
response: e?.response?.data,
}
);
throw new Error('Failed to add movie to Radarr');
@@ -221,15 +249,34 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
public removeMovie = async (movieId: number): Promise<void> => {
try {
const { id, title } = await this.getMovieByTmdbId(movieId);
await this.delete(`/movie/${id}`, {
deleteFiles: 'true',
addImportExclusion: 'false',
await this.axios.delete(`/movie/${id}`, {
params: {
deleteFiles: true,
addImportExclusion: false,
},
});
logger.info(`[Radarr] Removed movie ${title}`);
} catch (e) {
throw new Error(`[Radarr] Failed to remove movie: ${e.message}`);
}
};
public clearCache = ({
tmdbId,
externalId,
}: {
tmdbId?: number | null;
externalId?: number | null;
}) => {
if (tmdbId) {
this.removeCache('/movie/lookup', {
term: `tmdb:${tmdbId}`,
});
}
if (externalId) {
this.removeCache(`/movie/${externalId}`);
}
};
}
export default RadarrAPI;

View File

@@ -117,9 +117,9 @@ class SonarrAPI extends ServarrBase<{
public async getSeries(): Promise<SonarrSeries[]> {
try {
const data = await this.get<SonarrSeries[]>('/series');
const response = await this.axios.get<SonarrSeries[]>('/series');
return data;
return response.data;
} catch (e) {
throw new Error(`[Sonarr] Failed to retrieve series: ${e.message}`);
}
@@ -127,9 +127,9 @@ class SonarrAPI extends ServarrBase<{
public async getSeriesById(id: number): Promise<SonarrSeries> {
try {
const data = await this.get<SonarrSeries>(`/series/${id}`);
const response = await this.axios.get<SonarrSeries>(`/series/${id}`);
return data;
return response.data;
} catch (e) {
throw new Error(`[Sonarr] Failed to retrieve series by ID: ${e.message}`);
}
@@ -137,15 +137,17 @@ class SonarrAPI extends ServarrBase<{
public async getSeriesByTitle(title: string): Promise<SonarrSeries[]> {
try {
const data = await this.get<SonarrSeries[]>('/series/lookup', {
term: title,
const response = await this.axios.get<SonarrSeries[]>('/series/lookup', {
params: {
term: title,
},
});
if (!data[0]) {
if (!response.data[0]) {
throw new Error('No series found');
}
return data;
return response.data;
} catch (e) {
logger.error('Error retrieving series by series title', {
label: 'Sonarr API',
@@ -158,15 +160,17 @@ class SonarrAPI extends ServarrBase<{
public async getSeriesByTvdbId(id: number): Promise<SonarrSeries> {
try {
const data = await this.get<SonarrSeries[]>('/series/lookup', {
term: `tvdb:${id}`,
const response = await this.axios.get<SonarrSeries[]>('/series/lookup', {
params: {
term: `tvdb:${id}`,
},
});
if (!data[0]) {
if (!response.data[0]) {
throw new Error('Series not found');
}
return data[0];
return response.data[0];
} catch (e) {
logger.error('Error retrieving series by tvdb ID', {
label: 'Sonarr API',
@@ -184,30 +188,32 @@ class SonarrAPI extends ServarrBase<{
// If the series already exists, we will simply just update it
if (series.id) {
series.monitored = options.monitored ?? series.monitored;
series.tags = options.tags ?? series.tags;
series.tags = options.tags
? Array.from(new Set([...series.tags, ...options.tags]))
: series.tags;
series.seasons = this.buildSeasonList(options.seasons, series.seasons);
const newSeriesData = await this.put<SonarrSeries>(
const newSeriesResponse = await this.axios.put<SonarrSeries>(
'/series',
series as any
series
);
if (newSeriesData.id) {
if (newSeriesResponse.data.id) {
logger.info('Updated existing series in Sonarr.', {
label: 'Sonarr',
seriesId: newSeriesData.id,
seriesTitle: newSeriesData.title,
seriesId: newSeriesResponse.data.id,
seriesTitle: newSeriesResponse.data.title,
});
logger.debug('Sonarr update details', {
label: 'Sonarr',
movie: newSeriesData,
series: newSeriesResponse.data,
});
if (options.searchNow) {
this.searchSeries(newSeriesData.id);
this.searchSeries(newSeriesResponse.data.id);
}
return newSeriesData;
return newSeriesResponse.data;
} else {
logger.error('Failed to update series in Sonarr', {
label: 'Sonarr',
@@ -217,35 +223,38 @@ class SonarrAPI extends ServarrBase<{
}
}
const createdSeriesData = await this.post<SonarrSeries>('/series', {
tvdbId: options.tvdbid,
title: options.title,
qualityProfileId: options.profileId,
languageProfileId: options.languageProfileId,
seasons: this.buildSeasonList(
options.seasons,
series.seasons.map((season) => ({
seasonNumber: season.seasonNumber,
// We force all seasons to false if its the first request
monitored: false,
}))
),
tags: options.tags,
seasonFolder: options.seasonFolder,
monitored: options.monitored,
rootFolderPath: options.rootFolderPath,
seriesType: options.seriesType,
addOptions: {
ignoreEpisodesWithFiles: true,
searchForMissingEpisodes: options.searchNow,
},
} as Partial<SonarrSeries>);
const createdSeriesResponse = await this.axios.post<SonarrSeries>(
'/series',
{
tvdbId: options.tvdbid,
title: options.title,
qualityProfileId: options.profileId,
languageProfileId: options.languageProfileId,
seasons: this.buildSeasonList(
options.seasons,
series.seasons.map((season) => ({
seasonNumber: season.seasonNumber,
// We force all seasons to false if its the first request
monitored: false,
}))
),
tags: options.tags,
seasonFolder: options.seasonFolder,
monitored: options.monitored,
rootFolderPath: options.rootFolderPath,
seriesType: options.seriesType,
addOptions: {
ignoreEpisodesWithFiles: true,
searchForMissingEpisodes: options.searchNow,
},
} as Partial<SonarrSeries>
);
if (createdSeriesData.id) {
if (createdSeriesResponse.data.id) {
logger.info('Sonarr accepted request', { label: 'Sonarr' });
logger.debug('Sonarr add details', {
label: 'Sonarr',
movie: createdSeriesData,
series: createdSeriesResponse.data,
});
} else {
logger.error('Failed to add movie to Sonarr', {
@@ -255,20 +264,13 @@ class SonarrAPI extends ServarrBase<{
throw new Error('Failed to add series to Sonarr');
}
return createdSeriesData;
return createdSeriesResponse.data;
} catch (e) {
let errorData;
try {
errorData = await e.cause?.text();
errorData = JSON.parse(errorData);
} catch {
/* empty */
}
logger.error('Something went wrong while adding a series to Sonarr.', {
label: 'Sonarr API',
errorMessage: e.message,
options,
response: errorData,
response: e?.response?.data,
});
throw new Error('Failed to add series');
}
@@ -340,19 +342,44 @@ class SonarrAPI extends ServarrBase<{
return newSeasons;
}
public removeSerie = async (serieId: number): Promise<void> => {
try {
const { id, title } = await this.getSeriesByTvdbId(serieId);
await this.delete(`/series/${id}`, {
deleteFiles: 'true',
addImportExclusion: 'false',
await this.axios.delete(`/series/${id}`, {
params: {
deleteFiles: true,
addImportExclusion: false,
},
});
logger.info(`[Radarr] Removed serie ${title}`);
} catch (e) {
throw new Error(`[Radarr] Failed to remove serie: ${e.message}`);
}
};
public clearCache = ({
tvdbId,
externalId,
title,
}: {
tvdbId?: number | null;
externalId?: number | null;
title?: string | null;
}) => {
if (tvdbId) {
this.removeCache('/series/lookup', {
term: `tvdb:${tvdbId}`,
});
}
if (externalId) {
this.removeCache(`/series/${externalId}`);
}
if (title) {
this.removeCache('/series/lookup', {
term: title,
});
}
};
}
export default SonarrAPI;

View File

@@ -1,7 +1,9 @@
import ExternalAPI from '@server/api/externalapi';
import type { User } from '@server/entity/User';
import type { TautulliSettings } from '@server/lib/settings';
import logger from '@server/logger';
import { requestInterceptorFunction } from '@server/utils/customProxyAgent';
import type { AxiosInstance } from 'axios';
import axios from 'axios';
import { uniqWith } from 'lodash';
export interface TautulliHistoryRecord {
@@ -112,25 +114,26 @@ interface TautulliInfoResponse {
};
}
class TautulliAPI extends ExternalAPI {
class TautulliAPI {
private axios: AxiosInstance;
constructor(settings: TautulliSettings) {
super(
`${settings.useSsl ? 'https' : 'http'}://${settings.hostname}:${
this.axios = axios.create({
baseURL: `${settings.useSsl ? 'https' : 'http'}://${settings.hostname}:${
settings.port
}${settings.urlBase ?? ''}`,
{
apikey: settings.apiKey || '',
}
);
params: { apikey: settings.apiKey },
});
this.axios.interceptors.request.use(requestInterceptorFunction);
}
public async getInfo(): Promise<TautulliInfo> {
try {
return (
await this.get<TautulliInfoResponse>('/api/v2', {
cmd: 'get_tautulli_info',
await this.axios.get<TautulliInfoResponse>('/api/v2', {
params: { cmd: 'get_tautulli_info' },
})
).response.data;
).data.response.data;
} catch (e) {
logger.error('Something went wrong fetching Tautulli server info', {
label: 'Tautulli API',
@@ -147,12 +150,14 @@ class TautulliAPI extends ExternalAPI {
): Promise<TautulliWatchStats[]> {
try {
return (
await this.get<TautulliWatchStatsResponse>('/api/v2', {
cmd: 'get_item_watch_time_stats',
rating_key: ratingKey,
grouping: '1',
await this.axios.get<TautulliWatchStatsResponse>('/api/v2', {
params: {
cmd: 'get_item_watch_time_stats',
rating_key: ratingKey,
grouping: 1,
},
})
).response.data;
).data.response.data;
} catch (e) {
logger.error(
'Something went wrong fetching media watch stats from Tautulli',
@@ -173,12 +178,14 @@ class TautulliAPI extends ExternalAPI {
): Promise<TautulliWatchUser[]> {
try {
return (
await this.get<TautulliWatchUsersResponse>('/api/v2', {
cmd: 'get_item_user_stats',
rating_key: ratingKey,
grouping: '1',
await this.axios.get<TautulliWatchUsersResponse>('/api/v2', {
params: {
cmd: 'get_item_user_stats',
rating_key: ratingKey,
grouping: 1,
},
})
).response.data;
).data.response.data;
} catch (e) {
logger.error(
'Something went wrong fetching media watch users from Tautulli',
@@ -201,13 +208,15 @@ class TautulliAPI extends ExternalAPI {
}
return (
await this.get<TautulliWatchStatsResponse>('/api/v2', {
cmd: 'get_user_watch_time_stats',
user_id: user.plexId.toString(),
query_days: '0',
grouping: '1',
await this.axios.get<TautulliWatchStatsResponse>('/api/v2', {
params: {
cmd: 'get_user_watch_time_stats',
user_id: user.plexId,
query_days: 0,
grouping: 1,
},
})
).response.data[0];
).data.response.data[0];
} catch (e) {
logger.error(
'Something went wrong fetching user watch stats from Tautulli',
@@ -238,17 +247,19 @@ class TautulliAPI extends ExternalAPI {
while (results.length < 20) {
const tautulliData = (
await this.get<TautulliHistoryResponse>('/api/v2', {
cmd: 'get_history',
grouping: '1',
order_column: 'date',
order_dir: 'desc',
user_id: user.plexId.toString(),
media_type: 'movie,episode',
length: take.toString(),
start: start.toString(),
await this.axios.get<TautulliHistoryResponse>('/api/v2', {
params: {
cmd: 'get_history',
grouping: 1,
order_column: 'date',
order_dir: 'desc',
user_id: user.plexId,
media_type: 'movie,episode',
length: take,
start,
},
})
).response.data.data;
).data.response.data.data;
if (!tautulliData.length) {
return results;

View File

@@ -1,5 +1,7 @@
import ExternalAPI from '@server/api/externalapi';
import type { TvShowProvider } from '@server/api/provider';
import cacheManager from '@server/lib/cache';
import { getSettings } from '@server/lib/settings';
import { sortBy } from 'lodash';
import type {
TmdbCollection,
@@ -37,23 +39,36 @@ interface SingleSearchOptions extends SearchOptions {
year?: number;
}
export type SortOptions =
| 'popularity.asc'
| 'popularity.desc'
| 'release_date.asc'
| 'release_date.desc'
| 'revenue.asc'
| 'revenue.desc'
| 'primary_release_date.asc'
| 'primary_release_date.desc'
| 'original_title.asc'
| 'original_title.desc'
| 'vote_average.asc'
| 'vote_average.desc'
| 'vote_count.asc'
| 'vote_count.desc'
| 'first_air_date.asc'
| 'first_air_date.desc';
export const SortOptionsIterable = [
'popularity.desc',
'popularity.asc',
'release_date.desc',
'release_date.asc',
'revenue.desc',
'revenue.asc',
'primary_release_date.desc',
'primary_release_date.asc',
'original_title.asc',
'original_title.desc',
'vote_average.desc',
'vote_average.asc',
'vote_count.desc',
'vote_count.asc',
'first_air_date.desc',
'first_air_date.asc',
] as const;
export type SortOptions = (typeof SortOptionsIterable)[number];
export interface TmdbCertificationResponse {
certifications: {
[country: string]: {
certification: string;
meaning?: string;
order?: number;
}[];
};
}
interface DiscoverMovieOptions {
page?: number;
@@ -74,6 +89,10 @@ interface DiscoverMovieOptions {
sortBy?: SortOptions;
watchRegion?: string;
watchProviders?: string;
certification?: string;
certificationGte?: string;
certificationLte?: string;
certificationCountry?: string;
}
interface DiscoverTvOptions {
@@ -96,9 +115,14 @@ interface DiscoverTvOptions {
watchRegion?: string;
watchProviders?: string;
withStatus?: string; // Returning Series: 0 Planned: 1 In Production: 2 Ended: 3 Cancelled: 4 Pilot: 5
certification?: string;
certificationGte?: string;
certificationLte?: string;
certificationCountry?: string;
}
class TheMovieDb extends ExternalAPI {
class TheMovieDb extends ExternalAPI implements TvShowProvider {
private locale: string;
private discoverRegion?: string;
private originalLanguage?: string;
constructor({
@@ -108,16 +132,17 @@ class TheMovieDb extends ExternalAPI {
super(
'https://api.themoviedb.org/3',
{
api_key: 'db55323b8d3e4154498498a75642b381',
api_key: '431a8708161bcd1f1fbe7536137e61ed',
},
{
nodeCache: cacheManager.getCache('tmdb').data,
rateLimit: {
maxRequests: 20,
maxRPS: 50,
id: 'tmdb',
},
}
);
this.locale = getSettings().main?.locale || 'en';
this.discoverRegion = discoverRegion;
this.originalLanguage = originalLanguage;
}
@@ -126,14 +151,11 @@ class TheMovieDb extends ExternalAPI {
query,
page = 1,
includeAdult = false,
language = 'en',
language = this.locale,
}: SearchOptions): Promise<TmdbSearchMultiResponse> => {
try {
const data = await this.get<TmdbSearchMultiResponse>('/search/multi', {
query,
page: page.toString(),
include_adult: includeAdult ? 'true' : 'false',
language,
params: { query, page, include_adult: includeAdult, language },
});
return data;
@@ -151,16 +173,18 @@ class TheMovieDb extends ExternalAPI {
query,
page = 1,
includeAdult = false,
language = 'en',
language = this.locale,
year,
}: SingleSearchOptions): Promise<TmdbSearchMovieResponse> => {
try {
const data = await this.get<TmdbSearchMovieResponse>('/search/movie', {
query,
page: page.toString(),
include_adult: includeAdult ? 'true' : 'false',
language,
primary_release_year: year?.toString() || '',
params: {
query,
page,
include_adult: includeAdult,
language,
primary_release_year: year,
},
});
return data;
@@ -178,16 +202,18 @@ class TheMovieDb extends ExternalAPI {
query,
page = 1,
includeAdult = false,
language = 'en',
language = this.locale,
year,
}: SingleSearchOptions): Promise<TmdbSearchTvResponse> => {
try {
const data = await this.get<TmdbSearchTvResponse>('/search/tv', {
query,
page: page.toString(),
include_adult: includeAdult ? 'true' : 'false',
language,
first_air_date_year: year?.toString() || '',
params: {
query,
page,
include_adult: includeAdult,
language,
first_air_date_year: year,
},
});
return data;
@@ -203,14 +229,14 @@ class TheMovieDb extends ExternalAPI {
public getPerson = async ({
personId,
language = 'en',
language = this.locale,
}: {
personId: number;
language?: string;
}): Promise<TmdbPersonDetails> => {
try {
const data = await this.get<TmdbPersonDetails>(`/person/${personId}`, {
language,
params: { language },
});
return data;
@@ -221,7 +247,7 @@ class TheMovieDb extends ExternalAPI {
public getPersonCombinedCredits = async ({
personId,
language = 'en',
language = this.locale,
}: {
personId: number;
language?: string;
@@ -230,7 +256,7 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbPersonCombinedCredits>(
`/person/${personId}/combined_credits`,
{
language,
params: { language },
}
);
@@ -244,7 +270,7 @@ class TheMovieDb extends ExternalAPI {
public getMovie = async ({
movieId,
language = 'en',
language = this.locale,
}: {
movieId: number;
language?: string;
@@ -253,9 +279,12 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbMovieDetails>(
`/movie/${movieId}`,
{
language,
append_to_response:
'credits,external_ids,videos,keywords,release_dates,watch/providers',
params: {
language,
append_to_response:
'credits,external_ids,videos,keywords,release_dates,watch/providers',
include_video_language: language + ', en',
},
},
43200
);
@@ -268,7 +297,7 @@ class TheMovieDb extends ExternalAPI {
public getTvShow = async ({
tvId,
language = 'en',
language = this.locale,
}: {
tvId: number;
language?: string;
@@ -277,9 +306,12 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbTvDetails>(
`/tv/${tvId}`,
{
language,
append_to_response:
'aggregate_credits,credits,external_ids,keywords,videos,content_ratings,watch/providers',
params: {
language,
append_to_response:
'aggregate_credits,credits,external_ids,keywords,videos,content_ratings,watch/providers',
include_video_language: language + ', en',
},
},
43200
);
@@ -303,11 +335,20 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSeasonWithEpisodes>(
`/tv/${tvId}/season/${seasonNumber}`,
{
language: language || '',
append_to_response: 'external_ids',
params: {
language,
append_to_response: 'external_ids',
},
}
);
data.episodes = data.episodes.map((episode) => {
if (episode.still_path) {
episode.still_path = `https://image.tmdb.org/t/p/original/${episode.still_path}`;
}
return episode;
});
return data;
} catch (e) {
throw new Error(`[TMDB] Failed to fetch TV show details: ${e.message}`);
@@ -317,7 +358,7 @@ class TheMovieDb extends ExternalAPI {
public async getMovieRecommendations({
movieId,
page = 1,
language = 'en',
language = this.locale,
}: {
movieId: number;
page?: number;
@@ -327,8 +368,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSearchMovieResponse>(
`/movie/${movieId}/recommendations`,
{
page: page.toString(),
language,
params: {
page,
language,
},
}
);
@@ -341,7 +384,7 @@ class TheMovieDb extends ExternalAPI {
public async getMovieSimilar({
movieId,
page = 1,
language = 'en',
language = this.locale,
}: {
movieId: number;
page?: number;
@@ -351,8 +394,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSearchMovieResponse>(
`/movie/${movieId}/similar`,
{
page: page.toString(),
language,
params: {
page,
language,
},
}
);
@@ -365,7 +410,7 @@ class TheMovieDb extends ExternalAPI {
public async getMoviesByKeyword({
keywordId,
page = 1,
language = 'en',
language = this.locale,
}: {
keywordId: number;
page?: number;
@@ -375,8 +420,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSearchMovieResponse>(
`/keyword/${keywordId}/movies`,
{
page: page.toString(),
language,
params: {
page,
language,
},
}
);
@@ -389,7 +436,7 @@ class TheMovieDb extends ExternalAPI {
public async getTvRecommendations({
tvId,
page = 1,
language = 'en',
language = this.locale,
}: {
tvId: number;
page?: number;
@@ -399,8 +446,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSearchTvResponse>(
`/tv/${tvId}/recommendations`,
{
page: page.toString(),
language,
params: {
page,
language,
},
}
);
@@ -415,7 +464,7 @@ class TheMovieDb extends ExternalAPI {
public async getTvSimilar({
tvId,
page = 1,
language = 'en',
language = this.locale,
}: {
tvId: number;
page?: number;
@@ -423,8 +472,10 @@ class TheMovieDb extends ExternalAPI {
}): Promise<TmdbSearchTvResponse> {
try {
const data = await this.get<TmdbSearchTvResponse>(`/tv/${tvId}/similar`, {
page: page.toString(),
language,
params: {
page,
language,
},
});
return data;
@@ -437,7 +488,7 @@ class TheMovieDb extends ExternalAPI {
sortBy = 'popularity.desc',
page = 1,
includeAdult = false,
language = 'en',
language = this.locale,
primaryReleaseDateGte,
primaryReleaseDateLte,
originalLanguage,
@@ -452,6 +503,10 @@ class TheMovieDb extends ExternalAPI {
voteCountLte,
watchProviders,
watchRegion,
certification,
certificationGte,
certificationLte,
certificationCountry,
}: DiscoverMovieOptions = {}): Promise<TmdbSearchMovieResponse> => {
try {
const defaultFutureDate = new Date(
@@ -465,38 +520,44 @@ class TheMovieDb extends ExternalAPI {
.split('T')[0];
const data = await this.get<TmdbSearchMovieResponse>('/discover/movie', {
sort_by: sortBy,
page: page.toString(),
include_adult: includeAdult ? 'true' : 'false',
language,
region: this.discoverRegion || '',
with_original_language:
originalLanguage && originalLanguage !== 'all'
? originalLanguage
: originalLanguage === 'all'
? ''
: this.originalLanguage || '',
// Set our release date values, but check if one is set and not the other,
// so we can force a past date or a future date. TMDB Requires both values if one is set!
'primary_release_date.gte':
!primaryReleaseDateGte && primaryReleaseDateLte
? defaultPastDate
: primaryReleaseDateGte || '',
'primary_release_date.lte':
!primaryReleaseDateLte && primaryReleaseDateGte
? defaultFutureDate
: primaryReleaseDateLte || '',
with_genres: genre || '',
with_companies: studio || '',
with_keywords: keywords || '',
'with_runtime.gte': withRuntimeGte || '',
'with_runtime.lte': withRuntimeLte || '',
'vote_average.gte': voteAverageGte || '',
'vote_average.lte': voteAverageLte || '',
'vote_count.gte': voteCountGte || '',
'vote_count.lte': voteCountLte || '',
watch_region: watchRegion || '',
with_watch_providers: watchProviders || '',
params: {
sort_by: sortBy,
page,
include_adult: includeAdult,
language,
region: this.discoverRegion || '',
with_original_language:
originalLanguage && originalLanguage !== 'all'
? originalLanguage
: originalLanguage === 'all'
? undefined
: this.originalLanguage,
// Set our release date values, but check if one is set and not the other,
// so we can force a past date or a future date. TMDB Requires both values if one is set!
'primary_release_date.gte':
!primaryReleaseDateGte && primaryReleaseDateLte
? defaultPastDate
: primaryReleaseDateGte,
'primary_release_date.lte':
!primaryReleaseDateLte && primaryReleaseDateGte
? defaultFutureDate
: primaryReleaseDateLte,
with_genres: genre,
with_companies: studio,
with_keywords: keywords,
'with_runtime.gte': withRuntimeGte,
'with_runtime.lte': withRuntimeLte,
'vote_average.gte': voteAverageGte,
'vote_average.lte': voteAverageLte,
'vote_count.gte': voteCountGte,
'vote_count.lte': voteCountLte,
watch_region: watchRegion,
with_watch_providers: watchProviders,
certification: certification,
'certification.gte': certificationGte,
'certification.lte': certificationLte,
certification_country: certificationCountry,
},
});
return data;
@@ -508,7 +569,7 @@ class TheMovieDb extends ExternalAPI {
public getDiscoverTv = async ({
sortBy = 'popularity.desc',
page = 1,
language = 'en',
language = this.locale,
firstAirDateGte,
firstAirDateLte,
includeEmptyReleaseDate = false,
@@ -525,6 +586,10 @@ class TheMovieDb extends ExternalAPI {
watchProviders,
watchRegion,
withStatus,
certification,
certificationGte,
certificationLte,
certificationCountry,
}: DiscoverTvOptions = {}): Promise<TmdbSearchTvResponse> => {
try {
const defaultFutureDate = new Date(
@@ -538,41 +603,45 @@ class TheMovieDb extends ExternalAPI {
.split('T')[0];
const data = await this.get<TmdbSearchTvResponse>('/discover/tv', {
sort_by: sortBy,
page: page.toString(),
language,
region: this.discoverRegion || '',
// Set our release date values, but check if one is set and not the other,
// so we can force a past date or a future date. TMDB Requires both values if one is set!
'first_air_date.gte':
!firstAirDateGte && firstAirDateLte
? defaultPastDate
: firstAirDateGte || '',
'first_air_date.lte':
!firstAirDateLte && firstAirDateGte
? defaultFutureDate
: firstAirDateLte || '',
with_original_language:
originalLanguage && originalLanguage !== 'all'
? originalLanguage
: originalLanguage === 'all'
? ''
: this.originalLanguage || '',
include_null_first_air_dates: includeEmptyReleaseDate
? 'true'
: 'false',
with_genres: genre || '',
with_networks: network?.toString() || '',
with_keywords: keywords || '',
'with_runtime.gte': withRuntimeGte || '',
'with_runtime.lte': withRuntimeLte || '',
'vote_average.gte': voteAverageGte || '',
'vote_average.lte': voteAverageLte || '',
'vote_count.gte': voteCountGte || '',
'vote_count.lte': voteCountLte || '',
with_watch_providers: watchProviders || '',
watch_region: watchRegion || '',
with_status: withStatus || '',
params: {
sort_by: sortBy,
page,
language,
region: this.discoverRegion || '',
// Set our release date values, but check if one is set and not the other,
// so we can force a past date or a future date. TMDB Requires both values if one is set!
'first_air_date.gte':
!firstAirDateGte && firstAirDateLte
? defaultPastDate
: firstAirDateGte,
'first_air_date.lte':
!firstAirDateLte && firstAirDateGte
? defaultFutureDate
: firstAirDateLte,
with_original_language:
originalLanguage && originalLanguage !== 'all'
? originalLanguage
: originalLanguage === 'all'
? undefined
: this.originalLanguage,
include_null_first_air_dates: includeEmptyReleaseDate,
with_genres: genre,
with_networks: network,
with_keywords: keywords,
'with_runtime.gte': withRuntimeGte,
'with_runtime.lte': withRuntimeLte,
'vote_average.gte': voteAverageGte,
'vote_average.lte': voteAverageLte,
'vote_count.gte': voteCountGte,
'vote_count.lte': voteCountLte,
with_watch_providers: watchProviders,
watch_region: watchRegion,
with_status: withStatus,
certification: certification,
'certification.gte': certificationGte,
'certification.lte': certificationLte,
certification_country: certificationCountry,
},
});
return data;
@@ -583,7 +652,7 @@ class TheMovieDb extends ExternalAPI {
public getUpcomingMovies = async ({
page = 1,
language = 'en',
language = this.locale,
}: {
page: number;
language: string;
@@ -592,10 +661,12 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbUpcomingMoviesResponse>(
'/movie/upcoming',
{
page: page.toString(),
language,
region: this.discoverRegion || '',
originalLanguage: this.originalLanguage || '',
params: {
page,
language,
region: this.discoverRegion,
originalLanguage: this.originalLanguage,
},
}
);
@@ -608,7 +679,7 @@ class TheMovieDb extends ExternalAPI {
public getAllTrending = async ({
page = 1,
timeWindow = 'day',
language = 'en',
language = this.locale,
}: {
page?: number;
timeWindow?: 'day' | 'week';
@@ -618,9 +689,11 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSearchMultiResponse>(
`/trending/all/${timeWindow}`,
{
page: page.toString(),
language,
region: this.discoverRegion || '',
params: {
page,
language,
region: this.discoverRegion,
},
}
);
@@ -641,7 +714,9 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSearchMovieResponse>(
`/trending/movie/${timeWindow}`,
{
page: page.toString(),
params: {
page,
},
}
);
@@ -662,7 +737,9 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbSearchTvResponse>(
`/trending/tv/${timeWindow}`,
{
page: page.toString(),
params: {
page,
},
}
);
@@ -675,7 +752,7 @@ class TheMovieDb extends ExternalAPI {
public async getByExternalId({
externalId,
type,
language = 'en',
language = this.locale,
}:
| {
externalId: string;
@@ -691,8 +768,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbExternalIdResponse>(
`/find/${externalId}`,
{
external_source: type === 'imdb' ? 'imdb_id' : 'tvdb_id',
language,
params: {
external_source: type === 'imdb' ? 'imdb_id' : 'tvdb_id',
language,
},
}
);
@@ -704,7 +783,7 @@ class TheMovieDb extends ExternalAPI {
public async getMediaByImdbId({
imdbId,
language = 'en',
language = this.locale,
}: {
imdbId: string;
language?: string;
@@ -743,7 +822,7 @@ class TheMovieDb extends ExternalAPI {
public async getShowByTvdbId({
tvdbId,
language = 'en',
language = this.locale,
}: {
tvdbId: number;
language?: string;
@@ -773,7 +852,7 @@ class TheMovieDb extends ExternalAPI {
public async getCollection({
collectionId,
language = 'en',
language = this.locale,
}: {
collectionId: number;
language?: string;
@@ -782,7 +861,9 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbCollection>(
`/collection/${collectionId}`,
{
language,
params: {
language,
},
}
);
@@ -847,7 +928,7 @@ class TheMovieDb extends ExternalAPI {
}
public async getMovieGenres({
language = 'en',
language = this.locale,
}: {
language?: string;
} = {}): Promise<TmdbGenre[]> {
@@ -855,7 +936,9 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbGenresResult>(
'/genre/movie/list',
{
language,
params: {
language,
},
},
86400 // 24 hours
);
@@ -867,7 +950,9 @@ class TheMovieDb extends ExternalAPI {
const englishData = await this.get<TmdbGenresResult>(
'/genre/movie/list',
{
language: 'en',
params: {
language: 'en',
},
},
86400 // 24 hours
);
@@ -894,7 +979,7 @@ class TheMovieDb extends ExternalAPI {
}
public async getTvGenres({
language = 'en',
language = this.locale,
}: {
language?: string;
} = {}): Promise<TmdbGenre[]> {
@@ -902,7 +987,9 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbGenresResult>(
'/genre/tv/list',
{
language,
params: {
language,
},
},
86400 // 24 hours
);
@@ -914,7 +1001,9 @@ class TheMovieDb extends ExternalAPI {
const englishData = await this.get<TmdbGenresResult>(
'/genre/tv/list',
{
language: 'en',
params: {
language: 'en',
},
},
86400 // 24 hours
);
@@ -940,11 +1029,40 @@ class TheMovieDb extends ExternalAPI {
}
}
public getMovieCertifications =
async (): Promise<TmdbCertificationResponse> => {
try {
const data = await this.get<TmdbCertificationResponse>(
'/certification/movie/list',
{},
604800 // 7 days
);
return data;
} catch (e) {
throw new Error(`[TMDB] Failed to fetch movie certifications: ${e}`);
}
};
public getTvCertifications = async (): Promise<TmdbCertificationResponse> => {
try {
const data = await this.get<TmdbCertificationResponse>(
'/certification/tv/list',
{},
604800 // 7 days
);
return data;
} catch (e) {
throw new Error(`[TMDB] Failed to fetch TV certifications: ${e.message}`);
}
};
public async getKeywordDetails({
keywordId,
}: {
keywordId: number;
}): Promise<TmdbKeyword> {
}): Promise<TmdbKeyword | null> {
try {
const data = await this.get<TmdbKeyword>(
`/keyword/${keywordId}`,
@@ -954,6 +1072,9 @@ class TheMovieDb extends ExternalAPI {
return data;
} catch (e) {
if (e.response?.status === 404) {
return null;
}
throw new Error(`[TMDB] Failed to fetch keyword: ${e.message}`);
}
}
@@ -969,8 +1090,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbKeywordSearchResponse>(
'/search/keyword',
{
query,
page: page.toString(),
params: {
query,
page,
},
},
86400 // 24 hours
);
@@ -992,8 +1115,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<TmdbCompanySearchResponse>(
'/search/company',
{
query,
page: page.toString(),
params: {
query,
page,
},
},
86400 // 24 hours
);
@@ -1013,7 +1138,9 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<{ results: TmdbWatchProviderRegion[] }>(
'/watch/providers/regions',
{
language: language ? this.originalLanguage || '' : '',
params: {
language: language ?? this.originalLanguage,
},
},
86400 // 24 hours
);
@@ -1037,8 +1164,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<{ results: TmdbWatchProviderDetails[] }>(
'/watch/providers/movie',
{
language: language ? this.originalLanguage || '' : '',
watch_region: watchRegion,
params: {
language: language ?? this.originalLanguage,
watch_region: watchRegion,
},
},
86400 // 24 hours
);
@@ -1062,8 +1191,10 @@ class TheMovieDb extends ExternalAPI {
const data = await this.get<{ results: TmdbWatchProviderDetails[] }>(
'/watch/providers/tv',
{
language: language ? this.originalLanguage || '' : '',
watch_region: watchRegion,
params: {
language: language ?? this.originalLanguage,
watch_region: watchRegion,
},
},
86400 // 24 hours
);

View File

@@ -220,7 +220,7 @@ export interface TmdbTvEpisodeResult {
show_id: number;
still_path: string;
vote_average: number;
vote_cuont: number;
vote_count: number;
}
export interface TmdbTvSeasonResult {

431
server/api/tvdb/index.ts Normal file
View File

@@ -0,0 +1,431 @@
import ExternalAPI from '@server/api/externalapi';
import type { TvShowProvider } from '@server/api/provider';
import TheMovieDb from '@server/api/themoviedb';
import type {
TmdbSeasonWithEpisodes,
TmdbTvDetails,
TmdbTvEpisodeResult,
TmdbTvSeasonResult,
} from '@server/api/themoviedb/interfaces';
import type {
TvdbBaseResponse,
TvdbEpisode,
TvdbLoginResponse,
TvdbSeasonDetails,
TvdbTvDetails,
} from '@server/api/tvdb/interfaces';
import cacheManager, { type AvailableCacheIds } from '@server/lib/cache';
import logger from '@server/logger';
interface TvdbConfig {
baseUrl: string;
maxRequestsPerSecond: number;
maxRequests: number;
cachePrefix: AvailableCacheIds;
}
const DEFAULT_CONFIG: TvdbConfig = {
baseUrl: 'https://api4.thetvdb.com/v4',
maxRequestsPerSecond: 50,
maxRequests: 20,
cachePrefix: 'tvdb' as const,
};
const enum TvdbIdStatus {
INVALID = -1,
}
type TvdbId = number;
type ValidTvdbId = Exclude<TvdbId, TvdbIdStatus.INVALID>;
class Tvdb extends ExternalAPI implements TvShowProvider {
static instance: Tvdb;
private readonly tmdb: TheMovieDb;
private static readonly DEFAULT_CACHE_TTL = 43200;
private static readonly DEFAULT_LANGUAGE = 'eng';
private token: string;
private pin?: string;
constructor(pin?: string) {
const finalConfig = { ...DEFAULT_CONFIG };
super(
finalConfig.baseUrl,
{},
{
nodeCache: cacheManager.getCache(finalConfig.cachePrefix).data,
rateLimit: {
maxRequests: finalConfig.maxRequests,
maxRPS: finalConfig.maxRequestsPerSecond,
},
}
);
this.pin = pin;
this.tmdb = new TheMovieDb();
}
public static async getInstance(): Promise<Tvdb> {
if (!this.instance) {
this.instance = new Tvdb();
await this.instance.login();
}
return this.instance;
}
private async refreshToken(): Promise<void> {
try {
if (!this.token) {
await this.login();
return;
}
const base64Url = this.token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const payload = JSON.parse(Buffer.from(base64, 'base64').toString());
if (!payload.exp) {
await this.login();
}
const now = Math.floor(Date.now() / 1000);
const diff = payload.exp - now;
// refresh token 1 week before expiration
if (diff < 604800) {
await this.login();
}
} catch (error) {
this.handleError('Failed to refresh token', error);
}
}
public async test(): Promise<void> {
try {
await this.login();
} catch (error) {
this.handleError('Login failed', error);
throw error;
}
}
async login(): Promise<TvdbLoginResponse> {
let body: { apiKey: string; pin?: string } = {
apiKey: 'd00d9ecb-a9d0-4860-958a-74b14a041405',
};
if (this.pin) {
body = {
...body,
pin: this.pin,
};
}
const response = await this.post<TvdbBaseResponse<TvdbLoginResponse>>(
'/login',
{
...body,
}
);
this.token = response.data.token;
return response.data;
}
public async getShowByTvdbId({
tvdbId,
language,
}: {
tvdbId: number;
language?: string;
}): Promise<TmdbTvDetails> {
try {
const tmdbTvShow = await this.tmdb.getShowByTvdbId({
tvdbId: tvdbId,
language,
});
try {
await this.refreshToken();
const validTvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (this.isValidTvdbId(validTvdbId)) {
return this.enrichTmdbShowWithTvdbData(tmdbTvShow, validTvdbId);
}
return tmdbTvShow;
} catch (error) {
return tmdbTvShow;
}
} catch (error) {
this.handleError('Failed to fetch TV show details', error);
throw error;
}
}
public async getTvShow({
tvId,
language,
}: {
tvId: number;
language?: string;
}): Promise<TmdbTvDetails> {
try {
const tmdbTvShow = await this.tmdb.getTvShow({ tvId, language });
try {
await this.refreshToken();
const tvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (this.isValidTvdbId(tvdbId)) {
return await this.enrichTmdbShowWithTvdbData(tmdbTvShow, tvdbId);
}
return tmdbTvShow;
} catch (error) {
this.handleError('Failed to fetch TV show details', error);
return tmdbTvShow;
}
} catch (error) {
this.handleError('Failed to fetch TV show details', error);
return this.tmdb.getTvShow({ tvId, language });
}
}
public async getTvSeason({
tvId,
seasonNumber,
language = Tvdb.DEFAULT_LANGUAGE,
}: {
tvId: number;
seasonNumber: number;
language?: string;
}): Promise<TmdbSeasonWithEpisodes> {
if (seasonNumber === 0) {
return this.createEmptySeasonResponse(tvId);
}
try {
const tmdbTvShow = await this.tmdb.getTvShow({ tvId, language });
try {
await this.refreshToken();
const tvdbId = this.getTvdbIdFromTmdb(tmdbTvShow);
if (!this.isValidTvdbId(tvdbId)) {
return await this.tmdb.getTvSeason({ tvId, seasonNumber, language });
}
return await this.getTvdbSeasonData(tvdbId, seasonNumber, tvId);
} catch (error) {
this.handleError('Failed to fetch TV season details', error);
return await this.tmdb.getTvSeason({ tvId, seasonNumber, language });
}
} catch (error) {
logger.error(
`[TVDB] Failed to fetch TV season details: ${error.message}`
);
throw error;
}
}
private async enrichTmdbShowWithTvdbData(
tmdbTvShow: TmdbTvDetails,
tvdbId: ValidTvdbId
): Promise<TmdbTvDetails> {
try {
await this.refreshToken();
const tvdbData = await this.fetchTvdbShowData(tvdbId);
const seasons = this.processSeasons(tvdbData);
if (!seasons.length) {
return tmdbTvShow;
}
return { ...tmdbTvShow, seasons };
} catch (error) {
logger.error(
`Failed to enrich TMDB show with TVDB data: ${error.message} token: ${this.token}`
);
return tmdbTvShow;
}
}
private async fetchTvdbShowData(tvdbId: number): Promise<TvdbTvDetails> {
const resp = await this.get<TvdbBaseResponse<TvdbTvDetails>>(
`/series/${tvdbId}/extended?meta=episodes&short=true`,
{
headers: {
Authorization: `Bearer ${this.token}`,
},
},
Tvdb.DEFAULT_CACHE_TTL
);
return resp.data;
}
private processSeasons(tvdbData: TvdbTvDetails): TmdbTvSeasonResult[] {
if (!tvdbData || !tvdbData.seasons || !tvdbData.episodes) {
return [];
}
const seasons = tvdbData.seasons
.filter(
(season) =>
season.number > 0 && season.type && season.type.type === 'official'
)
.sort((a, b) => a.number - b.number)
.map((season) => this.createSeasonData(season, tvdbData));
return seasons;
}
private createSeasonData(
season: TvdbSeasonDetails,
tvdbData: TvdbTvDetails
): TmdbTvSeasonResult {
if (!season.number) {
return {
id: 0,
episode_count: 0,
name: '',
overview: '',
season_number: 0,
poster_path: '',
air_date: '',
};
}
const episodeCount = tvdbData.episodes.filter(
(episode) => episode.seasonNumber === season.number
).length;
return {
id: tvdbData.id,
episode_count: episodeCount,
name: `${season.number}`,
overview: '',
season_number: season.number,
poster_path: '',
air_date: '',
};
}
private async getTvdbSeasonData(
tvdbId: number,
seasonNumber: number,
tvId: number
//language: string = Tvdb.DEFAULT_LANGUAGE
): Promise<TmdbSeasonWithEpisodes> {
const tvdbData = await this.fetchTvdbShowData(tvdbId);
if (!tvdbData) {
logger.error(`Failed to fetch TVDB data for ID: ${tvdbId}`);
return this.createEmptySeasonResponse(tvId);
}
// get season id
const season = tvdbData.seasons.find(
(season) =>
season.number === seasonNumber &&
season.type.type &&
season.type.type === 'official'
);
if (!season) {
logger.error(
`Failed to find season ${seasonNumber} for TVDB ID: ${tvdbId}`
);
return this.createEmptySeasonResponse(tvId);
}
const resp = await this.get<TvdbBaseResponse<TvdbSeasonDetails>>(
`/seasons/${season.id}/extended`,
{
headers: {
Authorization: `Bearer ${this.token}`,
},
}
);
const seasons = resp.data;
const episodes = this.processEpisodes(seasons, seasonNumber, tvId);
return {
episodes,
external_ids: { tvdb_id: tvdbId },
name: '',
overview: '',
id: seasons.id,
air_date: seasons.firstAired,
season_number: episodes.length,
};
}
private processEpisodes(
tvdbSeason: TvdbSeasonDetails,
seasonNumber: number,
tvId: number
): TmdbTvEpisodeResult[] {
if (!tvdbSeason || !tvdbSeason.episodes) {
logger.error('No episodes found in TVDB season data');
return [];
}
return tvdbSeason.episodes
.filter((episode) => episode.seasonNumber === seasonNumber)
.map((episode, index) => this.createEpisodeData(episode, index, tvId));
}
private createEpisodeData(
episode: TvdbEpisode,
index: number,
tvId: number
): TmdbTvEpisodeResult {
return {
id: episode.id,
air_date: episode.aired,
episode_number: episode.number,
name: episode.name || `Episode ${index + 1}`,
overview: episode.overview || '',
season_number: episode.seasonNumber,
production_code: '',
show_id: tvId,
still_path: episode.image ? episode.image : '',
vote_average: 1,
vote_count: 1,
};
}
private createEmptySeasonResponse(tvId: number): TmdbSeasonWithEpisodes {
return {
episodes: [],
external_ids: { tvdb_id: tvId },
name: '',
overview: '',
id: 0,
air_date: '',
season_number: 0,
};
}
private getTvdbIdFromTmdb(tmdbTvShow: TmdbTvDetails): TvdbId {
return tmdbTvShow?.external_ids?.tvdb_id ?? TvdbIdStatus.INVALID;
}
private isValidTvdbId(tvdbId: TvdbId): tvdbId is ValidTvdbId {
return tvdbId !== TvdbIdStatus.INVALID;
}
private handleError(context: string, error: Error): void {
throw new Error(`[TVDB] ${context}: ${error.message}`);
}
}
export default Tvdb;

View File

@@ -0,0 +1,144 @@
export interface TvdbBaseResponse<T> {
data: T;
errors: string;
}
export interface TvdbLoginResponse {
token: string;
}
interface TvDetailsAliases {
language: string;
name: string;
}
interface TvDetailsStatus {
id: number;
name: string;
recordType: string;
keepUpdated: boolean;
}
export interface TvdbTvDetails {
id: number;
name: string;
slug: string;
image: string;
nameTranslations: string[];
overwiewTranslations: string[];
aliases: TvDetailsAliases[];
firstAired: Date;
lastAired: Date;
nextAired: Date | string;
score: number;
status: TvDetailsStatus;
originalCountry: string;
originalLanguage: string;
defaultSeasonType: string;
isOrderRandomized: boolean;
lastUpdated: Date;
averageRuntime: number;
seasons: TvdbSeasonDetails[];
episodes: TvdbEpisode[];
}
interface TvdbCompanyType {
companyTypeId: number;
companyTypeName: string;
}
interface TvdbParentCompany {
id?: number;
name?: string;
relation?: {
id?: number;
typeName?: string;
};
}
interface TvdbCompany {
id: number;
name: string;
slug: string;
nameTranslations?: string[];
overviewTranslations?: string[];
aliases?: string[];
country: string;
primaryCompanyType: number;
activeDate: string;
inactiveDate?: string;
companyType: TvdbCompanyType;
parentCompany: TvdbParentCompany;
tagOptions?: string[];
}
interface TvdbType {
id: number;
name: string;
type: string;
alternateName?: string;
}
interface TvdbArtwork {
id: number;
image: string;
thumbnail: string;
language: string;
type: number;
score: number;
width: number;
height: number;
includesText: boolean;
}
export interface TvdbEpisode {
id: number;
seriesId: number;
name: string;
aired: string;
runtime: number;
nameTranslations: string[];
overview?: string;
overviewTranslations: string[];
image: string;
imageType: number;
isMovie: number;
seasons?: string[];
number: number;
absoluteNumber: number;
seasonNumber: number;
lastUpdated: string;
finaleType?: string;
year: string;
}
export interface TvdbSeasonDetails {
id: number;
seriesId: number;
type: TvdbType;
number: number;
nameTranslations: string[];
overviewTranslations: string[];
image: string;
imageType: number;
companies: {
studio: TvdbCompany[];
network: TvdbCompany[];
production: TvdbCompany[];
distributor: TvdbCompany[];
special_effects: TvdbCompany[];
};
lastUpdated: string;
year: string;
episodes: TvdbEpisode[];
trailers: string[];
artwork: TvdbArtwork[];
tagOptions?: string[];
firstAired: string;
}
export interface TvdbEpisodeTranslation {
name: string;
overview: string;
language: string;
}

View File

@@ -4,7 +4,9 @@ export enum ApiErrorCode {
InvalidAuthToken = 'INVALID_AUTH_TOKEN',
InvalidEmail = 'INVALID_EMAIL',
NotAdmin = 'NOT_ADMIN',
NoAdminUser = 'NO_ADMIN_USER',
SyncErrorGroupedFolders = 'SYNC_ERROR_GROUPED_FOLDERS',
SyncErrorNoLibraries = 'SYNC_ERROR_NO_LIBRARIES',
Unauthorized = 'UNAUTHORIZED',
Unknown = 'UNKNOWN',
}

View File

@@ -3,6 +3,7 @@ export enum MediaRequestStatus {
APPROVED,
DECLINED,
FAILED,
COMPLETED,
}
export enum MediaType {
@@ -17,4 +18,5 @@ export enum MediaStatus {
PARTIALLY_AVAILABLE,
AVAILABLE,
BLACKLISTED,
DELETED,
}

View File

@@ -68,8 +68,10 @@ const prodConfig: DataSourceOptions = {
const postgresDevConfig: DataSourceOptions = {
type: 'postgres',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT ?? '5432'),
host: process.env.DB_SOCKET_PATH || process.env.DB_HOST,
port: process.env.DB_SOCKET_PATH
? undefined
: parseInt(process.env.DB_PORT ?? '5432'),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME ?? 'jellyseerr',
@@ -84,8 +86,10 @@ const postgresDevConfig: DataSourceOptions = {
const postgresProdConfig: DataSourceOptions = {
type: 'postgres',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT ?? '5432'),
host: process.env.DB_SOCKET_PATH || process.env.DB_HOST,
port: process.env.DB_SOCKET_PATH
? undefined
: parseInt(process.env.DB_PORT ?? '5432'),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME ?? 'jellyseerr',

View File

@@ -1,11 +1,12 @@
import { MediaStatus, type MediaType } from '@server/constants/media';
import { getRepository } from '@server/datasource';
import dataSource from '@server/datasource';
import Media from '@server/entity/Media';
import { User } from '@server/entity/User';
import type { BlacklistItem } from '@server/interfaces/api/blacklistInterfaces';
import { DbAwareColumn } from '@server/utils/DbColumnHelper';
import type { EntityManager } from 'typeorm';
import {
Column,
CreateDateColumn,
Entity,
Index,
JoinColumn,
@@ -35,7 +36,7 @@ export class Blacklist implements BlacklistItem {
@ManyToOne(() => User, (user) => user.id, {
eager: true,
})
user: User;
user?: User;
@OneToOne(() => Media, (media) => media.blacklist, {
onDelete: 'CASCADE',
@@ -43,34 +44,42 @@ export class Blacklist implements BlacklistItem {
@JoinColumn()
public media: Media;
@CreateDateColumn()
@Column({ nullable: true, type: 'varchar' })
public blacklistedTags?: string;
@DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
public createdAt: Date;
constructor(init?: Partial<Blacklist>) {
Object.assign(this, init);
}
public static async addToBlacklist({
blacklistRequest,
}: {
blacklistRequest: {
mediaType: MediaType;
title?: ZodOptional<ZodString>['_output'];
tmdbId: ZodNumber['_output'];
};
}): Promise<void> {
public static async addToBlacklist(
{
blacklistRequest,
}: {
blacklistRequest: {
mediaType: MediaType;
title?: ZodOptional<ZodString>['_output'];
tmdbId: ZodNumber['_output'];
blacklistedTags?: string;
};
},
entityManager?: EntityManager
): Promise<void> {
const em = entityManager ?? dataSource;
const blacklist = new this({
...blacklistRequest,
});
const mediaRepository = getRepository(Media);
const mediaRepository = em.getRepository(Media);
let media = await mediaRepository.findOne({
where: {
tmdbId: blacklistRequest.tmdbId,
},
});
const blacklistRepository = getRepository(this);
const blacklistRepository = em.getRepository(this);
await blacklistRepository.save(blacklist);

View File

@@ -2,13 +2,8 @@ import type { DiscoverSliderType } from '@server/constants/discover';
import { defaultSliders } from '@server/constants/discover';
import { getRepository } from '@server/datasource';
import logger from '@server/logger';
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { DbAwareColumn } from '@server/utils/DbColumnHelper';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
class DiscoverSlider {
@@ -55,10 +50,14 @@ class DiscoverSlider {
@Column({ nullable: true })
public data?: string;
@CreateDateColumn()
@DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
public createdAt: Date;
@UpdateDateColumn()
@DbAwareColumn({
type: 'datetime',
default: () => 'CURRENT_TIMESTAMP',
onUpdate: 'CURRENT_TIMESTAMP',
})
public updatedAt: Date;
constructor(init?: Partial<DiscoverSlider>) {

View File

@@ -1,13 +1,13 @@
import type { IssueType } from '@server/constants/issue';
import { IssueStatus } from '@server/constants/issue';
import { DbAwareColumn } from '@server/utils/DbColumnHelper';
import {
AfterLoad,
Column,
CreateDateColumn,
Entity,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import IssueComment from './IssueComment';
import Media from './Media';
@@ -55,12 +55,21 @@ class Issue {
})
public comments: IssueComment[];
@CreateDateColumn()
@DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
public createdAt: Date;
@UpdateDateColumn()
@DbAwareColumn({
type: 'datetime',
default: () => 'CURRENT_TIMESTAMP',
onUpdate: 'CURRENT_TIMESTAMP',
})
public updatedAt: Date;
@AfterLoad()
sortComments() {
this.comments?.sort((a, b) => a.id - b.id);
}
constructor(init?: Partial<Issue>) {
Object.assign(this, init);
}

View File

@@ -1,11 +1,5 @@
import {
Column,
CreateDateColumn,
Entity,
ManyToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { DbAwareColumn } from '@server/utils/DbColumnHelper';
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import Issue from './Issue';
import { User } from './User';
@@ -28,10 +22,14 @@ class IssueComment {
@Column({ type: 'text' })
public message: string;
@CreateDateColumn()
@DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
public createdAt: Date;
@UpdateDateColumn()
@DbAwareColumn({
type: 'datetime',
default: () => 'CURRENT_TIMESTAMP',
onUpdate: 'CURRENT_TIMESTAMP',
})
public updatedAt: Date;
constructor(init?: Partial<IssueComment>) {

View File

@@ -15,13 +15,11 @@ import { getHostname } from '@server/utils/getHostname';
import {
AfterLoad,
Column,
CreateDateColumn,
Entity,
Index,
OneToMany,
OneToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import Issue from './Issue';
import { MediaRequest } from './MediaRequest';
@@ -108,7 +106,9 @@ class Media {
@Column({ type: 'int', default: MediaStatus.UNKNOWN })
public status4k: MediaStatus;
@OneToMany(() => MediaRequest, (request) => request.media, { cascade: true })
@OneToMany(() => MediaRequest, (request) => request.media, {
cascade: ['insert', 'remove'],
})
public requests: MediaRequest[];
@OneToMany(() => Watchlist, (watchlist) => watchlist.media)
@@ -126,10 +126,14 @@ class Media {
@OneToOne(() => Blacklist, (blacklist) => blacklist.media)
public blacklist: Promise<Blacklist>;
@CreateDateColumn()
@DbAwareColumn({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
public createdAt: Date;
@UpdateDateColumn()
@DbAwareColumn({
type: 'datetime',
default: () => 'CURRENT_TIMESTAMP',
onUpdate: 'CURRENT_TIMESTAMP',
})
public updatedAt: Date;
/**

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More