diff --git a/.all-contributorsrc b/.all-contributorsrc
index 3cf5e765c5..5a1ddadd59 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -737,6 +737,177 @@
"contributions": [
"translation"
]
+ },
+ {
+ "login": "Eclipseop",
+ "name": "Mackenzie",
+ "avatar_url": "https://avatars.githubusercontent.com/u/5846213?v=4",
+ "profile": "https://github.com/Eclipseop",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "s0up4200",
+ "name": "soup",
+ "avatar_url": "https://avatars.githubusercontent.com/u/18177310?v=4",
+ "profile": "https://github.com/s0up4200",
+ "contributions": [
+ "doc"
+ ]
+ },
+ {
+ "login": "ceptonit",
+ "name": "ceptonit",
+ "avatar_url": "https://avatars.githubusercontent.com/u/12678743?v=4",
+ "profile": "https://github.com/ceptonit",
+ "contributions": [
+ "doc"
+ ]
+ },
+ {
+ "login": "aedelbro",
+ "name": "aedelbro",
+ "avatar_url": "https://avatars.githubusercontent.com/u/36162221?v=4",
+ "profile": "https://github.com/aedelbro",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "lunks",
+ "name": "Pedro Nascimento",
+ "avatar_url": "https://avatars.githubusercontent.com/u/91118?v=4",
+ "profile": "http://twitter.com/lunks/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "owenvoke",
+ "name": "Owen Voke",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1899334?v=4",
+ "profile": "https://voke.dev",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Nimelrian",
+ "name": "Sebastian K",
+ "avatar_url": "https://avatars.githubusercontent.com/u/8960836?v=4",
+ "profile": "https://github.com/Nimelrian",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "jariz",
+ "name": "jariz",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1415847?v=4",
+ "profile": "https://github.com/jariz",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Alexays",
+ "name": "Alex",
+ "avatar_url": "https://avatars.githubusercontent.com/u/13947260?v=4",
+ "profile": "https://arouillard.fr",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Zebebles",
+ "name": "Zeb Muller",
+ "avatar_url": "https://avatars.githubusercontent.com/u/11425451?v=4",
+ "profile": "https://github.com/Zebebles",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "SMores",
+ "name": "Shane Friedman",
+ "avatar_url": "https://avatars.githubusercontent.com/u/5354254?v=4",
+ "profile": "http://smoores.dev",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "IzaacJ",
+ "name": "Izaac Brånn",
+ "avatar_url": "https://avatars.githubusercontent.com/u/711323?v=4",
+ "profile": "https://izaacj.me",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "SalmanTariq",
+ "name": "Salman Tariq",
+ "avatar_url": "https://avatars.githubusercontent.com/u/13284494?v=4",
+ "profile": "https://github.com/SalmanTariq",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "andrew-kennedy",
+ "name": "Andrew Kennedy",
+ "avatar_url": "https://avatars.githubusercontent.com/u/2387159?v=4",
+ "profile": "https://github.com/andrew-kennedy",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Fallenbagel",
+ "name": "Fallenbagel",
+ "avatar_url": "https://avatars.githubusercontent.com/u/98979876?v=4",
+ "profile": "https://github.com/Fallenbagel",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "scorp200",
+ "name": "Anton K. (ai Doge)",
+ "avatar_url": "https://avatars.githubusercontent.com/u/9427639?v=4",
+ "profile": "http://aidoge.xyz",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "marcofaggian",
+ "name": "Marco Faggian",
+ "avatar_url": "https://avatars.githubusercontent.com/u/19221001?v=4",
+ "profile": "https://marcofaggian.com",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "nemchik",
+ "name": "Eric Nemchik",
+ "avatar_url": "https://avatars.githubusercontent.com/u/725456?v=4",
+ "profile": "http://nemchik.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "RemiRigal",
+ "name": "RemiRigal",
+ "avatar_url": "https://avatars.githubusercontent.com/u/19256051?v=4",
+ "profile": "https://github.com/RemiRigal",
+ "contributions": [
+ "code"
+ ]
}
],
"badgeTemplate": "-orange.svg\"/>",
@@ -745,5 +916,7 @@
"projectOwner": "sct",
"repoType": "github",
"repoHost": "https://github.com",
- "skipCi": false
+ "skipCi": false,
+ "commitConvention": "angular",
+ "commitType": "docs"
}
diff --git a/.gitattributes b/.gitattributes
index 2883a5d26f..eb5d2314fc 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -24,3 +24,24 @@
*.woff binary
*.pyc binary
*.pdf binary
+
+#
+## Theses files/directories should be excluded from git archives
+#
+
+.husky export-ignore
+.vscode export-ignore
+docs export-ignore
+
+.git* export-ignore
+*ignore export-ignore
+*.md export-ignore
+
+.all-contributorsrc export-ignore
+.editorconfig export-ignore
+Dockerfile.local export-ignore
+docker-compose.yml export-ignore
+stylelint.config.js export-ignore
+
+public/os_logo_filled.png export-ignore
+public/preview.jpg export-ignore
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 6effae045d..68a2d018e8 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,10 +1,10 @@
# Global code ownership
-* @sct @TheCatLady @danshilm
+* @sct @TheCatLady @danshilm @OwsleyJr
# Documentation
-/.all-contributorsrc @TheCatLady @samwiseg0 @danshilm
-/*.md @TheCatLady @samwiseg0 @danshilm
-/docs/ @TheCatLady @samwiseg0 @danshilm
+/.all-contributorsrc @TheCatLady @samwiseg0 @danshilm @OwsleyJr
+/*.md @TheCatLady @samwiseg0 @danshilm @OwsleyJr
+/docs/ @TheCatLady @samwiseg0 @danshilm @OwsleyJr
# Snap-related files
/.github/workflows/snap.yaml @samwiseg0
@@ -12,4 +12,4 @@
# i18n locale files
/src/i18n/locale/ @sct @TheCatLady
-/src/i18n/locale/en.json @sct @TheCatLady @danshilm
+/src/i18n/locale/en.json @sct @TheCatLady @danshilm @OwsleyJr
diff --git a/.github/holopin.yml b/.github/holopin.yml
new file mode 100644
index 0000000000..ee4edc81b3
--- /dev/null
+++ b/.github/holopin.yml
@@ -0,0 +1,5 @@
+organization: overseerr
+defaultSticker: clcyagj1j329008l468ya8pu2
+stickers:
+ - id: clcyagj1j329008l468ya8pu2
+ alias: overseerr-contributor
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 05db03e1bd..2be6b2e050 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,8 +12,8 @@ jobs:
test:
name: Lint & Test Build
if: github.event_name == 'pull_request'
- runs-on: ubuntu-20.04
- container: node:16.17-alpine
+ runs-on: ubuntu-22.04
+ container: node:18.18-alpine
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -31,7 +31,7 @@ jobs:
build_and_push:
name: Build & Publish Docker Images
if: github.ref == 'refs/heads/develop' && !contains(github.event.head_commit.message, '[skip ci]')
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -39,13 +39,6 @@ jobs:
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- - name: Cache Docker layers
- uses: actions/cache@v3
- with:
- path: /tmp/.buildx-cache
- key: ${{ runner.os }}-buildx-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-buildx-
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
@@ -71,21 +64,12 @@ jobs:
sctx/overseerr:${{ github.sha }}
ghcr.io/sct/overseerr:develop
ghcr.io/sct/overseerr:${{ github.sha }}
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
- - # Temporary fix
- # https://github.com/docker/build-push-action/issues/252
- # https://github.com/moby/buildkit/issues/1896
- name: Move cache
- run: |
- rm -rf /tmp/.buildx-cache
- mv /tmp/.buildx-cache-new /tmp/.buildx-cache
discord:
name: Send Discord Notification
needs: build_and_push
if: always() && github.event_name != 'pull_request' && !contains(github.event.head_commit.message, '[skip ci]')
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Get Build Job Status
uses: technote-space/workflow-conclusion-action@v3
@@ -94,9 +78,9 @@ jobs:
run: |
failures=(neutral, skipped, timed_out, action_required)
if [[ ${array[@]} =~ $WORKFLOW_CONCLUSION ]]; then
- echo ::set-output name=status::failure
+ echo "status=failure" >> $GITHUB_OUTPUT
else
- echo ::set-output name=status::$WORKFLOW_CONCLUSION
+ echo "status=$WORKFLOW_CONCLUSION" >> $GITHUB_OUTPUT
fi
- name: Post Status to Discord
uses: sarisia/actions-status-discord@v1
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000000..10926bbd92
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,41 @@
+name: 'CodeQL'
+
+on:
+ push:
+ branches: ['develop']
+ pull_request:
+ branches: ['develop']
+ schedule:
+ - cron: '50 7 * * 5'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [javascript]
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ queries: +security-and-quality
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: '/language:${{ matrix.language }}'
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index 6e0d8f3d89..330644290f 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -8,13 +8,13 @@ on:
jobs:
build_and_push:
name: Build & Publish Docker Preview Images
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Get the version
id: get_version
- run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
+ run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 839b2245c8..806d51bf07 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ on:
jobs:
semantic-release:
name: Tag and release latest version
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -45,7 +45,7 @@ jobs:
build-snap:
name: Build Snap Package (${{ matrix.architecture }})
needs: semantic-release
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
@@ -67,9 +67,9 @@ jobs:
run: |
git fetch --prune --tags
if [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
- echo ::set-output name=RELEASE::stable
+ echo "RELEASE=stable" >> $GITHUB_OUTPUT
else
- echo ::set-output name=RELEASE::edge
+ echo "RELEASE=edge" >> $GITHUB_OUTPUT
fi
- name: Set Up QEMU
uses: docker/setup-qemu-action@v2
@@ -91,8 +91,9 @@ jobs:
snap: ${{ steps.build.outputs.snap }}
- name: Publish Snap Package
uses: snapcore/action-publish@v1
+ env:
+ SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_LOGIN }}
with:
- store_login: ${{ secrets.SNAP_LOGIN }}
snap: ${{ steps.build.outputs.snap }}
release: ${{ steps.prepare.outputs.RELEASE }}
@@ -100,7 +101,7 @@ jobs:
name: Send Discord Notification
needs: semantic-release
if: always()
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Get Build Job Status
uses: technote-space/workflow-conclusion-action@v3
@@ -109,9 +110,9 @@ jobs:
run: |
failures=(neutral, skipped, timed_out, action_required)
if [[ ${array[@]} =~ $WORKFLOW_CONCLUSION ]]; then
- echo ::set-output name=status::failure
+ echo "status=failure" >> $GITHUB_OUTPUT
else
- echo ::set-output name=status::$WORKFLOW_CONCLUSION
+ echo "status=$WORKFLOW_CONCLUSION" >> $GITHUB_OUTPUT
fi
- name: Post Status to Discord
uses: sarisia/actions-status-discord@v1
diff --git a/.github/workflows/snap.yaml b/.github/workflows/snap.yaml
index bf00e04d7d..16489a8996 100644
--- a/.github/workflows/snap.yaml
+++ b/.github/workflows/snap.yaml
@@ -8,7 +8,7 @@ on:
jobs:
jobs:
name: Job Check
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- name: Cancel Previous Runs
@@ -19,7 +19,7 @@ jobs:
build-snap:
name: Build Snap Package (${{ matrix.architecture }})
needs: jobs
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
@@ -35,9 +35,9 @@ jobs:
run: |
git fetch --prune --unshallow --tags
if [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
- echo ::set-output name=RELEASE::stable
+ echo "RELEASE=stable" >> $GITHUB_OUTPUT
else
- echo ::set-output name=RELEASE::edge
+ echo "RELEASE=edge" >> $GITHUB_OUTPUT
fi
- name: Set Up QEMU
uses: docker/setup-qemu-action@v2
@@ -57,8 +57,9 @@ jobs:
snap: ${{ steps.build.outputs.snap }}
- name: Publish Snap Package
uses: snapcore/action-publish@v1
+ env:
+ SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_LOGIN }}
with:
- store_login: ${{ secrets.SNAP_LOGIN }}
snap: ${{ steps.build.outputs.snap }}
release: ${{ steps.prepare.outputs.RELEASE }}
@@ -66,7 +67,7 @@ jobs:
name: Send Discord Notification
needs: build-snap
if: always() && !contains(github.event.head_commit.message, '[skip ci]')
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Get Build Job Status
uses: technote-space/workflow-conclusion-action@v3
@@ -75,9 +76,9 @@ jobs:
run: |
failures=(neutral, skipped, timed_out, action_required)
if [[ ${array[@]} =~ $WORKFLOW_CONCLUSION ]]; then
- echo ::set-output name=status::failure
+ echo "status=failure" >> $GITHUB_OUTPUT
else
- echo ::set-output name=status::$WORKFLOW_CONCLUSION
+ echo "status=$WORKFLOW_CONCLUSION" >> $GITHUB_OUTPUT
fi
- name: Post Status to Discord
uses: sarisia/actions-status-discord@v1
diff --git a/.gitignore b/.gitignore
index 4f7c3ce6cb..6e051447e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,6 @@ cypress/screenshots
# TS Build Info
tsconfig.tsbuildinfo
+
+# Config Cache Directory
+config/cache
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 45da7ba676..1a23757129 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -16,5 +16,8 @@
}
],
"editor.formatOnSave": true,
- "typescript.preferences.importModuleSpecifier": "non-relative"
+ "typescript.preferences.importModuleSpecifier": "non-relative",
+ "files.associations": {
+ "globals.css": "tailwindcss"
+ }
}
diff --git a/Dockerfile b/Dockerfile
index 851ba47216..949bf59628 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:16.17-alpine AS BUILD_IMAGE
+FROM node:18.18-alpine AS BUILD_IMAGE
WORKDIR /app
@@ -7,10 +7,11 @@ ENV TARGETPLATFORM=${TARGETPLATFORM:-linux/amd64}
RUN \
case "${TARGETPLATFORM}" in \
- 'linux/arm64' | 'linux/arm/v7') \
- apk add --no-cache python3 make g++ && \
- ln -s /usr/bin/python3 /usr/bin/python \
- ;; \
+ 'linux/arm64' | 'linux/arm/v7') \
+ apk update && \
+ apk add --no-cache python3 make g++ gcc libc6-compat bash && \
+ yarn global add node-gyp \
+ ;; \
esac
COPY package.json yarn.lock ./
@@ -33,7 +34,7 @@ RUN touch config/DOCKER
RUN echo "{\"commitTag\": \"${COMMIT_TAG}\"}" > committag.json
-FROM node:16.17-alpine
+FROM node:18.18-alpine
WORKDIR /app
diff --git a/Dockerfile.local b/Dockerfile.local
index 39e0534f32..7efa68b51d 100644
--- a/Dockerfile.local
+++ b/Dockerfile.local
@@ -1,4 +1,4 @@
-FROM node:16.17-alpine
+FROM node:18.18-alpine
COPY . /app
WORKDIR /app
diff --git a/README.md b/README.md
index 05de02e235..b5fa8824be 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,9 @@
-
-
+
@@ -74,110 +73,137 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
diff --git a/cypress/config/settings.cypress.json b/cypress/config/settings.cypress.json
index bb7b661b0a..7a4bbef5d6 100644
--- a/cypress/config/settings.cypress.json
+++ b/cypress/config/settings.cypress.json
@@ -3,147 +3,147 @@
"vapidPrivate": "tmnslaO8ZWN6bNbSEv_rolPeBTlNxOwCCAHrM9oZz3M",
"vapidPublic": "BK_EpP8NDm9waor2zn6_S28o3ZYv4kCkJOfYpO3pt3W6jnPmxrgTLANUBNbbyaNatPnSQ12De9CeqSYQrqWzHTs",
"main": {
- "apiKey": "testkey",
- "applicationTitle": "Overseerr",
- "applicationUrl": "",
- "csrfProtection": false,
- "cacheImages": false,
- "defaultPermissions": 32,
- "defaultQuotas": {
- "movie": {},
- "tv": {}
- },
- "hideAvailable": false,
- "localLogin": true,
- "newPlexLogin": true,
- "region": "",
- "originalLanguage": "",
- "trustProxy": false,
- "partialRequestsEnabled": true,
- "locale": "en"
+ "apiKey": "testkey",
+ "applicationTitle": "Overseerr",
+ "applicationUrl": "",
+ "csrfProtection": false,
+ "cacheImages": false,
+ "defaultPermissions": 32,
+ "defaultQuotas": {
+ "movie": {},
+ "tv": {}
+ },
+ "hideAvailable": false,
+ "localLogin": true,
+ "newPlexLogin": true,
+ "region": "",
+ "originalLanguage": "",
+ "trustProxy": false,
+ "partialRequestsEnabled": true,
+ "locale": "en"
},
"plex": {
- "name": "Seerr",
- "ip": "192.168.1.1",
- "port": 32400,
- "useSsl": false,
- "libraries": [
- {
- "id": "1",
- "name": "Movies",
- "enabled": true,
- "type": "movie"
- }
- ],
- "machineId": "test"
+ "name": "Seerr",
+ "ip": "192.168.1.1",
+ "port": 32400,
+ "useSsl": false,
+ "libraries": [
+ {
+ "id": "1",
+ "name": "Movies",
+ "enabled": true,
+ "type": "movie"
+ }
+ ],
+ "machineId": "test"
},
"tautulli": {},
"radarr": [],
"sonarr": [],
"public": {
- "initialized": true
+ "initialized": true
},
"notifications": {
- "agents": {
- "email": {
- "enabled": false,
- "options": {
- "emailFrom": "",
- "smtpHost": "",
- "smtpPort": 587,
- "secure": false,
- "ignoreTls": false,
- "requireTls": false,
- "allowSelfSigned": false,
- "senderName": "Overseerr"
- }
- },
- "discord": {
- "enabled": false,
- "types": 0,
- "options": {
- "webhookUrl": "",
- "enableMentions": true
- }
- },
- "lunasea": {
- "enabled": false,
- "types": 0,
- "options": {
- "webhookUrl": ""
- }
- },
- "slack": {
- "enabled": false,
- "types": 0,
- "options": {
- "webhookUrl": ""
- }
- },
- "telegram": {
- "enabled": false,
- "types": 0,
- "options": {
- "botAPI": "",
- "chatId": "",
- "sendSilently": false
- }
+ "agents": {
+ "email": {
+ "enabled": false,
+ "options": {
+ "emailFrom": "",
+ "smtpHost": "",
+ "smtpPort": 587,
+ "secure": false,
+ "ignoreTls": false,
+ "requireTls": false,
+ "allowSelfSigned": false,
+ "senderName": "Overseerr"
+ }
+ },
+ "discord": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "webhookUrl": "",
+ "enableMentions": true
+ }
+ },
+ "lunasea": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "webhookUrl": ""
+ }
+ },
+ "slack": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "webhookUrl": ""
+ }
+ },
+ "telegram": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "botAPI": "",
+ "chatId": "",
+ "sendSilently": false
+ }
+ },
+ "pushbullet": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "accessToken": ""
+ }
+ },
+ "pushover": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "accessToken": "",
+ "userToken": ""
+ }
+ },
+ "webhook": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "webhookUrl": "",
+ "jsonPayload": "IntcbiAgICBcIm5vdGlmaWNhdGlvbl90eXBlXCI6IFwie3tub3RpZmljYXRpb25fdHlwZX19XCIsXG4gICAgXCJldmVudFwiOiBcInt7ZXZlbnR9fVwiLFxuICAgIFwic3ViamVjdFwiOiBcInt7c3ViamVjdH19XCIsXG4gICAgXCJtZXNzYWdlXCI6IFwie3ttZXNzYWdlfX1cIixcbiAgICBcImltYWdlXCI6IFwie3tpbWFnZX19XCIsXG4gICAgXCJ7e21lZGlhfX1cIjoge1xuICAgICAgICBcIm1lZGlhX3R5cGVcIjogXCJ7e21lZGlhX3R5cGV9fVwiLFxuICAgICAgICBcInRtZGJJZFwiOiBcInt7bWVkaWFfdG1kYmlkfX1cIixcbiAgICAgICAgXCJ0dmRiSWRcIjogXCJ7e21lZGlhX3R2ZGJpZH19XCIsXG4gICAgICAgIFwic3RhdHVzXCI6IFwie3ttZWRpYV9zdGF0dXN9fVwiLFxuICAgICAgICBcInN0YXR1czRrXCI6IFwie3ttZWRpYV9zdGF0dXM0a319XCJcbiAgICB9LFxuICAgIFwie3tyZXF1ZXN0fX1cIjoge1xuICAgICAgICBcInJlcXVlc3RfaWRcIjogXCJ7e3JlcXVlc3RfaWR9fVwiLFxuICAgICAgICBcInJlcXVlc3RlZEJ5X2VtYWlsXCI6IFwie3tyZXF1ZXN0ZWRCeV9lbWFpbH19XCIsXG4gICAgICAgIFwicmVxdWVzdGVkQnlfdXNlcm5hbWVcIjogXCJ7e3JlcXVlc3RlZEJ5X3VzZXJuYW1lfX1cIixcbiAgICAgICAgXCJyZXF1ZXN0ZWRCeV9hdmF0YXJcIjogXCJ7e3JlcXVlc3RlZEJ5X2F2YXRhcn19XCJcbiAgICB9LFxuICAgIFwie3tpc3N1ZX19XCI6IHtcbiAgICAgICAgXCJpc3N1ZV9pZFwiOiBcInt7aXNzdWVfaWR9fVwiLFxuICAgICAgICBcImlzc3VlX3R5cGVcIjogXCJ7e2lzc3VlX3R5cGV9fVwiLFxuICAgICAgICBcImlzc3VlX3N0YXR1c1wiOiBcInt7aXNzdWVfc3RhdHVzfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X2VtYWlsXCI6IFwie3tyZXBvcnRlZEJ5X2VtYWlsfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X3VzZXJuYW1lXCI6IFwie3tyZXBvcnRlZEJ5X3VzZXJuYW1lfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X2F2YXRhclwiOiBcInt7cmVwb3J0ZWRCeV9hdmF0YXJ9fVwiXG4gICAgfSxcbiAgICBcInt7Y29tbWVudH19XCI6IHtcbiAgICAgICAgXCJjb21tZW50X21lc3NhZ2VcIjogXCJ7e2NvbW1lbnRfbWVzc2FnZX19XCIsXG4gICAgICAgIFwiY29tbWVudGVkQnlfZW1haWxcIjogXCJ7e2NvbW1lbnRlZEJ5X2VtYWlsfX1cIixcbiAgICAgICAgXCJjb21tZW50ZWRCeV91c2VybmFtZVwiOiBcInt7Y29tbWVudGVkQnlfdXNlcm5hbWV9fVwiLFxuICAgICAgICBcImNvbW1lbnRlZEJ5X2F2YXRhclwiOiBcInt7Y29tbWVudGVkQnlfYXZhdGFyfX1cIlxuICAgIH0sXG4gICAgXCJ7e2V4dHJhfX1cIjogW11cbn0i"
+ }
+ },
+ "webpush": {
+ "enabled": false,
+ "options": {}
+ },
+ "gotify": {
+ "enabled": false,
+ "types": 0,
+ "options": {
+ "url": "",
+ "token": ""
+ }
+ }
+ }
+ },
+ "jobs": {
+ "plex-recently-added-scan": {
+ "schedule": "0 */5 * * * *"
},
- "pushbullet": {
- "enabled": false,
- "types": 0,
- "options": {
- "accessToken": ""
- }
+ "plex-full-scan": {
+ "schedule": "0 0 3 * * *"
},
- "pushover": {
- "enabled": false,
- "types": 0,
- "options": {
- "accessToken": "",
- "userToken": ""
- }
+ "radarr-scan": {
+ "schedule": "0 0 4 * * *"
},
- "webhook": {
- "enabled": false,
- "types": 0,
- "options": {
- "webhookUrl": "",
- "jsonPayload": "IntcbiAgICBcIm5vdGlmaWNhdGlvbl90eXBlXCI6IFwie3tub3RpZmljYXRpb25fdHlwZX19XCIsXG4gICAgXCJldmVudFwiOiBcInt7ZXZlbnR9fVwiLFxuICAgIFwic3ViamVjdFwiOiBcInt7c3ViamVjdH19XCIsXG4gICAgXCJtZXNzYWdlXCI6IFwie3ttZXNzYWdlfX1cIixcbiAgICBcImltYWdlXCI6IFwie3tpbWFnZX19XCIsXG4gICAgXCJ7e21lZGlhfX1cIjoge1xuICAgICAgICBcIm1lZGlhX3R5cGVcIjogXCJ7e21lZGlhX3R5cGV9fVwiLFxuICAgICAgICBcInRtZGJJZFwiOiBcInt7bWVkaWFfdG1kYmlkfX1cIixcbiAgICAgICAgXCJ0dmRiSWRcIjogXCJ7e21lZGlhX3R2ZGJpZH19XCIsXG4gICAgICAgIFwic3RhdHVzXCI6IFwie3ttZWRpYV9zdGF0dXN9fVwiLFxuICAgICAgICBcInN0YXR1czRrXCI6IFwie3ttZWRpYV9zdGF0dXM0a319XCJcbiAgICB9LFxuICAgIFwie3tyZXF1ZXN0fX1cIjoge1xuICAgICAgICBcInJlcXVlc3RfaWRcIjogXCJ7e3JlcXVlc3RfaWR9fVwiLFxuICAgICAgICBcInJlcXVlc3RlZEJ5X2VtYWlsXCI6IFwie3tyZXF1ZXN0ZWRCeV9lbWFpbH19XCIsXG4gICAgICAgIFwicmVxdWVzdGVkQnlfdXNlcm5hbWVcIjogXCJ7e3JlcXVlc3RlZEJ5X3VzZXJuYW1lfX1cIixcbiAgICAgICAgXCJyZXF1ZXN0ZWRCeV9hdmF0YXJcIjogXCJ7e3JlcXVlc3RlZEJ5X2F2YXRhcn19XCJcbiAgICB9LFxuICAgIFwie3tpc3N1ZX19XCI6IHtcbiAgICAgICAgXCJpc3N1ZV9pZFwiOiBcInt7aXNzdWVfaWR9fVwiLFxuICAgICAgICBcImlzc3VlX3R5cGVcIjogXCJ7e2lzc3VlX3R5cGV9fVwiLFxuICAgICAgICBcImlzc3VlX3N0YXR1c1wiOiBcInt7aXNzdWVfc3RhdHVzfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X2VtYWlsXCI6IFwie3tyZXBvcnRlZEJ5X2VtYWlsfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X3VzZXJuYW1lXCI6IFwie3tyZXBvcnRlZEJ5X3VzZXJuYW1lfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X2F2YXRhclwiOiBcInt7cmVwb3J0ZWRCeV9hdmF0YXJ9fVwiXG4gICAgfSxcbiAgICBcInt7Y29tbWVudH19XCI6IHtcbiAgICAgICAgXCJjb21tZW50X21lc3NhZ2VcIjogXCJ7e2NvbW1lbnRfbWVzc2FnZX19XCIsXG4gICAgICAgIFwiY29tbWVudGVkQnlfZW1haWxcIjogXCJ7e2NvbW1lbnRlZEJ5X2VtYWlsfX1cIixcbiAgICAgICAgXCJjb21tZW50ZWRCeV91c2VybmFtZVwiOiBcInt7Y29tbWVudGVkQnlfdXNlcm5hbWV9fVwiLFxuICAgICAgICBcImNvbW1lbnRlZEJ5X2F2YXRhclwiOiBcInt7Y29tbWVudGVkQnlfYXZhdGFyfX1cIlxuICAgIH0sXG4gICAgXCJ7e2V4dHJhfX1cIjogW11cbn0i"
- }
+ "sonarr-scan": {
+ "schedule": "0 30 4 * * *"
},
- "webpush": {
- "enabled": false,
- "options": {}
+ "download-sync": {
+ "schedule": "0 * * * * *"
},
- "gotify": {
- "enabled": false,
- "types": 0,
- "options": {
- "url": "",
- "token": ""
- }
+ "download-sync-reset": {
+ "schedule": "0 0 1 * * *"
}
- }
- },
- "jobs": {
- "plex-recently-added-scan": {
- "schedule": "0 */5 * * * *"
- },
- "plex-full-scan": {
- "schedule": "0 0 3 * * *"
- },
- "radarr-scan": {
- "schedule": "0 0 4 * * *"
- },
- "sonarr-scan": {
- "schedule": "0 30 4 * * *"
- },
- "download-sync": {
- "schedule": "0 * * * * *"
- },
- "download-sync-reset": {
- "schedule": "0 0 1 * * *"
- }
}
- }
+}
diff --git a/cypress/e2e/discover.cy.ts b/cypress/e2e/discover.cy.ts
index 3489061b0e..545f25658b 100644
--- a/cypress/e2e/discover.cy.ts
+++ b/cypress/e2e/discover.cy.ts
@@ -36,7 +36,9 @@ describe('Discover', () => {
});
it('loads upcoming movies', () => {
- cy.intercept('/api/v1/discover/movies/upcoming*').as('getUpcomingMovies');
+ cy.intercept('/api/v1/discover/movies?page=1&primaryReleaseDateGte*').as(
+ 'getUpcomingMovies'
+ );
cy.visit('/');
cy.wait('@getUpcomingMovies');
clickFirstTitleCardInSlider('Upcoming Movies');
@@ -50,7 +52,9 @@ describe('Discover', () => {
});
it('loads upcoming series', () => {
- cy.intercept('/api/v1/discover/tv/upcoming*').as('getUpcomingSeries');
+ cy.intercept('/api/v1/discover/tv?page=1&firstAirDateGte=*').as(
+ 'getUpcomingSeries'
+ );
cy.visit('/');
cy.wait('@getUpcomingSeries');
clickFirstTitleCardInSlider('Upcoming Series');
diff --git a/cypress/e2e/pull-to-refresh.cy.ts b/cypress/e2e/pull-to-refresh.cy.ts
index d56c55897a..732ee41377 100644
--- a/cypress/e2e/pull-to-refresh.cy.ts
+++ b/cypress/e2e/pull-to-refresh.cy.ts
@@ -13,7 +13,7 @@ describe('Pull To Refresh', () => {
url: '/api/v1/*',
}).as('apiCall');
- cy.get('.searchbar').swipe('bottom', [190, 400]);
+ cy.get('.searchbar').swipe('bottom', [190, 500]);
cy.wait('@apiCall').then((interception) => {
assert.isNotNull(
diff --git a/cypress/e2e/settings/discover-customization.cy.ts b/cypress/e2e/settings/discover-customization.cy.ts
new file mode 100644
index 0000000000..469994a3fb
--- /dev/null
+++ b/cypress/e2e/settings/discover-customization.cy.ts
@@ -0,0 +1,163 @@
+describe('Discover Customization', () => {
+ beforeEach(() => {
+ cy.loginAsAdmin();
+ cy.intercept('/api/v1/settings/discover').as('getDiscoverSliders');
+ });
+
+ it('show the discover customization settings', () => {
+ cy.visit('/');
+
+ cy.get('[data-testid=discover-start-editing]').click();
+
+ cy.get('[data-testid=create-slider-header')
+ .should('contain', 'Create New Slider')
+ .scrollIntoView();
+
+ // There should be some built in options
+ cy.get('[data-testid=discover-slider-edit-mode]').should(
+ 'contain',
+ 'Recently Added'
+ );
+ cy.get('[data-testid=discover-slider-edit-mode]').should(
+ 'contain',
+ 'Recent Requests'
+ );
+ });
+
+ it('can drag to re-order elements and save to persist the changes', () => {
+ let dataTransfer = new DataTransfer();
+ cy.visit('/');
+
+ cy.get('[data-testid=discover-start-editing]').click();
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .first()
+ .trigger('dragstart', { dataTransfer });
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .eq(1)
+ .trigger('drop', { dataTransfer });
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .eq(1)
+ .trigger('dragend', { dataTransfer });
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .eq(1)
+ .should('contain', 'Recently Added');
+
+ cy.get('[data-testid=discover-customize-submit').click();
+ cy.wait('@getDiscoverSliders');
+
+ cy.reload();
+
+ cy.get('[data-testid=discover-start-editing]').click();
+
+ dataTransfer = new DataTransfer();
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .eq(1)
+ .should('contain', 'Recently Added');
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .first()
+ .trigger('dragstart', { dataTransfer });
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .eq(1)
+ .trigger('drop', { dataTransfer });
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .eq(1)
+ .trigger('dragend', { dataTransfer });
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .eq(1)
+ .should('contain', 'Recent Requests');
+
+ cy.get('[data-testid=discover-customize-submit').click();
+ cy.wait('@getDiscoverSliders');
+ });
+
+ it('can create a new discover option and remove it', () => {
+ cy.visit('/');
+ cy.intercept('/api/v1/settings/discover/*').as('discoverSlider');
+ cy.intercept('/api/v1/search/keyword*').as('searchKeyword');
+
+ cy.get('[data-testid=discover-start-editing]').click();
+
+ const sliderTitle = 'Custom Keyword Slider';
+
+ cy.get('#sliderType').select('TMDB Movie Keyword');
+
+ cy.get('#title').type(sliderTitle);
+ // First confirm that an invalid keyword doesn't allow us to submit anything
+ cy.get('#data').type('invalidkeyword{enter}', { delay: 100 });
+ cy.wait('@searchKeyword');
+
+ cy.get('[data-testid=create-discover-option-form]')
+ .find('button')
+ .should('be.disabled');
+
+ cy.get('#data').clear();
+ cy.get('#data').type('christmas{enter}', { delay: 100 });
+
+ // Confirming we have some results
+ cy.contains('.slider-header', sliderTitle)
+ .next('[data-testid=media-slider]')
+ .find('[data-testid=title-card]');
+
+ cy.get('[data-testid=create-discover-option-form]').submit();
+
+ cy.wait('@discoverSlider');
+ cy.wait('@getDiscoverSliders');
+ cy.wait(1000);
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .first()
+ .should('contain', sliderTitle);
+
+ // Make sure its still there even if we reload
+ cy.reload();
+
+ cy.get('[data-testid=discover-start-editing]').click();
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .first()
+ .should('contain', sliderTitle);
+
+ // Verify it's not rendering on our discover page (its still disabled!)
+ cy.visit('/');
+
+ cy.get('.slider-header').should('not.contain', sliderTitle);
+
+ cy.get('[data-testid=discover-start-editing]').click();
+
+ // Enable it, and check again
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .first()
+ .find('[role="checkbox"]')
+ .click();
+
+ cy.get('[data-testid=discover-customize-submit').click();
+ cy.wait('@getDiscoverSliders');
+
+ cy.visit('/');
+
+ cy.contains('.slider-header', sliderTitle)
+ .next('[data-testid=media-slider]')
+ .find('[data-testid=title-card]');
+
+ cy.get('[data-testid=discover-start-editing]').click();
+
+ // let's delete it and confirm its deleted.
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .first()
+ .find('[data-testid=discover-slider-remove-button]')
+ .click();
+
+ cy.wait('@discoverSlider');
+ cy.wait('@getDiscoverSliders');
+ cy.wait(1000);
+
+ cy.get('[data-testid=discover-slider-edit-mode]')
+ .first()
+ .should('not.contain', sliderTitle);
+ });
+});
diff --git a/cypress/e2e/settings/general-settings.cy.ts b/cypress/e2e/settings/general-settings.cy.ts
index 3717f65b08..bcfce1a328 100644
--- a/cypress/e2e/settings/general-settings.cy.ts
+++ b/cypress/e2e/settings/general-settings.cy.ts
@@ -16,7 +16,7 @@ describe('General Settings', () => {
cy.visit('/settings');
cy.get('#trustProxy').click();
- cy.get('form').submit();
+ cy.get('[data-testid=settings-main-form]').submit();
cy.get('[data-testid=modal-title]').should(
'contain',
'Server Restart Required'
@@ -26,7 +26,7 @@ describe('General Settings', () => {
cy.get('[data-testid=modal-title]').should('not.exist');
cy.get('[type=checkbox]#trustProxy').click();
- cy.get('form').submit();
+ cy.get('[data-testid=settings-main-form]').submit();
cy.get('[data-testid=modal-title]').should('not.exist');
});
});
diff --git a/docs/extending-overseerr/fail2ban.md b/docs/extending-overseerr/fail2ban.md
index 1cf9131f0f..4f2b1c5941 100644
--- a/docs/extending-overseerr/fail2ban.md
+++ b/docs/extending-overseerr/fail2ban.md
@@ -11,4 +11,4 @@ To use Fail2ban with Overseerr, create a new file named `overseerr.local` in you
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.
+You can then add a jail using this filter in `jail.local`. Please see the [Fail2ban documentation](https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Jails) for details on how to configure the jail.
diff --git a/docs/extending-overseerr/reverse-proxy.md b/docs/extending-overseerr/reverse-proxy.md
index 84752f7c2c..ec456fdbc1 100644
--- a/docs/extending-overseerr/reverse-proxy.md
+++ b/docs/extending-overseerr/reverse-proxy.md
@@ -141,7 +141,7 @@ location ^~ /overseerr {
sub_filter '\/_next' '\/$app\/_next';
sub_filter '/_next' '/$app/_next';
sub_filter '/api/v1' '/$app/api/v1';
- sub_filter '/login/plex/loading' '/$app/login/plex/loading';
+ sub_filter '/login/popup/loading' '/$app/login/popup/loading';
sub_filter '/images/' '/$app/images/';
sub_filter '/android-' '/$app/android-';
sub_filter '/apple-' '/$app/apple-';
diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md
index 98e26f59f7..abaef46aae 100644
--- a/docs/getting-started/installation.md
+++ b/docs/getting-started/installation.md
@@ -28,6 +28,7 @@ docker run -d \
--name overseerr \
-e LOG_LEVEL=debug \
-e TZ=Asia/Tokyo \
+ -e PORT=5055 `#optional` \
-p 5055:5055 \
-v /path/to/appdata/config:/app/config \
--restart unless-stopped \
@@ -81,6 +82,7 @@ services:
environment:
- LOG_LEVEL=debug
- TZ=Asia/Tokyo
+ - PORT=5055 #optional
ports:
- 5055:5055
volumes:
@@ -88,7 +90,7 @@ services:
restart: unless-stopped
```
-Then, start all services defined in the your Compose file:
+Then, start all services defined in the Compose file:
```bash
docker-compose up -d
@@ -146,8 +148,6 @@ Then, create and start the Overseerr container:
docker run -d --name overseerr -e LOG_LEVEL=debug -e TZ=Asia/Tokyo -p 5055:5055 -v "overseerr-data:/app/config" --restart unless-stopped sctx/overseerr:latest
```
-If using a named volume like above, you can safely ignore the warning about the `/app/config` folder being incorrectly mounted on the setup page.
-
To access the files inside the volume created above, navigate to `\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\overseerr-data\_data` using File Explorer.
{% hint style="info" %}
@@ -155,7 +155,7 @@ Docker on Windows works differently than it does on Linux; it runs Docker inside
**If you must run Docker on Windows, you should put the `/app/config` directory mount inside the VM and not on the Windows host.** (This also applies to other containers with SQLite databases.)
-Named volumes, like in the example commands above, are automatically mounted inside the VM.
+Named volumes, like in the example commands above, are automatically mounted inside the VM. Therefore the warning on the setup about the `/app/config` folder being incorrectly mounted page should be ignored.
{% endhint %}
## Linux
diff --git a/docs/using-overseerr/settings/README.md b/docs/using-overseerr/settings/README.md
index 820430736e..477129fc91 100644
--- a/docs/using-overseerr/settings/README.md
+++ b/docs/using-overseerr/settings/README.md
@@ -40,6 +40,14 @@ If you enable this setting and find yourself unable to access Overseerr, you can
This setting is **disabled** by default.
+### Enable Image Caching
+
+When enabled, Overseerr will proxy and cache images from pre-configured sources (such as TMDB). This can use a significant amount of disk space.
+
+Images are saved in the `config/cache/images` and stale images are cleared out every 24 hours.
+
+You should enable this if you are having issues with loading images directly from TMDB in your browser.
+
### Display Language
Set the default display language for Overseerr. Users can override this setting in their user settings.
diff --git a/next.config.js b/next.config.js
index b0e872e885..9cd65f9734 100644
--- a/next.config.js
+++ b/next.config.js
@@ -19,5 +19,6 @@ module.exports = {
},
experimental: {
scrollRestoration: true,
+ largePageDataBytes: 256000,
},
};
diff --git a/overseerr-api.yml b/overseerr-api.yml
index 164187de3d..ea800b708f 100644
--- a/overseerr-api.yml
+++ b/overseerr-api.yml
@@ -26,6 +26,8 @@ tags:
description: Endpoints related to retrieving movies and their details.
- name: tv
description: Endpoints related to retrieving TV series and their details.
+ - name: other
+ description: Endpoints related to other TMDB data
- name: person
description: Endpoints related to retrieving person details.
- name: media
@@ -600,6 +602,17 @@ components:
name:
type: string
example: Adventure
+ Company:
+ type: object
+ properties:
+ id:
+ type: number
+ example: 1
+ logo_path:
+ type: string
+ nullable: true
+ name:
+ type: string
ProductionCompany:
type: object
properties:
@@ -1039,6 +1052,8 @@ components:
nullable: true
status:
type: number
+ example: 0
+ description: Availability of the media. 1 = `UNKNOWN`, 2 = `PENDING`, 3 = `PROCESSING`, 4 = `PARTIALLY_AVAILABLE`, 5 = `AVAILABLE`
requests:
type: array
readOnly: true
@@ -1258,6 +1273,8 @@ components:
type: string
userToken:
type: string
+ sound:
+ type: string
GotifySettings:
type: object
properties:
@@ -1693,6 +1710,9 @@ components:
pushoverUserKey:
type: string
nullable: true
+ pushoverSound:
+ type: string
+ nullable: true
telegramEnabled:
type: boolean
telegramBotUsername:
@@ -1780,6 +1800,40 @@ components:
message:
type: string
example: A comment
+ DiscoverSlider:
+ type: object
+ properties:
+ id:
+ type: number
+ example: 1
+ type:
+ type: number
+ example: 1
+ title:
+ type: string
+ nullable: true
+ isBuiltIn:
+ type: boolean
+ enabled:
+ type: boolean
+ data:
+ type: string
+ example: '1234'
+ nullable: true
+ required:
+ - type
+ - enabled
+ - title
+ - data
+ WatchProviderRegion:
+ type: object
+ properties:
+ iso_3166_1:
+ type: string
+ english_name:
+ type: string
+ native_name:
+ type: string
securitySchemes:
cookieAuth:
type: apiKey
@@ -2475,29 +2529,44 @@ paths:
content:
application/json:
schema:
- type: array
- items:
- type: object
- properties:
- id:
- type: string
- example: cache-id
- name:
- type: string
- example: cache name
- stats:
+ type: object
+ properties:
+ imageCache:
+ type: object
+ properties:
+ tmdb:
+ type: object
+ properties:
+ size:
+ type: number
+ example: 123456
+ imageCount:
+ type: number
+ example: 123
+ apiCaches:
+ type: array
+ items:
type: object
properties:
- hits:
- type: number
- misses:
- type: number
- keys:
- type: number
- ksize:
- type: number
- vsize:
- type: number
+ id:
+ type: string
+ example: cache-id
+ name:
+ type: string
+ example: cache name
+ stats:
+ type: object
+ properties:
+ hits:
+ type: number
+ misses:
+ type: number
+ keys:
+ type: number
+ ksize:
+ type: number
+ vsize:
+ type: number
/settings/cache/{cacheId}/flush:
post:
summary: Flush a specific cache
@@ -2797,6 +2866,33 @@ paths:
responses:
'204':
description: Test notification attempted
+ /settings/notifications/pushover/sounds:
+ get:
+ summary: Get Pushover sounds
+ description: Returns valid Pushover sound options in a JSON array.
+ tags:
+ - settings
+ parameters:
+ - in: query
+ name: token
+ required: true
+ schema:
+ type: string
+ nullable: false
+ responses:
+ '200':
+ description: Returned Pushover settings
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ description:
+ type: string
/settings/notifications/gotify:
get:
summary: Get Gotify notification settings
@@ -3027,6 +3123,133 @@ paths:
responses:
'204':
description: Test notification attempted
+ /settings/discover:
+ get:
+ summary: Get all discover sliders
+ description: Returns all discovery sliders. Built-in and custom made.
+ tags:
+ - settings
+ responses:
+ '200':
+ description: Returned all discovery sliders
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/DiscoverSlider'
+ post:
+ summary: Batch update all sliders.
+ description: |
+ Batch update all sliders at once. Should also be used for creation. Will only update sliders provided
+ and will not delete any sliders not present in the request. If a slider is missing a required field,
+ it will be ignored. Requires the `ADMIN` permission.
+ tags:
+ - settings
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/DiscoverSlider'
+ responses:
+ '200':
+ description: Returned all newly updated discovery sliders
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/DiscoverSlider'
+ /settings/discover/{sliderId}:
+ put:
+ summary: Update a single slider
+ description: |
+ Updates a single slider and return the newly updated slider. Requires the `ADMIN` permission.
+ tags:
+ - settings
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ title:
+ type: string
+ example: 'Slider Title'
+ type:
+ type: number
+ example: 1
+ data:
+ type: string
+ example: '1'
+ responses:
+ '200':
+ description: Returns newly added discovery slider
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscoverSlider'
+ delete:
+ summary: Delete slider by ID
+ description: Deletes the slider with the provided sliderId. Requires the `ADMIN` permission.
+ tags:
+ - settings
+ parameters:
+ - in: path
+ name: sliderId
+ required: true
+ schema:
+ type: number
+ responses:
+ '200':
+ description: Slider successfully deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscoverSlider'
+ /settings/discover/add:
+ post:
+ summary: Add a new slider
+ description: |
+ Add a single slider and return the newly created slider. Requires the `ADMIN` permission.
+ tags:
+ - settings
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ title:
+ type: string
+ example: 'New Slider'
+ type:
+ type: number
+ example: 1
+ data:
+ type: string
+ example: '1'
+ responses:
+ '200':
+ description: Returns newly added discovery slider
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscoverSlider'
+ /settings/discover/reset:
+ get:
+ summary: Reset all discover sliders
+ description: Resets all discovery sliders to the default values. Requires the `ADMIN` permission.
+ tags:
+ - settings
+ responses:
+ '204':
+ description: All sliders reset to defaults
/settings/about:
get:
summary: Get server stats
@@ -3206,6 +3429,80 @@ paths:
type: string
required:
- password
+ /auth/oidc-login:
+ get:
+ security: []
+ summary: Redirect to the OpenID Connect provider
+ description: Constructs the redirect URL to the OpenID Connect provider, and redirects the user to it.
+ tags:
+ - auth
+ responses:
+ '302':
+ description: Redirect to the authentication url for the OpenID Connect provider
+ headers:
+ Location:
+ schema:
+ type: string
+ example: https://example.com/auth/oidc/callback?response_type=code&client_id=client_id&redirect_uri=https%3A%2F%2Fexample.com%2Fauth%2Foidc%2Fcallback&scope=openid%20email&state=state
+ Set-Cookie:
+ schema:
+ type: string
+ example: 'oidc-state=123456789; HttpOnly; max-age=60000; Secure'
+ /auth/oidc-callback:
+ get:
+ security: []
+ summary: The callback endpoint for the OpenID Connect provider redirect
+ description: Takes the `code` and `state` parameters from the OpenID Connect provider, and exchanges them for a token.
+ parameters:
+ - in: query
+ name: code
+ required: true
+ schema:
+ type: string
+ example: '123456789'
+ - in: query
+ name: state
+ required: true
+ schema:
+ type: string
+ example: '123456789'
+ - in: query
+ name: scope
+ required: false
+ allowReserved: true
+ schema:
+ type: string
+ example: 'openid email profile'
+ - in: query
+ name: error
+ required: false
+ schema:
+ type: string
+ - in: query
+ name: error_description
+ required: false
+ schema:
+ type: string
+ - in: cookie
+ name: oidc-state
+ required: true
+ schema:
+ type: string
+ example: '123456789'
+ tags:
+ - auth
+ responses:
+ '302':
+ description: A redirect to the home page if successful or back to the login page if not
+ headers:
+ Location:
+ schema:
+ type: string
+ example: /
+ Set-Cookie:
+ schema:
+ type: string
+ example: 'oidc-state=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
/user:
get:
summary: Get all users
@@ -3424,7 +3721,7 @@ paths:
$ref: '#/components/schemas/User'
/user/{userId}/requests:
get:
- summary: Get user by ID
+ summary: Get requests for a specific user
description: |
Retrieves a user's requests in a JSON object.
tags:
@@ -3520,7 +3817,7 @@ paths:
example: false
/user/{userId}/watchlist:
get:
- summary: Get user by ID
+ summary: Get the Plex watchlist for a specific user
description: |
Retrieves a user's Plex Watchlist in a JSON object.
tags:
@@ -3847,6 +4144,86 @@ paths:
- $ref: '#/components/schemas/MovieResult'
- $ref: '#/components/schemas/TvResult'
- $ref: '#/components/schemas/PersonResult'
+ /search/keyword:
+ get:
+ summary: Search for keywords
+ description: Returns a list of TMDB keywords matching the search query
+ tags:
+ - search
+ parameters:
+ - in: query
+ name: query
+ required: true
+ schema:
+ type: string
+ example: 'christmas'
+ - in: query
+ name: page
+ schema:
+ type: number
+ example: 1
+ default: 1
+ responses:
+ '200':
+ description: Results
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ page:
+ type: number
+ example: 1
+ totalPages:
+ type: number
+ example: 20
+ totalResults:
+ type: number
+ example: 200
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/Keyword'
+ /search/company:
+ get:
+ summary: Search for companies
+ description: Returns a list of TMDB companies matching the search query. (Will not return origin country)
+ tags:
+ - search
+ parameters:
+ - in: query
+ name: query
+ required: true
+ schema:
+ type: string
+ example: 'Disney'
+ - in: query
+ name: page
+ schema:
+ type: number
+ example: 1
+ default: 1
+ responses:
+ '200':
+ description: Results
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ page:
+ type: number
+ example: 1
+ totalPages:
+ type: number
+ example: 20
+ totalResults:
+ type: number
+ example: 200
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/Company'
/discover/movies:
get:
summary: Discover movies
@@ -3868,13 +4245,73 @@ paths:
- in: query
name: genre
schema:
- type: number
+ type: string
example: 18
- in: query
name: studio
schema:
type: number
example: 1
+ - in: query
+ name: keywords
+ schema:
+ type: string
+ example: 1,2
+ - in: query
+ name: sortBy
+ schema:
+ type: string
+ example: popularity.desc
+ - in: query
+ name: primaryReleaseDateGte
+ schema:
+ type: string
+ example: 2022-01-01
+ - in: query
+ name: primaryReleaseDateLte
+ schema:
+ type: string
+ example: 2023-01-01
+ - in: query
+ name: withRuntimeGte
+ schema:
+ type: number
+ example: 60
+ - in: query
+ name: withRuntimeLte
+ schema:
+ type: number
+ example: 120
+ - in: query
+ name: voteAverageGte
+ schema:
+ type: number
+ example: 7
+ - in: query
+ name: voteAverageLte
+ schema:
+ type: number
+ example: 10
+ - in: query
+ name: voteCountGte
+ schema:
+ type: number
+ example: 7
+ - in: query
+ name: voteCountLte
+ schema:
+ type: number
+ example: 10
+ - in: query
+ name: watchRegion
+ schema:
+ type: string
+ example: US
+ - in: query
+ name: watchProviders
+ schema:
+ type: string
+ example: 8|9
responses:
'200':
description: Results
@@ -4097,13 +4534,73 @@ paths:
- in: query
name: genre
schema:
- type: number
+ type: string
example: 18
- in: query
name: network
schema:
type: number
example: 1
+ - in: query
+ name: keywords
+ schema:
+ type: string
+ example: 1,2
+ - in: query
+ name: sortBy
+ schema:
+ type: string
+ example: popularity.desc
+ - in: query
+ name: firstAirDateGte
+ schema:
+ type: string
+ example: 2022-01-01
+ - in: query
+ name: firstAirDateLte
+ schema:
+ type: string
+ example: 2023-01-01
+ - in: query
+ name: withRuntimeGte
+ schema:
+ type: number
+ example: 60
+ - in: query
+ name: withRuntimeLte
+ schema:
+ type: number
+ example: 120
+ - in: query
+ name: voteAverageGte
+ schema:
+ type: number
+ example: 7
+ - in: query
+ name: voteAverageLte
+ schema:
+ type: number
+ example: 10
+ - in: query
+ name: voteCountGte
+ schema:
+ type: number
+ example: 7
+ - in: query
+ name: voteCountLte
+ schema:
+ type: number
+ example: 10
+ - in: query
+ name: watchRegion
+ schema:
+ type: string
+ example: US
+ - in: query
+ name: watchProviders
+ schema:
+ type: string
+ example: 8|9
responses:
'200':
description: Results
@@ -4585,9 +5082,13 @@ paths:
type: number
example: 123
seasons:
- type: array
- items:
- type: number
+ oneOf:
+ - type: array
+ items:
+ type: number
+ minimum: 1
+ - type: string
+ enum: [all]
is4k:
type: boolean
example: false
@@ -4666,7 +5167,7 @@ paths:
$ref: '#/components/schemas/MediaRequest'
put:
summary: Update MediaRequest
- description: Updates a specific media request and returns the request in a JSON object.. Requires the `MANAGE_REQUESTS` permission.
+ description: Updates a specific media request and returns the request in a JSON object. Requires the `MANAGE_REQUESTS` permission.
tags:
- request
parameters:
@@ -4677,6 +5178,37 @@ paths:
example: '1'
schema:
type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ mediaType:
+ type: string
+ enum: [movie, tv]
+ seasons:
+ type: array
+ items:
+ type: number
+ minimum: 1
+ is4k:
+ type: boolean
+ example: false
+ serverId:
+ type: number
+ profileId:
+ type: number
+ rootFolder:
+ type: string
+ languageProfileId:
+ type: number
+ userId:
+ type: number
+ nullable: true
+ required:
+ - mediaType
responses:
'200':
description: Succesfully updated request
@@ -4747,7 +5279,7 @@ paths:
required: true
schema:
type: string
- enum: [pending, approve, decline, available]
+ enum: [approve, decline]
responses:
'200':
description: Request status changed
@@ -4912,6 +5444,63 @@ paths:
audienceRating:
type: string
enum: ['Spilled', 'Upright']
+ /movie/{movieId}/ratingscombined:
+ get:
+ summary: Get RT and IMDB movie ratings combined
+ description: Returns ratings from RottenTomatoes and IMDB based on the provided movieId in a JSON object.
+ tags:
+ - movies
+ parameters:
+ - in: path
+ name: movieId
+ required: true
+ schema:
+ type: number
+ example: 337401
+ responses:
+ '200':
+ description: Ratings returned
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ rt:
+ type: object
+ properties:
+ title:
+ type: string
+ example: Mulan
+ year:
+ type: number
+ example: 2020
+ url:
+ type: string
+ example: 'http://www.rottentomatoes.com/m/mulan_2020/'
+ criticsScore:
+ type: number
+ example: 85
+ criticsRating:
+ type: string
+ enum: ['Rotten', 'Fresh', 'Certified Fresh']
+ audienceScore:
+ type: number
+ example: 65
+ audienceRating:
+ type: string
+ enum: ['Spilled', 'Upright']
+ imdb:
+ type: object
+ properties:
+ title:
+ type: string
+ example: I am Legend
+ url:
+ type: string
+ example: 'https://www.imdb.com/title/tt0480249'
+ criticsScore:
+ type: number
+ example: 6.5
/tv/{tvId}:
get:
summary: Get TV details
@@ -5867,6 +6456,89 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Issue'
+ /keyword/{keywordId}:
+ get:
+ summary: Get keyword
+ description: |
+ Returns a single keyword in JSON format.
+ tags:
+ - other
+ parameters:
+ - in: path
+ name: keywordId
+ required: true
+ schema:
+ type: number
+ example: 1
+ responses:
+ '200':
+ description: Keyword returned
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Keyword'
+ /watchproviders/regions:
+ get:
+ summary: Get watch provider regions
+ description: |
+ Returns a list of all available watch provider regions.
+ tags:
+ - other
+ responses:
+ '200':
+ description: Watch provider regions returned
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/WatchProviderRegion'
+ /watchproviders/movies:
+ get:
+ summary: Get watch provider movies
+ description: |
+ Returns a list of all available watch providers for movies.
+ tags:
+ - other
+ parameters:
+ - in: query
+ name: watchRegion
+ required: true
+ schema:
+ type: string
+ example: US
+ responses:
+ '200':
+ description: Watch providers for movies returned
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/WatchProviderDetails'
+ /watchproviders/tv:
+ get:
+ summary: Get watch provider series
+ description: |
+ Returns a list of all available watch providers for series.
+ tags:
+ - other
+ parameters:
+ - in: query
+ name: watchRegion
+ required: true
+ schema:
+ type: string
+ example: US
+ responses:
+ '200':
+ description: Watch providers for series returned
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/WatchProviderDetails'
security:
- cookieAuth: []
- apiKey: []
diff --git a/package.json b/package.json
index 3a1d60de64..92aae6dc3b 100644
--- a/package.json
+++ b/package.json
@@ -29,144 +29,148 @@
},
"license": "MIT",
"dependencies": {
- "@formatjs/intl-displaynames": "6.0.3",
- "@formatjs/intl-locale": "3.0.3",
- "@formatjs/intl-pluralrules": "5.0.3",
+ "@formatjs/intl-displaynames": "6.2.6",
+ "@formatjs/intl-locale": "3.1.1",
+ "@formatjs/intl-pluralrules": "5.1.10",
"@formatjs/intl-utils": "3.8.4",
- "@headlessui/react": "0.0.0-insiders.b301f04",
- "@heroicons/react": "1.0.6",
+ "@headlessui/react": "1.7.12",
+ "@heroicons/react": "2.0.16",
"@supercharge/request-ip": "1.2.0",
- "@svgr/webpack": "6.3.1",
- "@tanem/react-nprogress": "5.0.11",
- "ace-builds": "1.9.6",
- "axios": "0.27.2",
+ "@svgr/webpack": "6.5.1",
+ "@tanem/react-nprogress": "5.0.30",
+ "ace-builds": "1.15.2",
+ "axios": "1.3.4",
"axios-rate-limit": "1.3.0",
- "bcrypt": "5.0.1",
+ "bcrypt": "5.1.0",
"bowser": "2.11.0",
"connect-typeorm": "1.1.4",
"cookie-parser": "1.4.6",
- "copy-to-clipboard": "3.3.2",
+ "copy-to-clipboard": "3.3.3",
"country-flag-icons": "1.5.5",
- "cronstrue": "2.11.0",
+ "cronstrue": "2.23.0",
"csurf": "1.11.0",
- "date-fns": "2.29.1",
+ "date-fns": "2.29.3",
+ "dayjs": "1.11.7",
"email-templates": "9.0.0",
- "express": "4.18.1",
+ "express": "4.18.2",
"express-openapi-validator": "4.13.8",
- "express-rate-limit": "6.5.1",
+ "express-rate-limit": "6.7.0",
"express-session": "1.17.3",
"formik": "2.2.9",
"gravatar-url": "3.1.0",
"intl": "1.2.5",
+ "jwt-decode": "^3.1.2",
"lodash": "4.17.21",
- "next": "12.2.5",
+ "next": "12.3.4",
"node-cache": "5.1.2",
- "node-gyp": "9.1.0",
- "node-schedule": "2.1.0",
- "nodemailer": "6.7.8",
- "openpgp": "5.4.0",
+ "node-gyp": "9.3.1",
+ "node-schedule": "2.1.1",
+ "nodemailer": "6.9.1",
+ "openpgp": "5.7.0",
"plex-api": "5.3.2",
"pug": "3.0.2",
- "pulltorefreshjs": "0.1.22",
"react": "18.2.0",
"react-ace": "10.1.0",
"react-animate-height": "2.1.2",
+ "react-aria": "3.23.0",
"react-dom": "18.2.0",
- "react-intersection-observer": "9.4.0",
- "react-intl": "6.0.5",
- "react-markdown": "8.0.3",
+ "react-intersection-observer": "9.4.3",
+ "react-intl": "6.2.10",
+ "react-markdown": "8.0.5",
"react-popper-tooltip": "4.4.2",
- "react-select": "5.4.0",
- "react-spring": "9.5.2",
+ "react-select": "5.7.0",
+ "react-spring": "9.7.1",
+ "react-tailwindcss-datepicker-sct": "1.3.4",
"react-toast-notifications": "2.5.1",
"react-truncate-markup": "5.1.2",
- "react-use-clipboard": "1.0.8",
+ "react-use-clipboard": "1.0.9",
"reflect-metadata": "0.1.13",
"secure-random-password": "0.2.3",
- "semver": "7.3.7",
- "sqlite3": "5.0.11",
- "swagger-ui-express": "4.5.0",
- "swr": "1.3.0",
- "typeorm": "0.3.7",
+ "semver": "7.3.8",
+ "sqlite3": "5.1.4",
+ "swagger-ui-express": "4.6.2",
+ "swr": "2.0.4",
+ "typeorm": "0.3.12",
"web-push": "3.5.0",
- "winston": "3.8.1",
+ "winston": "3.8.2",
"winston-daily-rotate-file": "4.7.1",
"xml2js": "0.4.23",
"yamljs": "0.3.0",
- "yup": "0.32.11"
+ "yup": "0.32.11",
+ "zod": "3.20.6"
},
"devDependencies": {
- "@babel/cli": "7.18.10",
- "@commitlint/cli": "17.0.3",
- "@commitlint/config-conventional": "17.0.3",
- "@semantic-release/changelog": "6.0.1",
+ "@babel/cli": "7.21.0",
+ "@commitlint/cli": "17.4.4",
+ "@commitlint/config-conventional": "17.4.4",
+ "@semantic-release/changelog": "6.0.2",
"@semantic-release/commit-analyzer": "9.0.2",
"@semantic-release/exec": "6.0.3",
"@semantic-release/git": "10.0.1",
- "@tailwindcss/aspect-ratio": "0.4.0",
- "@tailwindcss/forms": "0.5.2",
- "@tailwindcss/typography": "0.5.4",
+ "@tailwindcss/aspect-ratio": "0.4.2",
+ "@tailwindcss/forms": "0.5.3",
+ "@tailwindcss/typography": "0.5.9",
"@types/bcrypt": "5.0.0",
"@types/cookie-parser": "1.4.3",
"@types/country-flag-icons": "1.2.0",
"@types/csurf": "1.11.2",
"@types/email-templates": "8.0.4",
- "@types/express": "4.17.13",
- "@types/express-session": "1.17.4",
- "@types/lodash": "4.14.183",
+ "@types/express": "4.17.17",
+ "@types/express-session": "1.17.6",
+ "@types/lodash": "4.14.191",
"@types/node": "17.0.36",
"@types/node-schedule": "2.1.0",
- "@types/nodemailer": "6.4.5",
- "@types/pulltorefreshjs": "0.1.5",
- "@types/react": "18.0.17",
- "@types/react-dom": "18.0.6",
+ "@types/nodemailer": "6.4.7",
+ "@types/react": "18.0.28",
+ "@types/react-dom": "18.0.11",
"@types/react-transition-group": "4.4.5",
"@types/secure-random-password": "0.2.1",
- "@types/semver": "7.3.12",
+ "@types/semver": "7.3.13",
"@types/swagger-ui-express": "4.1.3",
"@types/web-push": "3.3.2",
"@types/xml2js": "0.4.11",
"@types/yamljs": "0.2.31",
"@types/yup": "0.29.14",
- "@typescript-eslint/eslint-plugin": "5.33.1",
- "@typescript-eslint/parser": "5.33.1",
- "autoprefixer": "10.4.8",
+ "@typescript-eslint/eslint-plugin": "5.54.0",
+ "@typescript-eslint/parser": "5.54.0",
+ "autoprefixer": "10.4.13",
"babel-plugin-react-intl": "8.2.25",
"babel-plugin-react-intl-auto": "3.3.0",
- "commitizen": "4.2.5",
+ "commitizen": "4.3.0",
"copyfiles": "2.4.1",
"cy-mobile-commands": "0.3.0",
- "cypress": "10.6.0",
+ "cypress": "12.7.0",
"cz-conventional-changelog": "3.3.0",
- "eslint": "8.22.0",
- "eslint-config-next": "12.2.5",
- "eslint-config-prettier": "8.5.0",
- "eslint-plugin-formatjs": "4.1.0",
- "eslint-plugin-jsx-a11y": "6.6.1",
- "eslint-plugin-no-relative-import-paths": "1.4.0",
+ "eslint": "8.35.0",
+ "eslint-config-next": "12.3.4",
+ "eslint-config-prettier": "8.6.0",
+ "eslint-plugin-formatjs": "4.9.0",
+ "eslint-plugin-jsx-a11y": "6.7.1",
+ "eslint-plugin-no-relative-import-paths": "1.5.2",
"eslint-plugin-prettier": "4.2.1",
- "eslint-plugin-react": "7.30.1",
+ "eslint-plugin-react": "7.32.2",
"eslint-plugin-react-hooks": "4.6.0",
"extract-react-intl-messages": "4.1.1",
- "husky": "8.0.1",
- "lint-staged": "12.4.3",
- "nodemon": "2.0.19",
- "postcss": "8.4.16",
- "prettier": "2.7.1",
- "prettier-plugin-organize-imports": "3.1.0",
- "prettier-plugin-tailwindcss": "0.1.13",
- "semantic-release": "19.0.3",
+ "husky": "8.0.3",
+ "lint-staged": "13.1.2",
+ "nodemon": "2.0.20",
+ "postcss": "8.4.21",
+ "prettier": "2.8.4",
+ "prettier-plugin-organize-imports": "3.2.2",
+ "prettier-plugin-tailwindcss": "0.2.3",
+ "semantic-release": "19.0.5",
"semantic-release-docker-buildx": "1.0.1",
- "tailwindcss": "3.1.8",
+ "tailwindcss": "3.2.7",
"ts-node": "10.9.1",
- "tsc-alias": "1.7.0",
- "tsconfig-paths": "4.1.0",
- "typescript": "4.7.4"
+ "tsc-alias": "1.8.2",
+ "tsconfig-paths": "4.1.2",
+ "typescript": "4.9.5"
},
"resolutions": {
"sqlite3/node-gyp": "8.4.1",
- "@types/react": "18.0.17",
- "@types/react-dom": "18.0.6"
+ "@types/react": "18.0.28",
+ "@types/react-dom": "18.0.11",
+ "@types/express-session": "1.17.6"
},
"config": {
"commitizen": {
@@ -224,7 +228,7 @@
{
"path": "semantic-release-docker-buildx",
"buildArgs": {
- "COMMIT_TAG": "$GITHUB_SHA"
+ "COMMIT_TAG": "$GIT_SHA"
},
"imageNames": [
"sctx/overseerr",
diff --git a/public/offline.html b/public/offline.html
index 732782ee11..da4ba235a4 100644
--- a/public/offline.html
+++ b/public/offline.html
@@ -17,7 +17,7 @@
}
h1 {
- color: #6366F1;
+ color: #6366f1;
}
p {
@@ -37,7 +37,7 @@ You are offline