* Added NineManga (All) * done latest, all and manga parse. * Complete manga img parse * Added TODO to change language conditions. * Date corrections. * Remove old icons. * Override status and date functions in the different classes.
This commit is contained in:
parent
5533dae52f
commit
de52d6c215
|
@ -0,0 +1,12 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
appName = 'Tachiyomi: NineManga'
|
||||
pkgNameSuffix = "all.ninemanga"
|
||||
extClass = '.NineMangaEs; .NineMangaBr; .NineMangaEn; .NineMangaRu; .NineMangaDe; .NineMangaIt; .NineMangaFr'
|
||||
extVersionCode = 1
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
|
@ -0,0 +1,127 @@
|
|||
package eu.kanade.tachiyomi.extension.all.ninemanga
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import okhttp3.Request
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
open class NineManga(override val name: String, override val baseUrl: String, override val lang: String) : ParsedHttpSource() {
|
||||
|
||||
override val supportsLatest: Boolean = true
|
||||
|
||||
private fun newHeaders() = super.headersBuilder()
|
||||
.add("Accept-Language", "es-ES,es;q=0.9,en;q=0.8,gl;q=0.7")
|
||||
.add("Host", baseUrl.substringAfterLast("/")) // like: es.ninemanga.com
|
||||
.add("Connection", "keep-alive")
|
||||
.add("Upgrade-Insecure-Requests", "1")
|
||||
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/60")
|
||||
.build()
|
||||
|
||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/list/New-Update/", headers) // "$baseUrl/category/updated_$page.html"
|
||||
|
||||
override fun latestUpdatesSelector() = "ul.direlist > li"
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
|
||||
element.select("dl.bookinfo").let {
|
||||
setUrlWithoutDomain(it.select("dd > a.bookname").attr("href") + "?waring=1") // To removes warning message and shows chapter list.
|
||||
title = it.select("dd > a.bookname").first().text()
|
||||
thumbnail_url = it.select("dt > a > img").attr("src")
|
||||
}
|
||||
}
|
||||
|
||||
override fun latestUpdatesNextPageSelector() = "ul.pageList > li:last-child > a.l"
|
||||
|
||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/category/index_$page.html", headers)
|
||||
|
||||
override fun popularMangaSelector() = latestUpdatesSelector()
|
||||
|
||||
override fun popularMangaFromElement(element: Element) = latestUpdatesFromElement(element)
|
||||
|
||||
override fun popularMangaNextPageSelector() = latestUpdatesNextPageSelector()
|
||||
|
||||
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
||||
document.select("div.bookintro").let {
|
||||
thumbnail_url = document.select("a.bookface > img").attr("src")
|
||||
genre = document.select("li[itemprop=genre] > a").joinToString(", ") {
|
||||
it.text()
|
||||
}
|
||||
author = it.select("a[itemprop=author]").text()
|
||||
artist = ""
|
||||
description = it.select("p[itemprop=description]").text().orEmpty()
|
||||
status = parseStatus(it.select("a.red").first().text().orEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
open fun parseStatus(status: String) = when {
|
||||
status.contains("Ongoing") -> SManga.ONGOING
|
||||
status.contains("Completed") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = "ul.sub_vol_ul > li"
|
||||
|
||||
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
||||
element.select("a.chapter_list_a").let {
|
||||
name = it.text()
|
||||
setUrlWithoutDomain(it.attr("href"))
|
||||
}
|
||||
date_upload = parseChapterDate(element.select("span").text())
|
||||
}
|
||||
|
||||
open fun parseChapterDate(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
if(dateWords[1].contains(",")){
|
||||
try {
|
||||
return SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
return 0L
|
||||
}
|
||||
}else {
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
return Calendar.getInstance().apply {
|
||||
when (dateWords[1]) {
|
||||
"minutes" -> Calendar.MINUTE
|
||||
"hours" -> Calendar.HOUR
|
||||
else -> null
|
||||
}?.let {
|
||||
add(it, -timeAgo)
|
||||
}
|
||||
}.timeInMillis
|
||||
}
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url, newHeaders())
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
|
||||
document.select("select#page").first().select("option").forEach {
|
||||
add(Page(size, baseUrl + it.attr("value")))
|
||||
}
|
||||
}
|
||||
|
||||
override fun imageUrlRequest(page: Page) = GET(page.url, newHeaders())
|
||||
|
||||
override fun imageUrlParse(document: Document) = document.select("div.pic_box img.manga_pic").first().attr("src").orEmpty()
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
return GET("$baseUrl/search/?name_sel=&wd=$query&author_sel=&author=&artist_sel=&artist=&category_id=&out_category_id=&completed_series=&page=$page.html", headers)
|
||||
}
|
||||
|
||||
override fun searchMangaSelector() = popularMangaSelector()
|
||||
|
||||
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
|
||||
|
||||
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
//TODO: Implement filters list.
|
||||
// Array.from(document.querySelectorAll('.optionbox .typelist:nth-child(3) ul')).map(a => Array.from(a.querySelectorAll('li')).map(b => `Genre("${b.querySelector('label').innerText}", "${a.querySelector('li[cate_id]').getAttribute('cate_id')}")`)).join(',\n')
|
||||
// http://es.ninemanga.com/search/?name_sel=contain&wd=&author_sel=contain&author=&artist_sel=contain&artist=&category_id=&out_category_id=&completed_series=either&type=high
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
package eu.kanade.tachiyomi.extension.all.ninemanga
|
||||
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceFactory
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class NineMangaFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = getAllNineManga()
|
||||
}
|
||||
|
||||
fun getAllNineManga(): List<Source> {
|
||||
return listOf(
|
||||
NineMangaEn(),
|
||||
NineMangaEs(),
|
||||
NineMangaBr(),
|
||||
NineMangaRu(),
|
||||
NineMangaDe(),
|
||||
NineMangaIt(),
|
||||
NineMangaFr()
|
||||
)
|
||||
}
|
||||
|
||||
class NineMangaEn : NineManga("NineMangaEn", "http://en.ninemanga.com", "en")
|
||||
|
||||
class NineMangaEs : NineManga("NineMangaEs", "http://es.ninemanga.com", "es") {
|
||||
override fun parseStatus(status: String) = when {
|
||||
status.contains("En curso") -> SManga.ONGOING
|
||||
status.contains("Completado") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun parseChapterDate(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
if(dateWords[1].contains(",")){
|
||||
try {
|
||||
return SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
return 0L
|
||||
}
|
||||
}else{
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
return Calendar.getInstance().apply {
|
||||
when (dateWords[1]) {
|
||||
"minutos" -> Calendar.MINUTE
|
||||
"horas" -> Calendar.HOUR
|
||||
else -> null
|
||||
}?.let {
|
||||
add(it, -timeAgo)
|
||||
}
|
||||
}.timeInMillis
|
||||
}
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
|
||||
class NineMangaBr : NineManga("NineMangaBr", "http://br.ninemanga.com", "br") {
|
||||
override fun parseStatus(status: String) = when {
|
||||
status.contains("Em tradução") -> SManga.ONGOING
|
||||
status.contains("Completo") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun parseChapterDate(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
if(dateWords[1].contains(",")){
|
||||
try {
|
||||
return SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
return 0L
|
||||
}
|
||||
}else{
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
return Calendar.getInstance().apply {
|
||||
when (dateWords[1]) {
|
||||
"minutos" -> Calendar.MINUTE
|
||||
"hora" -> Calendar.HOUR
|
||||
else -> null
|
||||
}?.let {
|
||||
add(it, -timeAgo)
|
||||
}
|
||||
}.timeInMillis
|
||||
}
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
|
||||
class NineMangaRu : NineManga("NineMangaRu", "http://ru.ninemanga.com", "ru") {
|
||||
override fun parseStatus(status: String) = when {
|
||||
// No Ongoing status
|
||||
status.contains("завершенный") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun parseChapterDate(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
if(dateWords[1].contains(",")){
|
||||
try {
|
||||
return SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
return 0L
|
||||
}
|
||||
}else{
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
return Calendar.getInstance().apply {
|
||||
when (dateWords[1]) {
|
||||
"минут" -> Calendar.MINUTE
|
||||
"часа" -> Calendar.HOUR
|
||||
else -> null
|
||||
}?.let {
|
||||
add(it, -timeAgo)
|
||||
}
|
||||
}.timeInMillis
|
||||
}
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
|
||||
class NineMangaDe : NineManga("NineMangaDe", "http://de.ninemanga.com", "de") {
|
||||
override fun parseStatus(status: String) = when {
|
||||
status.contains("Laufende") -> SManga.ONGOING
|
||||
status.contains("Abgeschlossen") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun parseChapterDate(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
try {
|
||||
return SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
else if (dateWords.size == 2) { // Aleman
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
return Calendar.getInstance().apply {
|
||||
when (dateWords[1]) {
|
||||
"Stunden" -> Calendar.HOUR // Aleman - 2 palabras
|
||||
else -> null
|
||||
}?.let {
|
||||
add(it, -timeAgo)
|
||||
}
|
||||
}.timeInMillis
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
|
||||
class NineMangaIt : NineManga("NineMangaIt", "http://it.ninemanga.com", "it") {
|
||||
override fun parseStatus(status: String) = when {
|
||||
status.contains("In corso") -> SManga.ONGOING
|
||||
status.contains("Completato") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun parseChapterDate(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
if(!dateWords[1].contains(",")){
|
||||
try {
|
||||
return SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
return 0L
|
||||
}
|
||||
}else{
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
return Calendar.getInstance().apply {
|
||||
when (dateWords[1]) {
|
||||
"minuti" -> Calendar.MINUTE
|
||||
"ore" -> Calendar.HOUR
|
||||
else -> null
|
||||
}?.let {
|
||||
add(it, -timeAgo)
|
||||
}
|
||||
}.timeInMillis
|
||||
}
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
|
||||
class NineMangaFr : NineManga("NineMangaFr", "http://fr.ninemanga.com", "fr") {
|
||||
override fun parseStatus(status: String) = when {
|
||||
status.contains("En cours") -> SManga.ONGOING
|
||||
status.contains("Complété") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun parseChapterDate(date: String): Long {
|
||||
val dateWords = date.split(" ")
|
||||
|
||||
if (dateWords.size == 3) {
|
||||
try {
|
||||
return SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
|
||||
else if(dateWords.size == 5) {
|
||||
val timeAgo = Integer.parseInt(dateWords[3])
|
||||
return Calendar.getInstance().apply {
|
||||
when (dateWords[4]) {
|
||||
"minutes" -> Calendar.MINUTE
|
||||
"heures" -> Calendar.HOUR
|
||||
else -> null
|
||||
}?.let {
|
||||
add(it, -timeAgo)
|
||||
}
|
||||
}.timeInMillis
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue