mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-11-04 00:25:15 +00:00 
			
		
		
		
	Using https://github.com/asottile/pyupgrade 1. `__future__` imports and `coding: utf-8` were removed 2. Files were rewritten with `pyupgrade --py36-plus --keep-percent-format` 3. f-strings were cherry-picked from `pyupgrade --py36-plus` Extractors are left untouched (except removing header) to avoid unnecessary merge conflicts
		
			
				
	
	
		
			163 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import functools
 | 
						|
import json
 | 
						|
 | 
						|
from .common import InfoExtractor
 | 
						|
from ..utils import (
 | 
						|
    ExtractorError,
 | 
						|
    OnDemandPagedList,
 | 
						|
    determine_ext,
 | 
						|
    int_or_none,
 | 
						|
    try_get,
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
class MurrtubeIE(InfoExtractor):
 | 
						|
    _VALID_URL = r'''(?x)
 | 
						|
                        (?:
 | 
						|
                            murrtube:|
 | 
						|
                            https?://murrtube\.net/videos/(?P<slug>[a-z0-9\-]+)\-
 | 
						|
                        )
 | 
						|
                        (?P<id>[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})
 | 
						|
                    '''
 | 
						|
    _TEST = {
 | 
						|
        'url': 'https://murrtube.net/videos/inferno-x-skyler-148b6f2a-fdcc-4902-affe-9c0f41aaaca0',
 | 
						|
        'md5': '169f494812d9a90914b42978e73aa690',
 | 
						|
        'info_dict': {
 | 
						|
            'id': '148b6f2a-fdcc-4902-affe-9c0f41aaaca0',
 | 
						|
            'ext': 'mp4',
 | 
						|
            'title': 'Inferno X Skyler',
 | 
						|
            'description': 'Humping a very good slutty sheppy (roomate)',
 | 
						|
            'thumbnail': r're:^https?://.*\.jpg$',
 | 
						|
            'duration': 284,
 | 
						|
            'uploader': 'Inferno Wolf',
 | 
						|
            'age_limit': 18,
 | 
						|
            'comment_count': int,
 | 
						|
            'view_count': int,
 | 
						|
            'like_count': int,
 | 
						|
            'tags': ['hump', 'breed', 'Fursuit', 'murrsuit', 'bareback'],
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    def _download_gql(self, video_id, op, note=None, fatal=True):
 | 
						|
        result = self._download_json(
 | 
						|
            'https://murrtube.net/graphql',
 | 
						|
            video_id, note, data=json.dumps(op).encode(), fatal=fatal,
 | 
						|
            headers={'Content-Type': 'application/json'})
 | 
						|
        return result['data']
 | 
						|
 | 
						|
    def _real_extract(self, url):
 | 
						|
        video_id = self._match_id(url)
 | 
						|
        data = self._download_gql(video_id, {
 | 
						|
            'operationName': 'Medium',
 | 
						|
            'variables': {
 | 
						|
                'id': video_id,
 | 
						|
            },
 | 
						|
            'query': '''\
 | 
						|
query Medium($id: ID!) {
 | 
						|
  medium(id: $id) {
 | 
						|
    title
 | 
						|
    description
 | 
						|
    key
 | 
						|
    duration
 | 
						|
    commentsCount
 | 
						|
    likesCount
 | 
						|
    viewsCount
 | 
						|
    thumbnailKey
 | 
						|
    tagList
 | 
						|
    user {
 | 
						|
      name
 | 
						|
      __typename
 | 
						|
    }
 | 
						|
    __typename
 | 
						|
  }
 | 
						|
}'''})
 | 
						|
        meta = data['medium']
 | 
						|
 | 
						|
        storage_url = 'https://storage.murrtube.net/murrtube/'
 | 
						|
        format_url = storage_url + meta.get('key', '')
 | 
						|
        thumbnail = storage_url + meta.get('thumbnailKey', '')
 | 
						|
 | 
						|
        if determine_ext(format_url) == 'm3u8':
 | 
						|
            formats = self._extract_m3u8_formats(
 | 
						|
                format_url, video_id, 'mp4', entry_protocol='m3u8_native', fatal=False)
 | 
						|
        else:
 | 
						|
            formats = [{'url': format_url}]
 | 
						|
 | 
						|
        return {
 | 
						|
            'id': video_id,
 | 
						|
            'title': meta.get('title'),
 | 
						|
            'description': meta.get('description'),
 | 
						|
            'formats': formats,
 | 
						|
            'thumbnail': thumbnail,
 | 
						|
            'duration': int_or_none(meta.get('duration')),
 | 
						|
            'uploader': try_get(meta, lambda x: x['user']['name']),
 | 
						|
            'view_count': meta.get('viewsCount'),
 | 
						|
            'like_count': meta.get('likesCount'),
 | 
						|
            'comment_count': meta.get('commentsCount'),
 | 
						|
            'tags': meta.get('tagList'),
 | 
						|
            'age_limit': 18,
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
class MurrtubeUserIE(MurrtubeIE):
 | 
						|
    IE_DESC = 'Murrtube user profile'
 | 
						|
    _VALID_URL = r'https?://murrtube\.net/(?P<id>[^/]+)$'
 | 
						|
    _TEST = {
 | 
						|
        'url': 'https://murrtube.net/stormy',
 | 
						|
        'info_dict': {
 | 
						|
            'id': 'stormy',
 | 
						|
        },
 | 
						|
        'playlist_mincount': 27,
 | 
						|
    }
 | 
						|
    _PAGE_SIZE = 10
 | 
						|
 | 
						|
    def _fetch_page(self, username, user_id, page):
 | 
						|
        data = self._download_gql(username, {
 | 
						|
            'operationName': 'Media',
 | 
						|
            'variables': {
 | 
						|
                'limit': self._PAGE_SIZE,
 | 
						|
                'offset': page * self._PAGE_SIZE,
 | 
						|
                'sort': 'latest',
 | 
						|
                'userId': user_id,
 | 
						|
            },
 | 
						|
            'query': '''\
 | 
						|
query Media($q: String, $sort: String, $userId: ID, $offset: Int!, $limit: Int!) {
 | 
						|
  media(q: $q, sort: $sort, userId: $userId, offset: $offset, limit: $limit) {
 | 
						|
    id
 | 
						|
    __typename
 | 
						|
  }
 | 
						|
}'''},
 | 
						|
            'Downloading page {0}'.format(page + 1))
 | 
						|
        if data is None:
 | 
						|
            raise ExtractorError(f'Failed to retrieve video list for page {page + 1}')
 | 
						|
 | 
						|
        media = data['media']
 | 
						|
 | 
						|
        for entry in media:
 | 
						|
            yield self.url_result('murrtube:{0}'.format(entry['id']), MurrtubeIE.ie_key())
 | 
						|
 | 
						|
    def _real_extract(self, url):
 | 
						|
        username = self._match_id(url)
 | 
						|
        data = self._download_gql(username, {
 | 
						|
            'operationName': 'User',
 | 
						|
            'variables': {
 | 
						|
                'id': username,
 | 
						|
            },
 | 
						|
            'query': '''\
 | 
						|
query User($id: ID!) {
 | 
						|
  user(id: $id) {
 | 
						|
    id
 | 
						|
    __typename
 | 
						|
  }
 | 
						|
}'''},
 | 
						|
            'Downloading user info')
 | 
						|
        if data is None:
 | 
						|
            raise ExtractorError('Failed to fetch user info')
 | 
						|
 | 
						|
        user = data['user']
 | 
						|
 | 
						|
        entries = OnDemandPagedList(functools.partial(
 | 
						|
            self._fetch_page, username, user.get('id')), self._PAGE_SIZE)
 | 
						|
 | 
						|
        return self.playlist_result(entries, username)
 |