AnimeSama: Fix Website changes (#3939)
* AnimeSama: Full Rewrite * AnimeSama: Fix "Special" chapters * AnimeSama: Changes asked by AwkwardPeak7 * AnimeSama: Maybe better containsMultipleTimes function * AnimeSama: Changes from AwkwardPeak7
This commit is contained in:
parent
cb1d65d02c
commit
cb4c648b19
|
@ -1,7 +1,7 @@
|
|||
ext {
|
||||
extName = 'AnimeSama'
|
||||
extClass = '.AnimeSama'
|
||||
extVersionCode = 1
|
||||
extVersionCode = 2
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
package eu.kanade.tachiyomi.extension.fr.animesama
|
||||
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
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.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class AnimeSama : ParsedHttpSource() {
|
||||
|
||||
|
@ -24,80 +23,68 @@ class AnimeSama : ParsedHttpSource() {
|
|||
|
||||
override val baseUrl = "https://anime-sama.fr"
|
||||
|
||||
val cdn_url = "https://cdn.statically.io/gh/Anime-Sama/IMG/img/animes/animes%20icones%20carr%C3%A9/"
|
||||
private val cdn = "$baseUrl/s2/scans/"
|
||||
|
||||
override val lang = "fr"
|
||||
|
||||
override val supportsLatest = true
|
||||
override val supportsLatest = false
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
|
||||
.add("Accept-Language", "fr-FR")
|
||||
|
||||
// Popular
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return GET("$baseUrl/scan", headers)
|
||||
return GET("$baseUrl/catalogue/", headers)
|
||||
}
|
||||
|
||||
override fun popularMangaSelector() = "figure.figure"
|
||||
override fun popularMangaSelector() = ".cardListAnime.Scans"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga {
|
||||
return SManga.create().apply {
|
||||
title = element.select("figcaption").text()
|
||||
title = element.select("h1").text()
|
||||
setUrlWithoutDomain(element.select("a").attr("href"))
|
||||
thumbnail_url = element.select("a > img").attr("src")
|
||||
thumbnail_url = element.select("img").attr("src")
|
||||
}
|
||||
}
|
||||
|
||||
override fun popularMangaNextPageSelector(): String? = null
|
||||
|
||||
// Latest
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return GET(baseUrl, headers)
|
||||
}
|
||||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
|
||||
|
||||
override fun latestUpdatesSelector() = "div.container-fluid:nth-child(15) > div:nth-child(1) figure"
|
||||
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SManga {
|
||||
return SManga.create().apply {
|
||||
title = element.select("figcaption").text().replace("\\nScan\\n", "")
|
||||
setUrlWithoutDomain(cdn_url + title.replace(" ", "-").trim() + "carre.jpg")
|
||||
thumbnail_url = element.select("img").attr("src")
|
||||
}
|
||||
}
|
||||
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
|
||||
|
||||
override fun latestUpdatesNextPageSelector(): String? = null
|
||||
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
|
||||
|
||||
// Search
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val uri = Uri.parse("$baseUrl/search/search.php").buildUpon()
|
||||
.appendQueryParameter("terme", query + " [SCANS]")
|
||||
.appendQueryParameter("s", "Search")
|
||||
return GET(uri.toString(), headers)
|
||||
val url = "$baseUrl/template-php/defaut/fetch.php"
|
||||
val formBody = FormBody.Builder()
|
||||
.add("query", query)
|
||||
.build()
|
||||
|
||||
return POST(url, headers, formBody)
|
||||
}
|
||||
override fun searchMangaSelector() = "div.media-body"
|
||||
override fun searchMangaSelector() = "a[href*='catalogue']"
|
||||
override fun searchMangaNextPageSelector(): String? = null
|
||||
override fun searchMangaFromElement(element: Element): SManga {
|
||||
return SManga.create().apply {
|
||||
title = element.select("h5").text()
|
||||
setUrlWithoutDomain(element.select("a").attr("href"))
|
||||
thumbnail_url =
|
||||
cdn_url + title.replace(
|
||||
" [SCANS]",
|
||||
"",
|
||||
).replace(" ", "-").trim() + "carre.jpg"
|
||||
title = element.select("h3").text()
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
thumbnail_url = element.select("img").attr("src")
|
||||
}
|
||||
}
|
||||
|
||||
// Details
|
||||
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
|
||||
title = document.select("div.carousel-item:nth-child(1) > div:nth-child(2) > h5:nth-child(1)").text()
|
||||
description = document.select("div.carousel-item:nth-child(2) > div:nth-child(2) > p:nth-child(1)").text()
|
||||
thumbnail_url = document.select("div.carousel-item:nth-child(1) > img:nth-child(1)").attr("src")
|
||||
genre = document.select("div.carousel-item:nth-child(2) > div:nth-child(2) > p:nth-child(2)").text().replace("Genres : ", "")
|
||||
description = document.select("#sousBlocMilieu > div h2:contains(Synopsis)+p").text()
|
||||
genre = document.select("#sousBlocMilieu > div h2:contains(Genres)+a").text()
|
||||
title = document.select("#titreOeuvre").text()
|
||||
thumbnail_url = document.select("#coverOeuvre").attr("src")
|
||||
}
|
||||
|
||||
// Chapters
|
||||
|
@ -105,58 +92,109 @@ class AnimeSama : ParsedHttpSource() {
|
|||
|
||||
override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException()
|
||||
|
||||
fun String.containsMultipleTimes(search: String): Boolean {
|
||||
val regex = Regex(search)
|
||||
val matches = regex.findAll(this)
|
||||
val count = matches.count()
|
||||
return count > 1
|
||||
}
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request {
|
||||
val url = "$baseUrl${manga.url}/scan/vf"
|
||||
return GET(url, headers)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
val javascriptUrl = document.select("body > script:nth-child(3)").attr("abs:src")
|
||||
var document = response.asJsoup()
|
||||
|
||||
val newHeaders = headersBuilder()
|
||||
.add("Accept-Version", "v1")
|
||||
.build()
|
||||
val baseChapterUrl = "episodes.js?title=" + document.select("#titreOeuvre").text()
|
||||
|
||||
val request = GET(javascriptUrl, newHeaders)
|
||||
val responsejs = client.newCall(request).execute()
|
||||
val jsonDataString = responsejs.body.string()
|
||||
val requestToFetchChapters = GET("${document.baseUri()}/$baseChapterUrl", headers)
|
||||
val javascriptFile = client.newCall(requestToFetchChapters).execute()
|
||||
var javascriptFileContent = javascriptFile.body.string()
|
||||
|
||||
return jsonDataString
|
||||
val parsedJavascriptFileToJson = javascriptFileContent
|
||||
.split(" ", ",")
|
||||
.filter { it.contains("eps") && !it.contains("drive.google.com") }
|
||||
.mapNotNull { it.replace("=", "").replace("eps", "").toIntOrNull() }
|
||||
.sorted()
|
||||
.map { chapter ->
|
||||
}.asReversed()
|
||||
var parsedChapterList: MutableList<SChapter> = ArrayList()
|
||||
var chapterDelay = 0
|
||||
|
||||
var scriptContent = document.select("script:containsData(resetListe\\(\\))").toString()
|
||||
if (scriptContent.containsMultipleTimes("resetListe()")) {
|
||||
var scriptCommandList = document.html().split(";")
|
||||
var createListRegex = Regex("""creerListe\((\d+,\s*\d+)\)""")
|
||||
var specialRegex = Regex("""newSP\((\d+(\.\d+)?)\)""")
|
||||
scriptCommandList.forEach { command ->
|
||||
when {
|
||||
createListRegex.find(command) != null -> {
|
||||
var data = createListRegex.find(command)!!.groupValues[1].split(",")
|
||||
var start = data[0].replace(" ", "").toInt()
|
||||
var end = data[1].replace(" ", "").toInt()
|
||||
|
||||
for (i in start..end) {
|
||||
parsedChapterList.add(
|
||||
SChapter.create().apply {
|
||||
name = "Chapitre $chapter"
|
||||
setUrlWithoutDomain(javascriptUrl + "/$chapter")
|
||||
name = "Chapitre " + i
|
||||
setUrlWithoutDomain(document.baseUri() + "/" + baseChapterUrl + "&id=${parsedChapterList.size + 1}")
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
specialRegex.find(command) != null -> {
|
||||
var title = specialRegex.find(command)!!.groupValues[1]
|
||||
parsedChapterList.add(
|
||||
SChapter.create().apply {
|
||||
name = "Chapitre " + title
|
||||
setUrlWithoutDomain(document.baseUri() + "/" + baseChapterUrl + "&id=${parsedChapterList.size + 1}")
|
||||
},
|
||||
)
|
||||
chapterDelay++
|
||||
}
|
||||
/* The site contains an as-yet unused command called "newSPE", and as I have no concrete examples of its use, I haven't implemented it yet. */
|
||||
}
|
||||
}
|
||||
}
|
||||
for (index in parsedChapterList.size..parsedJavascriptFileToJson.size - 1) {
|
||||
parsedChapterList.add(
|
||||
SChapter.create().apply {
|
||||
name = "Chapitre " + (parsedChapterList.size + 1 - chapterDelay)
|
||||
setUrlWithoutDomain(document.baseUri() + "/" + baseChapterUrl + "&id=${parsedChapterList.size + 1}")
|
||||
},
|
||||
)
|
||||
}
|
||||
return parsedChapterList.asReversed()
|
||||
}
|
||||
|
||||
// Pages
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
val url = document.baseUri().split("/")
|
||||
val javascriptUrlFinal = url.subList(0, url.size - 1).joinToString("/")
|
||||
val javascriptResponse = checkJavascript(javascriptUrlFinal)
|
||||
val jsonDataString = javascriptResponse.body.string()
|
||||
val url = document.baseUri().toHttpUrl()
|
||||
|
||||
val episode = url[url.size - 1]
|
||||
val allEpisodes = jsonDataString.split("var")
|
||||
val title = url.queryParameter("title")
|
||||
val chapter = url.queryParameter("id")
|
||||
|
||||
val theEpisode = allEpisodes.firstOrNull { it.contains("eps$episode") }
|
||||
val allChapters = document.body().toString().split("var")
|
||||
|
||||
val chapterImageListString = allChapters.firstOrNull { it.contains("eps$chapter=") }
|
||||
?: return emptyList()
|
||||
|
||||
val final_list = theEpisode
|
||||
val chapterImageListParsed = chapterImageListString
|
||||
.substringAfter("[")
|
||||
.substringBefore("]")
|
||||
.split(",")
|
||||
|
||||
return final_list
|
||||
.substring(0, final_list.lastIndexOf(",")).replace("""'""".toRegex(), "\"")
|
||||
.let { json.decodeFromString<List<String>>("[$it]") }
|
||||
.mapIndexed { i, imageUrl -> Page(i, "", imageUrl) }
|
||||
val image_list = mutableListOf<Page>()
|
||||
|
||||
for (index in 1 until chapterImageListParsed.size) {
|
||||
image_list.add(
|
||||
Page(index, imageUrl = "$cdn$title/$chapter/$index.jpg"),
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkJavascript(url: String): Response {
|
||||
val request = GET(url, headers)
|
||||
|
||||
return client.newCall(request).execute()
|
||||
return image_list
|
||||
}
|
||||
|
||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||
|
|
Loading…
Reference in New Issue