phub 4.8.3__py3-none-any.whl → 4.8.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- phub/__main__.py +15 -7
- phub/core.py +6 -5
- phub/objects/query.py +8 -5
- phub/objects/video.py +1 -1
- {phub-4.8.3.dist-info → phub-4.8.5.dist-info}/METADATA +2 -1
- {phub-4.8.3.dist-info → phub-4.8.5.dist-info}/RECORD +10 -10
- {phub-4.8.3.dist-info → phub-4.8.5.dist-info}/WHEEL +0 -0
- {phub-4.8.3.dist-info → phub-4.8.5.dist-info}/entry_points.txt +0 -0
- {phub-4.8.3.dist-info → phub-4.8.5.dist-info}/licenses/LICENSE +0 -0
- {phub-4.8.3.dist-info → phub-4.8.5.dist-info}/top_level.txt +0 -0
phub/__main__.py
CHANGED
|
@@ -4,8 +4,9 @@ PHUB built-in CLI.
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
import argparse
|
|
7
|
-
import re
|
|
8
7
|
|
|
8
|
+
from typing import Union
|
|
9
|
+
from base_api import BaseCore
|
|
9
10
|
from phub import Client, Video
|
|
10
11
|
|
|
11
12
|
|
|
@@ -22,7 +23,7 @@ def text_progress_bar(downloaded, total, title=False):
|
|
|
22
23
|
print(f"\r | {title} | -->: [{bar}] {percents}%", end='')
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
def download_video(client: Client, url: [str
|
|
26
|
+
def download_video(client: Client, url: Union[str | Video], output: str, quality: str, downloader: str, use_video_id=False):
|
|
26
27
|
if not isinstance(url, Video):
|
|
27
28
|
video = client.get(url)
|
|
28
29
|
|
|
@@ -33,10 +34,15 @@ def download_video(client: Client, url: [str, Video], output: str, quality: str,
|
|
|
33
34
|
else:
|
|
34
35
|
raise "Some error happened here, please report on GitHub, thank you :) "
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
if use_video_id:
|
|
38
|
+
title = video.id
|
|
39
|
+
|
|
40
|
+
else:
|
|
41
|
+
title = BaseCore().strip_title(title=video.title)
|
|
42
|
+
|
|
37
43
|
final_output_path = os.path.join(output, title + ".mp4")
|
|
38
44
|
|
|
39
|
-
print(f"Downloading: {title} to: {final_output_path}")
|
|
45
|
+
print(f"Downloading: {video.title} to: {final_output_path}")
|
|
40
46
|
video.download(path=final_output_path, quality=quality, downloader=downloader, display=text_progress_bar)
|
|
41
47
|
print(f"Successfully downloaded: {title}")
|
|
42
48
|
|
|
@@ -47,6 +53,7 @@ def main():
|
|
|
47
53
|
group.add_argument("-url", type=str, help="a PornHub Video URL", default="")
|
|
48
54
|
group.add_argument("-model", type=str, help="a Pornhub Model URL", default="")
|
|
49
55
|
parser.add_argument("-video_limit", type=int, help="the maximum number of videos to download from a model (Default: all)", default=100000)
|
|
56
|
+
parser.add_argument("--use-video-id", action="store_true", help="uses video ID as the title instead of the original video title")
|
|
50
57
|
group.add_argument("-file", type=str, help="List to a file with Video URLs (separated by new lines)", default="")
|
|
51
58
|
parser.add_argument("-downloader", type=str, help="The threading (download backend) to use", choices=[
|
|
52
59
|
"threaded", "default", "ffmpeg"], default="threaded")
|
|
@@ -64,11 +71,12 @@ def main():
|
|
|
64
71
|
model = args.model
|
|
65
72
|
video_limit = args.video_limit
|
|
66
73
|
file = args.file
|
|
74
|
+
use_video_id = args.use_video_id
|
|
67
75
|
|
|
68
76
|
client = Client()
|
|
69
77
|
|
|
70
78
|
if len(url) >= 3: # Comparison with not == "" doesn't work, don't ask me why I have no fucking idea...
|
|
71
|
-
download_video(client=client, url=url, output=output, quality=quality, downloader=downloader)
|
|
79
|
+
download_video(client=client, url=url, output=output, quality=quality, downloader=downloader, use_video_id=use_video_id)
|
|
72
80
|
|
|
73
81
|
elif len(model) >= 3:
|
|
74
82
|
model_videos = client.get_user(model).videos
|
|
@@ -78,7 +86,7 @@ def main():
|
|
|
78
86
|
if idx >= video_limit:
|
|
79
87
|
break
|
|
80
88
|
|
|
81
|
-
download_video(client=client, url=video, output=output, quality=quality, downloader=downloader)
|
|
89
|
+
download_video(client=client, url=video, output=output, quality=quality, downloader=downloader, use_video_id=use_video_id)
|
|
82
90
|
idx += 1
|
|
83
91
|
|
|
84
92
|
elif len(file) >= 1:
|
|
@@ -95,7 +103,7 @@ def main():
|
|
|
95
103
|
|
|
96
104
|
for idx, url in enumerate(urls, start=1):
|
|
97
105
|
print(f"[{idx}|{len(urls)}] Downloading: {url}")
|
|
98
|
-
download_video(client=client, url=url, output=output, quality=quality, downloader=downloader)
|
|
106
|
+
download_video(client=client, url=url, output=output, quality=quality, downloader=downloader, use_video_id=use_video_id)
|
|
99
107
|
|
|
100
108
|
|
|
101
109
|
if __name__ == '__main__':
|
phub/core.py
CHANGED
|
@@ -59,7 +59,9 @@ class Client:
|
|
|
59
59
|
|
|
60
60
|
self.logger = setup_logger(name="PHUB API - [Client]", log_file=None, level=logging.ERROR)
|
|
61
61
|
self.core = core or BaseCore(config=RuntimeConfig())
|
|
62
|
-
self.core.initialize_session(
|
|
62
|
+
self.core.initialize_session()
|
|
63
|
+
self.core.session.headers.update(consts.HEADERS)
|
|
64
|
+
self.core.session.cookies.update(consts.HEADERS)
|
|
63
65
|
# Applying PornHub specific cookies and headers to base API
|
|
64
66
|
self.logger.debug('Initialised new Client %s', self)
|
|
65
67
|
|
|
@@ -359,7 +361,7 @@ class Client:
|
|
|
359
361
|
AssertioneError: If one or more filters don't match their literals.
|
|
360
362
|
'''
|
|
361
363
|
|
|
362
|
-
query = query.strip()
|
|
364
|
+
query = query.strip().lower()
|
|
363
365
|
|
|
364
366
|
assert query, 'Query must be a non-empty string'
|
|
365
367
|
|
|
@@ -368,7 +370,7 @@ class Client:
|
|
|
368
370
|
literals.ass('exclude_category', exclude_category, literals.category )
|
|
369
371
|
literals.ass('sort' , sort , literals.sort )
|
|
370
372
|
literals.ass('period' , period , literals.period )
|
|
371
|
-
|
|
373
|
+
s = f'search "{query}"'
|
|
372
374
|
return queries.VideoQuery(
|
|
373
375
|
client = self,
|
|
374
376
|
func = 'video/search',
|
|
@@ -381,8 +383,7 @@ class Client:
|
|
|
381
383
|
't': literals.map.period.get(period),
|
|
382
384
|
'hd': literals._craft_boolean(hd)
|
|
383
385
|
},
|
|
384
|
-
query_repr =
|
|
385
|
-
)
|
|
386
|
+
query_repr = s)
|
|
386
387
|
|
|
387
388
|
def get_playlist(self, playlist: Union[str, int, Playlist]) -> Playlist:
|
|
388
389
|
'''
|
phub/objects/query.py
CHANGED
|
@@ -5,6 +5,7 @@ import logging
|
|
|
5
5
|
from base_api.base import setup_logger
|
|
6
6
|
from functools import cache, cached_property
|
|
7
7
|
from typing import TYPE_CHECKING, Iterator, Any, Callable, Union
|
|
8
|
+
from urllib.parse import urlencode, urlsplit, parse_qsl, urlunsplit
|
|
8
9
|
|
|
9
10
|
from . import Video, User, FeedItem
|
|
10
11
|
|
|
@@ -93,7 +94,6 @@ class Query:
|
|
|
93
94
|
self._query_repr = query_repr
|
|
94
95
|
|
|
95
96
|
# Build URL
|
|
96
|
-
args |= {'page': '{page}'}
|
|
97
97
|
self.url = utils.concat(self.BASE, func, utils.urlify(args))
|
|
98
98
|
|
|
99
99
|
self.suppress_spicevids = True
|
|
@@ -181,14 +181,17 @@ class Query:
|
|
|
181
181
|
Returns:
|
|
182
182
|
str: The raw page content.
|
|
183
183
|
'''
|
|
184
|
-
|
|
184
|
+
|
|
185
185
|
assert isinstance(index, int)
|
|
186
|
-
|
|
186
|
+
parts = list(urlsplit(self.url))
|
|
187
|
+
q = dict(parse_qsl(parts[3], keep_blank_values=True))
|
|
188
|
+
q['page'] = str(index + 1) # PH uses 1-based pages; omit or set "1" for page 1
|
|
189
|
+
parts[3] = urlencode(q)
|
|
190
|
+
url = urlunsplit(parts)
|
|
191
|
+
|
|
187
192
|
req = self.client.call(url, get_response=True, throw=False)
|
|
188
|
-
|
|
189
193
|
if req.status_code == 404:
|
|
190
194
|
raise errors.NoResult()
|
|
191
|
-
|
|
192
195
|
return req.text
|
|
193
196
|
|
|
194
197
|
@cache
|
phub/objects/video.py
CHANGED
|
@@ -262,7 +262,7 @@ class Video:
|
|
|
262
262
|
remux=remux, callback_remux=display_remux)
|
|
263
263
|
|
|
264
264
|
except Exception as e:
|
|
265
|
-
self.logger.error(f"An error
|
|
265
|
+
self.logger.error(f"An error occurred while downloading video {e}")
|
|
266
266
|
|
|
267
267
|
return path
|
|
268
268
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phub
|
|
3
|
-
Version: 4.8.
|
|
3
|
+
Version: 4.8.5
|
|
4
4
|
Summary: An API for Pornhub
|
|
5
5
|
Author-email: Egsagon <egsagon.git@gmail.com>, EchterAlsFake <EchterAlsFake@proton.me>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -689,6 +689,7 @@ Description-Content-Type: text/markdown
|
|
|
689
689
|
License-File: LICENSE
|
|
690
690
|
Requires-Dist: httpx[brotli,socks]
|
|
691
691
|
Requires-Dist: eaf_base_api
|
|
692
|
+
Requires-Dist: h2
|
|
692
693
|
Dynamic: license-file
|
|
693
694
|
|
|
694
695
|
<p align="center">
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
phub/__init__.py,sha256=tEWpP7XSkDB9_M5iJ1XHSgpJ6g4olWqYTX8f9IBpIAA,635
|
|
2
|
-
phub/__main__.py,sha256=
|
|
2
|
+
phub/__main__.py,sha256=nP5IffsxbcFzPdGkMWky4fs647NOswW9DT-S5AcLQtU,4028
|
|
3
3
|
phub/consts.py,sha256=a-okcZtwtSDmt4eub_acE1xWg1Fqxm1DZ9yy7aVGvM0,12453
|
|
4
|
-
phub/core.py,sha256=
|
|
4
|
+
phub/core.py,sha256=_5iMMcvnt9Ue-1YY1u0Nlc4Sra-VMHFoiLcxIaUSLSM,18441
|
|
5
5
|
phub/errors.py,sha256=KiNt_4T4ffzgL-2iIfD8qhIHN_5DeKV4FLPcY72sOw8,1822
|
|
6
6
|
phub/literals.py,sha256=ZnRnn5hJNI3hM6aj2YxsxPANUR-PCqfE2SuQGD8_Yq4,10794
|
|
7
7
|
phub/utils.py,sha256=MYPYvpLrWAYXcwpSUJnRWvFNP0N9iOyLxkzaJFsk8GA,6582
|
|
@@ -15,18 +15,18 @@ phub/objects/data.py,sha256=hJpbuL185CLmISYCsmVu8WZVJEsiFC246bL1-QHa9j0,5967
|
|
|
15
15
|
phub/objects/feed.py,sha256=JFvNc59VfGXU3PiW17GySQooy-5h8zLfl0vHIs9ga48,2691
|
|
16
16
|
phub/objects/image.py,sha256=qCLuaOy-EYzA_uXxiPRQeCLHPf9gFr0o7TDszQvWXZs,3376
|
|
17
17
|
phub/objects/playlist.py,sha256=hpP76yH23LdDS0iL28jhp_iG7EGetYJA3xoqZZdXjTs,3278
|
|
18
|
-
phub/objects/query.py,sha256=
|
|
18
|
+
phub/objects/query.py,sha256=gALFeOQA48loUStLA_d9npQHIAkw0CdTAIOQ_h_tFuA,11811
|
|
19
19
|
phub/objects/user.py,sha256=pIumIGC_MQXQ-hjzf_0c0I_egL4WziHrh2e8XegArEc,8161
|
|
20
|
-
phub/objects/video.py,sha256=
|
|
20
|
+
phub/objects/video.py,sha256=0XJL-PP8HVqb2uUexIMZVfQ29-qGEeb60_yVoj3RLuc,19169
|
|
21
21
|
phub/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
phub/tests/test_auth.py,sha256=ySy1Aw0bogMGDSTmzVXO_W352cbRFzXUGjuDX1Iu0xE,609
|
|
23
23
|
phub/tests/test_model.py,sha256=hRpmIjsx2z0EjTWsIpwT_vpHm-H4wCmZtvGWOohaIKQ,1426
|
|
24
24
|
phub/tests/test_playlist.py,sha256=-hS5bIBecsv3zSNlUo66b73DdVbkYlmVThYip9Ivpss,1081
|
|
25
25
|
phub/tests/test_search.py,sha256=VeqyjVzu0QnIYR6NhcujXy8wfCcWn1BlvKS06iY-7JY,1301
|
|
26
26
|
phub/tests/test_video.py,sha256=4E70tiza45byMFIrjBdnpP3xOSyk1YKoTGNP4_QTI0E,1465
|
|
27
|
-
phub-4.8.
|
|
28
|
-
phub-4.8.
|
|
29
|
-
phub-4.8.
|
|
30
|
-
phub-4.8.
|
|
31
|
-
phub-4.8.
|
|
32
|
-
phub-4.8.
|
|
27
|
+
phub-4.8.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
28
|
+
phub-4.8.5.dist-info/METADATA,sha256=K7OEBgDD9c1VArJvma_ccZmUZ0yi177cSxbUmIMon8k,41758
|
|
29
|
+
phub-4.8.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
30
|
+
phub-4.8.5.dist-info/entry_points.txt,sha256=oxL1BvDV19M1IGLgwFElgb37PlmGnblDBEfMwx3x6u8,44
|
|
31
|
+
phub-4.8.5.dist-info/top_level.txt,sha256=xqJ5Lg28Ba-pgvXf8qwpTFurW3neZhguNd8bhbQonZo,5
|
|
32
|
+
phub-4.8.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|