from .common import InfoExtractor from ..postprocessor.ffmpeg import FFmpegPostProcessor from ..utils import ( ExtractorError, extract_attributes, float_or_none, get_element_by_id, get_element_by_class, get_element_html_by_class, get_element_html_by_id, int_or_none, PostProcessingError, strip_or_none, str_or_none, str_to_int, traverse_obj, try_call, unified_timestamp, ) class RobloxIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?roblox\.com/library/(?P\d+)' _TESTS = [{ # UGC Audio 'url': 'https://www.roblox.com/library/7910582982/Backrooms-Ambiance-High-Quality', 'md5': '', 'info_dict': { 'id': '7910582982', 'ext': 'ogg', 'title': 'Backrooms Ambiance (High Quality)', 'description': 'Found an actual higher quality of the sound.', 'uploader': 'ChaseDJ549', 'uploader_id': '412014916', 'categories': ['Horror'], 'like_count': int, 'timestamp': 1636142127, 'modified_timestamp': 1656694893 }, }] def _real_extract(self, url): asset_id = self._match_id(url) webpage = self._download_webpage(url, asset_id) item_container_div = get_element_html_by_id('item-container', webpage) item_container_attrs = extract_attributes(item_container_div[:item_container_div.find('>')+1]) asset_type = item_container_attrs.get('data-asset-type') if asset_type and (asset_type not in ('Audio', 'Video')): raise ExtractorError('This asset is not an audio/video', expected=True) asset_uploader_id, asset_uploader_name = self._search_regex( r'>By \d+)[^"\']*["\'][^>]*>@?(?P\w+)