remove 2dgirls.tech and add gogoanime
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
// used both in common.gradle and themesources library
|
||||
dependencies {
|
||||
// Lib 1.3, but using specific commit so we don't need to bump up the version
|
||||
compileOnly "com.github.jmir1:extensions-lib:92b69d1"
|
||||
compileOnly "com.github.jmir1:extensions-lib:6467320"
|
||||
|
||||
// These are provided by the app itself
|
||||
compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
|
@ -2,10 +2,10 @@ apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
extName = '2dgirls.tech'
|
||||
pkgNameSuffix = 'en.twodgirlstech'
|
||||
extClass = '.TwoDGirlsTech'
|
||||
extVersionCode = 12
|
||||
extName = 'Gogoanime'
|
||||
pkgNameSuffix = 'en.gogoanime'
|
||||
extClass = '.GogoAnime'
|
||||
extVersionCode = 1
|
||||
libVersion = '11'
|
||||
}
|
||||
dependencies {
|
@ -0,0 +1,144 @@
|
||||
package eu.kanade.tachiyomi.animeextension.en.gogoanime
|
||||
|
||||
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.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.network.await
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
|
||||
class GogoAnime : ParsedAnimeHttpSource() {
|
||||
|
||||
override val name = "Gogoanime"
|
||||
|
||||
override val baseUrl = "https://www1.gogoanime.ai"
|
||||
|
||||
override val lang = "en"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
override fun popularAnimeSelector(): String = "div.img a"
|
||||
|
||||
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/popular.html?page=$page")
|
||||
|
||||
override fun popularAnimeFromElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.attr("href"))
|
||||
anime.thumbnail_url = element.select("img").first().attr("src")
|
||||
anime.title = element.attr("title")
|
||||
return anime
|
||||
}
|
||||
|
||||
override fun popularAnimeNextPageSelector(): String = "ul.pagination-list li:last-child:not(.selected)"
|
||||
|
||||
override fun episodeListSelector() = "ul#episode_page li a"
|
||||
|
||||
override fun episodeListParse(response: Response): List<SEpisode> {
|
||||
val document = response.asJsoup()
|
||||
val totalEpisodes = document.select(episodeListSelector()).last().attr("ep_end")
|
||||
val id = document.select("input#movie_id").attr("value")
|
||||
return runBlocking { episodesRequest(totalEpisodes, id) }
|
||||
}
|
||||
|
||||
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 epResponse = client.newCall(request)
|
||||
.await()
|
||||
val document = epResponse.asJsoup()
|
||||
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("li.dowloads a").attr("href")
|
||||
val dlResponse = client.newCall(GET(link))
|
||||
.await()
|
||||
val document = dlResponse.asJsoup()
|
||||
return linksFromElement(document.select(episodeLinkSelector()).first())
|
||||
}
|
||||
|
||||
override fun episodeFromElement(element: Element): SEpisode {
|
||||
val episode = SEpisode.create()
|
||||
episode.setUrlWithoutDomain(baseUrl + element.attr("href").substringAfter(" "))
|
||||
val ep = element.selectFirst("div.name").ownText().substringAfter(" ")
|
||||
episode.episode_number = ep.toFloat()
|
||||
episode.name = "Episode $ep"
|
||||
episode.date_upload = System.currentTimeMillis()
|
||||
return episode
|
||||
}
|
||||
|
||||
override fun episodeLinkSelector() = "div.mirror_link:has(a[download])"
|
||||
|
||||
override fun linksFromElement(element: Element): List<Link> {
|
||||
val links = mutableListOf<Link>()
|
||||
val linkElements = element.select("a[download]")
|
||||
for (e in linkElements) {
|
||||
val quality = e.text().substringAfter("Download (").replace("P - mp4)", "p")
|
||||
links.add(Link(e.attr("href"), quality))
|
||||
}
|
||||
return links
|
||||
}
|
||||
|
||||
override fun searchAnimeFromElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.attr("href"))
|
||||
anime.thumbnail_url = element.select("img").first().attr("src")
|
||||
anime.title = element.attr("title")
|
||||
return anime
|
||||
}
|
||||
|
||||
override fun searchAnimeNextPageSelector(): String = "ul.pagination-list li:last-child:not(.selected)"
|
||||
|
||||
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 animeDetailsParse(document: Document): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.title = document.select("div.anime_info_body_bg h1").text()
|
||||
anime.genre = document.select("p.type:eq(5) a").joinToString("") { it.text() }
|
||||
anime.description = document.select("p.type:eq(4)").first().ownText()
|
||||
anime.status = parseStatus(document.select("p.type:eq(7) a").text())
|
||||
return anime
|
||||
}
|
||||
|
||||
private fun parseStatus(statusString: String): Int {
|
||||
return when (statusString) {
|
||||
"Ongoing" -> SAnime.ONGOING
|
||||
"Completed" -> SAnime.COMPLETED
|
||||
else -> SAnime.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
override fun latestUpdatesNextPageSelector(): String = "ul.pagination-list li:last-child:not(.selected)"
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(baseUrl + element.attr("href"))
|
||||
val style = element.select("div.thumbnail-popular").attr("style")
|
||||
anime.thumbnail_url = style.substringAfter("background: url('").substringBefore("');")
|
||||
anime.title = element.attr("title")
|
||||
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 latestUpdatesSelector(): String = "div.added_series_body.popular li a:has(div)"
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 81 KiB |
@ -1,203 +0,0 @@
|
||||
package eu.kanade.tachiyomi.animeextension.en.twodgirlstech
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
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.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.Call
|
||||
import okhttp3.Callback
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.io.IOException
|
||||
import java.net.URLEncoder
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class TwoDGirlsTech : ParsedAnimeHttpSource() {
|
||||
|
||||
override val name = "2dgirls.tech"
|
||||
|
||||
override val baseUrl = "https://2dgirls.tech"
|
||||
|
||||
override val lang = "en"
|
||||
|
||||
override val supportsLatest = false
|
||||
|
||||
override fun fetchPopularAnime(page: Int): Observable<AnimesPage> {
|
||||
return Observable.just(runBlocking { get(page) })
|
||||
}
|
||||
|
||||
suspend fun get(page: Int): AnimesPage {
|
||||
var hasNextPage = true
|
||||
val request = GET("$baseUrl/api/popular/$page")
|
||||
val arrayListDetails: ArrayList<SAnime> = ArrayList()
|
||||
return suspendCoroutine<AnimesPage> { continuation ->
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
throw e
|
||||
}
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val strResponse = response.body!!.string()
|
||||
// creating json object
|
||||
val json = JSONObject(strResponse)
|
||||
// creating json array
|
||||
val jsonArrayInfo: JSONArray = json.getJSONArray("results")
|
||||
val size: Int = jsonArrayInfo.length()
|
||||
for (i in 0 until size) {
|
||||
val anime = SAnime.create()
|
||||
val jsonObjectDetail: JSONObject = jsonArrayInfo.getJSONObject(i)
|
||||
anime.title = jsonObjectDetail.getString("title")
|
||||
anime.thumbnail_url = jsonObjectDetail.getString("image")
|
||||
anime.setUrlWithoutDomain("/api/detailshtml/" + jsonObjectDetail.getString("id"))
|
||||
arrayListDetails.add(anime)
|
||||
}
|
||||
hasNextPage = (arrayListDetails.isNotEmpty())
|
||||
continuation.resume(AnimesPage(arrayListDetails, hasNextPage))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setDetails(anime: SAnime): SAnime {
|
||||
val request = GET("$baseUrl/api/details/${anime.url.split("/api/detailshtml/").last()}")
|
||||
return suspendCoroutine<SAnime> { continuation ->
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
throw e
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val strResponse = response.body!!.string()
|
||||
// creating json object
|
||||
val json = JSONObject(strResponse)
|
||||
// creating json array
|
||||
val jsonArrayInfo: JSONArray = json.getJSONArray("results")
|
||||
val size: Int = jsonArrayInfo.length()
|
||||
for (i in 0..size - 1) {
|
||||
val jsonObjectDetail: JSONObject = jsonArrayInfo.getJSONObject(i)
|
||||
anime.genre = jsonObjectDetail.getString("genres")
|
||||
when (jsonObjectDetail.getString("status").replace("\\s".toRegex(), "")) {
|
||||
"Ongoing" -> anime.status = SAnime.ONGOING
|
||||
"Completed" -> anime.status = SAnime.COMPLETED
|
||||
}
|
||||
anime.description = jsonObjectDetail.getString("summary")
|
||||
}
|
||||
continuation.resume(anime)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
|
||||
return Observable.just(runBlocking { getSearch(page, query) })
|
||||
}
|
||||
|
||||
suspend fun getSearch(page: Int, query: String): AnimesPage {
|
||||
var hasNextPage: Boolean
|
||||
val queryEncoded = withContext(Dispatchers.IO) { URLEncoder.encode(query, "utf-8") }
|
||||
val request = GET("$baseUrl/api/search/$queryEncoded/$page")
|
||||
val arrayListDetails: ArrayList<SAnime> = ArrayList()
|
||||
return suspendCoroutine<AnimesPage> { continuation ->
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
throw e
|
||||
}
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val strResponse = response.body!!.string()
|
||||
// creating json object
|
||||
val json = JSONObject(strResponse)
|
||||
// creating json array
|
||||
val jsonArrayInfo: JSONArray = json.getJSONArray("results")
|
||||
val size: Int = jsonArrayInfo.length()
|
||||
for (i in 0..size - 1) {
|
||||
val anime = SAnime.create()
|
||||
val jsonObjectDetail: JSONObject = jsonArrayInfo.getJSONObject(i)
|
||||
anime.title = jsonObjectDetail.getString("title")
|
||||
anime.thumbnail_url = jsonObjectDetail.getString("image")
|
||||
anime.setUrlWithoutDomain("/api/detailshtml/" + jsonObjectDetail.getString("id"))
|
||||
arrayListDetails.add(anime)
|
||||
}
|
||||
hasNextPage = json.getBoolean("nextpage")
|
||||
continuation.resume(AnimesPage(arrayListDetails, hasNextPage))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> {
|
||||
return Observable.just(runBlocking { setDetails(anime) })
|
||||
}
|
||||
|
||||
override fun episodeListSelector() = "div[id^=episode-]"
|
||||
|
||||
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
|
||||
return super.fetchEpisodeList(anime).flatMap { Observable.just(it.reversed()) }
|
||||
}
|
||||
|
||||
override fun episodeFromElement(element: Element): SEpisode {
|
||||
val id = element.id().split(":").last()
|
||||
val episodeNumber = element.id().split("episode-").last().split(":").first()
|
||||
val episode = SEpisode.create()
|
||||
episode.episode_number = episodeNumber.toFloat()
|
||||
episode.name = "Episode $episodeNumber"
|
||||
episode.url = "/api/watchinghtml/$id/$episodeNumber"
|
||||
episode.date_upload = System.currentTimeMillis()
|
||||
return episode
|
||||
}
|
||||
|
||||
override fun episodeLinkSelector() = "body"
|
||||
|
||||
override fun linksFromElement(element: Element): List<Link> {
|
||||
val json = JSONObject(element.text())
|
||||
val jsonArrayInfo: JSONArray = json.getJSONArray("links")
|
||||
val size: Int = jsonArrayInfo.length()
|
||||
val urls = mutableListOf<Link>()
|
||||
for (i in 0..size - 1) {
|
||||
val jsonObjectDetail: JSONObject = jsonArrayInfo.getJSONObject(i)
|
||||
urls.add(Link(jsonObjectDetail.getString("src"), jsonObjectDetail.getString("size")))
|
||||
}
|
||||
return urls
|
||||
}
|
||||
|
||||
override fun popularAnimeSelector(): String = throw Exception("Not used")
|
||||
|
||||
override fun searchAnimeFromElement(element: Element): SAnime = throw Exception("Not used")
|
||||
|
||||
override fun searchAnimeNextPageSelector(): String? = throw Exception("Not used")
|
||||
|
||||
override fun searchAnimeSelector(): String = throw Exception("Not used")
|
||||
|
||||
override fun popularAnimeRequest(page: Int): Request = throw Exception("Not used")
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = throw Exception("Not used")
|
||||
|
||||
override fun popularAnimeNextPageSelector(): String? = throw Exception("Not used")
|
||||
|
||||
override fun popularAnimeFromElement(element: Element): SAnime = throw Exception("Not used")
|
||||
|
||||
override fun animeDetailsParse(document: Document): SAnime = throw Exception("Not used")
|
||||
|
||||
override fun latestUpdatesNextPageSelector(): String? = throw Exception("Not used")
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SAnime = throw Exception("Not used")
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not used")
|
||||
|
||||
override fun latestUpdatesSelector(): String = throw Exception("Not used")
|
||||
|
||||
companion object {
|
||||
const val baseAltTextUrl = "https://fakeimg.pl/1500x2126/ffffff/000000/?text="
|
||||
const val baseAltTextPostUrl = "&font_size=42&font=museo"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user