[VXXX] Refactor and apply further code review suggestions

This commit is contained in:
tabjy 2022-10-29 02:35:12 -04:00
parent 8414d8d8f5
commit 9d2b2f9b1e
7 changed files with 144 additions and 251 deletions

View File

@ -1,44 +0,0 @@
# coding: utf-8
from __future__ import unicode_literals
from .vxxx import VXXXIE
class BdsmxTubeIE(VXXXIE):
_VALID_URL = r'https?://bdsmx\.tube/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://bdsmx.tube/video/127583/latex-puppy-leashed/',
'md5': '79751d4ed75668afe07a660c4bcb2f1b',
'info_dict': {
'id': '127583',
'ext': 'mp4',
'title': 'Latex Puppy Leashed',
'display_id': 'latex-puppy-leashed',
'thumbnail': 'https://tn.bdsmx-porn.com/contents/videos_screenshots/127000/127583/480x270/1.jpg',
'description': '',
'timestamp': 1651003323,
'upload_date': '20220426',
'duration': 68.0,
'categories': ['Asian', 'Brunette', 'Cosplay', 'Fetish',
'Fuck Machine', 'Gagging', 'Japanese',
'JAV Uncensored', 'Latex', 'Leather', 'POV'],
'age_limit': 18,
}
}]
def _download_info_object(self, video_id):
return self._download_json(
'https://bdsmx.tube/api/json/video/86400/0/{0}/{1}.json'.format(
int(video_id) // 1000 * 1000,
video_id,
), video_id, headers={'Referer': 'https://bdsmx.tube'})['video']
def _download_format_object(self, video_id):
return self._download_json(
'https://bdsmx.tube/api/videofile.php?video_id={0}'.format(video_id),
video_id,
headers={'Referer': 'https://bdsmx.tube'}
)
def _get_video_host(self):
return 'bdsmx.tube'

View File

@ -1,44 +0,0 @@
# coding: utf-8
from __future__ import unicode_literals
from .vxxx import VXXXIE
class BlackPornTubeIE(VXXXIE):
_VALID_URL = r'https?://blackporn\.tube/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://blackporn.tube/video/10043813/young-ebony-babe-gets-super-wet/',
'md5': '4a4c126970f2f1453b8b2050947fc870',
'info_dict': {
'id': '10043813',
'ext': 'mp4',
'title': 'Young Ebony Babe Gets Super Wet',
'display_id': 'young-ebony-babe-gets-super-wet',
'thumbnail': 'https://tn.blackporn.tube/contents/videos_screenshots/10043000/10043813/480x270/1.jpg',
'description': '',
'timestamp': 1654806141,
'upload_date': '20220609',
'duration': 193.0,
'categories': ['BDSM', 'Bondage', 'Celebrity', 'Ebony', 'Fetish',
'Shibari Bondage', 'Solo Female',
'Tattoo'],
'age_limit': 18,
}
}]
def _download_info_object(self, video_id):
return self._download_json(
'https://blackporn.tube/api/json/video/86400/0/{}/{}.json'.format(
int(video_id) // 1000 * 1000,
video_id,
), video_id, headers={'Referer': 'https://blackporn.tube'})['video']
def _download_format_object(self, video_id):
return self._download_json(
'https://blackporn.tube/api/videofile.php?video_id={}'.format(video_id),
video_id,
headers={'Referer': 'https://blackporn.tube'}
)
def _get_video_host(self):
return 'blackporn.tube'

View File

