Added support for Anime Sama (#12382)

* - First functional version of extension

* - Real icons using as280093 tool

* - New icons with real tools
- Addition and modification of lessandrojean's advice to make it work well
- Manga icons in full HD

Co-authored-by: CriosChan <nc!Mtep&2ovv#7VJoPbUU6ifFu>
This commit is contained in:
CriosChan 2022-07-02 01:06:24 +02:00 committed by GitHub
parent 8d2c9c79ed
commit 4b6faa8952
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 184 additions and 0 deletions

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="eu.kanade.tachiyomi.extension" />

View File

@ -0,0 +1,11 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = 'AnimeSama'
pkgNameSuffix = 'fr.animesama'
extClass = '.AnimeSama'
extVersionCode = 1
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -0,0 +1,171 @@
package eu.kanade.tachiyomi.extension.fr.animesama
import android.net.Uri
import eu.kanade.tachiyomi.network.GET
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.Headers
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() {
override val name = "AnimeSama"
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/"
override val lang = "fr"
override val supportsLatest = true
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)
}
override fun popularMangaSelector() = "figure.figure"
override fun popularMangaFromElement(element: Element): SManga {
return SManga.create().apply {
title = element.select("figcaption").text()
setUrlWithoutDomain(element.select("a").attr("href"))
thumbnail_url = element.select("a > img").attr("src")
}
}
override fun popularMangaNextPageSelector(): String? = null
// Latest
override fun latestUpdatesRequest(page: Int): Request {
return GET(baseUrl, headers)
}
override fun latestUpdatesSelector() = "div.container-fluid:nth-child(15) > div:nth-child(1) figure"
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 latestUpdatesNextPageSelector(): String? = null
// 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)
}
override fun searchMangaSelector() = "div.media-body"
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"
}
}
// 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 : ", "")
}
// Chapters
override fun chapterListSelector() = throw Exception("Not used")
override fun chapterFromElement(element: Element): SChapter = throw Exception("Not used")
override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup()
val javascriptUrl = document.select("body > script:nth-child(3)").attr("abs:src")
val newHeaders = headersBuilder()
.add("Accept-Version", "v1")
.build()
val request = GET(javascriptUrl, newHeaders)
val responsejs = client.newCall(request).execute()
val jsonDataString = responsejs.body?.string().orEmpty()
return jsonDataString
.split(" ", ",")
.filter { it.contains("eps") && !it.contains("drive.google.com") }
.mapNotNull { it.replace("=", "").replace("eps", "").toIntOrNull() }
.sorted()
.map { chapter ->
SChapter.create().apply {
name = "Chapitre $chapter"
setUrlWithoutDomain(javascriptUrl + "/$chapter")
}
}
}
// 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().orEmpty()
val episode = url[url.size - 1]
val allEpisodes = jsonDataString.split("var")
val theEpisode = allEpisodes.firstOrNull { it.contains("eps$episode") }
?: return emptyList()
val final_list = theEpisode
.substringAfter("[")
.substringBefore("]")
return final_list
.substring(0, final_list.lastIndexOf(",")).replace("""'""".toRegex(), "\"")
.let { json.decodeFromString<List<String>>("[$it]") }
.mapIndexed { i, imageUrl -> Page(i, "", imageUrl) }
}
private fun checkJavascript(url: String): Response {
val request = GET(url, headers)
return client.newCall(request).execute()
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used")
override fun imageRequest(page: Page): Request {
val imgHeaders = headersBuilder()
.add("Referer", baseUrl)
.build()
return GET(page.imageUrl!!, imgHeaders)
}
}