mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Compare commits
No commits in common. "004c481a5eb8ac8bb0c5a486f2e1f5b35e414f52" and "e6b9d621f96beba6e427aa092d09bb448caf8d93" have entirely different histories.
004c481a5e
...
e6b9d621f9
8 changed files with 7 additions and 176 deletions
|
@ -1,101 +0,0 @@
|
||||||
package com.lagradost.cloudstream3.extractors
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.lagradost.cloudstream3.SubtitleFile
|
|
||||||
import com.lagradost.cloudstream3.app
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.INFER_TYPE
|
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
|
||||||
import org.mozilla.javascript.Context
|
|
||||||
import org.mozilla.javascript.NativeJSON
|
|
||||||
import org.mozilla.javascript.NativeObject
|
|
||||||
import org.mozilla.javascript.Scriptable
|
|
||||||
import java.util.Base64
|
|
||||||
|
|
||||||
open class Vidguardto : ExtractorApi() {
|
|
||||||
override val name = "Vidguard"
|
|
||||||
override val mainUrl = "https://vidguard.to"
|
|
||||||
override val requiresReferer = false
|
|
||||||
|
|
||||||
override suspend fun getUrl(
|
|
||||||
url: String,
|
|
||||||
referer: String?,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
) {
|
|
||||||
val res = app.get(url)
|
|
||||||
val resc = res.document.select("script:containsData(eval)").firstOrNull()?.data()
|
|
||||||
resc?.let {
|
|
||||||
val jsonStr2 = AppUtils.parseJson<SvgObject>(runJS2(it))
|
|
||||||
val watchlink = sigDecode(jsonStr2.stream)
|
|
||||||
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
this.name,
|
|
||||||
name,
|
|
||||||
watchlink,
|
|
||||||
this.mainUrl,
|
|
||||||
Qualities.Unknown.value,
|
|
||||||
INFER_TYPE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun sigDecode(url: String): String {
|
|
||||||
val sig = url.split("sig=")[1].split("&")[0]
|
|
||||||
var t = ""
|
|
||||||
for (v in sig.chunked(2)) {
|
|
||||||
val byteValue = Integer.parseInt(v, 16) xor 2
|
|
||||||
t += byteValue.toChar()
|
|
||||||
}
|
|
||||||
val padding = when (t.length % 4) {
|
|
||||||
2 -> "=="
|
|
||||||
3 -> "="
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
val decoded = Base64.getDecoder().decode((t + padding).toByteArray(Charsets.UTF_8))
|
|
||||||
t = String(decoded).dropLast(5).reversed()
|
|
||||||
val charArray = t.toCharArray()
|
|
||||||
for (i in 0 until charArray.size - 1 step 2) {
|
|
||||||
val temp = charArray[i]
|
|
||||||
charArray[i] = charArray[i + 1]
|
|
||||||
charArray[i + 1] = temp
|
|
||||||
}
|
|
||||||
val modifiedSig = String(charArray).dropLast(5)
|
|
||||||
return url.replace(sig, modifiedSig)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun runJS2(hideMyHtmlContent: String): String {
|
|
||||||
Log.d("runJS", "start")
|
|
||||||
val rhino = Context.enter()
|
|
||||||
rhino.initSafeStandardObjects()
|
|
||||||
rhino.optimizationLevel = -1
|
|
||||||
val scope: Scriptable = rhino.initSafeStandardObjects()
|
|
||||||
scope.put("window", scope, scope)
|
|
||||||
var result = ""
|
|
||||||
try {
|
|
||||||
Log.d("runJS", "Executing JavaScript: $hideMyHtmlContent")
|
|
||||||
rhino.evaluateString(scope, hideMyHtmlContent, "JavaScript", 1, null)
|
|
||||||
val svgObject = scope.get("svg", scope)
|
|
||||||
result = if (svgObject is NativeObject) {
|
|
||||||
NativeJSON.stringify(Context.getCurrentContext(), scope, svgObject, null, null).toString()
|
|
||||||
} else {
|
|
||||||
Context.toString(svgObject)
|
|
||||||
}
|
|
||||||
Log.d("runJS", "Result: $result")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("runJS", "Error executing JavaScript", e)
|
|
||||||
} finally {
|
|
||||||
Context.exit()
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
data class SvgObject(
|
|
||||||
val stream: String,
|
|
||||||
val hash: String
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -9,11 +9,9 @@ import androidx.core.view.isVisible
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
|
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.databinding.ResultEpisodeBinding
|
import com.lagradost.cloudstream3.databinding.ResultEpisodeBinding
|
||||||
import com.lagradost.cloudstream3.databinding.ResultEpisodeLargeBinding
|
import com.lagradost.cloudstream3.databinding.ResultEpisodeLargeBinding
|
||||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.secondsToReadable
|
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_LONG_CLICK
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_LONG_CLICK
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
|
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
|
||||||
|
@ -25,8 +23,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import java.text.DateFormat
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
||||||
|
@ -108,7 +104,7 @@ class EpisodeAdapter(
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
return if (item.poster.isNullOrBlank() && item.description.isNullOrBlank()) 0 else 1
|
return if (item.poster.isNullOrBlank()) 0 else 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,33 +260,6 @@ class EpisodeAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card.airDate != null) {
|
|
||||||
val isUpcoming = unixTimeMS < card.airDate
|
|
||||||
|
|
||||||
if (isUpcoming) {
|
|
||||||
episodePlayIcon.isVisible = false
|
|
||||||
episodeUpcomingIcon.isVisible = !episodePoster.isVisible
|
|
||||||
episodeDate.setText(
|
|
||||||
txt(
|
|
||||||
R.string.episode_upcoming_format,
|
|
||||||
secondsToReadable(card.airDate.minus(unixTimeMS).div(1000).toInt(), "")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
episodeUpcomingIcon.isVisible = false
|
|
||||||
|
|
||||||
val formattedAirDate = SimpleDateFormat.getDateInstance(
|
|
||||||
DateFormat.LONG,
|
|
||||||
Locale.getDefault()
|
|
||||||
).apply {
|
|
||||||
}.format(Date(card.airDate))
|
|
||||||
|
|
||||||
episodeDate.setText(txt(formattedAirDate))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
episodeDate.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLayout(EMULATOR or PHONE)) {
|
if (isLayout(EMULATOR or PHONE)) {
|
||||||
episodePoster.setOnClickListener {
|
episodePoster.setOnClickListener {
|
||||||
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
||||||
|
@ -302,7 +271,6 @@ class EpisodeAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@ data class ResultEpisode(
|
||||||
val videoWatchState: VideoWatchState,
|
val videoWatchState: VideoWatchState,
|
||||||
/** Sum of all previous season episode counts + episode */
|
/** Sum of all previous season episode counts + episode */
|
||||||
val totalEpisodeIndex: Int? = null,
|
val totalEpisodeIndex: Int? = null,
|
||||||
val airDate: Long? = null,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun ResultEpisode.getRealPosition(): Long {
|
fun ResultEpisode.getRealPosition(): Long {
|
||||||
|
@ -86,7 +85,6 @@ fun buildResultEpisode(
|
||||||
tvType: TvType,
|
tvType: TvType,
|
||||||
parentId: Int,
|
parentId: Int,
|
||||||
totalEpisodeIndex: Int? = null,
|
totalEpisodeIndex: Int? = null,
|
||||||
airDate: Long? = null,
|
|
||||||
): ResultEpisode {
|
): ResultEpisode {
|
||||||
val posDur = getViewPos(id)
|
val posDur = getViewPos(id)
|
||||||
val videoWatchState = getVideoWatchState(id) ?: VideoWatchState.None
|
val videoWatchState = getVideoWatchState(id) ?: VideoWatchState.None
|
||||||
|
@ -109,8 +107,7 @@ fun buildResultEpisode(
|
||||||
tvType,
|
tvType,
|
||||||
parentId,
|
parentId,
|
||||||
videoWatchState,
|
videoWatchState,
|
||||||
totalEpisodeIndex,
|
totalEpisodeIndex
|
||||||
airDate,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2277,8 +2277,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
fillers.getOrDefault(episode, false),
|
fillers.getOrDefault(episode, false),
|
||||||
loadResponse.type,
|
loadResponse.type,
|
||||||
mainId,
|
mainId,
|
||||||
totalIndex,
|
totalIndex
|
||||||
airDate = i.date
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val season = eps.seasonIndex ?: 0
|
val season = eps.seasonIndex ?: 0
|
||||||
|
@ -2327,8 +2326,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
null,
|
null,
|
||||||
loadResponse.type,
|
loadResponse.type,
|
||||||
mainId,
|
mainId,
|
||||||
totalIndex,
|
totalIndex
|
||||||
airDate = episode.date
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val season = ep.seasonIndex ?: 0
|
val season = ep.seasonIndex ?: 0
|
||||||
|
|
|
@ -186,7 +186,6 @@ import com.lagradost.cloudstream3.extractors.VideoVard
|
||||||
import com.lagradost.cloudstream3.extractors.VideovardSX
|
import com.lagradost.cloudstream3.extractors.VideovardSX
|
||||||
import com.lagradost.cloudstream3.extractors.Vidgomunime
|
import com.lagradost.cloudstream3.extractors.Vidgomunime
|
||||||
import com.lagradost.cloudstream3.extractors.Vidgomunimesb
|
import com.lagradost.cloudstream3.extractors.Vidgomunimesb
|
||||||
import com.lagradost.cloudstream3.extractors.Vidguardto
|
|
||||||
import com.lagradost.cloudstream3.extractors.VidhideExtractor
|
import com.lagradost.cloudstream3.extractors.VidhideExtractor
|
||||||
import com.lagradost.cloudstream3.extractors.Vidmoly
|
import com.lagradost.cloudstream3.extractors.Vidmoly
|
||||||
import com.lagradost.cloudstream3.extractors.Vidmolyme
|
import com.lagradost.cloudstream3.extractors.Vidmolyme
|
||||||
|
@ -889,8 +888,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf(
|
||||||
StreamWishExtractor(),
|
StreamWishExtractor(),
|
||||||
EmturbovidExtractor(),
|
EmturbovidExtractor(),
|
||||||
Vtbe(),
|
Vtbe(),
|
||||||
EPlayExtractor(),
|
EPlayExtractor()
|
||||||
Vidguardto()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="960"
|
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
|
||||||
android:fillColor="#9BA0A4"
|
|
||||||
android:pathData="M320,800h320v-120q0,-66 -47,-113t-113,-47q-66,0 -113,47t-47,113v120ZM480,440q66,0 113,-47t47,-113v-120L320,160v120q0,66 47,113t113,47ZM160,880v-80h80v-120q0,-61 28.5,-114.5T348,480q-51,-32 -79.5,-85.5T240,280v-120h-80v-80h640v80h-80v120q0,61 -28.5,114.5T612,480q51,32 79.5,85.5T720,680v120h80v80L160,880ZM480,800ZM480,160Z"/>
|
|
||||||
</vector>
|
|
|
@ -43,26 +43,14 @@
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:nextFocusRight="@id/download_button"
|
android:nextFocusRight="@id/download_button"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
tools:src="@drawable/example_poster"
|
tools:src="@drawable/example_poster" />
|
||||||
tools:visibility="invisible"/>
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/episode_play_icon"
|
|
||||||
android:layout_width="36dp"
|
android:layout_width="36dp"
|
||||||
android:layout_height="36dp"
|
android:layout_height="36dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:contentDescription="@string/play_episode"
|
android:contentDescription="@string/play_episode"
|
||||||
android:src="@drawable/play_button"
|
android:src="@drawable/play_button" />
|
||||||
tools:visibility="invisible"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/episode_upcoming_icon"
|
|
||||||
android:layout_width="36dp"
|
|
||||||
android:layout_height="36dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:src="@drawable/hourglass_24"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<androidx.core.widget.ContentLoadingProgressBar
|
||||||
android:id="@+id/episode_progress"
|
android:id="@+id/episode_progress"
|
||||||
|
@ -112,13 +100,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="?attr/grayTextColor"
|
android:textColor="?attr/grayTextColor"
|
||||||
tools:text="Rated: 8.8" />
|
tools:text="Rated: 8.8" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/episode_date"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="?attr/grayTextColor"
|
|
||||||
tools:text="15 Apr 2024" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.lagradost.cloudstream3.ui.download.button.PieFetchButton
|
<com.lagradost.cloudstream3.ui.download.button.PieFetchButton
|
||||||
|
|
|
@ -292,7 +292,6 @@
|
||||||
<string name="episodes">Episodes</string>
|
<string name="episodes">Episodes</string>
|
||||||
<string name="episodes_range">%1$d-%2$d</string>
|
<string name="episodes_range">%1$d-%2$d</string>
|
||||||
<string name="episode_format" formatted="true">%1$d %2$s</string>
|
<string name="episode_format" formatted="true">%1$d %2$s</string>
|
||||||
<string name="episode_upcoming_format" formatted="true">Upcoming in %s</string>
|
|
||||||
<string name="season_short">S</string>
|
<string name="season_short">S</string>
|
||||||
<string name="episode_short">E</string>
|
<string name="episode_short">E</string>
|
||||||
<string name="no_episodes_found">No Episodes found</string>
|
<string name="no_episodes_found">No Episodes found</string>
|
||||||
|
|
Loading…
Reference in a new issue