@ -106,7 +106,6 @@ from .bbc import (
BBCCoUkPlaylistIE, BBCCoUkPlaylistIE,
BBCIE, BBCIE,
) )
from .bdsmxtube import BdsmxTubeIE
from .beeg import BeegIE from .beeg import BeegIE
from .behindkink import BehindKinkIE from .behindkink import BehindKinkIE
from .bellmedia import BellMediaIE from .bellmedia import BellMediaIE
@ -139,7 +138,6 @@ from .bleacherreport import (
BleacherReportIE, BleacherReportIE,
BleacherReportCMSIE, BleacherReportCMSIE,
) )
from .blackporntube import BlackPornTubeIE
from .bloomberg import BloombergIE from .bloomberg import BloombergIE
from .bokecc import BokeCCIE from .bokecc import BokeCCIE
from .bongacams import BongaCamsIE from .bongacams import BongaCamsIE
@ -522,7 +520,6 @@ from .instagram import (
) )
from .internazionale import InternazionaleIE from .internazionale import InternazionaleIE
from .internetvideoarchive import InternetVideoArchiveIE from .internetvideoarchive import InternetVideoArchiveIE
from .inporn import InPornIE
from .iprima import IPrimaIE from .iprima import IPrimaIE
from .iqiyi import IqiyiIE from .iqiyi import IqiyiIE
from .ir90tv import Ir90TvIE from .ir90tv import Ir90TvIE
@ -675,7 +672,6 @@ from .metacritic import MetacriticIE
from .mgoon import MgoonIE from .mgoon import MgoonIE
from .mgtv import MGTVIE from .mgtv import MGTVIE
from .miaopai import MiaoPaiIE from .miaopai import MiaoPaiIE
from .mrgay import MrGayIE
from .microsoftvirtualacademy import ( from .microsoftvirtualacademy import (
MicrosoftVirtualAcademyIE, MicrosoftVirtualAcademyIE,
MicrosoftVirtualAcademyCourseIE, MicrosoftVirtualAcademyCourseIE,
@ -1589,7 +1585,6 @@ from .ximalaya import (
XimalayaAlbumIE XimalayaAlbumIE
) )
from .xminus import XMinusIE from .xminus import XMinusIE
from .xmilf import XMilfIE
from .xnxx import XNXXIE from .xnxx import XNXXIE
from .xstream import XstreamIE from .xstream import XstreamIE
from .xtube import XTubeUserIE, XTubeIE from .xtube import XTubeUserIE, XTubeIE

View File

@ -1,43 +0,0 @@
# coding: utf-8
from __future__ import unicode_literals
from .vxxx import VXXXIE
class InPornIE(VXXXIE):
_VALID_URL = r'https?://(?:www\.)?inporn\.com/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://inporn.com/video/533613/2k-t-2nd-season-parm-151/',
'md5': 'c358d1da6b451ebe7cfb00dd89741607',
'info_dict': {
'id': '533613',
'ext': 'mp4',
'title': '2k 美月まい - ガーリー系アパレルモt゙ルの挑発パンチラ 2nd Season [parm-151]',
'display_id': '2k-t-2nd-season-parm-151',
'thumbnail': 'https://tn.inporn.com/media/tn/533613_1.jpg',
'description': '',
'timestamp': 1664571262,
'upload_date': '20220930',
'duration': 480.0,
'categories': ['Asian', 'Brunette', 'Casting', 'HD', 'Japanese',
'JAV Uncensored'],
'age_limit': 18,
},
}]
def _download_info_object(self, video_id):
return self._download_json(
'https://inporn.com/api/json/video/86400/0/{}/{}.json'.format(
int(video_id) // 1000 * 1000,
video_id,
), video_id, headers={'Referer': 'https://inporn.com'})['video']
def _download_format_object(self, video_id):
return self._download_json(
'https://inporn.com/api/videofile.php?video_id={}'.format(video_id),
video_id,
headers={'Referer': 'https://inporn.com'}
)
def _get_video_host(self):
return 'inporn.com'

View File

