Merge pull request #32 from jmir1/lib12

This commit is contained in:
jmir1
2021-06-29 16:31:54 +02:00
committed by GitHub
9 changed files with 91 additions and 86 deletions

View File

@ -1,7 +1,7 @@
// used both in common.gradle and themesources library // used both in common.gradle and themesources library
dependencies { dependencies {
// Lib 1.3, but using specific commit so we don't need to bump up the version // Lib 1.3, but using specific commit so we don't need to bump up the version
compileOnly "com.github.jmir1:extensions-lib:6467320" compileOnly "com.github.jmir1:extensions-lib:632a3e4"
// These are provided by the app itself // These are provided by the app itself
compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"

View File

@ -5,8 +5,8 @@ ext {
extName = '4anime.to' extName = '4anime.to'
pkgNameSuffix = 'en.fouranime' pkgNameSuffix = 'en.fouranime'
extClass = '.FourAnime' extClass = '.FourAnime'
extVersionCode = 11 extVersionCode = 12
libVersion = '11' libVersion = '12'
} }
dependencies { dependencies {
ext.coroutinesVersion = "1.4.3" ext.coroutinesVersion = "1.4.3"

View File

@ -1,9 +1,9 @@
package eu.kanade.tachiyomi.animeextension.en.fouranime package eu.kanade.tachiyomi.animeextension.en.fouranime
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.Link
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import okhttp3.Request import okhttp3.Request
@ -58,12 +58,21 @@ class FourAnime : ParsedAnimeHttpSource() {
text.replace("[^\\d]".toRegex(), "").toFloat() + firstLetterAsNumber text.replace("[^\\d]".toRegex(), "").toFloat() + firstLetterAsNumber
} }
} }
override fun episodeLinkSelector() = "source"
override fun linksFromElement(element: Element): List<Link> { override fun videoListSelector() = "source"
return mutableListOf(Link(element.attr("src"), "1080p"))
override fun videoFromElement(element: Element): Video {
return Video(element.attr("src"), "1080p", null, null)
} }
override fun fetchVideoUrl(video: Video): Observable<String> {
return Observable.just(video.url)
}
override fun videoUrlSelector() = throw Exception("not used")
override fun videoUrlFromElement(element: Element) = throw Exception("not used")
override fun searchAnimeFromElement(element: Element): SAnime { override fun searchAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create() val anime = SAnime.create()
anime.setUrlWithoutDomain(element.select("a").attr("href")) anime.setUrlWithoutDomain(element.select("a").attr("href"))

View File

@ -5,8 +5,8 @@ ext {
extName = 'Gogoanime' extName = 'Gogoanime'
pkgNameSuffix = 'en.gogoanime' pkgNameSuffix = 'en.gogoanime'
extClass = '.GogoAnime' extClass = '.GogoAnime'
extVersionCode = 5 extVersionCode = 6
libVersion = '11' libVersion = '12'
} }
dependencies { dependencies {
ext.coroutinesVersion = "1.4.3" ext.coroutinesVersion = "1.4.3"

View File

@ -1,23 +1,22 @@
package eu.kanade.tachiyomi.animeextension.en.gogoanime package eu.kanade.tachiyomi.animeextension.en.gogoanime
import android.util.Log
import com.google.gson.JsonParser import com.google.gson.JsonParser
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.Link
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.Headers import okhttp3.Headers.Companion.toHeaders
import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import java.lang.Exception
class GogoAnime : ParsedAnimeHttpSource() { class GogoAnime : ParsedAnimeHttpSource() {
@ -29,6 +28,8 @@ class GogoAnime : ParsedAnimeHttpSource() {
override val supportsLatest = true override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
override fun popularAnimeSelector(): String = "div.img a" override fun popularAnimeSelector(): String = "div.img a"
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/popular.html?page=$page") override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/popular.html?page=$page")
@ -53,30 +54,13 @@ class GogoAnime : ParsedAnimeHttpSource() {
} }
private suspend fun episodesRequest(totalEpisodes: String, id: String): List<SEpisode> { private suspend fun episodesRequest(totalEpisodes: String, id: String): List<SEpisode> {
val request = GET("https://ajax.gogo-load.com/ajax/load-list-episode?ep_start=0&ep_end=$totalEpisodes&id=$id") val request = GET("https://ajax.gogo-load.com/ajax/load-list-episode?ep_start=0&ep_end=$totalEpisodes&id=$id", headers)
val epResponse = client.newCall(request) val epResponse = client.newCall(request)
.await() .await()
val document = epResponse.asJsoup() val document = epResponse.asJsoup()
return document.select("a").map { episodeFromElement(it) } return document.select("a").map { episodeFromElement(it) }
} }
override fun fetchEpisodeLink(episode: SEpisode): Observable<List<Link>> {
return client.newCall(GET(baseUrl + episode.url))
.asObservableSuccess()
.map { response ->
runBlocking { linkRequest(response) }
}
}
private suspend fun linkRequest(response: Response): List<Link> {
val elements = response.asJsoup()
val link = elements.select("a[data-video*=streamani.net/load.php]").attr("data-video")
val dlResponse = client.newCall(GET("https:$link", Headers.headersOf("referer", baseUrl)))
.await()
val document = dlResponse.asJsoup()
return linksFromElement(document.select(episodeLinkSelector()).first())
}
override fun episodeFromElement(element: Element): SEpisode { override fun episodeFromElement(element: Element): SEpisode {
val episode = SEpisode.create() val episode = SEpisode.create()
episode.setUrlWithoutDomain(baseUrl + element.attr("href").substringAfter(" ")) episode.setUrlWithoutDomain(baseUrl + element.attr("href").substringAfter(" "))
@ -87,12 +71,26 @@ class GogoAnime : ParsedAnimeHttpSource() {
return episode return episode
} }
override fun episodeLinkSelector() = "div.videocontent script" override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
var videoListUrl = document.selectFirst("a[data-video*=streamani.net/load.php]").attr("data-video")
if (!videoListUrl.startsWith("https:")) videoListUrl = "https:$videoListUrl"
val newHeaderList = mutableMapOf(Pair("referer", baseUrl))
headers.forEach { newHeaderList[it.first] = it.second }
val videoListResponse = runBlocking {
client.newCall(GET(videoListUrl, newHeaderList.toHeaders()))
.await().asJsoup()
}
return videoListFromElement(videoListResponse.selectFirst(videoListSelector()))
}
override fun linksFromElement(element: Element): List<Link> { override fun videoListSelector() = "div.videocontent script"
val links = mutableListOf<Link>()
override fun videoFromElement(element: Element) = throw Exception("not used")
private fun videoListFromElement(element: Element): List<Video> {
val videos = mutableListOf<Video>()
val content = element.data() val content = element.data()
Log.i("links", content)
var hit = content.indexOf("playerInstance.setup(") var hit = content.indexOf("playerInstance.setup(")
while (hit >= 0) { while (hit >= 0) {
val objectString = val objectString =
@ -106,36 +104,37 @@ class GogoAnime : ParsedAnimeHttpSource() {
link = link.replace("/videos/hls/$toRemove", "/videos/hls/") link = link.replace("/videos/hls/$toRemove", "/videos/hls/")
} }
val quality = jsonObject["label"].asString val quality = jsonObject["label"].asString
Log.i("links:", "$link - $quality") if (videos.isEmpty() || !videos.last().url.contains(link.substringAfterLast("/"))) {
if (links.isEmpty() || !links.last().url.contains(link.substringAfterLast("/"))) {
if (link.contains("m3u8")) { if (link.contains("m3u8")) {
val individualLinks = runBlocking { getIndividualLinks(link) } val individualLinks = runBlocking { getIndividualLinks(link) }
individualLinks.forEach { links.add(it) } individualLinks.forEach { videos.add(it) }
} else { } else {
links.add(Link(link, quality)) videos.add(Video(link, quality, link, null))
} }
} }
hit = content.indexOf("playerInstance.setup(", hit + 1) hit = content.indexOf("playerInstance.setup(", hit + 1)
} }
return links return videos
} }
private suspend fun getIndividualLinks(link: String): List<Link> { private suspend fun getIndividualLinks(link: String): List<Video> {
val response = client.newCall(GET(link)).await().body!!.string() val response = client.newCall(GET(link)).await().body!!.string()
Log.i("links", response)
val links = response.split("\n").filter { !it.startsWith("#") && it.isNotEmpty() }.toMutableList() val links = response.split("\n").filter { !it.startsWith("#") && it.isNotEmpty() }.toMutableList()
val qualities = response.split("\n").filter { it.startsWith("#EXT-X-STREAM-INF") }.toMutableList() val qualities = response.split("\n").filter { it.startsWith("#EXT-X-STREAM-INF") }.toMutableList()
Log.i("links", links.lastIndex.toString() + qualities.lastIndex.toString()) val linkList = mutableListOf<Video>()
val linkList = mutableListOf<Link>()
if (qualities.lastIndex != links.lastIndex) return emptyList() if (qualities.lastIndex != links.lastIndex) return emptyList()
for (i in 0..qualities.lastIndex) { for (i in 0..qualities.lastIndex) {
links[i] = link.substringBeforeLast("/") + "/" + links[i] links[i] = link.substringBeforeLast("/") + "/" + links[i]
qualities[i] = qualities[i].substringAfter("NAME=").replace("\"", "") qualities[i] = qualities[i].substringAfter("NAME=").replace("\"", "")
linkList.add(Link(links[i], qualities[i])) linkList.add(Video(links[i], qualities[i], links[i], null))
} }
return linkList.reversed() return linkList.reversed()
} }
override fun videoUrlFromElement(element: Element): String = throw Exception("not used")
override fun videoUrlSelector() = throw Exception("not used")
override fun searchAnimeFromElement(element: Element): SAnime { override fun searchAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create() val anime = SAnime.create()
anime.setUrlWithoutDomain(element.attr("href")) anime.setUrlWithoutDomain(element.attr("href"))
@ -148,7 +147,8 @@ class GogoAnime : ParsedAnimeHttpSource() {
override fun searchAnimeSelector(): String = "div.img a" override fun searchAnimeSelector(): String = "div.img a"
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = GET("$baseUrl/search.html?keyword=$query&page=$page") override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request =
GET("$baseUrl/search.html?keyword=$query&page=$page", headers)
override fun animeDetailsParse(document: Document): SAnime { override fun animeDetailsParse(document: Document): SAnime {
val anime = SAnime.create() val anime = SAnime.create()
@ -178,7 +178,8 @@ class GogoAnime : ParsedAnimeHttpSource() {
return anime return anime
} }
override fun latestUpdatesRequest(page: Int): Request = GET("https://ajax.gogo-load.com/ajax/page-recent-release-ongoing.html?page=$page&type=1") override fun latestUpdatesRequest(page: Int): Request =
GET("https://ajax.gogo-load.com/ajax/page-recent-release-ongoing.html?page=$page&type=1", headers)
override fun latestUpdatesSelector(): String = "div.added_series_body.popular li a:has(div)" override fun latestUpdatesSelector(): String = "div.added_series_body.popular li a:has(div)"
} }

View File

@ -5,8 +5,8 @@ ext {
extName = 'hanime.tv' extName = 'hanime.tv'
pkgNameSuffix = 'en.hanime' pkgNameSuffix = 'en.hanime'
extClass = '.Hanime' extClass = '.Hanime'
extVersionCode = 6 extVersionCode = 7
libVersion = '11' libVersion = '12'
containsNsfw = true containsNsfw = true
} }
dependencies { dependencies {

View File

@ -6,9 +6,9 @@ import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.Link
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
@ -117,16 +117,16 @@ class Hanime : AnimeHttpSource() {
return anime return anime
} }
override fun episodeLinkParse(response: Response): List<Link> { override fun videoListParse(response: Response): List<Video> {
val responseString = response.body!!.string() val responseString = response.body!!.string()
val jElement: JsonElement = JsonParser.parseString(responseString) val jElement: JsonElement = JsonParser.parseString(responseString)
val jObject: JsonObject = jElement.asJsonObject val jObject: JsonObject = jElement.asJsonObject
val server = jObject.get("videos_manifest").asJsonObject.get("servers").asJsonArray[0].asJsonObject val server = jObject.get("videos_manifest").asJsonObject.get("servers").asJsonArray[0].asJsonObject
val streams = server.get("streams").asJsonArray val streams = server.get("streams").asJsonArray
val linkList = mutableListOf<Link>() val linkList = mutableListOf<Video>()
for (stream in streams) { for (stream in streams) {
if (stream.asJsonObject.get("kind").asString != "premium_alert") { if (stream.asJsonObject.get("kind").asString != "premium_alert") {
linkList.add(Link(stream.asJsonObject.get("url").asString, stream.asJsonObject.get("height").asString + "p")) linkList.add(Video(stream.asJsonObject.get("url").asString, stream.asJsonObject.get("height").asString + "p", stream.asJsonObject.get("url").asString, null))
} }
} }
return linkList return linkList

View File

@ -5,8 +5,8 @@ ext {
extName = 'tenshi.moe' extName = 'tenshi.moe'
pkgNameSuffix = 'en.tenshimoe' pkgNameSuffix = 'en.tenshimoe'
extClass = '.TenshiMoe' extClass = '.TenshiMoe'
extVersionCode = 16 extVersionCode = 17
libVersion = '11' libVersion = '12'
} }
dependencies { dependencies {
ext.coroutinesVersion = "1.4.3" ext.coroutinesVersion = "1.4.3"

View File

@ -3,22 +3,21 @@ package eu.kanade.tachiyomi.animeextension.en.tenshimoe
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.util.Log import android.util.Log
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.Link
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.Headers import okhttp3.Headers.Companion.toHeaders
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import java.lang.Exception
import java.lang.Float.parseFloat import java.lang.Float.parseFloat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
@ -47,7 +46,7 @@ class TenshiMoe : ParsedAnimeHttpSource() {
return anime return anime
} }
override fun popularAnimeNextPageSelector(): String? = "ul.pagination li.page-item a[rel=next]" override fun popularAnimeNextPageSelector(): String = "ul.pagination li.page-item a[rel=next]"
override fun episodeListSelector() = "ul.episode-loop li a" override fun episodeListSelector() = "ul.episode-loop li a"
@ -88,34 +87,30 @@ class TenshiMoe : ParsedAnimeHttpSource() {
return Date(-1L) return Date(-1L)
} }
override fun fetchEpisodeLink(episode: SEpisode): Observable<List<Link>> { override fun videoListParse(response: Response): List<Video> {
return client.newCall(GET(baseUrl + episode.url)) val document = response.asJsoup()
.asObservableSuccess() val iframe = document.selectFirst("iframe").attr("src")
.map { response -> val referer = response.request.url.encodedPath
Log.w("tenshi", "linkReq") val newHeaderList = mutableMapOf(Pair("referer", baseUrl + referer))
runBlocking { linkRequest(response) } headers.forEach { newHeaderList[it.first] = it.second }
} val iframeResponse = runBlocking {
} client.newCall(GET(iframe, newHeaderList.toHeaders()))
.await().asJsoup()
private suspend fun linkRequest(response: Response): List<Link> {
val elements = response.asJsoup()
val link = elements.select("iframe").attr("src")
val dlResponse = client.newCall(GET(link, Headers.headersOf("referer", response.request.url.toString()))).await()
val document = dlResponse.asJsoup()
return linksFromElement(document.select(episodeLinkSelector()).first())
}
override fun episodeLinkSelector() = "video#player"
override fun linksFromElement(element: Element): List<Link> {
val linkList = mutableListOf<Link>()
val linkElements = element.select("source")
for (link in linkElements) {
linkList.add(Link(link.attr("src"), link.attr("title")))
} }
return linkList return iframeResponse.select(videoListSelector()).map { videoFromElement(it) }
} }
override fun videoListSelector() = "source"
override fun videoFromElement(element: Element): Video {
Log.i("lol", element.attr("src"))
return Video(element.attr("src"), element.attr("title"), element.attr("src"), null)
}
override fun videoUrlFromElement(element: Element): String = throw Exception("not used")
override fun videoUrlSelector() = throw Exception("not used")
override fun searchAnimeFromElement(element: Element): SAnime { override fun searchAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create() val anime = SAnime.create()
anime.setUrlWithoutDomain(element.attr("href") + "?s=srt-d") anime.setUrlWithoutDomain(element.attr("href") + "?s=srt-d")