phub 4.7.8__py3-none-any.whl → 4.8.0__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/consts.py CHANGED
@@ -227,8 +227,7 @@ class re:
227
227
  container = find( engine.DOTALL, r'class=\"container(.*)' ) # Get the page container
228
228
  document = find( engine.DOTALL, r'.*' ) # Match a whole document
229
229
  get_playlist_unavailable = find( engine.DOTALL, r': (\d+)</h5' ) # Get playlist unavailable videos amount
230
- playlist_data = find( engine.DOTALL, r'id=\"playlistWrapper(.*?)playlistSectionWrapper\"' ) # Get playlist data container
231
- get_playlist_size = find( engine.DOTALL, r'- (\d+).*?\"avatarPosition' ) # Get playlist video amount
230
+ get_playlist_size = find( engine.DOTALL, r'var itemsCount = (.*?) ||' ) # Get playlist video amount
232
231
  get_playlist_likes = find( engine.DOTALL, r'<span class="votesUp">(.*?)</span>' ) # Get playlist likes
233
232
  get_playlist_dislikes = find( engine.DOTALL, r'<span class="votesDown">(.*?)</span>' ) # Get playlist dislikes
234
233
  get_playlist_ratings = find( engine.DOTALL, r'<span class="percent">(.*?)%</span>' ) # Get paylist like/dislike ratio
phub/core.py CHANGED
@@ -1,7 +1,7 @@
1
1
  '''
2
2
  PHUB core module.
3
3
  '''
4
-
4
+ import re
5
5
  import time
6
6
  import logging
7
7
  import random
@@ -209,12 +209,13 @@ class Client:
209
209
  raise errors.ClientAlreadyLogged()
210
210
 
211
211
  # Get token
212
- page = self.call('').text
212
+ page = self.call('https://www.pornhub.com').text
213
213
  try:
214
214
  base_token = consts.re.get_token(page)
215
215
 
216
216
  except errors.RegexError:
217
- raise LoginFailed("(Probably) invalid credentials. If you are sure they are correct, please report this issue.")
217
+ self.logger.warning("Couldn't get token. Trying alternative method...")
218
+ base_token = re.search(r'data-token="(.*?)"', string=page).group(1)
218
219
 
219
220
  # Send credentials
220
221
  payload = consts.LOGIN_PAYLOAD | self.credentials | {'token': base_token}
phub/modules/parser.py CHANGED
@@ -79,8 +79,7 @@ def challenge(client: Client, challenge: str, token: str) -> None:
79
79
 
80
80
  # Build and inject cookie
81
81
  cookie = f'{n}*{p // n}:{s}:{token}:1'
82
- client.core.config.cookies = {'KEY', cookie}
82
+ client.core.config.cookies = {'KEY': cookie}
83
83
  client.core.update_cookies()
84
84
  logger.info('Injected cookie %s', cookie)
85
- print("Injected cookie for authentication")
86
85
  # EOF
phub/objects/playlist.py CHANGED
@@ -1,5 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import re
4
+ import time
3
5
  from typing import TYPE_CHECKING
4
6
  from functools import cache, cached_property
5
7
 
@@ -34,7 +36,6 @@ class Playlist(queries.VideoQuery):
34
36
 
35
37
  # Initialise
36
38
  super().__init__(client, func = None)
37
-
38
39
  # Define both playlist url (first page) and chunked (next pages)
39
40
  self.url = 'playlist/' + str(pid)
40
41
  self.chunk_url = f'playlist/viewChunked?id={pid}' '&token={token}&page={page}'
@@ -70,13 +71,9 @@ class Playlist(queries.VideoQuery):
70
71
  raise errors.NoResult()
71
72
 
72
73
  return response.text
73
-
74
- @cached_property
75
- def _data(self) -> str:
76
- return consts.re.playlist_data(self._page)
77
74
 
78
75
  def __len__(self) -> int:
79
- return int(consts.re.get_playlist_size(self._page))
76
+ return int(re.search(r'var\s+itemsCount\s*=\s*(\d+)\s*\|\|', string=self._page).group(1))
80
77
 
81
78
  @cached_property
82
79
  def hidden_videos_amount(self) -> int:
@@ -89,27 +86,27 @@ class Playlist(queries.VideoQuery):
89
86
  @cached_property
90
87
  def like(self) -> Like:
91
88
  return Like(
92
- int(consts.re.get_playlist_likes(self._data)),
93
- int(consts.re.get_playlist_dislikes(self._data)),
94
- float(consts.re.get_playlist_ratings(self._data))
89
+ int(consts.re.get_playlist_likes(self._page)),
90
+ int(consts.re.get_playlist_dislikes(self._page)),
91
+ float(consts.re.get_playlist_ratings(self._page))
95
92
  )
