import base64 import json import urllib.parse from datetime import datetime from Crypto.Cipher import AES from yt_dlp.extractor.common import InfoExtractor class FilemoonIE(InfoExtractor): _valid_domains = r'|'.join([ r'filemoon\.sx', r'bysejikuar\.com', r'bysedikamoum\.com', r'byse\.sx', r'byseraguci\.com', r'bysezejataos\.com', r'filemoon\.to', r'filemoon\.eu', r'filemooon\.link', r'morgan0928-6v7c14vs\.fun', r'bf0skv\.org', r'ghajini-emtftw1o\.lol', r'f51rm\.com', r'filemooon\.link', r'bysekoze\.com', r'bysesayeveum\.com' ]) _VALID_URL = r'https?://(?:' + _valid_domains + ')/(?:d|e)/(?P[^?#]+)?$' def fix_base64(self, text): replaced = text.replace('-','+').replace('_','/') padding_length = 0 if (len(replaced) % 4 == 0) else 4 - len(replaced) % 4 return base64.b64decode(replaced + '=' * padding_length) def fix_key_parts(self, key_parts): fixed = [self.fix_base64(key_part) for key_part in key_parts] return b''.join(fixed) def _real_extract(self, url): video_id = urllib.parse.unquote_plus(self._match_id(url)) metadata = self._download_json(f'https://filemoon.to/api/videos/{video_id}/details', video_id) playback = self._download_json(f'https://filemoon.to/api/videos/{video_id}/playback', video_id) iv = self.fix_base64(playback['playback']['iv']) ciphertext = self.fix_base64(playback['playback']['payload']) key = self.fix_key_parts(playback['playback']['key_parts']) cipher = AES.new(key, AES.MODE_GCM, nonce=iv) plaintext = cipher.decrypt_and_verify(ciphertext[:-16], ciphertext[-16:]) content = json.loads(plaintext.decode('utf8')) print(json.dumps(content, indent=4)) m3u8_url = content['sources'][0]['url'] formats = self._extract_m3u8_formats( m3u8_url, video_id, 'mp4', 'm3u8_native', m3u8_id='hls') created_at = datetime.fromisoformat(metadata['created_at']).strftime('%Y%m%d') ret = { 'id': video_id, 'display_id': video_id, 'title': metadata['title'], 'thumbnail': f'https://img-place.com/{video_id}.jpg', 'upload_date': created_at, 'formats': formats, } print(json.dumps(ret, indent=4)) return ret