Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ open class ResultFragmentPhone : FullScreenPlayer() {
}

private fun loadTrailer(index: Int? = null) {

val isSuccess =
currentTrailers.getOrNull(index ?: currentTrailerIndex)?.let { (extractedTrailerLink,_) ->
context?.let { ctx ->
Expand Down Expand Up @@ -189,6 +190,7 @@ open class ResultFragmentPhone : FullScreenPlayer() {
// result_trailer_loading?.isVisible = isSuccess
val turnVis = !isSuccess && !isFullScreenPlayer
resultBinding?.apply {
resultTitle.isVisible = isSuccess
resultSmallscreenHolder.isVisible = turnVis
resultPosterBackgroundHolder.apply {
val fadeIn: Animation = AlphaAnimation(alpha, if (turnVis) 1.0f else 0.0f).apply {
Expand Down Expand Up @@ -800,6 +802,17 @@ open class ResultFragmentPhone : FullScreenPlayer() {
}
}

if (!d.logourl.isNullOrBlank()) {
backgroundPosterWatermarkBadge.isVisible = true
resultTitle.isVisible = false

backgroundPosterWatermarkBadge.loadImage(d.logourl)
} else {
// No logo URL → show title
backgroundPosterWatermarkBadge.isVisible = false
resultTitle.isVisible = true
}

var isExpanded = false
resultDescription.apply {
setTextHtml(d.plotText)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,17 @@ class ResultFragmentTv : BaseFragment<FragmentResultTvBinding>(
backgroundPoster.loadImage(d.posterBackgroundImage) {
error { getImageFromDrawable(context ?: return@error null, error) }
}

if (!d.logourl.isNullOrBlank()) {
backgroundPosterWatermarkBadgeHolder.isVisible = true
resultTitle.isVisible = false

backgroundPosterWatermarkBadgeHolder.loadImage(d.logourl)
} else {
// No logo URL → show title
backgroundPosterWatermarkBadgeHolder.isVisible = false
resultTitle.isVisible = true
}
comingSoon = d.comingSoon
resultTvComingSoon.isVisible = d.comingSoon

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ data class ResultData(

val posterImage: String?,
val posterBackgroundImage: String?,
val logourl: String?,
val plotText: UiText,
val apiName: UiText,
val ratingText: UiText?,
Expand Down Expand Up @@ -245,6 +246,7 @@ fun LoadResponse.toResultData(repo: APIRepository): ResultData {
plot!!
),
backgroundPosterUrl = backgroundPosterUrl,
logourl = logourl,
title = name,
typeText = txt(
when (type) {
Expand Down Expand Up @@ -1895,6 +1897,7 @@ class ResultViewModel2 : ViewModel() {
// set posters, might fuck up due to headers idk
posterUrl = posterUrl ?: res?.image
backgroundPosterUrl = backgroundPosterUrl ?: res?.cover
logourl = logourl
},
{
if (meta == null) return@runAllAsync
Expand Down Expand Up @@ -2695,6 +2698,7 @@ class ResultViewModel2 : ViewModel() {
override var syncData: MutableMap<String, String> = mutableMapOf(),
override var posterHeaders: Map<String, String>? = null,
override var backgroundPosterUrl: String? = null,
override var logourl: String? = null,
override var contentRating: String? = null,
override var uniqueUrl: String = url,
val id: Int?,
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/res/layout/fragment_result.xml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,17 @@
android:layout_height="60dp"
android:layout_gravity="bottom"
android:background="@drawable/background_shadow" />

<ImageView
android:id="@+id/background_poster_watermark_badge"
android:layout_width="160dp"
android:layout_height="56dp"
android:layout_gravity="bottom|start"
android:layout_marginStart="18dp"
android:layout_marginBottom="15dp"
android:adjustViewBounds="true"
android:scaleType="fitStart"
android:foregroundGravity="bottom|left" />
</FrameLayout>
</FrameLayout>

Expand Down
16 changes: 14 additions & 2 deletions app/src/main/res/layout/fragment_result_tv.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_height="275dp"
android:visibility="visible">


<com.lagradost.cloudstream3.utils.PercentageCropImageView
android:id="@+id/background_poster"
android:layout_width="match_parent"
Expand All @@ -36,6 +37,16 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
app:cropYCenterOffsetPct="0.20"
tools:src="@drawable/profile_bg_dark_blue" />

<ImageView
android:id="@+id/background_poster_watermark_badge_holder"
android:layout_width="160dp"
android:layout_height="56dp"
android:layout_gravity="bottom|start"
android:layout_marginStart="18dp"
android:layout_marginBottom="45dp"
android:adjustViewBounds="true"
android:scaleType="fitStart" />

<ImageView
android:layout_marginBottom="-1dp"
android:layout_width="match_parent"
Expand All @@ -46,8 +57,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit

<com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/result_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_gravity="center"
android:orientation="vertical"
app:shimmer_auto_start="true"
Expand Down Expand Up @@ -897,6 +908,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:visibility="gone"
app:cardCornerRadius="@dimen/rounded_image_radius">


<ImageView
android:id="@+id/result_poster"
android:layout_width="100dp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,7 @@ interface LoadResponse {
var syncData: MutableMap<String, String>
var posterHeaders: Map<String, String>?
var backgroundPosterUrl: String?
var logourl: String?
var contentRating: String?

var uniqueUrl: String
Expand Down Expand Up @@ -2217,6 +2218,7 @@ constructor(
override var syncData: MutableMap<String, String> = mutableMapOf(),
override var posterHeaders: Map<String, String>? = null,
override var backgroundPosterUrl: String? = null,
override var logourl: String? = null,
override var contentRating: String? = null,
override var uniqueUrl: String = url
) : LoadResponse
Expand Down Expand Up @@ -2277,6 +2279,7 @@ constructor(
override var nextAiring: NextAiring? = null,
override var seasonNames: List<SeasonData>? = null,
override var backgroundPosterUrl: String? = null,
override var logourl: String? = null,
override var contentRating: String? = null,
override var uniqueUrl: String = url
) : LoadResponse, EpisodeResponse {
Expand Down Expand Up @@ -2362,6 +2365,7 @@ constructor(
override var syncData: MutableMap<String, String> = mutableMapOf(),
override var posterHeaders: Map<String, String>? = null,
override var backgroundPosterUrl: String? = null,
override var logourl: String? = null,
override var contentRating: String? = null,
override var uniqueUrl: String = url
) : LoadResponse
Expand Down Expand Up @@ -2410,6 +2414,7 @@ constructor(
override var syncData: MutableMap<String, String> = mutableMapOf(),
override var posterHeaders: Map<String, String>? = null,
override var backgroundPosterUrl: String? = null,
override var logourl: String? = null,
override var contentRating: String? = null,
override var uniqueUrl: String = url
) : LoadResponse
Expand Down Expand Up @@ -2589,6 +2594,7 @@ constructor(
override var nextAiring: NextAiring? = null,
override var seasonNames: List<SeasonData>? = null,
override var backgroundPosterUrl: String? = null,
override var logourl: String? = null,
override var contentRating: String? = null,
override var uniqueUrl: String = url
) : LoadResponse, EpisodeResponse {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.lagradost.cloudstream3.extractors

import com.lagradost.api.Log
import com.lagradost.cloudstream3.Prerelease
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.newExtractorLink

@Prerelease
class BuzzServer : ExtractorApi() {
override val name = "BuzzServer"
override val mainUrl = "https://buzzheavier.com"
override val requiresReferer = true

override suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
try {
val qualityText = app.get(url).documentLarge.selectFirst("div.max-w-2xl > span")?.text()
val quality = getQualityFromName(qualityText)
val response = app.get("$url/download", referer = url, allowRedirects = false)
val redirectUrl = response.headers["hx-redirect"] ?: ""

if (redirectUrl.isNotEmpty()) {
callback.invoke(
newExtractorLink(
"BuzzServer",
"BuzzServer",
redirectUrl,
) {
this.quality = quality
}
)
} else {
Log.w("BuzzServer", "No redirect URL found in headers.")
}
} catch (e: Exception) {
Log.e("BuzzServer", "Exception occurred: ${e.message}")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.httpsify
import com.lagradost.cloudstream3.utils.newExtractorLink

Expand All @@ -19,18 +20,28 @@ open class Krakenfiles : ExtractorApi() {
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val id = Regex("/(?:view|embed-video)/([\\da-zA-Z]+)").find(url)?.groupValues?.get(1)
val id = Regex("/(?:view|embed-video)/([\\da-zA-Z]+)")
.find(url)
?.groupValues
?.get(1)
?: return

val doc = app.get("$mainUrl/embed-video/$id").document
val link = doc.selectFirst("source")?.attr("src")
val title = doc.select("span.coin-name").text()
val link = doc.selectFirst("source")?.attr("src") ?: return
val quality = getQualityFromName(title)


callback.invoke(
callback(
newExtractorLink(
this.name,
this.name,
httpsify(link ?: return),
)
name,
name,
httpsify(link)
) {
this.quality = quality
}
)

}

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.lagradost.cloudstream3.extractors.BigwarpArt
import com.lagradost.cloudstream3.extractors.BigwarpIO
import com.lagradost.cloudstream3.extractors.Blogger
import com.lagradost.cloudstream3.extractors.BullStream
import com.lagradost.cloudstream3.extractors.BuzzServer
import com.lagradost.cloudstream3.extractors.ByseSX
import com.lagradost.cloudstream3.extractors.Bysezejataos
import com.lagradost.cloudstream3.extractors.ByteShare
Expand Down Expand Up @@ -791,15 +792,26 @@ enum class Qualities(var value: Int, val defaultPriority: Int) {
}
}

private val QUALITY_REGEX_MAP = listOf(
Regex("""\b(4k|2160p?|2160)\b""", RegexOption.IGNORE_CASE) to Qualities.P2160.value,
Regex("""\b1440p?|1440\b""", RegexOption.IGNORE_CASE) to Qualities.P1440.value,
Regex("""\b1080p?|1080\b""", RegexOption.IGNORE_CASE) to Qualities.P1080.value,
Regex("""\b720p?|720\b""", RegexOption.IGNORE_CASE) to Qualities.P720.value,
Regex("""\b480p?|480\b""", RegexOption.IGNORE_CASE) to Qualities.P480.value
)
private var lastResolvedQuality: Int = Qualities.Unknown.value

fun getQualityFromName(qualityName: String?): Int {
if (qualityName == null)
return Qualities.Unknown.value

val match = qualityName.lowercase().replace("p", "").trim()
return when (match) {
"4k" -> Qualities.P2160
else -> null
}?.value ?: match.toIntOrNull() ?: Qualities.Unknown.value
if (qualityName.isNullOrBlank())
return lastResolvedQuality

for ((regex, quality) in QUALITY_REGEX_MAP) {
if (regex.containsMatchIn(qualityName)) {
lastResolvedQuality = maxOf(lastResolvedQuality, quality)
return lastResolvedQuality
}
}
return lastResolvedQuality
}

private val packedRegex = Regex("""eval\(function\(p,a,c,k,e,.*\)\)""")
Expand Down Expand Up @@ -1077,6 +1089,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf(
Fembed9hd(),
StreamM4u(),
Krakenfiles(),
BuzzServer(),
Gofile(),
Vicloud(),
Uservideo(),
Expand Down