@ -1,43 +0,0 @@
# coding: utf-8
from __future__ import unicode_literals
from .vxxx import VXXXIE
class MrGayIE(VXXXIE):
_VALID_URL = r'https?://mrgay\.com/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://mrgay.com/video/10169199/jpn-crossdresser-6/',
'md5': 'b5780a9437c205b4bc87eb939b23e8ef',
'info_dict': {
'id': '10169199',
'ext': 'mp4',
'title': 'Jpn Crossdresser 6',
'display_id': 'jpn-crossdresser-6',
'thumbnail': 'https://tn.mrgay.com/media/tn/10169199_1.jpg',
'description': '',
'timestamp': 1651066888,
'upload_date': '20220427',
'duration': 834.0,
'categories': ['Amateur', 'Asian', 'Brunette', 'Crossdressing',
'Japanese', 'Webcam'],
'age_limit': 18,
}
}]
def _download_info_object(self, video_id):
return self._download_json(
'https://mrgay.com/api/json/video/86400/0/{}/{}.json'.format(
int(video_id) // 1000 * 1000,
video_id,
), video_id, headers={'Referer': 'https://mrgay.com'})['video']
def _download_format_object(self, video_id):
return self._download_json(
'https://mrgay.com/api/videofile.php?video_id={}'.format(video_id),
video_id,
headers={'Referer': 'https://mrgay.com'}
)
def _get_video_host(self):
return 'mrgay.com'

View File