96
93
 
97
94
  @cached_property
98
95
  def views(self) -> int:
99
- raw: str = consts.re.get_playlist_views(self._data)
96
+ raw: str = consts.re.get_playlist_views(self._page)
100
97
  return int(raw.replace(',', ''))
101
98
 
102
99
  @cached_property
103
100
  def tags(self) -> list[str]:
104
- return consts.re.get_playlist_tags(self._data)
101
+ return consts.re.get_playlist_tags(self._page)
105
102
 
106
103
  @cached_property
107
104
  def author(self) -> User:
108
- url = consts.re.get_playlist_author(self._data)
105
+ url = consts.re.get_playlist_author(self._page)
109
106
  return User.get(self.client, consts.HOST + url)
110
107
 
111
108
  @cached_property
112
109
  def title(self) -> str:
113
- return consts.re.get_playlist_title(self._data)
110
+ return consts.re.get_playlist_title(self._page)
114
111
 
115
112
  # EOF
phub/objects/query.py CHANGED
@@ -184,7 +184,7 @@ class Query:
184
184
 
185
185
  assert isinstance(index, int)
186
186
  url = self.url.format(page = index + 1)
187
- req = self.client.call(url, get_response=True)
187
+ req = self.client.call(url, get_response=True, throw=False)
188
188
 
189
189
  if req.status_code == 404:
190
190
  raise errors.NoResult()
phub/objects/user.py CHANGED
@@ -1,8 +1,10 @@
1
1
  from __future__ import annotations
2
2
  import logging
3
+ import re
3
4
 
4
5
  from dataclasses import dataclass
5
6
  from functools import cached_property
7
+
6
8
  from base_api.base import setup_logger
7
9
  from typing import TYPE_CHECKING, Literal, Union
8
10
 
@@ -223,8 +225,16 @@ class User:
223
225
  '''
224
226
  The user bio.
225
227
  '''
226
-
227
- return consts.re.user_bio(self._page, throw = False)
228
+ try:
229
+ bio = consts.re.user_bio(self._page, throw = False)
230
+ assert bio, str
231
+ except (errors.RegexError, AssertionError):
232
+ try:
233
+ bio = re.search(r'<div class="profileReadMoreExcerpt">\s*(.*?)\s*</div>', self._page, re.DOTALL).group(1)
234
+ except AttributeError:
235
+ return None # User has no bio probably
236
+
237
+ return bio
228
238
 
229
239
  @cached_property
230
240
  def info(self) -> dict[str, str]:
