Remove named capture groups from most extensions (#7328)

* remove named capture group (simple)

* remove named capture group (spot checks)
This commit is contained in:
Vetle Ledaal 2025-01-26 13:45:37 +01:00 committed by Draff
parent 07c6de7cf6
commit c15852943e
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
38 changed files with 71 additions and 71 deletions

View File

@ -2,7 +2,7 @@ plugins {
id("lib-multisrc") id("lib-multisrc")
} }
baseVersionCode = 5 baseVersionCode = 6
dependencies { dependencies {
api(project(":lib:synchrony")) api(project(":lib:synchrony"))

View File

@ -276,14 +276,14 @@ abstract class ColaManga(
}.also(screen::addPreference) }.also(screen::addPreference)
} }
private val keyMappingRegex = Regex("""if\s*\(\s*([a-zA-Z0-9_]+)\s*==\s*(?<keyType>\d+)\s*\)\s*\{\s*return\s*'(?<key>[a-zA-Z0-9_]+)'\s*;""") private val keyMappingRegex = Regex("""if\s*\(\s*([a-zA-Z0-9_]+)\s*==\s*(\d+)\s*\)\s*\{\s*return\s*'([a-zA-Z0-9_]+)'\s*;""")
private val keyMapping by lazy { private val keyMapping by lazy {
val obfuscatedReadJs = client.newCall(GET("$baseUrl/js/manga.read.js")).execute().body.string() val obfuscatedReadJs = client.newCall(GET("$baseUrl/js/manga.read.js")).execute().body.string()
val readJs = Deobfuscator.deobfuscateScript(obfuscatedReadJs) val readJs = Deobfuscator.deobfuscateScript(obfuscatedReadJs)
?: throw Exception(intl.couldNotDeobufscateScript) ?: throw Exception(intl.couldNotDeobufscateScript)
keyMappingRegex.findAll(readJs).associate { it.groups["keyType"]!!.value to it.groups["key"]!!.value } keyMappingRegex.findAll(readJs).associate { it.groups[1]!!.value to it.groups[2]!!.value }
} }
private fun randomString() = buildString(15) { private fun randomString() = buildString(15) {

View File

@ -2,7 +2,7 @@ plugins {
id("lib-multisrc") id("lib-multisrc")
} }
baseVersionCode = 12 baseVersionCode = 13
dependencies { dependencies {
api(project(":lib:i18n")) api(project(":lib:i18n"))

View File

@ -290,7 +290,7 @@ abstract class Keyoapp(
.firstOrNull { CDN_HOST_REGEX.containsMatchIn(it.html()) } .firstOrNull { CDN_HOST_REGEX.containsMatchIn(it.html()) }
?.let { ?.let {
val cdnHost = CDN_HOST_REGEX.find(it.html()) val cdnHost = CDN_HOST_REGEX.find(it.html())
?.groups?.get("host")?.value ?.groups?.get(1)?.value
?.replace(CDN_CLEAN_REGEX, "") ?.replace(CDN_CLEAN_REGEX, "")
"https://$cdnHost/uploads" "https://$cdnHost/uploads"
} }
@ -314,7 +314,7 @@ abstract class Keyoapp(
protected open fun Element.getImageUrl(selector: String): String? { protected open fun Element.getImageUrl(selector: String): String? {
return this.selectFirst(selector)?.let { element -> return this.selectFirst(selector)?.let { element ->
IMG_REGEX.find(element.attr("style"))?.groups?.get("url")?.value IMG_REGEX.find(element.attr("style"))?.groups?.get(1)?.value
?.toHttpUrlOrNull()?.let { ?.toHttpUrlOrNull()?.let {
it.newBuilder() it.newBuilder()
.setQueryParameter("w", "480") // Keyoapp returns the dynamic size of the thumbnail to any size .setQueryParameter("w", "480") // Keyoapp returns the dynamic size of the thumbnail to any size
@ -376,8 +376,8 @@ abstract class Keyoapp(
companion object { companion object {
private const val SHOW_PAID_CHAPTERS_PREF = "pref_show_paid_chap" private const val SHOW_PAID_CHAPTERS_PREF = "pref_show_paid_chap"
private const val SHOW_PAID_CHAPTERS_DEFAULT = false private const val SHOW_PAID_CHAPTERS_DEFAULT = false
val CDN_HOST_REGEX = """realUrl\s*=\s*`[^`]+//(?<host>[^/]+)""".toRegex() val CDN_HOST_REGEX = """realUrl\s*=\s*`[^`]+//([^/]+)""".toRegex()
val CDN_CLEAN_REGEX = """\$\{[^}]*\}""".toRegex() val CDN_CLEAN_REGEX = """\$\{[^}]*\}""".toRegex()
val IMG_REGEX = """url\(['"]?(?<url>[^(['"\)])]+)""".toRegex() val IMG_REGEX = """url\(['"]?([^(['"\)])]+)""".toRegex()
} }
} }

View File

@ -2,4 +2,4 @@ plugins {
id("lib-multisrc") id("lib-multisrc")
} }
baseVersionCode = 3 baseVersionCode = 4

View File

@ -267,7 +267,7 @@ abstract class SlimeReadTheme(
companion object { companion object {
const val PREFIX_SEARCH = "id:" const val PREFIX_SEARCH = "id:"
val FUNCTION_REGEX = """(?<script>\[""\.concat\("[^,]+,"\."\)\.concat\((?<infix>[^,]+),":\d+"\)\])""".toRegex(RegexOption.DOT_MATCHES_ALL) val FUNCTION_REGEX = """(\[""\.concat\("[^,]+,"\."\)\.concat\(([^,]+),":\d+"\)\])""".toRegex(RegexOption.DOT_MATCHES_ALL)
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT) val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT)
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Little Garden' extName = 'Little Garden'
extClass = '.LittleGarden' extClass = '.LittleGarden'
extVersionCode = 2 extVersionCode = 3
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -31,7 +31,7 @@ class LittleGarden : ParsedHttpSource() {
private const val cdnUrl = "https://littlexgarden.com/static/images/webp/" private const val cdnUrl = "https://littlexgarden.com/static/images/webp/"
private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull() private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()
private val slugRegex = Regex("\\\\\"slug\\\\\":\\\\\"(.*?(?=\\\\\"))") private val slugRegex = Regex("\\\\\"slug\\\\\":\\\\\"(.*?(?=\\\\\"))")
private val oricolPageRegex = Regex("\\{colored:(?<colored>.*?(?=,)),original:(?<original>.*?(?=,))") private val oricolPageRegex = Regex("\\{colored:(.*?(?=,)),original:(.*?(?=,))")
private val oriPageRegex = Regex("""original:"(.*?(?="))""") private val oriPageRegex = Regex("""original:"(.*?(?="))""")
} }
@ -176,10 +176,10 @@ class LittleGarden : ParsedHttpSource() {
val engChaps: IntArray = intArrayOf(970, 987, 992) val engChaps: IntArray = intArrayOf(970, 987, 992)
if (document.selectFirst("div.manga-name")!!.text().trim() == "One Piece" && (engChaps.contains(chapNb) || chapNb > 1004)) { // Permits to get French pages rather than English pages for some chapters if (document.selectFirst("div.manga-name")!!.text().trim() == "One Piece" && (engChaps.contains(chapNb) || chapNb > 1004)) { // Permits to get French pages rather than English pages for some chapters
oricolPageRegex.findAll(document.select("script:containsData(pages)").toString()).asIterable().mapIndexed { i, it -> oricolPageRegex.findAll(document.select("script:containsData(pages)").toString()).asIterable().mapIndexed { i, it ->
if (it.groups["colored"]?.value?.contains("\"") == true) { // Their JS dict has " " around the link only when available. Also uses colored pages rather than B&W as it's the main strength of this site if (it.groups[1]?.value?.contains("\"") == true) { // Their JS dict has " " around the link only when available. Also uses colored pages rather than B&W as it's the main strength of this site
pages.add(Page(i, "", cdnUrl + it.groups["colored"]?.value?.replace("\"", "") + ".webp")) pages.add(Page(i, "", cdnUrl + it.groups[1]?.value?.replace("\"", "") + ".webp"))
} else { } else {
pages.add(Page(i, "", cdnUrl + it.groups["original"]?.value?.replace("\"", "") + ".webp")) pages.add(Page(i, "", cdnUrl + it.groups[2]?.value?.replace("\"", "") + ".webp"))
} }
} }
} else { } else {

View File

@ -3,7 +3,7 @@ ext {
extClass = '.SnowmtlFactory' extClass = '.SnowmtlFactory'
themePkg = 'machinetranslations' themePkg = 'machinetranslations'
baseUrl = 'https://snowmtl.ru' baseUrl = 'https://snowmtl.ru'
overrideVersionCode = 6 overrideVersionCode = 7
isNsfw = true isNsfw = true
} }

View File

@ -97,9 +97,9 @@ class BingTranslator(private val client: OkHttpClient, private val headers: Head
val matchTwo = IG_PARAM_REGEX.find(scriptTwo)?.groups val matchTwo = IG_PARAM_REGEX.find(scriptTwo)?.groups
return TokenGroup( return TokenGroup(
token = matchOne?.get("token")?.value ?: "", token = matchOne?.get(2)?.value ?: "",
key = matchOne?.get("key")?.value ?: "", key = matchOne?.get(1)?.value ?: "",
ig = matchTwo?.get("ig")?.value ?: "", ig = matchTwo?.get(1)?.value ?: "",
iid = document.selectFirst("div[data-iid]:not([class])")?.attr("data-iid") ?: "", iid = document.selectFirst("div[data-iid]:not([class])")?.attr("data-iid") ?: "",
) )
} }
@ -109,8 +109,8 @@ class BingTranslator(private val client: OkHttpClient, private val headers: Head
} }
companion object { companion object {
val TOKENS_REGEX = """params_AbusePreventionHelper(\s+)?=(\s+)?[^\[]\[(?<key>\d+),"(?<token>[^"]+)""".toRegex() val TOKENS_REGEX = """params_AbusePreventionHelper(\s+)?=(\s+)?[^\[]\[(\d+),"([^"]+)""".toRegex()
val IG_PARAM_REGEX = """IG:"(?<ig>[^"]+)""".toRegex() val IG_PARAM_REGEX = """IG:"([^"]+)""".toRegex()
const val MAX_CHARS_ALLOW = 1000 const val MAX_CHARS_ALLOW = 1000
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Hachi' extName = 'Hachi'
extClass = '.Hachi' extClass = '.Hachi'
extVersionCode = 1 extVersionCode = 2
isNsfw = true isNsfw = true
} }

View File

@ -170,7 +170,7 @@ class Hachi : HttpSource() {
// Details // Details
override fun mangaDetailsRequest(manga: SManga): Request { override fun mangaDetailsRequest(manga: SManga): Request {
val slug = patternMangaUrl.find(manga.url)?.groups?.get("slug")?.value val slug = patternMangaUrl.find(manga.url)?.groups?.get(1)?.value
?: throw Exception("Failed to find manga from URL") ?: throw Exception("Failed to find manga from URL")
val url = "$baseUrl/_next/data/$buildId/article/$slug.json".toHttpUrl().newBuilder() val url = "$baseUrl/_next/data/$buildId/article/$slug.json".toHttpUrl().newBuilder()
@ -226,8 +226,8 @@ class Hachi : HttpSource() {
// Pages // Pages
override fun pageListRequest(chapter: SChapter): Request { override fun pageListRequest(chapter: SChapter): Request {
val matchGroups = patternMangaUrl.find(chapter.url)!!.groups val matchGroups = patternMangaUrl.find(chapter.url)!!.groups
val slug = matchGroups["slug"]!!.value val slug = matchGroups[1]!!.value
val number = matchGroups["number"]!!.value val number = matchGroups[2]!!.value
val url = "$baseUrl/_next/data/$buildId/article/$slug/chapter/$number.json".toHttpUrl() val url = "$baseUrl/_next/data/$buildId/article/$slug/chapter/$number.json".toHttpUrl()
.newBuilder() .newBuilder()
@ -289,7 +289,7 @@ class Hachi : HttpSource() {
} }
private val patternMangaUrl = private val patternMangaUrl =
"""/article/(?<slug>[^/]+)(?:/chapter/(?<number>[^/?&#]+))?""".toRegex() """/article/([^/]+)(?:/chapter/([^/?&#]+))?""".toRegex()
const val SEARCH_PREFIX = "slug:" const val SEARCH_PREFIX = "slug:"
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'I Roved Out' extName = 'I Roved Out'
extClass = '.IRovedOut' extClass = '.IRovedOut'
extVersionCode = 4 extVersionCode = 5
isNsfw = true isNsfw = true
} }

View File

@ -30,7 +30,7 @@ class IRovedOut : HttpSource() {
It updates in chunks anywhere between 3 and 30 pages long at least once a month. It updates in chunks anywhere between 3 and 30 pages long at least once a month.
""".trimIndent() """.trimIndent()
private val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US) private val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
private val titleRegex = Regex("Book (?<bookNumber>\\d+): (?<chapterTitle>.+)") private val titleRegex = Regex("Book (\\d+): (?.+)")
override fun chapterListRequest(manga: SManga): Request = throw UnsupportedOperationException() override fun chapterListRequest(manga: SManga): Request = throw UnsupportedOperationException()
@ -79,8 +79,8 @@ class IRovedOut : HttpSource() {
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> { override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
val match = titleRegex.matchEntire(chapter.name) ?: return Observable.just(listOf()) val match = titleRegex.matchEntire(chapter.name) ?: return Observable.just(listOf())
val bookNumber = match.groups["bookNumber"]!!.value.toInt() val bookNumber = match.groups[1]!!.value.toInt()
val title = match.groups["chapterTitle"]!!.value val title = match.groups[2]!!.value
val bookPage = client.newCall(GET(archiveUrl + if (bookNumber != 1) "-book-$bookNumber" else "", headers)).execute().asJsoup() val bookPage = client.newCall(GET(archiveUrl + if (bookNumber != 1) "-book-$bookNumber" else "", headers)).execute().asJsoup()
val chapterWrap = bookPage.select(".comic-archive-chapter-wrap").find { it.selectFirst(".comic-archive-chapter")!!.text() == title } val chapterWrap = bookPage.select(".comic-archive-chapter-wrap").find { it.selectFirst(".comic-archive-chapter")!!.text() == title }
val pageUrls = chapterWrap?.select(".comic-archive-list-wrap .comic-archive-title > a")?.map { it.attr("href") } ?: return Observable.just(listOf()) val pageUrls = chapterWrap?.select(".comic-archive-list-wrap .comic-archive-title > a")?.map { it.attr("href") } ?: return Observable.just(listOf())

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Rolia Scan' extName = 'Rolia Scan'
extClass = '.RoliaScan' extClass = '.RoliaScan'
extVersionCode = 1 extVersionCode = 2
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -282,7 +282,7 @@ class RoliaScan : ParsedHttpSource() {
} }
private fun getOptionList(pattern: Regex, content: String, cssQuery: String = "option"): List<Option> { private fun getOptionList(pattern: Regex, content: String, cssQuery: String = "option"): List<Option> {
val query = pattern.find(content)?.groups?.get("query")?.value ?: return emptyList() val query = pattern.find(content)?.groups?.get(1)?.value ?: return emptyList()
return content.getDocumentFragmentFilter(pattern) return content.getDocumentFragmentFilter(pattern)
?.select(cssQuery) ?.select(cssQuery)
?.map { element -> ?.map { element ->
@ -295,13 +295,13 @@ class RoliaScan : ParsedHttpSource() {
} }
private fun String.getDocumentFragmentFilter(pattern: Regex): Document? { private fun String.getDocumentFragmentFilter(pattern: Regex): Document? {
return pattern.find(this)?.groups?.get("value")?.value?.let { return pattern.find(this)?.groups?.get(2)?.value?.let {
val fragment = json.decodeFromString<String>(it) val fragment = json.decodeFromString<String>(it)
Jsoup.parseBodyFragment(fragment) Jsoup.parseBodyFragment(fragment)
} }
} }
private fun buildRegex(field: String) = """"(?<query>$field)":(?<value>"<[^,]+)""".toRegex() private fun buildRegex(field: String) = """"($field)":("<[^,]+)""".toRegex()
private data class Option(val name: String = "", val value: String = "", val query: String = "") private data class Option(val name: String = "", val value: String = "", val query: String = "")

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Webcomics' extName = 'Webcomics'
extClass = '.Webcomics' extClass = '.Webcomics'
extVersionCode = 4 extVersionCode = 5
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -164,7 +164,7 @@ class Webcomics : ParsedHttpSource(), ConfigurableSource {
?: throw Exception("You may need to log in") ?: throw Exception("You may need to log in")
return PAGE_REGEX.findAll(script.data()).mapIndexed { index, match -> return PAGE_REGEX.findAll(script.data()).mapIndexed { index, match ->
Page(index, imageUrl = match.groups["img"]!!.value.unicode()) Page(index, imageUrl = match.groups[1]!!.value.unicode())
}.toList() }.toList()
} }
@ -227,7 +227,7 @@ class Webcomics : ParsedHttpSource(), ConfigurableSource {
} }
companion object { companion object {
val PAGE_REGEX = """src:(\s+)?"(?<img>[^"]+)""".toRegex() val PAGE_REGEX = """src:(\s+)?"([^"]+)""".toRegex()
val WHITE_SPACE_REGEX = """[\s]+""".toRegex() val WHITE_SPACE_REGEX = """[\s]+""".toRegex()
val PUNCTUATION_REGEX = "[\\p{Punct}]".toRegex() val PUNCTUATION_REGEX = "[\\p{Punct}]".toRegex()
val UNICODE_REGEX = "\\\\u([0-9A-Fa-f]{4})|\\\\U([0-9A-Fa-f]{8})".toRegex() val UNICODE_REGEX = "\\\\u([0-9A-Fa-f]{4})|\\\\U([0-9A-Fa-f]{8})".toRegex()

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Plot Twist No Fansub' extName = 'Plot Twist No Fansub'
extClass = '.PlotTwistNoFansub' extClass = '.PlotTwistNoFansub'
extVersionCode = 7 extVersionCode = 8
isNsfw = true isNsfw = true
} }

View File

@ -191,7 +191,7 @@ class PlotTwistNoFansub : ParsedHttpSource(), ConfigurableSource {
val script = document.select("script") val script = document.select("script")
.map(Element::data) .map(Element::data)
.firstNotNullOf(CHAPTER_PAGES_REGEX::find) .firstNotNullOf(CHAPTER_PAGES_REGEX::find)
val result = json.decodeFromString<PagesPayloadDto>(script.groups["json"]!!.value) val result = json.decodeFromString<PagesPayloadDto>(script.groups[1]!!.value)
val mangaSlug = "${result.cdnUrl}/${result.mangaSlug}" val mangaSlug = "${result.cdnUrl}/${result.mangaSlug}"
val chapterNumber = result.chapterNumber val chapterNumber = result.chapterNumber
return result.images.mapIndexed { i, img -> return result.images.mapIndexed { i, img ->
@ -260,7 +260,7 @@ class PlotTwistNoFansub : ParsedHttpSource(), ConfigurableSource {
companion object { companion object {
private val MANGAID1_REGEX = ""","manid":"(\d+)",""".toRegex() private val MANGAID1_REGEX = ""","manid":"(\d+)",""".toRegex()
private val UNESCAPE_REGEX = """\\(.)""".toRegex() private val UNESCAPE_REGEX = """\\(.)""".toRegex()
private val CHAPTER_PAGES_REGEX = """obj\s*=\s*(?<json>.*)\s*;""".toRegex() private val CHAPTER_PAGES_REGEX = """obj\s*=\s*(.*)\s*;""".toRegex()
private val ACTION_REGEX = """action:\s*?(['"])([^\r\n]+?)\1""".toRegex() private val ACTION_REGEX = """action:\s*?(['"])([^\r\n]+?)\1""".toRegex()
private const val MAX_MANGA_RESULTS = 1000 private const val MAX_MANGA_RESULTS = 1000
} }

View File

@ -3,7 +3,7 @@ ext {
extClass = '.FRScan' extClass = '.FRScan'
themePkg = 'madara' themePkg = 'madara'
baseUrl = 'https://fr-scan.com' baseUrl = 'https://fr-scan.com'
overrideVersionCode = 6 overrideVersionCode = 7
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -24,7 +24,7 @@ class FRScan : Madara("FR-Scan", "https://fr-scan.com", "fr", dateFormat = Simpl
val chapterPreloaded = document.selectFirst("#chapter_preloaded_images") val chapterPreloaded = document.selectFirst("#chapter_preloaded_images")
?: return super.pageListParse(document) ?: return super.pageListParse(document)
val content = CHAPTER_PAGES_REGEX.find(chapterPreloaded.data())?.groups?.get("pages")!!.value val content = CHAPTER_PAGES_REGEX.find(chapterPreloaded.data())?.groups?.get(1)!!.value
val pages = json.decodeFromString<List<String>>(content) val pages = json.decodeFromString<List<String>>(content)
return pages.mapIndexed { index, imageUrl -> return pages.mapIndexed { index, imageUrl ->
@ -33,6 +33,6 @@ class FRScan : Madara("FR-Scan", "https://fr-scan.com", "fr", dateFormat = Simpl
} }
companion object { companion object {
val CHAPTER_PAGES_REGEX = """=\s+(?<pages>\[.+\])""".toRegex() val CHAPTER_PAGES_REGEX = """=\s+(\[.+\])""".toRegex()
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Read Mangas' extName = 'Read Mangas'
extClass = '.ReadMangas' extClass = '.ReadMangas'
extVersionCode = 36 extVersionCode = 37
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -253,7 +253,7 @@ class ReadMangas() : HttpSource() {
val document = response.asJsoup() val document = response.asJsoup()
val scripts = document.select("script").joinToString("\n") { it.data() } val scripts = document.select("script").joinToString("\n") { it.data() }
val pages = IMAGE_URL_REGEX.findAll(scripts).mapIndexed { index, match -> val pages = IMAGE_URL_REGEX.findAll(scripts).mapIndexed { index, match ->
Page(index, imageUrl = match.groups["imageUrl"]!!.value) Page(index, imageUrl = match.groups[1]!!.value)
}.toList() }.toList()
return pages return pages
@ -294,7 +294,7 @@ class ReadMangas() : HttpSource() {
@SuppressLint("SimpleDateFormat") @SuppressLint("SimpleDateFormat")
companion object { companion object {
val IMAGE_URL_REGEX = """url\\":\\"(?<imageUrl>[^(\\")]+)""".toRegex() val IMAGE_URL_REGEX = """url\\":\\"([^(\\")]+)""".toRegex()
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Taiyō' extName = 'Taiyō'
extClass = '.Taiyo' extClass = '.Taiyo'
extVersionCode = 4 extVersionCode = 5
isNsfw = true isNsfw = true
} }

View File

@ -214,7 +214,7 @@ class Taiyo : ParsedHttpSource() {
.build() .build()
val chapters = client.newCall(GET(pageUrl, headers)).execute().let { val chapters = client.newCall(GET(pageUrl, headers)).execute().let {
CHAPTER_REGEX.find(it.body.string())?.groups?.get("chapters")?.value CHAPTER_REGEX.find(it.body.string())?.groups?.get(1)?.value
} }
val parsed = json.decodeFromString<ChapterListDto>(chapters!!) val parsed = json.decodeFromString<ChapterListDto>(chapters!!)
@ -320,7 +320,7 @@ class Taiyo : ParsedHttpSource() {
val script = getScriptContainingToken(scripts) val script = getScriptContainingToken(scripts)
?: throw Exception("Não foi possivel localizar o token") ?: throw Exception("Não foi possivel localizar o token")
return TOKEN_REGEX.find(script)?.groups?.get("token")?.value return TOKEN_REGEX.find(script)?.groups?.get(1)?.value
?: throw Exception("Não foi possivel extrair o token") ?: throw Exception("Não foi possivel extrair o token")
} }
@ -339,8 +339,8 @@ class Taiyo : ParsedHttpSource() {
companion object { companion object {
const val PREFIX_SEARCH = "id:" const val PREFIX_SEARCH = "id:"
val CHAPTER_REGEX = """(?<chapters>\{"chapters".+"totalPages":\d+\})""".toRegex() val CHAPTER_REGEX = """(\{"chapters".+"totalPages":\d+\})""".toRegex()
val TOKEN_REGEX = """NEXT_PUBLIC_MEILISEARCH_PUBLIC_KEY:(\s+)?"(?<token>[^"]+)""".toRegex() val TOKEN_REGEX = """NEXT_PUBLIC_MEILISEARCH_PUBLIC_KEY:(\s+)?"([^"]+)""".toRegex()
const val BEARER_TOKEN_PREF = "TAIYO_BEARER_TOKEN" const val BEARER_TOKEN_PREF = "TAIYO_BEARER_TOKEN"
private const val IMG_CDN = "https://cdn.taiyo.moe/medias" private const val IMG_CDN = "https://cdn.taiyo.moe/medias"

View File

@ -3,7 +3,7 @@ ext {
extClass = '.TraducoesDoLipe' extClass = '.TraducoesDoLipe'
themePkg = 'zeistmanga' themePkg = 'zeistmanga'
baseUrl = 'https://traducoesdolipe.blogspot.com' baseUrl = 'https://traducoesdolipe.blogspot.com'
overrideVersionCode = 0 overrideVersionCode = 1
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -40,7 +40,7 @@ class TraducoesDoLipe : ZeistManga(
override fun getChapterFeedUrl(doc: Document): String { override fun getChapterFeedUrl(doc: Document): String {
val feed = doc.select("script").map(Element::html) val feed = doc.select("script").map(Element::html)
.firstOrNull { script -> script.contains("catNameProject") } .firstOrNull { script -> script.contains("catNameProject") }
?.let { script -> PROJECT_NAME_REGEX.find(script)?.groups?.get("project")?.value } ?.let { script -> PROJECT_NAME_REGEX.find(script)?.groups?.get(1)?.value }
?: throw Exception("Não foi possivel encontrar o nome do projeto") ?: throw Exception("Não foi possivel encontrar o nome do projeto")
return apiUrl(chapterCategory) return apiUrl(chapterCategory)
@ -52,7 +52,7 @@ class TraducoesDoLipe : ZeistManga(
override fun pageListParse(response: Response): List<Page> { override fun pageListParse(response: Response): List<Page> {
val document = response.asJsoup() val document = response.asJsoup()
val pages = document.selectFirst(".chapter script")!!.html().let { val pages = document.selectFirst(".chapter script")!!.html().let {
val list = PAGES_REGEX.find(it)?.groups?.get("pages")?.value val list = PAGES_REGEX.find(it)?.groups?.get(1)?.value
json.decodeFromString<List<String>>(list!!) json.decodeFromString<List<String>>(list!!)
} }
@ -62,7 +62,7 @@ class TraducoesDoLipe : ZeistManga(
} }
companion object { companion object {
val PROJECT_NAME_REGEX = """=\s+?\('(?<project>[^']+)""".toRegex() val PROJECT_NAME_REGEX = """=\s+?\('([^']+)""".toRegex()
val PAGES_REGEX = """=(?<pages>\[[^]]+])""".toRegex() val PAGES_REGEX = """=(\[[^]]+])""".toRegex()
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Tsuki Mangás' extName = 'Tsuki Mangás'
extClass = '.TsukiMangas' extClass = '.TsukiMangas'
extVersionCode = 6 extVersionCode = 7
isNsfw = true isNsfw = true
} }

View File

@ -316,7 +316,7 @@ class TsukiMangas : HttpSource() {
} }
} }
private val apiHeadersRegex = Regex("""headers\.common(?:\.(?<key>[0-9A-Za-z_]+)|\[['"](?<key2>[0-9A-Za-z-_]+)['"]])\s*=\s*['"](?<value>[a-zA-Z0-9_ :;.,\\/?!(){}\[\]@<>=\-+*#$&`|~^%]+)['"]""") private val apiHeadersRegex = Regex("""headers\.common(?:\.([0-9A-Za-z_]+)|\[['"]([0-9A-Za-z-_]+)['"]])\s*=\s*['"]([a-zA-Z0-9_ :;.,\\/?!(){}\[\]@<>=\-+*#$&`|~^%]+)['"]""")
private val apiHeaders by lazy { private val apiHeaders by lazy {
val document = client.newCall(GET(baseUrl, headers)).execute().asJsoup() val document = client.newCall(GET(baseUrl, headers)).execute().asJsoup()
@ -325,7 +325,7 @@ class TsukiMangas : HttpSource() {
val matches = apiHeadersRegex.findAll(script) val matches = apiHeadersRegex.findAll(script)
matches.associate { matches.associate {
(it.groups["key"] ?: it.groups["key2"]!!).value to it.groups["value"]!!.value (it.groups[1] ?: it.groups[2]!!).value to it.groups[3]!!.value
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Hattori Manga' extName = 'Hattori Manga'
extClass = '.HattoriManga' extClass = '.HattoriManga'
extVersionCode = 39 extVersionCode = 40
isNsfw = true isNsfw = true
} }

View File

@ -254,7 +254,7 @@ class HattoriManga : HttpSource() {
thumbnail_url = element.selectFirst(".img-con")?.absUrl("data-setbg") thumbnail_url = element.selectFirst(".img-con")?.absUrl("data-setbg")
genre = element.select(".product-card-con ul li").joinToString { it.text() } genre = element.select(".product-card-con ul li").joinToString { it.text() }
val script = element.attr("onclick") val script = element.attr("onclick")
setUrlWithoutDomain(REGEX_MANGA_URL.find(script)!!.groups["url"]!!.value) setUrlWithoutDomain(REGEX_MANGA_URL.find(script)!!.groups[1]!!.value)
} }
private fun parseGenres(document: Document): List<Genre> { private fun parseGenres(document: Document): List<Genre> {
@ -279,7 +279,7 @@ class HattoriManga : HttpSource() {
companion object { companion object {
const val SEARCH_PREFIX = "slug:" const val SEARCH_PREFIX = "slug:"
val REGEX_MANGA_URL = """='(?<url>[^']+)""".toRegex() val REGEX_MANGA_URL = """='([^']+)""".toRegex()
val dateFormat = SimpleDateFormat("dd.MM.yyyy", Locale.US) val dateFormat = SimpleDateFormat("dd.MM.yyyy", Locale.US)
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Uzay Manga' extName = 'Uzay Manga'
extClass = '.UzayManga' extClass = '.UzayManga'
extVersionCode = 37 extVersionCode = 38
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -138,7 +138,7 @@ class UzayManga : ParsedHttpSource() {
?: return emptyList() ?: return emptyList()
return pageRegex.findAll(script).mapIndexed { index, result -> return pageRegex.findAll(script).mapIndexed { index, result ->
val url = result.groups.get("path")!!.value val url = result.groups.get(1)!!.value
Page(index, document.location(), "$CDN_URL/upload/series/$url") Page(index, document.location(), "$CDN_URL/upload/series/$url")
}.toList() }.toList()
} }
@ -158,7 +158,7 @@ class UzayManga : ParsedHttpSource() {
const val CDN_URL = "https://cdn1.uzaymanga.com" const val CDN_URL = "https://cdn1.uzaymanga.com"
const val URL_SEARCH_PREFIX = "slug:" const val URL_SEARCH_PREFIX = "slug:"
val dateFormat = SimpleDateFormat("MMM d ,yyyy", Locale("tr")) val dateFormat = SimpleDateFormat("MMM d ,yyyy", Locale("tr"))
val pageRegex = """\\"path\\":\\"(?<path>[^"]+)\\""".trimIndent().toRegex() val pageRegex = """\\"path\\":\\"([^"]+)\\""".trimIndent().toRegex()
} }
} }

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'LXHentai' extName = 'LXHentai'
extClass = '.LxHentai' extClass = '.LxHentai'
extVersionCode = 13 extVersionCode = 14
isNsfw = true isNsfw = true
} }

View File

@ -137,7 +137,7 @@ class LxHentai : ParsedHttpSource(), ConfigurableSource {
}.trim() }.trim()
thumbnail_url = document.selectFirst(".cover")?.attr("style")?.let { thumbnail_url = document.selectFirst(".cover")?.attr("style")?.let {
IMAGE_REGEX.find(it)?.groups?.get("img")?.value IMAGE_REGEX.find(it)?.groups?.get(1)?.value
} }
val statusString = document.select("div.grow div.mt-2:contains(Tình trạng) a").first()!!.text() val statusString = document.select("div.grow div.mt-2:contains(Tình trạng) a").first()!!.text()
@ -323,7 +323,7 @@ class LxHentai : ParsedHttpSource(), ConfigurableSource {
const val PREFIX_ID_SEARCH = "id:" const val PREFIX_ID_SEARCH = "id:"
val CHAPTER_NUMBER_REGEX = Regex("""[+\-]?([0-9]*[.])?[0-9]+""", RegexOption.IGNORE_CASE) val CHAPTER_NUMBER_REGEX = Regex("""[+\-]?([0-9]*[.])?[0-9]+""", RegexOption.IGNORE_CASE)
val IMAGE_REGEX = """url\('(?<img>[^']+)""".toRegex() val IMAGE_REGEX = """url\('([^']+)""".toRegex()
private const val DEFAULT_BASE_URL_PREF = "defaultBaseUrl" private const val DEFAULT_BASE_URL_PREF = "defaultBaseUrl"
private const val RESTART_APP = "Khởi chạy lại ứng dụng để áp dụng thay đổi." private const val RESTART_APP = "Khởi chạy lại ứng dụng để áp dụng thay đổi."

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'Roumanwu' extName = 'Roumanwu'
extClass = '.Roumanwu' extClass = '.Roumanwu'
extVersionCode = 14 extVersionCode = 15
isNsfw = true isNsfw = true
} }

View File

@ -34,7 +34,7 @@ class Roumanwu : ParsedHttpSource(), ConfigurableSource {
override val client = network.cloudflareClient.newBuilder().addInterceptor(ScrambledImageInterceptor).build() override val client = network.cloudflareClient.newBuilder().addInterceptor(ScrambledImageInterceptor).build()
private val imageUrlRegex = """\\"imageUrl\\":\\"(?<imageUrl>[^\\]+)""".toRegex() private val imageUrlRegex = """\\"imageUrl\\":\\"([^\\]+)""".toRegex()
override fun popularMangaRequest(page: Int) = GET("$baseUrl/home", headers) override fun popularMangaRequest(page: Int) = GET("$baseUrl/home", headers)
override fun popularMangaNextPageSelector(): String? = null override fun popularMangaNextPageSelector(): String? = null
@ -110,7 +110,7 @@ class Roumanwu : ParsedHttpSource(), ConfigurableSource {
val images = document.selectFirst("script:containsData(imageUrl)")?.data() val images = document.selectFirst("script:containsData(imageUrl)")?.data()
?.let { content -> ?.let { content ->
imageUrlRegex imageUrlRegex
.findAll(content).map { it.groups["imageUrl"]?.value } .findAll(content).map { it.groups[1]?.value }
.toList() .toList()
} ?: return emptyList() } ?: return emptyList()