From 43fdd9573fb5a88e307b7d087e4b0adc94a98d8e Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 31 Mar 2023 04:36:51 +0700 Subject: [PATCH] added StremioX --- StremioX/build.gradle.kts | 26 + StremioX/icon.png | Bin 0 -> 52736 bytes StremioX/src/main/AndroidManifest.xml | 2 + .../src/main/kotlin/com/hexated/StremioX.kt | 594 ++++++++++++++++++ .../main/kotlin/com/hexated/StremioXPlugin.kt | 14 + 5 files changed, 636 insertions(+) create mode 100644 StremioX/build.gradle.kts create mode 100644 StremioX/icon.png create mode 100644 StremioX/src/main/AndroidManifest.xml create mode 100644 StremioX/src/main/kotlin/com/hexated/StremioX.kt create mode 100644 StremioX/src/main/kotlin/com/hexated/StremioXPlugin.kt diff --git a/StremioX/build.gradle.kts b/StremioX/build.gradle.kts new file mode 100644 index 00000000..57b33f83 --- /dev/null +++ b/StremioX/build.gradle.kts @@ -0,0 +1,26 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "en" + // All of these properties are optional, you can safely remove them + + description = "Allow you to use Stremio addons as sources such as torrentio. (!) Requires setup" + authors = listOf("Hexated") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "TvSeries", + "Movie", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=www.stremio.com&sz=%size%" +} \ No newline at end of file diff --git a/StremioX/icon.png b/StremioX/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6ca05ae63433004899d15c56b37e5c7de8429ec5 GIT binary patch literal 52736 zcmeFY^;=Z$7cRVKsG&hpNkLix0i~HiKvcR>DH9YFkj?=SDJkhLK@=(J96~@sQt9sQ zn1PA2@$2Wk-rvqYa4v>xfIWNf^*n2>d)@0^n-E=Xb!v)B6aWBF-@T)%4**c`M<@Uz z1>X+cf1iSH#Ma7M$^cLrNr`<#0{+hZDgd~M1Hif!0LUc* z0EgEHJ7g^vHfxD{8hVJ8AIFIsc_mjEa;TmP!ybn^7#3U^nd%CiOMGC$zuWx_l{5_Tb zhZpAm+&>}uz9~1t4?=YN_VEP^cYj1XH2&JffT*j?qoW^d`F`v7#TmsN?7sKLEPK@3 z*B&SeC=uvOc^ehge#o9oyXpME`Pxsp^^OhMtN)ljV>_nvyOpIY$Vd_R|K9$uTTsbb z{)b7|nRGm!F;swTdYwXWoR*`!N*Z>I82qGYlcFcs&Z5OgRMl4?QL2>{;BoRuPUg?2 z7y7*=^%Q}RpNM~p;xwj*wS9Th@3_i6rP$B^zSty$m9Owtsk!)vl0t@Qts#5E>g>RN z|LQ3l;rfktvW2|%F}r%jDp{)%x0&)sc@_mPvHFP0lZ zPmhR|WU(}R&>IwcwK?W>Wmhqlt+_Ah=~G_rq@*N+PgdHpT4V}$$i}M5Gmgn@>u;KB zn4ER5?XN$st*#Y!uXl#0rJ$xzXXxj0tcPTPKHBH|*BxVW%p-U~V~%q5Cimv^$Em3tt-gIL8(12&;#So6()qzq2eP z9IF$q1Or~A=%TF?lK*fidGEk*=xwoW@dcn4Di?KhNl zIJYld+!>g8@Vf@RLEJ#4GkGh0{A_Y@1bz}zXX(9uaF#ypwplYJ>1COkoGPmnt=ZVG z;i=AWFa2`1B6l)hzm#7{VdG^m%7+H5mzn$$5;1yRYvIar)zdm7qJ>4*EWPWovn{{K zOo}Y3T~3?pR*)Neg=8ip&}Xb_{zOPb#pk9#VWNk`MnEO0(Xg*3x&u#9kDnZQj>2^5 z><}gmEWI6fB8V&#(^Gw3WlLi)77}|r{>Su7@%6w;Op0pGjX+a854+)5SF9x_4k>~O zW0D!O-@U{dM&&Dh=Zxhvpkk=oRwF~{L8`pV_HYO#9J|Ri1$Q}W;HyeZhG!;8WQH~| zycY&^n6*fdyjdvZNLEOOH_qf3<$+a)yE&W;S*9hW;<{Ar_ch4*`XJ>g!3tsNNrlZk zQhwr2Hyvbd&;+U0tDmU!SBwADG`22pKOm3 zats(GXS6>~+a?9-G<-uP;DUlfwK=~fUKC7h5GRs`lZXcK`WTG*{7AI`+*6TRP4t^O^TysF=W5D~(RUYE~`A@l9ig;LJu3}BYaYiq@oFlj>gX_7vEFbP+>A$xFEChKFKRje!c zAi%e4?av?lKEZoq?hj#S21&5@*=^7v;GaBQNG$;Jc}moDNvsy=oK8l_@sA@2b(ZKr zML6LP9G??(qHxf`?_~g2Rwc{qyOX6`&eGH4WE=2jrtx64eFj@`LTG=8@>)0HN|Jfn zg3_k%f8nq7mLefsIqnZv@-Cu=hqeL4DuB9N~zJ8?q@E63%z9bw?I30%=@7X6zre}a2xDeJnrgna$- z@##v)1&!T0FBfShe}iT)T)>xfS~6ztB@#0tI)mFR#*d)(xO^O5ZO;pD2ENVu0^wG; zmU*uU23q58`0L2zK2~ZhMH8O@$L+8a221U6d!PderXR2Lb>5m(k*a|_

)CfrCUEY_TyWE_isndIi zudqCgM7_cOv?X-?{&5H=wHg*1l{0J=aMeBt`DwridMUH&50ee~PYkEi(a8_X{UOWKfHQng zA1)B?aoDtn5|_Px#0&5THViadA_@3WS0(yL}?!K#~?8*_*Uuj{6V^UzFAHHk~u>4&MBORh^+>4r6)WRFNVaJ z5UMf`%PJsQsINkhBVt2@BJd~wJJ!5;hA7H=ZM4doP+^IO6AU_N8ctaR1oC{Ly&G;! zAPXFT#V|B( zEs%4gSti;jpKa-7@p>y0z9xTR;O6=}R9%0uw4$v1-VQbkwZBlzf$Ji?0OQ;`Q*28Q z+~i*f`}3Od`B>>BuDBkZrU6H9jucZ5Hip=KrOLm+ok@WR;cuDwj-}o5c)mV^6CiZK zJ)8-91cz+tJ-PKuCYw!Es@gMe5{kc7tqG&{MNs=yDH$I>oor5z5zSzRyWvhJ0b!_< zvH5lH&7WDUhU7o9C=l--1tRwcqeraqlVUh^BzAWDGr>F3Q~jAxvx?Z$FMbu4@xkAm z+d|ArW2#gyW;y&X#6%Am_`KY}U5mD_Ka8R6n^tf<#kZvO&o>F@UjU2%zvY&htH&D+ zn3l*b>i7L>J-ctB>gNC5mol(~x^8K|*2(@vDg!DJHuW_TR3ZdV|7 zGc|1*vjsXNr$Cy^Le_DknaK$H{+%%JtMZg7=*)ZN0BO~ifet|)Sx(k1%w`bT=p;pd zyKSlSV1|6MJjEjh&$-?D-2CL3$#xpsZSv9K zt`=8g;Qa->y#k>y4Y@8rI6}TS*=&RdGM27dJLFX^93ipDCF5dg_0q8 zew(Wi@SYyu@Fd703B%&MjU@DKO*zh5nnx~y;LjMU)w=k5u_wjSecLwdb8!PLns!EL!)Wxta31&K=_EWmxOMxv1^`KbpcV0Y98Hd+RfG4hS4xld-2 zz0M}>)6Fa%erS-8N%cv2BrgK&57l>7k(JIPU%tsZ*}=yU+PD6IP5oiP=!bXgfzs%bg5jTpYV=W$(4mAX)HiB?L#Qc-SQGkd%l8K9~7 zV*FUzkQe@nzvq4aHxxPZLvnjvvg9K17B>fLTW|a?&f<`&zEBYP6Efh3Z%)^aXs10& z9NYkvtyZ*fC3R)M`M!lY;i4�UvU82cHy+qBI~AoX{BM|r@O@*ynE?$4rB;d7S1 zgar&dmEDs(0c#5aw#>5TlopOhX1qtiqUeoba>Z26=8*gg_`xGMgc~CXKS8>mLkt~^iLdKSpZ6Lq zP9CId@WwxJ#^(Xl&Xct`+n5&Q`s>%s=~RK!ipl=$qh9h=_K$@{P5f_p9&LXmScoO9 z;+pMoYj7#~iUXFa+QGl^&fcTBjc!BEKSZ9=9(^RY?XE(Hb%twacXRqh9dSA12;Fc3 z3(9qKw*aY>wYY0+^5ERm6e6DF#H7i+8WvjA@ic8O{*-$3jI=V1C9{CSPyR&A1oyCo zAP-g?BKXlM9KWNbrHPb(Fm7B-ZS=R8n&7FGZ*}4ui!UJ`mPv) z=UF}rSR-$mel%n2V%l@@*-mkrsq=WhD5648yYOdY;{ zP-XWQ8GV;#q8}%ZD+XoE6 z`~rCyaL-xv1Xx?RrUh*_`?Pa3z`Q)N*T$x}Z>^euyfg*5Ig^;2h#9zgS&iZ<+ppEQ z>~Z&hi$m^X$@#pFd$v>LkQ<9TlV09V*JvX=h`JujzZDe*ijM4S@Q^Enf(*VL}qtPuH1*(Pg!@DD3i-$$(nW(te)27Qs1j`){-Du z&Z&flwExa0bnY_bSJ`(oXW))S;9dYEi3k56vQh-teoSS*G2>=&)+VNPoY(k?jBqY3 zX46o$gFTPN3=S*iOTKr_A3?_GUnvY)`ij$VugSCX$D-s}I)OaE$rrq5p2)IVYTu`hkis)h(LB6 zZgZV|5yN*q`q2OsGM-*|WemJL!6R|G8QxDoN+%1<-AKLepynR){#ksWE_dWVPem#c zRPE=TERkyhGe1@2JtVBy+#tGFdd$CFcd_Y{oZ-Lc>PeeHl

MqS+d|CVN3_;opv+ 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 Qr))NA zQXQSv>w1oN)d)IJMj+*!5m8sg1oPEhPsV>(VQG`fN3Xc0;GEdJR!SSTl|57YXp!N&A4(pl# z|GL5I2C;WArGPkp22xSM8&E`hWKQE$fgjtzW|$ugnB*8n2SR^`0CrP}+}^k(m9BMr{o>os>Hh|sUFbB@;%6QhoeZ>NjuO9(?8pVaLB6l55g z`4{-k_P1$?H3$|2t~)snxb0cb@WvplZ)3@^>nI!A=5_1x+}@sCGS2x8plY|l#6f8~ zU--9<=5VNw1BodJ+$9L?NOCrnu=nv9w^-7iC{lV#7y6w#^iAgQ+csQ+$o2EstrH90Ym<>7XM`4^~)u5C%-u}Mh+Oog)N?0PSix0oT}x~I@gQ--`TfvU$WWz^~}fG089MlF&*9qPg(Wa+#rq6p|<0y zO%TjcxW^k)?Bh(!|~6&)~9{4fh

  • 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

    W(P@zw9( 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

    *X;=G6}FlG z7hw}WdP5CMWTjR)ejsa+Kf+xsNu3(P{kmvr`DVCT*a6B^MUJwkgSE^Gsd@x z(j96)Iq$qxDI%+!k8*+L9Cs@PgjcQ^{AXt#0(Sn!MFT1%+i_7!1%;ns0jNb}7iLQC z9ncNgc7th}V_Rks#NR;%oDz}tbf9mfXFBDi5lJD0AWf~Kh5E~1DIKD%H#3lJ%@J5Q z&y2-`cPkUWyz_5=NIW+D|3g;=lz^3L^2=gBA+C?LtXw8jRpQsZQt(5xZP-%%^)PpC zH$ub!uY`oCqfZ7;k6L(1sT-kA?eFD#`5Qczk%}SKt&yy$&;dZj&j+X$*e#aLFx-)B z8>T<%HX;1Q)nJ_u^h|$c>CSi16QwK~okG$G8GQFtwH$u@R=-2JvuhV=U+~Qh7ndJ~ z=TUoc?w&Xuxk{k$vbRSmLIO9rx>kxfzB=5|jx1dw^{O2kt>51hz9qwpjn3ZZMH&UefJ5B{=Iw+ zCt}5?J67jIy941%WJ^eLm?((2ceT<%Yw&Yy}&#|L#t*6&SNLO1Ev->QOU$v9Nmqo;|h z4`lNsVdA`%y5N7piml!hS|b4o73?hgJ~P3VA)dh<>{l*!{>4$t1Q!B-$ZS*C@Ya!# zwqk4%!^Hx9_1AdxSSDga&}0;sKE9?5zDT7!&&N_yx=g@k?|fs9x)|9Hy59b~AIb=v zE{ir-Q9O75dTp+qWT=Duss-U;sZ{@MRXdk>wWG7#$FB%jVS1z^B_2n|6J z#63Ltdj5TMp<|9O@H_^qn|OgM$Xu-T@^n}_+?fg21~f}{HX}1wVrN(;>mjWwPuf$$ zF)faCVyExOyL925R*vn7hb#f2fP(Qe(gR?j$R%R1CI>xyuPJwtPQ~)7;JSs&b<|w^+A~dx8 z#9k{_dsAT`vncaIU+X6P33Ea7#F8?b=W^h$0pCbj9Vn`=4J49R83zB5OWwI@dsij* zy{OK)^cV0ZeTg1^Nq&dnlrdw44$nIh$y-}7qeb1|hnX3G$GK#v2qD5TD3a`OM_JQ{ zCM;Lfo+<5=(t&c*fd6lL-p=M(PXFs>wvHR_}{zlz9|eLu+Cc|S4p9!^`}#_y*5Z5ql&!kf}&cxU2<)C&R80_ z-DpFb7k)UI_nyN_F3OPnIZA2WZ^F^gBrDg^=|-Oi)GB1aOZ=4-e(7cKC|8U3uF-Po zGAqG0sO`MOGtJm^qoPWSZ#9bg%4fd%nURIIfQ4c4RKvGzn%&vA`k^M0TSxE2v&cQ* zQ)Fj#9NP4k!j~%5{bLHgK{}Fti$7Gr`}0^H3fykD;vt+8DAnVoo4YMCD96CvGr2}x zqK`k{WIf)u8=5ZMOZ$!wwD#UQ3GdR�ADl2>i<@}m&^6K;Ty4i5jWg4nS2k= z+VM5?#dhE}{XY9yTFjq*ub2;mI$df)Zf_9UJK z%|*K}xa_#5tG9-Gwbo+2b)G+}E^CRz9yB;qc*B(O@DbCwK`XTDr@RizQ7n0oYu*-F z5I!|+@tt3bx2fm0cfIWhWPQ5g9^?1#8?No<`qSsge(zmk#6ugOiqPu7?)Zff@@9vW z1-hlfDpqf}&vv14$8V0cXZV+92A$imhpROy*^J(pvxWZU^J-IflG{<7*5 zu;2Fa$cCo))<0%#e9yXio3^R8K04{xy3GkREWp(|lBll0kN??A-X)wqv3ip#0|SF< ziEBhjN@7W>RdP`(kYX@0Ff!CNFw-?M4KXmaGBvU?HPJROure_CqrdPqiiX_$l+3hB z+!}g|B*TFk1VJ{WR%E7GIp^o(7X=q2CZ{qO^3P`S1WF3QC0&6k{L|8kQ%e}kElysk zRtL&T!es+8D^hbJTrzW0^NKU`^B4>bj7&Zq4U@-I6p5}-2q~iRvlJdl& zRECU_l7eC@ef`Yb#Pn1k&P>kM%P&gbb6$2XP^|<=ZAeCGZjzOiOMY@G(9RMos{o+V zVg|$I|99)dEQPA^1es!G<&m11o>2mJ*>klUd(jMnDhkg`DanAiKA&X?nnAum@0C;* zq%wfrrC*SjZoeta52#2S$wj^)KvfKeW=1Av1_s9FCK_SE(}7Avkdy>xR;4l+8(Nqf znL0VybaVOxWfgzx$Us{lpp9q}&GBwk;$ac=DtTNX(HZV2TFD@xc z&CSe@&rM9uFOE;jOfN1iiqA~W&x<#-ur#wU*8@6l(fyyhfMzpzy85}Sb4q9e02G%R AhyVZp literal 0 HcmV?d00001 diff --git a/StremioX/src/main/AndroidManifest.xml b/StremioX/src/main/AndroidManifest.xml new file mode 100644 index 00000000..c98063f8 --- /dev/null +++ b/StremioX/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/StremioX/src/main/kotlin/com/hexated/StremioX.kt b/StremioX/src/main/kotlin/com/hexated/StremioX.kt new file mode 100644 index 00000000..cd973fc9 --- /dev/null +++ b/StremioX/src/main/kotlin/com/hexated/StremioX.kt @@ -0,0 +1,594 @@ +package com.hexated + +import android.util.Log +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.cloudstream3.utils.AppUtils.toJson +import org.json.JSONObject +import java.net.URI +import java.util.ArrayList +import kotlin.math.roundToInt + +open class StremioX : MainAPI() { + override var mainUrl = "https://torrentio.strem.fun" + override var name = "StremioX" + override val hasMainPage = true + override val hasQuickSearch = true + override val supportedTypes = setOf( + TvType.Others, + ) + + companion object { + const val TRACKER_LIST_URL = + "https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_best.txt" + const val openSubAPI = "https://opensubtitles.strem.io/stremio/v1" + const val watchSomuchAPI = "https://watchsomuch.tv" + private const val tmdbAPI = "https://api.themoviedb.org/3" + private val apiKey = + base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL + + fun getType(t: String?): TvType { + return when (t) { + "movie" -> TvType.Movie + else -> TvType.TvSeries + } + } + + fun getStatus(t: String?): ShowStatus { + return when (t) { + "Returning Series" -> ShowStatus.Ongoing + else -> ShowStatus.Completed + } + } + + private fun base64DecodeAPI(api: String): String { + return api.chunked(4).map { base64Decode(it) }.reversed().joinToString("") + } + + } + + override val mainPage = mainPageOf( + "$tmdbAPI/trending/all/day?api_key=$apiKey®ion=US" to "Trending", + "$tmdbAPI/movie/popular?api_key=$apiKey®ion=US" to "Popular Movies", + "$tmdbAPI/tv/popular?api_key=$apiKey®ion=US&with_original_language=en" to "Popular TV Shows", + "$tmdbAPI/tv/airing_today?api_key=$apiKey®ion=US&with_original_language=en" to "Airing Today TV Shows", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=213" to "Netflix", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=1024" to "Amazon", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2739" to "Disney+", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=453" to "Hulu", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2552" to "Apple TV+", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=49" to "HBO", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=4330" to "Paramount+", + "$tmdbAPI/movie/top_rated?api_key=$apiKey®ion=US" to "Top Rated Movies", + "$tmdbAPI/tv/top_rated?api_key=$apiKey®ion=US" to "Top Rated TV Shows", + "$tmdbAPI/movie/upcoming?api_key=$apiKey®ion=US" to "Upcoming Movies", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_original_language=ko" to "Korean Shows", + ) + + private fun getImageUrl(link: String?): String? { + if (link == null) return null + return if (link.startsWith("/")) "https://image.tmdb.org/t/p/w500/$link" else link + } + + private fun getOriImageUrl(link: String?): String? { + if (link == null) return null + return if (link.startsWith("/")) "https://image.tmdb.org/t/p/original/$link" else link + } + + override suspend fun getMainPage( + page: Int, request: MainPageRequest + ): HomePageResponse { + val adultQuery = + if (settingsForProvider.enableAdult) "" else "&without_keywords=190370|13059|226161|195669|190370" + val type = if (request.data.contains("/movie")) "movie" else "tv" + val home = app.get("${request.data}$adultQuery&page=$page") + .parsedSafe()?.results?.mapNotNull { media -> + media.toSearchResponse(type) + } ?: throw ErrorLoadingException("Invalid Json reponse") + return newHomePageResponse(request.name, home) + } + + private fun Media.toSearchResponse(type: String? = null): SearchResponse? { + return newMovieSearchResponse( + title ?: name ?: originalTitle ?: return null, + Data(id = id, type = mediaType ?: type).toJson(), + TvType.Movie, + ) { + this.posterUrl = getImageUrl(posterPath) + } + } + + override suspend fun quickSearch(query: String): List? = search(query) + + override suspend fun search(query: String): List? { + return app.get( + "$tmdbAPI/search/multi?api_key=$apiKey&language=en-US&query=$query&page=1&include_adult=${settingsForProvider.enableAdult}" + ).parsedSafe()?.results?.mapNotNull { media -> + media.toSearchResponse() + } + } + + override suspend fun load(url: String): LoadResponse? { + val data = parseJson(url) + val type = getType(data.type) + val resUrl = if (type == TvType.Movie) { + "$tmdbAPI/movie/${data.id}?api_key=$apiKey&append_to_response=keywords,credits,external_ids,videos,recommendations" + } else { + "$tmdbAPI/tv/${data.id}?api_key=$apiKey&append_to_response=keywords,credits,external_ids,videos,recommendations" + } + val res = app.get(resUrl).parsedSafe() + ?: throw ErrorLoadingException("Invalid Json Response") + + val title = res.title ?: res.name ?: return null + val poster = getOriImageUrl(res.posterPath) + val bgPoster = getOriImageUrl(res.backdropPath) + val year = (res.releaseDate ?: res.firstAirDate)?.split("-")?.first()?.toIntOrNull() + val rating = res.vote_average.toString().toRatingInt() + val genres = res.genres?.mapNotNull { it.name } + val isAnime = + genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") + val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty() + .ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } + + val actors = res.credits?.cast?.mapNotNull { cast -> + ActorData( + Actor( + cast.name ?: cast.originalName ?: return@mapNotNull null, + getImageUrl(cast.profilePath) + ), roleString = cast.character + ) + } ?: return null + val recommendations = + res.recommendations?.results?.mapNotNull { media -> media.toSearchResponse() } + + val trailer = + res.videos?.results?.map { "https://www.youtube.com/watch?v=${it.key}" }?.randomOrNull() + + return if (type == TvType.TvSeries) { + val episodes = res.seasons?.mapNotNull { season -> + app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey") + .parsedSafe()?.episodes?.map { eps -> + Episode( + LoadData( + res.external_ids?.imdb_id, + eps.seasonNumber, + eps.episodeNumber + ).toJson(), + name = eps.name, + season = eps.seasonNumber, + episode = eps.episodeNumber, + posterUrl = getImageUrl(eps.stillPath), + rating = eps.voteAverage?.times(10)?.roundToInt(), + description = eps.overview + ).apply { + this.addDate(eps.airDate) + } + } + }?.flatten() ?: listOf() + newTvSeriesLoadResponse( + title, url, if (isAnime) TvType.Anime else TvType.TvSeries, episodes + ) { + this.posterUrl = poster + this.backgroundPosterUrl = bgPoster + this.year = year + this.plot = res.overview + this.tags = if (isAnime) keywords else genres + this.rating = rating + this.showStatus = getStatus(res.status) + this.recommendations = recommendations + this.actors = actors + addTrailer(trailer) + } + } else { + newMovieLoadResponse( + title, + url, + TvType.Movie, + LoadData(res.external_ids?.imdb_id).toJson() + ) { + this.posterUrl = poster + this.backgroundPosterUrl = bgPoster + this.year = year + this.plot = res.overview + this.duration = res.runtime + this.tags = if (isAnime) keywords else genres + this.rating = rating + this.recommendations = recommendations + this.actors = actors + addTrailer(trailer) + } + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val res = parseJson(data) + + argamap( + { + invokeMainSource(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeWatchsomuch(res.imdbId, res.season, res.episode, subtitleCallback) + }, + { + invokeOpenSubs(res.imdbId, res.season, res.episode, subtitleCallback) + }, + ) + + return true + } + + private suspend fun invokeMainSource( + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val fixMainUrl = mainUrl.fixSourceUrl() + val url = if(season == null) { + "$fixMainUrl/stream/movie/$imdbId.json" + } else { + "$fixMainUrl/stream/series/$imdbId:$season:$episode.json" + } + val res = AppUtils.tryParseJson(app.get(url).text) ?: return + res.streams.forEach { stream -> + stream.runCallback(subtitleCallback, callback) + } + } + + private suspend fun invokeOpenSubs( + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + ) { + val id = if(season == null) { + imdbId + } else { + "$imdbId $season $episode" + } + val data = base64Encode("""{"id":1,"jsonrpc":"2.0","method":"subtitles.find","params":[null,{"query":{"itemHash":"$id"}}]}""".toByteArray()) + app.get("$openSubAPI/q.json?b=$data").parsedSafe()?.result?.all?.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + SubtitleHelper.fromThreeLettersToLanguage(sub.lang ?: "") ?: sub.lang + ?: "", + sub.url ?: return@map + ) + ) + } + + } + + private suspend fun invokeWatchsomuch( + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + ) { + val id = imdbId?.removePrefix("tt") + val epsId = app.post( + "${watchSomuchAPI}/Watch/ajMovieTorrents.aspx", data = mapOf( + "index" to "0", + "mid" to "$id", + "wsk" to "f6ea6cde-e42b-4c26-98d3-b4fe48cdd4fb", + "lid" to "", + "liu" to "" + ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).parsedSafe()?.movie?.torrents?.let { eps -> + if (season == null) { + eps.firstOrNull()?.id + } else { + eps.find { it.episode == episode && it.season == season }?.id + } + } ?: return + + val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) + + val subUrl = if (season == null) { + "${watchSomuchAPI}/Watch/ajMovieSubtitles.aspx?mid=$id&tid=$epsId&part=" + } else { + "${watchSomuchAPI}/Watch/ajMovieSubtitles.aspx?mid=$id&tid=$epsId&part=S${seasonSlug}E${episodeSlug}" + } + + app.get(subUrl).parsedSafe()?.subtitles?.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + sub.label ?: "", fixUrl(sub.url ?: return@map null, watchSomuchAPI) + ) + ) + } + + + } + + private fun String.fixSourceUrl() : String { + return this.replace("/manifest.json", "").replace("stremio://", "https://") + } + + private fun getEpisodeSlug( + season: Int? = null, + episode: Int? = null, + ): Pair { + return if (season == null && episode == null) { + "" to "" + } else { + (if (season!! < 10) "0$season" else "$season") to (if (episode!! < 10) "0$episode" else "$episode") + } + } + + private fun fixUrl(url: String, domain: String): String { + if (url.startsWith("http")) { + return url + } + if (url.isEmpty()) { + return "" + } + + val startsWithNoHttp = url.startsWith("//") + if (startsWithNoHttp) { + return "https:$url" + } else { + if (url.startsWith('/')) { + return domain + url + } + return "$domain/$url" + } + } + + private data class StreamsResponse(val streams: List) + private data class Subtitle( + val url: String?, + val lang: String?, + val id: String?, + ) + + private data class Stream( + val name: String?, + val title: String?, + val url: String?, + val description: String?, + val ytId: String?, + val externalUrl: String?, + val behaviorHints: JSONObject?, + val infoHash: String?, + val sources: List = emptyList(), + val subtitles: List = emptyList() + ) { + suspend fun runCallback( + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + if (url != null) { + var referer: String? = null + try { + val headers = ((behaviorHints?.get("proxyHeaders") as? JSONObject) + ?.get("request") as? JSONObject) + referer = + headers?.get("referer") as? String ?: headers?.get("origin") as? String + } catch (ex: Throwable) { + Log.e("Stremio", Log.getStackTraceString(ex)) + } + callback.invoke( + ExtractorLink( + name ?: "", + title ?: name ?: "", + url, + referer ?: "", + getQualityFromName(description), + isM3u8 = URI(url).path.endsWith(".m3u8") + ) + ) + subtitles.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + SubtitleHelper.fromThreeLettersToLanguage(sub.lang ?: "") ?: sub.lang + ?: "", + sub.url ?: return@map + ) + ) + } + } + if (ytId != null) { + loadExtractor("https://www.youtube.com/watch?v=$ytId", subtitleCallback, callback) + } + if (externalUrl != null) { + loadExtractor(externalUrl, subtitleCallback, callback) + } + if (infoHash != null) { + val resp = app.get(TRACKER_LIST_URL).text + val otherTrackers = resp + .split("\n") + .filterIndexed { i, _ -> i % 2 == 0 } + .filter { s -> s.isNotEmpty() }.joinToString("") { "&tr=$it" } + + val sourceTrackers = sources + .filter { it.startsWith("tracker:") } + .map { it.removePrefix("tracker:") } + .filter { s -> s.isNotEmpty() }.joinToString("") { "&tr=$it" } + + val magnet = "magnet:?xt=urn:btih:${infoHash}${sourceTrackers}${otherTrackers}" + callback.invoke( + ExtractorLink( + name ?: "", + title ?: name ?: "", + magnet, + "", + Qualities.Unknown.value + ) + ) + } + } + } + + data class OsSubtitles( + @JsonProperty("url") val url: String? = null, + @JsonProperty("lang") val lang: String? = null, + ) + + data class OsAll( + @JsonProperty("all") val all: ArrayList? = arrayListOf(), + ) + + data class OsResult( + @JsonProperty("result") val result: OsAll? = null, + ) + + data class WatchsomuchTorrents( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("movieId") val movieId: Int? = null, + @JsonProperty("season") val season: Int? = null, + @JsonProperty("episode") val episode: Int? = null, + ) + + data class WatchsomuchMovies( + @JsonProperty("torrents") val torrents: ArrayList? = arrayListOf(), + ) + + data class WatchsomuchResponses( + @JsonProperty("movie") val movie: WatchsomuchMovies? = null, + ) + + data class WatchsomuchSubtitles( + @JsonProperty("url") val url: String? = null, + @JsonProperty("label") val label: String? = null, + ) + + data class WatchsomuchSubResponses( + @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), + ) + + data class LoadData( + val imdbId: String? = null, + val season: Int? = null, + val episode: Int? = null, + ) + + data class Data( + val id: Int? = null, + val type: String? = null, + val aniId: String? = null, + val malId: Int? = null, + ) + + data class Results( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), + ) + + data class Media( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("original_title") val originalTitle: String? = null, + @JsonProperty("media_type") val mediaType: String? = null, + @JsonProperty("poster_path") val posterPath: String? = null, + ) + + data class Genres( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + ) + + data class Keywords( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + ) + + data class KeywordResults( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("keywords") val keywords: ArrayList? = arrayListOf(), + ) + + data class Seasons( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("season_number") val seasonNumber: Int? = null, + @JsonProperty("air_date") val airDate: String? = null, + ) + + data class Cast( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("original_name") val originalName: String? = null, + @JsonProperty("character") val character: String? = null, + @JsonProperty("known_for_department") val knownForDepartment: String? = null, + @JsonProperty("profile_path") val profilePath: String? = null, + ) + + data class Episodes( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("overview") val overview: String? = null, + @JsonProperty("air_date") val airDate: String? = null, + @JsonProperty("still_path") val stillPath: String? = null, + @JsonProperty("vote_average") val voteAverage: Double? = null, + @JsonProperty("episode_number") val episodeNumber: Int? = null, + @JsonProperty("season_number") val seasonNumber: Int? = null, + ) + + data class MediaDetailEpisodes( + @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), + ) + + data class Trailers( + @JsonProperty("key") val key: String? = null, + ) + + data class ResultsTrailer( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), + ) + + data class ExternalIds( + @JsonProperty("imdb_id") val imdb_id: String? = null, + @JsonProperty("tvdb_id") val tvdb_id: String? = null, + ) + + data class Credits( + @JsonProperty("cast") val cast: ArrayList? = arrayListOf(), + ) + + data class ResultsRecommendations( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), + ) + + data class LastEpisodeToAir( + @JsonProperty("episode_number") val episode_number: Int? = null, + @JsonProperty("season_number") val season_number: Int? = null, + ) + + data class MediaDetail( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("imdb_id") val imdbId: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("original_title") val originalTitle: String? = null, + @JsonProperty("original_name") val originalName: String? = null, + @JsonProperty("poster_path") val posterPath: String? = null, + @JsonProperty("backdrop_path") val backdropPath: String? = null, + @JsonProperty("release_date") val releaseDate: String? = null, + @JsonProperty("first_air_date") val firstAirDate: String? = null, + @JsonProperty("overview") val overview: String? = null, + @JsonProperty("runtime") val runtime: Int? = null, + @JsonProperty("vote_average") val vote_average: Any? = null, + @JsonProperty("original_language") val original_language: String? = null, + @JsonProperty("status") val status: String? = null, + @JsonProperty("genres") val genres: ArrayList? = arrayListOf(), + @JsonProperty("keywords") val keywords: KeywordResults? = null, + @JsonProperty("last_episode_to_air") val last_episode_to_air: LastEpisodeToAir? = null, + @JsonProperty("seasons") val seasons: ArrayList? = arrayListOf(), + @JsonProperty("videos") val videos: ResultsTrailer? = null, + @JsonProperty("external_ids") val external_ids: ExternalIds? = null, + @JsonProperty("credits") val credits: Credits? = null, + @JsonProperty("recommendations") val recommendations: ResultsRecommendations? = null, + ) + +} diff --git a/StremioX/src/main/kotlin/com/hexated/StremioXPlugin.kt b/StremioX/src/main/kotlin/com/hexated/StremioXPlugin.kt new file mode 100644 index 00000000..329d8ca3 --- /dev/null +++ b/StremioX/src/main/kotlin/com/hexated/StremioXPlugin.kt @@ -0,0 +1,14 @@ + +package com.hexated + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class StremioXPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(StremioX()) + } +} \ No newline at end of file