@@ -247,10 +257,14 @@ class User:
247
257
  '''
248
258
 
249
259
  from . import Image
250
-
251
- url = (getattr(self, '_cached_avatar_url')
260
+ try:
261
+ url = (getattr(self, '_cached_avatar_url')
252
262
  or consts.re.user_avatar(self._page))
253
-
263
+
264
+ except errors.RegexError:
265
+ url = (getattr(self, '_cached_avatar_url')
266
+ or re.search(r"/(?:model|pornstar)/(.*?)/about", string=self._page).group(1))
267
+
254
268
  return Image(client = self.client,
255
269
  url = url,
256
270
  name = f'{self.name}-avatar')
phub/tests/test_auth.py CHANGED
@@ -1,10 +1,14 @@
1
- import os
2
-
3
1
  try:
2
+ import os
4
3
  from phub import Client
4
+ from base_api.modules.config import config
5
+ from base_api.base import BaseCore
5
6
 
6
7
  except (ModuleNotFoundError, ImportError):
8
+ import os
7
9
  from ...phub import Client
10
+ from base_api.modules.config import config
11
+ from base_api.base import BaseCore
8
12
 
9
13
  def test_auth():
10
14
 
@@ -12,10 +16,11 @@ def test_auth():
12
16
  password = os.getenv('PASSWORD')
13
17
 
14
18
  assert email and password
15
-
16
- client = Client(email, password, login = False)
17
- client.login()
18
-
19
+
20
+ config.request_delay = 0
21
+ core = BaseCore(config=config)
22
+ client = Client(language="en", core=core, email=email, password=password)
23
+
19
24
  assert client.logged
20
25
 
21
26
  # EOF
phub/tests/test_model.py CHANGED
@@ -1,14 +1,19 @@
1
1
  try:
2
2
  from phub import Client
3
-
3
+ from base_api.modules.config import config
4
+ from base_api.base import BaseCore
4
5
  except (ModuleNotFoundError, ImportError):
5
6
  from ...phub import Client
7
+ from base_api.modules.config import config
8
+ from base_api.base import BaseCore
9
+
10
+ config.request_delay = 0
11
+ core = BaseCore(config=config)
12
+ client = Client(language="en", core=core) # Make a delay, so that PornHub isn't stressed too much
6
13
 
7
14
  url = "https://pornhub.com/pornstar/nancy-a"
8
- client = Client(language="en") # Make a delay, so that PornHub isn't stressed too much
9
15
  model = client.get_user(url)
10
16
 
11
-
12
17
  def test_info():
13
18
  assert isinstance(model.info, dict)
14
19
 
@@ -1,8 +1,11 @@
1
1
  try:
2
2
  from phub import Client, Like, User
3
-
4
- except (ImportError, ModuleNotFoundError):
3
+ from base_api.modules.config import config
4
+ from base_api.base import BaseCore
5
+ except (ModuleNotFoundError, ImportError):
5
6
  from ...phub import Client, Like, User
7
+ from base_api.modules.config import config
8
+ from base_api.base import BaseCore
6
9
 
7
10
  url = "https://de.pornhub.com/playlist/113348141"
8
11
  client = Client(language="en")
phub/tests/test_search.py CHANGED
@@ -1,13 +1,16 @@
1
1
  try:
2
2
  from phub import Client
3
- from phub import literals
4
-
3
+ from base_api.modules.config import config
4
+ from base_api.base import BaseCore
5
5
  except (ModuleNotFoundError, ImportError):
6
6
  from ...phub import Client
7
- from ...phub import literals
8
-
9
- client = Client(language="en")
7
+ from base_api.modules.config import config
8
+ from base_api.base import BaseCore
10
9
 
10
+ config.request_delay = 0
11
+ core = BaseCore(config=config)
12
+ client = Client(language="en", core=core) # Make a delay, so that PornHub isn't stressed too much
13
+ print(f"Using config:; {client.core.config.request_delay}")
11
14
 
12
15
  def test_basic_search():
13
16
  search = client.search("Mia Khalifa") # for the nostalgia
phub/tests/test_video.py CHANGED
@@ -1,10 +1,13 @@
1
1
  try:
2
2
  from phub import Client
3
-
4
- except (ImportError, ModuleNotFoundError):
3
+ from base_api.modules.config import config
4
+ from base_api.base import BaseCore
5
+ except (ModuleNotFoundError, ImportError):
5
6
  from ...phub import Client
6
7
 
7
- client = Client(language="en")
8
+ config.request_delay = 0
9
+ core = BaseCore(config=config)
10
+ client = Client(language="en", core=core) # Make a delay, so that PornHub isn't stressed too much
8
11
  url = "https://de.pornhub.com/view_video.php?viewkey=ph60f99fa4b5cd7"
9
12
  video = client.get(url)
10
13
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: phub
3
- Version: 4.7.8
3
+ Version: 4.8.0
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
@@ -1,32 +1,32 @@
1
1
  phub/__init__.py,sha256=tEWpP7XSkDB9_M5iJ1XHSgpJ6g4olWqYTX8f9IBpIAA,635
2
2
  phub/__main__.py,sha256=rRph6K-lXFURL7t8s0q_XB5-4Bqtrkg_ZoERjhjNmow,3637
3
- phub/consts.py,sha256=fp5dqY5DHtoxH82S_Rcz4LCAVJZlMUH5Wl5pH_d6l4U,12629
4
- phub/core.py,sha256=gbnB9-IO_DGQgTXsjUmUbZxWpIDadieeFMmcabF4u1U,18254
3
+ phub/consts.py,sha256=a-okcZtwtSDmt4eub_acE1xWg1Fqxm1DZ9yy7aVGvM0,12453
4
+ phub/core.py,sha256=JeD-Z0tqxXvWotVhlZu0Lor0Sw3QcnUyAXyAcsEBfGA,18325
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
8
8
  phub/modules/__init__.py,sha256=h8BQjvxnqCEXxDCn7iDvnGLv0ZF_lE0dFlI7HVkzN5A,133
9
9
  phub/modules/display.py,sha256=BxI8SSx8tc-BUkrWYG-75BjgS2dwlw9M5QXHoyci3Gs,2445
10
- phub/modules/parser.py,sha256=BbJw0iDZ0dhaJEuoWKoRr68CthMz_yl7AzC01eJoZOo,2385
10
+ phub/modules/parser.py,sha256=v2iDYAZB6VQ6KvKR_Oe1Cs5Du42W0yNFvtliJKxbZdI,2337
11
11
  phub/modules/rss.py,sha256=j666dZenn3tWgLVXd2U3ox2-tWyUynFXuArzG2bmOFc,980
12
12
  phub/objects/__init__.py,sha256=BHOythbS-r01YKYSxtExBlJZYF38hkp85aLAoVQfDd4,446
13
13
  phub/objects/account.py,sha256=B1hSHmYHip08Gy-TdVmYq25iAA8rjdVuzwwkpjGjl8c,6044
14
14
  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
- phub/objects/playlist.py,sha256=WmFI9EIqSpKxyRmPmGHzT2OUbKo9qsBv0-fWUJrZZFw,3332
18
- phub/objects/query.py,sha256=DaB-X-lDomm1vemcG2XFVEoWNZYhLA3iZoWyui_vhsY,11583
19
- phub/objects/user.py,sha256=pcsy-HMxgjrGhokCm0glg_DwIiRc4IZ87bThdZZXeLs,7627
17
+ phub/objects/playlist.py,sha256=hpP76yH23LdDS0iL28jhp_iG7EGetYJA3xoqZZdXjTs,3278
18
+ phub/objects/query.py,sha256=crYC-MJGEf04XO3hfU7FPyyHEnBWS9D8XbeQmtTnpzQ,11596
19
+ phub/objects/user.py,sha256=pIumIGC_MQXQ-hjzf_0c0I_egL4WziHrh2e8XegArEc,8161
20
20
  phub/objects/video.py,sha256=oPfKaxCulvSWoCNvp0w7DZACfl9Vx8DaOdDWEye69w4,19191
21
21
  phub/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- phub/tests/test_auth.py,sha256=QEnHrPvfTQesEFyDeaZ2bIRgB10dwqygsjM3QeSWRmQ,357
23
- phub/tests/test_model.py,sha256=i39bxsw16X0_-iL4Jfy-CwbGH9y5UeTzFZp0l-6WyjM,1188
24
- phub/tests/test_playlist.py,sha256=nByfOysRBwQUF2nyfKdldSW1Oq2cULRcTkphmF3QQQk,910
25
- phub/tests/test_search.py,sha256=G1u9OUttBWfko-M71MBqgtEzUjYj8NXtsApB-MZY0Fs,1010
26
- phub/tests/test_video.py,sha256=_TgI5oxLKlh3hSOYf7KDwYiQL2cLITNwiNkBFJQQLpE,1103
27
- phub-4.7.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
28
- phub-4.7.8.dist-info/METADATA,sha256=qaynT-pFgtK-ymXHZxSlT7TpVoLB7J4dXNoFoeaZ1Sw,41777
29
- phub-4.7.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- phub-4.7.8.dist-info/entry_points.txt,sha256=oxL1BvDV19M1IGLgwFElgb37PlmGnblDBEfMwx3x6u8,44
31
- phub-4.7.8.dist-info/top_level.txt,sha256=xqJ5Lg28Ba-pgvXf8qwpTFurW3neZhguNd8bhbQonZo,5
32
- phub-4.7.8.dist-info/RECORD,,
22
+ phub/tests/test_auth.py,sha256=ySy1Aw0bogMGDSTmzVXO_W352cbRFzXUGjuDX1Iu0xE,609
23
+ phub/tests/test_model.py,sha256=hRpmIjsx2z0EjTWsIpwT_vpHm-H4wCmZtvGWOohaIKQ,1426
24
+ phub/tests/test_playlist.py,sha256=-hS5bIBecsv3zSNlUo66b73DdVbkYlmVThYip9Ivpss,1081
25
+ phub/tests/test_search.py,sha256=VeqyjVzu0QnIYR6NhcujXy8wfCcWn1BlvKS06iY-7JY,1301
26
+ phub/tests/test_video.py,sha256=bX-gPhDa34p6-5Ei20gh9opNkLs_08JHEfhVlQUwfMU,1312
27
+ phub-4.8.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
28
+ phub-4.8.0.dist-info/METADATA,sha256=hWshEqar7OxI6ZaGjINSVfkUratn5fGayKqtbctNNsc,41777
29
+ phub-4.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ phub-4.8.0.dist-info/entry_points.txt,sha256=oxL1BvDV19M1IGLgwFElgb37PlmGnblDBEfMwx3x6u8,44
31
+ phub-4.8.0.dist-info/top_level.txt,sha256=xqJ5Lg28Ba-pgvXf8qwpTFurW3neZhguNd8bhbQonZo,5
32
+ phub-4.8.0.dist-info/RECORD,,
File without changes