Compare commits

...

8 Commits

Author SHA1 Message Date
Zakaria aourzag 504342706e Multporn: fix popular listing (#154)
CI / Prepare job (push) Successful in 18s Details
CI / Build multisrc modules (push) Successful in 6m8s Details
CI / Build individual modules (push) Successful in 1m9s Details
CI / Publish repo (push) Successful in 2m50s Details
Co-authored-by: stevenyomi <95685115+stevenyomi@users.noreply.github.com>
2024-01-12 03:35:06 +00:00
Vetle Ledaal 3523acfe90 Fix popular selector for Mundo Hentai (#155) 2024-01-12 03:35:04 +00:00
Vetle Ledaal 2ce5e88163 Update domain for TonizuToon (#152) 2024-01-12 03:35:01 +00:00
Vetle Ledaal 283c117b49 Update domain for Gekkou Scans (#150) 2024-01-12 03:34:59 +00:00
bapeey c72814cc9a Fix XOXO Comics (#148) 2024-01-12 03:34:49 +00:00
stevenyomi 34c46abf9d Roumanwu: update URL (#146) 2024-01-12 03:34:42 +00:00
stevenyomi defa788dd5 DMZJ: fix comment page (Brotli issue) (#145) 2024-01-12 03:34:39 +00:00
kooper100 abc5afb00f Updated parsing of manga title from URL. (#59) 2024-01-12 03:34:30 +00:00
17 changed files with 63 additions and 53 deletions

View File

@ -3,12 +3,15 @@ package eu.kanade.tachiyomi.extension.pt.gekkouscan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class GekkouScans : Madara(
"Gekkou Scans",
"https://gekkouscans.top",
"https://gekkou.site",
"pt-BR",
dateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("pt", "BR")),
) {
// Theme changed from MMRCMS to Madara, again.
@ -22,4 +25,10 @@ class GekkouScans : Madara(
.build()
override val useNewChapterEndpoint: Boolean = true
override val mangaDetailsSelectorTitle = "#manga-title"
override val mangaDetailsSelectorStatus = ".summary-heading:contains(Status) ~ .summary-content"
override fun searchPage(page: Int): String = if (page == 1) "" else "page/$page/"
}

View File

@ -6,7 +6,17 @@ import java.util.Locale
class TonizuToon : Madara(
"TonizuToon",
"https://tonizutoon.com",
"https://tonizu.com",
"tr",
SimpleDateFormat("MMMMM d, yyyy", Locale("tr")),
)
dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ROOT),
) {
override val useNewChapterEndpoint = true
override val mangaDetailsSelectorTitle = "#manga-title"
override val mangaDetailsSelectorAuthor = ".summary-heading:contains(Yazar) ~ .summary-content"
override val mangaDetailsSelectorStatus = ".summary-heading:contains(Durumu) ~ .summary-content"
override fun searchPage(page: Int): String = if (page == 1) "" else "page/$page/"
}

View File

@ -14,7 +14,8 @@ import java.text.SimpleDateFormat
import java.util.Locale
class XoxoComics : WPComics("XOXO Comics", "https://xoxocomic.com", "en", SimpleDateFormat("MM/dd/yyyy", Locale.US), null) {
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/comic-updates?page=$page", headers)
override val popularPath = "hot-comic"
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/comic-update?page=$page", headers)
override fun latestUpdatesSelector() = "li.row"
override fun latestUpdatesFromElement(element: Element): SManga {
return SManga.create().apply {
@ -26,7 +27,7 @@ class XoxoComics : WPComics("XOXO Comics", "https://xoxocomic.com", "en", Simple
}
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
return GET("$baseUrl/search?keyword=$query&page=$page", headers)
return GET("$baseUrl/search-comic?keyword=$query&page=$page", headers)
}
override fun chapterListParse(response: Response): List<SChapter> {

View File

@ -467,24 +467,27 @@ abstract class Madara(
"مكتملة",
"مكتمل",
"已完结",
"Tamamlandı",
)
protected val ongoingStatusList: Array<String> = arrayOf(
"OnGoing", "Продолжается", "Updating", "Em Lançamento", "Em lançamento", "Em andamento",
"Em Andamento", "En cours", "En Cours", "En cours de publication", "Ativo", "Lançando", "Đang Tiến Hành", "Devam Ediyor",
"Devam ediyor", "In Corso", "In Arrivo", "مستمرة", "مستمر", "En Curso", "En curso", "Emision",
"Curso", "En marcha", "Publicandose", "En emision", "连载中", "Em Lançamento",
"Curso", "En marcha", "Publicandose", "En emision", "连载中", "Em Lançamento", "Devam Ediyo",
)
protected val hiatusStatusList: Array<String> = arrayOf(
"On Hold",
"Pausado",
"En espera",
"Durduruldu",
)
protected val canceledStatusList: Array<String> = arrayOf(
"Canceled",
"Cancelado",
"İptal Edildi",
)
override fun mangaDetailsParse(document: Document): SManga {

View File

@ -112,7 +112,7 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("FreeWebtoonCoins", "https://freewebtooncoins.com", "en", overrideVersionCode = 1),
SingleLang("GalaxyDegenScans", "https://gdscans.com", "en", overrideVersionCode = 4),
SingleLang("Gatemanga", "https://gatemanga.com", "ar", overrideVersionCode = 1),
SingleLang("Gekkou Scans", "https://gekkouscans.top", "pt-BR", isNsfw = true, pkgName = "gekkouscan", overrideVersionCode = 1),
SingleLang("Gekkou Scans", "https://gekkou.site", "pt-BR", isNsfw = true, pkgName = "gekkouscan", overrideVersionCode = 2),
SingleLang("Ghost Scan", "https://ghostscan.com.br", "pt-BR", isNsfw = true),
SingleLang("Girls Love Manga!", "https://glmanga.com", "en", isNsfw = true, className = "GirlsLoveManga"),
SingleLang("Glory Manga", "https://glorymanga.com", "tr"),
@ -456,7 +456,7 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("The Guild", "https://theguildscans.com", "en"),
SingleLang("Time Naight", "https://timenaight.com", "tr"),
SingleLang("Todaymic", "https://todaymic.com", "en", overrideVersionCode = 1),
SingleLang("TonizuToon", "https://tonizutoon.com", "tr", isNsfw = true),
SingleLang("TonizuToon", "https://tonizu.com", "tr", isNsfw = true, overrideVersionCode = 1),
SingleLang("ToonChill", "https://toonchill.com", "en", overrideVersionCode = 1),
SingleLang("ToonGod", "https://www.toongod.org", "en", isNsfw = true, overrideVersionCode = 5),
SingleLang("Toonily.net", "https://toonily.net", "en", isNsfw = true, className = "Toonilynet", overrideVersionCode = 2),

View File

@ -128,7 +128,7 @@ abstract class WPComics(
open fun String?.toStatus(): Int {
val ongoingWords = listOf("Ongoing", "Updating", "Đang tiến hành")
val completedWords = listOf("Complete", "Hoàn thành")
val completedWords = listOf("Complete", "Completed", "Hoàn thành")
return when {
this == null -> SManga.UNKNOWN
ongoingWords.doesInclude(this) -> SManga.ONGOING

View File

@ -9,7 +9,7 @@ class WPComicsGenerator : ThemeSourceGenerator {
override val themeClass = "WPComics"
override val baseVersionCode: Int = 2
override val baseVersionCode: Int = 3
override val sources = listOf(
SingleLang("NetTruyen", "https://www.nettruyenclub.com", "vi", overrideVersionCode = 21),

View File

@ -6,7 +6,7 @@ ext {
extName = 'Madokami'
pkgNameSuffix = 'en.madokami'
extClass = '.Madokami'
extVersionCode = 7
extVersionCode = 8
}
apply from: "$rootDir/common.gradle"

View File

@ -67,7 +67,10 @@ class Madokami : ConfigurableSource, ParsedHttpSource() {
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
manga.url = element.attr("href")
manga.title = URLDecoder.decode(element.attr("href").split("/").last(), "UTF-8").trimStart('!')
val pathSegments = element.attr("href").split("/")
var i = pathSegments.size
manga.description = URLDecoder.decode(pathSegments[i - 1], "UTF-8")
do { i--; manga.title = URLDecoder.decode(pathSegments[i], "UTF-8") } while (URLDecoder.decode(pathSegments[i], "UTF-8").startsWith("!"))
return manga
}
@ -109,8 +112,7 @@ class Madokami : ConfigurableSource, ParsedHttpSource() {
override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create()
manga.author = document.select("a[itemprop=\"author\"]").joinToString(", ") { it.text() }
manga.description = "Tags: " + document.select("div.genres[itemprop=\"keywords\"] a.tag.tag-category").joinToString(", ") { it.text() }
manga.genre = document.select("div.genres a.tag[itemprop=\"genre\"]").joinToString(", ") { it.text() }
manga.genre = document.select("div.genres a.tag").joinToString(", ") { it.text() }
manga.status = if (document.select("span.scanstatus").text() == "Yes") SManga.COMPLETED else SManga.UNKNOWN
manga.thumbnail_url = document.select("div.manga-info img[itemprop=\"image\"]").attr("src")
return manga

View File

@ -6,7 +6,7 @@ ext {
extName = 'Multporn'
pkgNameSuffix = 'en.multporn'
extClass = '.Multporn'
extVersionCode = 3
extVersionCode = 4
isNsfw = true
}

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.extension.en.multporn
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservable
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.Filter
@ -12,18 +11,11 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
@ -47,36 +39,22 @@ class Multporn : ParsedHttpSource() {
// Popular
private fun buildPopularMangaRequest(page: Int, filters: FilterList = FilterList()): Request {
val body = FormBody.Builder()
.addEncoded("page", page.toString())
.addEncoded("view_name", "top")
.addEncoded("view_display_id", "page")
val url = "$baseUrl/best".toHttpUrl().newBuilder()
.addQueryParameter("page", page.toString())
(if (filters.isEmpty()) getFilterList(POPULAR_DEFAULT_SORT_BY_FILTER_STATE) else filters).forEach {
when (it) {
is SortBySelectFilter -> body.addEncoded("sort_by", it.selected.uri)
is SortOrderSelectFilter -> body.addEncoded("sort_order", it.selected.uri)
is PopularTypeSelectFilter -> body.addEncoded("type", it.selected.uri)
is SortBySelectFilter -> url.addQueryParameter("sort_by", it.selected.uri)
is SortOrderSelectFilter -> url.addQueryParameter("sort_order", it.selected.uri)
is PopularTypeSelectFilter -> url.addQueryParameter("type", it.selected.uri)
else -> { }
}
}
return POST("$baseUrl/views/ajax", headers, body.build())
return GET(url.build(), headers)
}
override fun popularMangaRequest(page: Int) = buildPopularMangaRequest(page - 1)
override fun popularMangaParse(response: Response): MangasPage {
val html = json.decodeFromString<JsonArray>(response.body.string())
.last { it.jsonObject["command"]!!.jsonPrimitive.content == "insert" }.jsonObject["data"]!!.jsonPrimitive.content
return super.popularMangaParse(
response.newBuilder()
.body(html.toResponseBody("text/html; charset=UTF-8".toMediaTypeOrNull()))
.build(),
)
}
override fun popularMangaSelector() = ".masonry-item"
override fun popularMangaNextPageSelector() = ".pager-next a"
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
@ -88,7 +66,7 @@ class Multporn : ParsedHttpSource() {
// Latest
private fun buildLatestMangaRequest(page: Int, filters: FilterList = FilterList()): Request {
val url = "$baseUrl/new".toHttpUrlOrNull()!!.newBuilder()
val url = "$baseUrl/new".toHttpUrl().newBuilder()
.addQueryParameter("page", page.toString())
(if (filters.isEmpty()) getFilterList(LATEST_DEFAULT_SORT_BY_FILTER_STATE) else filters).forEach {
@ -126,7 +104,7 @@ class Multporn : ParsedHttpSource() {
}
private fun buildSearchMangaRequest(page: Int, query: String, filtersArg: FilterList = FilterList()): Request {
val url = "$baseUrl/search".toHttpUrlOrNull()!!.newBuilder()
val url = "$baseUrl/search".toHttpUrl().newBuilder()
.addQueryParameter("page", page.toString())
.addQueryParameter("views_fulltext", query)

View File

@ -5,7 +5,7 @@ ext {
extName = 'Mundo Hentai'
pkgNameSuffix = 'pt.mundohentai'
extClass = '.MundoHentai'
extVersionCode = 7
extVersionCode = 8
isNsfw = true
}

View File

@ -56,7 +56,7 @@ class MundoHentai : ParsedHttpSource() {
return GET("$baseUrl/category/doujinshi/$pageStr", newHeaders)
}
override fun popularMangaSelector(): String = "div.lista > ul > li div.thumb-conteudo:has(a[href^=$baseUrl]:has(span.thumb-imagem)):not(:contains(Tufos))"
override fun popularMangaSelector(): String = "div.lista > ul > li div.thumb-conteudo:has(a[href^=$baseUrl]):not(:contains(Tufos))"
override fun popularMangaFromElement(element: Element): SManga = genericMangaFromElement(element)

View File

@ -6,7 +6,7 @@ ext {
extName = 'DMZJ'
pkgNameSuffix = 'zh.dmzj'
extClass = '.Dmzj'
extVersionCode = 41
extVersionCode = 42
}
apply from: "$rootDir/common.gradle"

View File

@ -27,7 +27,7 @@ class Dmzj : ConfigurableSource, HttpSource() {
override val lang = "zh"
override val supportsLatest = true
override val name = "动漫之家"
override val baseUrl = "https://m.dmzj.com"
override val baseUrl = "https://m.idmzj.com"
private val preferences: SharedPreferences =
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
@ -36,6 +36,13 @@ class Dmzj : ConfigurableSource, HttpSource() {
.addInterceptor(ImageUrlInterceptor)
.addInterceptor(CommentsInterceptor)
.rateLimit(4)
.apply {
val interceptors = interceptors()
val index = interceptors.indexOfFirst { "Brotli" in it.javaClass.simpleName }
if (index >= 0) {
interceptors.add(interceptors.removeAt(index))
}
}
.build()
// API v4 randomly fails

View File

@ -6,7 +6,7 @@ ext {
extName = 'Roumanwu'
pkgNameSuffix = 'zh.roumanwu'
extClass = '.Roumanwu'
extVersionCode = 6
extVersionCode = 7
isNsfw = true
}

View File

@ -116,7 +116,7 @@ class Roumanwu : HttpSource(), ConfigurableSource {
private const val MIRROR_PREF_SUMMARY = "使用镜像网址。重启软件生效。"
// 地址: https://rou.pub/dizhi
private val MIRRORS = arrayOf("https://rouman5.com", "https://roum2.xyz")
private val MIRRORS = arrayOf("https://rouman5.com", "https://roum10.xyz")
private val MIRRORS_DESC = arrayOf("主站", "镜像")
private const val MIRROR_DEFAULT = 1.toString() // use mirror