@ -2,12 +2,15 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import base64 import base64
import re
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
float_or_none,
int_or_none,
parse_duration, parse_duration,
strip_or_none,
unified_timestamp, unified_timestamp,
url_or_none,
) )
@ -22,7 +25,7 @@ class VXXXIE(InfoExtractor):
'title': 'Monica Aka Selina', 'title': 'Monica Aka Selina',
'display_id': 'monica-aka-selina', 'display_id': 'monica-aka-selina',
'thumbnail': 'https://tn.vxxx.com/contents/videos_screenshots/80000/80747/420x236/1.jpg', 'thumbnail': 'https://tn.vxxx.com/contents/videos_screenshots/80000/80747/420x236/1.jpg',
'description': '', 'description': None,
'timestamp': 1607167706, 'timestamp': 1607167706,
'upload_date': '20201205', 'upload_date': '20201205',
'duration': 2373.0, 'duration': 2373.0,
@ -32,6 +35,10 @@ class VXXXIE(InfoExtractor):
} }
}] }]
_BASE_URL = 'https://vxxx.com'
_INFO_OBJECT_URL_TMPL = '{0}/api/json/video/86400/0/{1}/{2}.json'
_FORMAT_OBJECT_URL_TMPL = '{0}/api/videofile.php?video_id={1}'
def _download_info_object(self, video_id): def _download_info_object(self, video_id):
return self._download_json( return self._download_json(
self._INFO_OBJECT_URL_TMPL.format( self._INFO_OBJECT_URL_TMPL.format(
@ -47,11 +54,6 @@ class VXXXIE(InfoExtractor):
headers={'Referer': self._BASE_URL} headers={'Referer': self._BASE_URL}
) )
@classmethod
def _get_video_host(cls):
# or use the proper Python URL parsing functions
return cls._BASE_URL.split('//')[-1]
def _decode_base164(self, e): def _decode_base164(self, e):
""" """
Some non-standard encoding called "base164" in the JavaScript code. It's Some non-standard encoding called "base164" in the JavaScript code. It's
@ -61,21 +63,19 @@ class VXXXIE(InfoExtractor):
- "~" is used for padding instead of "=" - "~" is used for padding instead of "="
""" """
# using the kwarg to memoise the result # using the kwarg to memoise the result
def get_trans_tbl(from_, to, tbl={}): def get_trans_tbl(from_, to, tbl={}):
k = (from_, to) k = (from_, to)
if not tbl.get(k): if not tbl.get(k):
tbl[k] = string.maketrans(from_, to) tbl[k] = str.maketrans(from_, to)
return tbl[k] return tbl[k]
# maybe for the 2nd arg: trans_tbl = get_trans_tbl(
# import unicodedata and '\u0410\u0412\u0421\u0415\u041c.,~',
# ''.join((unicodedata.lookup('CYRILLIC CAPITAL LETTER ' + x) for x in ('A', 'BE', 'ES', 'IE', 'EM'))) + '+/=' 'ABCEM+/=')
trans_tbl = get_trans_tbl('АBCEM.,~', 'ABCEM+/=') return base64.b64decode(e.translate(trans_tbl)).decode()
return base64.b64decode(e.translate(trans_tbl)
).decode()
def _extract_info(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)
info_object = self._download_info_object(video_id) info_object = self._download_info_object(video_id)
@ -87,21 +87,22 @@ class VXXXIE(InfoExtractor):
'title': title, 'title': title,
'display_id': info_object.get('dir'), 'display_id': info_object.get('dir'),
'thumbnail': url_or_none(info_object.get('thumb')), 'thumbnail': url_or_none(info_object.get('thumb')),
'description': strip_or_none(info_object('description')) or None, 'description': strip_or_none(info_object.get('description')) or None,
'timestamp': unified_timestamp(info_object.get('post_date')), 'timestamp': unified_timestamp(info_object.get('post_date')),
'duration': parse_duration(info_object.get('duration')), 'duration': parse_duration(info_object.get('duration')),
'view_count': int_or_none(stats.get('viewed')), 'view_count': int_or_none(stats.get('viewed')),
'like_count': int_or_none(stats.get('likes')), 'like_count': int_or_none(stats.get('likes')),
'dislike_count': int_or_none(stats.get('dislikes')), 'dislike_count': int_or_none(stats.get('dislikes')),
'average_rating': float_or_none(stats.get('rating')), 'average_rating': float_or_none(stats.get('rating')),
'categories': [category['title'] for category in (info_object.get('categories') or {}).values() if category.get('title')], 'categories': [category['title'] for category in (info_object.get('categories') or {}).values()
if category.get('title')],
'age_limit': 18, 'age_limit': 18,
} }
format_object = self._download_format_object(video_id) format_object = self._download_format_object(video_id)
m3u8_formats = self._extract_m3u8_formats( m3u8_formats = self._extract_m3u8_formats(
'https://{0}{1}&f=video.m3u8'.format( '{0}/{1}&f=video.m3u8'.format(
self._get_video_host(), self._BASE_URL,
self._decode_base164(format_object[0]['video_url']) self._decode_base164(format_object[0]['video_url'])
), ),
video_id, 'mp4') video_id, 'mp4')
@ -110,10 +111,124 @@ class VXXXIE(InfoExtractor):
return info return info
def _real_extract(self, url):
info = self._extract_info(url)
if not info['formats']: class BdsmxTubeIE(VXXXIE):
return self.url_result(url, 'Generic') _VALID_URL = r'https?://bdsmx\.tube/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://bdsmx.tube/video/127583/latex-puppy-leashed/',
'md5': '79751d4ed75668afe07a660c4bcb2f1b',
'info_dict': {
'id': '127583',
'ext': 'mp4',
'title': 'Latex Puppy Leashed',
'display_id': 'latex-puppy-leashed',
'thumbnail': 'https://tn.bdsmx-porn.com/contents/videos_screenshots/127000/127583/480x270/1.jpg',
'description': None,
'timestamp': 1651003323,
'upload_date': '20220426',
'duration': 68.0,
'categories': ['Asian', 'Brunette', 'Cosplay', 'Fetish',
'Fuck Machine', 'Gagging', 'Japanese',
'JAV Uncensored', 'Latex', 'Leather', 'POV'],
'age_limit': 18,
}
}]
return info _BASE_URL = 'https://bdsmx.tube'
class BlackPornTubeIE(VXXXIE):
_VALID_URL = r'https?://blackporn\.tube/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://blackporn.tube/video/10043813/young-ebony-babe-gets-super-wet/',
'md5': '4a4c126970f2f1453b8b2050947fc870',
'info_dict': {
'id': '10043813',
'ext': 'mp4',
'title': 'Young Ebony Babe Gets Super Wet',
'display_id': 'young-ebony-babe-gets-super-wet',
'thumbnail': 'https://tn.blackporn.tube/contents/videos_screenshots/10043000/10043813/480x270/1.jpg',
'description': None,
'timestamp': 1654806141,
'upload_date': '20220609',
'duration': 193.0,
'categories': ['BDSM', 'Bondage', 'Celebrity', 'Ebony', 'Fetish',
'Shibari Bondage', 'Solo Female',
'Tattoo'],
'age_limit': 18,
}
}]
_BASE_URL = 'https://blackporn.tube'
class InPornIE(VXXXIE):
_VALID_URL = r'https?://(?:www\.)?inporn\.com/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://inporn.com/video/533613/2k-t-2nd-season-parm-151/',
'md5': 'c358d1da6b451ebe7cfb00dd89741607',
'info_dict': {
'id': '533613',
'ext': 'mp4',
'title': '2k 美月まい - ガーリー系アパレルモt゙ルの挑発パンチラ 2nd Season [parm-151]',
'display_id': '2k-t-2nd-season-parm-151',
'thumbnail': 'https://tn.inporn.com/media/tn/533613_1.jpg',
'description': None,
'timestamp': 1664571262,
'upload_date': '20220930',
'duration': 480.0,
'categories': ['Asian', 'Brunette', 'Casting', 'HD', 'Japanese',
'JAV Uncensored'],
'age_limit': 18,
},
}]
_BASE_URL = 'https://inporn.com'
class MrGayIE(VXXXIE):
_VALID_URL = r'https?://mrgay\.com/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://mrgay.com/video/10169199/jpn-crossdresser-6/',
'md5': 'b5780a9437c205b4bc87eb939b23e8ef',
'info_dict': {
'id': '10169199',
'ext': 'mp4',
'title': 'Jpn Crossdresser 6',
'display_id': 'jpn-crossdresser-6',
'thumbnail': 'https://tn.mrgay.com/media/tn/10169199_1.jpg',
'description': None,
'timestamp': 1651066888,
'upload_date': '20220427',
'duration': 834.0,
'categories': ['Amateur', 'Asian', 'Brunette', 'Crossdressing',
'Japanese', 'Webcam'],
'age_limit': 18,
}
}]
_BASE_URL = 'https://mrgay.com'
class XMilfIE(VXXXIE):
_VALID_URL = r'https?://xmilf\.com/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://xmilf.com/video/143777/big-boob-brunette-masturbates3/',
'md5': 'a196fe8daebe194a758754c81e9232ad',
'info_dict': {
'id': '143777',
'ext': 'mp4',
'title': 'Big Boob Brunette Masturbates',
'display_id': 'big-boob-brunette-masturbates3',
'thumbnail': 'https://tn.xmilf.com/contents/videos_screenshots/143000/143777/480x270/1.jpg',
'description': None,
'timestamp': 1662465481,
'upload_date': '20220906',
'duration': 480.0,
'categories': ['Amateur', 'Big Tits', 'Brunette', 'Fetish', 'HD',
'Lingerie', 'MILF', 'Webcam'],
'age_limit': 18,
}
}]
_BASE_URL = 'https://xmilf.com'

