Compare commits
1 Commits
test-fix-i
...
preview-dn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9b2d3ccf1 |
108
.github/workflows/release.yml
vendored
108
.github/workflows/release.yml
vendored
@@ -35,60 +35,60 @@ jobs:
|
|||||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
run: npx semantic-release
|
run: npx semantic-release
|
||||||
|
|
||||||
# build-snap:
|
build-snap:
|
||||||
# name: Build Snap Package (${{ matrix.architecture }})
|
name: Build Snap Package (${{ matrix.architecture }})
|
||||||
# needs: semantic-release
|
needs: semantic-release
|
||||||
# runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
# strategy:
|
strategy:
|
||||||
# fail-fast: false
|
fail-fast: false
|
||||||
# matrix:
|
matrix:
|
||||||
# architecture:
|
architecture:
|
||||||
# - amd64
|
- amd64
|
||||||
# - arm64
|
- arm64
|
||||||
# - armhf
|
- armhf
|
||||||
# steps:
|
steps:
|
||||||
# - name: Checkout Code
|
- name: Checkout Code
|
||||||
# uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
# with:
|
with:
|
||||||
# fetch-depth: 0
|
fetch-depth: 0
|
||||||
# - name: Switch to main branch
|
- name: Switch to main branch
|
||||||
# run: git checkout main
|
run: git checkout main
|
||||||
# - name: Pull latest changes
|
- name: Pull latest changes
|
||||||
# run: git pull
|
run: git pull
|
||||||
# - name: Prepare
|
- name: Prepare
|
||||||
# id: prepare
|
id: prepare
|
||||||
# run: |
|
run: |
|
||||||
# git fetch --prune --tags
|
git fetch --prune --tags
|
||||||
# if [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
|
if [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
|
||||||
# echo "RELEASE=stable" >> $GITHUB_OUTPUT
|
echo "RELEASE=stable" >> $GITHUB_OUTPUT
|
||||||
# else
|
else
|
||||||
# echo "RELEASE=edge" >> $GITHUB_OUTPUT
|
echo "RELEASE=edge" >> $GITHUB_OUTPUT
|
||||||
# fi
|
fi
|
||||||
# - name: Set Up QEMU
|
- name: Set Up QEMU
|
||||||
# uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
# with:
|
with:
|
||||||
# image: tonistiigi/binfmt@sha256:df15403e06a03c2f461c1f7938b171fda34a5849eb63a70e2a2109ed5a778bde
|
image: tonistiigi/binfmt@sha256:df15403e06a03c2f461c1f7938b171fda34a5849eb63a70e2a2109ed5a778bde
|
||||||
# - name: Build Snap Package
|
- name: Build Snap Package
|
||||||
# uses: diddlesnaps/snapcraft-multiarch-action@v1
|
uses: diddlesnaps/snapcraft-multiarch-action@v1
|
||||||
# id: build
|
id: build
|
||||||
# with:
|
with:
|
||||||
# architecture: ${{ matrix.architecture }}
|
architecture: ${{ matrix.architecture }}
|
||||||
# - name: Upload Snap Package
|
- name: Upload Snap Package
|
||||||
# uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
# with:
|
with:
|
||||||
# name: jellyseerr-snap-package-${{ matrix.architecture }}
|
name: jellyseerr-snap-package-${{ matrix.architecture }}
|
||||||
# path: ${{ steps.build.outputs.snap }}
|
path: ${{ steps.build.outputs.snap }}
|
||||||
# - name: Review Snap Package
|
- name: Review Snap Package
|
||||||
# uses: diddlesnaps/snapcraft-review-tools-action@v1
|
uses: diddlesnaps/snapcraft-review-tools-action@v1
|
||||||
# with:
|
with:
|
||||||
# snap: ${{ steps.build.outputs.snap }}
|
snap: ${{ steps.build.outputs.snap }}
|
||||||
# - name: Publish Snap Package
|
- name: Publish Snap Package
|
||||||
# uses: snapcore/action-publish@v1
|
uses: snapcore/action-publish@v1
|
||||||
# env:
|
env:
|
||||||
# SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_LOGIN }}
|
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_LOGIN }}
|
||||||
# with:
|
with:
|
||||||
# snap: ${{ steps.build.outputs.snap }}
|
snap: ${{ steps.build.outputs.snap }}
|
||||||
# release: ${{ steps.prepare.outputs.RELEASE }}
|
release: ${{ steps.prepare.outputs.RELEASE }}
|
||||||
|
|
||||||
discord:
|
discord:
|
||||||
name: Send Discord Notification
|
name: Send Discord Notification
|
||||||
|
|||||||
@@ -133,11 +133,6 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
}
|
}
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
logger.debug(`Logging in to Jellyfin server: ${this.jellyfinHost}`, {
|
|
||||||
label: 'Jellyfin API',
|
|
||||||
clientIp: ClientIP,
|
|
||||||
});
|
|
||||||
|
|
||||||
const authResponse = await this.post<JellyfinLoginResponse>(
|
const authResponse = await this.post<JellyfinLoginResponse>(
|
||||||
'/Users/AuthenticateByName',
|
'/Users/AuthenticateByName',
|
||||||
{
|
{
|
||||||
@@ -151,12 +146,6 @@ class JellyfinAPI extends ExternalAPI {
|
|||||||
|
|
||||||
return authResponse;
|
return authResponse;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Failed to login to Jellyfin server', {
|
|
||||||
label: 'Jellyfin API',
|
|
||||||
clientIp: ClientIP,
|
|
||||||
error: e,
|
|
||||||
});
|
|
||||||
|
|
||||||
const status = e.response?.status;
|
const status = e.response?.status;
|
||||||
|
|
||||||
const networkErrorCodes = new Set([
|
const networkErrorCodes = new Set([
|
||||||
|
|||||||
@@ -83,17 +83,13 @@ class JellyfinScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const has4k = metadata.MediaSources?.some((MediaSource) => {
|
const has4k = metadata.MediaSources?.some((MediaSource) => {
|
||||||
return MediaSource.MediaStreams.filter(
|
return MediaSource.MediaStreams.some((MediaStream) => {
|
||||||
(MediaStream) => MediaStream.Type === 'Video'
|
|
||||||
).some((MediaStream) => {
|
|
||||||
return (MediaStream.Width ?? 0) > 2000;
|
return (MediaStream.Width ?? 0) > 2000;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasOtherResolution = metadata.MediaSources?.some((MediaSource) => {
|
const hasOtherResolution = metadata.MediaSources?.some((MediaSource) => {
|
||||||
return MediaSource.MediaStreams.filter(
|
return MediaSource.MediaStreams.some((MediaStream) => {
|
||||||
(MediaStream) => MediaStream.Type === 'Video'
|
|
||||||
).some((MediaStream) => {
|
|
||||||
return (MediaStream.Width ?? 0) <= 2000;
|
return (MediaStream.Width ?? 0) <= 2000;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import { ApiError } from '@server/types/error';
|
|||||||
import * as EmailValidator from 'email-validator';
|
import * as EmailValidator from 'email-validator';
|
||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import gravatarUrl from 'gravatar-url';
|
import gravatarUrl from 'gravatar-url';
|
||||||
import net from 'net';
|
|
||||||
|
|
||||||
const authRoutes = Router();
|
const authRoutes = Router();
|
||||||
|
|
||||||
@@ -272,21 +271,11 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
|
|||||||
? jellyfinHost.slice(0, -1)
|
? jellyfinHost.slice(0, -1)
|
||||||
: jellyfinHost;
|
: jellyfinHost;
|
||||||
|
|
||||||
const ip = req.ip;
|
const ip = req.ip ? req.ip.split(':').reverse()[0] : undefined;
|
||||||
let clientIp;
|
|
||||||
|
|
||||||
if (ip) {
|
|
||||||
if (net.isIPv4(ip)) {
|
|
||||||
clientIp = ip;
|
|
||||||
} else if (net.isIPv6(ip)) {
|
|
||||||
clientIp = ip.startsWith('::ffff:') ? ip.substring(7) : ip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const account = await jellyfinserver.login(
|
const account = await jellyfinserver.login(
|
||||||
body.username,
|
body.username,
|
||||||
body.password,
|
body.password,
|
||||||
clientIp
|
ip
|
||||||
);
|
);
|
||||||
|
|
||||||
// Next let's see if the user already exists
|
// Next let's see if the user already exists
|
||||||
|
|||||||
@@ -434,38 +434,33 @@ const MovieDetails = ({ movie }: MovieDetailsProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{hasPermission(Permission.MANAGE_REQUESTS) &&
|
{hasPermission(Permission.MANAGE_REQUESTS) && data.mediaInfo && (
|
||||||
data.mediaInfo &&
|
<Tooltip content={intl.formatMessage(messages.managemovie)}>
|
||||||
(data.mediaInfo.jellyfinMediaId ||
|
<Button
|
||||||
data.mediaInfo.jellyfinMediaId4k ||
|
buttonType="ghost"
|
||||||
data.mediaInfo.status !== MediaStatus.UNKNOWN ||
|
onClick={() => setShowManager(true)}
|
||||||
data.mediaInfo.status4k !== MediaStatus.UNKNOWN) && (
|
className="relative ml-2 first:ml-0"
|
||||||
<Tooltip content={intl.formatMessage(messages.managemovie)}>
|
>
|
||||||
<Button
|
<CogIcon className="!mr-0" />
|
||||||
buttonType="ghost"
|
{hasPermission(
|
||||||
onClick={() => setShowManager(true)}
|
[Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
|
||||||
className="relative ml-2 first:ml-0"
|
{
|
||||||
>
|
type: 'or',
|
||||||
<CogIcon className="!mr-0" />
|
}
|
||||||
{hasPermission(
|
) &&
|
||||||
[Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
|
(
|
||||||
{
|
data.mediaInfo?.issues.filter(
|
||||||
type: 'or',
|
(issue) => issue.status === IssueStatus.OPEN
|
||||||
}
|
) ?? []
|
||||||
) &&
|
).length > 0 && (
|
||||||
(
|
<>
|
||||||
data.mediaInfo?.issues.filter(
|
<div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
|
||||||
(issue) => issue.status === IssueStatus.OPEN
|
<div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
|
||||||
) ?? []
|
</>
|
||||||
).length > 0 && (
|
)}
|
||||||
<>
|
</Button>
|
||||||
<div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
|
</Tooltip>
|
||||||
<div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
|
)}
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="media-overview">
|
<div className="media-overview">
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ const messages = defineMessages({
|
|||||||
discordId: 'Discord User ID',
|
discordId: 'Discord User ID',
|
||||||
discordIdTip:
|
discordIdTip:
|
||||||
'The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your Discord user account',
|
'The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your Discord user account',
|
||||||
validationemailrequired: 'Email required',
|
|
||||||
validationemailformat: 'Valid email required',
|
|
||||||
validationDiscordId: 'You must provide a valid Discord user ID',
|
validationDiscordId: 'You must provide a valid Discord user ID',
|
||||||
plexwatchlistsyncmovies: 'Auto-Request Movies',
|
plexwatchlistsyncmovies: 'Auto-Request Movies',
|
||||||
plexwatchlistsyncmoviestip:
|
plexwatchlistsyncmoviestip:
|
||||||
@@ -90,9 +88,6 @@ const UserGeneralSettings = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const UserGeneralSettingsSchema = Yup.object().shape({
|
const UserGeneralSettingsSchema = Yup.object().shape({
|
||||||
email: Yup.string()
|
|
||||||
.email(intl.formatMessage(messages.validationemailformat))
|
|
||||||
.required(intl.formatMessage(messages.validationemailrequired)),
|
|
||||||
discordId: Yup.string()
|
discordId: Yup.string()
|
||||||
.nullable()
|
.nullable()
|
||||||
.matches(/^\d{17,19}$/, intl.formatMessage(messages.validationDiscordId)),
|
.matches(/^\d{17,19}$/, intl.formatMessage(messages.validationDiscordId)),
|
||||||
|
|||||||
@@ -1177,8 +1177,6 @@
|
|||||||
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "Settings saved successfully!",
|
"components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "Settings saved successfully!",
|
||||||
"components.UserProfile.UserSettings.UserGeneralSettings.user": "User",
|
"components.UserProfile.UserSettings.UserGeneralSettings.user": "User",
|
||||||
"components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "You must provide a valid Discord user ID",
|
"components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "You must provide a valid Discord user ID",
|
||||||
"components.UserProfile.UserSettings.UserGeneralSettings.validationemailformat": "Valid email required",
|
|
||||||
"components.UserProfile.UserSettings.UserGeneralSettings.validationemailrequired": "Email required",
|
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.deviceDefault": "Device Default",
|
"components.UserProfile.UserSettings.UserNotificationSettings.deviceDefault": "Device Default",
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.discordId": "User ID",
|
"components.UserProfile.UserSettings.UserNotificationSettings.discordId": "User ID",
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your user account",
|
"components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your user account",
|
||||||
|
|||||||
Reference in New Issue
Block a user