Upload 2 files
Browse files- sources/filemoon.py +36 -0
- sources/vidplay.py +73 -0
sources/filemoon.py
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import re
|
2 |
+
import requests
|
3 |
+
from utils import Utilities
|
4 |
+
from typing import Optional, Tuple, Dict, Any
|
5 |
+
|
6 |
+
class FilemoonExtractor:
|
7 |
+
@staticmethod
|
8 |
+
def unpack(p: str, a: int, c: int, k: list, e: Optional[Any]=None, d: Optional[Any]=None) -> str:
|
9 |
+
for i in range(c-1, -1, -1):
|
10 |
+
if k[i]: p = re.sub("\\b"+Utilities.int_2_base(i,a)+"\\b", k[i], p)
|
11 |
+
return p
|
12 |
+
|
13 |
+
def resolve_source(self, url: str, **kwargs: Dict[str, Any]) -> Tuple[Optional[str], None, Optional[str]]:
|
14 |
+
req = requests.get(url)
|
15 |
+
if req.status_code != 200:
|
16 |
+
print(f"[FilemoonExtractor] Failed to retrieve media, status code: {req.status_code}...")
|
17 |
+
return None, None, None
|
18 |
+
|
19 |
+
matches = re.search(r"eval\(function\(p,a,c,k,e,d\).*?\}\('(.*?)'\.split", req.text)
|
20 |
+
if not matches:
|
21 |
+
print("[FilemoonExtractor] Failed to retrieve media, could not find eval function...")
|
22 |
+
return None, None, None
|
23 |
+
|
24 |
+
DE_packer_args = re.search(r"^(.*?}\);)\',(.*?),(.*?),'(.*?)$", matches.group(1))
|
25 |
+
processed_matches = list(DE_packer_args.groups())
|
26 |
+
processed_matches[1] = int(processed_matches[1])
|
27 |
+
processed_matches[2] = int(processed_matches[2])
|
28 |
+
processed_matches[3] = processed_matches[3].split("|")
|
29 |
+
|
30 |
+
unpacked = self.unpack(*processed_matches)
|
31 |
+
hls_urls = re.findall(r"\{file:\"([^\"]*)\"\}", unpacked)
|
32 |
+
|
33 |
+
# hls_filename = hls_urls[0].split("?")[0].rsplit("/")[-1]
|
34 |
+
# mp4_url = hls_urls[0].replace("hls2", "download") #.replace(hls_filename, "media") # filename is arbitrary
|
35 |
+
|
36 |
+
return hls_urls, None, url
|
sources/vidplay.py
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import re
|
2 |
+
import json
|
3 |
+
import base64
|
4 |
+
import requests
|
5 |
+
from urllib.parse import unquote
|
6 |
+
from typing import Optional, Tuple, Dict, List
|
7 |
+
from utils import Utilities, CouldntFetchKeys
|
8 |
+
|
9 |
+
class VidplayExtractor:
|
10 |
+
KEY_URL = "https://github.com/Ciarands/vidsrc-keys/blob/main/keys.json"
|
11 |
+
|
12 |
+
@staticmethod
|
13 |
+
def get_futoken(key: str, url: str, provider_url: str) -> str:
|
14 |
+
req = requests.get(f"{provider_url}/futoken", headers={"Referer": url})
|
15 |
+
fu_key = re.search(r"var\s+k\s*=\s*'([^']+)'", req.text).group(1)
|
16 |
+
|
17 |
+
return f"{fu_key},{','.join([str(ord(fu_key[i % len(fu_key)]) + ord(key[i])) for i in range(len(key))])}"
|
18 |
+
|
19 |
+
@staticmethod
|
20 |
+
def get_vidplay_subtitles(url_data: str) -> Dict:
|
21 |
+
subtitles_url = re.search(r"info=([^&]+)", url_data)
|
22 |
+
if not subtitles_url:
|
23 |
+
return {}
|
24 |
+
|
25 |
+
subtitles_url_formatted = unquote(subtitles_url.group(1))
|
26 |
+
req = requests.get(subtitles_url_formatted)
|
27 |
+
|
28 |
+
if req.status_code == 200:
|
29 |
+
return {subtitle.get("label"): subtitle.get("file") for subtitle in req.json()}
|
30 |
+
|
31 |
+
return {}
|
32 |
+
|
33 |
+
@staticmethod
|
34 |
+
def encode_id(v_id: str) -> str:
|
35 |
+
req = requests.get(VidplayExtractor.KEY_URL)
|
36 |
+
|
37 |
+
if req.status_code != 200:
|
38 |
+
raise CouldntFetchKeys("Failed to fetch decryption keys!")
|
39 |
+
|
40 |
+
matches = re.search(r"\"rawLines\":\s*\[\"(.+)\"\]", req.text)
|
41 |
+
if not matches:
|
42 |
+
raise CouldntFetchKeys("Failed to extract rawLines from keys page!")
|
43 |
+
|
44 |
+
key1, key2 = json.loads(matches.group(1).replace("\\", ""))
|
45 |
+
decoded_id = Utilities.decode_data(key1, v_id)
|
46 |
+
encoded_result = Utilities.decode_data(key2, decoded_id)
|
47 |
+
|
48 |
+
encoded_base64 = base64.b64encode(encoded_result)
|
49 |
+
decoded_result = encoded_base64.decode("utf-8")
|
50 |
+
|
51 |
+
return decoded_result.replace("/", "_")
|
52 |
+
|
53 |
+
def resolve_source(self, url: str, fetch_subtitles: bool, provider_url: str) -> Tuple[Optional[List], Optional[Dict], Optional[str]]:
|
54 |
+
url_data = url.split("?")
|
55 |
+
|
56 |
+
subtitles = {}
|
57 |
+
if fetch_subtitles:
|
58 |
+
subtitles = self.get_vidplay_subtitles(url_data[1])
|
59 |
+
|
60 |
+
key = self.encode_id(url_data[0].split("/e/")[-1])
|
61 |
+
futoken = self.get_futoken(key, url, provider_url)
|
62 |
+
|
63 |
+
req = requests.get(f"{provider_url}/mediainfo/{futoken}?{url_data[1]}&autostart=true", headers={"Referer": url})
|
64 |
+
if req.status_code != 200:
|
65 |
+
print(f"[VidplayExtractor] Failed to retrieve media, status code: {req.status_code}...")
|
66 |
+
return None, None, None
|
67 |
+
|
68 |
+
req_data = req.json()
|
69 |
+
if (req_data.get("result")) and (type(req_data.get("result")) == dict):
|
70 |
+
sources = req_data.get("result").get("sources")
|
71 |
+
return [value.get("file") for value in sources], subtitles, url
|
72 |
+
|
73 |
+
return None, None, None
|