View File

@ -1,43 +0,0 @@
# coding: utf-8
from __future__ import unicode_literals
from .vxxx import VXXXIE
class XMilfIE(VXXXIE):
_VALID_URL = r'https?://xmilf\.com/video/(?P<id>\d+)'
_TESTS = [{
'url': 'https://xmilf.com/video/143777/big-boob-brunette-masturbates3/',
'md5': 'a196fe8daebe194a758754c81e9232ad',
'info_dict': {
'id': '143777',
'ext': 'mp4',
'title': 'Big Boob Brunette Masturbates',
'display_id': 'big-boob-brunette-masturbates3',
'thumbnail': 'https://tn.xmilf.com/contents/videos_screenshots/143000/143777/480x270/1.jpg',
'description': '',
'timestamp': 1662465481,
'upload_date': '20220906',
'duration': 480.0,
'categories': ['Amateur', 'Big Tits', 'Brunette', 'Fetish', 'HD',
'Lingerie', 'MILF', 'Webcam'],
'age_limit': 18,
}
}]
def _download_info_object(self, video_id):
return self._download_json(
'https://xmilf.com/api/json/video/86400/0/{}/{}.json'.format(
int(video_id) // 1000 * 1000,
video_id,
), video_id, headers={'Referer': 'https://xmilf.com'})['video']
def _download_format_object(self, video_id):
return self._download_json(
'https://xmilf.com/api/videofile.php?video_id={}'.format(video_id),
video_id,
headers={'Referer': 'https://xmilf.com'}
)
def _get_video_host(self):
return 'xmilf.com'