Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
zeedif authored Feb 9, 2025
2 parents 81cf0c0 + 01c37cb commit 95c06ba
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 5 deletions.
8 changes: 4 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[versions]
kotlin = "2.1.0"
kotlin = "2.1.10"
coroutines = "1.10.1"
serialization = "1.8.0"
okhttp = "5.0.0-alpha.14" # Major version is locked by Tachiyomi extensions
javalin = "6.4.0"
jackson = "2.18.2" # jackson version locked by javalin, ref: `io.javalin.core.util.OptionalDependency`
exposed = "0.57.0"
exposed = "0.59.0"
dex2jar = "v64" # Stuck until https://github.com/ThexXTURBOXx/dex2jar/issues/27 is fixed
polyglot = "24.1.2"
settings = "1.3.0"
Expand Down Expand Up @@ -36,7 +36,7 @@ serialization-xml = { module = "io.github.pdvrieze.xmlutil:serialization-jvm", v
# Logging
slf4japi = "org.slf4j:slf4j-api:2.0.16"
logback = "ch.qos.logback:logback-classic:1.5.16"
kotlinlogging = "io.github.oshai:kotlin-logging-jvm:7.0.3"
kotlinlogging = "io.github.oshai:kotlin-logging-jvm:7.0.4"

# OkHttp
okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
Expand Down Expand Up @@ -66,7 +66,7 @@ exposed-javatime = { module = "org.jetbrains.exposed:exposed-java-time", version
h2 = "com.h2database:h2:1.4.200" # current database driver, can't update to h2 v2 without sql migration

# Exposed Migrations
exposed-migrations = "com.github.Suwayomi:exposed-migrations:3.5.0"
exposed-migrations = "com.github.Suwayomi:exposed-migrations:3.7.0"

# Dependency Injection
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package suwayomi.tachidesk.manga.model.dataclass

import kotlinx.serialization.Serializable
import nl.adaptivity.xmlutil.serialization.XmlElement
import nl.adaptivity.xmlutil.serialization.XmlSerialName
import nl.adaptivity.xmlutil.serialization.XmlValue

@Serializable
@XmlSerialName("feed", "", "")
data class OpdsDataClass(
@XmlElement(true)
val id: String,
@XmlElement(true)
val title: String,
@XmlElement(true)
val icon: String? = null,
@XmlElement(true)
val updated: String, // ISO-8601
@XmlElement(true)
val author: Author? = null,
@XmlElement(true)
val links: List<Link>,
@XmlElement(true)
val entries: List<Entry>,
@XmlSerialName("xmlns", "", "")
val xmlns: String = "http://www.w3.org/2005/Atom",
@XmlSerialName("xmlns:xsd", "", "")
val xmlnsXsd: String = "http://www.w3.org/2001/XMLSchema",
@XmlSerialName("xmlns:xsi", "", "")
val xmlnsXsi: String = "http://www.w3.org/2001/XMLSchema-instance",
@XmlSerialName("xmlns:opds", "", "")
val xmlnsOpds: String = "http://opds-spec.org/2010/catalog",
@XmlSerialName("xmlns:dcterms", "", "")
val xmlnsDublinCore: String = "http://purl.org/dc/terms/",
@XmlSerialName("xmlns:pse", "", "")
val xmlnsPse: String = "http://vaemendis.net/opds-pse/ns",
@XmlElement(true)
@XmlSerialName("totalResults", "http://a9.com/-/spec/opensearch/1.1/", "")
val totalResults: Long? = null,
@XmlElement(true)
@XmlSerialName("itemsPerPage", "http://a9.com/-/spec/opensearch/1.1/", "")
val itemsPerPage: Int? = null,
@XmlElement(true)
@XmlSerialName("startIndex", "http://a9.com/-/spec/opensearch/1.1/", "")
val startIndex: Int? = null,
) {
@Serializable
@XmlSerialName("author", "", "")
data class Author(
@XmlElement(true)
val name: String,
@XmlElement(true)
val uri: String? = null,
@XmlElement(true)
val email: String? = null,
)

@Serializable
@XmlSerialName("link", "", "")
data class Link(
val rel: String,
val href: String,
val type: String? = null,
val title: String? = null,
@XmlSerialName("pse:count", "", "")
val pseCount: Int? = null,
)

@Serializable
@XmlSerialName("entry", "", "")
data class Entry(
@XmlElement(true)
val id: String,
@XmlElement(true)
val title: String,
@XmlElement(true)
val updated: String,
@XmlElement(true)
val summary: Summary? = null,
@XmlElement(true)
val content: Content? = null,
@XmlElement(true)
val link: List<Link>,
@XmlElement(true)
val authors: List<Author>? = null,
@XmlElement(true)
val categories: List<Category>? = null,
@XmlElement(true)
@XmlSerialName("language", "http://purl.org/dc/terms/", "dc")
val extent: String? = null,
@XmlElement(true)
@XmlSerialName("format", "http://purl.org/dc/terms/format", "dc")
val format: String? = null,
)

@Serializable
@XmlSerialName("summary", "", "")
data class Summary(
val type: String = "text",
@XmlValue(true) val value: String = "",
)

@Serializable
@XmlSerialName("content", "", "")
data class Content(
val type: String = "text",
@XmlValue(true) val value: String = "",
)

@Serializable
@XmlSerialName("category", "", "")
data class Category(
val scheme: String? = null,
val term: String,
val label: String,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package suwayomi.tachidesk.opds.controller

import io.javalin.http.HttpStatus
import suwayomi.tachidesk.opds.impl.Opds
import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.util.handler
import suwayomi.tachidesk.server.util.pathParam
import suwayomi.tachidesk.server.util.queryParam
import suwayomi.tachidesk.server.util.withOperation

object OpdsController {
private const val OPDS_MIME = "application/xml;profile=opds-catalog;charset=UTF-8"
private const val BASE_URL = "/api/opds/v1.2"

val rootFeed =
handler(
documentWith = {
withOperation {
summary("OPDS Root Feed")
description("OPDS feed for the list of available manga sources")
}
},
behaviorOf = { ctx ->
ctx.future {
future {
Opds.getRootFeed(BASE_URL)
}.thenApply { xml ->
ctx.contentType(OPDS_MIME).result(xml)
}
}
},
withResults = {
httpCode(HttpStatus.OK)
},
)

val sourceFeed =
handler(
pathParam<Long>("sourceId"),
queryParam<Int?>("pageNumber"),
documentWith = {
withOperation {
summary("OPDS Source Feed")
description("OPDS feed for a specific manga source")
}
},
behaviorOf = { ctx, sourceId, pageNumber ->
ctx.future {
future {
Opds.getSourceFeed(sourceId, BASE_URL, pageNumber ?: 1)
}.thenApply { xml ->
ctx.contentType(OPDS_MIME).result(xml)
}
}
},
withResults = {
httpCode(HttpStatus.OK)
httpCode(HttpStatus.NOT_FOUND)
},
)

val mangaFeed =
handler(
pathParam<Int>("mangaId"),
queryParam<Int?>("pageNumber"),
documentWith = {
withOperation {
summary("OPDS Manga Feed")
description("OPDS feed for chapters of a specific manga")
}
},
behaviorOf = { ctx, mangaId, pageNumber ->
ctx.future {
future {
Opds.getMangaFeed(mangaId, BASE_URL, pageNumber ?: 1)
}.thenApply { xml ->
ctx.contentType(OPDS_MIME).result(xml)
}
}
},
withResults = {
httpCode(HttpStatus.OK)
httpCode(HttpStatus.NOT_FOUND)
},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package suwayomi.tachidesk.server
import io.github.oshai.kotlinlogging.KotlinLogging
import io.javalin.Javalin
import io.javalin.apibuilder.ApiBuilder.path
import io.javalin.http.HandlerType
import io.javalin.http.UnauthorizedResponse
import io.javalin.http.staticfiles.Location
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -111,6 +112,11 @@ object JavalinSetup {
}

app.beforeMatched { ctx ->
val isPreFlight = ctx.method() == HandlerType.OPTIONS
if (isPreFlight) {
return@beforeMatched
}

fun credentialsValid(): Boolean {
val basicAuthCredentials = ctx.basicAuthCredentials() ?: return false
val (username, password) = basicAuthCredentials
Expand Down

0 comments on commit 95c06ba

Please sign in to comment.