-
Notifications
You must be signed in to change notification settings - Fork 800
Expand file tree
/
Copy pathFilemoon.kt
More file actions
118 lines (99 loc) · 3.84 KB
/
Filemoon.kt
File metadata and controls
118 lines (99 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package com.lagradost.cloudstream3.extractors
import com.lagradost.api.Log
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper
import com.lagradost.cloudstream3.network.WebViewResolver
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.JsUnpacker
import com.lagradost.cloudstream3.utils.M3u8Helper
class FileMoon : FilemoonV2() {
override var mainUrl = "https://filemoon.to"
override var name = "FileMoon"
}
class FileMoonIn : FilemoonV2() {
override var mainUrl = "https://filemoon.in"
override var name = "FileMoon"
}
class FileMoonSx : FilemoonV2() {
override var mainUrl = "https://filemoon.sx"
override var name = "FileMoonSx"
}
open class FilemoonV2 : ExtractorApi() {
override var name = "Filemoon"
override var mainUrl = "https://filemoon.to"
override val requiresReferer = true
override suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val defaultHeaders = mapOf(
"Referer" to url,
"Sec-Fetch-Dest" to "iframe",
"Sec-Fetch-Mode" to "navigate",
"Sec-Fetch-Site" to "cross-site",
"User-Agent" to "Mozilla/5.0 (X11; Linux x86_64; rv:137.0) Gecko/20100101 Firefox/137.0"
)
val initialResponse = app.get(url, defaultHeaders)
val iframeSrcUrl = initialResponse.document.selectFirst("iframe")?.attr("src")
if (iframeSrcUrl.isNullOrEmpty()) {
val fallbackScriptData = initialResponse.document
.selectFirst("script:containsData(function(p,a,c,k,e,d))")
?.data().orEmpty()
val unpackedScript = JsUnpacker(fallbackScriptData).unpack()
val linkFound = JwPlayerHelper.extractStreamLinks(
unpackedScript.orEmpty(),
name,
mainUrl,
callback,
subtitleCallback,
defaultHeaders
)
if (!linkFound) {
Log.d("FilemoonV2", "No iframe and no video URL found in script fallback.")
}
return
}
// If iframe was found, continue processing
val iframeHeaders = defaultHeaders + ("Accept-Language" to "en-US,en;q=0.5")
val iframeResponse = app.get(iframeSrcUrl, headers = iframeHeaders)
val iframeScriptData = iframeResponse.document
.selectFirst("script:containsData(function(p,a,c,k,e,d))")
?.data().orEmpty()
val unpackedScript = JsUnpacker(iframeScriptData).unpack()
val linkFound = JwPlayerHelper.extractStreamLinks(
unpackedScript.orEmpty(),
name,
mainUrl,
callback,
subtitleCallback
)
if (!linkFound) {
// Last-resort fallback using WebView interception
val resolver = WebViewResolver(
interceptUrl = Regex("""(m3u8|master\.txt)"""),
additionalUrls = listOf(Regex("""(m3u8|master\.txt)""")),
useOkhttp = false,
timeout = 15_000L
)
val interceptedUrl = app.get(
iframeSrcUrl,
referer = referer,
interceptor = resolver
).url
if (interceptedUrl.isNotEmpty()) {
M3u8Helper.generateM3u8(
name,
interceptedUrl,
mainUrl,
headers = defaultHeaders
).forEach(callback)
} else {
Log.d("FilemoonV2", "No video URL intercepted in WebView fallback.")
}
}
}
}