NineHentai: Tags, Sorting, more manga details (#981)

This commit is contained in:
krogon500 2019-03-30 03:35:17 +05:00 committed by Eugene
parent 3014f5b3f6
commit fc3a2bf425
4 changed files with 1650 additions and 93 deletions

View File

@ -5,11 +5,11 @@ ext {
appName = 'Tachiyomi: NineHentai'
pkgNameSuffix = 'all.ninehentai'
extClass = '.NineHentai'
extVersionCode = 3
extVersionCode = 4
libVersion = '1.2'
}
dependencies {
compileOnly 'com.google.code.gson:gson:2.8.2'
compileOnly 'com.google.code.gson:gson:2.8.5'
compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0'
compileOnly 'com.github.inorichi.injekt:injekt-core:65b0440'
}

View File

@ -1,5 +1,32 @@
package eu.kanade.tachiyomi.extension.all.ninehentai
data class id(
val id : Int
import eu.kanade.tachiyomi.source.model.Filter
data class Manga(
val id : Int,
var title: String,
val image_server: String,
val tags: List<Tag>,
val total_page: Int
)
class Tag(
val id: Int,
name: String,
val description: String = "null",
val type: Int = 1
): Filter.TriState(name)
data class SearchRequest(
val text: String,
val page: Int,
val sort: Int,
val pages: Map<String, IntArray> = mapOf("range" to intArrayOf(0, 2000)),
val tag: Map<String, Items>
)
data class Items(
val included: MutableList<Tag>,
val excluded: MutableList<Tag>
)

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi.extension.all.ninehentai
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.fromJson
import com.github.salomonbrys.kotson.int
import com.github.salomonbrys.kotson.string
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.network.POST
@ -15,7 +15,6 @@ import okhttp3.*
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import java.net.URLEncoder
import java.util.*
open class NineHentai : ParsedHttpSource() {
@ -30,6 +29,8 @@ open class NineHentai : ParsedHttpSource() {
override val client: OkHttpClient = network.cloudflareClient
private val gson = Gson()
override fun popularMangaRequest(page: Int): Request {
return POST(baseUrl + SEARCH_URL, headers, buildRequestBody(page = page, sort = 1))
}
@ -42,105 +43,92 @@ open class NineHentai : ParsedHttpSource() {
return client.newCall(popularMangaRequest(page))
.asObservableSuccess()
.map { response ->
popularMangaParse(response)
getMangaList(response, page)
}
}
override fun popularMangaParse(response: Response): MangasPage {
val list = getMangaList(response)
return MangasPage(list, list.isNotEmpty())
}
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
return client.newCall(latestUpdatesRequest(page))
.asObservableSuccess()
.map { response ->
latestUpdatesParse(response)
getMangaList(response, page)
}
}
override fun latestUpdatesParse(response: Response): MangasPage = popularMangaParse(response)
private fun getMangaList(response: Response): List<SManga> {
val jsonData = response.body()!!.string()
val jsonObject = JsonParser().parse(jsonData).asJsonObject
val results = jsonObject.getAsJsonArray("results")
return parseSearch(results.toList())
}
private fun parseSearch(jsonArray: List<JsonElement>): List<SManga> {
val mutableList = mutableListOf<SManga>()
jsonArray.forEach { json ->
val manga = SManga.create()
val id = json["id"].string
manga.url = "$baseUrl/g/$id"
manga.title = json["title"].string
manga.thumbnail_url = json["image_server"].string + id + "/" + "cover.jpg"
mutableList.add(manga)
}
return mutableList
}
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
return client.newCall(mangaDetailsRequest(manga))
.asObservableSuccess()
.map { response ->
chapterListParse(response)
}
}
private fun getChapter(response: Response): SChapter {
val jsonData = response.body()!!.string()
val jsonObject = JsonParser().parse(jsonData).asJsonObject
val jsonArray = jsonObject.getAsJsonObject("results")
val sChapter = SChapter.create()
jsonArray.let { json ->
val id = json["id"].string
sChapter.url = "$baseUrl/g/$id"
sChapter.name = "chapter"
//api doesnt return date so setting to current date for now
sChapter.date_upload = Date().time
}
return sChapter
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
return POST(baseUrl + SEARCH_URL, headers, buildRequestBody(query, page))
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return client.newCall(searchMangaRequest(page, query, filters))
.asObservableSuccess()
.map { response ->
searchMangaParse(response)
getMangaList(response, page)
}
}
override fun searchMangaParse(response: Response): MangasPage = popularMangaParse(response)
override fun mangaDetailsParse(response: Response): SManga {
private fun getMangaList(response: Response, page: Int): MangasPage {
val jsonData = response.body()!!.string()
val jsonObject = JsonParser().parse(jsonData).asJsonObject
val results = jsonObject.getAsJsonObject("results")
return parseSearch(listOf(results))[0]
val totalPages = jsonObject["total_count"].int
val results = jsonObject["results"].array
return MangasPage(parseSearch(results.toList()), page < totalPages)
}
override fun chapterListParse(response: Response): List<SChapter> = listOf(getChapter(response))
private fun parseSearch(jsonArray: List<JsonElement>): List<SManga> {
val mutableList = mutableListOf<SManga>()
jsonArray.forEach { json ->
val manga = SManga.create()
val gsonManga = gson.fromJson<Manga>(json)
manga.url = "/g/${gsonManga.id}"
manga.title = gsonManga.title
manga.thumbnail_url = gsonManga.image_server + gsonManga.id + "/cover.jpg"
manga.genre = gsonManga.tags.filter { it.type == 1 }.joinToString { it.name }
manga.artist = gsonManga.tags.firstOrNull { it.type == 4 }?.name
manga.initialized = true
mutableList.add(manga)
}
return mutableList
}
override fun pageListParse(document: Document) = throw Exception("Not used")
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
val chapter = SChapter.create()
val chapterId = manga.url.substringAfter("/g/").toInt()
chapter.url = "/g/$chapterId"
chapter.name = "chapter"
//api doesnt return date so setting to current date for now
chapter.date_upload = Date().time
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
val mangaId = chapter.url.substringAfter("/g/").toInt()
return Observable.just(listOf(chapter))
}
return client.newCall(POST(baseUrl + MANGA_URL, headers, buildIdBody(mangaId)))
.asObservableSuccess()
.map { response ->
pageListParse(response)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val includedTags = mutableListOf<Tag>()
val excludedTags = mutableListOf<Tag>()
var sort = 0
for (filter in if (filters.isEmpty()) getFilterList() else filters) {
when(filter){
is GenreList -> {
filter.state.forEach { f ->
if (!f.isIgnored()) {
if (f.isExcluded())
excludedTags.add(f)
else
includedTags.add(f)
}
}
}
is Sorting -> {
sort = filter.state!!.index
}
}
}
return POST(baseUrl + SEARCH_URL, headers, buildRequestBody(query, page, sort, includedTags, excludedTags))
}
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return Observable.just(manga)
}
override fun pageListRequest(chapter: SChapter): Request {
val mangaId = chapter.url.substringAfter("/g/").toInt()
return POST(baseUrl + MANGA_URL, headers, buildIdBody(mangaId))
}
override fun pageListParse(response: Response): List<Page> {
@ -152,38 +140,54 @@ open class NineHentai : ParsedHttpSource() {
var mangaId: String
jsonArray.let { json ->
mangaId = json["id"].string
imageUrl = json["image_server"].string + mangaId + "/"
imageUrl = json["image_server"].string + mangaId
totalPages = json["total_page"].int
}
val pages = mutableListOf<Page>()
for (i in 1..totalPages) {
pages.add(Page(pages.size, "", "$imageUrl$i.jpg"))
pages.add(Page(pages.size, "", "$imageUrl/$i.jpg"))
}
return pages
}
private fun buildRequestBody(searchText: String = "", page: Int = 0, sort: Int = 0): RequestBody {
val gson = GsonBuilder().create()
val json = gson.toJson(mapOf("search" to mapOf("text" to searchText, "page" to page, "sort" to sort, "pages" to mapOf("range" to intArrayOf(0, 2000)), "tag" to mapOf("text" to "", "type" to 1, "tags" to arrayOf<String>(), "items" to mapOf("included" to arrayOf<String>(), "excluded" to arrayOf())))))
private fun buildRequestBody(searchText: String = "", page: Int, sort: Int = 0, includedTags: MutableList<Tag> = arrayListOf(), excludedTags: MutableList<Tag> = arrayListOf()): RequestBody {
val json = gson.toJson(mapOf("search" to SearchRequest(text = searchText, page = page-1, sort = sort, tag = mapOf("items" to Items(includedTags, excludedTags)))))
return RequestBody.create(MEDIA_TYPE, json)
}
override fun mangaDetailsRequest(manga: SManga): Request {
val id = manga.url.substringAfter("/g/").toInt()
return POST(baseUrl + MANGA_URL, headers, buildIdBody(id))
private fun buildIdBody(id: Int): RequestBody {
return RequestBody.create(MEDIA_TYPE, gson.toJson(mapOf("id" to id)))
}
private fun buildIdBody(id: Int): RequestBody {
val dto = eu.kanade.tachiyomi.extension.all.ninehentai.id(id)
return RequestBody.create(MEDIA_TYPE, Gson().toJson(dto))
}
private class GenreList(tags: List<Tag>) : Filter.Group<Tag>("Tags", tags)
private class Sorting : Filter.Sort("Sorting",
arrayOf("Newest", "Popular Rightnow", "Most Fapped", "Most Viewed", "By Title"),
Filter.Sort.Selection(1, false))
override fun getFilterList() = FilterList(
Sorting(),
GenreList(NHTags.getTagsList())
)
override fun imageUrlParse(document: Document): String = ""
override fun chapterListRequest(manga: SManga): Request = throw Exception("Not Used")
override fun popularMangaParse(response: Response): MangasPage = throw Exception("Not Used")
override fun latestUpdatesParse(response: Response): MangasPage = throw Exception("Not Used")
override fun searchMangaParse(response: Response): MangasPage = throw Exception("Not Used")
override fun chapterListParse(response: Response): List<SChapter> = throw Exception("Not Used")
override fun chapterFromElement(element: Element): SChapter = throw Exception("Not used")
override fun pageListParse(document: Document) = throw Exception("Not used")
override fun chapterListSelector(): String = throw Exception("Not used")
override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("Not used")
@ -192,6 +196,8 @@ open class NineHentai : ParsedHttpSource() {
override fun latestUpdatesSelector(): String = throw Exception("Not used")
override fun mangaDetailsParse(response: Response): SManga = throw Exception("Not Used")
override fun mangaDetailsParse(document: Document): SManga = throw Exception("Not used")
override fun popularMangaFromElement(element: Element): SManga = throw Exception("Not used")