Compare commits

...

8 Commits

Author SHA1 Message Date
Ludovic Ortega
66f1cb7df7 chore: disable nextjs telemetry
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2026-02-19 20:28:41 +01:00
nova-api
fa905be002 docs: remove double quotes (") from DB_HOST environment variable (#2514) 2026-02-19 08:56:25 +00:00
fallenbagel
9da8bb6dea fix: preserve blocklist on media deletion & optimise watchlist-sync (#2478) 2026-02-18 21:23:50 +01:00
Michael Reid
0e636a3f99 docs(synology): add installation guide via SynoCommunity (#2503)
Co-authored-by: Ludovic Ortega <github@mail.adminafk.fr>
2026-02-18 16:49:51 +01:00
fallenbagel
e0e4b6f512 fix(watchlist-sync): correct permission typo for TV auto requests (#2488) 2026-02-18 15:23:20 +01:00
Ludovic Ortega
dc1734d41f docs(truenas): update install/migration guide (#2491)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2026-02-18 17:30:25 +05:00
Ludovic Ortega
06e5eb0704 ci: add create-tag workflow to streamline release process (#2493)
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2026-02-18 12:22:16 +00:00
DataBitz
88afcc113d docs: media server support clarification [skip ci] (#2498) 2026-02-18 14:08:48 +05:00
12 changed files with 292 additions and 18 deletions

View File

@@ -129,7 +129,7 @@ jobs:
build:
name: Build (per-arch, native runners)
if: github.ref == 'refs/heads/develop' && !contains(github.event.head_commit.message, '[skip ci]')
if: github.ref == 'refs/heads/develop'
strategy:
matrix:
include:
@@ -237,7 +237,7 @@ jobs:
discord:
name: Send Discord Notification
needs: publish
if: always() && github.event_name != 'pull_request' && !contains(github.event.head_commit.message, '[skip ci]')
if: always() && github.event_name != 'pull_request'
runs-on: ubuntu-24.04
steps:
- name: Determine Workflow Status

87
.github/workflows/create-tag.yml vendored Normal file
View File

@@ -0,0 +1,87 @@
---
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
name: Create tag
on:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
determine-tag-version:
name: Determine tag version
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
tag_version: ${{ steps.git-cliff.outputs.tag_version }}
steps:
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Install git-cliff
uses: taiki-e/install-action@cede0bb282aae847dfa8aacca3a41c86d973d4d7 # v2.68.1
with:
tool: git-cliff
- name: Get tag version
id: git-cliff
run: |
tag_version=$(git-cliff -c .github/cliff.toml --bumped-version --unreleased)
echo "Next tag version is ${tag_version}"
echo "tag_version=${tag_version}" >> "$GITHUB_OUTPUT"
create-tag:
name: Create tag
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
permissions:
contents: write
needs: determine-tag-version
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_VERSION: ${{ needs.determine-tag-version.outputs.tag_version }}
steps:
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
ssh-key: '${{ secrets.COMMIT_KEY }}'
- name: Pnpm Setup
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
- name: Set up Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version-file: 'package.json'
# For workflows with elevated privileges we recommend disabling automatic caching.
# https://github.com/actions/setup-node
package-manager-cache: false
- name: Configure git
run: |
git config --global user.name "${{ github.actor }}"
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
- name: Bump package.json
run: npm version ${TAG_VERSION} --no-commit-hooks --no-git-tag-version
- name: Commit updated files
run: |
git add package.json
git commit -m 'chore(release): prepare ${TAG_VERSION}'
git push
- name: Create git tag
run: |
git tag ${TAG_VERSION}
git push origin ${TAG_VERSION}

View File

@@ -30,7 +30,7 @@ If your PostgreSQL server is configured to accept TCP connections, you can speci
```dotenv
DB_TYPE=postgres # Which DB engine to use, either sqlite or postgres. The default is sqlite.
DB_HOST="localhost" # (optional) The host (URL) of the database. The default is "localhost".
DB_HOST=localhost # (optional) The host (URL) of the database. The default is "localhost".
DB_PORT="5432" # (optional) The port to connect to. The default is "5432".
DB_USER= # (required) Username used to connect to the database.
DB_PASS= # (required) Password of the user used to connect to the database.

View File

@@ -0,0 +1,111 @@
---
title: Synology (Advanced)
description: Install Seerr on Synology NAS using SynoCommunity
sidebar_position: 5
---
# Synology
:::warning
Third-party installation methods are maintained by the community. The Seerr team is not responsible for these packages.
:::
:::warning
This method is not recommended for most users. It is intended for advanced users who are using Synology NAS.
:::
## Prerequisites
- Synology NAS running **DSM 7.2** or later
- 64-bit architecture (x86_64 or ARMv8)
- [SynoCommunity package source](https://synocommunity.com/) added to Package Center
## Adding the SynoCommunity Package Source
If you haven't already added SynoCommunity to your Package Center:
1. Open **Package Center** in DSM
2. Click **Settings** in the top-right corner
3. Go to the **Package Sources** tab
4. Click **Add**
5. Enter the following:
- **Name**: `SynoCommunity`
- **Location**: `https://packages.synocommunity.com`
6. Click **OK**
## Installation
1. In **Package Center**, search for **Seerr**
2. Click **Install**
3. Follow the installation wizard prompts
4. Package Center will automatically install any required dependencies (Node.js v22)
### Access Seerr
Once installed, access Seerr at:
```
http://<your-synology-ip>:5055
```
You can also click the **Open** button in Package Center or find Seerr in the DSM main menu.
## Configuration
Seerr's configuration files are stored at:
```
/var/packages/seerr/var/config
```
:::info
The Seerr package runs as a dedicated service user managed by DSM. No manual permission configuration is required.
:::
## Managing the Service
You can start, stop, and restart Seerr from **Package Center** → Find Seerr → Use the action buttons.
## Updating
When a new version is available:
1. Open **Package Center**
2. Go to **Installed** packages
3. Find **Seerr** and click **Update** if available
:::tip
Enable automatic updates in Package Center settings to keep Seerr up to date.
:::
## Troubleshooting
### Viewing Logs
Seerr logs are located at `/var/packages/seerr/var/config/logs` and can be accessed using:
- **File Browser** package (recommended for most users)
- SSH (advanced users)
### Port Conflicts
Seerr uses port 5055. If this port is already in use:
- **Docker containers**: Remap the conflicting container to a different port
- **Other packages**: The conflicting package will need to be uninstalled as Seerr's port cannot be changed
SynoCommunity ensures there are no port conflicts with other SynoCommunity packages or official Synology packages.
### Package Won't Start
Ensure Node.js v22 is installed and running by checking its status in **Package Center**.
## Uninstallation
1. Open **Package Center**
2. Find **Seerr** in your installed packages
3. Click **Uninstall**
:::caution
Uninstalling will remove the application but preserve your configuration data by default. Select "Remove data" during uninstallation if you want a complete removal.
:::

View File

@@ -4,12 +4,6 @@ description: Install Seerr using TrueNAS
sidebar_position: 4
---
# TrueNAS
:::danger
This method has not yet been updated for Seerr and is currently a work in progress.
You can follow the ongoing work on this issue https://github.com/truenas/apps/issues/3374.
:::
<!--
:::warning
Third-party installation methods are maintained by the community. The Seerr team is not responsible for these packages.
:::
@@ -17,4 +11,7 @@ Third-party installation methods are maintained by the community. The Seerr team
:::warning
This method is not recommended for most users. It is intended for advanced users who are using TrueNAS distribution.
:::
-->
## Installation
Go to the 'Apps' menu, click the 'Discover Apps' button in the top right, search for 'Seerr' in the search bar, and install the app.

View File

@@ -210,7 +210,42 @@ See https://aur.archlinux.org/packages/seerr
### TrueNAS
Waiting for https://github.com/truenas/apps/issues/3374
Refer to [Seerr TrueNAS Documentation](/getting-started/third-parties/truenas), all of our examples have been updated to reflect the below change.
<Tabs groupId="truenas-migration" queryString>
<TabItem value="hostpath" label="Host Path">
**This guide describes how to migrate from Host Path storage (not ixVolume).**
1. Stop Jellyseerr/Overseerr
2. Install Seerr and use the same Host Path storage that was used by Jellyseerr/Overseerr
3. Start Seerr app
4. Delete Jellyseerr/Overseerr app
</TabItem>
<TabItem value="ixvolume" label="ixVolume">
**This guide describes how to migrate from ixVolume storage (not Host Path).**
1. Stop Jellyseerr/Overseerr
2. Create a dataset for Seerr
If your apps normally store data under something like:
```
/mnt/storage/<app-name>
```
then create a dataset named:
```
storage/seerr
```
resulting in:
```
/mnt/storage/seerr
```
3. Copy ixVolume Data
Open System Settings → Shell, or SSH into your TrueNAS server as root and run :
```bash
rsync -av /mnt/.ix-apps/app_mounts/jellyseerr/ /mnt/storage/seerr/
```
4. Install Seerr and use the same Host Path storage that was created before (`/mnt/storage/seerr/config` in our example)
5. Start Seerr app
6. Delete Jellyseerr/Overseerr app
</TabItem>
</Tabs>
### Unraid
@@ -277,4 +312,4 @@ For Jellyseerr users, use `/mnt/user/appdata/jellyseerr`.
:::tip
If you are using a reverse proxy (such as SWAG or Nginx Proxy Manager), update your proxy configuration to point to the new container name `seerr`. The default port remains `5055`.
:::
:::

View File

@@ -19,7 +19,7 @@ Please check how to migrate to Seerr in our [migration guide](https://docs.seerr
Seerr brings several features that were previously available in Jellyseerr but missing from Overseerr. These additions improve flexibility, performance, and overall control for admins and power users:
* **Alternative media solution:** Added support for Jellyfin and Emby in addition to the existing Plex integration.
* **Alternative media solution:** Added support for Jellyfin and Emby as alternatives to Plex. Only one integration can be used at a time.
* **PostgreSQL support**: In addition to SQLite, you can now opt in to using a PostgreSQL database.
* **Blocklist for movies, series, and tags**: Allows permitted users to hide movies, series, or tags from regular users.
* **Override rules**: Adjust default request settings based on conditions such as user, tag, or other criteria.

View File

@@ -16,7 +16,12 @@ const config: Config = {
deploymentBranch: 'gh-pages',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
markdown: {
hooks: {
onBrokenMarkdownLinks: 'warn',
},
},
i18n: {
defaultLocale: 'en',

View File

@@ -5,6 +5,7 @@
"packageManager": "pnpm@10.24.0",
"scripts": {
"preinstall": "npx only-allow pnpm",
"postinstall": "next telemetry disable",
"dev": "nodemon -e ts --watch server --watch seerr-api.yml -e .json,.ts,.yml -x ts-node -r tsconfig-paths/register --files --project server/tsconfig.json server/index.ts",
"build:server": "tsc --project server/tsconfig.json && copyfiles -u 2 server/templates/**/*.{html,pug} dist/templates && tsc-alias -p server/tsconfig.json",
"build:next": "next build",

View File

@@ -206,6 +206,19 @@ class Media {
Object.assign(this, init);
}
public resetServiceData(): void {
this.serviceId = null;
this.serviceId4k = null;
this.externalServiceId = null;
this.externalServiceId4k = null;
this.externalServiceSlug = null;
this.externalServiceSlug4k = null;
this.ratingKey = null;
this.ratingKey4k = null;
this.jellyfinMediaId = null;
this.jellyfinMediaId4k = null;
}
@AfterLoad()
public setPlexUrls(): void {
const { machineId, webAppUrl } = getSettings().plex;

View File

@@ -45,7 +45,7 @@ class WatchlistSync {
[
Permission.AUTO_REQUEST,
Permission.AUTO_REQUEST_MOVIE,
Permission.AUTO_APPROVE_TV,
Permission.AUTO_REQUEST_TV,
],
{ type: 'or' }
)
@@ -70,13 +70,33 @@ class WatchlistSync {
response.items.map((i) => i.tmdbId)
);
const watchlistTmdbIds = response.items.map((i) => i.tmdbId);
const requestRepository = getRepository(MediaRequest);
const existingAutoRequests = await requestRepository
.createQueryBuilder('request')
.leftJoinAndSelect('request.media', 'media')
.where('request.requestedBy = :userId', { userId: user.id })
.andWhere('request.isAutoRequest = true')
.andWhere('media.tmdbId IN (:...tmdbIds)', { tmdbIds: watchlistTmdbIds })
.getMany();
const autoRequestedTmdbIds = new Set(
existingAutoRequests
.filter((r) => r.media != null)
.map((r) => `${r.media.mediaType}:${r.media.tmdbId}`)
);
const unavailableItems = response.items.filter(
// If we can find watchlist items in our database that are also available, we should exclude them
(i) =>
!autoRequestedTmdbIds.has(
`${i.type === 'show' ? MediaType.TV : MediaType.MOVIE}:${i.tmdbId}`
) &&
!mediaItems.find(
(m) =>
m.tmdbId === i.tmdbId &&
((m.status !== MediaStatus.UNKNOWN && m.mediaType === 'movie') ||
(m.status === MediaStatus.BLOCKLISTED ||
(m.status !== MediaStatus.UNKNOWN && m.mediaType === 'movie') ||
(m.mediaType === 'tv' && m.status === MediaStatus.AVAILABLE))
)
);

View File

@@ -174,7 +174,12 @@ mediaRoutes.delete(
where: { id: Number(req.params.id) },
});
await mediaRepository.remove(media);
if (media.status === MediaStatus.BLOCKLISTED) {
media.resetServiceData();
await mediaRepository.save(media);
} else {
await mediaRepository.remove(media);
}
return res.status(204).send();
} catch (e) {