Manhwa latino: (#9848)
* First commit Mahnwa-Latino Extension. * manhwa-latino: Implementing find function TODO: only works with text, filter not implemented yet * manhwa-latino Add Parser to finde the information of Manhwa-Latino The parser 'ManhwaLatinoSiteParser.kt' make the whole magic to find the information of the Website. Mudularize The code and adding documentation * manhwa-latino: Adding Logos der Extension TODO: I am not to happy, i will check it later. * manhwa-latino: Adding Tags to Genre Combobox * manhwa-latino: Adding Headers to prevent error 404 The headers are necesary to prevent error 403 by downloading images. * manhwa-latino: Tags addded into Manga Description Page Status from Manga readed from Tags * manhwa-latino: Modularize Code * manhwa-latino: Adding Uploaddate for Chapters * manhwa-latino: Bug to get Chapter Number fixed * manhwa-latino: Logo 0.2 * manhwa-latino: Versionb 1.2.10 Adding Comments to ManhwaLatinoSiteParser * manhwa-latino: Remove logo_model directory * manhwa-latino: Show Seconds after Release a new Chapter * manhwa-latino: Fix for Cloudflare * manhwa-latino: Try to fix Cloudflare ByPass Adding isNsfw to build.gradle * manhwa-latino: Update from parser after website update * manhwa-latino: Deactivate lastest manga and new Client The new website from Manhwa-Latino doesnt show lastest mangas. * manhwa-latino: Adding Manifest to load url-adress The extesion will bi able to open and find mangas with the url. TODO: first version. NOT READY YET. * manhwa-latino: Fix to find Manga Status information * Manhwa-Latino: The Extension can open a Link Now the extension can recognize a link from Manhwa-Latino and show the manga from the link in the app. * Manhwa-Latino: Modularize Code and Activity for Url added * Manhwa-Latino: Add Constant-File. This file contain all contants for this extension. Co-authored-by: Luis Beroiza <luisalberto.beroizaosses@intern.osp-dd.de> Co-authored-by: AlberyKous <extreme_rvd@hotmail.com>
This commit is contained in:
parent
726813f019
commit
33088997db
|
@ -1,2 +1,24 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest package="eu.kanade.tachiyomi.extension" />
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="eu.kanade.tachiyomi.extension">
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity
|
||||||
|
android:name=".es.manhwalatino.ManhwaLatinoUrlActivity"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:exported="true"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data
|
||||||
|
android:host="manhwa-latino.com"
|
||||||
|
android:pathPattern="/..*/..*"
|
||||||
|
android:scheme="https" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
</manifest>
|
|
@ -5,8 +5,8 @@ ext {
|
||||||
extName = 'Manhwa-Latino'
|
extName = 'Manhwa-Latino'
|
||||||
pkgNameSuffix = 'es.manhwalatino'
|
pkgNameSuffix = 'es.manhwalatino'
|
||||||
extClass = '.ManhwaLatino'
|
extClass = '.ManhwaLatino'
|
||||||
extVersionCode = 11
|
extVersionCode = 14
|
||||||
containsNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.es.manhwalatino
|
||||||
|
|
||||||
|
object MLConstants {
|
||||||
|
|
||||||
|
const val PREFIX_MANGA_ID_SEARCH = "id:"
|
||||||
|
|
||||||
|
const val searchMangaNextPageSelector = "link[rel=next]"
|
||||||
|
const val latestUpdatesSelector = "div.slider__item"
|
||||||
|
const val searchMangaSelector = "div.page-item-detail.manga"
|
||||||
|
const val popularMangaNextPageSelector = "a.nextpostslink"
|
||||||
|
const val latestUpdatesNextPageSelector = "div[role=navigation] a.last"
|
||||||
|
|
||||||
|
const val popularMangaSelector = "div.page-item-detail.manga"
|
||||||
|
const val popularGenreTitleHTMLSelector: String = "div.item-summary div.post-title h3"
|
||||||
|
const val popularGenreUrlHTMLSelector: String = "div.item-summary div.post-title h3 a"
|
||||||
|
const val popularGenreThumbnailUrlMangaHTMLSelector: String = "div.item-thumb.c-image-hover img"
|
||||||
|
|
||||||
|
const val searchPageTitleHTMLSelector: String = "div.tab-summary div.post-title h3"
|
||||||
|
const val searchPageUrlHTMLSelector: String = "div.tab-summary div.post-title h3 a"
|
||||||
|
const val searchPageThumbnailUrlMangaHTMLSelector: String = "div.tab-thumb.c-image-hover img"
|
||||||
|
|
||||||
|
const val mangaDetailsThumbnailUrlHTMLSelector: String = "div.summary_image img"
|
||||||
|
const val mangaDetailsAuthorHTMLSelector: String = "div.author-content"
|
||||||
|
const val mangaDetailsArtistHTMLSelector: String = "div.artist-content"
|
||||||
|
const val mangaDetailsDescriptionHTMLSelector: String = "div.post-content_item > div > p"
|
||||||
|
const val mangaDetailsGenreHTMLSelector: String = "div.genres-content a"
|
||||||
|
const val mangaDetailsTagsHTMLSelector: String = "div.tags-content a"
|
||||||
|
const val mangaDetailsAttributes: String = "div.summary_content div.post-content_item"
|
||||||
|
const val searchSiteMangasHTMLSelector = "div.c-tabs-item__content"
|
||||||
|
const val genreSiteMangasHTMLSelector = "div.page-item-detail.manga"
|
||||||
|
const val latestUpdatesSelectorUrl = "div.slider__thumb_item > a"
|
||||||
|
const val latestUpdatesSelectorThumbnailUrl = "div.slider__thumb_item > a > img"
|
||||||
|
const val latestUpdatesSelectorTitle = "div.slider__content h4"
|
||||||
|
const val chapterListParseSelector = "li.wp-manga-chapter"
|
||||||
|
const val chapterLinkParser = "a"
|
||||||
|
const val chapterReleaseDateLinkParser = "span.chapter-release-date a"
|
||||||
|
const val chapterReleaseDateIParser = "span.chapter-release-date i"
|
||||||
|
const val pageListParseSelector = "div.page-break.no-gaps img"
|
||||||
|
}
|
|
@ -11,10 +11,12 @@ import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
|
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
|
||||||
|
|
||||||
class ManhwaLatino : ParsedHttpSource() {
|
class ManhwaLatino : ParsedHttpSource() {
|
||||||
|
|
||||||
|
@ -28,10 +30,20 @@ class ManhwaLatino : ParsedHttpSource() {
|
||||||
*/
|
*/
|
||||||
override val baseUrl = "https://manhwa-latino.com"
|
override val baseUrl = "https://manhwa-latino.com"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header for Request
|
||||||
|
*/
|
||||||
|
override fun headersBuilder() = Headers.Builder().add("Referer", "$baseUrl")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http Client
|
||||||
|
*/
|
||||||
|
override val client: OkHttpClient = network.client.newBuilder().build()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parser for Mainsite or Genre Site
|
* Parser for Mainsite or Genre Site
|
||||||
*/
|
*/
|
||||||
val manhwaLatinoSiteParser = ManhwaLatinoSiteParser(baseUrl)
|
val manhwaLatinoSiteParser = ManhwaLatinoSiteParser(baseUrl, client, headers)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ISO 639-1 compliant language code (two letters in lower case).
|
* An ISO 639-1 compliant language code (two letters in lower case).
|
||||||
|
@ -43,37 +55,25 @@ class ManhwaLatino : ParsedHttpSource() {
|
||||||
*/
|
*/
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
/**
|
|
||||||
* User Agent for this wWebsite
|
|
||||||
*/
|
|
||||||
private val userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " +
|
|
||||||
"(KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
|
|
||||||
|
|
||||||
override fun headersBuilder(): Headers.Builder {
|
|
||||||
return Headers.Builder()
|
|
||||||
.add("User-Agent", userAgent)
|
|
||||||
.add("Referer", "$baseUrl/")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Jsoup selector that returns a list of [Element] corresponding to each manga.
|
* Returns the Jsoup selector that returns a list of [Element] corresponding to each manga.
|
||||||
*/
|
*/
|
||||||
override fun popularMangaSelector(): String {
|
override fun popularMangaSelector(): String {
|
||||||
return manhwaLatinoSiteParser.popularMangaSelector
|
return MLConstants.popularMangaSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Jsoup selector that returns a list of [Element] corresponding to each manga.
|
* Returns the Jsoup selector that returns a list of [Element] corresponding to each manga.
|
||||||
*/
|
*/
|
||||||
override fun latestUpdatesSelector(): String {
|
override fun latestUpdatesSelector(): String {
|
||||||
return manhwaLatinoSiteParser.latestUpdatesSelector
|
return MLConstants.latestUpdatesSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Jsoup selector that returns a list of [Element] corresponding to each manga.
|
* Returns the Jsoup selector that returns a list of [Element] corresponding to each manga.
|
||||||
*/
|
*/
|
||||||
override fun searchMangaSelector(): String {
|
override fun searchMangaSelector(): String {
|
||||||
return manhwaLatinoSiteParser.searchMangaSelector
|
return MLConstants.searchMangaSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,7 +87,7 @@ class ManhwaLatino : ParsedHttpSource() {
|
||||||
* there's no next page.
|
* there's no next page.
|
||||||
*/
|
*/
|
||||||
override fun popularMangaNextPageSelector(): String {
|
override fun popularMangaNextPageSelector(): String {
|
||||||
return manhwaLatinoSiteParser.popularMangaNextPageSelector
|
return MLConstants.popularMangaNextPageSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,7 +95,7 @@ class ManhwaLatino : ParsedHttpSource() {
|
||||||
* there's no next page.
|
* there's no next page.
|
||||||
*/
|
*/
|
||||||
override fun latestUpdatesNextPageSelector(): String {
|
override fun latestUpdatesNextPageSelector(): String {
|
||||||
return manhwaLatinoSiteParser.latestUpdatesNextPageSelector
|
return MLConstants.latestUpdatesNextPageSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,7 +103,7 @@ class ManhwaLatino : ParsedHttpSource() {
|
||||||
* there's no next page.
|
* there's no next page.
|
||||||
*/
|
*/
|
||||||
override fun searchMangaNextPageSelector(): String {
|
override fun searchMangaNextPageSelector(): String {
|
||||||
return manhwaLatinoSiteParser.searchMangaNextPageSelector
|
return MLConstants.searchMangaNextPageSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,6 +157,10 @@ class ManhwaLatino : ParsedHttpSource() {
|
||||||
return GET(uri.toString(), headers)
|
return GET(uri.toString(), headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||||
|
return manhwaLatinoSiteParser.fetchSearchManga(page, query, filters)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
||||||
*
|
*
|
||||||
|
@ -166,13 +170,13 @@ class ManhwaLatino : ParsedHttpSource() {
|
||||||
return manhwaLatinoSiteParser.searchMangaParse(response)
|
return manhwaLatinoSiteParser.searchMangaParse(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Returns the request for the details of a manga. Override only if it's needed to change the
|
* Returns the request for the details of a manga. Override only if it's needed to change the
|
||||||
// * url, send different headers or request method like POST.
|
* url, send different headers or request method like POST.
|
||||||
// *
|
*
|
||||||
// * @param manga the manga to be updated.
|
* @param manga the manga to be updated.
|
||||||
// */
|
*/
|
||||||
// override fun mangaDetailsRequest(manga: SManga) = GET(baseUrl + manga.url, headers)
|
override fun mangaDetailsRequest(manga: SManga) = GET(baseUrl + manga.url, headers)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request for updating the chapter list. Override only if it's needed to override
|
* Returns the request for updating the chapter list. Override only if it's needed to override
|
||||||
|
|
|
@ -2,62 +2,70 @@ package eu.kanade.tachiyomi.extension.es.manhwalatino
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.extension.es.manhwalatino.filters.UriFilter
|
import eu.kanade.tachiyomi.extension.es.manhwalatino.filters.UriFilter
|
||||||
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import okhttp3.Headers
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
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 org.jsoup.select.Elements
|
||||||
|
import rx.Observable
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
class ManhwaLatinoSiteParser(
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val client: OkHttpClient,
|
||||||
|
private val headers: Headers
|
||||||
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ADD SEARCH_TAG
|
* Search Type
|
||||||
*/
|
*/
|
||||||
enum class SearchType {
|
enum class SearchType {
|
||||||
SEARCH_FREE, SEARCH_FILTER
|
SEARCH_FREE, SEARCH_FILTER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of manga
|
||||||
|
*/
|
||||||
|
enum class MangaType {
|
||||||
|
ALL, ADULT, GAY;
|
||||||
|
|
||||||
|
// Static Enum Function
|
||||||
|
companion object {
|
||||||
|
fun isForAdults(mangaTypes: List<MangaType>): Boolean {
|
||||||
|
for (type in mangaTypes) {
|
||||||
|
when (type) {
|
||||||
|
ADULT, GAY -> return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS Class to search in the title of the manga
|
||||||
|
fun getBadge(): String {
|
||||||
|
return when (this) {
|
||||||
|
ADULT -> "adult"
|
||||||
|
GAY -> "gay"
|
||||||
|
ALL -> ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of search ( FREE, FILTER)
|
* Type of search ( FREE, FILTER)
|
||||||
*/
|
*/
|
||||||
var searchType = SearchType.SEARCH_FREE
|
private var searchType = SearchType.SEARCH_FREE
|
||||||
|
|
||||||
private val urlHTMLSelector: String = "a"
|
|
||||||
private val titleHTMLSelector: String = "h3"
|
|
||||||
private val thumbnailUrlMangaListHTMLSelector: String = "div.item-thumb.c-image-hover img"
|
|
||||||
private val authorHTMLSelector: String = "div.author-content"
|
|
||||||
private val artistHTMLSelector: String = "div.artist-content"
|
|
||||||
private val descriptionHTMLSelector: String = "div.summary__content.show-more p"
|
|
||||||
private val genreHTMLSelector: String = "div.genres-content a"
|
|
||||||
private val statusHTMLSelector: String =
|
|
||||||
"div.summary_content div.post-status div.post-content_item div.summary-content"
|
|
||||||
private val thumbnailUrlMangaDetailsHTMLSelector: String = "div.summary_image img"
|
|
||||||
private val tagsHTMLSelector: String = "div.tags-content a"
|
|
||||||
private val searchSiteMangasHTMLSelector = "div.c-tabs-item__content"
|
|
||||||
private val genreSiteMangasHTMLSelector = "div.page-item-detail.manga"
|
|
||||||
private val latestUpdatesSelectorUrl = "div.slider__thumb_item a"
|
|
||||||
private val latestUpdatesSelectorThumbnailUrl = "div.slider__thumb_item a img"
|
|
||||||
private val latestUpdatesSelectorTitle = "div.slider__content h4"
|
|
||||||
private val chapterListParseSelector = "li.wp-manga-chapter"
|
|
||||||
private val chapterLinkParser = "a"
|
|
||||||
private val chapterReleaseDateLinkParser = "span.chapter-release-date a"
|
|
||||||
private val chapterReleaseDateIParser = "span.chapter-release-date i"
|
|
||||||
private val pageListParseSelector = "div.page-break.no-gaps img"
|
|
||||||
|
|
||||||
val searchMangaNextPageSelector = "link[rel=next]"
|
|
||||||
val latestUpdatesSelector = "div.slider__item"
|
|
||||||
|
|
||||||
val popularMangaSelector = "div.page-item-detail.manga"
|
|
||||||
val searchMangaSelector = "div.page-item-detail.manga"
|
|
||||||
val popularMangaNextPageSelector = "a.nextpostslink"
|
|
||||||
val latestUpdatesNextPageSelector = "div[role=navigation] a.last"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Latest Updates are in a Slider, this Methods get a Manga from the slide
|
* The Latest Updates are in a Slider, this Methods get a Manga from the slide
|
||||||
|
@ -65,9 +73,9 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
fun getMangaFromLastTranslatedSlide(element: Element): SManga {
|
fun getMangaFromLastTranslatedSlide(element: Element): SManga {
|
||||||
val manga = SManga.create()
|
val manga = SManga.create()
|
||||||
manga.url =
|
manga.url =
|
||||||
getUrlWithoutDomain(element.select(latestUpdatesSelectorUrl).first().attr("abs:href"))
|
getUrlWithoutDomain(element.select(MLConstants.latestUpdatesSelectorUrl).first().attr("abs:href"))
|
||||||
manga.title = element.select(latestUpdatesSelectorTitle).text().trim()
|
manga.title = element.select(MLConstants.latestUpdatesSelectorTitle).text().trim()
|
||||||
manga.thumbnail_url = element.select(latestUpdatesSelectorThumbnailUrl).attr("abs:data-src")
|
manga.thumbnail_url = element.select(MLConstants.latestUpdatesSelectorThumbnailUrl).attr("abs:src").replace("//", "/")
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,29 +84,56 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
*/
|
*/
|
||||||
fun latestUpdatesHasNextPages() = false
|
fun latestUpdatesHasNextPages() = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search the information of a Manga with the URL-Address
|
||||||
|
*/
|
||||||
|
fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||||
|
return if (query.startsWith(MLConstants.PREFIX_MANGA_ID_SEARCH)) {
|
||||||
|
val realQuery = query.removePrefix(MLConstants.PREFIX_MANGA_ID_SEARCH)
|
||||||
|
client.newCall(GET("$baseUrl/$realQuery", headers))
|
||||||
|
.asObservableSuccess().map { response ->
|
||||||
|
val details = getMangaDetails(response.asJsoup())
|
||||||
|
details.url = "/$realQuery"
|
||||||
|
MangasPage(listOf(details), false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val request = GET(searchMangaRequest(page, query, filters).toString(), headers)
|
||||||
|
client.newCall(request)
|
||||||
|
.asObservableSuccess().map { response ->
|
||||||
|
searchMangaParse(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get eine Liste mit Mangas from Search Site
|
* Get eine Liste mit Mangas from Search Site
|
||||||
*/
|
*/
|
||||||
fun getMangasFromSearchSite(document: Document): List<SManga> {
|
private fun getMangasFromSearchSite(document: Document): List<SManga> {
|
||||||
return document.select(searchSiteMangasHTMLSelector).map { getMangaFromList(it) }
|
return document.select(MLConstants.searchSiteMangasHTMLSelector).map {
|
||||||
|
val manga = SManga.create()
|
||||||
|
manga.url = getUrlWithoutDomain(it.select(MLConstants.searchPageUrlHTMLSelector).attr("abs:href"))
|
||||||
|
manga.title = it.select(MLConstants.searchPageTitleHTMLSelector).text().trim()
|
||||||
|
manga.thumbnail_url = it.select(MLConstants.searchPageThumbnailUrlMangaHTMLSelector).attr("abs:data-src")
|
||||||
|
manga
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get eine Liste mit Mangas from Genre Site
|
* Get eine Liste mit Mangas from Genre Site
|
||||||
*/
|
*/
|
||||||
fun getMangasFromGenreSite(document: Document): List<SManga> {
|
private fun getMangasFromGenreSite(document: Document): List<SManga> {
|
||||||
return document.select(genreSiteMangasHTMLSelector).map { getMangaFromList(it) }
|
return document.select(MLConstants.genreSiteMangasHTMLSelector).map { getMangaFromList(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse The Information from Mangas From Search or Genre Site
|
* Parse The Information from Mangas From Popular or Genre Site
|
||||||
* Title, Address and thumbnail_url
|
* Title, Address and thumbnail_url
|
||||||
*/
|
*/
|
||||||
fun getMangaFromList(element: Element): SManga {
|
fun getMangaFromList(element: Element): SManga {
|
||||||
val manga = SManga.create()
|
val manga = SManga.create()
|
||||||
manga.url = getUrlWithoutDomain(element.select(urlHTMLSelector).first().attr("abs:href"))
|
manga.url = getUrlWithoutDomain(element.select(MLConstants.popularGenreUrlHTMLSelector).attr("abs:href"))
|
||||||
manga.title = element.select(titleHTMLSelector).text().trim()
|
manga.title = element.select(MLConstants.popularGenreTitleHTMLSelector).text().trim()
|
||||||
manga.thumbnail_url = element.select(thumbnailUrlMangaListHTMLSelector).attr("abs:data-src")
|
manga.thumbnail_url = element.select(MLConstants.popularGenreThumbnailUrlMangaHTMLSelector).attr("abs:data-src")
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,33 +145,61 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
fun getMangaDetails(document: Document): SManga {
|
fun getMangaDetails(document: Document): SManga {
|
||||||
val manga = SManga.create()
|
val manga = SManga.create()
|
||||||
|
|
||||||
val descriptionList = document.select(descriptionHTMLSelector).map { it.text() }
|
val titleElements = document.select("#manga-title h1")
|
||||||
val author = document.select(authorHTMLSelector).text()
|
val mangaType = getMangaBadges(titleElements)
|
||||||
val artist = document.select(artistHTMLSelector).text()
|
val descriptionList = document.select(MLConstants.mangaDetailsDescriptionHTMLSelector).map { it.text() }
|
||||||
|
val author = document.select(MLConstants.mangaDetailsAuthorHTMLSelector).text()
|
||||||
|
val artist = document.select(MLConstants.mangaDetailsArtistHTMLSelector).text()
|
||||||
|
|
||||||
val genrelist = document.select(genreHTMLSelector).map { it.text() }
|
val genrelist = document.select(MLConstants.mangaDetailsGenreHTMLSelector).map { it.text() }
|
||||||
val tagList = document.select(tagsHTMLSelector).map { it.text() }
|
val tagList = document.select(MLConstants.mangaDetailsTagsHTMLSelector).map { it.text() }
|
||||||
val genreTagList = genrelist + tagList
|
val genreTagList = genrelist + tagList
|
||||||
|
|
||||||
|
manga.title = titleElements.last().ownText().trim()
|
||||||
manga.thumbnail_url =
|
manga.thumbnail_url =
|
||||||
document.select(thumbnailUrlMangaDetailsHTMLSelector).attr("abs:data-src")
|
document.select(MLConstants.mangaDetailsThumbnailUrlHTMLSelector).attr("abs:data-src")
|
||||||
manga.description = descriptionList.joinToString("\n")
|
manga.description = descriptionList.joinToString("\n")
|
||||||
manga.author = if (author.isBlank()) "Autor Desconocido" else author
|
manga.author = if (author.isBlank()) "Autor Desconocido" else author
|
||||||
manga.artist = artist
|
manga.artist = artist
|
||||||
manga.genre = genreTagList.joinToString(", ")
|
manga.genre = genreTagList.joinToString(", ")
|
||||||
manga.status = findMangaStatus(tagList, document)
|
manga.status = findMangaStatus(tagList, document.select(MLConstants.mangaDetailsAttributes))
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findMangaStatus(tagList: List<String>, document: Document): Int {
|
/**
|
||||||
return if (tagList.contains("Fin")) {
|
* Types of the Manga
|
||||||
SManga.COMPLETED
|
* Return aList with all Types from a Manga
|
||||||
} else {
|
* for example Adults, Gay
|
||||||
when (document.select(statusHTMLSelector)?.first()?.text()?.trim()) {
|
* if the list is empty the manga is for everyone
|
||||||
"Publicandose" -> SManga.ONGOING
|
*/
|
||||||
else -> SManga.UNKNOWN
|
private fun getMangaBadges(titleBadges: Elements): List<MangaType> {
|
||||||
|
val types = mutableListOf<MangaType>()
|
||||||
|
|
||||||
|
for (badge in titleBadges.select("span")) {
|
||||||
|
if (badge.hasClass(MangaType.ADULT.getBadge()))
|
||||||
|
types.add(MangaType.ADULT)
|
||||||
|
if (badge.hasClass(MangaType.GAY.getBadge()))
|
||||||
|
types.add(MangaType.GAY)
|
||||||
|
}
|
||||||
|
return types
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findMangaStatus(tagList: List<String>, elements: Elements): Int {
|
||||||
|
if (tagList.contains("Fin")) {
|
||||||
|
return SManga.COMPLETED
|
||||||
|
}
|
||||||
|
elements.forEach { element ->
|
||||||
|
val key = element.select("div.summary-heading h5")?.text()?.trim()
|
||||||
|
val value = element.select("div.summary-content")?.text()?.trim()
|
||||||
|
|
||||||
|
if (key == "Estado") {
|
||||||
|
return when (value) {
|
||||||
|
"Publicandose" -> SManga.ONGOING
|
||||||
|
else -> SManga.UNKNOWN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return SManga.UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,9 +208,9 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
* @param response the response from the site.
|
* @param response the response from the site.
|
||||||
*/
|
*/
|
||||||
fun getChapterListParse(response: Response): List<SChapter> {
|
fun getChapterListParse(response: Response): List<SChapter> {
|
||||||
return response.asJsoup().select(chapterListParseSelector).map { element ->
|
return response.asJsoup().select(MLConstants.chapterListParseSelector).map { element ->
|
||||||
// Link to the Chapter with the info (address and chapter title)
|
// Link to the Chapter with the info (address and chapter title)
|
||||||
val chapterInfo = element.select(chapterLinkParser)
|
val chapterInfo = element.select(MLConstants.chapterLinkParser)
|
||||||
// Chaptername
|
// Chaptername
|
||||||
val chapterName = chapterInfo.text().trim()
|
val chapterName = chapterInfo.text().trim()
|
||||||
// release date came as text with format dd/mm/yyyy from a link or <i>dd/mm/yyyy</i>
|
// release date came as text with format dd/mm/yyyy from a link or <i>dd/mm/yyyy</i>
|
||||||
|
@ -171,8 +234,8 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
* Get The String with the information about the Release date of the Chapter
|
* Get The String with the information about the Release date of the Chapter
|
||||||
*/
|
*/
|
||||||
private fun getChapterReleaseDate(element: Element): String {
|
private fun getChapterReleaseDate(element: Element): String {
|
||||||
val chapterReleaseDateLink = element.select(chapterReleaseDateLinkParser).attr("title")
|
val chapterReleaseDateLink = element.select(MLConstants.chapterReleaseDateLinkParser).attr("title")
|
||||||
val chapterReleaseDateI = element.select(chapterReleaseDateIParser).text()
|
val chapterReleaseDateI = element.select(MLConstants.chapterReleaseDateIParser).text()
|
||||||
return when {
|
return when {
|
||||||
chapterReleaseDateLink.isNotEmpty() -> chapterReleaseDateLink
|
chapterReleaseDateLink.isNotEmpty() -> chapterReleaseDateLink
|
||||||
chapterReleaseDateI.isNotEmpty() -> chapterReleaseDateI
|
chapterReleaseDateI.isNotEmpty() -> chapterReleaseDateI
|
||||||
|
@ -204,7 +267,7 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
getReleaseTime(releaseDateStr, Calendar.DAY_OF_YEAR)
|
getReleaseTime(releaseDateStr, Calendar.DAY_OF_YEAR)
|
||||||
|
|
||||||
regExDate.containsMatchIn(releaseDateStr) ->
|
regExDate.containsMatchIn(releaseDateStr) ->
|
||||||
SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).parse(releaseDateStr).time
|
SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).parse(releaseDateStr)!!.time
|
||||||
|
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
@ -229,7 +292,7 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
*/
|
*/
|
||||||
fun getPageListParse(response: Response): List<Page> {
|
fun getPageListParse(response: Response): List<Page> {
|
||||||
val list =
|
val list =
|
||||||
response.asJsoup().select(pageListParseSelector).mapIndexed { index, imgElement ->
|
response.asJsoup().select(MLConstants.pageListParseSelector).mapIndexed { index, imgElement ->
|
||||||
Page(index, "", imgElement.attr("abs:data-src"))
|
Page(index, "", imgElement.attr("abs:data-src"))
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
|
@ -270,11 +333,11 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
val hasNextPages = hasNextPages(document)
|
val hasNextPages = hasNextPages(document)
|
||||||
val mangas: List<SManga>
|
val mangas: List<SManga>
|
||||||
|
|
||||||
when (searchType) {
|
mangas = when (searchType) {
|
||||||
SearchType.SEARCH_FREE ->
|
SearchType.SEARCH_FREE ->
|
||||||
mangas = getMangasFromSearchSite(document)
|
getMangasFromSearchSite(document)
|
||||||
SearchType.SEARCH_FILTER ->
|
SearchType.SEARCH_FILTER ->
|
||||||
mangas = getMangasFromGenreSite(document)
|
getMangasFromGenreSite(document)
|
||||||
}
|
}
|
||||||
|
|
||||||
return MangasPage(mangas, hasNextPages)
|
return MangasPage(mangas, hasNextPages)
|
||||||
|
@ -283,12 +346,12 @@ class ManhwaLatinoSiteParser(private val baseUrl: String) {
|
||||||
/**
|
/**
|
||||||
* Check if there ir another page to show
|
* Check if there ir another page to show
|
||||||
*/
|
*/
|
||||||
fun hasNextPages(document: Document): Boolean {
|
private fun hasNextPages(document: Document): Boolean {
|
||||||
return !document.select(searchMangaNextPageSelector).isEmpty()
|
return !document.select(MLConstants.searchMangaNextPageSelector).isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Address url without the base url.
|
* Create a Address url without the base url.
|
||||||
*/
|
*/
|
||||||
protected fun getUrlWithoutDomain(url: String) = url.substringAfter(baseUrl)
|
private fun getUrlWithoutDomain(url: String) = url.substringAfter(baseUrl)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.es.manhwalatino
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
class ManhwaLatinoUrlActivity : Activity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
val pathSegments = intent?.data?.pathSegments
|
||||||
|
|
||||||
|
if (pathSegments != null && pathSegments.size > 1) {
|
||||||
|
val type = pathSegments[0]
|
||||||
|
val mangaName = pathSegments[1]
|
||||||
|
|
||||||
|
val mainIntent = Intent().apply {
|
||||||
|
action = "eu.kanade.tachiyomi.SEARCH"
|
||||||
|
putExtra("query", "${MLConstants.PREFIX_MANGA_ID_SEARCH}$type/$mangaName")
|
||||||
|
putExtra("filter", packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
startActivity(mainIntent)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
Log.e("MLUrlActivity", e.toString())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e("TMOUrlActivity", "could not parse uri from intent $intent")
|
||||||
|
}
|
||||||
|
|
||||||
|
finish()
|
||||||
|
exitProcess(0)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue