Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 17 KiB |
|
@ -1,5 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.flixscans
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.flixscans.FlixScans
|
|
||||||
|
|
||||||
class FlixScansNet : FlixScans("Flix Scans", "https://flixscans.org", "en", cdnUrl = "https://media.flixscans.org/")
|
|
|
@ -1,13 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.extension.ar.galaxymanga
|
package eu.kanade.tachiyomi.extension.ar.galaxymanga
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.flixscans.FlixScans
|
import eu.kanade.tachiyomi.multisrc.flixscans.FlixScans
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import okhttp3.Request
|
|
||||||
|
|
||||||
class GalaxyManga : FlixScans("جالاكسي مانجا", "https://flixscans.com", "ar") {
|
class GalaxyManga : FlixScans("جالاكسي مانجا", "https://flixscans.com", "ar") {
|
||||||
override val versionId = 2
|
override val versionId = 2
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request {
|
|
||||||
return GET("$apiUrl/webtoon/pages/home/action", headers)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.multisrc.flixscans
|
package eu.kanade.tachiyomi.multisrc.flixscans
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
|
@ -16,7 +15,6 @@ import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
import okhttp3.Callback
|
import okhttp3.Callback
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
@ -28,8 +26,8 @@ abstract class FlixScans(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val baseUrl: String,
|
override val baseUrl: String,
|
||||||
override val lang: String,
|
override val lang: String,
|
||||||
protected val apiUrl: String = baseUrl.replace("://", "://api.").plus("/api/v1"),
|
protected val apiUrl: String = "$baseUrl/api/__api_party/noxApi",
|
||||||
protected val cdnUrl: String = baseUrl.replace("://", "://api.").plus("/storage/"),
|
protected val cdnUrl: String = baseUrl.replace("://", "://media.").plus("/"),
|
||||||
) : HttpSource() {
|
) : HttpSource() {
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
@ -43,6 +41,12 @@ abstract class FlixScans(
|
||||||
override fun headersBuilder() = super.headersBuilder()
|
override fun headersBuilder() = super.headersBuilder()
|
||||||
.add("Referer", baseUrl)
|
.add("Referer", baseUrl)
|
||||||
|
|
||||||
|
protected open fun postPath(path: String): Request {
|
||||||
|
val payload = """{"path":"$path","headers":{}}""".toRequestBody(JSON_MEDIA_TYPE)
|
||||||
|
|
||||||
|
return POST(apiUrl, headers, payload)
|
||||||
|
}
|
||||||
|
|
||||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||||
runCatching { fetchGenre() }
|
runCatching { fetchGenre() }
|
||||||
|
|
||||||
|
@ -50,7 +54,7 @@ abstract class FlixScans(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request {
|
override fun popularMangaRequest(page: Int): Request {
|
||||||
return GET("$apiUrl/webtoon/homepage/home", headers)
|
return postPath("webtoon/pages/home/romance")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
|
@ -70,16 +74,14 @@ abstract class FlixScans(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int): Request {
|
override fun latestUpdatesRequest(page: Int): Request {
|
||||||
return GET("$apiUrl/search/advance?page=$page&serie_type=webtoon", headers)
|
return postPath("search/advance?page=$page&serie_type=webtoon")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||||
val result = response.parseAs<ApiResponse<BrowseSeries>>()
|
val result = response.parseAs<ApiResponse<BrowseSeries>>()
|
||||||
val currentPage = response.request.url.queryParameter("page")
|
|
||||||
?.toIntOrNull() ?: 1
|
|
||||||
|
|
||||||
val entries = result.data.map { it.toSManga(cdnUrl) }
|
val entries = result.data.map { it.toSManga(cdnUrl) }
|
||||||
val hasNextPage = result.meta.lastPage > currentPage
|
val hasNextPage = result.meta.lastPage > result.meta.currentPage
|
||||||
|
|
||||||
return MangasPage(entries, hasNextPage)
|
return MangasPage(entries, hasNextPage)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +133,7 @@ abstract class FlixScans(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchGenreRequest(): Request {
|
private fun fetchGenreRequest(): Request {
|
||||||
return GET("$apiUrl/search/genres", headers)
|
return postPath("search/genres")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchGenreParse(response: Response): List<GenreHolder> {
|
private fun fetchGenreParse(response: Response): List<GenreHolder> {
|
||||||
|
@ -168,53 +170,55 @@ abstract class FlixScans(
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
if (query.isNotEmpty()) {
|
if (query.isNotEmpty()) {
|
||||||
val requestBody = SearchInput(query.trim())
|
val searchBody = SearchInput(query.trim())
|
||||||
.let(json::encodeToString)
|
.let(json::encodeToString)
|
||||||
.toRequestBody(JSON_MEDIA_TYPE)
|
.replace("\"", "\\\"")
|
||||||
|
|
||||||
val newHeaders = headersBuilder()
|
val requestBody = """{
|
||||||
.add("Content-Length", requestBody.contentLength().toString())
|
|"path":"search/serie?page=$page",
|
||||||
.add("Content-Type", requestBody.contentType().toString())
|
|"headers":{"Content-type":"application/json"},
|
||||||
.build()
|
|"method":"POST","body":"$searchBody"
|
||||||
|
|}
|
||||||
|
""".trimMargin().toRequestBody(JSON_MEDIA_TYPE)
|
||||||
|
|
||||||
return POST("$apiUrl/search/serie?page=$page", newHeaders, requestBody)
|
return POST(apiUrl, headers, requestBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
val advSearchUrl = apiUrl.toHttpUrl().newBuilder().apply {
|
val advSearchBody = buildString {
|
||||||
addPathSegments("search/advance")
|
append("search/advance")
|
||||||
addQueryParameter("page", page.toString())
|
append("?page=", page)
|
||||||
addQueryParameter("serie_type", "webtoon")
|
append("&serie_type=webtoon")
|
||||||
|
|
||||||
filters.forEach { filter ->
|
filters.forEach { filter ->
|
||||||
when (filter) {
|
when (filter) {
|
||||||
is GenreFilter -> {
|
is GenreFilter -> {
|
||||||
filter.checked.let {
|
filter.checked.let {
|
||||||
if (it.isNotEmpty()) {
|
if (it.isNotEmpty()) {
|
||||||
addQueryParameter("genres", it.joinToString(","))
|
append("&genres=", it.joinToString(","))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is MainGenreFilter -> {
|
is MainGenreFilter -> {
|
||||||
if (filter.state > 0) {
|
if (filter.state > 0) {
|
||||||
addQueryParameter("main_genres", filter.selected)
|
append("&main_genres=", filter.selected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is TypeFilter -> {
|
is TypeFilter -> {
|
||||||
if (filter.state > 0) {
|
if (filter.state > 0) {
|
||||||
addQueryParameter("type", filter.selected)
|
append("&type=", filter.selected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is StatusFilter -> {
|
is StatusFilter -> {
|
||||||
if (filter.state > 0) {
|
if (filter.state > 0) {
|
||||||
addQueryParameter("status", filter.selected)
|
append("&status=", filter.selected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.build()
|
}
|
||||||
|
|
||||||
return GET(advSearchUrl, headers)
|
return postPath(advSearchBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response) = latestUpdatesParse(response)
|
override fun searchMangaParse(response: Response) = latestUpdatesParse(response)
|
||||||
|
@ -222,7 +226,7 @@ abstract class FlixScans(
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
val id = manga.url.split("-")[1]
|
val id = manga.url.split("-")[1]
|
||||||
|
|
||||||
return GET("$apiUrl/webtoon/series/$id", headers)
|
return postPath("webtoon/series/$id")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMangaUrl(manga: SManga) = baseUrl + manga.url
|
override fun getMangaUrl(manga: SManga) = baseUrl + manga.url
|
||||||
|
@ -236,7 +240,7 @@ abstract class FlixScans(
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
val id = manga.url.split("-")[1]
|
val id = manga.url.split("-")[1]
|
||||||
|
|
||||||
return GET("$apiUrl/webtoon/chapters/$id-desc", headers)
|
return postPath("webtoon/chapters/$id-desc")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
|
@ -250,7 +254,7 @@ abstract class FlixScans(
|
||||||
.substringAfterLast("/")
|
.substringAfterLast("/")
|
||||||
.substringBefore("-")
|
.substringBefore("-")
|
||||||
|
|
||||||
return GET("$apiUrl/webtoon/chapters/chapter/$id", headers)
|
return postPath("webtoon/chapters/chapter/$id")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChapterUrl(chapter: SChapter) = baseUrl + chapter.url
|
override fun getChapterUrl(chapter: SChapter) = baseUrl + chapter.url
|
||||||
|
@ -269,6 +273,6 @@ abstract class FlixScans(
|
||||||
use { body.string() }.let(json::decodeFromString)
|
use { body.string() }.let(json::decodeFromString)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()
|
private val JSON_MEDIA_TYPE = "application/json".toMediaTypeOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ data class ApiResponse<T>(
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PageInfo(
|
data class PageInfo(
|
||||||
@SerialName("last_page") val lastPage: Int,
|
@SerialName("last_page") val lastPage: Int,
|
||||||
|
@SerialName("current_page") val currentPage: Int,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
|
@ -9,7 +9,7 @@ class FlixScansGenerator : ThemeSourceGenerator {
|
||||||
|
|
||||||
override val themeClass = "FlixScans"
|
override val themeClass = "FlixScans"
|
||||||
|
|
||||||
override val baseVersionCode: Int = 3
|
override val baseVersionCode: Int = 4
|
||||||
|
|
||||||
override val sources = listOf(
|
override val sources = listOf(
|
||||||
SingleLang("Flix Scans", "https://flixscans.org", "en", className = "FlixScansNet", pkgName = "flixscans"),
|
SingleLang("Flix Scans", "https://flixscans.org", "en", className = "FlixScansNet", pkgName = "flixscans"),
|
||||||
|
|