From 68b70d54d95c41acb09023690f802ace6088868d Mon Sep 17 00:00:00 2001 From: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> Date: Sat, 1 Nov 2025 12:57:15 +0500 Subject: [PATCH] add MangaBall (#11344) * MangaBall * remove * suggested changes and more * remove this * MangaBall: Fix Korean language code * change to Locale.ROOT as the pattern isn't language specific * only throw if filtered --- src/all/mangaball/AndroidManifest.xml | 21 + src/all/mangaball/build.gradle | 8 + .../mangaball/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 5325 bytes .../mangaball/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2735 bytes .../res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 8189 bytes .../res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 15992 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 23583 bytes .../tachiyomi/extension/all/mangaball/Dto.kt | 71 +++ .../extension/all/mangaball/Filters.kt | 201 +++++++++ .../extension/all/mangaball/MangaBall.kt | 403 ++++++++++++++++++ .../all/mangaball/MangaBallFactory.kt | 50 +++ .../extension/all/mangaball/UrlActivity.kt | 29 ++ 12 files changed, 783 insertions(+) create mode 100644 src/all/mangaball/AndroidManifest.xml create mode 100644 src/all/mangaball/build.gradle create mode 100644 src/all/mangaball/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/all/mangaball/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/all/mangaball/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/all/mangaball/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/all/mangaball/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/Dto.kt create mode 100644 src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/Filters.kt create mode 100644 src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBall.kt create mode 100644 src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBallFactory.kt create mode 100644 src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/UrlActivity.kt diff --git a/src/all/mangaball/AndroidManifest.xml b/src/all/mangaball/AndroidManifest.xml new file mode 100644 index 000000000..5eff26df2 --- /dev/null +++ b/src/all/mangaball/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/src/all/mangaball/build.gradle b/src/all/mangaball/build.gradle new file mode 100644 index 000000000..1469f3c38 --- /dev/null +++ b/src/all/mangaball/build.gradle @@ -0,0 +1,8 @@ +ext { + extName = 'Manga Ball' + extClass = '.MangaBallFactory' + extVersionCode = 1 + isNsfw = true +} + +apply from: "$rootDir/common.gradle" diff --git a/src/all/mangaball/res/mipmap-hdpi/ic_launcher.png b/src/all/mangaball/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..03854c11d94c659322b075dcbf9e685410cf3fe0 GIT binary patch literal 5325 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 literal 0 HcmV?d00001 diff --git a/src/all/mangaball/res/mipmap-mdpi/ic_launcher.png b/src/all/mangaball/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c1562e10bd2cf510f4c0d87f596dd2c33a6f9bb6 GIT binary patch literal 2735 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 pj%Q_a}Jqs;X+N4rZ$6xmr}InrE-5Qd8Ab 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 literal 0 HcmV?d00001 diff --git a/src/all/mangaball/res/mipmap-xxhdpi/ic_launcher.png b/src/all/mangaball/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..21c53e08afdd82672701eedd5ba75818e3d7392e GIT binary patch literal 15992 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 S=>IXw0a9Y}qBX*Xf&T~Pw{U*| literal 0 HcmV?d00001 diff --git a/src/all/mangaball/res/mipmap-xxxhdpi/ic_launcher.png b/src/all/mangaball/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..679052f9c547d6af2e6d46d5cc1c35a98476bf50 GIT binary patch literal 23583 zcmV*MKx4m&P)V_7pb`d->lLU(fa7}m zD<@xx0F^LsT(3YS0vy-dUpe_o1gM08<9Y=u5#YGq{>sT$B0wb!9M>yQi2%p-_E%26 zv=N}R`>WjH^0xwor8(r%07!3rlt$mBxt5iE1-}CBz+d9XP?A9C-nRbR{ij~Gk{nC$ zTT|IWNvwbsz&-u0zbi3BC@G+`w#(l=eYl|d`;u7PW7Otp=y%C6>bu-^>j3QYL<)b# z2QzU0a8f0P2ql34Rtm2HJe93CFtKP)V)DZXonpH1|(6&4nc=*8VH zUtVfz-?w4@djSVK@%ya9hYx?ZapT7QCeU+Rtq5U72D@eR z>3*mYzzX~XdiCkmt5>&}n3!Ss{feVUkJd;{O_iLS9LdeiRX^3Nd;ng%XG-#ZS#3L* zag~L4qoboGDk@6&Gchqys#U9Y7zA=E;Nr7Yt5z)oXb=hXC*+(UlnCGn_#=Au?AZ+y zm;%ghaOB7l$;->LU?%5dycW!6go1+v+ka5+1Nn>NeZEptPb9Cry&D-BDK%=;keW4X z9>wpYR<2z6i-`dFUc@7xD809bLWKbCz#oAQBThg4^q~a>1+OP3C&y??@9!ps0=Pqg zV8HY}~kU_1d*-FWbF)cZ2+VBCYq!ZlUcKti0d1n}0C( zE5f_v1PvQDOa~lw-?nXAGWI(cAFECf6c-2;0%(Od5`&BC)2Gif(BwxKC-(RPxS@I` z7(no448E{*ZzLd?u^p>-?bamJ)B$qEILhfNc-~DECJ- zXwaYrSk{IE2M)y8QGUMUT{yB=jO{kU>wUM5OB8?$K%k0Q%?H?eple-JlT!wWk+cO zMi5Ikc6}7)1Hg+8&C!DG`(+SF?bhvB&8cO}mJk2;-+wP*e6*cwr8p=q5G(??P=5?6 zrd_*sZ-M#`3Y6vR_v{wgZj*eu@5?iG<2Y6n+-~g0YTUu}Yd5F*_3JN#Q3Xz8$qp44 z2n7NtlP9S^KC!^kUsF<2+WW)aN`kW6EvDl>SHO!JRg#7QT#y8mTU zfOdTZbKm`4cOfv8ZTqrU*8WS1>)Fi-K7svdX=x{6yjdm^SjC`#tU;kb0HyrmL!~zk zO7ISbIQR;v*2TA50Ds!FYs>Y1QFYwE_lpvjWBGnb_8m;y!M@9oiR|p`MivAh7tq$A zQbzzC=%!4c6n}^SNl8fzZc>-sgpU>Q`!Y7Wu^-F(CE0gbZCj5E#uWxnX4ZxtaKKQ8 ztq9;Z5(L8mtO~G_|4jr)wp&DBSZ-08>Kj7&(zo3+cK1sff$aJZ_C6?+*BF9e+79Mj zyESFo%G^^>&n`S@|6SFE#|QR{*ngXvfjSko&ckm;1dxEw2(xB-kps{I zL>+)4&}O?4*e!;?!0!uS`SOe}%L> z`SLB;tx-wd_owZ0hX8hy^CT|$`c9~x^Q9fTXYB6VQNfbFZ#TY@ydOy0-aOCc1_A6Q z9jsZ@*Yt$wQ!>*5#ykC~uE;9%Kz|fxHpb@}sf&B$)Ux2nWpRt=?MZO>Exm7p> zuv?�{&1TfG^{>d!{_!FUhfcYP-T9fZf6cY7z|Tarc9H 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, + private val pagination: Pagination, +) { + @Serializable + class Pagination( + @SerialName("current_page") + val currentPage: Int, + @SerialName("last_page") + val lastPage: Int, + ) + + fun hasNextPage() = pagination.currentPage < pagination.lastPage +} + +@Serializable +class SearchManga( + val url: String, + val name: String, + val cover: String, + val isAdult: Boolean, +) + +@Serializable +class ChapterListResponse( + @SerialName("ALL_CHAPTERS") + val chapters: List, +) + +@Serializable +class ChapterContainer( + @SerialName("number_float") + val number: Float, + val translations: List, +) + +@Serializable +class Chapter( + val id: String, + val name: String, + val language: String, + val group: Group, + val date: String, + val volume: Int, +) + +@Serializable +class Group( + @SerialName("_id") + val id: String, + val name: String, +) + +@Serializable +class Yoast( + @SerialName("@graph") + val graph: List, +) { + @Serializable + class Graph( + @SerialName("@type") + val type: String, + val url: String? = null, + ) +} diff --git a/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/Filters.kt b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/Filters.kt new file mode 100644 index 000000000..c4c646768 --- /dev/null +++ b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/Filters.kt @@ -0,0 +1,201 @@ +package eu.kanade.tachiyomi.extension.all.mangaball + +import eu.kanade.tachiyomi.source.model.Filter + +abstract class SelectFilter( + name: String, + private val options: List>, +) : Filter.Select( + name, + options.map { it.first }.toTypedArray(), +) { + val selected get() = options[state].second +} + +class TriStateFilter(name: String, val value: T) : Filter.TriState(name) + +abstract class TriStateGroupFilter( + name: String, + options: List>, +) : Filter.Group>( + name, + options.map { TriStateFilter(it.first, it.second) }, +) { + val included get() = state.filter { it.isIncluded() }.map { it.value } + val excluded get() = state.filter { it.isExcluded() }.map { it.value } +} + +class SortFilter : SelectFilter( + "Sort By", + options = listOf( + "Lastest Updated Chapters" to "updated_chapters_desc", + "Oldest Updated Chapters" to "updated_chapters_asc", + "Lastest Created" to "created_at_desc", + "Oldest Created" to "created_at_asc", + "Title A-Z" to "name_asc", + "Title Z-A" to "name_desc", + "Views High to Low" to "views_desc", + "Views Low to High" to "views_asc", + ), +) + +class ContentFilter : TriStateGroupFilter( + "Content", + options = listOf( + "Gore" to "685148d115e8b86aae68e4f3", + "Sexual Violence" to "685146c5f3ed681c80f257e7", + ), +) + +class FormatFilter : TriStateGroupFilter( + "Format", + options = listOf( + "4-Koma" to "685148d115e8b86aae68e4ec", + "Adaptation" to "685148cf15e8b86aae68e4de", + "Anthology" to "685148e915e8b86aae68e558", + "Award Winning" to "685148fe15e8b86aae68e5a7", + "Doujinshi" to "6851490e15e8b86aae68e5da", + "Fan Colored" to "6851498215e8b86aae68e704", + "Full Color" to "685148d615e8b86aae68e502", + "Long Strip" to "685148d915e8b86aae68e517", + "Official Colored" to "6851493515e8b86aae68e64a", + "Oneshot" to "685148eb15e8b86aae68e56c", + "Self-Published" to "6851492e15e8b86aae68e633", + "Web Comic" to "685148d715e8b86aae68e50d", + ), +) + +class GenreFilter : TriStateGroupFilter( + "Genre", + options = listOf( + "Action" to "685146c5f3ed681c80f257e3", + "Adult" to "689371f0a943baf927094f03", + "Adventure" to "685146c5f3ed681c80f257e6", + "Boys' Love" to "685148ef15e8b86aae68e573", + "Comedy" to "685146c5f3ed681c80f257e5", + "Crime" to "685148da15e8b86aae68e51f", + "Drama" to "685148cf15e8b86aae68e4dd", + "Ecchi" to "6892a73ba943baf927094e37", + "Fantasy" to "685146c5f3ed681c80f257ea", + "Girls' Love" to "685148da15e8b86aae68e524", + "Historical" to "685148db15e8b86aae68e527", + "Horror" to "685148da15e8b86aae68e520", + "Isekai" to "685146c5f3ed681c80f257e9", + "Magical Girls" to "6851490d15e8b86aae68e5d4", + "Mature" to "68932d11a943baf927094e7b", + "Mecha" to "6851490c15e8b86aae68e5d2", + "Medical" to "6851494e15e8b86aae68e66e", + "Mystery" to "685148d215e8b86aae68e4f4", + "Philosophical" to "685148e215e8b86aae68e544", + "Psychological" to "685148d715e8b86aae68e507", + "Romance" to "685148cf15e8b86aae68e4db", + "Sci-Fi" to "685148cf15e8b86aae68e4da", + "Shounen Ai" to "689f0ab1f2e66744c6091524", + "Slice of Life" to "685148d015e8b86aae68e4e3", + "Smut" to "689371f2a943baf927094f04", + "Sports" to "685148f515e8b86aae68e588", + "Superhero" to "6851492915e8b86aae68e61c", + "Thriller" to "685148d915e8b86aae68e51e", + "Tragedy" to "685148db15e8b86aae68e529", + "User Created" to "68932c3ea943baf927094e77", + "Wuxia" to "6851490715e8b86aae68e5c3", + "Yaoi" to "68932f68a943baf927094eaa", + "Yuri" to "6896a885a943baf927094f66", + ), +) + +class OriginFilter : TriStateGroupFilter( + "Origin", + options = listOf( + "Comic" to "68ecab8507ec62d87e62780f", + "Manga" to "68ecab1e07ec62d87e627806", + "Manhua" to "68ecab4807ec62d87e62780b", + "Manhwa" to "68ecab3b07ec62d87e627809", + ), +) + +class ThemeFilter : TriStateGroupFilter( + "Theme", + options = listOf( + "Aliens" to "6851490d15e8b86aae68e5d5", + "Animals" to "685148e715e8b86aae68e54b", + "Comics" to "68bf09ff8fdeab0b6a9bc2b7", + "Cooking" to "685148d215e8b86aae68e4f8", + "Crossdressing" to "685148df15e8b86aae68e534", + "Delinquents" to "685148d915e8b86aae68e519", + "Demons" to "685146c5f3ed681c80f257e4", + "Genderswap" to "685148d715e8b86aae68e505", + "Ghosts" to "685148d615e8b86aae68e501", + "Gyaru" to "685148d015e8b86aae68e4e8", + "Harem" to "685146c5f3ed681c80f257e8", + "Hentai" to "68bfceaf4dbc442a26519889", + "Incest" to "685148f215e8b86aae68e584", + "Loli" to "685148d715e8b86aae68e506", + "Mafia" to "685148d915e8b86aae68e518", + "Magic" to "685148d715e8b86aae68e509", + "Manhwa 18+" to "68f5f5ce5f29d3c1863dec3a", + "Martial Arts" to "6851490615e8b86aae68e5c2", + "Military" to "685148e215e8b86aae68e541", + "Monster Girls" to "685148db15e8b86aae68e52c", + "Monsters" to "685146c5f3ed681c80f257e2", + "Music" to "685148d015e8b86aae68e4e4", + "Ninja" to "685148d715e8b86aae68e508", + "Office Workers" to "685148d315e8b86aae68e4fd", + "Police" to "6851498815e8b86aae68e714", + "Post-Apocalyptic" to "685148e215e8b86aae68e540", + "Reincarnation" to "685146c5f3ed681c80f257e1", + "Reverse Harem" to "685148df15e8b86aae68e533", + "Samurai" to "6851490415e8b86aae68e5b9", + "School Life" to "685148d015e8b86aae68e4e7", + "Shota" to "685148d115e8b86aae68e4ed", + "Supernatural" to "685148db15e8b86aae68e528", + "Survival" to "685148cf15e8b86aae68e4dc", + "Time Travel" to "6851490c15e8b86aae68e5d1", + "Traditional Games" to "6851493515e8b86aae68e645", + "Vampires" to "685148f915e8b86aae68e597", + "Video Games" to "685148e115e8b86aae68e53c", + "Villainess" to "6851492115e8b86aae68e602", + "Virtual Reality" to "68514a1115e8b86aae68e83e", + "Zombies" to "6851490c15e8b86aae68e5d3", + ), +) + +class TagIncludeMode : SelectFilter( + "Tag Include Mode", + options = listOf( + "AND" to "and", + "OR" to "or", + ), +) + +class TagExcludeMode : SelectFilter( + "Tag Exclude Mode", + options = listOf( + "AND" to "and", + "OR" to "or", + ), +) + +class DemographicFilter : SelectFilter( + "Magazine Demographic", + options = listOf( + "Any" to "any", + "Shounen" to "shounen", + "Shoujo" to "shoujo", + "Seinen" to "seinen", + "Josei" to "josei", + "Yuri" to "yuri", + "Yaoi" to "yaoi", + ), +) + +class StatusFilter : SelectFilter( + "Publication Status", + options = listOf( + "Any" to "any", + "Ongoing" to "ongoing", + "Completed" to "completed", + "Hiatus" to "hiatus", + "Cancelled" to "cancelled", + ), +) diff --git a/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBall.kt b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBall.kt new file mode 100644 index 000000000..e4bdc0956 --- /dev/null +++ b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBall.kt @@ -0,0 +1,403 @@ +package eu.kanade.tachiyomi.extension.all.mangaball + +import android.util.Log +import androidx.preference.PreferenceScreen +import androidx.preference.SwitchPreferenceCompat +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.POST +import eu.kanade.tachiyomi.source.ConfigurableSource +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.util.asJsoup +import keiyoushi.utils.firstInstance +import keiyoushi.utils.getPreferencesLazy +import keiyoushi.utils.parseAs +import keiyoushi.utils.tryParse +import okhttp3.Call +import okhttp3.Callback +import okhttp3.FormBody +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.Request +import okhttp3.Response +import okhttp3.internal.closeQuietly +import okio.IOException +import org.jsoup.nodes.Document +import rx.Observable +import java.lang.UnsupportedOperationException +import java.text.SimpleDateFormat +import java.util.Locale + +class MangaBall( + override val lang: String, + private vararg val siteLang: String, +) : HttpSource(), ConfigurableSource { + + override val name = "Manga Ball" + override val baseUrl = "https://mangaball.net" + override val supportsLatest = true + private val preferences by getPreferencesLazy() + + override val client = network.cloudflareClient.newBuilder() + .addInterceptor { chain -> + var request = chain.request() + if (request.url.pathSegments[0] == "api") { + request = request.newBuilder() + .header("X-Requested-With", "XMLHttpRequest") + .header("X-CSRF-TOKEN", getCSRF()) + .build() + + val response = chain.proceed(request) + if (!response.isSuccessful && response.code == 403) { + response.close() + request = request.newBuilder() + .header("X-CSRF-TOKEN", getCSRF(forceReset = true)) + .build() + + chain.proceed(request) + } else { + response + } + } else { + chain.proceed(request) + } + } + .build() + + private var _csrf: String? = null + + @Synchronized + private fun getCSRF(document: Document? = null, forceReset: Boolean = false): String { + if (_csrf == null || document != null || forceReset) { + val doc = document ?: client.newCall( + GET(baseUrl, headers), + ).execute().asJsoup() + + doc.selectFirst("meta[name=csrf-token]") + ?.attr("content") + ?.takeIf { it.isNotBlank() } + ?.also { _csrf = it } + } + + return _csrf ?: throw Exception("CSRF token not found") + } + + override fun headersBuilder() = super.headersBuilder() + .set("Referer", "$baseUrl/") + + override fun popularMangaRequest(page: Int): Request { + val filters = getFilterList().apply { + firstInstance().state = 6 + } + + return searchMangaRequest(page, "", filters) + } + + override fun popularMangaParse(response: Response) = + searchMangaParse(response) + + override fun latestUpdatesRequest(page: Int) = + searchMangaRequest(page, "", getFilterList()) + + override fun latestUpdatesParse(response: Response) = + searchMangaParse(response) + + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { + return if (query.startsWith("https://")) { + deepLink(query) + } else { + super.fetchSearchManga(page, query, filters) + } + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val body = FormBody.Builder().apply { + add("search_input", query.trim()) + add("filters[sort]", filters.firstInstance().selected) + add("filters[page]", page.toString()) + filters.filterIsInstance>().forEach { tags -> + tags.included.forEach { tag -> + add("filters[tag_included_ids][]", tag) + } + } + add("filters[tag_included_mode]", filters.firstInstance().selected) + filters.filterIsInstance>().forEach { tags -> + tags.excluded.forEach { tag -> + add("filters[tag_excluded_ids][]", tag) + } + } + add("filters[tag_excluded_mode]", filters.firstInstance().selected) + add("filters[contentRating]", "any") + add("filters[demographic]", filters.firstInstance().selected) + add("filters[person]", "any") + add("filters[publicationYear]", "") + add("filters[publicationStatus]", filters.firstInstance().selected) + siteLang.forEach { + add("filters[translatedLanguage][]", it) + } + }.build() + + return POST("$baseUrl/api/v1/title/search-advanced/", headers, body) + } + + override fun getFilterList() = FilterList( + SortFilter(), + DemographicFilter(), + StatusFilter(), + ContentFilter(), + FormatFilter(), + GenreFilter(), + OriginFilter(), + ThemeFilter(), + TagIncludeMode(), + TagExcludeMode(), + ) + + override fun searchMangaParse(response: Response): MangasPage { + val data = response.parseAs() + val hideNsfw = hideNsfwPreference() + + val mangas = data.data + .filterNot { + it.isAdult && hideNsfw + } + .map { + SManga.create().apply { + url = it.url.toHttpUrl().pathSegments[1] + title = it.name + thumbnail_url = it.cover + } + } + + if (mangas.isEmpty() && hideNsfw) { + throw Exception("All results filtered out due to nsfw filter") + } + + return MangasPage(mangas, data.hasNextPage()) + } + + private fun deepLink(url: String): Observable { + val httpUrl = url.toHttpUrl() + if ( + httpUrl.host == baseUrl.toHttpUrl().host && + httpUrl.pathSegments.size >= 2 && + httpUrl.pathSegments[0] in listOf("title-detail", "chapter-detail") + ) { + val slug = if (httpUrl.pathSegments[0] == "title-detail") { + httpUrl.pathSegments[1] + } else { + client.newCall(GET(httpUrl, headers)).execute() + .use { response -> + response.asJsoup() + .selectFirst(".yoast-schema-graph")!!.data() + .parseAs() + .graph.first { it.type == "WebPage" } + .url!!.toHttpUrl() + .pathSegments[1] + } + } + + val manga = SManga.create().apply { + this.url = slug + } + + return fetchMangaDetails(manga).map { + MangasPage(listOf(it), false) + } + } + + throw Exception("Unsupported url") + } + + override fun mangaDetailsRequest(manga: SManga): Request { + return GET(getMangaUrl(manga), headers) + } + + override fun getMangaUrl(manga: SManga): String { + return "$baseUrl/title-detail/${manga.url}/" + } + + override fun mangaDetailsParse(response: Response): SManga { + val document = response.asJsoup() + getCSRF(document) + + return SManga.create().apply { + url = document.location().toHttpUrl().pathSegments[1] + title = document.selectFirst("#comicDetail h6")!!.ownText() + thumbnail_url = document.selectFirst("img.featured-cover")?.absUrl("src") + genre = buildList { + document.selectFirst("#featuredComicsCarousel img[src*=/flags/]") + ?.attr("src")?.also { + when { + it.contains("jp") -> add("Manga") + it.contains("kr") -> add("Manhwa") + it.contains("cn") -> add("Manhua") + } + } + document.select("#comicDetail span[data-tag-id]") + .mapTo(this) { it.ownText() } + }.joinToString() + author = document.select("#comicDetail span[data-person-id]") + .eachText().joinToString() + description = buildString { + document.selectFirst("#descriptionContent p") + ?.also { append(it.wholeText()) } + document.selectFirst("#comicDetail span.badge:contains(Published)") + ?.also { append("\n\n", it.text()) } + val titles = document.select("div.alternate-name-container").text().split("/") + if (titles.isNotEmpty()) { + append("\n\nAlternative Names: \n") + titles.forEach { + append("- ", it.trim(), "\n") + } + } + }.trim() + status = when (document.selectFirst("span.badge-status")?.text()) { + "Ongoing" -> SManga.ONGOING + "Completed" -> SManga.COMPLETED + "Hiatus" -> SManga.ON_HIATUS + "Cancelled" -> SManga.CANCELLED + else -> SManga.UNKNOWN + } + } + } + + override fun chapterListRequest(manga: SManga): Request { + val id = manga.url.substringAfterLast("-") + val body = FormBody.Builder() + .add("title_id", id) + .build() + + return POST("$baseUrl/api/v1/chapter/chapter-listing-by-title-id/", headers, body) + } + + override fun chapterListParse(response: Response): List { + (response.request.body as FormBody).also { + updateViews(it.value(0)) + } + + val data = response.parseAs() + + return data.chapters.flatMap { chapter -> + chapter.translations.mapNotNull { translation -> + if (translation.language in siteLang) { + SChapter.create().apply { + url = translation.id + name = buildString { + if (translation.volume > 0) { + append("Vol. ") + append(translation.volume) + append(" ") + } + val number = chapter.number.toString().removeSuffix(".0") + if (translation.name.contains(number)) { + append(translation.name.trim()) + } else { + append("Ch. ") + append(number) + append(" ") + append(translation.name.trim()) + } + } + chapter_number = chapter.number + date_upload = dateFormat.tryParse(translation.date) + scanlator = buildString { + append(translation.group.name) + // id is usually the name of the site the chapter was scraped from + // if not then it is generated id of an active group on the site + if (groupIdRegex.matchEntire(translation.group.id) == null) { + append(" (") + append(translation.group.id) + append(")") + } + } + } + } else { + null + } + } + } + } + + private val groupIdRegex = Regex("""[a-z0-9]{24}""") + + private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT) + + override fun pageListRequest(chapter: SChapter): Request { + return GET(getChapterUrl(chapter), headers) + } + + override fun getChapterUrl(chapter: SChapter): String { + return "$baseUrl/chapter-detail/${chapter.url}/" + } + + override fun pageListParse(response: Response): List { + val document = response.asJsoup() + getCSRF(document) + + document.select("script:containsData(titleId)").joinToString(";") { it.data() }.also { + val titleId = titleIdRegex.find(it) + ?.groupValues?.get(1) + ?: return@also + val chapterId = chapterIdRegex.find(it) + ?.groupValues?.get(1) + ?: return@also + + updateViews(titleId, chapterId) + } + + val script = document.select("script:containsData(chapterImages)").joinToString(";") { it.data() } + val images = imagesRegex.find(script) + ?.groupValues?.get(1) + ?.parseAs>() + .orEmpty() + + return images.mapIndexed { idx, img -> + Page(idx, imageUrl = img) + } + } + + private val imagesRegex = Regex("""const\s+chapterImages\s*=\s*JSON\.parse\(`([^`]+)`\)""") + private val titleIdRegex = Regex("""const\s+titleId\s*=\s*`([^`]+)`;""") + private val chapterIdRegex = Regex("""const\s+chapterId\s*=\s*`([^`]+)`;""") + + private fun updateViews(titleId: String, chapterId: String = "") { + val body = FormBody.Builder() + .add("title_id", titleId) + .add("chapter_id", chapterId) + .build() + + val request = POST("$baseUrl/api/v1/views/update/", headers, body) + + client.newCall(request) + .enqueue( + object : Callback { + override fun onResponse(call: Call, response: Response) { + response.closeQuietly() + } + override fun onFailure(call: Call, e: IOException) { + Log.e(name, "Failed to update views", e) + } + }, + ) + } + + override fun setupPreferenceScreen(screen: PreferenceScreen) { + SwitchPreferenceCompat(screen.context).apply { + key = NSFW_PREF + title = "Hide NSFW content" + setDefaultValue(false) + }.also(screen::addPreference) + } + + private fun hideNsfwPreference() = preferences.getBoolean(NSFW_PREF, false) + + override fun imageUrlParse(response: Response): String { + throw UnsupportedOperationException() + } +} + +private const val NSFW_PREF = "nsfw_pref" diff --git a/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBallFactory.kt b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBallFactory.kt new file mode 100644 index 000000000..e1a4a4ed6 --- /dev/null +++ b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/MangaBallFactory.kt @@ -0,0 +1,50 @@ +package eu.kanade.tachiyomi.extension.all.mangaball + +import eu.kanade.tachiyomi.source.SourceFactory + +class MangaBallFactory : SourceFactory { + override fun createSources() = listOf( + MangaBall("ar", "ar"), + MangaBall("bg", "bg"), + MangaBall("bn", "bn"), + MangaBall("ca", "ca", "ca-ad", "ca-es", "ca-fr", "ca-it", "ca-pt"), + MangaBall("cs", "cs"), + MangaBall("da", "da"), + MangaBall("de", "de"), + MangaBall("el", "el"), + MangaBall("en", "en"), + MangaBall("es", "es", "es-ar", "es-mx", "es-es", "es-la", "es-419"), + MangaBall("fa", "fa"), + MangaBall("fi", "fi"), + MangaBall("fr", "fr"), + MangaBall("he", "he"), + MangaBall("hi", "hi"), + MangaBall("hu", "hu"), + MangaBall("id", "id"), + MangaBall("it", "it", "it-it"), + MangaBall("is", "ib", "ib-is", "is"), + MangaBall("ja", "jp"), + MangaBall("ko", "kr"), + MangaBall("kn", "kn", "kn-in", "kn-my", "kn-sg", "kn-tw"), + MangaBall("ml", "ml", "ml-in", "ml-my", "ml-sg", "ml-tw"), + MangaBall("ms", "ms"), + MangaBall("ne", "ne"), + MangaBall("nl", "nl", "nl-be"), + MangaBall("no", "no"), + MangaBall("pl", "pl"), + MangaBall("pt-BR", "pt-br", "pt-pt"), + MangaBall("ro", "ro"), + MangaBall("ru", "ru"), + MangaBall("sk", "sk"), + MangaBall("sl", "sl"), + MangaBall("sq", "sq"), + MangaBall("sr", "sr", "sr-cyrl"), + MangaBall("sv", "sv"), + MangaBall("ta", "ta"), + MangaBall("th", "th", "th-hk", "th-kh", "th-la", "th-my", "th-sg"), + MangaBall("tr", "tr"), + MangaBall("uk", "uk"), + MangaBall("vi", "vi"), + MangaBall("zh", "zh", "zh-cn", "zh-hk", "zh-mo", "zh-sg", "zh-tw"), + ) +} diff --git a/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/UrlActivity.kt b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/UrlActivity.kt new file mode 100644 index 000000000..33e5b18e9 --- /dev/null +++ b/src/all/mangaball/src/eu/kanade/tachiyomi/extension/all/mangaball/UrlActivity.kt @@ -0,0 +1,29 @@ +package eu.kanade.tachiyomi.extension.all.mangaball + +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 UrlActivity : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val mainIntent = Intent().apply { + action = "eu.kanade.tachiyomi.SEARCH" + putExtra("query", intent.data.toString()) + putExtra("filter", packageName) + } + + try { + startActivity(mainIntent) + } catch (e: ActivityNotFoundException) { + Log.e("MangaBall", "Unable to launch activity", e) + } + + finish() + exitProcess(0) + } +}