mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-02-12 15:42:25 +00:00
Compare commits
26 Commits
fix/ci-wor
...
renovate/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fff4a7bfa | ||
|
|
8b5914001d | ||
|
|
5eaaad660d | ||
|
|
de36952f53 | ||
|
|
6b8400cc3d | ||
|
|
a0bf5199ba | ||
|
|
01264c10a6 | ||
|
|
558b31f386 | ||
|
|
5656df4339 | ||
|
|
fa4d51c5e6 | ||
|
|
21bb702fd3 | ||
|
|
4a494271dd | ||
|
|
1f6768178a | ||
|
|
fead4acae1 | ||
|
|
ccd042750d | ||
|
|
e4619556ba | ||
|
|
9f2dc178f5 | ||
|
|
4c751e0a86 | ||
|
|
32d8086121 | ||
|
|
7c200899d7 | ||
|
|
613d72fa26 | ||
|
|
909e2142d6 | ||
|
|
8083ab78b5 | ||
|
|
cbc0138507 | ||
|
|
7b10888c95 | ||
|
|
acb9da6f93 |
@@ -1,17 +1,31 @@
|
|||||||
{
|
{
|
||||||
"name": "Development Jellyfin Server",
|
"name": "Development Jellyfin Server",
|
||||||
"image": "mcr.microsoft.com/devcontainers/dotnet:9.0-bookworm",
|
"image": "mcr.microsoft.com/devcontainers/dotnet:10.0-noble",
|
||||||
"service": "app",
|
"service": "app",
|
||||||
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||||
// restores nuget packages, installs the dotnet workloads and installs the dev https certificate
|
// restores nuget packages, installs the dotnet workloads and installs the dev https certificate
|
||||||
"postStartCommand": "sudo dotnet restore; sudo dotnet workload update; sudo dotnet dev-certs https --trust; sudo bash \"./.devcontainer/install-ffmpeg.sh\"",
|
"postStartCommand": "sudo dotnet restore; sudo dotnet workload update; sudo dotnet dev-certs https --trust; sudo bash \"./.devcontainer/install-ffmpeg.sh\"",
|
||||||
// reads the extensions list and installs them
|
// The previous way of installing extensions via the vs command dont work on selfhosted devcontainers
|
||||||
"postAttachCommand": "cat .vscode/extensions.json | jq -r .recommendations[] | xargs -n 1 code --install-extension",
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"ms-dotnettools.csharp",
|
||||||
|
"editorconfig.editorconfig",
|
||||||
|
"github.vscode-github-actions",
|
||||||
|
"ms-dotnettools.vscode-dotnet-runtime",
|
||||||
|
"ms-dotnettools.csdevkit",
|
||||||
|
"alexcvzz.vscode-sqlite",
|
||||||
|
"streetsidesoftware.code-spell-checker",
|
||||||
|
"eamodio.gitlens",
|
||||||
|
"redhat.vscode-xml"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/dotnet:2": {
|
"ghcr.io/devcontainers/features/dotnet:2": {
|
||||||
"version": "none",
|
"version": "none",
|
||||||
"dotnetRuntimeVersions": "9.0",
|
"dotnetRuntimeVersions": "10.0",
|
||||||
"aspNetCoreRuntimeVersions": "9.0"
|
"aspNetCoreRuntimeVersions": "10.0"
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers-extra/features/apt-packages:1": {
|
"ghcr.io/devcontainers-extra/features/apt-packages:1": {
|
||||||
"preserve_apt_list": false,
|
"preserve_apt_list": false,
|
||||||
|
|||||||
6
.github/workflows/ci-codeql-analysis.yml
vendored
6
.github/workflows/ci-codeql-analysis.yml
vendored
@@ -28,13 +28,13 @@ jobs:
|
|||||||
dotnet-version: '10.0.x'
|
dotnet-version: '10.0.x'
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
queries: +security-extended
|
queries: +security-extended
|
||||||
|
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
|
||||||
|
|||||||
55
.github/workflows/ci-compat-build.yml
vendored
55
.github/workflows/ci-compat-build.yml
vendored
@@ -1,55 +0,0 @@
|
|||||||
name: ABI Compatibility Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
abi-head:
|
|
||||||
name: ABI - HEAD
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
|
||||||
with:
|
|
||||||
dotnet-version: '10.0.x'
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: dotnet build Jellyfin.Server -o ./out
|
|
||||||
|
|
||||||
- name: Upload Head
|
|
||||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
||||||
with:
|
|
||||||
name: abi-head
|
|
||||||
retention-days: 1
|
|
||||||
if-no-files-found: error
|
|
||||||
path: out/
|
|
||||||
|
|
||||||
abi-base:
|
|
||||||
name: ABI - BASE
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.base.sha }}
|
|
||||||
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
|
||||||
with:
|
|
||||||
dotnet-version: '10.0.x'
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: dotnet build Jellyfin.Server -o ./out
|
|
||||||
|
|
||||||
- name: Upload Base
|
|
||||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
||||||
with:
|
|
||||||
name: abi-base
|
|
||||||
retention-days: 1
|
|
||||||
if-no-files-found: error
|
|
||||||
path: out/
|
|
||||||
91
.github/workflows/ci-compat.yml
vendored
91
.github/workflows/ci-compat.yml
vendored
@@ -1,20 +1,87 @@
|
|||||||
name: ABI Compatibility
|
name: ABI Compatibility
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
pull_request_target:
|
||||||
workflows: ["ABI Compatibility Build"]
|
|
||||||
types: [completed]
|
|
||||||
|
|
||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
abi-head:
|
||||||
|
name: ABI - HEAD
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions: read-all
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||||
|
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
||||||
|
with:
|
||||||
|
dotnet-version: '10.0.x'
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
dotnet build Jellyfin.Server -o ./out
|
||||||
|
|
||||||
|
- name: Upload Head
|
||||||
|
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||||
|
with:
|
||||||
|
name: abi-head
|
||||||
|
retention-days: 14
|
||||||
|
if-no-files-found: error
|
||||||
|
path: out/
|
||||||
|
|
||||||
|
abi-base:
|
||||||
|
name: ABI - BASE
|
||||||
|
if: ${{ github.base_ref != '' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions: read-all
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
||||||
|
with:
|
||||||
|
dotnet-version: '10.0.x'
|
||||||
|
|
||||||
|
- name: Checkout common ancestor
|
||||||
|
env:
|
||||||
|
HEAD_REF: ${{ github.head_ref }}
|
||||||
|
run: |
|
||||||
|
git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }}
|
||||||
|
git -c protocol.version=2 fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/*
|
||||||
|
ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF)
|
||||||
|
git checkout --progress --force $ANCESTOR_REF
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
dotnet build Jellyfin.Server -o ./out
|
||||||
|
|
||||||
|
- name: Upload Head
|
||||||
|
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||||
|
with:
|
||||||
|
name: abi-base
|
||||||
|
retention-days: 14
|
||||||
|
if-no-files-found: error
|
||||||
|
path: out/
|
||||||
|
|
||||||
abi-diff:
|
abi-diff:
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write # to create or update comment (peter-evans/create-or-update-comment)
|
||||||
|
|
||||||
name: ABI - Difference
|
name: ABI - Difference
|
||||||
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request_target' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- abi-head
|
||||||
|
- abi-base
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Download abi-head
|
- name: Download abi-head
|
||||||
@@ -22,16 +89,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: abi-head
|
name: abi-head
|
||||||
path: abi-head
|
path: abi-head
|
||||||
run-id: ${{ github.event.workflow_run.id }}
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Download abi-base
|
- name: Download abi-base
|
||||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||||
with:
|
with:
|
||||||
name: abi-base
|
name: abi-base
|
||||||
path: abi-base
|
path: abi-base
|
||||||
run-id: ${{ github.event.workflow_run.id }}
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Setup ApiCompat
|
- name: Setup ApiCompat
|
||||||
run: |
|
run: |
|
||||||
@@ -55,7 +118,7 @@ jobs:
|
|||||||
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
|
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
|
||||||
id: find-comment
|
id: find-comment
|
||||||
with:
|
with:
|
||||||
issue-number: ${{ github.event.workflow_run.pull_requests[0].number }}
|
issue-number: ${{ github.event.pull_request.number }}
|
||||||
direction: last
|
direction: last
|
||||||
body-includes: abi-diff-workflow-comment
|
body-includes: abi-diff-workflow-comment
|
||||||
|
|
||||||
@@ -63,7 +126,7 @@ jobs:
|
|||||||
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
|
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
|
||||||
if: ${{ steps.diff.outputs.body != '' }}
|
if: ${{ steps.diff.outputs.body != '' }}
|
||||||
with:
|
with:
|
||||||
issue-number: ${{ github.event.workflow_run.pull_requests[0].number }}
|
issue-number: ${{ github.event.pull_request.number }}
|
||||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||||
edit-mode: replace
|
edit-mode: replace
|
||||||
token: ${{ secrets.JF_BOT_TOKEN }}
|
token: ${{ secrets.JF_BOT_TOKEN }}
|
||||||
@@ -82,7 +145,7 @@ jobs:
|
|||||||
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
|
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
|
||||||
if: ${{ steps.diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }}
|
if: ${{ steps.diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }}
|
||||||
with:
|
with:
|
||||||
issue-number: ${{ github.event.workflow_run.pull_requests[0].number }}
|
issue-number: ${{ github.event.pull_request.number }}
|
||||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||||
edit-mode: replace
|
edit-mode: replace
|
||||||
token: ${{ secrets.JF_BOT_TOKEN }}
|
token: ${{ secrets.JF_BOT_TOKEN }}
|
||||||
|
|||||||
55
.github/workflows/ci-openapi-build.yml
vendored
55
.github/workflows/ci-openapi-build.yml
vendored
@@ -1,55 +0,0 @@
|
|||||||
name: OpenAPI Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
openapi-head:
|
|
||||||
name: OpenAPI - HEAD
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
|
||||||
with:
|
|
||||||
dotnet-version: '10.0.x'
|
|
||||||
|
|
||||||
- name: Generate openapi.json
|
|
||||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
|
||||||
|
|
||||||
- name: Upload openapi.json
|
|
||||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
||||||
with:
|
|
||||||
name: openapi-head
|
|
||||||
retention-days: 1
|
|
||||||
if-no-files-found: error
|
|
||||||
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
|
||||||
|
|
||||||
openapi-base:
|
|
||||||
name: OpenAPI - BASE
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.base.sha }}
|
|
||||||
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
|
||||||
with:
|
|
||||||
dotnet-version: '10.0.x'
|
|
||||||
|
|
||||||
- name: Generate openapi.json
|
|
||||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
|
||||||
|
|
||||||
- name: Upload openapi.json
|
|
||||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
||||||
with:
|
|
||||||
name: openapi-base
|
|
||||||
retention-days: 1
|
|
||||||
if-no-files-found: error
|
|
||||||
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
|
||||||
62
.github/workflows/ci-openapi.yml
vendored
62
.github/workflows/ci-openapi.yml
vendored
@@ -1,31 +1,30 @@
|
|||||||
name: OpenAPI
|
name: OpenAPI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
workflow_run:
|
pull_request_target:
|
||||||
workflows: ["OpenAPI Build"]
|
|
||||||
types: [completed]
|
|
||||||
|
|
||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
openapi-head:
|
openapi-head:
|
||||||
name: OpenAPI - HEAD
|
name: OpenAPI - HEAD
|
||||||
if: ${{ github.event_name == 'push' }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions: read-all
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||||
|
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
||||||
with:
|
with:
|
||||||
dotnet-version: '10.0.x'
|
dotnet-version: '10.0.x'
|
||||||
|
|
||||||
- name: Generate openapi.json
|
- name: Generate openapi.json
|
||||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||||
|
|
||||||
@@ -37,29 +36,65 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
||||||
|
|
||||||
|
openapi-base:
|
||||||
|
name: OpenAPI - BASE
|
||||||
|
if: ${{ github.base_ref != '' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions: read-all
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Checkout common ancestor
|
||||||
|
env:
|
||||||
|
HEAD_REF: ${{ github.head_ref }}
|
||||||
|
run: |
|
||||||
|
git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }}
|
||||||
|
git -c protocol.version=2 fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/*
|
||||||
|
ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF)
|
||||||
|
git checkout --progress --force $ANCESTOR_REF
|
||||||
|
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
||||||
|
with:
|
||||||
|
dotnet-version: '10.0.x'
|
||||||
|
- name: Generate openapi.json
|
||||||
|
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||||
|
|
||||||
|
- name: Upload openapi.json
|
||||||
|
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||||
|
with:
|
||||||
|
name: openapi-base
|
||||||
|
retention-days: 14
|
||||||
|
if-no-files-found: error
|
||||||
|
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net10.0/openapi.json
|
||||||
|
|
||||||
openapi-diff:
|
openapi-diff:
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
name: OpenAPI - Difference
|
name: OpenAPI - Difference
|
||||||
if: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request_target' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- openapi-head
|
||||||
|
- openapi-base
|
||||||
steps:
|
steps:
|
||||||
- name: Download openapi-head
|
- name: Download openapi-head
|
||||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||||
with:
|
with:
|
||||||
name: openapi-head
|
name: openapi-head
|
||||||
path: openapi-head
|
path: openapi-head
|
||||||
run-id: ${{ github.event.workflow_run.id }}
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Download openapi-base
|
- name: Download openapi-base
|
||||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||||
with:
|
with:
|
||||||
name: openapi-base
|
name: openapi-base
|
||||||
path: openapi-base
|
path: openapi-base
|
||||||
run-id: ${{ github.event.workflow_run.id }}
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Detect OpenAPI changes
|
- name: Detect OpenAPI changes
|
||||||
id: openapi-diff
|
id: openapi-diff
|
||||||
@@ -70,12 +105,11 @@ jobs:
|
|||||||
markdown: openapi-changelog.md
|
markdown: openapi-changelog.md
|
||||||
add-pr-comment: true
|
add-pr-comment: true
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
pr-number: ${{ github.event.workflow_run.pull_requests[0].number }}
|
|
||||||
|
|
||||||
|
|
||||||
publish-unstable:
|
publish-unstable:
|
||||||
name: OpenAPI - Publish Unstable Spec
|
name: OpenAPI - Publish Unstable Spec
|
||||||
if: ${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
if: ${{ github.event_name != 'pull_request_target' && !startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- openapi-head
|
- openapi-head
|
||||||
@@ -136,7 +170,7 @@ jobs:
|
|||||||
|
|
||||||
publish-stable:
|
publish-stable:
|
||||||
name: OpenAPI - Publish Stable Spec
|
name: OpenAPI - Publish Stable Spec
|
||||||
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- openapi-head
|
- openapi-head
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Run "dotnet list package (dash,dash)outdated" to see the latest versions of each package.-->
|
<!-- Run "dotnet list package (dash,dash)outdated" to see the latest versions of each package.-->
|
||||||
<ItemGroup Label="Package Dependencies">
|
<ItemGroup Label="Package Dependencies">
|
||||||
<PackageVersion Include="AsyncKeyedLock" Version="8.0.0" />
|
<PackageVersion Include="AsyncKeyedLock" Version="8.0.1" />
|
||||||
<PackageVersion Include="AutoFixture.AutoMoq" Version="4.18.1" />
|
<PackageVersion Include="AutoFixture.AutoMoq" Version="4.18.1" />
|
||||||
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
|
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
|
||||||
<PackageVersion Include="AutoFixture" Version="4.18.1" />
|
<PackageVersion Include="AutoFixture" Version="4.18.1" />
|
||||||
@@ -26,27 +26,27 @@
|
|||||||
<PackageVersion Include="libse" Version="4.0.12" />
|
<PackageVersion Include="libse" Version="4.0.12" />
|
||||||
<PackageVersion Include="LrcParser" Version="2025.623.0" />
|
<PackageVersion Include="LrcParser" Version="2025.623.0" />
|
||||||
<PackageVersion Include="MetaBrainz.MusicBrainz" Version="8.0.1" />
|
<PackageVersion Include="MetaBrainz.MusicBrainz" Version="8.0.1" />
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="5.0.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="5.0.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
|
||||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.2" />
|
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.3" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||||
<PackageVersion Include="MimeTypes" Version="2.5.2" />
|
<PackageVersion Include="MimeTypes" Version="2.5.2" />
|
||||||
<PackageVersion Include="Morestachio" Version="5.0.1.631" />
|
<PackageVersion Include="Morestachio" Version="5.0.1.631" />
|
||||||
@@ -74,12 +74,12 @@
|
|||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="[3.116.1]" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="[3.116.1]" />
|
||||||
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
|
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
|
||||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||||
<PackageVersion Include="Svg.Skia" Version="3.2.1" />
|
<PackageVersion Include="Svg.Skia" Version="3.4.1" />
|
||||||
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="6.9.0" />
|
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="6.9.0" />
|
||||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="7.3.2" />
|
<PackageVersion Include="Swashbuckle.AspNetCore" Version="7.3.2" />
|
||||||
<PackageVersion Include="System.Text.Json" Version="10.0.2" />
|
<PackageVersion Include="System.Text.Json" Version="10.0.3" />
|
||||||
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
|
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
|
||||||
<PackageVersion Include="z440.atl.core" Version="7.10.0" />
|
<PackageVersion Include="z440.atl.core" Version="7.11.0" />
|
||||||
<PackageVersion Include="TMDbLib" Version="2.3.0" />
|
<PackageVersion Include="TMDbLib" Version="2.3.0" />
|
||||||
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />
|
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />
|
||||||
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
|
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
|
||||||
|
|||||||
@@ -37,15 +37,25 @@ namespace Emby.Server.Implementations.Library
|
|||||||
while (attributeIndex > -1 && attributeIndex < maxIndex)
|
while (attributeIndex > -1 && attributeIndex < maxIndex)
|
||||||
{
|
{
|
||||||
var attributeEnd = attributeIndex + attribute.Length;
|
var attributeEnd = attributeIndex + attribute.Length;
|
||||||
if (attributeIndex > 0
|
if (attributeIndex > 0)
|
||||||
&& str[attributeIndex - 1] == '['
|
|
||||||
&& (str[attributeEnd] == '=' || str[attributeEnd] == '-'))
|
|
||||||
{
|
{
|
||||||
var closingIndex = str[attributeEnd..].IndexOf(']');
|
var attributeOpener = str[attributeIndex - 1];
|
||||||
// Must be at least 1 character before the closing bracket.
|
var attributeCloser = attributeOpener switch
|
||||||
if (closingIndex > 1)
|
|
||||||
{
|
{
|
||||||
return str[(attributeEnd + 1)..(attributeEnd + closingIndex)].Trim().ToString();
|
'[' => ']',
|
||||||
|
'(' => ')',
|
||||||
|
'{' => '}',
|
||||||
|
_ => '\0'
|
||||||
|
};
|
||||||
|
if (attributeCloser != '\0' && (str[attributeEnd] == '=' || str[attributeEnd] == '-'))
|
||||||
|
{
|
||||||
|
var closingIndex = str[attributeEnd..].IndexOf(attributeCloser);
|
||||||
|
|
||||||
|
// Must be at least 1 character before the closing bracket.
|
||||||
|
if (closingIndex > 1)
|
||||||
|
{
|
||||||
|
return str[(attributeEnd + 1)..(attributeEnd + closingIndex)].Trim().ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"Playlists": "Плэй-лісты",
|
"Playlists": "Плэй-лісты",
|
||||||
"Latest": "Апошняе",
|
"Latest": "Апошняе",
|
||||||
"LabelIpAddressValue": "IP-адрас: {0}",
|
"LabelIpAddressValue": "IP-адрас: {0}",
|
||||||
"ItemAddedWithName": "{0} даданы ў бібліятэку",
|
"ItemAddedWithName": "{0} дададзены ў бібліятэку",
|
||||||
"MessageApplicationUpdated": "Сервер Jellyfin абноўлены",
|
"MessageApplicationUpdated": "Сервер Jellyfin абноўлены",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "Абнаўленне праграмы ўсталявана",
|
"NotificationOptionApplicationUpdateInstalled": "Абнаўленне праграмы ўсталявана",
|
||||||
"PluginInstalledWithName": "{0} быў усталяваны",
|
"PluginInstalledWithName": "{0} быў усталяваны",
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"Channels": "Каналы",
|
"Channels": "Каналы",
|
||||||
"ChapterNameValue": "Раздзел {0}",
|
"ChapterNameValue": "Раздзел {0}",
|
||||||
"Collections": "Калекцыі",
|
"Collections": "Калекцыі",
|
||||||
"Default": "Па змаўчанні",
|
"Default": "Прадвызначана",
|
||||||
"FailedLoginAttemptWithUserName": "Няўдалая спроба ўваходу з {0}",
|
"FailedLoginAttemptWithUserName": "Няўдалая спроба ўваходу з {0}",
|
||||||
"Folders": "Папкі",
|
"Folders": "Папкі",
|
||||||
"Favorites": "Абранае",
|
"Favorites": "Абранае",
|
||||||
@@ -81,8 +81,8 @@
|
|||||||
"NotificationOptionInstallationFailed": "Збой усталёўкі",
|
"NotificationOptionInstallationFailed": "Збой усталёўкі",
|
||||||
"NewVersionIsAvailable": "Новая версія сервера Jellyfin даступная для cпампоўкі.",
|
"NewVersionIsAvailable": "Новая версія сервера Jellyfin даступная для cпампоўкі.",
|
||||||
"NotificationOptionCameraImageUploaded": "Выява камеры запампавана",
|
"NotificationOptionCameraImageUploaded": "Выява камеры запампавана",
|
||||||
"NotificationOptionAudioPlaybackStopped": "Прайграванне аўдыё спынена",
|
"NotificationOptionAudioPlaybackStopped": "Прайграванне аўдыя спынена",
|
||||||
"NotificationOptionAudioPlayback": "Прайграванне аўдыё пачалося",
|
"NotificationOptionAudioPlayback": "Прайграванне аўдыя пачалося",
|
||||||
"NotificationOptionNewLibraryContent": "Дададзены новы кантэнт",
|
"NotificationOptionNewLibraryContent": "Дададзены новы кантэнт",
|
||||||
"NotificationOptionPluginError": "Збой плагіна",
|
"NotificationOptionPluginError": "Збой плагіна",
|
||||||
"NotificationOptionPluginUninstalled": "Плагін выдалены",
|
"NotificationOptionPluginUninstalled": "Плагін выдалены",
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
"TaskCleanLogsDescription": "Esborra els registres que tinguin més de {0} dies.",
|
"TaskCleanLogsDescription": "Esborra els registres que tinguin més de {0} dies.",
|
||||||
"TaskCleanLogs": "Neteja dels registres",
|
"TaskCleanLogs": "Neteja dels registres",
|
||||||
"TaskRefreshLibraryDescription": "Escaneja les mediateques, a la cerca de fitxers nous i refresca les metadades.",
|
"TaskRefreshLibraryDescription": "Escaneja les mediateques, a la cerca de fitxers nous i refresca les metadades.",
|
||||||
"TaskRefreshLibrary": "Escaneig de les mediateques",
|
"TaskRefreshLibrary": "Escaneja la mediateca",
|
||||||
"TaskRefreshChapterImagesDescription": "Creació de les miniatures dels vídeos que tinguin capítols.",
|
"TaskRefreshChapterImagesDescription": "Creació de les miniatures dels vídeos que tinguin capítols.",
|
||||||
"TaskRefreshChapterImages": "Extracció de les imatges dels capítols",
|
"TaskRefreshChapterImages": "Extracció de les imatges dels capítols",
|
||||||
"TaskCleanCacheDescription": "Eliminació de la memòria cau no necessària per al servidor.",
|
"TaskCleanCacheDescription": "Eliminació de la memòria cau no necessària per al servidor.",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"CameraImageUploadedFrom": "Nova fotografija sa kamere je učitana iz {0}",
|
"CameraImageUploadedFrom": "Nova fotografija sa kamere je učitana iz {0}",
|
||||||
"Channels": "Kanali",
|
"Channels": "Kanali",
|
||||||
"ChapterNameValue": "Poglavlje {0}",
|
"ChapterNameValue": "Poglavlje {0}",
|
||||||
"Collections": "Kolekcije",
|
"Collections": "Zbirke",
|
||||||
"DeviceOfflineWithName": "{0} je prekinuo vezu",
|
"DeviceOfflineWithName": "{0} je prekinuo vezu",
|
||||||
"DeviceOnlineWithName": "{0} je povezan",
|
"DeviceOnlineWithName": "{0} je povezan",
|
||||||
"FailedLoginAttemptWithUserName": "Neuspješan pokušaj prijave od {0}",
|
"FailedLoginAttemptWithUserName": "Neuspješan pokušaj prijave od {0}",
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"ScheduledTaskFailedWithName": "{0} neuspjelo",
|
"ScheduledTaskFailedWithName": "{0} neuspjelo",
|
||||||
"ScheduledTaskStartedWithName": "{0} pokrenuto",
|
"ScheduledTaskStartedWithName": "{0} pokrenuto",
|
||||||
"ServerNameNeedsToBeRestarted": "{0} treba ponovno pokrenuti",
|
"ServerNameNeedsToBeRestarted": "{0} treba ponovno pokrenuti",
|
||||||
"Shows": "Serije",
|
"Shows": "Emisije",
|
||||||
"Songs": "Pjesme",
|
"Songs": "Pjesme",
|
||||||
"StartupEmbyServerIsLoading": "Jellyfin server se učitava. Pokušajte ponovo uskoro.",
|
"StartupEmbyServerIsLoading": "Jellyfin server se učitava. Pokušajte ponovo uskoro.",
|
||||||
"SubtitleDownloadFailureFromForItem": "Prijevod nije uspješno preuzet od {0} za {1}",
|
"SubtitleDownloadFailureFromForItem": "Prijevod nije uspješno preuzet od {0} za {1}",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"AppDeviceValues": "App: {0}, Dispositivo: {1}",
|
"AppDeviceValues": "App: {0}, Dispositivo: {1}",
|
||||||
"Application": "Applicazione",
|
"Application": "Applicazione",
|
||||||
"Artists": "Artisti",
|
"Artists": "Artisti",
|
||||||
"AuthenticationSucceededWithUserName": "{0} autenticato con successo",
|
"AuthenticationSucceededWithUserName": "{0} autenticato correttamente",
|
||||||
"Books": "Libri",
|
"Books": "Libri",
|
||||||
"CameraImageUploadedFrom": "È stata caricata una nuova fotografia da {0}",
|
"CameraImageUploadedFrom": "È stata caricata una nuova fotografia da {0}",
|
||||||
"Channels": "Canali",
|
"Channels": "Canali",
|
||||||
@@ -11,36 +11,36 @@
|
|||||||
"Collections": "Collezioni",
|
"Collections": "Collezioni",
|
||||||
"DeviceOfflineWithName": "{0} si è disconnesso",
|
"DeviceOfflineWithName": "{0} si è disconnesso",
|
||||||
"DeviceOnlineWithName": "{0} è connesso",
|
"DeviceOnlineWithName": "{0} è connesso",
|
||||||
"FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da {0}",
|
"FailedLoginAttemptWithUserName": "Tentativo di accesso non riuscito da {0}",
|
||||||
"Favorites": "Preferiti",
|
"Favorites": "Preferiti",
|
||||||
"Folders": "Cartelle",
|
"Folders": "Cartelle",
|
||||||
"Genres": "Generi",
|
"Genres": "Generi",
|
||||||
"HeaderAlbumArtists": "Artisti dell'album",
|
"HeaderAlbumArtists": "Artisti dell'album",
|
||||||
"HeaderContinueWatching": "Continua a guardare",
|
"HeaderContinueWatching": "Continua a guardare",
|
||||||
"HeaderFavoriteAlbums": "Album Preferiti",
|
"HeaderFavoriteAlbums": "Album preferiti",
|
||||||
"HeaderFavoriteArtists": "Artisti Preferiti",
|
"HeaderFavoriteArtists": "Artisti preferiti",
|
||||||
"HeaderFavoriteEpisodes": "Episodi Preferiti",
|
"HeaderFavoriteEpisodes": "Episodi preferiti",
|
||||||
"HeaderFavoriteShows": "Serie TV Preferite",
|
"HeaderFavoriteShows": "Serie TV preferite",
|
||||||
"HeaderFavoriteSongs": "Brani Preferiti",
|
"HeaderFavoriteSongs": "Brani preferiti",
|
||||||
"HeaderLiveTV": "Diretta TV",
|
"HeaderLiveTV": "Diretta TV",
|
||||||
"HeaderNextUp": "Prossimo",
|
"HeaderNextUp": "Prossimo",
|
||||||
"HeaderRecordingGroups": "Gruppi di Registrazione",
|
"HeaderRecordingGroups": "Gruppi di registrazione",
|
||||||
"HomeVideos": "Video Personali",
|
"HomeVideos": "Video personali",
|
||||||
"Inherit": "Eredita",
|
"Inherit": "Eredita",
|
||||||
"ItemAddedWithName": "{0} è stato aggiunto alla libreria",
|
"ItemAddedWithName": "{0} è stato aggiunto alla libreria",
|
||||||
"ItemRemovedWithName": "{0} è stato rimosso dalla libreria",
|
"ItemRemovedWithName": "{0} è stato rimosso dalla libreria",
|
||||||
"LabelIpAddressValue": "Indirizzo IP: {0}",
|
"LabelIpAddressValue": "Indirizzo IP: {0}",
|
||||||
"LabelRunningTimeValue": "Durata: {0}",
|
"LabelRunningTimeValue": "Durata: {0}",
|
||||||
"Latest": "Novità",
|
"Latest": "Novità",
|
||||||
"MessageApplicationUpdated": "Il Server Jellyfin è stato aggiornato",
|
"MessageApplicationUpdated": "Jellyfin Server è stato aggiornato",
|
||||||
"MessageApplicationUpdatedTo": "Jellyfin Server è stato aggiornato a {0}",
|
"MessageApplicationUpdatedTo": "Jellyfin Server è stato aggiornato a {0}",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "La sezione {0} della configurazione server è stata aggiornata",
|
"MessageNamedServerConfigurationUpdatedWithValue": "La sezione {0} della configurazione server è stata aggiornata",
|
||||||
"MessageServerConfigurationUpdated": "La configurazione del server è stata aggiornata",
|
"MessageServerConfigurationUpdated": "La configurazione del server è stata aggiornata",
|
||||||
"MixedContent": "Contenuto misto",
|
"MixedContent": "Contenuto misto",
|
||||||
"Movies": "Film",
|
"Movies": "Film",
|
||||||
"Music": "Musica",
|
"Music": "Musica",
|
||||||
"MusicVideos": "Video Musicali",
|
"MusicVideos": "Video musicali",
|
||||||
"NameInstallFailed": "{0} installazione fallita",
|
"NameInstallFailed": "{0} installazione non riuscita",
|
||||||
"NameSeasonNumber": "Stagione {0}",
|
"NameSeasonNumber": "Stagione {0}",
|
||||||
"NameSeasonUnknown": "Stagione sconosciuta",
|
"NameSeasonUnknown": "Stagione sconosciuta",
|
||||||
"NewVersionIsAvailable": "Una nuova versione di Jellyfin Server è disponibile per il download.",
|
"NewVersionIsAvailable": "Una nuova versione di Jellyfin Server è disponibile per il download.",
|
||||||
@@ -49,37 +49,37 @@
|
|||||||
"NotificationOptionAudioPlayback": "La riproduzione audio è iniziata",
|
"NotificationOptionAudioPlayback": "La riproduzione audio è iniziata",
|
||||||
"NotificationOptionAudioPlaybackStopped": "La riproduzione audio è stata interrotta",
|
"NotificationOptionAudioPlaybackStopped": "La riproduzione audio è stata interrotta",
|
||||||
"NotificationOptionCameraImageUploaded": "Immagine fotocamera caricata",
|
"NotificationOptionCameraImageUploaded": "Immagine fotocamera caricata",
|
||||||
"NotificationOptionInstallationFailed": "Installazione fallita",
|
"NotificationOptionInstallationFailed": "Installazione non riuscita",
|
||||||
"NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto",
|
"NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto",
|
||||||
"NotificationOptionPluginError": "Errore del plugin",
|
"NotificationOptionPluginError": "Errore del plugin",
|
||||||
"NotificationOptionPluginInstalled": "Plugin installato",
|
"NotificationOptionPluginInstalled": "Plugin installato",
|
||||||
"NotificationOptionPluginUninstalled": "Plugin disinstallato",
|
"NotificationOptionPluginUninstalled": "Plugin disinstallato",
|
||||||
"NotificationOptionPluginUpdateInstalled": "Aggiornamento plugin installato",
|
"NotificationOptionPluginUpdateInstalled": "Aggiornamento plugin installato",
|
||||||
"NotificationOptionServerRestartRequired": "Riavvio del server necessario",
|
"NotificationOptionServerRestartRequired": "Riavvio del server necessario",
|
||||||
"NotificationOptionTaskFailed": "Operazione pianificata fallita",
|
"NotificationOptionTaskFailed": "Operazione pianificata non riuscita",
|
||||||
"NotificationOptionUserLockedOut": "Utente bloccato",
|
"NotificationOptionUserLockedOut": "Utente bloccato",
|
||||||
"NotificationOptionVideoPlayback": "Riproduzione video iniziata",
|
"NotificationOptionVideoPlayback": "Riproduzione video iniziata",
|
||||||
"NotificationOptionVideoPlaybackStopped": "Riproduzione video interrotta",
|
"NotificationOptionVideoPlaybackStopped": "Riproduzione video interrotta",
|
||||||
"Photos": "Foto",
|
"Photos": "Foto",
|
||||||
"Playlists": "Playlist",
|
"Playlists": "Scalette",
|
||||||
"Plugin": "Plugin",
|
"Plugin": "Plugin",
|
||||||
"PluginInstalledWithName": "{0} è stato Installato",
|
"PluginInstalledWithName": "{0} è stato installato",
|
||||||
"PluginUninstalledWithName": "{0} è stato disinstallato",
|
"PluginUninstalledWithName": "{0} è stato disinstallato",
|
||||||
"PluginUpdatedWithName": "{0} è stato aggiornato",
|
"PluginUpdatedWithName": "{0} è stato aggiornato",
|
||||||
"ProviderValue": "Provider: {0}",
|
"ProviderValue": "Provider: {0}",
|
||||||
"ScheduledTaskFailedWithName": "{0} fallito",
|
"ScheduledTaskFailedWithName": "{0} non riuscito",
|
||||||
"ScheduledTaskStartedWithName": "{0} avviato",
|
"ScheduledTaskStartedWithName": "{0} avviato",
|
||||||
"ServerNameNeedsToBeRestarted": "{0} deve essere riavviato",
|
"ServerNameNeedsToBeRestarted": "{0} deve essere riavviato",
|
||||||
"Shows": "Serie TV",
|
"Shows": "Serie TV",
|
||||||
"Songs": "Brani",
|
"Songs": "Brani",
|
||||||
"StartupEmbyServerIsLoading": "Jellyfin server si sta avviando. Per favore riprova più tardi.",
|
"StartupEmbyServerIsLoading": "Jellyfin Server si sta avviando. Riprova più tardi.",
|
||||||
"SubtitleDownloadFailureFromForItem": "Impossibile scaricare i sottotitoli da {0} per {1}",
|
"SubtitleDownloadFailureFromForItem": "Impossibile scaricare i sottotitoli da {0} per {1}",
|
||||||
"Sync": "Sincronizza",
|
"Sync": "Sincronizza",
|
||||||
"System": "Sistema",
|
"System": "Sistema",
|
||||||
"TvShows": "Serie TV",
|
"TvShows": "Serie TV",
|
||||||
"User": "Utente",
|
"User": "Utente",
|
||||||
"UserCreatedWithName": "L'utente {0} è stato creato",
|
"UserCreatedWithName": "L'utente {0} è stato creato",
|
||||||
"UserDeletedWithName": "L'utente {0} è stato rimosso",
|
"UserDeletedWithName": "L'utente {0} è stato eliminato",
|
||||||
"UserDownloadingItemWithValues": "{0} sta scaricando {1}",
|
"UserDownloadingItemWithValues": "{0} sta scaricando {1}",
|
||||||
"UserLockedOutWithName": "L'utente {0} è stato bloccato",
|
"UserLockedOutWithName": "L'utente {0} è stato bloccato",
|
||||||
"UserOfflineFromDevice": "{0} si è disconnesso da {1}",
|
"UserOfflineFromDevice": "{0} si è disconnesso da {1}",
|
||||||
@@ -114,20 +114,20 @@
|
|||||||
"TasksLibraryCategory": "Libreria",
|
"TasksLibraryCategory": "Libreria",
|
||||||
"TasksMaintenanceCategory": "Manutenzione",
|
"TasksMaintenanceCategory": "Manutenzione",
|
||||||
"TaskCleanActivityLog": "Attività di Registro Completate",
|
"TaskCleanActivityLog": "Attività di Registro Completate",
|
||||||
"TaskCleanActivityLogDescription": "Elimina le voci del registro delle attività più vecchie dell’età configurata.",
|
"TaskCleanActivityLogDescription": "Elimina le voci del registro delle attività più vecchie dell'età configurata.",
|
||||||
"Undefined": "Non Definito",
|
"Undefined": "Non specificato",
|
||||||
"Forced": "Forzato",
|
"Forced": "Forzato",
|
||||||
"Default": "Predefinito",
|
"Default": "Predefinito",
|
||||||
"TaskOptimizeDatabaseDescription": "Compatta database e tronca spazi liberi. Eseguire questa azione dopo la scansione o dopo aver fatto altre modifiche inerenti il database potrebbe aumentarne le prestazioni.",
|
"TaskOptimizeDatabaseDescription": "Compatta database e tronca spazi liberi. Eseguire questa azione dopo la scansione o dopo aver fatto altre modifiche inerenti il database potrebbe aumentarne le prestazioni.",
|
||||||
"TaskOptimizeDatabase": "Ottimizza database",
|
"TaskOptimizeDatabase": "Ottimizza database",
|
||||||
"TaskKeyframeExtractor": "Estrattore di Keyframe",
|
"TaskKeyframeExtractor": "Estrattore di Keyframe",
|
||||||
"TaskKeyframeExtractorDescription": "Estrae i keyframe dai video per creare migliori playlist HLS. Questa procedura potrebbe richiedere molto tempo.",
|
"TaskKeyframeExtractorDescription": "Estrae i keyframe dai video per creare migliori scalette HLS. Questa procedura potrebbe richiedere molto tempo.",
|
||||||
"External": "Esterno",
|
"External": "Esterno",
|
||||||
"HearingImpaired": "Non Udenti",
|
"HearingImpaired": "Non udenti",
|
||||||
"TaskRefreshTrickplayImages": "Genera immagini Trickplay",
|
"TaskRefreshTrickplayImages": "Genera immagini Trickplay",
|
||||||
"TaskRefreshTrickplayImagesDescription": "Crea anteprime trickplay per i video nelle librerie abilitate.",
|
"TaskRefreshTrickplayImagesDescription": "Crea anteprime trickplay per i video nelle librerie abilitate.",
|
||||||
"TaskCleanCollectionsAndPlaylists": "Ripulire le collezioni e le playlist",
|
"TaskCleanCollectionsAndPlaylists": "Ripulisci le collezioni e le scalette",
|
||||||
"TaskCleanCollectionsAndPlaylistsDescription": "Rimuove gli elementi dalle collezioni e dalle playlist che non esistono più.",
|
"TaskCleanCollectionsAndPlaylistsDescription": "Rimuove gli elementi dalle collezioni e dalle scalette che non esistono più.",
|
||||||
"TaskAudioNormalization": "Normalizzazione dell'audio",
|
"TaskAudioNormalization": "Normalizzazione dell'audio",
|
||||||
"TaskAudioNormalizationDescription": "Scansiona i file alla ricerca dei dati per la normalizzazione dell'audio.",
|
"TaskAudioNormalizationDescription": "Scansiona i file alla ricerca dei dati per la normalizzazione dell'audio.",
|
||||||
"TaskDownloadMissingLyricsDescription": "Scarica testi per le canzoni",
|
"TaskDownloadMissingLyricsDescription": "Scarica testi per le canzoni",
|
||||||
|
|||||||
@@ -124,8 +124,8 @@
|
|||||||
"TaskKeyframeExtractor": "Extrator de Quadros-chave",
|
"TaskKeyframeExtractor": "Extrator de Quadros-chave",
|
||||||
"External": "Externo",
|
"External": "Externo",
|
||||||
"HearingImpaired": "Surdo",
|
"HearingImpaired": "Surdo",
|
||||||
"TaskRefreshTrickplayImages": "Gerar Imagens de Trickplay",
|
"TaskRefreshTrickplayImages": "Gerar imagens de trickplay",
|
||||||
"TaskRefreshTrickplayImagesDescription": "Cria ficheiros de trickplay para vídeos nas bibliotecas ativas.",
|
"TaskRefreshTrickplayImagesDescription": "Cria pré-visualizações de trickplay para vídeos nas bibliotecas ativadas.",
|
||||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
||||||
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
||||||
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
||||||
|
|||||||
@@ -124,8 +124,8 @@
|
|||||||
"HearingImpaired": "Problemas auditivos",
|
"HearingImpaired": "Problemas auditivos",
|
||||||
"TaskKeyframeExtractor": "Extrator de quadro-chave",
|
"TaskKeyframeExtractor": "Extrator de quadro-chave",
|
||||||
"TaskKeyframeExtractorDescription": "Retira frames chave do video para criar listas HLS precisas. Esta tarefa pode correr durante algum tempo.",
|
"TaskKeyframeExtractorDescription": "Retira frames chave do video para criar listas HLS precisas. Esta tarefa pode correr durante algum tempo.",
|
||||||
"TaskRefreshTrickplayImages": "Gerar miniaturas de vídeo",
|
"TaskRefreshTrickplayImages": "Gerar imagens de trickplay",
|
||||||
"TaskRefreshTrickplayImagesDescription": "Cria miniaturas de vídeo para vídeos nas bibliotecas definidas.",
|
"TaskRefreshTrickplayImagesDescription": "Cria pré-visualizações de trickplay para vídeos nas bibliotecas ativadas.",
|
||||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
||||||
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
||||||
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
||||||
|
|||||||
@@ -191,9 +191,17 @@ public class DisplayPreferencesController : BaseJellyfinApiController
|
|||||||
|
|
||||||
foreach (var key in displayPreferences.CustomPrefs.Keys.Where(key => key.StartsWith("landing-", StringComparison.OrdinalIgnoreCase)))
|
foreach (var key in displayPreferences.CustomPrefs.Keys.Where(key => key.StartsWith("landing-", StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
if (!Enum.TryParse<ViewType>(displayPreferences.CustomPrefs[key], true, out _))
|
var viewType = displayPreferences.CustomPrefs[key];
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(viewType))
|
||||||
{
|
{
|
||||||
_logger.LogError("Invalid ViewType: {LandingScreenOption}", displayPreferences.CustomPrefs[key]);
|
displayPreferences.CustomPrefs.Remove(key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Enum.TryParse<ViewType>(viewType, true, out _))
|
||||||
|
{
|
||||||
|
_logger.LogError("Invalid ViewType: {LandingScreenOption}", viewType);
|
||||||
displayPreferences.CustomPrefs.Remove(key);
|
displayPreferences.CustomPrefs.Remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,9 +74,10 @@ public class PeopleRepository(IDbContextFactory<JellyfinDbContext> dbProvider, I
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void UpdatePeople(Guid itemId, IReadOnlyList<PersonInfo> people)
|
public void UpdatePeople(Guid itemId, IReadOnlyList<PersonInfo> people)
|
||||||
{
|
{
|
||||||
foreach (var item in people.Where(e => e.Role is null))
|
foreach (var person in people)
|
||||||
{
|
{
|
||||||
item.Role = string.Empty;
|
person.Name = person.Name.Trim();
|
||||||
|
person.Role = person.Role?.Trim() ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiple metadata providers can provide the _same_ person
|
// multiple metadata providers can provide the _same_ person
|
||||||
|
|||||||
@@ -117,14 +117,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
|
|||||||
preferredLanguage = NormalizeLanguage(preferredLanguage, countryCode);
|
preferredLanguage = NormalizeLanguage(preferredLanguage, countryCode);
|
||||||
|
|
||||||
languages.Add(preferredLanguage);
|
languages.Add(preferredLanguage);
|
||||||
|
|
||||||
if (preferredLanguage.Length == 5) // Like en-US
|
|
||||||
{
|
|
||||||
// Currently, TMDb supports 2-letter language codes only.
|
|
||||||
// They are planning to change this in the future, thus we're
|
|
||||||
// supplying both codes if we're having a 5-letter code.
|
|
||||||
languages.Add(preferredLanguage.Substring(0, 2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
languages.Add("null");
|
languages.Add("null");
|
||||||
|
|||||||
@@ -11,21 +11,29 @@ namespace Jellyfin.Server.Implementations.Tests.Library
|
|||||||
[InlineData("Superman: Red Son [imdbid=tt10985510]", "imdbid", "tt10985510")]
|
[InlineData("Superman: Red Son [imdbid=tt10985510]", "imdbid", "tt10985510")]
|
||||||
[InlineData("Superman: Red Son [imdbid-tt10985510]", "imdbid", "tt10985510")]
|
[InlineData("Superman: Red Son [imdbid-tt10985510]", "imdbid", "tt10985510")]
|
||||||
[InlineData("Superman: Red Son - tt10985510", "imdbid", "tt10985510")]
|
[InlineData("Superman: Red Son - tt10985510", "imdbid", "tt10985510")]
|
||||||
|
[InlineData("Superman: Red Son {imdbid=tt10985510}", "imdbid", "tt10985510")]
|
||||||
|
[InlineData("Superman: Red Son (imdbid-tt10985510)", "imdbid", "tt10985510")]
|
||||||
[InlineData("Superman: Red Son", "imdbid", null)]
|
[InlineData("Superman: Red Son", "imdbid", null)]
|
||||||
[InlineData("Superman: Red Son", "something", null)]
|
|
||||||
[InlineData("Superman: Red Son [imdbid1=tt11111111][imdbid=tt10985510]", "imdbid", "tt10985510")]
|
[InlineData("Superman: Red Son [imdbid1=tt11111111][imdbid=tt10985510]", "imdbid", "tt10985510")]
|
||||||
[InlineData("Superman: Red Son [imdbid1-tt11111111][imdbid=tt10985510]", "imdbid", "tt10985510")]
|
[InlineData("Superman: Red Son {imdbid1=tt11111111}(imdbid=tt10985510)", "imdbid", "tt10985510")]
|
||||||
|
[InlineData("Superman: Red Son (imdbid1-tt11111111)[imdbid=tt10985510]", "imdbid", "tt10985510")]
|
||||||
[InlineData("Superman: Red Son [tmdbid=618355][imdbid=tt10985510]", "imdbid", "tt10985510")]
|
[InlineData("Superman: Red Son [tmdbid=618355][imdbid=tt10985510]", "imdbid", "tt10985510")]
|
||||||
[InlineData("Superman: Red Son [tmdbid-618355][imdbid-tt10985510]", "imdbid", "tt10985510")]
|
[InlineData("Superman: Red Son [tmdbid-618355]{imdbid-tt10985510}", "imdbid", "tt10985510")]
|
||||||
[InlineData("Superman: Red Son [tmdbid-618355][imdbid-tt10985510]", "tmdbid", "618355")]
|
[InlineData("Superman: Red Son (tmdbid-618355)[imdbid-tt10985510]", "tmdbid", "618355")]
|
||||||
[InlineData("Superman: Red Son [providera-id=1]", "providera-id", "1")]
|
[InlineData("Superman: Red Son [providera-id=1]", "providera-id", "1")]
|
||||||
[InlineData("Superman: Red Son [providerb-id=2]", "providerb-id", "2")]
|
[InlineData("Superman: Red Son [providerb-id=2]", "providerb-id", "2")]
|
||||||
[InlineData("Superman: Red Son [providera id=4]", "providera id", "4")]
|
[InlineData("Superman: Red Son [providera id=4]", "providera id", "4")]
|
||||||
[InlineData("Superman: Red Son [providerb id=5]", "providerb id", "5")]
|
[InlineData("Superman: Red Son [providerb id=5]", "providerb id", "5")]
|
||||||
[InlineData("Superman: Red Son [tmdbid=3]", "tmdbid", "3")]
|
[InlineData("Superman: Red Son [tmdbid=3]", "tmdbid", "3")]
|
||||||
[InlineData("Superman: Red Son [tvdbid-6]", "tvdbid", "6")]
|
[InlineData("Superman: Red Son [tvdbid-6]", "tvdbid", "6")]
|
||||||
|
[InlineData("Superman: Red Son {tmdbid=3}", "tmdbid", "3")]
|
||||||
|
[InlineData("Superman: Red Son (tvdbid-6)", "tvdbid", "6")]
|
||||||
[InlineData("[tmdbid=618355]", "tmdbid", "618355")]
|
[InlineData("[tmdbid=618355]", "tmdbid", "618355")]
|
||||||
|
[InlineData("{tmdbid=618355}", "tmdbid", "618355")]
|
||||||
|
[InlineData("(tmdbid=618355)", "tmdbid", "618355")]
|
||||||
[InlineData("[tmdbid-618355]", "tmdbid", "618355")]
|
[InlineData("[tmdbid-618355]", "tmdbid", "618355")]
|
||||||
|
[InlineData("{tmdbid-618355)", "tmdbid", null)]
|
||||||
|
[InlineData("[tmdbid-618355}", "tmdbid", null)]
|
||||||
[InlineData("tmdbid=111111][tmdbid=618355]", "tmdbid", "618355")]
|
[InlineData("tmdbid=111111][tmdbid=618355]", "tmdbid", "618355")]
|
||||||
[InlineData("[tmdbid=618355]tmdbid=111111]", "tmdbid", "618355")]
|
[InlineData("[tmdbid=618355]tmdbid=111111]", "tmdbid", "618355")]
|
||||||
[InlineData("tmdbid=618355]", "tmdbid", null)]
|
[InlineData("tmdbid=618355]", "tmdbid", null)]
|
||||||
@@ -36,6 +44,9 @@ namespace Jellyfin.Server.Implementations.Tests.Library
|
|||||||
[InlineData("[tmdbid=][imdbid=tt10985510]", "tmdbid", null)]
|
[InlineData("[tmdbid=][imdbid=tt10985510]", "tmdbid", null)]
|
||||||
[InlineData("[tmdbid-][imdbid-tt10985510]", "tmdbid", null)]
|
[InlineData("[tmdbid-][imdbid-tt10985510]", "tmdbid", null)]
|
||||||
[InlineData("Superman: Red Son [tmdbid-618355][tmdbid=1234567]", "tmdbid", "618355")]
|
[InlineData("Superman: Red Son [tmdbid-618355][tmdbid=1234567]", "tmdbid", "618355")]
|
||||||
|
[InlineData("{tmdbid=}{imdbid=tt10985510}", "tmdbid", null)]
|
||||||
|
[InlineData("(tmdbid-)(imdbid-tt10985510)", "tmdbid", null)]
|
||||||
|
[InlineData("Superman: Red Son {tmdbid-618355}{tmdbid=1234567}", "tmdbid", "618355")]
|
||||||
public void GetAttributeValue_ValidArgs_Correct(string input, string attribute, string? expectedResult)
|
public void GetAttributeValue_ValidArgs_Correct(string input, string attribute, string? expectedResult)
|
||||||
{
|
{
|
||||||
Assert.Equal(expectedResult, PathExtensions.GetAttributeValue(input, attribute));
|
Assert.Equal(expectedResult, PathExtensions.GetAttributeValue(input, attribute));
|
||||||
|
|||||||
Reference in New Issue
Block a user