package suwayomi.tachidesk.manga.controller /* * Copyright (C) Contributors to the Suwayomi project * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import io.javalin.http.HttpCode import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import org.kodein.di.DI import org.kodein.di.conf.global import org.kodein.di.instance import suwayomi.tachidesk.manga.impl.MangaList import suwayomi.tachidesk.manga.impl.Search import suwayomi.tachidesk.manga.impl.Search.FilterChange import suwayomi.tachidesk.manga.impl.Search.FilterData import suwayomi.tachidesk.manga.impl.Source import suwayomi.tachidesk.manga.impl.Source.SourcePreferenceChange import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass 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 SourceController { /** list of sources */ val list = handler( documentWith = { withOperation { summary("Sources list") description("List of sources") } }, behaviorOf = { ctx -> ctx.json(Source.getSourceList()) }, withResults = { json>(HttpCode.OK) } ) /** fetch source with id `sourceId` */ val retrieve = handler( pathParam("sourceId"), documentWith = { withOperation { summary("Source fetch") description("Fetch source with id `sourceId`") } }, behaviorOf = { ctx, sourceId -> ctx.json(Source.getSource(sourceId)!!) }, withResults = { json(HttpCode.OK) httpCode(HttpCode.NOT_FOUND) } ) /** popular mangas from source with id `sourceId` */ val popular = handler( pathParam("sourceId"), pathParam("pageNum"), documentWith = { withOperation { summary("Source popular manga") description("Popular mangas from source with id `sourceId`") } }, behaviorOf = { ctx, sourceId, pageNum -> ctx.future( future { MangaList.getMangaList(sourceId, pageNum, popular = true) } ) }, withResults = { json(HttpCode.OK) } ) /** latest mangas from source with id `sourceId` */ val latest = handler( pathParam("sourceId"), pathParam("pageNum"), documentWith = { withOperation { summary("Source latest manga") description("Latest mangas from source with id `sourceId`") } }, behaviorOf = { ctx, sourceId, pageNum -> ctx.future( future { MangaList.getMangaList(sourceId, pageNum, popular = false) } ) }, withResults = { json(HttpCode.OK) } ) /** fetch preferences of source with id `sourceId` */ val getPreferences = handler( pathParam("sourceId"), documentWith = { withOperation { summary("Source preferences") description("Fetch preferences of source with id `sourceId`") } }, behaviorOf = { ctx, sourceId -> ctx.json(Source.getSourcePreferences(sourceId)) }, withResults = { json>(HttpCode.OK) } ) /** set one preference of source with id `sourceId` */ val setPreference = handler( pathParam("sourceId"), documentWith = { withOperation { summary("Source preference set") description("Set one preference of source with id `sourceId`") } body() }, behaviorOf = { ctx, sourceId -> val preferenceChange = ctx.bodyAsClass(SourcePreferenceChange::class.java) ctx.json(Source.setSourcePreference(sourceId, preferenceChange)) }, withResults = { httpCode(HttpCode.OK) } ) /** fetch filters of source with id `sourceId` */ val getFilters = handler( pathParam("sourceId"), queryParam("reset", false), documentWith = { withOperation { summary("Source filters") description("Fetch filters of source with id `sourceId`") } }, behaviorOf = { ctx, sourceId, reset -> ctx.json(Search.getFilterList(sourceId, reset)) }, withResults = { json>(HttpCode.OK) } ) private val json by DI.global.instance() /** change filters of source with id `sourceId` */ val setFilters = handler( pathParam("sourceId"), documentWith = { withOperation { summary("Source filters set") description("Change filters of source with id `sourceId`") } body() body>() }, behaviorOf = { ctx, sourceId -> val filterChange = try { json.decodeFromString>(ctx.body()) } catch (e: Exception) { listOf(json.decodeFromString(ctx.body())) } ctx.json(Search.setFilter(sourceId, filterChange)) }, withResults = { httpCode(HttpCode.OK) } ) /** single source search */ val searchSingle = handler( pathParam("sourceId"), queryParam("searchTerm", ""), queryParam("pageNum", 1), documentWith = { withOperation { summary("Source search") description("Single source search") } }, behaviorOf = { ctx, sourceId, searchTerm, pageNum -> ctx.future(future { Search.sourceSearch(sourceId, searchTerm, pageNum) }) }, withResults = { json(HttpCode.OK) } ) /** quick search single source filter */ val quickSearchSingle = handler( pathParam("sourceId"), queryParam("pageNum", 1), documentWith = { withOperation { summary("Source manga quick search") description("Returns list of manga from source matching posted searchTerm and filter") } body() }, behaviorOf = { ctx, sourceId, pageNum -> val filter = json.decodeFromString(ctx.body()) ctx.future(future { Search.sourceFilter(sourceId, pageNum, filter) }) }, withResults = { json(HttpCode.OK) } ) /** all source search */ val searchAll = handler( pathParam("searchTerm"), documentWith = { withOperation { summary("Source global search") description("All source search") } }, behaviorOf = { ctx, searchTerm -> // TODO ctx.json(Search.sourceGlobalSearch(searchTerm)) }, withResults = { httpCode(HttpCode.OK) } ) }