From 5b33d95e03dc7a1da7ffee6b895f2dc6c405a29f Mon Sep 17 00:00:00 2001 From: Cuong-Tran Date: Sat, 18 Jan 2025 00:00:09 +0700 Subject: [PATCH] feat: add Anizone (#557) * feat: add AniZone * fix episode number parsing --- src/all/anizone/build.gradle | 11 + .../anizone/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3892 bytes .../anizone/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2217 bytes .../anizone/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4874 bytes .../anizone/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 8066 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10034 bytes .../animeextension/all/anizone/AniZone.kt | 513 ++++++++++++++++++ .../animeextension/all/anizone/LivewireDto.kt | 19 + 8 files changed, 543 insertions(+) create mode 100644 src/all/anizone/build.gradle create mode 100644 src/all/anizone/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/all/anizone/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/all/anizone/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/all/anizone/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/all/anizone/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/all/anizone/src/eu/kanade/tachiyomi/animeextension/all/anizone/AniZone.kt create mode 100644 src/all/anizone/src/eu/kanade/tachiyomi/animeextension/all/anizone/LivewireDto.kt diff --git a/src/all/anizone/build.gradle b/src/all/anizone/build.gradle new file mode 100644 index 00000000..9eb77b0c --- /dev/null +++ b/src/all/anizone/build.gradle @@ -0,0 +1,11 @@ +ext { + extName = 'AniZone' + extClass = '.AniZone' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" + +dependencies { + implementation(project(":lib:playlist-utils")) +} diff --git a/src/all/anizone/res/mipmap-hdpi/ic_launcher.png b/src/all/anizone/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..30ff4ee895110eb610480f27fe3013b1814a6af4 GIT binary patch literal 3892 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 literal 0 HcmV?d00001 diff --git a/src/all/anizone/res/mipmap-xhdpi/ic_launcher.png b/src/all/anizone/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..79cd46eeb55c03539dd404e001abe277d2cf69ac GIT binary patch literal 4874 zcmV+l6ZPzgP)qfdlS4j^|Wu~c_X6An1-e;e)_S);U=j=0w-<|dQ?WS|~dVK5u|Gsa1>#_GqfbtYq z1QO!fdU@kePC%TMpqzkm0^*E7oSQGVfN}!jj6j^5FSmfdF#!&FUJ^^NS8=Cy3<^P) zY4V#tTrc(3N$mfP8ukkl<)2tU9P=!tdeG)-xh z*{64ILD9`ej~1U%TmsdpJx`1L7bTG|tpD+!J!-_{=ep`@4exoHV!z?;mxS7-j@xpm z)Yn~e3Bk+CiFG9;CLBmkO4w34HF4&)O&`ttW!>`J5D{E%u{xO&K;S2}y=vfziRtxb z?aRq)dE{sjV|N?`{6_|C8+)!}oNS)^s`_|E?&k86_TJnf z1kn8oc%?SW9Q{##LGgJ`QGwSN4n10}<3tP8{n(6zlS&re()iBkED^`Tuob6PO#Jqj z6;E7(4Ik23fsO$3{mFP$J)_g8twqHp)p#w7^v+9iOu<)Ze=(w-h;T?j6Sxs`0_@>i zr6?7W5{~Tn{K>kQkp^V40_j+wBY@mb3SQMt?>K5FH7eA6PSdQ98gmyEQFcmPr<-(M zHd_Sx$L^+kY%%x$RF>6not09XyH-s+4vWz^a0IVN#KP&R2?3R`OnRd$Mr`-$c<38J z)T<-F8>P}WWN;B>QJQ@TYB=LxJm7N-YvnN+fSv9ZVP+E5`Rs{9N?`Y@i6`Lg19%;d zh5+*a4gnNe@hT_eMAumk8;^F{Chpb^oz{u9p9P86c*#7&md4dDo&PVfCI~hojvPop zJ^Z+T3=)7BMMJ`*vj8~(0AE!>g9F8FK9s$zz`iG&mjQskOc%tfCPB* zv$iH^fD`C}R=fRz?9mX-T^YQM+@1!n=5kMNEG z0+-`JCz|n!_!Db?WH8oR2k);1EXOkbcUwSYBnsXIg$RfYH)8EI)qE$PyFRaf3WFDl zCS@icAzo)a?r6(A{9p{JvdY2Of7{uHc_wuKjxJ%F&2C9$>!H~0z_CYA)8df9Nn7=V+0E?#GK)a&!b z`MqvHZR+e`=W0)DL9ru%w~oLqKtzDjA{1`N*zbqx5EA5jvLptdokIB|Q|%68Mt}-* zavknP55`@HP~`l+y>#QX8{NQbHhz#S@?{Q4u$+82>Bo{XCg7AyhY7<_wac;Z%1GmV zw%Bh+Kk)MP>LMRCp>{aN)*%|4_k3wDMc@_8Ojt#LVtytCU+7jy3z^BZk?Ubb`cR~* zT@JB^E!U*o?=ps3DM;=zAwUJZO!F&Ost65Es9|XlYx5#2*}82H94?3~qllKm^{&F- zz-#8t7*`eYTl}~dQvyl@ywkCsom;}AgRgO`kmS?YDGTAXcUIbN%pm5ce2ZVY8_sM* zE5WfzJNN8|=3TPFmCNP^ffI1DYYcE}uOp3mo?z#iF`+NCIrkI^I;1JMt#l(=Dx1UAQHq`~UB!yqxi zbp|5jj=V@6K2iuRyFUsC^YT46Wv+(^C@TvPYJUib7+Zjihf3oem%}30<ooZ^FW58(d{n6Sue%5Rx=-0!~5~bf?cNXPbj{MP3k6Obeh;LJEI&+VpuY55HvoS4wQM* zw7H+bxGCPjFG2__i>Lw1K(og6;JxSjOEqlpV{_o055KkU zU(ozym_6}!Y2K^*O@X!FJJGP|?wVNhNipW5T+Pp@FKw@&@F-+ro9n;d?o0b)Lcoa^ zKjeQNfRc2&`Rls?9q^n;E2+s*FT1duYF|ew86%Wqy27+ zu|M_e*$zexxJn8>-IzLi1&nz%JM;jFza{Iy#{ixH*K(YDGs)GdWiy7rN%d+9JNm=V zzr*EypLR{KUVH2o>1=t&uKjR9&+#5NWD_E4LahDA)v69FaNre93Y}VL#@nXn1UPiK zKb0-c00e`KV%5u>i9t2X;~J&s_(6VTpvK|0VK0cf%^sCNe#+~+bW z0sk0213p~&o$LO|Xf4ZT-X|?HdB#$hFztizeUIi_B*?+PqD>QcZTziD*RyCj#{9#k zTX}SoE|K=rcYzboAVh#taz_+dL-dHZA=9F^N)tij2biW9;WZ{81e>tqP(wxv7pXFjyQ`AOKh`+yPn30S%4 z@s~0sAgm=!r%$P03zkkFBIRr4w?9J9!PCOeRk4F=);(Qu;BGA}Ta3MJd*kEqGp@^c z%~7KHA?6>sx2rhJWm+0GaUQ(-_R3Pb9!n-vxL^rLh4cok+)i;3G=)+dmi%Llw*AVNkMP7+`f;mIgjN8@Bysho5{(OiX||Pu~H_ z$@F}Px3w>Ea@2jmRHm33dMw5-;6zusV=c_ZKeT0C$X-DazUKZi|3gcsLhN zS7P4iA5(Q)kje~cpj$tGBt}2t)l3qa_EqiZMW3oxsRWB~z221=R`c=;;q0r&z@dD4 z9YZ9YeOg_357(elD%x&Pl>WVChqVw$;U}Ad0H5j$+yd&hr9oJo!V@S-wwwcb(DdqY z;ekxQzl_TgIGaAL;jz+&?;JT3vO@>ANI59xpYzO}aDKCf(lP{kXI##R>@C9uUJut@*+N?9tnAfrKOWq&EEARahA!v9#D^rO z??RCmEj81E8=p*H!7~>Ri>(W942eaHfd$-$7J%Uv7d|>Ji5B11q5G+kUWJn=Qef5`KVj-<4Txqh?gr7H~ZTu5Cby{dIuLV92di_(06PE4GD ztDI}z9UdL>2BqUdzzG-K?->IuEeWa0W4MWOGis|W(f(@VPNOh>X9EKD?gDugvaD|q z)H=9}C5x!$yuStp;l}>|2?5^Vk`~Wa&m9iO*0NrxB}^ZDz6tu`!6rNDw{_TYg2omn zv=voOTa_)lXIW=^*1S8yl_kmvx3DjN2@7BWYTdjcygj*}(s*g>aq8^lS_2mi(AVQ2 zJZaeV%CcSiKM%kDz7MU%O@Ow+Qe=n=0mrwAxS(S6(}|(*nf|oEqaE_KA6whAKUoj| z*|uBST~%a6o9H)O6@Fi!u#PX+{RFgIcE|Ph`BKwYt2veFZ8FmAVvL|R{rH=by1)lv zmH@rdn0H4AJmcj|9(&^Dk%4a%=SMqzkI9Z0Zpa7;(40b05v7|8=oY?Y7qI3V~-v(jb7hT$D}&lx*nDBnAY~M9hCu_f!8WgRqZQkmu3*kY!5A ziVA!=2JB(AxDw!}elAG@R2E;@&Fi`y(+NsBZmrW@rxPM?35V+rR}6nF?A>J{)$@9 zQW6saN(;70C>hRUuuvy@(UWeR@#RgT^#9aW-~=3d!H^it10t}vHC~K>vDWM7Nxt~- zW_B8oHxv{Bw7X76%F^q!zURAygrurE$#t%UEiaou@onhpjMg%Bee!$1sJQ4z&exOa zojg&$vWy6z{k`hPwd$W;l9YOmUvNai>-@W^%ZexP);s=W%ST1|oA<7n+5!6!_3sB* zKi~stQ2m(t-TEh|pET01Hu&-Flvk(ib{=u;V>DqZZ3ldmE6Uw5A!pN^NmwN6U(j%V zL#7I(q|~h0bsBZ`Hs%KkoME7zLdWuX0ixwyCHmx7q6<2T)k%X`mL|4P^C^LBvovPo95n^ z{Ai@M^w>a|?R*9qjZyNKQLjFhfceEm1>1}B_btue{>Ajd{C&GZ;L}f7Mg2Qs)B=&@ zkU*A@79xWNXR;151rs9u_1-c%@4MoBRub#%q#eW)X*oSyK%kS`A;FzrPf}`-DR2%6 z^d=;F)Rx* zQ*kR`Axx_yphcHa`O*-;R_w2Q%$Ep^`W()rh`an6wvo1rr1J-$zy6iyHb9`900WR> wnWdb7SfXoCcR2wDAjL9EIRUXm*P!nI0i`IA2FXvgnE(I)07*qoM6N<$f&tESnE(I) literal 0 HcmV?d00001 diff --git a/src/all/anizone/res/mipmap-xxhdpi/ic_launcher.png b/src/all/anizone/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..47d0a46c3124af54e40d796ddf1be7e01c064c0f GIT binary patch literal 8066 zcmV-|AAR77P)igznnW?Vu>Q}$_>eZ|21c;}& z1Z+qk!N#-kN8=KJIDq0HuqA;wfNY5`{%{;XaSYg!Kpa4}#20@!4xl&&Y)K#vAY0;# zKO6^890Rr_5C@Pg@x>pG11OFGTM~#RfCzP!vCbsg>QMaQpaguekOg5-Ej1%r=)$NYzwQDtNmYSY^EhMG% zNPvWfjErhxne}a#R%K~bM&%b4cgrs*_eeDXxMIY`}B38$Z-Zrz=MO6kO0ZaiIAF-43#s|@++k$f0S5SIQPr99@)fx zE)5jKnMoN$Rsp03PjdHx)2=V@rA<4So!hLqq%=Vr@dy;t;FRirCYK$(?dvtOk%@`} zY{cy%G80(=P*821)22(UnoT;)I+j<`yQH*KSe7AxjEokImW_m^X#W_NBbE==D^*{C z3`YGDRcY9tGR;N_C1gXn*awilZApm%#ziJ}G|uDX(teOh(8 zyKO@CQ{T?XFRmeS|GCLNex{)do#&MTNaF%}x#sO4*igZtq}NI9cct`{!ZhE}n|G{V zu%1;@6ks7GRi?^7oPCm6WohkuPJSdiH(`{|hjoS)Wd%H{!Zs#$HSieK>xB9$FFO>P z)Ilz%0_OpQW!I^exOn?V{}|8yEDWeJZV!=I$O?dveNx#c{h}UIzc`*>+9JFrx51;z zKG6h_vN~2!VOH#)@XexXl~RA*xo-NUOa}R3EaW(V^y({(m0s!G?vuBbltMjyO;*9< zHTLnhCsKxn>dSx*odFP?eN-j`_9Zzf@x;CjGtXep{X=9mroup&7ug5ZS2_Zy zMfZpHqOZp$|YHsZ8pMV1?AYBn1C>iVqlL7rie{P)Bh?Sqq zJ_YQ907Cx|VL&6+0H&-%txk2cX6}0P)qB;|#=CU}!*Runz(#%M?J8 zCK&DyX#;5du+cB(<%wG=dM4W7K~@TPduV+UcFaD2g#BR+@Sz`yCB{IR0RW*P%^ApV zn@Exh18I9+?1L)I96$u@It?C6Y@$gv-1Fll_Ax}2*uYotdzF{$i#dR_B|Jb4#y}&) z3>0I+qce)r8>o77#ybEa07u3wvfs_B zaLRD@w?S+%y5l@lvwu`4k~aW!jbs%T7!Mp|y<1FMg6M2~D=RKjCJEMS00R70vZg1;T*;0bpeoD9Y@ zSMZ)tVWGe=K4B^Y7{w+xDnk(97c_zl>!qx`!b~Yu@Tf9`*!E#usGu5+*iEz`a1}r@ zKv0a`U>>o}8}hC4sw;qH6(cj8eZrfi3Lw?G&5Y+TGf-=qO8K4w&>8AyFqS(MjR)tJiUs1N|60>=sP$k<0k zxaD@3Nf?Qud%zG_hK9RSE(5VW;8_5vfQAYjvsoP+Y!lrVEAXhYk2&Z=JH(x;>S~j& zzOd|rn`0Xf6m%pu@BARih}L(9V(&x?JW|FoavGYT-if7kz)};^h7;iNH{Y1uVhEr% zETHV$FaSjcWQim}1&-IiV+OitgU4FkYV3o#V+bHEB2kHfoCJ=PLCnHn&D5RA0R)pG z9dYbA$v#H%k)0&*B!E)?CceZH$Pkqq7Y=XGXKq{c&aY59T8=r+2 zwakQ!%tShVV2Fm3+(+BbH<1wi5b z^E7}o(1cGalSw8TylXCR0Sg|!&6;Gxo*MShGWg(&{|Zin`7=_$6I}+f*3FX=Kvc#N zsVx3oVqyX;U`0Vv9s@P`9PZu^vrfHM%gyf~j- zUL5t4sR2JwdX;9K$7YE}LKQe>Grw_zTCi;9V8B(F6Y1xy{m^sd0yusG!+%-Q`9W2d z&0bSs>~>t36j+66@)X!V*ww&k<`7Z3uEMMUMy4)!53lRg5*{CWBUGt`R}vW~zouko z&e?S(X6Zy;Av`#HHN3NKE9oj)@BnO+0X(VRRO^~efX`{fVH3k25y)by$eSxWbN z1V+|ORpDES;71nS02}Vy_2}h6Tk&Wi?LeD*;0n}xy!|-J46EpK(vw~9C9nQVFwS_Jn z&IO!2)RcWJ7rNgy7qa#oR%Ra!Ks(rO{87ChXex8pPmS8`9KpS?rbGZy8HWputBf}1 zHHKyXxD(RT@Inytw0PA9*v_^pW>2_9%2qkK1YRqYFRy8L<}vxU4mZr zm2>Wb%!YMj-3|VpUr+>NpI8N}+2TM`w-$~e9s262O!jE(9f>jkSp^Q4&Y+%`!=&NY zGC;`XIeOX(_~YPlc;!i&w|eFaYhmsyp9%|h9z6b`HA*O_B*s2VA0G%;w?A7t0rcg( z``I?QZ~7{>C@8SRKG;{!0Z0`%ns~z=N=Z(FwM*`W%tp1P=*i13f}2LphoYh~c>U=i zP^V@U<7Wa!$iIKs4L1y*uM8k{=8=O3?YkSVX$8+r>a7Hx!$(iRu!mlSe|^2vGW+0z zF$B;M7S8c}hzhd;7X7G&42aIcyySu=u;Qs9Qt)7gufNZNyO|)_ZTax@#NKe_#b-*N z%VX4k&7e7vo2!oQvdh7PInKze3rnZp4oy!xMcQtChWX1sgC`e#1OfmHinfoQ^<&6D_5maV z4t5N8++UwF6k47wUwxIZYldgBCHaCC>j9VOH(YfgOuz3&s4VdtVLjjfya#R_vk1^P z($At$#GZW*-zw*L6Lsp|5BL|m-Czn%vW1vL6@Ue>xf%$?lZ zFnCO#7d^`3o_qs7`qy^t>y~FWgcq1GTDLa4OIDH&9L|BklU@e2hm4Y)BSo_7S*lmf zfF-Q0?OHXHH8uEqX&JNg-v0(B&-teYd_TttP=c3eM#jzs%c&3mQU#9Bmk7w>!~0zc zqX%{-?Y?L2Jq$Oq*?2HJM-xtZY6`rw;2t=uNqy;{_}ObM%wO(jukgg%FLM6L{aNy; z#4!V}hH-huiS+z?>%WKbjKR=1WCS2lLFS7GxxIA$Sq)+76L$c6 zZx^YZmG3fh=`OIOU#JYrwf?pdiDI_jLqam=`LoB_8Gev_8mAHQigTaB?nK{%IWafy*=P2wsfbo zkvHtq%{$t1y*-R)4e2W^XUH6)|IcPqIJcssXbAS0s8S ztDKPv-@G*u-w`UsH_qz86JLULn|A2Rkb^*6u(>RFzq_(n>UmT8LPomW!_Mp3f9N<2 z`1_Ke_uL89#mjaPKmi64-8mwVFvVvy|DnFnz2o`PfyWF#{IU_>p9=yQzz(jJn==@Bk3I}U%E0!f($+ho2 zL)%;pNjgMYwR!a5LGSuQBd&)*H(w@eQpoTB-MJTrPF@DT?)EdS9|m$GU0;aV#BiU1 z!o)#g8j%Et_Pzop4DCh|E_*vP^kW;Mo45T>n7>iIn#_}Z7o5%l(qsvRi=ON?>;EIn zstr|OyaadTn-;H^1@5xXexMiBtWNj&VBte1zrx~|wgq5gO}%;uK=s&G#(t!TDtZR8 z3K}kboSiStxC7d^rujtn?mr5>#w>*2|2QHXz#7cQGUvft;VR-ujt$@b0{zFo00_*` znJa}~M23)?W&`7mj>2aq_fa}of`h*5!*5~Kqbq`SSW#cHm9c9K)VQO~RhTxh{St0e zzb3rOLRT{z$~R9Dtgo&43La+L5EwuuN*GTwW&jIDV_O@Pl@6}LkkNMjcA$K)r0WBk z(Tsq)?S@O?(J?oWR4Q)(s;oOEyr}tnFroEhw63IhoQK{JqF1?%KG@?n;QYW&sLa6)4T-L;7tGt;BF*@3>Gl<@TkARt=%t@ z=?m?5G^h5pei- zsoJLO5NLC5W763D@arEikoj8n9XMu^pQg63092zlc5Vfav&~&}9#T_5Q8Dx$^E_R%wp*hl5&R?h>73L1S!&SCpjZ$EbrNqymS?|iyVGc57EyCz^0n(lk;#W3UVJxODS zo0B))^Binv{v~mug9o2S)rA|o7q&Q!eD(nMFY+m^Qq!9c;*rvyrZ|S+^p9}D#1|Brr`!mBCw=DDl z^0M=V-){d++pfS!0U7g{%?gU`<2ry&?|6R}X=(KYfV5o$@Of~S}6PH}r1Xi+$N{Sa@boM)kyQYx zfCuY#je)EJNUw3uXYo7lF!iMpjb|6Mvgh&S>gKJxq`>j3&&bm1)T*Mz`LsPRQ&v^T z@87V{+}`&F0^B5#j79~kf~P_OC|uY`?enJefonUqR1$QwGcS7m3z+&0hPtXV5B6!` zjqPDFJ58cLj-=nG6Se=(L&xB6!=7a^+DC}YBYIh|)b}71oo5+HzXc#_Ij+9md}bJF zyTK}GgaaoTO*EqWj$H(J+SPcbi+{lY`RAtggBH!%RRzR^*X~Vx>TS)hC9@~(I1Gc$ z(Hmk+7KgUDbS_M!!U%q=z|2m7%h>q3? zGQ#xdKY)cRzKB@qnf3Pu7Db8dqmqs=r|7sDs{kV-t%j1=0Z-5ds>)8L=EV4og{NIf zU4=#J47_di85TI-q3sze@{U>F57{MDc#jaC_$;60#??1r@jZCq0-l*yNlV}S5+<<# zc|6mmsxJMkWXvIJ=2!K~<(-MZ$b{jkw@M;z-;Hhu`V&_DYp4VM8&H+RWNDP@R$UJy)g32uvv|({B z7hYPh^1UslA-GuEd1qjN{OwAYU||%&$VZpMyPt|3LeoOwv-;U# z(5eM(j|zo_n~Qj)#ZJPA#}2KT%9O|2Yt`UoO}F2_)U-RKJ5BJ~xSX(s>b*1qcE^?3q7D!RCN<5M*6b0Xo?1eaCU!E@j@wuu^^WUc~z{;Dig z_UktuBnRvlv9OWL`#cGI{uBqT;UG>LejN;9k(4So$l`6WgD1WWU;W3wSsKwN2{u$@ zO_^}60jSXxf6t;cFf>mY4C>iI3*Vq7JT%z0=QMT$S>&BZ^oi&nm3J46gx2StPOTd7 z8kpHjKMu*y2k`8s^%?sNQu1Tr1~8uM!VOcSBK{idcx4|Fyc1ap+juo=U@LEJh9l9b+dz4x4zmsqGTw+r#3-M?Aco zU9@Eu&lLG&g#i!_K%Z+bf=9;m0E|MUBn<8R+uifD>+4KY#8OafNSxKA9;{h73M#R~ zhm?dt_D?XU;sO@p!Q+qc;NmAQja9mej#8K1JXw1W!A&EcGdyTuRKDi`WJI%gZOg=A z*TNk=+mj91A9ww!T_!-ARq~Yy9;ul(r61`MDlYKlYqn^2Fy|Ne1NhHwc4}Y|K)8F) zE-DnBudo238g+O^3uzxuU{Dg8%EPocg;O%=&XMyfM z2B3!84YFQKstm;2?`a0&Grz~x7r;ElP=_tsvf$Qx7eW!ckwO+7C>l(&CI8at1KEx6 zYOk!kdDKGK@XbzkcViqtT;7f_5XCq1)PudCSJ$>moVVh=ueDeis*#SJqO=9`4P!UJ zP8o4s5O)M0pmv84?v0((yuQl}ByMemW1t3?(~W3cdC`0?AVMZP z*HoAafMlJpqN2>~9JBhUj7DKI*{}!8Fo}7gwnrvIT3AhFt_lhuHDfqjc$C47e1=vh zrED2+sOr=y@W{Yr_Im{Z5N+^ef}jkpRp5{Zop3KCrJY^?5BAx^0CEO2)Pc1F9BLh| zGmq?Sv}^_nes>W--Y|%)tU>_Dh73b`Y;_h>>vvLJd6{+eLiHqor~^i& z;%EcMX)5Vc11=jeeG+6}Q|%2J;ceO&6Wpg-YF00r7_Nw_9`j|7c;MyjYP6?G+4Ssnp~ zidpU{0I36pOWZlzCdeQb7>7P@z3UiM=>z6<4M6qV-Od>S|eSNMplc;#z#Z(vrhl<~C<7#w%&_ z*$0o`Mjb%f3+EbKI($u8Vg~I6r|bchK{FcyRil`fg)>0#dU(^(7K4W}q>Ii2QP#y3IK>iw^kSkZ$;1mRIhdaNeSt7+0A$2

0nDn!vJ*0+k% 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 literal 0 HcmV?d00001 diff --git a/src/all/anizone/src/eu/kanade/tachiyomi/animeextension/all/anizone/AniZone.kt b/src/all/anizone/src/eu/kanade/tachiyomi/animeextension/all/anizone/AniZone.kt new file mode 100644 index 00000000..863b450b --- /dev/null +++ b/src/all/anizone/src/eu/kanade/tachiyomi/animeextension/all/anizone/AniZone.kt @@ -0,0 +1,513 @@ +package eu.kanade.tachiyomi.animeextension.all.anizone + +import android.app.Application +import android.content.SharedPreferences +import androidx.preference.ListPreference +import androidx.preference.PreferenceScreen +import androidx.preference.SwitchPreferenceCompat +import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource +import eu.kanade.tachiyomi.animesource.model.AnimeFilter +import eu.kanade.tachiyomi.animesource.model.AnimeFilterList +import eu.kanade.tachiyomi.animesource.model.AnimesPage +import eu.kanade.tachiyomi.animesource.model.SAnime +import eu.kanade.tachiyomi.animesource.model.SEpisode +import eu.kanade.tachiyomi.animesource.model.Track +import eu.kanade.tachiyomi.animesource.model.Video +import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource +import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.POST +import eu.kanade.tachiyomi.util.asJsoup +import eu.kanade.tachiyomi.util.parseAs +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.add +import kotlinx.serialization.json.addJsonObject +import kotlinx.serialization.json.buildJsonArray +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import kotlinx.serialization.json.putJsonArray +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import org.jsoup.Jsoup.parseBodyFragment +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import uy.kohesive.injekt.injectLazy +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.Locale + +class AniZone : AnimeHttpSource(), ConfigurableAnimeSource { + + override val name = "AniZone" + + override val baseUrl = "https://anizone.to" + + override val lang = "all" + + override val supportsLatest = true + + private val json: Json by injectLazy() + + private val preferences: SharedPreferences by lazy { + Injekt.get().getSharedPreferences("source_$id", 0x0000) + } + + private var token: String = "" + + private val snapShots: MutableMap = mutableMapOf( + ANIME_SNAPSHOT_KEY to "", + EPISODE_SNAPSHOT_KEY to "", + VIDEO_SNAPSHOT_KEY to "", + ) + + private var loadCount: Int = 0 + + // ============================== Popular =============================== + + override fun popularAnimeRequest(page: Int): Request { + return if (page == 1) { + loadCount = 0 + snapShots[ANIME_SNAPSHOT_KEY] = "" + + val updates = buildJsonObject { + put("sort", "title-asc") + } + val calls = buildJsonArray { } + + createLivewireReq(ANIME_SNAPSHOT_KEY, updates, calls) + } else { + val updates = buildJsonObject { } + val calls = buildJsonArray { + addJsonObject { + put("path", "") + put("method", "loadMore") + putJsonArray("params") { } + } + } + + createLivewireReq(ANIME_SNAPSHOT_KEY, updates, calls) + } + } + + override fun popularAnimeParse(response: Response): AnimesPage { + val html = response.parseAs().getHtml(ANIME_SNAPSHOT_KEY) + + val animeList = html.select("div.grid > div").drop(loadCount) + .map(::animeFromElement) + val hasNextPage = html.selectFirst("div[x-intersect~=loadMore]") != null + + loadCount += animeList.size + + return AnimesPage(animeList, hasNextPage) + } + + private fun animeFromElement(element: Element): SAnime { + return SAnime.create().apply { + thumbnail_url = element.selectFirst("img")!!.attr("src") + with(element.selectFirst("a.inline")!!) { + setUrlWithoutDomain(attr("href")) + title = text() + } + } + } + + // =============================== Latest =============================== + + override fun latestUpdatesRequest(page: Int): Request { + return if (page == 1) { + loadCount = 0 + snapShots[ANIME_SNAPSHOT_KEY] = "" + + val updates = buildJsonObject { + put("sort", "release-desc") + } + val calls = buildJsonArray { } + + createLivewireReq(ANIME_SNAPSHOT_KEY, updates, calls) + } else { + popularAnimeRequest(page) + } + } + + override fun latestUpdatesParse(response: Response): AnimesPage { + return popularAnimeParse(response) + } + + // =============================== Search =============================== + + override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { + val sortFilter = filters.filterIsInstance().first() + + return if (page == 1) { + loadCount = 0 + snapShots[ANIME_SNAPSHOT_KEY] = "" + + val updates = buildJsonObject { + if (query.isNotEmpty()) { + put("search", query) + } + put("sort", sortFilter.toUriPart()) + } + val calls = buildJsonArray { } + + createLivewireReq(ANIME_SNAPSHOT_KEY, updates, calls) + } else { + popularAnimeRequest(page) + } + } + + override fun searchAnimeParse(response: Response): AnimesPage { + return popularAnimeParse(response) + } + + // ============================== Filters =============================== + + override fun getFilterList(): AnimeFilterList { + return AnimeFilterList(SortFilter()) + } + + private class SortFilter : UriPartFilter( + "Sort", + arrayOf( + Pair("A-Z", "title-asc"), + Pair("Z-A", "title-desc"), + Pair("Earliest Release", "release-asc"), + Pair("Latest Release", "release-desc"), + Pair("First Added", "added-asc"), + Pair("Last Added", "added-desc"), + ), + ) + + private open class UriPartFilter(displayName: String, val vals: Array>) : + AnimeFilter.Select(displayName, vals.map { it.first }.toTypedArray()) { + fun toUriPart() = vals[state].second + } + + // =========================== Anime Details ============================ + + override fun animeDetailsParse(response: Response): SAnime { + val document = response.asJsoup() + + val infoDiv = document.select("div.flex.items-start > div")[1] + + return SAnime.create().apply { + thumbnail_url = document.selectFirst("div.flex.items-start img")!!.attr("abs:img") + + with(infoDiv) { + title = selectFirst("h1")!!.text() + status = select("span.flex")[1].parseStatus() + description = selectFirst("div:has(>h3:contains(Synopsis)) > div")?.html() + ?.replace("
", "\n") + ?.replace(MULTILINE_REGEX, "\n\n") + genre = select("div > a").joinToString { it.text() } + } + } + } + + private fun Element.parseStatus(): Int = when (this.text().lowercase()) { + "completed" -> SAnime.COMPLETED + "ongoing" -> SAnime.ONGOING + else -> SAnime.UNKNOWN + } + + // ============================== Episodes ============================== + + private fun getPredefinedSnapshots(slug: String): String { + return when (slug) { + "/anime/uyyyn4kf" -> """{"data":{"anime":[null,{"class":"anime","key":68,"s":"mdl"}],"title":null,"search":"","listSize":1104,"sort":"release-asc","sortOptions":[{"release-asc":"First Aired","release-desc":"Last Aired"},{"s":"arr"}],"view":"list","paginators":[{"page":1},{"s":"arr"}]},"memo":{"id":"GD1OiEMOJq6UQDQt1OBt","name":"pages.anime-detail","path":"anime\/uyyyn4kf","method":"GET","children":[],"scripts":[],"assets":[],"errors":[],"locale":"en"},"checksum":"5800932dd82e4862f34f6fd72d8098243b32643e8accb8da6a6a39cd0ee86acd"}""" + else -> "" + } + } + + override fun episodeListRequest(anime: SAnime): Request { + snapShots[EPISODE_SNAPSHOT_KEY] = getPredefinedSnapshots(anime.url) + + val updates = buildJsonObject { + put("sort", "release-desc") + } + val calls = buildJsonArray { } + + return createLivewireReq(EPISODE_SNAPSHOT_KEY, updates, calls, anime.url) + } + + override fun episodeListParse(response: Response): List { + val document = response.parseAs().getHtml(EPISODE_SNAPSHOT_KEY) + val episodeList = document.select(episodeSelector) + .map(::episodeFromElement) + .toMutableList() + loadCount = episodeList.size + + var hasMore = document.selectFirst("div[x-intersect~=loadMore]") != null + + while (hasMore) { + val updates = buildJsonObject { } + val calls = buildJsonArray { + addJsonObject { + put("path", "") + put("method", "loadMore") + putJsonArray("params") { } + } + } + + val resp = client.newCall( + createLivewireReq(EPISODE_SNAPSHOT_KEY, updates, calls), + ).execute().parseAs().getHtml(EPISODE_SNAPSHOT_KEY) + + val episodes = resp.select(episodeSelector) + .drop(loadCount) + .map(::episodeFromElement) + + episodeList.addAll(episodes) + loadCount += episodes.size + + hasMore = resp.selectFirst("div[x-intersect~=loadMore]") != null + } + + return episodeList + } + + private val episodeSelector = "ul > li" + + private fun episodeFromElement(element: Element): SEpisode { + val url = element.selectFirst("a[href]")!!.attr("abs:href") + + return SEpisode.create().apply { + setUrlWithoutDomain(url) + name = element.selectFirst("h3")!!.text() + date_upload = element.select("div.flex-row > span").getOrNull(1) + ?.text() + ?.let { parseDate(it) } + ?: 0L + } + } + + // ============================ Video Links ============================= + + override fun videoListRequest(episode: SEpisode): Request { + return GET(baseUrl + episode.url, headers) + } + + private val playlistUtils: PlaylistUtils by lazy { PlaylistUtils(client, headers) } + + override fun videoListParse(response: Response): List