Compare commits

..

1 Commits

Author SHA1 Message Date
fallenbagel
cb672ec3c4 docs: temporarily make it clear seerr is not released 2026-01-03 04:49:39 +05:00
10 changed files with 43 additions and 162 deletions

View File

@@ -45,12 +45,12 @@ The documentation linked above is for running the **latest Jellyseerr** release.
> [!WARNING]
> If you are migrating from **Overseerr** to **Seerr** for beta testing, **do not follow the Jellyseerr latest setup guide**.
Instead, follow the dedicated migration guide (with `:develop` tag):
Instead, follow the dedicated migration guide:
https://github.com/seerr-team/seerr/blob/develop/docs/migration-guide.mdx
> [!CAUTION]
> **DO NOT run Jellyseerr (latest) using an existing Overseerr database. This includes third-party images with `seerr:latest` (as it points to jellyseerr 2.7.3 and not seerr.**
> Doing so **may cause database corruption and/or irreversible data loss and/or weird unintended behaviour**.
> [!DANGER]
> **DO NOT run Jellyseerr (latest) using an existing Overseerr database.**
> Doing so **will cause database corruption and/or irreversible data loss**.
For migration assistance, beta testing questions, or troubleshooting, please join our **Discord** and ask for support there.

View File

@@ -666,16 +666,6 @@ class AvailabilitySync {
): Promise<boolean> {
let existsInRadarr = false;
if (is4k && media.status4k === MediaStatus.AVAILABLE) {
logger.debug(
`Checking if 4K movie [TMDB ID ${media.tmdbId}] exists in Radarr`,
{
label: 'AvailabilitySync',
externalServiceId4k: media.externalServiceId4k,
}
);
}
// Check for availability in all of the available radarr servers
// If any find the media, we will assume the media exists
for (const server of this.radarrServers.filter(
@@ -880,32 +870,6 @@ class AvailabilitySync {
this.plexSeasonsCache[ratingKey4k] =
await this.plexClient?.getChildrenMetadata(ratingKey4k);
}
if (plexMedia) {
if (media.mediaType === 'movie') {
const has4kByWidth = plexMedia.Media?.some(
(mediaItem) => (mediaItem.width ?? 0) >= 2000
);
if (is4k) {
if (ratingKey === ratingKey4k || !has4kByWidth) {
plexMedia = undefined;
}
} else {
const hasNon4kByWidth = plexMedia.Media?.some(
(mediaItem) =>
(mediaItem.width ?? 0) < 2000 && (mediaItem.width ?? 0) > 0
);
if (!hasNon4kByWidth && has4kByWidth) {
plexMedia = undefined;
}
}
} else if (media.mediaType === 'tv' && is4k) {
if (ratingKey === ratingKey4k) {
plexMedia = undefined;
}
}
}
}
if (plexMedia) {

View File

@@ -13,7 +13,9 @@ const migrationArrTags = async (settings: any): Promise<AllSettings> => {
}
const userRepository = getRepository(User);
const users = await userRepository.find();
const users = await userRepository.find({
select: ['id'],
});
let errorOccurred = false;
@@ -28,26 +30,15 @@ const migrationArrTags = async (settings: any): Promise<AllSettings> => {
});
const radarrTags = await radarr.getTags();
for (const user of users) {
const userTag = radarrTags.find(
(v) =>
v.label.startsWith(user.id + ' - ') ||
v.label.startsWith(user.id + '-')
const userTag = radarrTags.find((v) =>
v.label.startsWith(user.id + ' - ')
);
if (!userTag) {
continue;
}
await radarr.renameTag({
id: userTag.id,
label:
user.id +
'-' +
user.displayName
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/\s+/g, '-')
.replace(/[^a-z0-9-]/gi, '')
.replace(/-+/g, '-')
.replace(/^-|-$/g, ''),
label: userTag.label.replace(`${user.id} - `, `${user.id}-`),
});
}
} catch (error) {
@@ -70,26 +61,15 @@ const migrationArrTags = async (settings: any): Promise<AllSettings> => {
});
const sonarrTags = await sonarr.getTags();
for (const user of users) {
const userTag = sonarrTags.find(
(v) =>
v.label.startsWith(user.id + ' - ') ||
v.label.startsWith(user.id + '-')
const userTag = sonarrTags.find((v) =>
v.label.startsWith(user.id + ' - ')
);
if (!userTag) {
continue;
}
await sonarr.renameTag({
id: userTag.id,
label:
user.id +
'-' +
user.displayName
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/\s+/g, '-')
.replace(/[^a-z0-9-]/gi, '')
.replace(/-+/g, '-')
.replace(/^-|-$/g, ''),
label: userTag.label.replace(`${user.id} - `, `${user.id}-`),
});
}
} catch (error) {

View File

@@ -6,15 +6,6 @@ export class AddUniqueConstraintToPushSubscription1765233385034
name = 'AddUniqueConstraintToPushSubscription1765233385034';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
DELETE FROM "user_push_subscription"
WHERE id NOT IN (
SELECT MAX(id)
FROM "user_push_subscription"
GROUP BY "endpoint", "userId"
)
`);
await queryRunner.query(
`ALTER TABLE "user_push_subscription" ADD CONSTRAINT "UQ_6427d07d9a171a3a1ab87480005" UNIQUE ("endpoint", "userId")`
);

View File

@@ -6,15 +6,6 @@ export class AddUniqueConstraintToPushSubscription1765233385034
name = 'AddUniqueConstraintToPushSubscription1765233385034';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
DELETE FROM "user_push_subscription"
WHERE id NOT IN (
SELECT MAX(id)
FROM "user_push_subscription"
GROUP BY "endpoint", "userId"
)
`);
await queryRunner.query(
`CREATE UNIQUE INDEX "UQ_6427d07d9a171a3a1ab87480005" ON "user_push_subscription" ("endpoint", "userId")`
);

View File

@@ -29,16 +29,6 @@ import type {
} from 'typeorm';
import { EventSubscriber } from 'typeorm';
const sanitizeDisplayName = (displayName: string): string => {
return displayName
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/\s+/g, '-')
.replace(/[^a-z0-9-]/gi, '')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
};
@EventSubscriber()
export class MediaRequestSubscriber
implements EntitySubscriberInterface<MediaRequest>
@@ -320,15 +310,11 @@ export class MediaRequestSubscriber
mediaId: entity.media.id,
userId: entity.requestedBy.id,
newTag:
entity.requestedBy.id +
'-' +
sanitizeDisplayName(entity.requestedBy.displayName),
entity.requestedBy.id + '-' + entity.requestedBy.displayName,
});
userTag = await radarr.createTag({
label:
entity.requestedBy.id +
'-' +
sanitizeDisplayName(entity.requestedBy.displayName),
entity.requestedBy.id + '-' + entity.requestedBy.displayName,
});
}
if (userTag.id) {
@@ -645,15 +631,11 @@ export class MediaRequestSubscriber
mediaId: entity.media.id,
userId: entity.requestedBy.id,
newTag:
entity.requestedBy.id +
'-' +
sanitizeDisplayName(entity.requestedBy.displayName),
entity.requestedBy.id + '-' + entity.requestedBy.displayName,
});
userTag = await sonarr.createTag({
label:
entity.requestedBy.id +
'-' +
sanitizeDisplayName(entity.requestedBy.displayName),
entity.requestedBy.id + '-' + entity.requestedBy.displayName,
});
}
if (userTag.id) {

View File

@@ -3,7 +3,6 @@ import Button from '@app/components/Common/Button';
import { SmallLoadingSpinner } from '@app/components/Common/LoadingSpinner';
import usePlexLogin from '@app/hooks/usePlexLogin';
import defineMessages from '@app/utils/defineMessages';
import { Fragment } from 'react';
import { FormattedMessage } from 'react-intl';
const messages = defineMessages('components.Login', {
@@ -47,12 +46,8 @@ const PlexLoginButton = ({
>
{(chunks) => (
<>
{chunks.map((c, index) =>
typeof c === 'string' ? (
<span key={index}>{c}</span>
) : (
<Fragment key={index}>{c}</Fragment>
)
{chunks.map((c) =>
typeof c === 'string' ? <span>{c}</span> : c
)}
</>
)}

View File

@@ -25,7 +25,6 @@ import {
} from '@server/constants/media';
import { MediaServerType } from '@server/constants/server';
import type { MediaWatchDataResponse } from '@server/interfaces/api/mediaInterfaces';
import type { DownloadingItem } from '@server/lib/downloadtracker';
import type { RadarrSettings, SonarrSettings } from '@server/lib/settings';
import type { MovieDetails } from '@server/models/Movie';
import type { TvDetails } from '@server/models/Tv';
@@ -34,17 +33,6 @@ import Link from 'next/link';
import { useIntl } from 'react-intl';
import useSWR from 'swr';
const filterDuplicateDownloads = (
items: DownloadingItem[] = []
): DownloadingItem[] => {
const seen = new Set<string>();
return items.filter((item) => {
if (seen.has(item.downloadId)) return false;
seen.add(item.downloadId);
return true;
});
};
const messages = defineMessages('components.ManageSlideOver', {
manageModalTitle: 'Manage {mediaType}',
manageModalIssues: 'Open Issues',
@@ -242,30 +230,26 @@ const ManageSlideOver = ({
</h3>
<div className="overflow-hidden rounded-md border border-gray-700 shadow">
<ul>
{filterDuplicateDownloads(data.mediaInfo?.downloadStatus).map(
(status, index) => (
<Tooltip
key={`dl-status-${status.externalId}-${index}`}
content={status.title}
>
<li className="border-b border-gray-700 last:border-b-0">
<DownloadBlock downloadItem={status} />
</li>
</Tooltip>
)
)}
{filterDuplicateDownloads(data.mediaInfo?.downloadStatus4k).map(
(status, index) => (
<Tooltip
key={`dl-status-4k-${status.externalId}-${index}`}
content={status.title}
>
<li className="border-b border-gray-700 last:border-b-0">
<DownloadBlock downloadItem={status} is4k />
</li>
</Tooltip>
)
)}
{data.mediaInfo?.downloadStatus?.map((status, index) => (
<Tooltip
key={`dl-status-${status.externalId}-${index}`}
content={status.title}
>
<li className="border-b border-gray-700 last:border-b-0">
<DownloadBlock downloadItem={status} />
</li>
</Tooltip>
))}
{data.mediaInfo?.downloadStatus4k?.map((status, index) => (
<Tooltip
key={`dl-status-${status.externalId}-${index}`}
content={status.title}
>
<li className="border-b border-gray-700 last:border-b-0">
<DownloadBlock downloadItem={status} is4k />
</li>
</Tooltip>
))}
</ul>
</div>
</div>

View File

@@ -377,7 +377,6 @@ const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
webAppUrl: data?.webAppUrl,
}}
validationSchema={PlexSettingsSchema}
validateOnMount={true}
onSubmit={async (values) => {
let toastId: string | null = null;
try {
@@ -424,7 +423,6 @@ const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
values,
handleSubmit,
setFieldValue,
setValues,
isSubmitting,
isValid,
}) => {
@@ -447,12 +445,9 @@ const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
availablePresets[Number(e.target.value)];
if (targPreset) {
setValues({
...values,
hostname: targPreset.address,
port: targPreset.port,
useSsl: targPreset.ssl,
});
setFieldValue('hostname', targPreset.address);
setFieldValue('port', targPreset.port);
setFieldValue('useSsl', targPreset.ssl);
}
}}
>

View File

@@ -28,8 +28,7 @@ const LoginWithPlex = ({ onComplete }: LoginWithPlexProps) => {
const response = await axios.post('/api/v1/auth/plex', { authToken });
if (response.data?.id) {
const { data: user } = await axios.get('/api/v1/auth/me');
revalidate(user, false);
revalidate();
}
};
if (authToken) {