Add integration with Jellyseerr/Seerr (#558)

## Description
This PR add the ability to integrate with a [Jellyseerr/Seerr
server](https://github.com/seerr-team/seerr).

### Features
- Login to the Seerr server using API Key, Jellyfin credentials, or
local Seerr credentials
    - Separate Seerr logins per user profile
- Search Seerr from the search page
- Discover media from Seerr on the nav drawer `Discover` page
    - Also from movie, series, or person pages
- Seamless integration with existing media, i.e. selecting media found
from Seerr that already exists on the Jellyfin server, will go directly
to the regular media page
- Mostly consistent UI between Jellyfin media & Seerr media
- Submit requests to Seerr
- Cancel submitted requests

### Screenshots

![discover](https://github.com/user-attachments/assets/f830b48f-e2f1-43f4-9680-9c6d4e071765)

### Related issues
Closes #54

## Acknowledgements

The `app/src/main/seerr/seerr-api.yml` file is copied & modified from
https://github.com/seerr-team/seerr/blob/develop/seerr-api.yml. I hope
to try to upstream some of the changes in the future.
This commit is contained in:
Ray 2026-01-12 16:35:27 -05:00 committed by GitHub
parent f4e1b0e171
commit 4c7c465c67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
68 changed files with 13369 additions and 137 deletions

View file

@ -15,6 +15,7 @@ plugins {
alias(libs.plugins.protobuf)
alias(libs.plugins.kotlin.plugin.serialization)
alias(libs.plugins.aboutLibraries)
alias(libs.plugins.openapi.generator)
}
val isCI = if (System.getenv("CI") != null) System.getenv("CI").toBoolean() else false
@ -145,6 +146,12 @@ android {
isUniversalApk = true
}
}
sourceSets {
getByName("main") {
kotlin.srcDirs("$buildDir/generated/seerr_api/src/main/kotlin")
}
}
}
protobuf {
@ -176,6 +183,33 @@ aboutLibraries {
}
}
openApiGenerate {
generatorName.set("kotlin")
inputSpec.set("$projectDir/src/main/seerr/seerr-api.yml")
templateDir.set("$projectDir/src/main/seerr/templates")
outputDir.set("$buildDir/generated/seerr_api")
apiPackage.set("com.github.damontecres.wholphin.api.seerr")
modelPackage.set("com.github.damontecres.wholphin.api.seerr.model")
groupId.set("com.github.damontecres.wholphin.api.seerr")
id.set("seerr-api")
packageName.set("com.github.damontecres.wholphin.api.seerr")
additionalProperties.apply {
put("serializationLibrary", "kotlinx_serialization")
put("sortModelPropertiesByRequiredFlag", true)
put("sortParamsByRequiredFlag", true)
put("useCoroutines", true)
put("enumPropertyNaming", "UPPERCASE")
put("modelMutable", false)
// Note: this is only for downloading files, so it's not necessary to enable
put("supportAndroidApiLevel25AndBelow", false)
}
}
tasks.named("preBuild") {
dependsOn.add(tasks.named("openApiGenerate"))
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
@ -246,6 +280,8 @@ dependencies {
implementation(libs.acra.limiter)
compileOnly(libs.auto.service.annotations)
ksp(libs.auto.service.ksp)
implementation(platform(libs.okhttp.bom))
implementation(libs.okhttp)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test.junit4)