Skip to content

Commit 8ede70d

Browse files
errorcodeQQerrorcodeQQ
authored andcommitted
fix: add browser headers and fallback mirrors for PPV streams
1 parent a457a59 commit 8ede70d

1 file changed

Lines changed: 38 additions & 69 deletions

File tree

BinTV/src/main/kotlin/com/bintv/BinTVProvider.kt

Lines changed: 38 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -203,96 +203,59 @@ class BinTVProvider : MainAPI() {
203203

204204
// Fetch PPV matches
205205
val ppvMatches = mutableListOf<EventLoadData>()
206-
try {
207-
val ppvText = app.get("https://old.ppv.to/api/streams", timeout = 15L).text
208-
val ppvResponse = parseJson<PpvStreamsResponse>(ppvText)
209-
if (ppvResponse.success && !ppvResponse.streams.isNullOrEmpty()) {
210-
val now = System.currentTimeMillis()
211-
ppvResponse.streams.forEach { group ->
212-
if (group.category == "24/7 Streams") return@forEach
213-
group.streams?.forEach { stream ->
214-
val name = stream.name ?: ""
215-
if (name.isBlank()) return@forEach
216-
val startMs = (stream.starts_at ?: 0) * 1000L
217-
val endMs = (stream.ends_at ?: 0) * 1000L
218-
// Filter ended matches
219-
if (stream.ends_at != null && endMs < now - 600000L) return@forEach
220-
221-
val iframes = mutableListOf<MatchSource>()
222-
if (!stream.iframe.isNullOrBlank()) {
223-
// Get stream name
224-
val mainName = stream.source_tag?.takeIf { it.isNotBlank() } ?: "Main"
225-
iframes.add(MatchSource(mainName, stream.iframe))
226-
}
227-
stream.substreams?.forEachIndexed { subIdx, sub ->
228-
if (!sub.iframe.isNullOrBlank() && iframes.none { it.url == sub.iframe }) {
229-
// Get fallback name
230-
val rawName = sub.uri_name?.takeIf { it.isNotBlank() }
231-
?: sub.source_tag?.takeIf { it.isNotBlank() }
232-
?: sub.name?.takeIf { it.isNotBlank() }
233-
?: "Server ${subIdx + 1}"
234-
// Normalize name
235-
val prettyName = rawName
236-
.split("-").joinToString(" ") { part ->
237-
if (part.length <= 3) part.uppercase()
238-
else part.replaceFirstChar { it.uppercase() }
239-
}
240-
iframes.add(MatchSource(prettyName, sub.iframe))
241-
}
242-
}
243-
244-
if (iframes.isEmpty()) return@forEach
245-
246-
val numberedSources = iframes.mapIndexed { idx, src ->
247-
MatchSource(
248-
name = "${src.name} [${idx + 1}]",
249-
url = src.url
250-
)
251-
}
206+
val ppvUrls = listOf(
207+
"https://old.ppv.to/api/streams",
208+
"https://api.ppv.to/api/streams",
209+
"https://api.ppv.cx/api/streams"
210+
)
211+
val ppvHeaders = mapOf(
212+
"User-Agent" to "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36",
213+
"Referer" to "https://www.bintv.net/",
214+
"Origin" to "https://www.bintv.net"
215+
)
252216

253-
ppvMatches.add(
254-
EventLoadData(
255-
title = name,
256-
poster = stream.poster,
257-
date = startMs,
258-
endsAt = endMs,
259-
category = stream.category_name ?: group.category ?: "Other",
260-
sources = numberedSources,
261-
isPPV = true,
262-
isBinTV = false
263-
)
264-
)
265-
}
217+
var ppvText = ""
218+
for (url in ppvUrls) {
219+
try {
220+
val res = app.get(url, headers = ppvHeaders, timeout = 15L)
221+
if (res.code == 200 && res.text.isNotBlank()) {
222+
ppvText = res.text
223+
break
266224
}
225+
} catch (e: Exception) {
226+
println("BinTV: failed to load PPV matches from $url - ${e.message}")
267227
}
268-
} catch (e: Exception) {
269-
println("BinTV: failed to load PPV matches - ${e.message}")
270-
// Fallback API
228+
}
229+
230+
if (ppvText.isNotBlank()) {
271231
try {
272-
val fallbackText = app.get("https://api.ppv.to/api/streams", timeout = 15L).text
273-
val fallbackResponse = parseJson<PpvStreamsResponse>(fallbackText)
274-
if (fallbackResponse.success && !fallbackResponse.streams.isNullOrEmpty()) {
232+
val ppvResponse = parseJson<PpvStreamsResponse>(ppvText)
233+
if (ppvResponse.success && !ppvResponse.streams.isNullOrEmpty()) {
275234
val now = System.currentTimeMillis()
276-
fallbackResponse.streams.forEach { group ->
235+
ppvResponse.streams.forEach { group ->
277236
if (group.category == "24/7 Streams") return@forEach
278237
group.streams?.forEach { stream ->
279238
val name = stream.name ?: ""
280239
if (name.isBlank()) return@forEach
281240
val startMs = (stream.starts_at ?: 0) * 1000L
282241
val endMs = (stream.ends_at ?: 0) * 1000L
242+
// Filter ended matches
283243
if (stream.ends_at != null && endMs < now - 600000L) return@forEach
284244

285245
val iframes = mutableListOf<MatchSource>()
286246
if (!stream.iframe.isNullOrBlank()) {
247+
// Get stream name
287248
val mainName = stream.source_tag?.takeIf { it.isNotBlank() } ?: "Main"
288249
iframes.add(MatchSource(mainName, stream.iframe))
289250
}
290251
stream.substreams?.forEachIndexed { subIdx, sub ->
291252
if (!sub.iframe.isNullOrBlank() && iframes.none { it.url == sub.iframe }) {
253+
// Get fallback name
292254
val rawName = sub.uri_name?.takeIf { it.isNotBlank() }
293255
?: sub.source_tag?.takeIf { it.isNotBlank() }
294256
?: sub.name?.takeIf { it.isNotBlank() }
295257
?: "Server ${subIdx + 1}"
258+
// Normalize name
296259
val prettyName = rawName
297260
.split("-").joinToString(" ") { part ->
298261
if (part.length <= 3) part.uppercase()
@@ -301,10 +264,16 @@ class BinTVProvider : MainAPI() {
301264
iframes.add(MatchSource(prettyName, sub.iframe))
302265
}
303266
}
267+
304268
if (iframes.isEmpty()) return@forEach
269+
305270
val numberedSources = iframes.mapIndexed { idx, src ->
306-
MatchSource(name = "${src.name} [${idx + 1}]", url = src.url)
271+
MatchSource(
272+
name = "${src.name} [${idx + 1}]",
273+
url = src.url
274+
)
307275
}
276+
308277
ppvMatches.add(
309278
EventLoadData(
310279
title = name,
@@ -320,8 +289,8 @@ class BinTVProvider : MainAPI() {
320289
}
321290
}
322291
}
323-
} catch (fallbackErr: Exception) {
324-
println("BinTV: PPV fallback also failed - ${fallbackErr.message}")
292+
} catch (e: Exception) {
293+
println("BinTV: failed to parse PPV JSON - ${e.message}")
325294
}
326295
}
327296

0 commit comments

Comments
 (0)