diff --git a/src/es/leercomicsonline/build.gradle b/src/es/leercomicsonline/build.gradle new file mode 100644 index 000000000..c6622956b --- /dev/null +++ b/src/es/leercomicsonline/build.gradle @@ -0,0 +1,7 @@ +ext { + extName = 'Leer Comics Online' + extClass = '.LeerComicsOnline' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/es/leercomicsonline/res/mipmap-hdpi/ic_launcher.png b/src/es/leercomicsonline/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..306eda41d Binary files /dev/null and b/src/es/leercomicsonline/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/es/leercomicsonline/res/mipmap-mdpi/ic_launcher.png b/src/es/leercomicsonline/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..6eae60327 Binary files /dev/null and b/src/es/leercomicsonline/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/es/leercomicsonline/res/mipmap-xhdpi/ic_launcher.png b/src/es/leercomicsonline/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..19b884e25 Binary files /dev/null and b/src/es/leercomicsonline/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/es/leercomicsonline/res/mipmap-xxhdpi/ic_launcher.png b/src/es/leercomicsonline/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..346875a36 Binary files /dev/null and b/src/es/leercomicsonline/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/es/leercomicsonline/res/mipmap-xxxhdpi/ic_launcher.png b/src/es/leercomicsonline/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..2d1434e19 Binary files /dev/null and b/src/es/leercomicsonline/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/es/leercomicsonline/src/eu/kanade/tachiyomi/extension/es/leercomicsonline/LeerComicsOnline.kt b/src/es/leercomicsonline/src/eu/kanade/tachiyomi/extension/es/leercomicsonline/LeerComicsOnline.kt new file mode 100644 index 000000000..532b9e540 --- /dev/null +++ b/src/es/leercomicsonline/src/eu/kanade/tachiyomi/extension/es/leercomicsonline/LeerComicsOnline.kt @@ -0,0 +1,138 @@ +package eu.kanade.tachiyomi.extension.es.leercomicsonline + +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.source.online.HttpSource +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.Request +import okhttp3.Response +import uy.kohesive.injekt.injectLazy + +class LeerComicsOnline : HttpSource() { + + override val name = "Leer Comics Online" + override val baseUrl = "https://leercomicsonline.com" + override val lang = "es" + override val supportsLatest = false + + private val json: Json by injectLazy() + + private val comicsPerPage = 20 + + override fun popularMangaRequest(page: Int): Request = GET( + baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("api") + addPathSegments("series") + addQueryParameter("page", page.toString()) + }.build(), + headers, + ) + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = + GET( + baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("api") + addPathSegments("series") + addQueryParameter("page", page.toString()) + addQueryParameter("search", query) + }.build(), + headers, + ) + + override fun popularMangaParse(response: Response): MangasPage { + val page = response.request.url.queryParameter("page")!!.toInt() + val comics = json.decodeFromString>(response.body.string()) + return MangasPage( + comics.subList((page - 1) * comicsPerPage, page * comicsPerPage).map { comic -> + SManga.create().apply { + initialized = true + title = comic.title + thumbnail_url = baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("images") + addPathSegment("${comic.url}-300x461.jpg") + }.build().toString() + setUrlWithoutDomain( + baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("api") + addPathSegments("comics") + addQueryParameter("serieId", comic.id.toString()) + addQueryParameter("slug", comic.url) + }.build().toString(), + ) + } + }, + comics.count() > (page - 1) * comicsPerPage, + ) + } + + override fun searchMangaParse(response: Response): MangasPage { + val mangasPage = popularMangaParse(response) + val searchQuery = response.request.url.queryParameter("search").toString() + return MangasPage( + mangasPage.mangas.filter { + it.title.lowercase().contains(searchQuery, ignoreCase = true) + }, + mangasPage.hasNextPage, + ) + } + + override fun getMangaUrl(manga: SManga): String = baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("categorias") + addPathSegment((baseUrl + manga.url).toHttpUrl().queryParameter("slug").toString()) + }.build().toString() + + override fun chapterListParse(response: Response): List = + json.decodeFromString>(response.body.string()).reversed().map { + SChapter.create().apply { + name = it.title + setUrlWithoutDomain( + baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("api") + addPathSegment("pages") + addQueryParameter("id", it.id.toString()) + addQueryParameter( + "letter", + it.url.first().toString(), + ) + addQueryParameter("slug", it.url) + }.build().toString(), + ) + } + } + + override fun getChapterUrl(chapter: SChapter): String = baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment((baseUrl + chapter.url).toHttpUrl().queryParameter("slug").toString()) + }.build().toString() + + override fun pageListParse(response: Response): List { + return try { // some chapters are just empty + json.decodeFromString>(response.body.string()).mapIndexed { index, url -> + Page(index, imageUrl = url) + } + } catch (exception: Exception) { + emptyList() + } + } + + @Serializable + class Comic( + val title: String, + val url: String, + val id: Int, + ) + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException() + override fun latestUpdatesParse(response: Response): MangasPage = + throw UnsupportedOperationException() + + override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException() + override fun mangaDetailsParse(response: Response): SManga = + throw UnsupportedOperationException() +}