From b2878390b486e338151f26a2354711147012f88e Mon Sep 17 00:00:00 2001 From: Brandon Cohen Date: Mon, 25 Apr 2022 06:47:38 -0400 Subject: [PATCH 01/67] fix: manual browser refresh would redirect to home on search page (#2692) If you used the search feature and tried to manual refresh or share the link, it would reset the query. Taking you back to the home page. fix #2683 --- src/hooks/useSearchInput.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/useSearchInput.ts b/src/hooks/useSearchInput.ts index 8e879279..fd4d2088 100644 --- a/src/hooks/useSearchInput.ts +++ b/src/hooks/useSearchInput.ts @@ -1,9 +1,9 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import type { UrlObject } from 'url'; -import { useEffect, useState, Dispatch, SetStateAction } from 'react'; -import useDebouncedState from './useDebouncedState'; import { useRouter } from 'next/router'; +import { Dispatch, SetStateAction, useEffect, useState } from 'react'; +import type { UrlObject } from 'url'; import type { Nullable } from '../utils/typeHelpers'; +import useDebouncedState from './useDebouncedState'; type Url = string | UrlObject; @@ -48,7 +48,7 @@ const useSearchInput = (): SearchObject => { * in a new route. If we are, then we only replace the history. */ useEffect(() => { - if (debouncedValue !== '') { + if (debouncedValue !== '' && searchOpen) { if (router.pathname.startsWith('/search')) { router.replace({ pathname: router.pathname, From 1d00229a485bb2b376e9f63b52c70c7719f5f023 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Mon, 25 Apr 2022 09:09:22 -0400 Subject: [PATCH 02/67] feat(discover): add Paramount+ to network slider (#2608) --- src/components/Discover/NetworkSlider/index.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/Discover/NetworkSlider/index.tsx b/src/components/Discover/NetworkSlider/index.tsx index 44c776cf..61468a6f 100644 --- a/src/components/Discover/NetworkSlider/index.tsx +++ b/src/components/Discover/NetworkSlider/index.tsx @@ -110,6 +110,12 @@ const networks: Network[] = [ 'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/nm8d7P7MJNiBLdgIzUK0gkuEA4r.png', url: '/discover/tv/network/16', }, + { + name: 'Paramount+', + image: + 'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/fi83B1oztoS47xxcemFdPMhIzK.png', + url: '/discover/tv/network/4330', + }, { name: 'BBC One', image: From 475314c87bd0a79419702802a4d04787ef764f65 Mon Sep 17 00:00:00 2001 From: Gian Marco Cinalli Date: Mon, 25 Apr 2022 18:13:41 +0200 Subject: [PATCH 03/67] docs: update fail2ban documentation to handle logging changes (#2707) [skip ci] --- docs/extending-overseerr/fail2ban.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extending-overseerr/fail2ban.md b/docs/extending-overseerr/fail2ban.md index fbfe6fa8..1cf9131f 100644 --- a/docs/extending-overseerr/fail2ban.md +++ b/docs/extending-overseerr/fail2ban.md @@ -8,7 +8,7 @@ To use Fail2ban with Overseerr, create a new file named `overseerr.local` in you ``` [Definition] -failregex = .*\[info\]\[Auth\]\: Failed sign-in attempt.*"ip":"" +failregex = .*\[warn\]\[API\]\: Failed sign-in attempt.*"ip":"" ``` You can then add a jail using this filter in `jail.local`. Please see the [Fail2ban documetation](https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Jails) for details on how to configure the jail. From 29be6595125017700eccb34d33a0e852f23c97ba Mon Sep 17 00:00:00 2001 From: Danshil Kokil Mungur Date: Tue, 26 Apr 2022 02:53:33 +0400 Subject: [PATCH 04/67] fix(ui): don't show 0 playcount in slideover (#2714) --- src/components/ManageSlideOver/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ManageSlideOver/index.tsx b/src/components/ManageSlideOver/index.tsx index 8c6f2791..3e360d0a 100644 --- a/src/components/ManageSlideOver/index.tsx +++ b/src/components/ManageSlideOver/index.tsx @@ -210,7 +210,7 @@ const ManageSlideOver: React.FC< {hasPermission(Permission.ADMIN) && (data.mediaInfo?.serviceUrl || data.mediaInfo?.tautulliUrl || - watchData?.data?.playCount) && ( + !!watchData?.data?.playCount) && (

{intl.formatMessage(messages.manageModalMedia)} @@ -325,7 +325,7 @@ const ManageSlideOver: React.FC< {hasPermission(Permission.ADMIN) && (data.mediaInfo?.serviceUrl4k || data.mediaInfo?.tautulliUrl4k || - watchData?.data4k?.playCount) && ( + !!watchData?.data4k?.playCount) && (

{intl.formatMessage(messages.manageModalMedia4k)} From e4039d09c0380d80f03c7a00b51a150f88c02cca Mon Sep 17 00:00:00 2001 From: Danshil Kokil Mungur Date: Tue, 26 Apr 2022 03:06:36 +0400 Subject: [PATCH 05/67] feat(api): add issue counts endpoint (#2713) --- overseerr-api.yml | 30 ++++++++++++++++++++ server/routes/issue.ts | 64 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/overseerr-api.yml b/overseerr-api.yml index 77282ea1..be9ee0c0 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -5562,6 +5562,36 @@ paths: application/json: schema: $ref: '#/components/schemas/Issue' + + /issue/count: + get: + summary: Gets issue counts + description: | + Returns the number of open and closed issues, as well as the number of issues of each type. + tags: + - issue + responses: + '200': + description: Issue counts returned + content: + application/json: + schema: + type: object + properties: + total: + type: number + video: + type: number + audio: + type: number + subtitles: + type: number + others: + type: number + open: + type: number + closed: + type: number /issue/{issueId}: get: summary: Get issue diff --git a/server/routes/issue.ts b/server/routes/issue.ts index c7db5232..07cf3277 100644 --- a/server/routes/issue.ts +++ b/server/routes/issue.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; import { getRepository } from 'typeorm'; -import { IssueStatus } from '../constants/issue'; +import { IssueStatus, IssueType } from '../constants/issue'; import Issue from '../entity/Issue'; import IssueComment from '../entity/IssueComment'; import Media from '../entity/Media'; @@ -146,6 +146,68 @@ issueRoutes.post< } ); +issueRoutes.get('/count', async (req, res, next) => { + const issueRepository = getRepository(Issue); + + try { + const query = issueRepository.createQueryBuilder('issue'); + + const totalCount = await query.getCount(); + + const videoCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.VIDEO, + }) + .getCount(); + + const audioCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.AUDIO, + }) + .getCount(); + + const subtitlesCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.SUBTITLES, + }) + .getCount(); + + const othersCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.OTHER, + }) + .getCount(); + + const openCount = await query + .where('issue.status = :issueStatus', { + issueStatus: IssueStatus.OPEN, + }) + .getCount(); + + const closedCount = await query + .where('issue.status = :issueStatus', { + issueStatus: IssueStatus.RESOLVED, + }) + .getCount(); + + return res.status(200).json({ + total: totalCount, + video: videoCount, + audio: audioCount, + subtitles: subtitlesCount, + others: othersCount, + open: openCount, + closed: closedCount, + }); + } catch (e) { + logger.debug('Something went wrong retrieving issue counts.', { + label: 'API', + errorMessage: e.message, + }); + next({ status: 500, message: 'Unable to retrieve issue counts.' }); + } +}); + issueRoutes.get<{ issueId: string }>( '/:issueId', isAuthenticated( From 1054b4e2d7262d841fa83cde624f1138ad7bd23a Mon Sep 17 00:00:00 2001 From: Danshil Kokil Mungur Date: Sat, 30 Apr 2022 18:31:02 +0400 Subject: [PATCH 06/67] fix(search): use correct param to filter movies by year (#2727) --- server/api/themoviedb/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/api/themoviedb/index.ts b/server/api/themoviedb/index.ts index cf5e280c..b5060c03 100644 --- a/server/api/themoviedb/index.ts +++ b/server/api/themoviedb/index.ts @@ -129,7 +129,13 @@ class TheMovieDb extends ExternalAPI { }: SingleSearchOptions): Promise => { try { const data = await this.get('/search/movie', { - params: { query, page, include_adult: includeAdult, language, year }, + params: { + query, + page, + include_adult: includeAdult, + language, + primary_release_year: year, + }, }); return data; From 14519ef5559038b0d9d037a2bdc5d98e63c9db6f Mon Sep 17 00:00:00 2001 From: Brandon Cohen Date: Fri, 13 May 2022 15:15:53 -0400 Subject: [PATCH 07/67] fix(recommendations): only load more titles if there can be more than 40 (#2749) * fix: fixed recommendations page causing infinite network requests to tmdb api TMDB API would only return 40 results and the recommendations page expected more. This would cause an infinite amount of network requests. I set a limit specifically for this solving the problem. fix #2710 --- src/hooks/useDiscover.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hooks/useDiscover.ts b/src/hooks/useDiscover.ts index 24ba47c1..3bc016eb 100644 --- a/src/hooks/useDiscover.ts +++ b/src/hooks/useDiscover.ts @@ -82,7 +82,9 @@ const useDiscover = >( const isEmpty = !isLoadingInitialData && titles?.length === 0; const isReachingEnd = - isEmpty || (!!data && (data[data?.length - 1]?.results.length ?? 0) < 20); + isEmpty || + (!!data && (data[data?.length - 1]?.results.length ?? 0) < 20) || + (!!data && (data[data?.length - 1]?.totalResults ?? 0) < 41); return { isLoadingInitialData, From 9ded45fef80b4a7e0be237fbe0301629f862fff9 Mon Sep 17 00:00:00 2001 From: Brandon Cohen Date: Mon, 25 Apr 2022 06:47:38 -0400 Subject: [PATCH 08/67] fix: manual browser refresh would redirect to home on search page If you used the search feature and tried to manual refresh or share the link, it would reset the query. Taking you back to the home page. --- src/hooks/useSearchInput.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/useSearchInput.ts b/src/hooks/useSearchInput.ts index 8e879279..fd4d2088 100644 --- a/src/hooks/useSearchInput.ts +++ b/src/hooks/useSearchInput.ts @@ -1,9 +1,9 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import type { UrlObject } from 'url'; -import { useEffect, useState, Dispatch, SetStateAction } from 'react'; -import useDebouncedState from './useDebouncedState'; import { useRouter } from 'next/router'; +import { Dispatch, SetStateAction, useEffect, useState } from 'react'; +import type { UrlObject } from 'url'; import type { Nullable } from '../utils/typeHelpers'; +import useDebouncedState from './useDebouncedState'; type Url = string | UrlObject; @@ -48,7 +48,7 @@ const useSearchInput = (): SearchObject => { * in a new route. If we are, then we only replace the history. */ useEffect(() => { - if (debouncedValue !== '') { + if (debouncedValue !== '' && searchOpen) { if (router.pathname.startsWith('/search')) { router.replace({ pathname: router.pathname, From d22bc09652e5d4e703fca6838d06e4908432fe06 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Mon, 25 Apr 2022 09:09:22 -0400 Subject: [PATCH 09/67] feat: add Paramount+ to network slider --- src/components/Discover/NetworkSlider/index.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/Discover/NetworkSlider/index.tsx b/src/components/Discover/NetworkSlider/index.tsx index 44c776cf..61468a6f 100644 --- a/src/components/Discover/NetworkSlider/index.tsx +++ b/src/components/Discover/NetworkSlider/index.tsx @@ -110,6 +110,12 @@ const networks: Network[] = [ 'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/nm8d7P7MJNiBLdgIzUK0gkuEA4r.png', url: '/discover/tv/network/16', }, + { + name: 'Paramount+', + image: + 'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/fi83B1oztoS47xxcemFdPMhIzK.png', + url: '/discover/tv/network/4330', + }, { name: 'BBC One', image: From e42153c59946c4c64bccdae56b951771d0b628f4 Mon Sep 17 00:00:00 2001 From: Gian Marco Cinalli Date: Mon, 25 Apr 2022 18:13:41 +0200 Subject: [PATCH 10/67] docs: update fail2ban documentation to handle logging changes --- docs/extending-overseerr/fail2ban.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extending-overseerr/fail2ban.md b/docs/extending-overseerr/fail2ban.md index fbfe6fa8..1cf9131f 100644 --- a/docs/extending-overseerr/fail2ban.md +++ b/docs/extending-overseerr/fail2ban.md @@ -8,7 +8,7 @@ To use Fail2ban with Overseerr, create a new file named `overseerr.local` in you ``` [Definition] -failregex = .*\[info\]\[Auth\]\: Failed sign-in attempt.*"ip":"" +failregex = .*\[warn\]\[API\]\: Failed sign-in attempt.*"ip":"" ``` You can then add a jail using this filter in `jail.local`. Please see the [Fail2ban documetation](https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Jails) for details on how to configure the jail. From dec4062cdcecbe297f72364ede6a000b863117f4 Mon Sep 17 00:00:00 2001 From: Danshil Kokil Mungur Date: Tue, 26 Apr 2022 02:53:33 +0400 Subject: [PATCH 11/67] fix: don't show 0 playcount in slideover --- src/components/ManageSlideOver/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ManageSlideOver/index.tsx b/src/components/ManageSlideOver/index.tsx index 8c6f2791..3e360d0a 100644 --- a/src/components/ManageSlideOver/index.tsx +++ b/src/components/ManageSlideOver/index.tsx @@ -210,7 +210,7 @@ const ManageSlideOver: React.FC< {hasPermission(Permission.ADMIN) && (data.mediaInfo?.serviceUrl || data.mediaInfo?.tautulliUrl || - watchData?.data?.playCount) && ( + !!watchData?.data?.playCount) && (

{intl.formatMessage(messages.manageModalMedia)} @@ -325,7 +325,7 @@ const ManageSlideOver: React.FC< {hasPermission(Permission.ADMIN) && (data.mediaInfo?.serviceUrl4k || data.mediaInfo?.tautulliUrl4k || - watchData?.data4k?.playCount) && ( + !!watchData?.data4k?.playCount) && (

{intl.formatMessage(messages.manageModalMedia4k)} From af23a257d5795b5c3930cd3884a84a2e2eeeb1dc Mon Sep 17 00:00:00 2001 From: Danshil Kokil Mungur Date: Tue, 26 Apr 2022 03:06:36 +0400 Subject: [PATCH 12/67] feat(api): add issue counts endpoint --- overseerr-api.yml | 30 ++++++++++++++++++++ server/routes/issue.ts | 64 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/overseerr-api.yml b/overseerr-api.yml index cd7034b0..551f7dd9 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -5815,6 +5815,36 @@ paths: application/json: schema: $ref: '#/components/schemas/Issue' + + /issue/count: + get: + summary: Gets issue counts + description: | + Returns the number of open and closed issues, as well as the number of issues of each type. + tags: + - issue + responses: + '200': + description: Issue counts returned + content: + application/json: + schema: + type: object + properties: + total: + type: number + video: + type: number + audio: + type: number + subtitles: + type: number + others: + type: number + open: + type: number + closed: + type: number /issue/{issueId}: get: summary: Get issue diff --git a/server/routes/issue.ts b/server/routes/issue.ts index c7db5232..07cf3277 100644 --- a/server/routes/issue.ts +++ b/server/routes/issue.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; import { getRepository } from 'typeorm'; -import { IssueStatus } from '../constants/issue'; +import { IssueStatus, IssueType } from '../constants/issue'; import Issue from '../entity/Issue'; import IssueComment from '../entity/IssueComment'; import Media from '../entity/Media'; @@ -146,6 +146,68 @@ issueRoutes.post< } ); +issueRoutes.get('/count', async (req, res, next) => { + const issueRepository = getRepository(Issue); + + try { + const query = issueRepository.createQueryBuilder('issue'); + + const totalCount = await query.getCount(); + + const videoCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.VIDEO, + }) + .getCount(); + + const audioCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.AUDIO, + }) + .getCount(); + + const subtitlesCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.SUBTITLES, + }) + .getCount(); + + const othersCount = await query + .where('issue.issueType = :issueType', { + issueType: IssueType.OTHER, + }) + .getCount(); + + const openCount = await query + .where('issue.status = :issueStatus', { + issueStatus: IssueStatus.OPEN, + }) + .getCount(); + + const closedCount = await query + .where('issue.status = :issueStatus', { + issueStatus: IssueStatus.RESOLVED, + }) + .getCount(); + + return res.status(200).json({ + total: totalCount, + video: videoCount, + audio: audioCount, + subtitles: subtitlesCount, + others: othersCount, + open: openCount, + closed: closedCount, + }); + } catch (e) { + logger.debug('Something went wrong retrieving issue counts.', { + label: 'API', + errorMessage: e.message, + }); + next({ status: 500, message: 'Unable to retrieve issue counts.' }); + } +}); + issueRoutes.get<{ issueId: string }>( '/:issueId', isAuthenticated( From b07f7032ad89ccb359f3a6a4f4508de6b59ec393 Mon Sep 17 00:00:00 2001 From: Danshil Kokil Mungur Date: Sat, 30 Apr 2022 18:31:02 +0400 Subject: [PATCH 13/67] fix(search): use correct param to filter movies by year --- server/api/themoviedb/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/api/themoviedb/index.ts b/server/api/themoviedb/index.ts index cf5e280c..b5060c03 100644 --- a/server/api/themoviedb/index.ts +++ b/server/api/themoviedb/index.ts @@ -129,7 +129,13 @@ class TheMovieDb extends ExternalAPI { }: SingleSearchOptions): Promise => { try { const data = await this.get('/search/movie', { - params: { query, page, include_adult: includeAdult, language, year }, + params: { + query, + page, + include_adult: includeAdult, + language, + primary_release_year: year, + }, }); return data; From 4f972be8584e48f544268aef9d1d05769ba2e38e Mon Sep 17 00:00:00 2001 From: Brandon Cohen Date: Fri, 13 May 2022 15:15:53 -0400 Subject: [PATCH 14/67] fix(recommendations): fixed recommendations page causing infinite network requests to tmdb api TMDB API would only return 40 results and the recommendations page expected more. This would cause an infinite amount of network requests. A limit was implemented to specifically to solve this problem --- src/hooks/useDiscover.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hooks/useDiscover.ts b/src/hooks/useDiscover.ts index 24ba47c1..3bc016eb 100644 --- a/src/hooks/useDiscover.ts +++ b/src/hooks/useDiscover.ts @@ -82,7 +82,9 @@ const useDiscover = >( const isEmpty = !isLoadingInitialData && titles?.length === 0; const isReachingEnd = - isEmpty || (!!data && (data[data?.length - 1]?.results.length ?? 0) < 20); + isEmpty || + (!!data && (data[data?.length - 1]?.results.length ?? 0) < 20) || + (!!data && (data[data?.length - 1]?.totalResults ?? 0) < 41); return { isLoadingInitialData, From 2bfdf02c7942762bd9f5201459b1a9ad6003b9a6 Mon Sep 17 00:00:00 2001 From: Mohamed jinas Date: Sun, 22 May 2022 22:12:05 +0500 Subject: [PATCH 15/67] feat: conditional media server name --- next.config.js | 1 + src/components/TvDetails/index.tsx | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/next.config.js b/next.config.js index f0a623d4..83a0c63c 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,7 @@ module.exports = { env: { commitTag: process.env.COMMIT_TAG || 'local', + JELLYFIN_TYPE: 'emby', }, images: { domains: ['image.tmdb.org'], diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index 7de7fff1..98bf45e3 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -124,10 +124,7 @@ const TvDetails: React.FC = ({ tv }) => { }) ) { mediaLinks.push({ - text: - settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN - ? intl.formatMessage(messages.play, { mediaServerName: 'Jellyfin' }) - : intl.formatMessage(messages.play, { mediaServerName: 'Plex' }), + text: getAvalaibleMediaServerName(), url: data.mediaInfo?.mediaUrl, svg: , }); @@ -228,6 +225,18 @@ const TvDetails: React.FC = ({ tv }) => { data?.watchProviders?.find((provider) => provider.iso_3166_1 === region) ?.flatrate ?? []; + function getAvalaibleMediaServerName() { + if (process.env.JELLYFIN_TYPE === 'emby') { + return intl.formatMessage(messages.play, { mediaServerName: 'Emby' }); + } + + if (settings.currentSettings.mediaServerType === MediaServerType.PLEX) { + return intl.formatMessage(messages.play, { mediaServerName: 'Plex' }); + } + + return intl.formatMessage(messages.play, { mediaServerName: 'Jellyfin' }); + } + return (
Date: Mon, 23 May 2022 04:49:35 +0400 Subject: [PATCH 16/67] feat(manage slideover): show more request override details (#2772) * feat(manage slideover): show the language profile if request is for a show * feat(manage slideover): show name of profiles instead of id --- src/components/RequestBlock/index.tsx | 18 +++++++--- src/hooks/useRequestOverride.ts | 50 ++++++++++++++++++--------- src/i18n/locale/en.json | 1 + 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/components/RequestBlock/index.tsx b/src/components/RequestBlock/index.tsx index 073ffaeb..d1d4ae8a 100644 --- a/src/components/RequestBlock/index.tsx +++ b/src/components/RequestBlock/index.tsx @@ -26,6 +26,7 @@ const messages = defineMessages({ server: 'Destination Server', profilechanged: 'Quality Profile', rootfolder: 'Root Folder', + languageprofile: 'Language Profile', }); interface RequestBlockProps { @@ -38,7 +39,8 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { const intl = useIntl(); const [isUpdating, setIsUpdating] = useState(false); const [showEditModal, setShowEditModal] = useState(false); - const { profile, rootFolder, server } = useRequestOverride(request); + const { profile, rootFolder, server, languageProfile } = + useRequestOverride(request); const updateRequest = async (type: 'approve' | 'decline'): Promise => { setIsUpdating(true); @@ -209,7 +211,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => {

)} - {(server || profile !== null || rootFolder) && ( + {(server || profile || rootFolder || languageProfile) && ( <>
{intl.formatMessage(messages.requestoverrides)} @@ -223,12 +225,12 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { {server} )} - {profile !== null && ( + {profile && (
  • {intl.formatMessage(messages.profilechanged)} - ID {profile} + {profile}
  • )} {rootFolder && ( @@ -239,6 +241,14 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { {rootFolder} )} + {languageProfile && ( +
  • + + {intl.formatMessage(messages.languageprofile)} + + {languageProfile} +
  • + )} )} diff --git a/src/hooks/useRequestOverride.ts b/src/hooks/useRequestOverride.ts index ba791f99..be992e8b 100644 --- a/src/hooks/useRequestOverride.ts +++ b/src/hooks/useRequestOverride.ts @@ -1,45 +1,61 @@ import useSWR from 'swr'; import { MediaRequest } from '../../server/entity/MediaRequest'; -import { ServiceCommonServer } from '../../server/interfaces/api/serviceInterfaces'; +import { + ServiceCommonServer, + ServiceCommonServerWithDetails, +} from '../../server/interfaces/api/serviceInterfaces'; interface OverrideStatus { - server: string | null; - profile: number | null; - rootFolder: string | null; + server?: string; + profile?: string; + rootFolder?: string; + languageProfile?: string; } const useRequestOverride = (request: MediaRequest): OverrideStatus => { - const { data } = useSWR( + const { data: allServers } = useSWR( `/api/v1/service/${request.type === 'movie' ? 'radarr' : 'sonarr'}` ); - if (!data) { - return { - server: null, - profile: null, - rootFolder: null, - }; + const { data } = useSWR( + `/api/v1/service/${request.type === 'movie' ? 'radarr' : 'sonarr'}/${ + request.serverId + }` + ); + + if (!data || !allServers) { + return {}; } - const defaultServer = data.find( + const defaultServer = allServers.find( (server) => server.is4k === request.is4k && server.isDefault ); - const activeServer = data.find((server) => server.id === request.serverId); + const activeServer = allServers.find( + (server) => server.id === request.serverId + ); return { server: activeServer && request.serverId !== defaultServer?.id ? activeServer.name - : null, + : undefined, profile: defaultServer?.activeProfileId !== request.profileId - ? request.profileId - : null, + ? data.profiles.find((profile) => profile.id === request.profileId) + ?.name + : undefined, rootFolder: defaultServer?.activeDirectory !== request.rootFolder ? request.rootFolder - : null, + : undefined, + languageProfile: + request.type === 'tv' && + defaultServer?.activeLanguageProfileId !== request.languageProfileId + ? data.languageProfiles?.find( + (profile) => profile.id === request.languageProfileId + )?.name + : undefined, }; }; diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 6bcb3932..84b77f79 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -269,6 +269,7 @@ "components.QuotaSelector.unlimited": "Unlimited", "components.RegionSelector.regionDefault": "All Regions", "components.RegionSelector.regionServerDefault": "Default ({region})", + "components.RequestBlock.languageprofile": "Language Profile", "components.RequestBlock.profilechanged": "Quality Profile", "components.RequestBlock.requestoverrides": "Request Overrides", "components.RequestBlock.rootfolder": "Root Folder", From 1570a8715aa7db73f9a5372ea52eeb1ee501aaeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Bart=C3=ADk?= <63553146+sambartik@users.noreply.github.com> Date: Mon, 23 May 2022 15:36:00 +0200 Subject: [PATCH 17/67] Fix non-square profile pictures being squished --- src/components/IssueList/IssueItem/index.tsx | 1 + src/components/Layout/UserDropdown/index.tsx | 1 + src/components/RequestCard/index.tsx | 1 + src/components/RequestList/RequestItem/index.tsx | 2 ++ 4 files changed, 5 insertions(+) diff --git a/src/components/IssueList/IssueItem/index.tsx b/src/components/IssueList/IssueItem/index.tsx index 1695215a..b8a351ad 100644 --- a/src/components/IssueList/IssueItem/index.tsx +++ b/src/components/IssueList/IssueItem/index.tsx @@ -229,6 +229,7 @@ const IssueItem: React.FC = ({ issue }) => { src={issue.createdBy.avatar} alt="" className="avatar-sm ml-1.5" + style={{ objectFit: 'cover' }} /> {issue.createdBy.displayName} diff --git a/src/components/Layout/UserDropdown/index.tsx b/src/components/Layout/UserDropdown/index.tsx index a9923117..5637738e 100644 --- a/src/components/Layout/UserDropdown/index.tsx +++ b/src/components/Layout/UserDropdown/index.tsx @@ -41,6 +41,7 @@ const UserDropdown: React.FC = () => { > diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx index cc52f155..cbe301b8 100644 --- a/src/components/RequestCard/index.tsx +++ b/src/components/RequestCard/index.tsx @@ -232,6 +232,7 @@ const RequestCard: React.FC = ({ request, onTitleData }) => { src={requestData.requestedBy.avatar} alt="" className="avatar-sm" + style={{ objectFit: 'cover' }} /> {requestData.requestedBy.displayName} diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index b3c18e8f..889f0071 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -337,6 +337,7 @@ const RequestItem: React.FC = ({ src={requestData.requestedBy.avatar} alt="" className="avatar-sm ml-1.5" + style={{ objectFit: 'cover' }} /> {requestData.requestedBy.displayName} @@ -391,6 +392,7 @@ const RequestItem: React.FC = ({ src={requestData.modifiedBy.avatar} alt="" className="avatar-sm ml-1.5" + style={{ objectFit: 'cover' }} /> {requestData.modifiedBy.displayName} From e9fa94097a5ade24e47d90e9853194ae98ad9c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Bart=C3=ADk?= <63553146+sambartik@users.noreply.github.com> Date: Tue, 24 May 2022 19:50:37 +0200 Subject: [PATCH 18/67] Revert "Fix non-square profile pictures being squished" --- src/components/IssueList/IssueItem/index.tsx | 1 - src/components/Layout/UserDropdown/index.tsx | 1 - src/components/RequestCard/index.tsx | 1 - src/components/RequestList/RequestItem/index.tsx | 2 -- 4 files changed, 5 deletions(-) diff --git a/src/components/IssueList/IssueItem/index.tsx b/src/components/IssueList/IssueItem/index.tsx index b8a351ad..1695215a 100644 --- a/src/components/IssueList/IssueItem/index.tsx +++ b/src/components/IssueList/IssueItem/index.tsx @@ -229,7 +229,6 @@ const IssueItem: React.FC = ({ issue }) => { src={issue.createdBy.avatar} alt="" className="avatar-sm ml-1.5" - style={{ objectFit: 'cover' }} /> {issue.createdBy.displayName} diff --git a/src/components/Layout/UserDropdown/index.tsx b/src/components/Layout/UserDropdown/index.tsx index 5637738e..a9923117 100644 --- a/src/components/Layout/UserDropdown/index.tsx +++ b/src/components/Layout/UserDropdown/index.tsx @@ -41,7 +41,6 @@ const UserDropdown: React.FC = () => { > diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx index cbe301b8..cc52f155 100644 --- a/src/components/RequestCard/index.tsx +++ b/src/components/RequestCard/index.tsx @@ -232,7 +232,6 @@ const RequestCard: React.FC = ({ request, onTitleData }) => { src={requestData.requestedBy.avatar} alt="" className="avatar-sm" - style={{ objectFit: 'cover' }} /> {requestData.requestedBy.displayName} diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index 889f0071..b3c18e8f 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -337,7 +337,6 @@ const RequestItem: React.FC = ({ src={requestData.requestedBy.avatar} alt="" className="avatar-sm ml-1.5" - style={{ objectFit: 'cover' }} /> {requestData.requestedBy.displayName} @@ -392,7 +391,6 @@ const RequestItem: React.FC = ({ src={requestData.modifiedBy.avatar} alt="" className="avatar-sm ml-1.5" - style={{ objectFit: 'cover' }} /> {requestData.modifiedBy.displayName} From db05172d8b924a591ece4fae72d076eb59ee5f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Bart=C3=ADk?= <63553146+sambartik@users.noreply.github.com> Date: Wed, 25 May 2022 18:42:17 +0200 Subject: [PATCH 19/67] fix(ui): rectangular avatars getting stretched (#2782) --- src/components/IssueDetails/IssueComment/index.tsx | 2 +- src/components/IssueDetails/index.tsx | 2 +- src/components/IssueList/IssueItem/index.tsx | 2 +- src/components/Layout/UserDropdown/index.tsx | 2 +- src/components/ManageSlideOver/index.tsx | 4 ++-- src/components/RequestCard/index.tsx | 2 +- src/components/RequestList/RequestItem/index.tsx | 4 ++-- src/components/RequestModal/AdvancedRequester/index.tsx | 4 ++-- src/components/UserList/index.tsx | 2 +- src/components/UserProfile/ProfileHeader/index.tsx | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/IssueDetails/IssueComment/index.tsx b/src/components/IssueDetails/IssueComment/index.tsx index 99b26a44..11623f53 100644 --- a/src/components/IssueDetails/IssueComment/index.tsx +++ b/src/components/IssueDetails/IssueComment/index.tsx @@ -90,7 +90,7 @@ const IssueComment: React.FC = ({ diff --git a/src/components/IssueDetails/index.tsx b/src/components/IssueDetails/index.tsx index 8939f61d..c8cd841b 100644 --- a/src/components/IssueDetails/index.tsx +++ b/src/components/IssueDetails/index.tsx @@ -264,7 +264,7 @@ const IssueDetails: React.FC = () => { > diff --git a/src/components/IssueList/IssueItem/index.tsx b/src/components/IssueList/IssueItem/index.tsx index 1695215a..e5cd058a 100644 --- a/src/components/IssueList/IssueItem/index.tsx +++ b/src/components/IssueList/IssueItem/index.tsx @@ -228,7 +228,7 @@ const IssueItem: React.FC = ({ issue }) => { {issue.createdBy.displayName} diff --git a/src/components/Layout/UserDropdown/index.tsx b/src/components/Layout/UserDropdown/index.tsx index a9923117..e51fcabf 100644 --- a/src/components/Layout/UserDropdown/index.tsx +++ b/src/components/Layout/UserDropdown/index.tsx @@ -40,7 +40,7 @@ const UserDropdown: React.FC = () => { onClick={() => setDropdownOpen(true)} > diff --git a/src/components/ManageSlideOver/index.tsx b/src/components/ManageSlideOver/index.tsx index 3e360d0a..a1e9bab1 100644 --- a/src/components/ManageSlideOver/index.tsx +++ b/src/components/ManageSlideOver/index.tsx @@ -272,7 +272,7 @@ const ManageSlideOver: React.FC< {user.displayName} @@ -387,7 +387,7 @@ const ManageSlideOver: React.FC< {user.displayName} diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx index 38cf541f..c95bbf3b 100644 --- a/src/components/RequestCard/index.tsx +++ b/src/components/RequestCard/index.tsx @@ -231,7 +231,7 @@ const RequestCard: React.FC = ({ request, onTitleData }) => { {requestData.requestedBy.displayName} diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index 54a5a59c..27f66108 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -336,7 +336,7 @@ const RequestItem: React.FC = ({ {requestData.requestedBy.displayName} @@ -390,7 +390,7 @@ const RequestItem: React.FC = ({ {requestData.modifiedBy.displayName} diff --git a/src/components/RequestModal/AdvancedRequester/index.tsx b/src/components/RequestModal/AdvancedRequester/index.tsx index d4cead4a..58bbe777 100644 --- a/src/components/RequestModal/AdvancedRequester/index.tsx +++ b/src/components/RequestModal/AdvancedRequester/index.tsx @@ -534,7 +534,7 @@ const AdvancedRequester: React.FC = ({ {selectedUser.displayName} @@ -584,7 +584,7 @@ const AdvancedRequester: React.FC = ({ {user.displayName} diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx index d6243aa2..58c51d66 100644 --- a/src/components/UserList/index.tsx +++ b/src/components/UserList/index.tsx @@ -575,7 +575,7 @@ const UserList: React.FC = () => { diff --git a/src/components/UserProfile/ProfileHeader/index.tsx b/src/components/UserProfile/ProfileHeader/index.tsx index f677a008..3485c797 100644 --- a/src/components/UserProfile/ProfileHeader/index.tsx +++ b/src/components/UserProfile/ProfileHeader/index.tsx @@ -44,7 +44,7 @@ const ProfileHeader: React.FC = ({
    From 01e81a73a3ae3c4692d0b9b68dc27fe1a54b1a1d Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Thu, 26 May 2022 02:24:31 +0500 Subject: [PATCH 20/67] fix(ui): fix Avatar being broken when setup using internal ip allow avatar url to use externalHostname when setup using local ip fix #110 --- server/routes/auth.ts | 11 ++++++++--- server/routes/settings/index.ts | 7 ++++++- server/routes/user/index.ts | 7 ++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/server/routes/auth.ts b/server/routes/auth.ts index 1aacb69b..69d2fd52 100644 --- a/server/routes/auth.ts +++ b/server/routes/auth.ts @@ -213,6 +213,7 @@ authRoutes.post('/jellyfin', async (req, res, next) => { settings.jellyfin.hostname !== '' ? settings.jellyfin.hostname : body.hostname; + const { externalHostname } = getSettings().jellyfin; // Try to find deviceId that corresponds to jellyfin user, else generate a new one let user = await userRepository.findOne({ @@ -229,6 +230,10 @@ authRoutes.post('/jellyfin', async (req, res, next) => { } // First we need to attempt to log the user in to jellyfin const jellyfinserver = new JellyfinAPI(hostname ?? '', undefined, deviceId); + const jellyfinHost = + externalHostname && externalHostname.length > 0 + ? externalHostname + : hostname; const account = await jellyfinserver.login(body.username, body.password); // Next let's see if the user already exists @@ -244,7 +249,7 @@ authRoutes.post('/jellyfin', async (req, res, next) => { // Update the users avatar with their jellyfin profile pic (incase it changed) if (account.User.PrimaryImageTag) { - user.avatar = `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90`; + user.avatar = `${jellyfinHost}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90`; } else { user.avatar = '/os_logo_square.png'; } @@ -290,7 +295,7 @@ authRoutes.post('/jellyfin', async (req, res, next) => { jellyfinAuthToken: account.AccessToken, permissions: Permission.ADMIN, avatar: account.User.PrimaryImageTag - ? `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90` + ? `${jellyfinHost}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90` : '/os_logo_square.png', userType: UserType.JELLYFIN, }); @@ -319,7 +324,7 @@ authRoutes.post('/jellyfin', async (req, res, next) => { jellyfinAuthToken: account.AccessToken, permissions: settings.main.defaultPermissions, avatar: account.User.PrimaryImageTag - ? `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90` + ? `${jellyfinHost}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90` : '/os_logo_square.png', userType: UserType.JELLYFIN, }); diff --git a/server/routes/settings/index.ts b/server/routes/settings/index.ts index 8a5ef9a2..7ebff760 100644 --- a/server/routes/settings/index.ts +++ b/server/routes/settings/index.ts @@ -303,6 +303,11 @@ settingsRoutes.get('/jellyfin/library', async (req, res) => { settingsRoutes.get('/jellyfin/users', async (req, res) => { const settings = getSettings(); + const { hostname, externalHostname } = getSettings().jellyfin; + const jellyfinHost = + externalHostname && externalHostname.length > 0 + ? externalHostname + : hostname; const userRepository = getRepository(User); const admin = await userRepository.findOneOrFail({ @@ -321,7 +326,7 @@ settingsRoutes.get('/jellyfin/users', async (req, res) => { username: user.Name, id: user.Id, thumb: user.PrimaryImageTag - ? `${settings.jellyfin.hostname}/Users/${user.Id}/Images/Primary/?tag=${user.PrimaryImageTag}&quality=90` + ? `${jellyfinHost}/Users/${user.Id}/Images/Primary/?tag=${user.PrimaryImageTag}&quality=90` : '/os_logo_square.png', email: user.Name, })); diff --git a/server/routes/user/index.ts b/server/routes/user/index.ts index 308cb14a..a45391ac 100644 --- a/server/routes/user/index.ts +++ b/server/routes/user/index.ts @@ -494,6 +494,11 @@ router.post( const jellyfinUsersResponse = await jellyfinClient.getUsers(); const createdUsers: User[] = []; + const { hostname, externalHostname } = getSettings().jellyfin; + const jellyfinHost = + externalHostname && externalHostname.length > 0 + ? externalHostname + : hostname; for (const account of jellyfinUsersResponse.users) { if (account.Name) { const user = await userRepository @@ -505,7 +510,7 @@ router.post( .getOne(); const avatar = account.PrimaryImageTag - ? `${settings.jellyfin.hostname}/Users/${account.Id}/Images/Primary/?tag=${account.PrimaryImageTag}&quality=90` + ? `${jellyfinHost}/Users/${account.Id}/Images/Primary/?tag=${account.PrimaryImageTag}&quality=90` : '/os_logo_square.png'; if (user) { From ff3e3ce841f0676713242d0c8e3a977ef65530d8 Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Thu, 26 May 2022 05:49:33 +0500 Subject: [PATCH 21/67] feat: conditional media server name to add emby to tvdetails --- next.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/next.config.js b/next.config.js index 83a0c63c..f0a623d4 100644 --- a/next.config.js +++ b/next.config.js @@ -1,7 +1,6 @@ module.exports = { env: { commitTag: process.env.COMMIT_TAG || 'local', - JELLYFIN_TYPE: 'emby', }, images: { domains: ['image.tmdb.org'], From e75b71b8168b4a661971b809c88f9910c4206545 Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Thu, 26 May 2022 05:54:57 +0500 Subject: [PATCH 22/67] feat: conditional media server name to add emby to tvdetails --- src/components/TvDetails/index.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index 98bf45e3..fe9a039a 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -138,10 +138,7 @@ const TvDetails: React.FC = ({ tv }) => { }) ) { mediaLinks.push({ - text: - settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN - ? intl.formatMessage(messages.play4k, { mediaServerName: 'Jellyfin' }) - : intl.formatMessage(messages.play4k, { mediaServerName: 'Plex' }), + text: getAvalaibleMediaServerName(), url: data.mediaInfo?.mediaUrl4k, svg: , }); From ddd773c03ff61654490644dec21f406d03374b3d Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Thu, 26 May 2022 08:30:21 +0500 Subject: [PATCH 23/67] fix: conditional media server name for 4k url to add emby to tvdetails --- src/components/TvDetails/index.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index fe9a039a..0548e248 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -138,7 +138,7 @@ const TvDetails: React.FC = ({ tv }) => { }) ) { mediaLinks.push({ - text: getAvalaibleMediaServerName(), + text: getAvalaible4kMediaServerName(), url: data.mediaInfo?.mediaUrl4k, svg: , }); @@ -234,6 +234,18 @@ const TvDetails: React.FC = ({ tv }) => { return intl.formatMessage(messages.play, { mediaServerName: 'Jellyfin' }); } + function getAvalaible4kMediaServerName() { + if (process.env.JELLYFIN_TYPE === 'emby') { + return intl.formatMessage(messages.play4k, { mediaServerName: 'Emby' }); + } + + if (settings.currentSettings.mediaServerType === MediaServerType.PLEX) { + return intl.formatMessage(messages.play4k, { mediaServerName: 'Plex' }); + } + + return intl.formatMessage(messages.play4k, { mediaServerName: 'Jellyfin' }); + } + return (
    Date: Thu, 26 May 2022 08:37:51 +0500 Subject: [PATCH 24/67] feat(ui): conditional media server name to add emby to moviedetails --- src/components/MovieDetails/index.tsx | 34 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index fbbad4bd..0ba0b927 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -130,10 +130,7 @@ const MovieDetails: React.FC = ({ movie }) => { if (data.mediaInfo?.mediaUrl) { mediaLinks.push({ - text: - settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN - ? intl.formatMessage(messages.play, { mediaServerName: 'Jellyfin' }) - : intl.formatMessage(messages.play, { mediaServerName: 'Plex' }), + text: getAvalaibleMediaServerName(), url: data.mediaInfo?.mediaUrl, svg: , }); @@ -146,10 +143,7 @@ const MovieDetails: React.FC = ({ movie }) => { }) ) { mediaLinks.push({ - text: - settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN - ? intl.formatMessage(messages.play4k, { mediaServerName: 'Jellyfin' }) - : intl.formatMessage(messages.play4k, { mediaServerName: 'Plex' }), + text: getAvalaible4kMediaServerName(), url: data.mediaInfo?.mediaUrl4k, svg: , }); @@ -228,6 +222,30 @@ const MovieDetails: React.FC = ({ movie }) => { data?.watchProviders?.find((provider) => provider.iso_3166_1 === region) ?.flatrate ?? []; + function getAvalaibleMediaServerName() { + if (process.env.JELLYFIN_TYPE === 'emby') { + return intl.formatMessage(messages.play, { mediaServerName: 'Emby' }); + } + + if (settings.currentSettings.mediaServerType === MediaServerType.PLEX) { + return intl.formatMessage(messages.play, { mediaServerName: 'Plex' }); + } + + return intl.formatMessage(messages.play, { mediaServerName: 'Jellyfin' }); + } + + function getAvalaible4kMediaServerName() { + if (process.env.JELLYFIN_TYPE === 'emby') { + return intl.formatMessage(messages.play4k, { mediaServerName: 'Emby' }); + } + + if (settings.currentSettings.mediaServerType === MediaServerType.PLEX) { + return intl.formatMessage(messages.play4k, { mediaServerName: 'Plex' }); + } + + return intl.formatMessage(messages.play4k, { mediaServerName: 'Jellyfin' }); + } + return (
    Date: Thu, 26 May 2022 08:39:39 +0500 Subject: [PATCH 25/67] feat(ui): conditional media server name to add emby to issuedetails play on button --- src/components/IssueDetails/index.tsx | 68 +++++++++++++++++---------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/components/IssueDetails/index.tsx b/src/components/IssueDetails/index.tsx index 90cfb494..34613389 100644 --- a/src/components/IssueDetails/index.tsx +++ b/src/components/IssueDetails/index.tsx @@ -366,13 +366,18 @@ const IssueDetails: React.FC = () => { > - {intl.formatMessage(messages.playonplex, { - mediaServerName: - settings.currentSettings.mediaServerType === + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.playonplex, { + mediaServerName: 'Emby', + }) + : settings.currentSettings.mediaServerType === MediaServerType.PLEX - ? 'Plex' - : 'Jellyfin', - })} + ? intl.formatMessage(messages.playonplex, { + mediaServerName: 'Plex', + }) + : intl.formatMessage(messages.playonplex, { + mediaServerName: 'Jellyfin', + })} )} @@ -407,13 +412,18 @@ const IssueDetails: React.FC = () => { > - {intl.formatMessage(messages.play4konplex, { - mediaServerName: - settings.currentSettings.mediaServerType === + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.play4konplex, { + mediaServerName: 'Emby', + }) + : settings.currentSettings.mediaServerType === MediaServerType.PLEX - ? 'Plex' - : 'Jellyfin', - })} + ? intl.formatMessage(messages.play4konplex, { + mediaServerName: 'Plex', + }) + : intl.formatMessage(messages.play4konplex, { + mediaServerName: 'Jellyfin', + })} )} @@ -618,13 +628,18 @@ const IssueDetails: React.FC = () => { > - {intl.formatMessage(messages.playonplex, { - mediaServerName: - settings.currentSettings.mediaServerType === + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.playonplex, { + mediaServerName: 'Emby', + }) + : settings.currentSettings.mediaServerType === MediaServerType.PLEX - ? 'Plex' - : 'Jellyfin', - })} + ? intl.formatMessage(messages.playonplex, { + mediaServerName: 'Plex', + }) + : intl.formatMessage(messages.playonplex, { + mediaServerName: 'Jellyfin', + })} )} @@ -659,13 +674,18 @@ const IssueDetails: React.FC = () => { > - {intl.formatMessage(messages.play4konplex, { - mediaServerName: - settings.currentSettings.mediaServerType === + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.play4konplex, { + mediaServerName: 'Emby', + }) + : settings.currentSettings.mediaServerType === MediaServerType.PLEX - ? 'Plex' - : 'Jellyfin', - })} + ? intl.formatMessage(messages.play4konplex, { + mediaServerName: 'Plex', + }) + : intl.formatMessage(messages.play4konplex, { + mediaServerName: 'Jellyfin', + })} )} From f8a239b1b82feb8f2705bfd8b1b76dd448b14e7c Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Thu, 26 May 2022 08:52:16 +0500 Subject: [PATCH 26/67] style(ui): conditional media server name to add emby to settings Conditionaly media server name to replace every reference of jellyfin with emby in settings tab when environmental variable set --- src/components/Settings/SettingsJellyfin.tsx | 86 ++++++++++++++----- src/components/Settings/SettingsLayout.tsx | 16 +++- .../Settings/SettingsUsers/index.tsx | 12 ++- 3 files changed, 85 insertions(+), 29 deletions(-) diff --git a/src/components/Settings/SettingsJellyfin.tsx b/src/components/Settings/SettingsJellyfin.tsx index 9740762c..5a5d4ffa 100644 --- a/src/components/Settings/SettingsJellyfin.tsx +++ b/src/components/Settings/SettingsJellyfin.tsx @@ -14,28 +14,28 @@ import LoadingSpinner from '../Common/LoadingSpinner'; import LibraryItem from './LibraryItem'; const messages = defineMessages({ - jellyfinsettings: 'Jellyfin Settings', + jellyfinsettings: '{mediaServerName} Settings', jellyfinsettingsDescription: - 'Configure the settings for your Jellyfin server. Jellyfin scans your Jellyfin libraries to see what content is available.', + 'Configure the settings for your {mediaServerName} server. {mediaServerName} scans your {mediaServerName} libraries to see what content is available.', timeout: 'Timeout', save: 'Save Changes', saving: 'Saving…', - jellyfinlibraries: 'Jellyfin Libraries', + jellyfinlibraries: '{mediaServerName} Libraries', jellyfinlibrariesDescription: - 'The libraries Jellyfin scans for titles. Click the button below if no libraries are listed.', + 'The libraries {mediaServerName} scans for titles. Click the button below if no libraries are listed.', jellyfinSettingsFailure: - 'Something went wrong while saving Jellyfin settings.', - jellyfinSettingsSuccess: 'Jellyfin settings saved successfully!', - jellyfinSettings: 'Jellyfin Settings', + 'Something went wrong while saving {mediaServerName} settings.', + jellyfinSettingsSuccess: '{mediaServerName} settings saved successfully!', + jellyfinSettings: '{mediaServerName} Settings', jellyfinSettingsDescription: - 'Optionally configure an external player endpoint for your jellyfin server that is different to the internal URL used during setup', + 'Optionally configure an external player endpoint for your {mediaServerName} server that is different to the internal URL used during setup', externalUrl: 'External URL', validationUrl: 'You must provide a valid URL', syncing: 'Syncing', syncJellyfin: 'Sync Libraries', manualscanJellyfin: 'Manual Library Scan', manualscanDescriptionJellyfin: - "Normally, this will only be run once every 24 hours. Jellyfin will check your Jellyfin server's recently added more aggressively. If this is your first time configuring Jellyfin, a one-time full manual library scan is recommended!", + "Normally, this will only be run once every 24 hours. {mediaServerName} will check your {mediaServerName} server's recently added more aggressively. If this is your first time configuring {mediaServerName}, a one-time full manual library scan is recommended!", notrunning: 'Not Running', currentlibrary: 'Current Library: {name}', librariesRemaining: 'Libraries Remaining: {count}', @@ -161,10 +161,22 @@ const SettingsJellyfin: React.FC = ({ <>

    - + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.jellyfinlibraries, { + mediaServerName: 'Emby', + }) + : intl.formatMessage(messages.jellyfinlibraries, { + mediaServerName: 'Jellyfin', + })}

    - + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.jellyfinlibrariesDescription, { + mediaServerName: 'Emby', + }) + : intl.formatMessage(messages.jellyfinlibrariesDescription, { + mediaServerName: 'Jellyfin', + })}

    @@ -201,7 +213,13 @@ const SettingsJellyfin: React.FC = ({

    - + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.manualscanDescriptionJellyfin, { + mediaServerName: 'Emby', + }) + : intl.formatMessage(messages.manualscanDescriptionJellyfin, { + mediaServerName: 'Jellyfin', + })}

    @@ -305,10 +323,22 @@ const SettingsJellyfin: React.FC = ({ <>

    - {intl.formatMessage(messages.jellyfinSettings)} + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.jellyfinSettings, { + mediaServerName: 'Emby', + }) + : intl.formatMessage(messages.jellyfinSettings, { + mediaServerName: 'Jellyfin', + })}

    - {intl.formatMessage(messages.jellyfinSettingsDescription)} + {process.env.JELLYFIN_TYPE == 'emby' + ? intl.formatMessage(messages.jellyfinSettingsDescription, { + mediaServerName: 'Emby', + }) + : intl.formatMessage(messages.jellyfinSettingsDescription, { + mediaServerName: 'Jellyfin', + })}

    = ({ externalHostname: values.jellyfinExternalUrl, } as JellyfinSettings); - addToast(intl.formatMessage(messages.jellyfinSettingsSuccess), { - autoDismiss: true, - appearance: 'success', - }); + addToast( + intl.formatMessage(messages.jellyfinSettingsSuccess, { + mediaServerName: + process.env.JELLYFIN_TYPE == 'emby' ? 'Emby' : 'Jellyfin', + }), + { + autoDismiss: true, + appearance: 'success', + } + ); } catch (e) { - addToast(intl.formatMessage(messages.jellyfinSettingsFailure), { - autoDismiss: true, - appearance: 'error', - }); + addToast( + intl.formatMessage(messages.jellyfinSettingsFailure, { + mediaServerName: + process.env.JELLYFIN_TYPE == 'emby' ? 'Emby' : 'Jellyfin', + }), + { + autoDismiss: true, + appearance: 'error', + } + ); } finally { revalidate(); } diff --git a/src/components/Settings/SettingsLayout.tsx b/src/components/Settings/SettingsLayout.tsx index f2fa9078..23af1c63 100644 --- a/src/components/Settings/SettingsLayout.tsx +++ b/src/components/Settings/SettingsLayout.tsx @@ -8,7 +8,7 @@ const messages = defineMessages({ menuGeneralSettings: 'General', menuUsers: 'Users', menuPlexSettings: 'Plex', - menuJellyfinSettings: 'Jellyfin', + menuJellyfinSettings: '{mediaServerName}', menuServices: 'Services', menuNotifications: 'Notifications', menuLogs: 'Logs', @@ -18,7 +18,6 @@ const messages = defineMessages({ const SettingsLayout: React.FC = ({ children }) => { const intl = useIntl(); - const settingsRoutes: SettingsRoute[] = [ { text: intl.formatMessage(messages.menuGeneralSettings), @@ -36,7 +35,7 @@ const SettingsLayout: React.FC = ({ children }) => { regex: /^\/settings\/plex/, }, { - text: intl.formatMessage(messages.menuJellyfinSettings), + text: getAvalaibleMediaServerName(), route: '/settings/jellyfin', regex: /^\/settings\/jellyfin/, }, @@ -76,6 +75,17 @@ const SettingsLayout: React.FC = ({ children }) => {
    {children}
    ); + function getAvalaibleMediaServerName() { + if (process.env.JELLYFIN_TYPE === 'emby') { + return intl.formatMessage(messages.menuJellyfinSettings, { + mediaServerName: 'Emby', + }); + } + + return intl.formatMessage(messages.menuJellyfinSettings, { + mediaServerName: 'Jellyfin', + }); + } }; export default SettingsLayout; diff --git a/src/components/Settings/SettingsUsers/index.tsx b/src/components/Settings/SettingsUsers/index.tsx index d53a619b..03232f88 100644 --- a/src/components/Settings/SettingsUsers/index.tsx +++ b/src/components/Settings/SettingsUsers/index.tsx @@ -131,16 +131,20 @@ const SettingsUsers: React.FC = () => {

    - {process.env.JELLYFIN_TYPE == 'emby' + {publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.manualscanDescriptionJellyfin, { mediaServerName: 'Emby', }) @@ -323,7 +325,7 @@ const SettingsJellyfin: React.FC = ({ <>

    - {process.env.JELLYFIN_TYPE == 'emby' + {publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinSettings, { mediaServerName: 'Emby', }) @@ -332,7 +334,7 @@ const SettingsJellyfin: React.FC = ({ })}

    - {process.env.JELLYFIN_TYPE == 'emby' + {publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? intl.formatMessage(messages.jellyfinSettingsDescription, { mediaServerName: 'Emby', }) @@ -355,7 +357,9 @@ const SettingsJellyfin: React.FC = ({ addToast( intl.formatMessage(messages.jellyfinSettingsSuccess, { mediaServerName: - process.env.JELLYFIN_TYPE == 'emby' ? 'Emby' : 'Jellyfin', + publicRuntimeConfig.JELLYFIN_TYPE == 'emby' + ? 'Emby' + : 'Jellyfin', }), { autoDismiss: true, @@ -366,7 +370,9 @@ const SettingsJellyfin: React.FC = ({ addToast( intl.formatMessage(messages.jellyfinSettingsFailure, { mediaServerName: - process.env.JELLYFIN_TYPE == 'emby' ? 'Emby' : 'Jellyfin', + publicRuntimeConfig.JELLYFIN_TYPE == 'emby' + ? 'Emby' + : 'Jellyfin', }), { autoDismiss: true, diff --git a/src/components/Settings/SettingsLayout.tsx b/src/components/Settings/SettingsLayout.tsx index 23af1c63..3963d5c5 100644 --- a/src/components/Settings/SettingsLayout.tsx +++ b/src/components/Settings/SettingsLayout.tsx @@ -3,6 +3,7 @@ import { defineMessages, useIntl } from 'react-intl'; import globalMessages from '../../i18n/globalMessages'; import PageTitle from '../Common/PageTitle'; import SettingsTabs, { SettingsRoute } from '../Common/SettingsTabs'; +import getConfig from 'next/config'; const messages = defineMessages({ menuGeneralSettings: 'General', @@ -18,6 +19,7 @@ const messages = defineMessages({ const SettingsLayout: React.FC = ({ children }) => { const intl = useIntl(); + const { publicRuntimeConfig } = getConfig(); const settingsRoutes: SettingsRoute[] = [ { text: intl.formatMessage(messages.menuGeneralSettings), @@ -76,7 +78,7 @@ const SettingsLayout: React.FC = ({ children }) => { ); function getAvalaibleMediaServerName() { - if (process.env.JELLYFIN_TYPE === 'emby') { + if (publicRuntimeConfig.JELLYFIN_TYPE === 'emby') { return intl.formatMessage(messages.menuJellyfinSettings, { mediaServerName: 'Emby', }); diff --git a/src/components/Settings/SettingsUsers/index.tsx b/src/components/Settings/SettingsUsers/index.tsx index 03232f88..89c89673 100644 --- a/src/components/Settings/SettingsUsers/index.tsx +++ b/src/components/Settings/SettingsUsers/index.tsx @@ -14,6 +14,7 @@ import LoadingSpinner from '../../Common/LoadingSpinner'; import PageTitle from '../../Common/PageTitle'; import PermissionEdit from '../../PermissionEdit'; import QuotaSelector from '../../QuotaSelector'; +import getConfig from 'next/config'; const messages = defineMessages({ users: 'Users', @@ -42,6 +43,7 @@ const SettingsUsers: React.FC = () => { mutate: revalidate, } = useSWR('/api/v1/settings/main'); const settings = useSettings(); + const { publicRuntimeConfig } = getConfig(); if (!data && !error) { return ; @@ -131,7 +133,7 @@ const SettingsUsers: React.FC = () => {

    {user?.userType === UserType.PLEX ? ( + {intl.formatMessage(messages.plexuser)} + + ) : user?.userType === UserType.LOCAL ? ( + {intl.formatMessage(messages.localuser)} - ) : ( - + ) : publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? ( + {intl.formatMessage(messages.mediaServerUser, { - mediaServerName: - settings.currentSettings.mediaServerType === - MediaServerType.PLEX - ? 'Plex' - : 'Jellyfin', + mediaServerName: 'Emby', })} - )} + ) : user?.userType === UserType.JELLYFIN ? ( + + {intl.formatMessage(messages.mediaServerUser, { + mediaServerName: 'Jellyfin', + })} + + ) : null}
    From c117b37cd9fae5d148ad959cb02006e156abac8c Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Wed, 1 Jun 2022 14:48:05 +0200 Subject: [PATCH 38/67] feat(tv): tv seasons tv seasons --- overseerr-api.yml | 38 ++++++++++++++++++++++++++++++ server/api/themoviedb/index.ts | 27 +++++++++++++++++++++ server/models/Tv.ts | 8 +++++++ server/routes/tv.ts | 29 ++++++++++++++++++++++- src/components/TvDetails/index.tsx | 8 +++++++ 5 files changed, 109 insertions(+), 1 deletion(-) diff --git a/overseerr-api.yml b/overseerr-api.yml index 551f7dd9..c6611f79 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -1031,6 +1031,13 @@ components: type: array items: $ref: '#/components/schemas/WatchProviders' + TvSeasons: + type: object + properties: + seasons: + type: array + items: + $ref: '#/components/schemas/Season' MediaRequest: type: object properties: @@ -5082,6 +5089,37 @@ paths: application/json: schema: $ref: '#/components/schemas/TvDetails' + /tv/{tvId}/seasons: + get: + summary: Get TV seasons + description: Returns TV seasons based on the provided tvId in a JSON object. + tags: + - tv + parameters: + - in: path + name: tvId + required: true + schema: + type: number + example: 76479 + - in: query + name: page + schema: + type: number + example: 1 + default: 1 + - in: query + name: language + schema: + type: string + example: en + responses: + '200': + description: TV seasons + content: + application/json: + schema: + $ref: '#/components/schemas/TvSeasons' /tv/{tvId}/season/{seasonId}: get: summary: Get season details and episode list diff --git a/server/api/themoviedb/index.ts b/server/api/themoviedb/index.ts index b5060c03..bef79ce5 100644 --- a/server/api/themoviedb/index.ts +++ b/server/api/themoviedb/index.ts @@ -18,6 +18,7 @@ import { TmdbSearchTvResponse, TmdbSeasonWithEpisodes, TmdbTvDetails, + TmdbTvSeasonResult, TmdbUpcomingMoviesResponse, } from './interfaces'; @@ -271,6 +272,32 @@ class TheMovieDb extends ExternalAPI { } }; + public getTvSeasons = async ({ + tvId, + page = 1, + language = 'en', + }: { + tvId: number; + page: number; + language?: string; + }): Promise => { + try { + const data = await this.get( + `/tv/${tvId}`, + { + params: { + page, + language, + }, + }, + 43200 + ); + return data.seasons; + } catch (e) { + throw new Error(`[TMDb] Failed to fetch TV show seasons: ${e.message}`); + } + }; + public getTvSeason = async ({ tvId, seasonNumber, diff --git a/server/models/Tv.ts b/server/models/Tv.ts index b596b1d2..8599ac34 100644 --- a/server/models/Tv.ts +++ b/server/models/Tv.ts @@ -48,6 +48,10 @@ interface Season { seasonNumber: number; } +export interface TvSeasons { + seasons: Season[]; +} + export interface SeasonWithEpisodes extends Season { episodes: Episode[]; externalIds: ExternalIds; @@ -223,3 +227,7 @@ export const mapTvDetails = ( mediaInfo: media, watchProviders: mapWatchProviders(show['watch/providers']?.results ?? {}), }); + +export const mapTvSeasons = (seasons: TmdbTvSeasonResult[]): TvSeasons => ({ + seasons: seasons.map(mapSeasonResult), +}); diff --git a/server/routes/tv.ts b/server/routes/tv.ts index 201e7afe..7083aa9b 100644 --- a/server/routes/tv.ts +++ b/server/routes/tv.ts @@ -5,7 +5,11 @@ import { MediaType } from '../constants/media'; import Media from '../entity/Media'; import logger from '../logger'; import { mapTvResult } from '../models/Search'; -import { mapSeasonWithEpisodes, mapTvDetails } from '../models/Tv'; +import { + mapSeasonWithEpisodes, + mapTvDetails, + mapTvSeasons, +} from '../models/Tv'; const tvRoutes = Router(); @@ -33,6 +37,29 @@ tvRoutes.get('/:id', async (req, res, next) => { } }); +tvRoutes.get('/:id/seasons', async (req, res, next) => { + const tmdb = new TheMovieDb(); + try { + const seasons = await tmdb.getTvSeasons({ + tvId: Number(req.params.id), + page: Number(req.query.page), + language: req.locale ?? (req.query.language as string), + }); + + return res.status(200).json(mapTvSeasons(seasons)); + } catch (e) { + logger.debug('Something went wrong retrieving seasons', { + label: 'API', + errorMessage: e.message, + tvId: req.params.id, + }); + return next({ + status: 500, + message: 'Unable to retrieve seasons.', + }); + } +}); + tvRoutes.get('/:id/season/:seasonNumber', async (req, res, next) => { const tmdb = new TheMovieDb(); diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index a4d6bcef..f11eabb8 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -672,6 +672,14 @@ const TvDetails: React.FC = ({ tv }) => {

    + + {data.credits.cast.length > 0 && ( <>
    From 739f5f9c9ade8a1680bcb374f6c9e919a9e1426c Mon Sep 17 00:00:00 2001 From: notfakie <103784113+notfakie@users.noreply.github.com> Date: Thu, 2 Jun 2022 18:47:22 +1200 Subject: [PATCH 39/67] fix: only show mediaserver settings for current active mediaserver --- src/components/Settings/SettingsLayout.tsx | 37 +++++++++++----------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/components/Settings/SettingsLayout.tsx b/src/components/Settings/SettingsLayout.tsx index 3963d5c5..3de72f4a 100644 --- a/src/components/Settings/SettingsLayout.tsx +++ b/src/components/Settings/SettingsLayout.tsx @@ -1,9 +1,11 @@ +import getConfig from 'next/config'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; +import { MediaServerType } from '../../../server/constants/server'; +import useSettings from '../../hooks/useSettings'; import globalMessages from '../../i18n/globalMessages'; import PageTitle from '../Common/PageTitle'; import SettingsTabs, { SettingsRoute } from '../Common/SettingsTabs'; -import getConfig from 'next/config'; const messages = defineMessages({ menuGeneralSettings: 'General', @@ -20,6 +22,7 @@ const messages = defineMessages({ const SettingsLayout: React.FC = ({ children }) => { const intl = useIntl(); const { publicRuntimeConfig } = getConfig(); + const settings = useSettings(); const settingsRoutes: SettingsRoute[] = [ { text: intl.formatMessage(messages.menuGeneralSettings), @@ -31,16 +34,17 @@ const SettingsLayout: React.FC = ({ children }) => { route: '/settings/users', regex: /^\/settings\/users/, }, - { - text: intl.formatMessage(messages.menuPlexSettings), - route: '/settings/plex', - regex: /^\/settings\/plex/, - }, - { - text: getAvalaibleMediaServerName(), - route: '/settings/jellyfin', - regex: /^\/settings\/jellyfin/, - }, + settings.currentSettings.mediaServerType === MediaServerType.PLEX + ? { + text: intl.formatMessage(messages.menuPlexSettings), + route: '/settings/plex', + regex: /^\/settings\/plex/, + } + : { + text: getAvailableMediaServerName(), + route: '/settings/jellyfin', + regex: /^\/settings\/jellyfin/, + }, { text: intl.formatMessage(messages.menuServices), route: '/settings/services', @@ -77,15 +81,10 @@ const SettingsLayout: React.FC = ({ children }) => {
    {children}
    ); - function getAvalaibleMediaServerName() { - if (publicRuntimeConfig.JELLYFIN_TYPE === 'emby') { - return intl.formatMessage(messages.menuJellyfinSettings, { - mediaServerName: 'Emby', - }); - } - + function getAvailableMediaServerName() { return intl.formatMessage(messages.menuJellyfinSettings, { - mediaServerName: 'Jellyfin', + mediaServerName: + publicRuntimeConfig.JELLYFIN_TYPE === 'emby' ? 'Emby' : 'Jellyfin', }); } }; From 4b7bdd3d7d608fe0bf52f494766fd7c40bede859 Mon Sep 17 00:00:00 2001 From: notfakie <103784113+notfakie@users.noreply.github.com> Date: Thu, 2 Jun 2022 18:47:25 +1200 Subject: [PATCH 40/67] fix: remove internal Overseerr sponsor link, this is remaining on the main github page instead --- .../Settings/SettingsAbout/index.tsx | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/src/components/Settings/SettingsAbout/index.tsx b/src/components/Settings/SettingsAbout/index.tsx index ab79b11c..1afe948d 100644 --- a/src/components/Settings/SettingsAbout/index.tsx +++ b/src/components/Settings/SettingsAbout/index.tsx @@ -188,35 +188,6 @@ const SettingsAbout: React.FC = () => {
    -
    - - - - https://github.com/sponsors/sct - - - {intl.formatMessage(messages.preferredmethod)} - - - - - https://patreon.com/overseerr - - - -
    From 7450138ac12640797952c1a2d5e1e111d17a11e1 Mon Sep 17 00:00:00 2001 From: notfakie <103784113+notfakie@users.noreply.github.com> Date: Thu, 2 Jun 2022 18:47:27 +1200 Subject: [PATCH 41/67] fix: hide plex guid cache settings from ui when running in jellyfin/emby mode --- .../Settings/SettingsJobsCache/index.tsx | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/components/Settings/SettingsJobsCache/index.tsx b/src/components/Settings/SettingsJobsCache/index.tsx index 35e445cb..cfe8c4bf 100644 --- a/src/components/Settings/SettingsJobsCache/index.tsx +++ b/src/components/Settings/SettingsJobsCache/index.tsx @@ -10,9 +10,11 @@ import { } from 'react-intl'; import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; +import { MediaServerType } from '../../../../server/constants/server'; import { CacheItem } from '../../../../server/interfaces/api/settingsInterfaces'; import { JobId } from '../../../../server/lib/settings'; import Spinner from '../../../assets/spinner.svg'; +import useSettings from '../../../hooks/useSettings'; import globalMessages from '../../../i18n/globalMessages'; import { formatBytes } from '../../../utils/numberHelpers'; import Badge from '../../Common/Badge'; @@ -102,6 +104,7 @@ const SettingsJobs: React.FC = () => { const [isSaving, setIsSaving] = useState(false); const [jobScheduleMinutes, setJobScheduleMinutes] = useState(5); const [jobScheduleHours, setJobScheduleHours] = useState(1); + const settings = useSettings(); if (!data && !error) { return ; @@ -369,22 +372,33 @@ const SettingsJobs: React.FC = () => { - {cacheData?.map((cache) => ( - - {cache.name} - {intl.formatNumber(cache.stats.hits)} - {intl.formatNumber(cache.stats.misses)} - {intl.formatNumber(cache.stats.keys)} - {formatBytes(cache.stats.ksize)} - {formatBytes(cache.stats.vsize)} - - - - - ))} + {cacheData + ?.filter( + (cache) => + !( + settings.currentSettings.mediaServerType !== + MediaServerType.PLEX && cache.id === 'plexguid' + ) + ) + .map((cache) => ( + + {cache.name} + {intl.formatNumber(cache.stats.hits)} + {intl.formatNumber(cache.stats.misses)} + {intl.formatNumber(cache.stats.keys)} + {formatBytes(cache.stats.ksize)} + {formatBytes(cache.stats.vsize)} + + + + + ))} From 6574e18516201bc11b5f0c422bf6b432c722e067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Bart=C3=ADk?= <63553146+sambartik@users.noreply.github.com> Date: Sat, 4 Jun 2022 18:07:14 +0200 Subject: [PATCH 42/67] fix(scan): ignore virtual seasons Virtual seasons appeared as available / partially available, even though they were not even shown in the Jellyfin web UI. For more info see #119 --- server/api/jellyfin.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/api/jellyfin.ts b/server/api/jellyfin.ts index f6f6cb9d..0753682e 100644 --- a/server/api/jellyfin.ts +++ b/server/api/jellyfin.ts @@ -31,6 +31,7 @@ export interface JellyfinLibraryItem { Id: string; HasSubtitles: boolean; Type: 'Movie' | 'Episode' | 'Season' | 'Series'; + LocationType: 'FileSystem' | 'Offline' | 'Remote' | 'Virtual'; SeriesName?: string; SeriesId?: string; SeasonId?: string; @@ -251,7 +252,9 @@ class JellyfinAPI { try { const contents = await this.axios.get(`/Shows/${seriesID}/Seasons`); - return contents.data.Items; + return contents.data.Items.filter( + (item: JellyfinLibraryItem) => item.LocationType !== 'Virtual' + ); } catch (e) { logger.error( `Something went wrong while getting the list of seasons from the Jellyfin server: ${e.message}`, From c81154800fd7dc48fe890f4dd57ff33cbab973bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Bart=C3=ADk?= <63553146+sambartik@users.noreply.github.com> Date: Sun, 5 Jun 2022 12:41:34 +0200 Subject: [PATCH 43/67] fix(jellyfin): ignore additional items with virtual location type --- server/api/jellyfin.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/server/api/jellyfin.ts b/server/api/jellyfin.ts index 0753682e..fae632a2 100644 --- a/server/api/jellyfin.ts +++ b/server/api/jellyfin.ts @@ -206,7 +206,9 @@ class JellyfinAPI { `/Users/${this.userId}/Items?SortBy=SortName&SortOrder=Ascending&IncludeItemTypes=Series,Movie&Recursive=true&StartIndex=0&ParentId=${id}` ); - return contents.data.Items; + return contents.data.Items.filter( + (item: JellyfinLibraryItem) => item.LocationType !== 'Virtual' + ); } catch (e) { logger.error( `Something went wrong while getting library content from the Jellyfin server: ${e.message}`, @@ -222,7 +224,9 @@ class JellyfinAPI { `/Users/${this.userId}/Items/Latest?Limit=12&ParentId=${id}` ); - return contents.data; + return contents.data.filter( + (item: JellyfinLibraryItem) => item.LocationType !== 'Virtual' + ); } catch (e) { logger.error( `Something went wrong while getting library content from the Jellyfin server: ${e.message}`, @@ -238,7 +242,9 @@ class JellyfinAPI { `/Users/${this.userId}/Items/${id}` ); - return contents.data; + return contents.data.filter( + (item: JellyfinLibraryItem) => item.LocationType !== 'Virtual' + ); } catch (e) { logger.error( `Something went wrong while getting library content from the Jellyfin server: ${e.message}`, @@ -273,7 +279,9 @@ class JellyfinAPI { `/Shows/${seriesID}/Episodes?seasonId=${seasonID}` ); - return contents.data.Items; + return contents.data.Items.filter( + (item: JellyfinLibraryItem) => item.LocationType !== 'Virtual' + ); } catch (e) { logger.error( `Something went wrong while getting the list of episodes from the Jellyfin server: ${e.message}`, From d1dbd6e3b9b1134e06150fc5eb21f729f64c0955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Bart=C3=ADk?= <63553146+sambartik@users.noreply.github.com> Date: Sun, 5 Jun 2022 17:07:27 +0200 Subject: [PATCH 44/67] fix(jellyfin): sync errors --- server/api/jellyfin.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/server/api/jellyfin.ts b/server/api/jellyfin.ts index fae632a2..5dd258c4 100644 --- a/server/api/jellyfin.ts +++ b/server/api/jellyfin.ts @@ -224,9 +224,7 @@ class JellyfinAPI { `/Users/${this.userId}/Items/Latest?Limit=12&ParentId=${id}` ); - return contents.data.filter( - (item: JellyfinLibraryItem) => item.LocationType !== 'Virtual' - ); + return contents.data; } catch (e) { logger.error( `Something went wrong while getting library content from the Jellyfin server: ${e.message}`, @@ -242,9 +240,7 @@ class JellyfinAPI { `/Users/${this.userId}/Items/${id}` ); - return contents.data.filter( - (item: JellyfinLibraryItem) => item.LocationType !== 'Virtual' - ); + return contents.data; } catch (e) { logger.error( `Something went wrong while getting library content from the Jellyfin server: ${e.message}`, From 30c48f16ca0a74e7551b533bd75bc43304f946b1 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sun, 5 Jun 2022 17:46:26 +0200 Subject: [PATCH 45/67] feat(user email setting): added field to save user email fix #122 --- .idea/.gitignore | 8 +++ .idea/codeStyles/Project.xml | 67 +++++++++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 ++ .idea/dataSources.xml | 12 ++++ .idea/jellyseerr.iml | 12 ++++ .idea/modules.xml | 8 +++ .idea/vcs.xml | 6 ++ .../interfaces/api/userSettingsInterfaces.ts | 1 + server/routes/user/usersettings.ts | 1 + 9 files changed, 120 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/dataSources.xml create mode 100644 .idea/jellyseerr.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..ff5d00b0 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 00000000..a12bac1c --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:$PROJECT_DIR$/config/db/db.sqlite3 + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/jellyseerr.iml b/.idea/jellyseerr.iml new file mode 100644 index 00000000..0c8867d7 --- /dev/null +++ b/.idea/jellyseerr.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..bb19e753 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/server/interfaces/api/userSettingsInterfaces.ts b/server/interfaces/api/userSettingsInterfaces.ts index a3e132d6..d0a0ff9f 100644 --- a/server/interfaces/api/userSettingsInterfaces.ts +++ b/server/interfaces/api/userSettingsInterfaces.ts @@ -2,6 +2,7 @@ import { NotificationAgentKey } from '../../lib/settings'; export interface UserSettingsGeneralResponse { username?: string; + email?: string; discordId?: string; locale?: string; region?: string; diff --git a/server/routes/user/usersettings.ts b/server/routes/user/usersettings.ts index 0c53c94a..10555821 100644 --- a/server/routes/user/usersettings.ts +++ b/server/routes/user/usersettings.ts @@ -51,6 +51,7 @@ userSettingsRoutes.get<{ id: string }, UserSettingsGeneralResponse>( return res.status(200).json({ username: user.username, + email: user.email, discordId: user.settings?.discordId, locale: user.settings?.locale, region: user.settings?.region, From a8bc0c068b305710a224fa56a3725cc7e0758eb7 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sun, 5 Jun 2022 18:11:20 +0200 Subject: [PATCH 46/67] feat: email #122 --- server/routes/user/usersettings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/routes/user/usersettings.ts b/server/routes/user/usersettings.ts index 10555821..a05311a2 100644 --- a/server/routes/user/usersettings.ts +++ b/server/routes/user/usersettings.ts @@ -121,6 +121,7 @@ userSettingsRoutes.post< user.settings.locale = req.body.locale; user.settings.region = req.body.region; user.settings.originalLanguage = req.body.originalLanguage; + user.email = req.body.email ?? user.email; } await userRepository.save(user); @@ -131,6 +132,7 @@ userSettingsRoutes.post< locale: user.settings.locale, region: user.settings.region, originalLanguage: user.settings.originalLanguage, + email: user.email, }); } catch (e) { next({ status: 500, message: e.message }); From b22f20b6fa5f68398850ccbf9b6e1cc233b3c8f4 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sun, 5 Jun 2022 18:25:15 +0200 Subject: [PATCH 47/67] feat(user settings): added email field to user profiel settings #122 --- .../UserGeneralSettings/index.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx index ba01428f..5c6e4d2d 100644 --- a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx +++ b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx @@ -30,6 +30,7 @@ const messages = defineMessages({ general: 'General', generalsettings: 'General Settings', displayName: 'Display Name', + email: 'Email', save: 'Save Changes', saving: 'Saving…', mediaServerUser: '{mediaServerName} User', @@ -121,6 +122,7 @@ const UserGeneralSettings: React.FC = () => { { try { await axios.post(`/api/v1/user/${user?.id}/settings/main`, { username: values.displayName, + email: values.email, discordId: values.discordId, locale: values.locale, region: values.region, @@ -245,6 +248,24 @@ const UserGeneralSettings: React.FC = () => { )} +
    + +
    +
    + +
    + {errors.email && touched.email && ( +
    {errors.email}
    + )} +
    +
    - - {data.credits.cast.length > 0 && ( <>
    From 23779f4c7b1ba91bc2a2963302c00956be3678fb Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sun, 5 Jun 2022 18:43:52 +0200 Subject: [PATCH 49/67] style: removed .idea folder --- .idea/.gitignore | 8 ---- .idea/codeStyles/Project.xml | 67 ---------------------------- .idea/codeStyles/codeStyleConfig.xml | 5 --- .idea/dataSources.xml | 12 ----- .idea/jellyseerr.iml | 12 ----- .idea/modules.xml | 8 ---- .idea/vcs.xml | 6 --- 7 files changed, 118 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/dataSources.xml delete mode 100644 .idea/jellyseerr.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index ff5d00b0..00000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index a12bac1c..00000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - sqlite.xerial - true - org.sqlite.JDBC - jdbc:sqlite:$PROJECT_DIR$/config/db/db.sqlite3 - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/.idea/jellyseerr.iml b/.idea/jellyseerr.iml deleted file mode 100644 index 0c8867d7..00000000 --- a/.idea/jellyseerr.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index bb19e753..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 94ade93e16f02b372dafd2765bea475117431975 Mon Sep 17 00:00:00 2001 From: notfakie <103784113+notfakie@users.noreply.github.com> Date: Thu, 9 Jun 2022 17:08:00 +1200 Subject: [PATCH 50/67] fix: fix mediaServerType not set for Plex which leads to Plex users seeing Jellyfin settings --- server/routes/auth.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/routes/auth.ts b/server/routes/auth.ts index 7c92db62..0a05c6aa 100644 --- a/server/routes/auth.ts +++ b/server/routes/auth.ts @@ -70,6 +70,9 @@ authRoutes.post('/plex', async (req, res, next) => { userType: UserType.PLEX, }); + settings.main.mediaServerType = MediaServerType.PLEX; + settings.save(); + await userRepository.save(user); } else { const mainUser = await userRepository.findOneOrFail({ From 0fb5803eb9a7589141a63e13df9a8aa8ea4cebf2 Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Thu, 9 Jun 2022 16:38:18 +0500 Subject: [PATCH 51/67] fix(ui): fix translation errors for all locales in the import plex user button fix translation errors for all locales in the import plex user button as it currently shows as {mediaServerName} --- src/i18n/locale/ca.json | 2 +- src/i18n/locale/da.json | 2 +- src/i18n/locale/de.json | 2 +- src/i18n/locale/el.json | 2 +- src/i18n/locale/en.json | 2 +- src/i18n/locale/es.json | 2 +- src/i18n/locale/fr.json | 2 +- src/i18n/locale/hu.json | 2 +- src/i18n/locale/it.json | 2 +- src/i18n/locale/ja.json | 2 +- src/i18n/locale/nb_NO.json | 2 +- src/i18n/locale/nl.json | 2 +- src/i18n/locale/pl.json | 2 +- src/i18n/locale/pt_BR.json | 2 +- src/i18n/locale/pt_PT.json | 2 +- src/i18n/locale/ru.json | 2 +- src/i18n/locale/sq.json | 2 +- src/i18n/locale/sv.json | 2 +- src/i18n/locale/zh_Hans.json | 2 +- src/i18n/locale/zh_Hant.json | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/i18n/locale/ca.json b/src/i18n/locale/ca.json index 8e7f0873..027f4c5c 100644 --- a/src/i18n/locale/ca.json +++ b/src/i18n/locale/ca.json @@ -686,7 +686,7 @@ "components.UserList.nouserstoimport": "No hi ha usuaris nous de Plex a importar.", "components.UserList.localuser": "Usuari local", "components.UserList.importfromplexerror": "S'ha produït un error en importar usuaris de Plex.", - "components.UserList.importfromplex": "Importeu usuaris de {mediaServerName}", + "components.UserList.importfromplex": "Importeu usuaris de Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {usuari} other {usuaris}} de Plex importat correctament!", "components.TvDetails.watchtrailer": "Veure el tràiler", "components.TvDetails.viewfullcrew": "Mostreu equip complet", diff --git a/src/i18n/locale/da.json b/src/i18n/locale/da.json index d706e087..e472beed 100644 --- a/src/i18n/locale/da.json +++ b/src/i18n/locale/da.json @@ -850,7 +850,7 @@ "components.UserList.nouserstoimport": "Ingen nye brugere som kan importeres fra Plex.", "components.UserList.edituser": "Redigér Brugertilladelser", "components.UserList.email": "Email Adresse", - "components.UserList.importfromplex": "Importér Brugere fra {mediaServerName}", + "components.UserList.importfromplex": "Importér Brugere fra Plex", "components.UserList.owner": "Ejer", "components.UserList.password": "Kodeord", "components.UserList.passwordinfodescription": "Konfigurér en applikations-URL og aktivér emailnotifikationer for at tillade automatisk kodeordsgenerering.", diff --git a/src/i18n/locale/de.json b/src/i18n/locale/de.json index 0b8aa07b..a2454f28 100644 --- a/src/i18n/locale/de.json +++ b/src/i18n/locale/de.json @@ -223,7 +223,7 @@ "components.Settings.SettingsAbout.Releases.latestversion": "Neuste", "components.Settings.SettingsAbout.Releases.currentversion": "Aktuell", "components.UserList.importfromplexerror": "Beim Importieren von Plex-Benutzern ist etwas schief gelaufen.", - "components.UserList.importfromplex": "{mediaServerName}-Benutzer importieren", + "components.UserList.importfromplex": "Plex-Benutzer importieren", "components.TvDetails.viewfullcrew": "Komplette Crew anzeigen", "components.TvDetails.TvCrew.fullseriescrew": "Komplette Serien-Crew", "components.PersonDetails.crewmember": "Crew", diff --git a/src/i18n/locale/el.json b/src/i18n/locale/el.json index ac05b371..9355f5d6 100644 --- a/src/i18n/locale/el.json +++ b/src/i18n/locale/el.json @@ -602,7 +602,7 @@ "components.UserList.localuser": "Τοπικός χρήστης", "components.UserList.localLoginDisabled": "Η ρύθμιση Ενεργοποίηση τοπικής σύνδεσης είναι προς το παρόν απενεργοποιημένη.", "components.UserList.importfromplexerror": "Κάτι πήγε στραβά κατά την εισαγωγή χρηστών από το Plex.", - "components.UserList.importfromplex": "Εισαγωγή χρηστών από το {mediaServerName}", + "components.UserList.importfromplex": "Εισαγωγή χρηστών από το Plex", "components.UserList.importedfromplex": "{userCount, plural, one {# νέου χρήστη} other {#νέοι χρήστες}} εισήχθησαν απο το Plex επιτυχώς!", "components.UserList.email": "Διεύθυνση ηλεκτρονικού ταχυδρομείου", "components.UserList.edituser": "Επεξεργασία δικαιωμάτων χρήστη", diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 905ed650..b6f38832 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -861,7 +861,7 @@ "components.UserList.edituser": "Edit User Permissions", "components.UserList.email": "Email Address", "components.UserList.importedfromplex": "{userCount} Plex {userCount, plural, one {user} other {users}} imported successfully!", - "components.UserList.importfromplex": "Import {mediaServerName} Users", + "components.UserList.importfromplex": "Import Plex Users", "components.UserList.importfromplexerror": "Something went wrong while importing Plex users.", "components.UserList.localLoginDisabled": "The Enable Local Sign-In setting is currently disabled.", "components.UserList.localuser": "Local User", diff --git a/src/i18n/locale/es.json b/src/i18n/locale/es.json index f4ec6c68..e1ff1be0 100644 --- a/src/i18n/locale/es.json +++ b/src/i18n/locale/es.json @@ -223,7 +223,7 @@ "components.Settings.SettingsAbout.Releases.currentversion": "Actual", "components.MovieDetails.studio": "{studioCount, plural, one {Estudio} other {Estudios}}", "components.UserList.importfromplexerror": "Algo salió mal importando usuarios de Plex.", - "components.UserList.importfromplex": "Importar Usuarios de {mediaServerName}", + "components.UserList.importfromplex": "Importar Usuarios de Plex", "components.UserList.importedfromplex": "¡{userCount, plural, one {# nuevo usuario} other {# nuevos usuarios}} importado/s de Plex con éxito!", "components.TvDetails.viewfullcrew": "Ver Equipo Completo", "components.TvDetails.firstAirDate": "Primera fecha de emisión", diff --git a/src/i18n/locale/fr.json b/src/i18n/locale/fr.json index 2c846c2c..8099c7a2 100644 --- a/src/i18n/locale/fr.json +++ b/src/i18n/locale/fr.json @@ -223,7 +223,7 @@ "components.Settings.SettingsAbout.Releases.latestversion": "Dernière version", "components.Settings.SettingsAbout.Releases.currentversion": "Actuelle", "components.UserList.importfromplexerror": "Une erreur s'est produite durant l'importation des utilisateurs de Plex.", - "components.UserList.importfromplex": "Importer les utilisateurs de {mediaServerName}", + "components.UserList.importfromplex": "Importer les utilisateurs de Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {utilisateur} other {utilisateurs}} importé(s) depuis Plex avec succès !", "components.TvDetails.viewfullcrew": "Voir l'équipe complète de la série", "components.TvDetails.TvCrew.fullseriescrew": "Équipe complète de la série", diff --git a/src/i18n/locale/hu.json b/src/i18n/locale/hu.json index 00c46a4a..d04a9dc8 100644 --- a/src/i18n/locale/hu.json +++ b/src/i18n/locale/hu.json @@ -165,7 +165,7 @@ "components.UserList.password": "Jelszó", "components.UserList.localuser": "Helyi felhasználó", "components.UserList.importfromplexerror": "Hiba történt a felhasználók Plex-ről történő importálása közben.", - "components.UserList.importfromplex": "Felhasználók importálása {mediaServerName}-ről", + "components.UserList.importfromplex": "Felhasználók importálása Plex-ről", "components.UserList.importedfromplex": "{userCount, plural, =0 {Nem lett új} one {# új} other {# új}} felhasználó importálva Plex-ről!", "components.UserList.email": "E-mail-cím", "components.UserList.deleteuser": "Felhasználó törlése", diff --git a/src/i18n/locale/it.json b/src/i18n/locale/it.json index f6d43506..dea1ddd8 100644 --- a/src/i18n/locale/it.json +++ b/src/i18n/locale/it.json @@ -223,7 +223,7 @@ "components.Settings.SettingsAbout.Releases.latestversion": "Versione più recente", "components.Settings.SettingsAbout.Releases.currentversion": "Versione attuale", "components.UserList.importfromplexerror": "Qualcosa è andato storto nell'importare gli utenti Plex.", - "components.UserList.importfromplex": "Importa utenti {mediaServerName}", + "components.UserList.importfromplex": "Importa utenti Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {utente} other {utenti}} Plex {userCount, plural, one {importato} other {importati}} correttamente!", "components.TvDetails.viewfullcrew": "Vedi troupe completa", "components.TvDetails.TvCrew.fullseriescrew": "Troupe completa serie", diff --git a/src/i18n/locale/ja.json b/src/i18n/locale/ja.json index ebd18e27..f3fe3413 100644 --- a/src/i18n/locale/ja.json +++ b/src/i18n/locale/ja.json @@ -231,7 +231,7 @@ "components.TvDetails.watchtrailer": "予告編を見る", "components.MovieDetails.watchtrailer": "予告編を見る", "components.UserList.importfromplexerror": "Plexからユーザーをインポート中に問題が発生しました。", - "components.UserList.importfromplex": "{mediaServerName}からユーザーをインポート", + "components.UserList.importfromplex": "Plexからユーザーをインポート", "components.UserList.importedfromplex": "Plex から新ユーザー {userCount} 名をインポートしました。", "components.TvDetails.viewfullcrew": "フルクルーを表示", "components.TvDetails.firstAirDate": "初放送日", diff --git a/src/i18n/locale/nb_NO.json b/src/i18n/locale/nb_NO.json index 86f69ca5..61539a64 100644 --- a/src/i18n/locale/nb_NO.json +++ b/src/i18n/locale/nb_NO.json @@ -194,7 +194,7 @@ "components.UserList.userssaved": "Brukertillatelsene ble lagret!", "components.UserList.users": "Brukere", "components.UserList.importfromplexerror": "Noe gikk galt ved importering av brukere fra Plex.", - "components.UserList.importfromplex": "Importer brukere fra {mediaServerName}", + "components.UserList.importfromplex": "Importer brukere fra Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {ny bruker} other {nye brukere}} ble importert fra Plex!", "components.Settings.menuUsers": "Brukere", "components.Settings.SettingsUsers.users": "Brukere", diff --git a/src/i18n/locale/nl.json b/src/i18n/locale/nl.json index 70ac3d06..9d61ec7d 100644 --- a/src/i18n/locale/nl.json +++ b/src/i18n/locale/nl.json @@ -214,7 +214,7 @@ "components.UserList.userdeleteerror": "Er ging iets mis bij het verwijderen van de gebruiker.", "components.UserList.userdeleted": "Gebruiker succesvol verwijderd!", "components.UserList.importfromplexerror": "Er is iets misgegaan bij het importeren van Plex-gebruikers.", - "components.UserList.importfromplex": "{mediaServerName}-gebruikers importeren", + "components.UserList.importfromplex": "Plex-gebruikers importeren", "components.UserList.deleteuser": "Gebruiker verwijderen", "components.UserList.deleteconfirm": "Weet je zeker dat je deze gebruiker wilt verwijderen? Al hun bestaande aanvraaggegevens zullen worden verwijderd.", "components.TvDetails.watchtrailer": "Trailer bekijken", diff --git a/src/i18n/locale/pl.json b/src/i18n/locale/pl.json index 4089a50b..1a3eefb9 100644 --- a/src/i18n/locale/pl.json +++ b/src/i18n/locale/pl.json @@ -962,7 +962,7 @@ "components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "Wyślij po cichu", "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingsfailed": "Nie udało się zapisać ustawień powiadomień telegram.", "components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "Wielocyfrowy numer ID powiązany z Twoim kontem użytkownika", - "components.UserList.importfromplex": "Importuj użytkowników {mediaServerName}", + "components.UserList.importfromplex": "Importuj użytkowników Plex", "i18n.available": "Dostępny", "components.UserList.sortDisplayName": "Wyświetlana nazwa", "components.UserList.totalrequests": "Prośby", diff --git a/src/i18n/locale/pt_BR.json b/src/i18n/locale/pt_BR.json index 847e81f7..c99ebb02 100644 --- a/src/i18n/locale/pt_BR.json +++ b/src/i18n/locale/pt_BR.json @@ -228,7 +228,7 @@ "components.MovieDetails.viewfullcrew": "Ver Equipe Técnica Completa", "components.MovieDetails.MovieCrew.fullcrew": "Equipe Técnica Completa", "components.UserList.importfromplexerror": "Algo deu errado ao importar usuários do Plex.", - "components.UserList.importfromplex": "Importar Usuários do {mediaServerName}", + "components.UserList.importfromplex": "Importar Usuários do Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {usuário Plex importado} other {usuários Plex importados}} com sucesso!", "components.Settings.Notifications.NotificationsSlack.agentenabled": "Habilitar Agente", "components.RequestList.RequestItem.failedretry": "Algo deu errado ao retentar fazer a solicitação.", diff --git a/src/i18n/locale/pt_PT.json b/src/i18n/locale/pt_PT.json index fe72e0b6..4bcad9f5 100644 --- a/src/i18n/locale/pt_PT.json +++ b/src/i18n/locale/pt_PT.json @@ -199,7 +199,7 @@ "components.UserList.passwordinfodescription": "Configurar um URL de aplicação e ativar as notificações por e-mail para permitir a geração automática de palavra-passe.", "components.UserList.localuser": "Utilizador Local", "components.UserList.importfromplexerror": "Ocorreu um erro ao importar utilizadores do Plex.", - "components.UserList.importfromplex": "Importar Utilizadores do {mediaServerName}", + "components.UserList.importfromplex": "Importar Utilizadores do Plex", "components.UserList.importedfromplex": "{userCount, plural, one {# novo utilizador} other {# novos utilizadores}} importados do Plex com sucesso!", "components.UserList.email": "Endereço de E-mail", "components.UserList.deleteuser": "Apagar Utilizador", diff --git a/src/i18n/locale/ru.json b/src/i18n/locale/ru.json index a4fe8355..bf36dbb6 100644 --- a/src/i18n/locale/ru.json +++ b/src/i18n/locale/ru.json @@ -793,7 +793,7 @@ "components.UserList.usercreatedfailed": "Что-то пошло не так при создании пользователя.", "components.UserList.passwordinfodescription": "Настройте URL-адрес приложения и включите уведомления по электронной почте, чтобы обеспечить возможность автоматической генерации пароля.", "components.UserList.importfromplexerror": "Что-то пошло не так при импорте пользователей из Plex.", - "components.UserList.importfromplex": "Импортировать пользователей из {mediaServerName}", + "components.UserList.importfromplex": "Импортировать пользователей из Plex", "components.UserList.importedfromplex": "{userCount, plural, one {# новый пользователь} other {# новых пользователя(ей)}} успешно импортированы из Plex!", "components.UserList.edituser": "Изменить разрешения пользователя", "components.UserList.displayName": "Отображаемое имя", diff --git a/src/i18n/locale/sq.json b/src/i18n/locale/sq.json index 91b45b1d..3c63691e 100644 --- a/src/i18n/locale/sq.json +++ b/src/i18n/locale/sq.json @@ -1006,7 +1006,7 @@ "components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "Diçka shkoi keq duke ruajtur cilësimet.", "components.Settings.webAppUrlTip": "Në mënyrë opsionale drejto përdoruesit në aplikacionin web në serverin tënd në vend të atij web", "components.TvDetails.episodeRuntimeMinutes": "{runtime} minuta", - "components.UserList.importfromplex": "Importoni përdoruesit {mediaServerName}", + "components.UserList.importfromplex": "Importoni përdoruesit Plex", "components.UserList.importfromplexerror": "Diçka shkoi keq duke importuar përdoruesit Plex.", "components.TvDetails.firstAirDate": "Data e parë e transmetimit", "components.UserList.email": "Adresa email", diff --git a/src/i18n/locale/sv.json b/src/i18n/locale/sv.json index 4f68359f..bdbb4bbd 100644 --- a/src/i18n/locale/sv.json +++ b/src/i18n/locale/sv.json @@ -222,7 +222,7 @@ "components.Settings.SettingsAbout.Releases.releasedataMissing": "Versionsdata är för närvarande inte tillgänglig.", "components.Settings.SettingsAbout.Releases.latestversion": "Senaste Versionen", "components.Settings.SettingsAbout.Releases.currentversion": "Aktuell", - "components.UserList.importfromplex": "Importera {mediaServerName}användare", + "components.UserList.importfromplex": "Importera Plexanvändare", "components.UserList.importfromplexerror": "Något gick fel när Plexanvändare importerades.", "components.TvDetails.watchtrailer": "Kolla Trailer", "components.Settings.Notifications.allowselfsigned": "Tillåt Självsignerade Certifikat", diff --git a/src/i18n/locale/zh_Hans.json b/src/i18n/locale/zh_Hans.json index c48d04c9..16b29ad7 100644 --- a/src/i18n/locale/zh_Hans.json +++ b/src/i18n/locale/zh_Hans.json @@ -24,7 +24,7 @@ "components.UserList.localuser": "本地用户", "components.UserList.localLoginDisabled": "允许本地登录的设置目前被禁用。", "components.UserList.importfromplexerror": "导入 Plex 用户时出错。", - "components.UserList.importfromplex": "导入 {mediaServerName} 用户", + "components.UserList.importfromplex": "导入 Plex 用户", "components.UserList.importedfromplex": "{userCount} Plex {userCount, plural, one {user} other {users}} 成功导入!", "components.UserList.email": "电子邮件地址", "components.UserList.edituser": "编辑用户权限", diff --git a/src/i18n/locale/zh_Hant.json b/src/i18n/locale/zh_Hant.json index ca1a7313..d18433bb 100644 --- a/src/i18n/locale/zh_Hant.json +++ b/src/i18n/locale/zh_Hant.json @@ -52,7 +52,7 @@ "components.Settings.radarrsettings": "Radarr 設定", "components.Settings.menuPlexSettings": "Plex", "components.UserList.importfromplexerror": "匯入 Plex 使用者時出了點問題。", - "components.UserList.importfromplex": "匯入 {mediaServerName} 使用者", + "components.UserList.importfromplex": "匯入 Plex 使用者", "components.UserList.importedfromplex": "匯入 {userCount} 個 Plex 使用者成功!", "components.UserList.localuser": "本地使用者", "components.UserList.creating": "創建中…", From 543859e6f3b3a8cd4c61499a74bda610d3217626 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Fri, 10 Jun 2022 12:19:52 +0200 Subject: [PATCH 52/67] feat(uesrprofile): email requirement and validation --- .idea/.gitignore | 8 +++ .idea/codeStyles/Project.xml | 67 +++++++++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 ++ .idea/dataSources.xml | 12 ++++ .idea/git_toolbox_prj.xml | 15 +++++ .idea/jellyseerr.iml | 12 ++++ .idea/modules.xml | 8 +++ .idea/vcs.xml | 6 ++ package.json | 2 + server/entity/User.ts | 2 + server/lib/settings.ts | 5 ++ server/routes/auth.ts | 11 +++ src/components/Layout/Sidebar/index.tsx | 8 +++ src/components/Layout/UserWarnings/index.tsx | 66 ++++++++++++++++++ src/components/Layout/index.tsx | 1 + .../Notifications/NotificationsEmail.tsx | 15 +++++ .../UserGeneralSettings/index.tsx | 16 +++-- src/hooks/useUser.ts | 1 + tailwind.config.js | 1 + yarn.lock | 12 ++++ 20 files changed, 269 insertions(+), 4 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/dataSources.xml create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 .idea/jellyseerr.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 src/components/Layout/UserWarnings/index.tsx diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..ff5d00b0 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 00000000..a12bac1c --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:$PROJECT_DIR$/config/db/db.sqlite3 + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 00000000..02b915b8 --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jellyseerr.iml b/.idea/jellyseerr.iml new file mode 100644 index 00000000..0c8867d7 --- /dev/null +++ b/.idea/jellyseerr.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..bb19e753 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/package.json b/package.json index a25d16fd..7d5bb637 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "country-flag-icons": "^1.4.21", "csurf": "^1.11.0", "email-templates": "^8.0.10", + "email-validator": "^2.0.4", "express": "^4.17.3", "express-openapi-validator": "^4.13.6", "express-rate-limit": "^6.3.0", @@ -84,6 +85,7 @@ "@babel/cli": "^7.17.6", "@commitlint/cli": "^16.2.1", "@commitlint/config-conventional": "^16.2.1", + "@next/eslint-plugin-next": "^12.1.6", "@semantic-release/changelog": "^6.0.1", "@semantic-release/commit-analyzer": "^9.0.2", "@semantic-release/exec": "^6.0.3", diff --git a/server/entity/User.ts b/server/entity/User.ts index 157e7f24..7fa6dc67 100644 --- a/server/entity/User.ts +++ b/server/entity/User.ts @@ -137,6 +137,8 @@ export class User { @UpdateDateColumn() public updatedAt: Date; + public warnings: string[] = []; + constructor(init?: Partial) { Object.assign(this, init); } diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 6b167d7c..953fc3d0 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -134,6 +134,7 @@ interface FullPublicSettings extends PublicSettings { enablePushRegistration: boolean; locale: string; emailEnabled: boolean; + userEmailRequired: boolean; newPlexLogin: boolean; } @@ -159,6 +160,7 @@ export interface NotificationAgentSlack extends NotificationAgentConfig { export interface NotificationAgentEmail extends NotificationAgentConfig { options: { + userEmailRequired: boolean; emailFrom: string; smtpHost: string; smtpPort: number; @@ -335,6 +337,7 @@ class Settings { email: { enabled: false, options: { + userEmailRequired: false, emailFrom: '', smtpHost: '', smtpPort: 587, @@ -529,6 +532,8 @@ class Settings { enablePushRegistration: this.data.notifications.agents.webpush.enabled, locale: this.data.main.locale, emailEnabled: this.data.notifications.agents.email.enabled, + userEmailRequired: + this.data.notifications.agents.email.options.userEmailRequired, newPlexLogin: this.data.main.newPlexLogin, }; } diff --git a/server/routes/auth.ts b/server/routes/auth.ts index 7c92db62..20945151 100644 --- a/server/routes/auth.ts +++ b/server/routes/auth.ts @@ -9,6 +9,7 @@ import { Permission } from '../lib/permissions'; import { getSettings } from '../lib/settings'; import logger from '../logger'; import { isAuthenticated } from '../middleware/auth'; +import * as EmailValidator from 'email-validator'; const authRoutes = Router(); @@ -24,6 +25,16 @@ authRoutes.get('/me', isAuthenticated(), async (req, res) => { where: { id: req.user.id }, }); + // check if email is required in settings and if user has an valid email + const settings = await getSettings(); + if ( + settings.notifications.agents.email.options.userEmailRequired && + !EmailValidator.validate(user.email) + ) { + user.warnings.push('userEmailRequired'); + logger.warn(`User ${user.username} has no valid email address`); + } + return res.status(200).json(user); }); diff --git a/src/components/Layout/Sidebar/index.tsx b/src/components/Layout/Sidebar/index.tsx index 45716eeb..821a3d2d 100644 --- a/src/components/Layout/Sidebar/index.tsx +++ b/src/components/Layout/Sidebar/index.tsx @@ -14,6 +14,7 @@ import useClickOutside from '../../../hooks/useClickOutside'; import { Permission, useUser } from '../../../hooks/useUser'; import Transition from '../../Transition'; import VersionStatus from '../VersionStatus'; +import UserWarnings from '../UserWarnings'; const messages = defineMessages({ dashboard: 'Discover', @@ -177,6 +178,10 @@ const Sidebar: React.FC = ({ open, setClosed }) => { ); })} +
    + setClosed()} /> +
    + {hasPermission(Permission.ADMIN) && (
    setClosed()} /> @@ -236,6 +241,9 @@ const Sidebar: React.FC = ({ open, setClosed }) => { ); })} +
    + +
    {hasPermission(Permission.ADMIN) && (
    diff --git a/src/components/Layout/UserWarnings/index.tsx b/src/components/Layout/UserWarnings/index.tsx new file mode 100644 index 00000000..fe621d2a --- /dev/null +++ b/src/components/Layout/UserWarnings/index.tsx @@ -0,0 +1,66 @@ +import React from 'react'; +import Link from 'next/link'; +import { ExclamationIcon } from '@heroicons/react/outline'; +import { defineMessages, useIntl } from 'react-intl'; +import { useUser } from '../../../hooks/useUser'; + +const messages = defineMessages({ + emailRequired: 'An email address is required.', + emailInvalid: 'Email address is invalid.', + passwordRequired: 'A password is required.', +}); + +interface UserWarningsProps { + onClick?: () => void; +} + +const UserWarnings: React.FC = ({ onClick }) => { + const intl = useIntl(); + const { user } = useUser(); + if (!user) { + return null; + } + + let res = null; + + //check if a user has warnings + if (user.warnings.length > 0) { + user.warnings.forEach((warning) => { + let link = ''; + let warningText = ''; + let warningTitle = ''; + switch (warning) { + case 'userEmailRequired': + link = '/profile/settings/'; + warningTitle = 'Profile is incomplete'; + warningText = intl.formatMessage(messages.emailRequired); + } + + res = ( + + { + if (e.key === 'Enter' && onClick) { + onClick(); + } + }} + role="button" + tabIndex={0} + className="mx-2 mb-2 flex items-center rounded-lg bg-yellow-500 p-2 text-xs text-white ring-1 ring-gray-700 transition duration-300 hover:bg-yellow-400" + > + +
    + {warningTitle} + {warningText} +
    +
    + + ); + }); + } + + return res; +}; + +export default UserWarnings; diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index bde59277..b560c66e 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -50,6 +50,7 @@ const Layout: React.FC = ({ children }) => {
    + setSidebarOpen(false)} />
    diff --git a/src/components/Settings/Notifications/NotificationsEmail.tsx b/src/components/Settings/Notifications/NotificationsEmail.tsx index 40308390..e20a1305 100644 --- a/src/components/Settings/Notifications/NotificationsEmail.tsx +++ b/src/components/Settings/Notifications/NotificationsEmail.tsx @@ -16,6 +16,7 @@ const messages = defineMessages({ validationSmtpHostRequired: 'You must provide a valid hostname or IP address', validationSmtpPortRequired: 'You must provide a valid port number', agentenabled: 'Enable Agent', + userEmailRequired: 'Require user email', emailsender: 'Sender Address', smtpHost: 'SMTP Host', smtpPort: 'SMTP Port', @@ -125,6 +126,7 @@ const NotificationsEmail: React.FC = () => { { await axios.post('/api/v1/settings/notifications/email', { enabled: values.enabled, options: { + userEmailRequired: values.userEmailRequired, emailFrom: values.emailFrom, smtpHost: values.smtpHost, smtpPort: Number(values.smtpPort), @@ -241,6 +244,18 @@ const NotificationsEmail: React.FC = () => {
    +
    + +
    + +
    +
    {
    @@ -258,7 +261,12 @@ const UserGeneralSettings: React.FC = () => { id="email" name="email" type="text" - placeholder={user?.email} + placeholder="example@domain.com" + className={ + user?.warnings.find((w) => w === 'userEmailRequired') + ? 'border-2 border-red-400 focus:border-blue-600' + : '' + } />
    {errors.email && touched.email && ( diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts index 223cea32..4880a631 100644 --- a/src/hooks/useUser.ts +++ b/src/hooks/useUser.ts @@ -13,6 +13,7 @@ export type { PermissionCheckOptions }; export interface User { id: number; + warnings: string[]; plexUsername?: string; username?: string; displayName: string; diff --git a/tailwind.config.js b/tailwind.config.js index d1d023c0..aeb8b7f4 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -2,6 +2,7 @@ const defaultTheme = require('tailwindcss/defaultTheme'); module.exports = { + important: true, mode: 'jit', content: ['./src/pages/**/*.{ts,tsx}', './src/components/**/*.{ts,tsx}'], theme: { diff --git a/yarn.lock b/yarn.lock index b32edc90..06425347 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1622,6 +1622,13 @@ dependencies: glob "7.1.7" +"@next/eslint-plugin-next@^12.1.6": + version "12.1.6" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.1.6.tgz#dde3f98831f15923b25244588d924c716956292e" + integrity sha512-yNUtJ90NEiYFT6TJnNyofKMPYqirKDwpahcbxBgSIuABwYOdkGwzos1ZkYD51Qf0diYwpQZBeVqElTk7Q2WNqw== + dependencies: + glob "7.1.7" + "@next/swc-android-arm64@12.1.0": version "12.1.0" resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39" @@ -4780,6 +4787,11 @@ email-templates@^8.0.10: nodemailer "^6.7.2" preview-email "^3.0.5" +email-validator@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-2.0.4.tgz#b8dfaa5d0dae28f1b03c95881d904d4e40bfe7ed" + integrity sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ== + emoji-regex@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.0.1.tgz#77180edb279b99510a21b79b19e1dc283d8f3991" From cc69f66ba9ad0a3f0df4a2fa1c9363ab272ddc9e Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Fri, 10 Jun 2022 12:30:14 +0200 Subject: [PATCH 53/67] chore(.idea folder): removed .idea folder and added it to the .gitignore --- .gitignore | 3 ++ .idea/.gitignore | 8 ---- .idea/codeStyles/Project.xml | 67 ---------------------------- .idea/codeStyles/codeStyleConfig.xml | 5 --- .idea/dataSources.xml | 12 ----- .idea/git_toolbox_prj.xml | 15 ------- .idea/jellyseerr.iml | 12 ----- .idea/modules.xml | 8 ---- .idea/vcs.xml | 6 --- 9 files changed, 3 insertions(+), 133 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/dataSources.xml delete mode 100644 .idea/git_toolbox_prj.xml delete mode 100644 .idea/jellyseerr.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index 7d606105..41a0481f 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ config/db/db.sqlite3-journal # VS Code .vscode/launch.json + +# Webstorm +.idea diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index ff5d00b0..00000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index a12bac1c..00000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - sqlite.xerial - true - org.sqlite.JDBC - jdbc:sqlite:$PROJECT_DIR$/config/db/db.sqlite3 - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/jellyseerr.iml b/.idea/jellyseerr.iml deleted file mode 100644 index 0c8867d7..00000000 --- a/.idea/jellyseerr.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index bb19e753..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From d835336d330abfef5b15bc9febcb748a8154c7df Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Mon, 13 Jun 2022 14:21:05 +0200 Subject: [PATCH 54/67] feat(email validation): email requirement and validation + better importer --- server/lib/notifications/agents/email.ts | 41 ++++++++--- server/routes/user/index.ts | 72 +++++++------------ src/components/Setup/LoginWithPlex.tsx | 2 +- src/components/Setup/SetupLogin.tsx | 2 +- .../UserList/JellyfinImportModal.tsx | 16 +++++ src/components/UserList/index.tsx | 4 +- 6 files changed, 78 insertions(+), 59 deletions(-) diff --git a/server/lib/notifications/agents/email.ts b/server/lib/notifications/agents/email.ts index a1dd7e4e..cbed472f 100644 --- a/server/lib/notifications/agents/email.ts +++ b/server/lib/notifications/agents/email.ts @@ -13,6 +13,7 @@ import { NotificationAgentKey, } from '../../settings'; import { BaseAgent, NotificationAgent, NotificationPayload } from './agent'; +import * as EmailValidator from 'email-validator'; class EmailAgent extends BaseAgent @@ -215,14 +216,23 @@ class EmailAgent this.getSettings(), payload.notifyUser.settings?.pgpKey ); - await email.send( - this.buildMessage( - type, - payload, - payload.notifyUser.email, - payload.notifyUser.displayName - ) - ); + if (EmailValidator.validate(payload.notifyUser.email)) { + await email.send( + this.buildMessage( + type, + payload, + payload.notifyUser.email, + payload.notifyUser.displayName + ) + ); + } else { + logger.warn('Invalid email address provided for user', { + label: 'Notifications', + recipient: payload.notifyUser.displayName, + type: Notification[type], + subject: payload.subject, + }); + } } catch (e) { logger.error('Error sending email notification', { label: 'Notifications', @@ -268,9 +278,18 @@ class EmailAgent this.getSettings(), user.settings?.pgpKey ); - await email.send( - this.buildMessage(type, payload, user.email, user.displayName) - ); + if (EmailValidator.validate(user.email)) { + await email.send( + this.buildMessage(type, payload, user.email, user.displayName) + ); + } else { + logger.warn('Invalid email address provided for user', { + label: 'Notifications', + recipient: user.displayName, + type: Notification[type], + subject: payload.subject, + }); + } } catch (e) { logger.error('Error sending email notification', { label: 'Notifications', diff --git a/server/routes/user/index.ts b/server/routes/user/index.ts index a45391ac..667efca2 100644 --- a/server/routes/user/index.ts +++ b/server/routes/user/index.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; import gravatarUrl from 'gravatar-url'; -import { findIndex, sortBy } from 'lodash'; +import { findIndex, forEach, sortBy } from 'lodash'; import { getRepository, In, Not } from 'typeorm'; import JellyfinAPI from '../../api/jellyfin'; import PlexTvAPI from '../../api/plextv'; @@ -492,62 +492,44 @@ router.post( ); jellyfinClient.setUserId(admin.jellyfinUserId ?? ''); - const jellyfinUsersResponse = await jellyfinClient.getUsers(); + //const jellyfinUsersResponse = await jellyfinClient.getUsers(); const createdUsers: User[] = []; const { hostname, externalHostname } = getSettings().jellyfin; const jellyfinHost = externalHostname && externalHostname.length > 0 ? externalHostname : hostname; - for (const account of jellyfinUsersResponse.users) { - if (account.Name) { - const user = await userRepository - .createQueryBuilder('user') - .where('user.jellyfinUserId = :id', { id: account.Id }) - .orWhere('user.email = :email', { - email: account.Name, - }) - .getOne(); - const avatar = account.PrimaryImageTag - ? `${jellyfinHost}/Users/${account.Id}/Images/Primary/?tag=${account.PrimaryImageTag}&quality=90` - : '/os_logo_square.png'; + forEach(body.jellyfinUserIds, async (jellyfinUserId) => { + jellyfinClient.setUserId(jellyfinUserId); + const jellyfinUser = await jellyfinClient.getUser(); - if (user) { - // Update the user's avatar with their Jellyfin thumbnail, in case it changed - user.avatar = avatar; - user.email = account.Name; - user.jellyfinUsername = account.Name; + const user = await userRepository.findOne({ + select: ['id', 'jellyfinUserId'], + where: { jellyfinUserId: jellyfinUserId }, + }); - // In case the user was previously a local account - if (user.userType === UserType.LOCAL) { - user.userType = UserType.JELLYFIN; - user.jellyfinUserId = account.Id; - } - await userRepository.save(user); - } else if (!body || body.jellyfinUserIds.includes(account.Id)) { - // logger.error('CREATED USER', { - // label: 'API', - // }); + if (!user) { + const newUser = new User({ + jellyfinUsername: jellyfinUser.Name, + jellyfinUserId: jellyfinUser.Id, + jellyfinDeviceId: Buffer.from( + `BOT_jellyseerr_${jellyfinUser.Name ?? ''}` + ).toString('base64'), + email: jellyfinUser.Name, + permissions: settings.main.defaultPermissions, + avatar: jellyfinUser.PrimaryImageTag + ? `${jellyfinHost}/Users/${jellyfinUser.Id}/Images/Primary/?tag=${jellyfinUser.PrimaryImageTag}&quality=90` + : '/os_logo_square.png', + userType: UserType.JELLYFIN, + }); - const newUser = new User({ - jellyfinUsername: account.Name, - jellyfinUserId: account.Id, - jellyfinDeviceId: Buffer.from( - `BOT_overseerr_${account.Name ?? ''}` - ).toString('base64'), - email: account.Name, - permissions: settings.main.defaultPermissions, - avatar, - userType: UserType.JELLYFIN, - }); - await userRepository.save(newUser); - createdUsers.push(newUser); - } + await userRepository.save(newUser); + createdUsers.push(newUser); } - } - return res.status(201).json(User.filterMany(createdUsers)); + return res.status(201).json(User.filterMany(createdUsers)); + }); } catch (e) { next({ status: 500, message: e.message }); } diff --git a/src/components/Setup/LoginWithPlex.tsx b/src/components/Setup/LoginWithPlex.tsx index 90d4425b..4e5a1026 100644 --- a/src/components/Setup/LoginWithPlex.tsx +++ b/src/components/Setup/LoginWithPlex.tsx @@ -5,7 +5,7 @@ import { useUser } from '../../hooks/useUser'; import PlexLoginButton from '../PlexLoginButton'; const messages = defineMessages({ - welcome: 'Welcome to Overseerr', + welcome: 'Welcome to Jellyseerr', signinMessage: 'Get started by signing in with your Plex account', }); diff --git a/src/components/Setup/SetupLogin.tsx b/src/components/Setup/SetupLogin.tsx index d3d581b8..09e48e16 100644 --- a/src/components/Setup/SetupLogin.tsx +++ b/src/components/Setup/SetupLogin.tsx @@ -9,7 +9,7 @@ import { MediaServerType } from '../../../server/constants/server'; import getConfig from 'next/config'; const messages = defineMessages({ - welcome: 'Welcome to Overseerr', + welcome: 'Welcome to Jellyseerr', signinMessage: 'Get started by signing in', signinWithJellyfin: 'Use your {mediaServerName} account', signinWithPlex: 'Use your Plex account', diff --git a/src/components/UserList/JellyfinImportModal.tsx b/src/components/UserList/JellyfinImportModal.tsx index 3e2f7ddf..c3cf12a5 100644 --- a/src/components/UserList/JellyfinImportModal.tsx +++ b/src/components/UserList/JellyfinImportModal.tsx @@ -9,6 +9,7 @@ import globalMessages from '../../i18n/globalMessages'; import Alert from '../Common/Alert'; import Modal from '../Common/Modal'; import getConfig from 'next/config'; +import { UserResultsResponse } from '../../../server/interfaces/api/userInterfaces'; interface JellyfinImportProps { onCancel?: () => void; @@ -30,6 +31,7 @@ const messages = defineMessages({ const JellyfinImportModal: React.FC = ({ onCancel, onComplete, + children, }) => { const intl = useIntl(); const settings = useSettings(); @@ -117,6 +119,20 @@ const JellyfinImportModal: React.FC = ({ } }; + const { data: existingUsers } = useSWR( + `/api/v1/user?take=${children}` + ); + + data?.forEach((user, pos) => { + if ( + existingUsers?.results.some( + (existingUser) => existingUser.jellyfinUserId === user.id + ) + ) { + delete data[pos]; + } + }); + return ( { setShowImportModal(false); revalidate(); }} - /> + > + {data.pageInfo.results} + )} From a483ca9837e12e2385d0e2407e52d6c64ae435e2 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Mon, 13 Jun 2022 21:34:51 +0200 Subject: [PATCH 55/67] fix(jellyfinimportmodal): fix for importing all jellyfin users --- .../UserList/JellyfinImportModal.tsx | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/components/UserList/JellyfinImportModal.tsx b/src/components/UserList/JellyfinImportModal.tsx index c3cf12a5..c57e0651 100644 --- a/src/components/UserList/JellyfinImportModal.tsx +++ b/src/components/UserList/JellyfinImportModal.tsx @@ -51,6 +51,18 @@ const JellyfinImportModal: React.FC = ({ revalidateOnMount: true, }); + const { data: existingUsers } = useSWR( + `/api/v1/user?take=${children}` + ); + + data?.forEach((user, pos) => { + if ( + existingUsers?.results.some((data) => data.jellyfinUserId === user.id) + ) { + data?.splice(pos, 1); + } + }); + const importUsers = async () => { setImporting(true); @@ -119,20 +131,6 @@ const JellyfinImportModal: React.FC = ({ } }; - const { data: existingUsers } = useSWR( - `/api/v1/user?take=${children}` - ); - - data?.forEach((user, pos) => { - if ( - existingUsers?.results.some( - (existingUser) => existingUser.jellyfinUserId === user.id - ) - ) { - delete data[pos]; - } - }); - return ( Date: Tue, 14 Jun 2022 00:48:17 +0500 Subject: [PATCH 56/67] fix(ui): fixed translation issue where it showed as import {mediaServerName} user Fixed translation issue where it showed as import {mediaServerName} user as it was using the same variable both inside the plex import modal and also outside in userlist on the button --- src/components/UserList/index.tsx | 10 +++++----- src/i18n/locale/ca.json | 1 + src/i18n/locale/da.json | 1 + src/i18n/locale/de.json | 1 + src/i18n/locale/el.json | 1 + src/i18n/locale/en.json | 1 + src/i18n/locale/es.json | 1 + src/i18n/locale/fr.json | 1 + src/i18n/locale/hu.json | 1 + src/i18n/locale/it.json | 1 + src/i18n/locale/ja.json | 1 + src/i18n/locale/nb_NO.json | 1 + src/i18n/locale/nl.json | 3 ++- src/i18n/locale/pl.json | 1 + src/i18n/locale/pt_BR.json | 1 + src/i18n/locale/pt_PT.json | 1 + src/i18n/locale/ru.json | 1 + src/i18n/locale/sq.json | 1 + src/i18n/locale/sv.json | 1 + src/i18n/locale/zh_Hans.json | 1 + src/i18n/locale/zh_Hant.json | 1 + 21 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx index ff5ad97e..ce925cf0 100644 --- a/src/components/UserList/index.tsx +++ b/src/components/UserList/index.tsx @@ -9,6 +9,7 @@ import { } from '@heroicons/react/solid'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; +import getConfig from 'next/config'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; @@ -36,12 +37,11 @@ import Transition from '../Transition'; import BulkEditModal from './BulkEditModal'; import JellyfinImportModal from './JellyfinImportModal'; import PlexImportModal from './PlexImportModal'; -import getConfig from 'next/config'; const messages = defineMessages({ users: 'Users', userlist: 'User List', - importfromplex: 'Import {mediaServerName} Users', + importfrommediaserver: 'Import {mediaServerName} Users', user: 'User', totalrequests: 'Requests', accounttype: 'Type', @@ -506,15 +506,15 @@ const UserList: React.FC = () => { {publicRuntimeConfig.JELLYFIN_TYPE == 'emby' - ? intl.formatMessage(messages.importfromplex, { + ? intl.formatMessage(messages.importfrommediaserver, { mediaServerName: 'Emby', }) : settings.currentSettings.mediaServerType === MediaServerType.PLEX - ? intl.formatMessage(messages.importfromplex, { + ? intl.formatMessage(messages.importfrommediaserver, { mediaServerName: 'Plex', }) - : intl.formatMessage(messages.importfromplex, { + : intl.formatMessage(messages.importfrommediaserver, { mediaServerName: 'Jellyfin', })} diff --git a/src/i18n/locale/ca.json b/src/i18n/locale/ca.json index 027f4c5c..3e129ed0 100644 --- a/src/i18n/locale/ca.json +++ b/src/i18n/locale/ca.json @@ -686,6 +686,7 @@ "components.UserList.nouserstoimport": "No hi ha usuaris nous de Plex a importar.", "components.UserList.localuser": "Usuari local", "components.UserList.importfromplexerror": "S'ha produït un error en importar usuaris de Plex.", + "components.UserList.importfrommediaserver": "Importeu usuaris de {mediaServerName}", "components.UserList.importfromplex": "Importeu usuaris de Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {usuari} other {usuaris}} de Plex importat correctament!", "components.TvDetails.watchtrailer": "Veure el tràiler", diff --git a/src/i18n/locale/da.json b/src/i18n/locale/da.json index e472beed..3c61ac18 100644 --- a/src/i18n/locale/da.json +++ b/src/i18n/locale/da.json @@ -850,6 +850,7 @@ "components.UserList.nouserstoimport": "Ingen nye brugere som kan importeres fra Plex.", "components.UserList.edituser": "Redigér Brugertilladelser", "components.UserList.email": "Email Adresse", + "components.UserList.importfrommediaserver": "Importér Brugere fra {mediaServerName}", "components.UserList.importfromplex": "Importér Brugere fra Plex", "components.UserList.owner": "Ejer", "components.UserList.password": "Kodeord", diff --git a/src/i18n/locale/de.json b/src/i18n/locale/de.json index a2454f28..56b2ce09 100644 --- a/src/i18n/locale/de.json +++ b/src/i18n/locale/de.json @@ -223,6 +223,7 @@ "components.Settings.SettingsAbout.Releases.latestversion": "Neuste", "components.Settings.SettingsAbout.Releases.currentversion": "Aktuell", "components.UserList.importfromplexerror": "Beim Importieren von Plex-Benutzern ist etwas schief gelaufen.", + "components.UserList.importfrommediaserver": "{mediaServerName}-Benutzer importieren", "components.UserList.importfromplex": "Plex-Benutzer importieren", "components.TvDetails.viewfullcrew": "Komplette Crew anzeigen", "components.TvDetails.TvCrew.fullseriescrew": "Komplette Serien-Crew", diff --git a/src/i18n/locale/el.json b/src/i18n/locale/el.json index 9355f5d6..57784c73 100644 --- a/src/i18n/locale/el.json +++ b/src/i18n/locale/el.json @@ -602,6 +602,7 @@ "components.UserList.localuser": "Τοπικός χρήστης", "components.UserList.localLoginDisabled": "Η ρύθμιση Ενεργοποίηση τοπικής σύνδεσης είναι προς το παρόν απενεργοποιημένη.", "components.UserList.importfromplexerror": "Κάτι πήγε στραβά κατά την εισαγωγή χρηστών από το Plex.", + "components.UserList.importfrommediaserver": "Εισαγωγή χρηστών από το {mediaServerName}", "components.UserList.importfromplex": "Εισαγωγή χρηστών από το Plex", "components.UserList.importedfromplex": "{userCount, plural, one {# νέου χρήστη} other {#νέοι χρήστες}} εισήχθησαν απο το Plex επιτυχώς!", "components.UserList.email": "Διεύθυνση ηλεκτρονικού ταχυδρομείου", diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index b6f38832..c809b406 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -861,6 +861,7 @@ "components.UserList.edituser": "Edit User Permissions", "components.UserList.email": "Email Address", "components.UserList.importedfromplex": "{userCount} Plex {userCount, plural, one {user} other {users}} imported successfully!", + "components.UserList.importfrommediaserver": "Import {mediaServerName} Users", "components.UserList.importfromplex": "Import Plex Users", "components.UserList.importfromplexerror": "Something went wrong while importing Plex users.", "components.UserList.localLoginDisabled": "The Enable Local Sign-In setting is currently disabled.", diff --git a/src/i18n/locale/es.json b/src/i18n/locale/es.json index e1ff1be0..3f414d27 100644 --- a/src/i18n/locale/es.json +++ b/src/i18n/locale/es.json @@ -223,6 +223,7 @@ "components.Settings.SettingsAbout.Releases.currentversion": "Actual", "components.MovieDetails.studio": "{studioCount, plural, one {Estudio} other {Estudios}}", "components.UserList.importfromplexerror": "Algo salió mal importando usuarios de Plex.", + "components.UserList.importfrommediaserver": "Importar Usuarios de {mediaServerName}", "components.UserList.importfromplex": "Importar Usuarios de Plex", "components.UserList.importedfromplex": "¡{userCount, plural, one {# nuevo usuario} other {# nuevos usuarios}} importado/s de Plex con éxito!", "components.TvDetails.viewfullcrew": "Ver Equipo Completo", diff --git a/src/i18n/locale/fr.json b/src/i18n/locale/fr.json index 8099c7a2..22d8af98 100644 --- a/src/i18n/locale/fr.json +++ b/src/i18n/locale/fr.json @@ -223,6 +223,7 @@ "components.Settings.SettingsAbout.Releases.latestversion": "Dernière version", "components.Settings.SettingsAbout.Releases.currentversion": "Actuelle", "components.UserList.importfromplexerror": "Une erreur s'est produite durant l'importation des utilisateurs de Plex.", + "components.UserList.importfrommediaserver": "Importer les utilisateurs de {mediaServerName}", "components.UserList.importfromplex": "Importer les utilisateurs de Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {utilisateur} other {utilisateurs}} importé(s) depuis Plex avec succès !", "components.TvDetails.viewfullcrew": "Voir l'équipe complète de la série", diff --git a/src/i18n/locale/hu.json b/src/i18n/locale/hu.json index d04a9dc8..9a1f28c8 100644 --- a/src/i18n/locale/hu.json +++ b/src/i18n/locale/hu.json @@ -165,6 +165,7 @@ "components.UserList.password": "Jelszó", "components.UserList.localuser": "Helyi felhasználó", "components.UserList.importfromplexerror": "Hiba történt a felhasználók Plex-ről történő importálása közben.", + "components.UserList.importfrommediaserver": "Felhasználók importálása {mediaServerName}-ről", "components.UserList.importfromplex": "Felhasználók importálása Plex-ről", "components.UserList.importedfromplex": "{userCount, plural, =0 {Nem lett új} one {# új} other {# új}} felhasználó importálva Plex-ről!", "components.UserList.email": "E-mail-cím", diff --git a/src/i18n/locale/it.json b/src/i18n/locale/it.json index dea1ddd8..7d4cef42 100644 --- a/src/i18n/locale/it.json +++ b/src/i18n/locale/it.json @@ -223,6 +223,7 @@ "components.Settings.SettingsAbout.Releases.latestversion": "Versione più recente", "components.Settings.SettingsAbout.Releases.currentversion": "Versione attuale", "components.UserList.importfromplexerror": "Qualcosa è andato storto nell'importare gli utenti Plex.", + "components.UserList.importfrommediaserver": "Importa utenti {mediaServerName}", "components.UserList.importfromplex": "Importa utenti Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {utente} other {utenti}} Plex {userCount, plural, one {importato} other {importati}} correttamente!", "components.TvDetails.viewfullcrew": "Vedi troupe completa", diff --git a/src/i18n/locale/ja.json b/src/i18n/locale/ja.json index f3fe3413..f8386008 100644 --- a/src/i18n/locale/ja.json +++ b/src/i18n/locale/ja.json @@ -231,6 +231,7 @@ "components.TvDetails.watchtrailer": "予告編を見る", "components.MovieDetails.watchtrailer": "予告編を見る", "components.UserList.importfromplexerror": "Plexからユーザーをインポート中に問題が発生しました。", + "components.UserList.importfrommediaserver": "{mediaServerName}からユーザーをインポート", "components.UserList.importfromplex": "Plexからユーザーをインポート", "components.UserList.importedfromplex": "Plex から新ユーザー {userCount} 名をインポートしました。", "components.TvDetails.viewfullcrew": "フルクルーを表示", diff --git a/src/i18n/locale/nb_NO.json b/src/i18n/locale/nb_NO.json index 61539a64..07d5a664 100644 --- a/src/i18n/locale/nb_NO.json +++ b/src/i18n/locale/nb_NO.json @@ -194,6 +194,7 @@ "components.UserList.userssaved": "Brukertillatelsene ble lagret!", "components.UserList.users": "Brukere", "components.UserList.importfromplexerror": "Noe gikk galt ved importering av brukere fra Plex.", + "components.UserList.importfrommediaserver": "Importer brukere fra {mediaServerName}", "components.UserList.importfromplex": "Importer brukere fra Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {ny bruker} other {nye brukere}} ble importert fra Plex!", "components.Settings.menuUsers": "Brukere", diff --git a/src/i18n/locale/nl.json b/src/i18n/locale/nl.json index 9d61ec7d..077a31a9 100644 --- a/src/i18n/locale/nl.json +++ b/src/i18n/locale/nl.json @@ -214,7 +214,8 @@ "components.UserList.userdeleteerror": "Er ging iets mis bij het verwijderen van de gebruiker.", "components.UserList.userdeleted": "Gebruiker succesvol verwijderd!", "components.UserList.importfromplexerror": "Er is iets misgegaan bij het importeren van Plex-gebruikers.", - "components.UserList.importfromplex": "Plex-gebruikers importeren", + "components.UserList.importfrommediaserver": "{mediaServerName}-gebruikers importeren", + "components.UserList.importfromplex": "{mediaServerName}-gebruikers importeren", "components.UserList.deleteuser": "Gebruiker verwijderen", "components.UserList.deleteconfirm": "Weet je zeker dat je deze gebruiker wilt verwijderen? Al hun bestaande aanvraaggegevens zullen worden verwijderd.", "components.TvDetails.watchtrailer": "Trailer bekijken", diff --git a/src/i18n/locale/pl.json b/src/i18n/locale/pl.json index 1a3eefb9..597147d5 100644 --- a/src/i18n/locale/pl.json +++ b/src/i18n/locale/pl.json @@ -962,6 +962,7 @@ "components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "Wyślij po cichu", "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingsfailed": "Nie udało się zapisać ustawień powiadomień telegram.", "components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "Wielocyfrowy numer ID powiązany z Twoim kontem użytkownika", + "components.UserList.importfrommediaserver": "Importuj użytkowników {mediaServerName}", "components.UserList.importfromplex": "Importuj użytkowników Plex", "i18n.available": "Dostępny", "components.UserList.sortDisplayName": "Wyświetlana nazwa", diff --git a/src/i18n/locale/pt_BR.json b/src/i18n/locale/pt_BR.json index c99ebb02..3d200e45 100644 --- a/src/i18n/locale/pt_BR.json +++ b/src/i18n/locale/pt_BR.json @@ -228,6 +228,7 @@ "components.MovieDetails.viewfullcrew": "Ver Equipe Técnica Completa", "components.MovieDetails.MovieCrew.fullcrew": "Equipe Técnica Completa", "components.UserList.importfromplexerror": "Algo deu errado ao importar usuários do Plex.", + "components.UserList.importfrommediaserver": "Importar Usuários do {mediaServerName}", "components.UserList.importfromplex": "Importar Usuários do Plex", "components.UserList.importedfromplex": "{userCount} {userCount, plural, one {usuário Plex importado} other {usuários Plex importados}} com sucesso!", "components.Settings.Notifications.NotificationsSlack.agentenabled": "Habilitar Agente", diff --git a/src/i18n/locale/pt_PT.json b/src/i18n/locale/pt_PT.json index 4bcad9f5..7591a4da 100644 --- a/src/i18n/locale/pt_PT.json +++ b/src/i18n/locale/pt_PT.json @@ -199,6 +199,7 @@ "components.UserList.passwordinfodescription": "Configurar um URL de aplicação e ativar as notificações por e-mail para permitir a geração automática de palavra-passe.", "components.UserList.localuser": "Utilizador Local", "components.UserList.importfromplexerror": "Ocorreu um erro ao importar utilizadores do Plex.", + "components.UserList.importfrommediaserver": "Importar Utilizadores do {mediaServerName}", "components.UserList.importfromplex": "Importar Utilizadores do Plex", "components.UserList.importedfromplex": "{userCount, plural, one {# novo utilizador} other {# novos utilizadores}} importados do Plex com sucesso!", "components.UserList.email": "Endereço de E-mail", diff --git a/src/i18n/locale/ru.json b/src/i18n/locale/ru.json index bf36dbb6..9ba93e55 100644 --- a/src/i18n/locale/ru.json +++ b/src/i18n/locale/ru.json @@ -793,6 +793,7 @@ "components.UserList.usercreatedfailed": "Что-то пошло не так при создании пользователя.", "components.UserList.passwordinfodescription": "Настройте URL-адрес приложения и включите уведомления по электронной почте, чтобы обеспечить возможность автоматической генерации пароля.", "components.UserList.importfromplexerror": "Что-то пошло не так при импорте пользователей из Plex.", + "components.UserList.importfrommediaserver": "Импортировать пользователей из {mediaServerName}", "components.UserList.importfromplex": "Импортировать пользователей из Plex", "components.UserList.importedfromplex": "{userCount, plural, one {# новый пользователь} other {# новых пользователя(ей)}} успешно импортированы из Plex!", "components.UserList.edituser": "Изменить разрешения пользователя", diff --git a/src/i18n/locale/sq.json b/src/i18n/locale/sq.json index 3c63691e..627d2732 100644 --- a/src/i18n/locale/sq.json +++ b/src/i18n/locale/sq.json @@ -1006,6 +1006,7 @@ "components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "Diçka shkoi keq duke ruajtur cilësimet.", "components.Settings.webAppUrlTip": "Në mënyrë opsionale drejto përdoruesit në aplikacionin web në serverin tënd në vend të atij web", "components.TvDetails.episodeRuntimeMinutes": "{runtime} minuta", + "components.UserList.importfrommediaserver": "Importoni përdoruesit {mediaServerName}", "components.UserList.importfromplex": "Importoni përdoruesit Plex", "components.UserList.importfromplexerror": "Diçka shkoi keq duke importuar përdoruesit Plex.", "components.TvDetails.firstAirDate": "Data e parë e transmetimit", diff --git a/src/i18n/locale/sv.json b/src/i18n/locale/sv.json index bdbb4bbd..36247bd4 100644 --- a/src/i18n/locale/sv.json +++ b/src/i18n/locale/sv.json @@ -222,6 +222,7 @@ "components.Settings.SettingsAbout.Releases.releasedataMissing": "Versionsdata är för närvarande inte tillgänglig.", "components.Settings.SettingsAbout.Releases.latestversion": "Senaste Versionen", "components.Settings.SettingsAbout.Releases.currentversion": "Aktuell", + "components.UserList.importfrommediaserver": "Importera {mediaServerName}användare", "components.UserList.importfromplex": "Importera Plexanvändare", "components.UserList.importfromplexerror": "Något gick fel när Plexanvändare importerades.", "components.TvDetails.watchtrailer": "Kolla Trailer", diff --git a/src/i18n/locale/zh_Hans.json b/src/i18n/locale/zh_Hans.json index 16b29ad7..9ef29adb 100644 --- a/src/i18n/locale/zh_Hans.json +++ b/src/i18n/locale/zh_Hans.json @@ -24,6 +24,7 @@ "components.UserList.localuser": "本地用户", "components.UserList.localLoginDisabled": "允许本地登录的设置目前被禁用。", "components.UserList.importfromplexerror": "导入 Plex 用户时出错。", + "components.UserList.importfrommediaserver": "导入 {mediaServerName} 用户", "components.UserList.importfromplex": "导入 Plex 用户", "components.UserList.importedfromplex": "{userCount} Plex {userCount, plural, one {user} other {users}} 成功导入!", "components.UserList.email": "电子邮件地址", diff --git a/src/i18n/locale/zh_Hant.json b/src/i18n/locale/zh_Hant.json index d18433bb..85293a06 100644 --- a/src/i18n/locale/zh_Hant.json +++ b/src/i18n/locale/zh_Hant.json @@ -52,6 +52,7 @@ "components.Settings.radarrsettings": "Radarr 設定", "components.Settings.menuPlexSettings": "Plex", "components.UserList.importfromplexerror": "匯入 Plex 使用者時出了點問題。", + "components.UserList.importfrommediaserver": "匯入 {mediaServerName} 使用者", "components.UserList.importfromplex": "匯入 Plex 使用者", "components.UserList.importedfromplex": "匯入 {userCount} 個 Plex 使用者成功!", "components.UserList.localuser": "本地使用者", From d417fcafa1e38c6d56ed8360ae451e8b8ff82a8d Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Tue, 14 Jun 2022 00:51:44 +0500 Subject: [PATCH 57/67] fix(ui): replaced {mediaServerName} in the plex variable in NL locale replaced {mediaServerName} in the plex variable in NL locale --- src/i18n/locale/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/locale/nl.json b/src/i18n/locale/nl.json index 077a31a9..0d7c8468 100644 --- a/src/i18n/locale/nl.json +++ b/src/i18n/locale/nl.json @@ -215,7 +215,7 @@ "components.UserList.userdeleted": "Gebruiker succesvol verwijderd!", "components.UserList.importfromplexerror": "Er is iets misgegaan bij het importeren van Plex-gebruikers.", "components.UserList.importfrommediaserver": "{mediaServerName}-gebruikers importeren", - "components.UserList.importfromplex": "{mediaServerName}-gebruikers importeren", + "components.UserList.importfromplex": "Plex-gebruikers importeren", "components.UserList.deleteuser": "Gebruiker verwijderen", "components.UserList.deleteconfirm": "Weet je zeker dat je deze gebruiker wilt verwijderen? Al hun bestaande aanvraaggegevens zullen worden verwijderd.", "components.TvDetails.watchtrailer": "Trailer bekijken", From 29478fc19534589db37499f1cdcc21ea4d389a74 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Mon, 13 Jun 2022 23:13:22 +0200 Subject: [PATCH 58/67] fix(import all): fis for import all --- server/routes/user/index.ts | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/server/routes/user/index.ts b/server/routes/user/index.ts index 667efca2..5811fc05 100644 --- a/server/routes/user/index.ts +++ b/server/routes/user/index.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; import gravatarUrl from 'gravatar-url'; -import { findIndex, forEach, sortBy } from 'lodash'; +import { findIndex, sortBy } from 'lodash'; import { getRepository, In, Not } from 'typeorm'; import JellyfinAPI from '../../api/jellyfin'; import PlexTvAPI from '../../api/plextv'; @@ -500,9 +500,13 @@ router.post( ? externalHostname : hostname; - forEach(body.jellyfinUserIds, async (jellyfinUserId) => { - jellyfinClient.setUserId(jellyfinUserId); - const jellyfinUser = await jellyfinClient.getUser(); + jellyfinClient.setUserId(admin.jellyfinUserId ?? ''); + const jellyfinUsers = await jellyfinClient.getUsers(); + + for (const jellyfinUserId of body.jellyfinUserIds) { + const jellyfinUser = jellyfinUsers.users.find( + (user) => user.Id === jellyfinUserId + ); const user = await userRepository.findOne({ select: ['id', 'jellyfinUserId'], @@ -511,14 +515,14 @@ router.post( if (!user) { const newUser = new User({ - jellyfinUsername: jellyfinUser.Name, - jellyfinUserId: jellyfinUser.Id, + jellyfinUsername: jellyfinUser?.Name, + jellyfinUserId: jellyfinUser?.Id, jellyfinDeviceId: Buffer.from( - `BOT_jellyseerr_${jellyfinUser.Name ?? ''}` + `BOT_jellyseerr_${jellyfinUser?.Name ?? ''}` ).toString('base64'), - email: jellyfinUser.Name, + email: jellyfinUser?.Name, permissions: settings.main.defaultPermissions, - avatar: jellyfinUser.PrimaryImageTag + avatar: jellyfinUser?.PrimaryImageTag ? `${jellyfinHost}/Users/${jellyfinUser.Id}/Images/Primary/?tag=${jellyfinUser.PrimaryImageTag}&quality=90` : '/os_logo_square.png', userType: UserType.JELLYFIN, @@ -527,9 +531,8 @@ router.post( await userRepository.save(newUser); createdUsers.push(newUser); } - - return res.status(201).json(User.filterMany(createdUsers)); - }); + } + return res.status(201).json(User.filterMany(createdUsers)); } catch (e) { next({ status: 500, message: e.message }); } From e1081a7bc2fb10e58ed24a7d052571dcfb15a210 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sat, 18 Jun 2022 22:30:15 +0200 Subject: [PATCH 59/67] Create private_registery_push.yml --- .github/workflows/private_registery_push.yml | 41 ++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/private_registery_push.yml diff --git a/.github/workflows/private_registery_push.yml b/.github/workflows/private_registery_push.yml new file mode 100644 index 00000000..b3f88873 --- /dev/null +++ b/.github/workflows/private_registery_push.yml @@ -0,0 +1,41 @@ +name: 'create docker image on pull request' +on: + pull_request: + branches: [ develop ] + + workflow_dispatch: + +jobs: + build-image: + name: Tag and release alpha image on private repo + runs-on: self-hosted + env: + HUSKY: 0 + steps: + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - + name: Login to private registery + uses: docker/login-action@v1 + with: + registry: ${{ secrets.REGISTRY_URL }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - + name: Build and push + uses: docker/build-push-action@v2 + with: + context: ./ + file: ./Dockerfile + builder: ${{ steps.buildx.outputs.name }} + push: true + tags: '${{ secrets.REGISTRY_URL }}/Fallenbagel/jellyseerr:${{ github.sha }}' + cache-from: 'type=registry,ref=${{ secrets.REGISTRY_URL }}/Fallenbagel/jellyseerr:buildcache' + cache-to: 'type=registry,ref=${{ secrets.REGISTRY_URL }}/Fallenbagel/jellyseerr:buildcache,mode=max' From 89e8825b6121fb889a15a3754e91e9670569f6b3 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sat, 18 Jun 2022 22:39:24 +0200 Subject: [PATCH 60/67] fixes indent issues --- .github/workflows/private_registery_push.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/private_registery_push.yml b/.github/workflows/private_registery_push.yml index b3f88873..224ce34c 100644 --- a/.github/workflows/private_registery_push.yml +++ b/.github/workflows/private_registery_push.yml @@ -1,17 +1,15 @@ -name: 'create docker image on pull request' -on: - pull_request: - branches: [ develop ] +name: 'create docker image on pull request and push to private registery' - workflow_dispatch: +on: + pull_request: + branches: + - develop + workflow_dispatch: jobs: - build-image: - name: Tag and release alpha image on private repo - runs-on: self-hosted - env: - HUSKY: 0 - steps: + build-image: + runs-on: self-hosted + steps: - name: Checkout uses: actions/checkout@v2 From 31072f475807b1fc4d4b0616b2044ca1d4f3aefd Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sat, 18 Jun 2022 22:45:43 +0200 Subject: [PATCH 61/67] Update private_registery_push.yml --- .github/workflows/private_registery_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/private_registery_push.yml b/.github/workflows/private_registery_push.yml index 224ce34c..648aebb1 100644 --- a/.github/workflows/private_registery_push.yml +++ b/.github/workflows/private_registery_push.yml @@ -20,7 +20,7 @@ jobs: - name: Login to private registery - uses: docker/login-action@v1 + uses: docker/login-action@v2.0.0 with: registry: ${{ secrets.REGISTRY_URL }} username: ${{ secrets.REGISTRY_USERNAME }} From d3cea69011a7b2ee9b066418aea9a961e71d6167 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sat, 18 Jun 2022 22:48:47 +0200 Subject: [PATCH 62/67] Update private_registery_push.yml --- .github/workflows/private_registery_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/private_registery_push.yml b/.github/workflows/private_registery_push.yml index 648aebb1..262067b8 100644 --- a/.github/workflows/private_registery_push.yml +++ b/.github/workflows/private_registery_push.yml @@ -22,7 +22,7 @@ jobs: name: Login to private registery uses: docker/login-action@v2.0.0 with: - registry: ${{ secrets.REGISTRY_URL }} + registry: https://${{ secrets.REGISTRY_URL }} username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} From 63b7be0a384132cc397c402a5b6105c21567ddc3 Mon Sep 17 00:00:00 2001 From: Nicolai Van der Storm Date: Sat, 18 Jun 2022 22:55:07 +0200 Subject: [PATCH 63/67] Update private_registery_push.yml --- .github/workflows/private_registery_push.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/private_registery_push.yml b/.github/workflows/private_registery_push.yml index 262067b8..376223c7 100644 --- a/.github/workflows/private_registery_push.yml +++ b/.github/workflows/private_registery_push.yml @@ -22,7 +22,7 @@ jobs: name: Login to private registery uses: docker/login-action@v2.0.0 with: - registry: https://${{ secrets.REGISTRY_URL }} + registry: ${{ secrets.REGISTRY_URL }} username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} @@ -34,6 +34,6 @@ jobs: file: ./Dockerfile builder: ${{ steps.buildx.outputs.name }} push: true - tags: '${{ secrets.REGISTRY_URL }}/Fallenbagel/jellyseerr:${{ github.sha }}' - cache-from: 'type=registry,ref=${{ secrets.REGISTRY_URL }}/Fallenbagel/jellyseerr:buildcache' - cache-to: 'type=registry,ref=${{ secrets.REGISTRY_URL }}/Fallenbagel/jellyseerr:buildcache,mode=max' + tags: '${{ secrets.REGISTRY_URL }}/fallenbagel/jellyseerr:${{ github.sha }}' + cache-from: 'type=registry,ref=${{ secrets.REGISTRY_URL }}/fallenbagel/jellyseerr:buildcache' + cache-to: 'type=registry,ref=${{ secrets.REGISTRY_URL }}/fallenbagel/jellyseerr:buildcache,mode=max' From 8810c20fc18a55c2f6768ddc40830a8494946072 Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Sun, 19 Jun 2022 22:27:38 +0500 Subject: [PATCH 64/67] fix(setup&login): fix a description error in the manual scan in setup and add emby to login page Manual scan in setup says "Jellyfin will scan your Jellyfin's server" and same with emby, so I replaced jellyfin with jellyseerr. And also added emby to login page --- src/components/Login/index.tsx | 11 +++++++++-- src/components/Settings/SettingsJellyfin.tsx | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/Login/index.tsx b/src/components/Login/index.tsx index 5d3e7a3d..eb8f368b 100644 --- a/src/components/Login/index.tsx +++ b/src/components/Login/index.tsx @@ -15,12 +15,13 @@ import PlexLoginButton from '../PlexLoginButton'; import Transition from '../Transition'; import JellyfinLogin from './JellyfinLogin'; import LocalLogin from './LocalLogin'; +import getConfig from 'next/config'; const messages = defineMessages({ signin: 'Sign In', signinheader: 'Sign in to continue', signinwithplex: 'Use your Plex account', - signinwithjellyfin: 'Use your Jellyfin account', + signinwithjellyfin: 'Use your {mediaServerName} account', signinwithoverseerr: 'Use your {applicationTitle} account', }); @@ -32,6 +33,7 @@ const Login: React.FC = () => { const { user, revalidate } = useUser(); const router = useRouter(); const settings = useSettings(); + const { publicRuntimeConfig } = getConfig(); // Effect that is triggered when the `authToken` comes back from the Plex OAuth // We take the token and attempt to sign in. If we get a success message, we will @@ -133,7 +135,12 @@ const Login: React.FC = () => { {settings.currentSettings.mediaServerType == MediaServerType.PLEX ? intl.formatMessage(messages.signinwithplex) - : intl.formatMessage(messages.signinwithjellyfin)} + : intl.formatMessage(messages.signinwithjellyfin, { + mediaServerName: + publicRuntimeConfig.JELLYFIN_TYPE == 'emby' + ? 'Emby' + : 'Jellyfin', + })}
    diff --git a/src/components/Settings/SettingsJellyfin.tsx b/src/components/Settings/SettingsJellyfin.tsx index 4974c84b..ec98f3e7 100644 --- a/src/components/Settings/SettingsJellyfin.tsx +++ b/src/components/Settings/SettingsJellyfin.tsx @@ -36,7 +36,7 @@ const messages = defineMessages({ syncJellyfin: 'Sync Libraries', manualscanJellyfin: 'Manual Library Scan', manualscanDescriptionJellyfin: - "Normally, this will only be run once every 24 hours. {mediaServerName} will check your {mediaServerName} server's recently added more aggressively. If this is your first time configuring {mediaServerName}, a one-time full manual library scan is recommended!", + "Normally, this will only be run once every 24 hours. Jellyseerr will check your {mediaServerName} server's recently added more aggressively. If this is your first time configuring {mediaServerName}, a one-time full manual library scan is recommended!", notrunning: 'Not Running', currentlibrary: 'Current Library: {name}', librariesRemaining: 'Libraries Remaining: {count}', From 927511916306c12eda4280771bfd9828a383a3cb Mon Sep 17 00:00:00 2001 From: jab416171 Date: Sun, 19 Jun 2022 12:28:09 -0600 Subject: [PATCH 65/67] change email sender name to Jellyseerr on initial setup --- server/lib/settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 953fc3d0..53fe864c 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -345,7 +345,7 @@ class Settings { ignoreTls: false, requireTls: false, allowSelfSigned: false, - senderName: 'Overseerr', + senderName: 'Jellyseerr', }, }, discord: { From ae60d44f997a0b46b9099c70fa6ed22350b9893d Mon Sep 17 00:00:00 2001 From: jab416171 Date: Sun, 19 Jun 2022 12:38:49 -0600 Subject: [PATCH 66/67] Fix text for manual library scan --- src/components/Settings/SettingsJellyfin.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Settings/SettingsJellyfin.tsx b/src/components/Settings/SettingsJellyfin.tsx index ec98f3e7..a8cd2627 100644 --- a/src/components/Settings/SettingsJellyfin.tsx +++ b/src/components/Settings/SettingsJellyfin.tsx @@ -36,7 +36,7 @@ const messages = defineMessages({ syncJellyfin: 'Sync Libraries', manualscanJellyfin: 'Manual Library Scan', manualscanDescriptionJellyfin: - "Normally, this will only be run once every 24 hours. Jellyseerr will check your {mediaServerName} server's recently added more aggressively. If this is your first time configuring {mediaServerName}, a one-time full manual library scan is recommended!", + "Normally, this will only be run once every 24 hours. Jellyseerr will check your {mediaServerName} server's recently added more aggressively. If this is your first time configuring Jellyseerr, a one-time full manual library scan is recommended!", notrunning: 'Not Running', currentlibrary: 'Current Library: {name}', librariesRemaining: 'Libraries Remaining: {count}', From a5e6217f85646b8f8505e428161dbaf040faed91 Mon Sep 17 00:00:00 2001 From: Fallenbagel <98979876+Fallenbagel@users.noreply.github.com> Date: Mon, 20 Jun 2022 17:36:13 +0500 Subject: [PATCH 67/67] Changed run-on to self-hosted to speed up release process --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e36f8100..2ae294d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,7 +5,7 @@ on: workflow_dispatch jobs: semantic-release: name: Tag and release latest version - runs-on: ubuntu-20.04 + runs-on: self-hosted env: HUSKY: 0 steps: @@ -39,7 +39,7 @@ jobs: name: Send Discord Notification needs: semantic-release if: always() - runs-on: ubuntu-20.04 + runs-on: self-hosted steps: - name: Get Build Job Status uses: technote-space/workflow-conclusion-action@v2