From 2e410da03bf5aaf5477f5f719be5b5cdac2977db Mon Sep 17 00:00:00 2001
From: Claudemirovsky <63046606+Claudemirovsky@users.noreply.github.com>
Date: Wed, 17 Jan 2024 07:32:04 -0300
Subject: [PATCH] New source: SlimeRead (#317)
* feat: Create SlimeRead base
* feat: Implement popular manga page
* feat: Implement latest manga page
* feat: Implement search manga page
* feat: Implement manga details page
* feat: Implement chapter list
* feat: Parse page list
* fix: Revert chapter list
* chore: Apply rate-limit in the source API
* chore: Add Origin header to API requests
* chore: Add source icon
* chore: Add isNsfw flag
---
src/pt/slimeread/AndroidManifest.xml | 22 ++
src/pt/slimeread/build.gradle | 8 +
.../slimeread/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3761 bytes
.../slimeread/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1962 bytes
.../res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4778 bytes
.../res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 9415 bytes
.../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 11982 bytes
.../extension/pt/slimeread/SlimeRead.kt | 189 ++++++++++++++++++
.../pt/slimeread/SlimeReadFilters.kt | 141 +++++++++++++
.../pt/slimeread/SlimeReadUrlActivity.kt | 41 ++++
.../pt/slimeread/dto/SlimeReadDto.kt | 72 +++++++
11 files changed, 473 insertions(+)
create mode 100644 src/pt/slimeread/AndroidManifest.xml
create mode 100644 src/pt/slimeread/build.gradle
create mode 100644 src/pt/slimeread/res/mipmap-hdpi/ic_launcher.png
create mode 100644 src/pt/slimeread/res/mipmap-mdpi/ic_launcher.png
create mode 100644 src/pt/slimeread/res/mipmap-xhdpi/ic_launcher.png
create mode 100644 src/pt/slimeread/res/mipmap-xxhdpi/ic_launcher.png
create mode 100644 src/pt/slimeread/res/mipmap-xxxhdpi/ic_launcher.png
create mode 100644 src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeRead.kt
create mode 100644 src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadFilters.kt
create mode 100644 src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadUrlActivity.kt
create mode 100644 src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/dto/SlimeReadDto.kt
diff --git a/src/pt/slimeread/AndroidManifest.xml b/src/pt/slimeread/AndroidManifest.xml
new file mode 100644
index 000000000..d91361ff4
--- /dev/null
+++ b/src/pt/slimeread/AndroidManifest.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pt/slimeread/build.gradle b/src/pt/slimeread/build.gradle
new file mode 100644
index 000000000..7ef2001f4
--- /dev/null
+++ b/src/pt/slimeread/build.gradle
@@ -0,0 +1,8 @@
+ext {
+ extName = 'SlimeRead'
+ extClass = '.SlimeRead'
+ extVersionCode = 1
+ isNsfw = true
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/pt/slimeread/res/mipmap-hdpi/ic_launcher.png b/src/pt/slimeread/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..a205199044c27084c1e8d43d77004ef9d31397e7
GIT binary patch
literal 3761
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
bX4(G*s86x(HeR?l00000NkvXXu0mjf^MD%J
literal 0
HcmV?d00001
diff --git a/src/pt/slimeread/res/mipmap-mdpi/ic_launcher.png b/src/pt/slimeread/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..841ef2e73fa3367b2cbfac9f77b2ca82a07f5e8d
GIT binary patch
literal 1962
zcmV;b2UYlqP)?%;sXW6
z2MGS5o6f0-Iwx~uIz{c~TDq;(+8Mi~ue52>JU!=2ZhM>Dq~C2TMKJWzd++z%^ZkD3
zch31vZVdR3e+>U|{P>^1LMxa}0Uk3ZkA=h;qs94%Yk|-tuypCt0{ZL;g+h16<8izC
zLAn-~djBgn)XypBnd~LUhpblXdmfKx7ae1%B(woLn;AI+EOCm(UM*cJm*`&?0kifVv7hk=$xI)i-?aVftHpQ
zPpSf1;AIHSC45rt>n1Q;73LcMnZih#Ky!2Rqykf5xO^JY%4aqe=F|IZOE-a;6p#Tg
z6K1k|iZp?yrX~#q68_AVm^_|aRF29O8&K?8hTMWuegHw=0ET*gfxG=HOpJ07(Z3P$
zx?ZnWE{PQaYOpfk>(*{Y{kq#>Fy$oKDnZ13KpfF<2fXt95ol~|%&0)7
zYSeJeU2qYBrcxt*{_G$uHLb{Xwh9LIr6zQpIEGkZIm{IeMB**<9{*5ZnI#8!J(3D2
z1Y{HtVN>kDl@GoSgVBgprr&Y+s#b2qC7T`=z+%C11pCfX__V-i%@g;c<6{VPx5HB1
z46~i{kO&-j4*jRT(Ul7W0|RnNTwh-=tpJ0uP_5_hDpL(Jp!2n_y}
z5xk;8q6?cR0aWi2X-PS$DA0_DyzwdycgZr
zyK5WzFZ9lhKy7Vp+CGqPE5KuWUW2o)aYpb8M&ShdGZ>ReodtZts1d#0op^f376b$1
zY3oQUzy!qNye|DKC@R52yPieMl1nwfPe-M`VjD3E33{WD)$^%FJKKN4zTG?FA5H8N
zx^tkWre;!srncqSy7MWNmRE?FWuvB?9FjOjac?1jQH=W&Z#wdAg^1C8ORg2R0y-z~
zqSP8q@Q?WrnwTJ`7-;?|`Nn`eQq@QeAm@Y8U_>MmA!ijMk8;ZM_g{GVna9!7^_zYI
zPN!24xMJM~+;-nXw1`OnEiNg=(14ecHV+elfH2HtII$TlCo==%KLLhFu#gO%bAc1o
zNQ3@>pPn&_>qs;ro?+5Kx^G|Pz{ubLjHFtW#@>J9MVvhPl~_wUgqXmU>#xJD_ihvN
zvmy3~H9uc?iao>&^O%YD0kg$2NrXd=RbT+INHn1Ukz^a}2$9EhFA@oZ6FnLZBTCLO
z(U+hAHGS*|j(@Ijd@oA#UVr`xbo~0GJb~)!YC(WQqNv19i$@U(1`(uAbI9v~Z)6ao
zBSRvj7z8iM9_IO6soIubj`i2yOkqSX_eh<<_&9z(@hy7Jp22{(UwAl7VZ$oqQpaj5
zDneO#C7iBCII3y{QMPBM%H%Q^bt@ek8D#nZ5{znluq(Cd6`Kn-dAkT
z)T*Q=w{!?qRaIqdC1l8??ZW)NkML)D%b`))G;hs{KqfEEL`1gbkOi+Ri7P8BH5HI0
zlg-n5!)8|dfSQ0T=+yY0YrLl`6Q?8|l>16qQBg5(3TP426E=Dk;O3#!;c#@*=2SH0
z{bWy}vNlr=%qQ^VvOY@UCOYR=dl_G^Gt#26va*+Gle#C>Q?lVSmpIR)4(&zn4i67+
zr*UqOCR;A8pP0C@ueIClyNSdmCZuIlMuFLeiuyTP$4B5l@%emD()~Uu@
zjuJWw=-?NfT*>F@V<9`C>9#a(B`1)l3&X%DcZ+Bb@Y0ya--E}UooC!l!XAD;1Ci$Jbq;{X5v07*qoM6N<$g6&GON&o-=
literal 0
HcmV?d00001
diff --git a/src/pt/slimeread/res/mipmap-xhdpi/ic_launcher.png b/src/pt/slimeread/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..9034642e83cd9055b569e56a1a45403c077ebfbb
GIT binary patch
literal 4778
zcmV;b5>@SqP)KhiI0qy^V3GzXXUdgwHUlYBC=3JTC`X`$4opbPl)GiP8Yq7-
zKw-GjgQP*66Od&DvRwVN2Ykl~AOip2
zNsPoe6h1XknhJPktbq=?R`{e!Qz=VRW2abVG4Nq*8~rVOa+9G2GzNTKU7fqJvGLmB
z;o()|l2=@o=>LOuyM4FY?fz41YwIh`&CP)r5k!V+
z;w6Btj=PwtncaRnTO!B!sWnM>vTHj)vlHHI9YzRvb0=lwOXO1q-3YbWV*bm
zsp$~5g8)(`frkLfW38yD@YdGWZbtCurfM~Egrx(5k^v~SFP*x0uPrVv-qF_9c4mKn
z|6q)Sr1HQ+fCUS3p!MI~-QB%b3;3A;JemCQf+qAyL1JV*Jz3dhWo5tExpU`pc;N^h
zp=3IwMgX0+;o)4kaN(9>MSfB}6aqQ>kBRE@3zU
zTBL}lW2xrJxcp2GeiGKf#F!XHfR^B=MWT2-DOue-1nMO(O8qjFfLXI!`c91`6sIgU#&)SAH3oZ8@y?&}aaLdXK`$Ko4~9-v+_{&IE-rQf}nhtvdnr
z_4O&mfOO&jT}vQWoUk0q7cB=@Aug|&WL8f^i@lLZ82s(~;qd2wht548LwI~F>1aib
z^i)V@%lA1tms
zlq=fKh%Of&`q$ggyy=yU$&u~^;O!_$V}KICT7z)aDL;f+=UhJl{z+9fXe@}p^J^c6
z;BXL3HV62YUjtT8VH`pAg%&uy&H=Cg@pU-3dpDSofc!JB1gp0=MnV{Nzxyb3?)_v^
z&SY+<(Mz5(N`PKcWOI38$;~f<#U35qP`ctcC(J3fz{6{vh9ieNz=Y>=PdXQzwF}}1
zSXOI?vt~Kqm6zUvZCjd{5V;x_L*C-$6ZwYwj=}2Iu4E4
zA6kMl<*i(NAvFBp#<-%!o4)|tp(Z%m-U$u_-Me%}LRF;u;bR@(-2FZrYB`J&bvassv~OTdvQ#
z6EJh;OxZA+L*38sv6kvR667wKClD)O&=mzVX#-!BLNp-(5Aa;CevVN3v63=b5a7*
zwSFo*BOZ_{@NyPI-_5_|9w?rFT7qoI-PR-pKU!wurP6N>H@y%0HatD?wHnxRZB@I5
z&f_hd`p$#}2~q=H30$Ga$*wP5a0bl1_^x=&WI#<7d?IMq`bVI1_hxPa)WB9ENOuD8
z#@w`GfEqD$-ePyc_ilfgeX^u8_z{dFn;&0^i+6OVi2VILQjbw1K8J67gBIJ1DM=nukNOT7t
z&6mc89dE3Go&(!84?}r8CX5XdR;~;oKns{!@(LbMv-Aq6JM$+AkyJ16so?Qo0QUUl
z3FyLo1HsMo@CGSCx)U&C#thXMz@zgC=*GVA)h>eLuX+%Nm(lwzg`_9=LRcZdyTASv
z4t)3$4EG)}#2Ye7Kq}TA2QsS5$u~R=xh1u_fiIOF)<(%@4tc{@Z$AXR%}u0#tZu!$
z!Egf71zp@(Pvsmq>Dnjaz#kjIZN~0a$Stb}b8JaLPV+~H`f;gwJp(bndM?aZwh|n;
z6d}$Vz;Z}-s+V34CAi6BG7DZ7!8yURxO=v7(&J?I3#4AFHZr38x)V@SQ==k5WI-G=
zp;&Lkogly#U-x^kIXyUu9fw0({|v2oj0XpCH_V5?T?$pFTpTA)bbTL!zHh@b5cGFV
zV3gx6!MVh0@K#5E%;P`&HGK8XLonj+VSl@eX8;jSTbDE|9%%nY5qvq1-~m5N1W4^f
z{%
zNFblHVkMk@-X%~_lsJ=4Ha-}}vif_w;Yiy-_-4-z*wwTRT3ZevQS=K_zBMCh7c%An
z$t>NBR=n!Q)v)CI%MtAOtwAo#C&wpo*?YP=;DyK6AXw4+edaD)3^(5MYw+Y3C`5j~
z+QehHVf4B!A8vrx);)g0Uld|4%|n6MUh(r`E29rceJVJ4;sTpm795huQM|jaf&-{6%o*+NW4B
z)t;15OT05Kx>6**dv4NH`D<3=X#@uX53Rl)S`O^vF4Q;zBu$XYQT5E(aQAPX0e7B<
zyRnlQ<)KIh5Y1?%3wRnP{jlz_`(elSEvi@QPC!*vm0}E_Vdjb}uY(INyIQo+mDt8G
zYBmie{r$a6o-BA1F5xva=!c=e02`yz-wsC(4pR%+B3!P=3qG7D$R#R|9vp>FtcsqN
zfKPP|4)ntq4k!J6y^Jg~)=Bv(c)N1({!zNAD-?#&(ID1Y%!aVCk``+K)w%xFb+F;B
zm)U$mDP@cRkFOAJ{naB-*AQL&BCDiEhVb^kBdsma(cT8-)ic11>-+?KQE3Gfm6Rpz
zq!`DpqwNg10kpn33l<@Olluku^cJ?LX2mrm0sIgS8Taq{5^}xy;B>lKUD71yBoxp)
zv99jUBjCm1EcM~=p=NA*EmT&|1bk8$GcJLgeLI`rcMskH!vT6OQ)0>p0R-mNH{H#~
z-vm5Oj%fVsLn|sQDg~Rvj@FhV0z2Au%1imE@gpO{%<`#YHoF6I^SqFU;7u+WM>|K>
z*4FYZVC=vDq`_@98`WH2-j6UMEVd$!x;EkHRa@KFU6&Np}J&D=Xt9Xx^fe;gXgRPKDr#mzF1r0OoN*HPd7gX(GarMsmq`v0Fg7*{{m1&Cucr%1^&vP;
z=6M3_b+_>UxD9D$^D9nw^n+s$;h6W3dY5O}g$I#0ye(c($x
z%@#AWegd2&LNc$tG`G=tGU^6bT6@lCBL0vtJ`j0=l
zIPL@n5GCG$3dspgI%uITga8nkv^YoP458)HP?s!uXlM{+1SJH4q4lKz5@tn@p}a&W
zd7G9*gzeq=IkWuYvPuYGUHu3yt!EK2;y5If>qpPMZPjvSU{L}hcxPO%e!meDBY7FgKIuyMP#+)%DreEeLdaa_xG{CsiA}ZV^J$c_a%KL
zYmQB+&=b%zkSG^gp%+I&<&`sF#_UF@pR<5jJjo3Kz=Az>7D1x=h*g>glGT!2k>rrv
zk#}^V5ise)Hqoewq>I{4kD4Sy%E5zT57k#vRuwfKluNPnPz)L9KgLFD$w#nl^9Rt~(JpKBJZt@QAq^ym^pc7yW>j{E0}m(mw}{0N3dXd@PcfvU
zy%h$~u-<<8xrv24-6cp$Kr)xs19T=;3JYIC{GcTf%0sb-*80gZlU>IPz81Ms%A0Wl
zctKAF5U=MLxr?R;_=ZbRav%}wks>*e^de=-5>Q@Vu4y@1=m-z!JYJCsF^Z(%
z$jRtuz3VPPS_t3;-6-I-#sR&oUR+K_3D5#K59n%n^z;TJz&9iY2p*sn?5Qk8MuBe#
z0r*64%`rd=S!#Jxv3fO6`ky2~4M=IH)$*r$UhO&~!Oy4%q|#BIYt-_j>Jdf*FO;u)
z5H2k()ht206DuwGraJIbiU2h$)(iM-YQ51*5wr_JJM13xfc>%mD|)dOz_pByzAIKQ
z0wxf9*G}3`PbUKC22LX2ANU#fjF?ma=e1U~venLKO6wKs`3ec3SD4U#0KLE=<)^39
z4mjK4lzN7@D74Tm&^46
zl29kzs7?hO-fMXC8H{bx;;D_e$NWto5V#RZpdX%*^$Ra=P~3%8dxZ&AN^yYhe4=1X
zcQO^CC#=NnybEw^urBt!roQt6%9~G9<@#qH!tKff2>yn_!NGU2c-qJoz$fcZ>pf!B
zTp~$K0ue!hncl8M-XXlulZQ7b{92rqF`W67wRFK7RIOgjN-6|MSxuu1(fdGDZDmSl&;+{P
z1WajUrh4Pju->WOweLpzrU}S0PtycU6Od&DvRwUt0sR1!GaFTo#sB~S07*qoM6N<$
Eg1s&Kj{pDw
literal 0
HcmV?d00001
diff --git a/src/pt/slimeread/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/slimeread/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..919a41edd94ed81c0859496cb014f0227a994bc1
GIT binary patch
literal 9415
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
N002ovPDHLkV1kSZ$5sFU
literal 0
HcmV?d00001
diff --git a/src/pt/slimeread/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/slimeread/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..7ec1182ddec38c3389cbd63b34d2321dd59e5a0e
GIT binary patch
literal 11982
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
P)B$Np`A=oyhJODC!m-lS
literal 0
HcmV?d00001
diff --git a/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeRead.kt b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeRead.kt
new file mode 100644
index 000000000..8e6105a5a
--- /dev/null
+++ b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeRead.kt
@@ -0,0 +1,189 @@
+package eu.kanade.tachiyomi.extension.pt.slimeread
+
+import eu.kanade.tachiyomi.extension.pt.slimeread.dto.ChapterDto
+import eu.kanade.tachiyomi.extension.pt.slimeread.dto.LatestResponseDto
+import eu.kanade.tachiyomi.extension.pt.slimeread.dto.MangaInfoDto
+import eu.kanade.tachiyomi.extension.pt.slimeread.dto.PageListDto
+import eu.kanade.tachiyomi.extension.pt.slimeread.dto.PopularMangaDto
+import eu.kanade.tachiyomi.extension.pt.slimeread.dto.toSMangaList
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.network.asObservableSuccess
+import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
+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 kotlinx.serialization.json.Json
+import kotlinx.serialization.json.decodeFromStream
+import okhttp3.HttpUrl
+import okhttp3.HttpUrl.Companion.toHttpUrl
+import okhttp3.Request
+import okhttp3.Response
+import rx.Observable
+import uy.kohesive.injekt.injectLazy
+
+class SlimeRead : HttpSource() {
+
+ override val name = "SlimeRead"
+
+ override val baseUrl = "https://slimeread.com"
+
+ override val lang = "pt-BR"
+
+ override val supportsLatest = true
+
+ override val client by lazy {
+ network.client.newBuilder()
+ .rateLimitHost(baseUrl.toHttpUrl(), 2)
+ .rateLimitHost(API_URL.toHttpUrl(), 1)
+ .build()
+ }
+
+ override fun headersBuilder() = super.headersBuilder().add("Origin", baseUrl)
+
+ private val json: Json by injectLazy()
+
+ // ============================== Popular ===============================
+ override fun popularMangaRequest(page: Int) = GET("$API_URL/ranking/semana?nsfw=false", headers)
+
+ override fun popularMangaParse(response: Response): MangasPage {
+ val items = response.parseAs>()
+ val mangaList = items.toSMangaList()
+ return MangasPage(mangaList, false)
+ }
+
+ // =============================== Latest ===============================
+ override fun latestUpdatesRequest(page: Int) = GET("$API_URL/books?page=$page", headers)
+
+ override fun latestUpdatesParse(response: Response): MangasPage {
+ val dto = response.parseAs()
+ val mangaList = dto.data.toSMangaList()
+ val hasNextPage = dto.page < dto.pages
+ return MangasPage(mangaList, hasNextPage)
+ }
+
+ // =============================== Search ===============================
+ override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable {
+ return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
+ val id = query.removePrefix(PREFIX_SEARCH)
+ client.newCall(GET("$API_URL/book/$id", headers))
+ .asObservableSuccess()
+ .map(::searchMangaByIdParse)
+ } else {
+ super.fetchSearchManga(page, query, filters)
+ }
+ }
+
+ private fun searchMangaByIdParse(response: Response): MangasPage {
+ val details = mangaDetailsParse(response)
+ return MangasPage(listOf(details), false)
+ }
+
+ override fun getFilterList() = SlimeReadFilters.FILTER_LIST
+
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+ val params = SlimeReadFilters.getSearchParameters(filters)
+
+ val url = "$API_URL/book_search".toHttpUrl().newBuilder()
+ .addIfNotBlank("query", query)
+ .addIfNotBlank("genre[]", params.genre)
+ .addIfNotBlank("status", params.status)
+ .addIfNotBlank("searchMethod", params.searchMethod)
+ .apply {
+ params.categories.forEach {
+ addQueryParameter("categories[]", it)
+ }
+ }.build()
+
+ return GET(url, headers)
+ }
+
+ override fun searchMangaParse(response: Response) = popularMangaParse(response)
+
+ // =========================== Manga Details ============================
+ override fun getMangaUrl(manga: SManga) = baseUrl + manga.url.replace("/book/", "/manga/")
+
+ override fun mangaDetailsRequest(manga: SManga) = GET(API_URL + manga.url, headers)
+
+ override fun mangaDetailsParse(response: Response) = SManga.create().apply {
+ val info = response.parseAs()
+ thumbnail_url = info.thumbnail_url
+ title = info.name
+ description = info.description
+ genre = info.categories.joinToString()
+ status = when (info.status) {
+ 1 -> SManga.ONGOING
+ 2 -> SManga.COMPLETED
+ 3, 4 -> SManga.CANCELLED
+ 5 -> SManga.ON_HIATUS
+ else -> SManga.UNKNOWN
+ }
+ }
+
+ // ============================== Chapters ==============================
+ override fun chapterListRequest(manga: SManga) =
+ GET("$API_URL/book_cap_units_all?manga_id=${manga.url.substringAfterLast("/")}", headers)
+
+ override fun chapterListParse(response: Response): List {
+ val items = response.parseAs>()
+ val mangaId = response.request.url.queryParameter("manga_id")!!
+ return items.map {
+ SChapter.create().apply {
+ name = "Cap " + parseChapterNumber(it.number)
+ chapter_number = it.number
+ scanlator = it.scan?.scan_name
+ url = "/book_cap_units?manga_id=$mangaId&cap=${it.number}"
+ }
+ }.reversed()
+ }
+
+ private fun parseChapterNumber(number: Float): String {
+ val cap = number + 1F
+ val num = "%.2f".format(cap)
+ .let { if (cap < 10F) "0$it" else it }
+ .replace(",00", "")
+ .replace(",", ".")
+ return num
+ }
+
+ override fun getChapterUrl(chapter: SChapter): String {
+ val url = "$baseUrl${chapter.url}".toHttpUrl()
+ val id = url.queryParameter("manga_id")!!
+ val cap = url.queryParameter("cap")!!.toFloat()
+ val num = parseChapterNumber(cap)
+ return "$baseUrl/ler/$id/cap-$num"
+ }
+
+ // =============================== Pages ================================
+ override fun pageListRequest(chapter: SChapter) = GET(API_URL + chapter.url, headers)
+
+ override fun pageListParse(response: Response): List {
+ val pages = response.parseAs>().flatMap { it.pages }
+
+ return pages.mapIndexed { index, item ->
+ Page(index, "", item.url)
+ }
+ }
+
+ override fun imageUrlParse(response: Response): String {
+ throw UnsupportedOperationException()
+ }
+
+ // ============================= Utilities ==============================
+ private inline fun Response.parseAs(): T = use {
+ json.decodeFromStream(it.body.byteStream())
+ }
+
+ private fun HttpUrl.Builder.addIfNotBlank(query: String, value: String): HttpUrl.Builder {
+ if (value.isNotBlank()) addQueryParameter(query, value)
+ return this
+ }
+
+ companion object {
+ const val PREFIX_SEARCH = "id:"
+
+ private const val API_URL = "https://ai3.slimeread.com:8443"
+ }
+}
diff --git a/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadFilters.kt b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadFilters.kt
new file mode 100644
index 000000000..019bf954d
--- /dev/null
+++ b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadFilters.kt
@@ -0,0 +1,141 @@
+package eu.kanade.tachiyomi.extension.pt.slimeread
+
+import eu.kanade.tachiyomi.source.model.Filter
+import eu.kanade.tachiyomi.source.model.FilterList
+
+object SlimeReadFilters {
+ open class SelectFilter(
+ displayName: String,
+ val vals: Array>,
+ ) : Filter.Select(
+ displayName,
+ vals.map { it.first }.toTypedArray(),
+ ) {
+ val selected get() = vals[state].second
+ }
+
+ private inline fun FilterList.getSelected(): String {
+ return (first { it is R } as SelectFilter).selected
+ }
+
+ open class CheckBoxFilterList(name: String, val pairs: Array>) :
+ Filter.Group(name, pairs.map { CheckBoxVal(it.first) })
+
+ private class CheckBoxVal(name: String) : Filter.CheckBox(name, false)
+
+ private inline fun FilterList.parseCheckbox(
+ options: Array>,
+ ): Sequence {
+ return (first { it is R } as CheckBoxFilterList).state
+ .asSequence()
+ .filter { it.state }
+ .map { checkbox -> options.find { it.first == checkbox.name }!!.second }
+ }
+
+ internal class CategoriesFilter : CheckBoxFilterList("Categorias", SlimeReadFiltersData.CATEGORIES)
+
+ internal class GenreFilter : SelectFilter("Gênero", SlimeReadFiltersData.GENRES)
+ internal class SearchMethodFilter : SelectFilter("Método de busca", SlimeReadFiltersData.SEARCH_METHODS)
+ internal class StatusFilter : SelectFilter("Status", SlimeReadFiltersData.STATUS)
+
+ val FILTER_LIST get() = FilterList(
+ CategoriesFilter(),
+ GenreFilter(),
+ SearchMethodFilter(),
+ StatusFilter(),
+ )
+
+ data class FilterSearchParams(
+ val categories: Sequence = emptySequence(),
+ val genre: String = "",
+ val searchMethod: String = "",
+ val status: String = "",
+ )
+
+ internal fun getSearchParameters(filters: FilterList): FilterSearchParams {
+ if (filters.isEmpty()) return FilterSearchParams()
+
+ return FilterSearchParams(
+ filters.parseCheckbox(SlimeReadFiltersData.CATEGORIES),
+ filters.getSelected(),
+ filters.getSelected(),
+ filters.getSelected(),
+ )
+ }
+
+ private object SlimeReadFiltersData {
+ val CATEGORIES = arrayOf(
+ Pair("Adulto", "125"),
+ Pair("Artes Marciais", "117"),
+ Pair("Avant Garde", "154"),
+ Pair("Aventura", "112"),
+ Pair("Ação", "146"),
+ Pair("Comédia", "147"),
+ Pair("Culinária", "126"),
+ Pair("Doujinshi", "113"),
+ Pair("Drama", "148"),
+ Pair("Ecchi", "127"),
+ Pair("Erotico", "152"),
+ Pair("Esporte", "135"),
+ Pair("Fantasia", "114"),
+ Pair("Ficção Científica", "120"),
+ Pair("Filosofico", "150"),
+ Pair("Harém", "128"),
+ Pair("Histórico", "115"),
+ Pair("Isekai", "129"),
+ Pair("Josei", "116"),
+ Pair("Mecha", "130"),
+ Pair("Militar", "149"),
+ Pair("Mistério", "142"),
+ Pair("Médico", "118"),
+ Pair("One-shot", "131"),
+ Pair("Premiado", "155"),
+ Pair("Psicológico", "119"),
+ Pair("Romance", "141"),
+ Pair("Seinen", "140"),
+ Pair("Shoujo", "133"),
+ Pair("Shoujo-ai", "121"),
+ Pair("Shounen", "139"),
+ Pair("Shounen-ai", "134"),
+ Pair("Slice-of-life", "122"),
+ Pair("Sobrenatural", "123"),
+ Pair("Sugestivo", "153"),
+ Pair("Terror", "144"),
+ Pair("Thriller", "151"),
+ Pair("Tragédia", "137"),
+ Pair("Vida Escolar", "132"),
+ Pair("Yaoi", "124"),
+ Pair("Yuri", "136"),
+ )
+
+ private val SELECT = Pair("Selecione", "")
+
+ val GENRES = arrayOf(
+ SELECT,
+ Pair("Manga", "29"),
+ Pair("Light Novel", "34"),
+ Pair("Manhua", "31"),
+ Pair("Manhwa", "30"),
+ Pair("Novel", "33"),
+ Pair("Webcomic", "35"),
+ Pair("Webnovel", "36"),
+ Pair("Webtoon", "32"),
+ Pair("4-Koma", "37"),
+ )
+
+ val SEARCH_METHODS = arrayOf(
+ SELECT,
+ Pair("Preciso", "0"),
+ Pair("Geral", "1"),
+ )
+
+ val STATUS = arrayOf(
+ SELECT,
+ Pair("Em andamento", "1"),
+ Pair("Completo", "2"),
+ Pair("Dropado", "3"),
+ Pair("Cancelado", "4"),
+ Pair("Hiato", "5"),
+ )
+ }
+}
diff --git a/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadUrlActivity.kt b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadUrlActivity.kt
new file mode 100644
index 000000000..3e1241c75
--- /dev/null
+++ b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/SlimeReadUrlActivity.kt
@@ -0,0 +1,41 @@
+package eu.kanade.tachiyomi.extension.pt.slimeread
+
+import android.app.Activity
+import android.content.ActivityNotFoundException
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import kotlin.system.exitProcess
+
+/**
+ * Springboard that accepts https://slimeread.com/manga// intents
+ * and redirects them to the main Tachiyomi process.
+ */
+class SlimeReadUrlActivity : Activity() {
+
+ private val tag = javaClass.simpleName
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val pathSegments = intent?.data?.pathSegments
+ if (pathSegments != null && pathSegments.size > 1) {
+ val item = pathSegments[1]
+ val mainIntent = Intent().apply {
+ action = "eu.kanade.tachiyomi.SEARCH"
+ putExtra("query", "${SlimeRead.PREFIX_SEARCH}$item")
+ putExtra("filter", packageName)
+ }
+
+ try {
+ startActivity(mainIntent)
+ } catch (e: ActivityNotFoundException) {
+ Log.e(tag, e.toString())
+ }
+ } else {
+ Log.e(tag, "could not parse uri from intent $intent")
+ }
+
+ finish()
+ exitProcess(0)
+ }
+}
diff --git a/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/dto/SlimeReadDto.kt b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/dto/SlimeReadDto.kt
new file mode 100644
index 000000000..17cebaa73
--- /dev/null
+++ b/src/pt/slimeread/src/eu/kanade/tachiyomi/extension/pt/slimeread/dto/SlimeReadDto.kt
@@ -0,0 +1,72 @@
+package eu.kanade.tachiyomi.extension.pt.slimeread.dto
+
+import eu.kanade.tachiyomi.source.model.SManga
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class PopularMangaDto(
+ @SerialName("book_image") val thumbnail_url: String?,
+ @SerialName("book_id") val id: Int,
+ @SerialName("book_name_original") val name: String,
+)
+
+@Serializable
+data class LatestResponseDto(
+ val pages: Int,
+ val page: Int,
+ val data: List,
+)
+
+fun List.toSMangaList(): List = map { item ->
+ SManga.create().apply {
+ thumbnail_url = item.thumbnail_url
+ title = item.name
+ url = "/book/${item.id}"
+ }
+}
+
+@Serializable
+data class MangaInfoDto(
+ @SerialName("book_image") val thumbnail_url: String?,
+ @SerialName("book_name_original") val name: String,
+ @SerialName("book_status") val status: Int,
+ @SerialName("book_synopsis") val description: String?,
+ @SerialName("book_categories") private val _categories: List,
+) {
+ @Serializable
+ data class CategoryDto(val categories: CatDto)
+
+ @Serializable
+ data class CatDto(@SerialName("cat_name_ptBR") val name: String)
+
+ val categories = _categories.map { it.categories.name }
+}
+
+@Serializable
+data class ChapterDto(
+ @SerialName("btc_cap") val number: Float,
+ val scan: ScanDto?,
+) {
+ @Serializable
+ data class ScanDto(val scan_name: String?)
+}
+
+@Serializable
+data class PageListDto(@SerialName("book_temp_cap_unit") val pages: List)
+
+@Serializable
+data class PageDto(
+ @SerialName("btcu_image") private val path: String,
+ @SerialName("btcu_provider_host") private val hostId: Int,
+) {
+ val url by lazy {
+ val baseUrl = when (hostId) {
+ 2 -> "https://cdn.slimeread.com/"
+ 5 -> "https://black.slimeread.com/"
+ else -> "https://objects.slimeread.com/"
+ }
+
+ baseUrl + path
+ }
+}