Eporner_API 1.9.6__tar.gz → 2.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Eporner_API
3
- Version: 1.9.6
3
+ Version: 2.0
4
4
  Summary: A Python API for the Porn Site Eporner.com
5
5
  Author: Johannes Habel
6
6
  Author-email: Johannes Habel <EchterAlsFake@proton.me>
@@ -10,8 +10,6 @@ Classifier: Programming Language :: Python
10
10
  Requires-Dist: bs4
11
11
  Requires-Dist: eaf-base-api
12
12
  Requires-Dist: lxml ; extra == 'full'
13
- Requires-Dist: httpx[http2] ; extra == 'full'
14
- Requires-Dist: httpx[socks] ; extra == 'full'
15
13
  Requires-Python: >=3.9
16
14
  Project-URL: Homepage, https://github.com/EchterAlsFake/EPorner_API
17
15
  Provides-Extra: full
@@ -3,6 +3,7 @@ import html
3
3
  import json
4
4
  import os.path
5
5
  import logging
6
+ import asyncio
6
7
  import argparse
7
8
  import traceback
8
9
  import threading
@@ -33,7 +34,7 @@ from bs4 import BeautifulSoup
33
34
  from urllib.parse import urljoin
34
35
  from functools import cached_property
35
36
  from base_api.modules.config import RuntimeConfig
36
- from typing import Generator, Union, Optional, List
37
+ from typing import AsyncGenerator, Generator, Union, Optional, List
37
38
  from base_api.base import BaseCore, setup_logger, Helper
38
39
 
39
40
  """
@@ -102,21 +103,27 @@ def _choose_quality_from_list(available: List[str | int], target: Union[str, int
102
103
 
103
104
 
104
105
  class Video:
105
- def __init__(self, url: str, enable_html_scraping: bool = True, core: Optional[BaseCore] = None):
106
+ def __init__(self, url: str, enable_html_scraping: bool = True, core: Optional[BaseCore] = None, html_content=None):
106
107
  self.core = core
107
108
  self.url = url
108
109
  self.enable_html = enable_html_scraping
109
- self.html_content = None
110
+ self.html_content = html_content
110
111
  self.logger = setup_logger(name="EPorner API - [Video]", log_file=None, level=logging.CRITICAL)
111
- self.json_data = self.raw_json_data()
112
+ self.json_data = {}
113
+ self.html_json_data = {}
114
+
115
+ async def init(self):
116
+ self.json_data = await self.get_raw_json_data()
112
117
  if self.enable_html:
113
- self.request_html_content()
118
+ if not self.html_content:
119
+ await self.request_html_content()
114
120
  is_removed = REGEX_VIDEO_DISABLED.findall(self.html_content)
115
121
  for _ in is_removed:
116
122
  if _ == "deletedfile":
117
123
  raise VideoDisabled("Video has been removed because of a Copyright claim")
118
124
 
119
125
  self.html_json_data = self.extract_json_from_html()
126
+ return self
120
127
 
121
128
  def enable_logging(self, log_file: str, level, log_ip: str = None, log_port: int = None):
122
129
  self.logger = setup_logger(name="EPorner API - [Video]", log_file=log_file, level=level, http_ip=log_ip, http_port=log_port)
@@ -144,13 +151,13 @@ class Video:
144
151
  else:
145
152
  return self.url # Assuming this is a video ID (hopefully)
146
153
 
147
- def raw_json_data(self):
154
+ async def get_raw_json_data(self):
148
155
  """
149
156
  Uses the V2 API to retrieve information from a video
150
157
  :return:
151
158
  """
152
159
 
153
- data = self.core.fetch(f"{ROOT_URL}{API_VIDEO_ID}?id={self.video_id}&thumbsize=medium&format=json")
160
+ data = await self.core.fetch(f"{ROOT_URL}{API_VIDEO_ID}?id={self.video_id}&thumbsize=medium&format=json")
154
161
  parsed_data = json.loads(data)
155
162
  return parsed_data
156
163
 
@@ -212,11 +219,11 @@ class Video:
212
219
  The following methods are using HTML scraping. This is against the ToS from EPorner.com!
213
220
  """
214
221
 
215
- def request_html_content(self):
222
+ async def request_html_content(self):
216
223
  if not self.enable_html:
217
224
  raise HTML_IS_DISABLED("HTML content is disabled! See Documentation for more details")
218
225
 
219
- self.html_content = html.unescape(self.core.fetch(self.url))
226
+ self.html_content = html.unescape(await self.core.fetch(self.url))
220
227
 
221
228
 
222
229
  def extract_json_from_html(self):
@@ -333,13 +340,7 @@ JSONDecodeError: I need your help to fix this error. Please report the URL you'v
333
340
  self.logger.error("Couldn't find author. Please report this!")
334
341
  return None
335
342
 
336
- def direct_download_link(self, quality, mode) -> str:
337
- """
338
- Returns the direct download URL for a given quality (best/half/worst or a specific resolution).
339
- :param quality: 'best', 'half', 'worst', or a specific resolution like '720', '720p', 1080, etc.
340
- :param mode: The mode to filter links by (e.g., 'video')
341
- :return: str
342
- """
343
+ def _direct_download_quality_map(self, mode) -> dict[int, str]:
343
344
  if not self.enable_html:
344
345
  raise HTML_IS_DISABLED("HTML content is disabled! See Documentation for more details")
345
346
 
@@ -369,6 +370,25 @@ JSONDecodeError: I need your help to fix this error. Please report the URL you'v
369
370
  height = int(m.group(1)) # e.g., 1080
370
371
  quality_to_url[height] = href # last one wins; order doesn't matter
371
372
 
373
+ return quality_to_url
374
+
375
+ def video_qualities(self, mode=Encoding.mp4_h264) -> list:
376
+ """
377
+ Returns the available direct download qualities for a given mode.
378
+ :param mode: The mode to filter links by (e.g., 'video')
379
+ :return: list
380
+ """
381
+ quality_to_url = self._direct_download_quality_map(mode)
382
+ return sorted(quality_to_url.keys())
383
+
384
+ def direct_download_link(self, quality, mode) -> str:
385
+ """
386
+ Returns the direct download URL for a given quality (best/half/worst or a specific resolution).
387
+ :param quality: 'best', 'half', 'worst', or a specific resolution like '720', '720p', 1080, etc.
388
+ :param mode: The mode to filter links by (e.g., 'video')
389
+ :return: str
390
+ """
391
+ quality_to_url = self._direct_download_quality_map(mode)
372
392
  if not quality_to_url:
373
393
  raise NotAvailable(f"No URLs available for mode '{mode}'")
374
394
 
@@ -384,7 +404,7 @@ JSONDecodeError: I need your help to fix this error. Please report the URL you'v
384
404
  self.logger.info(f"Using direct download link: {full_url} ({chosen_height}p)")
385
405
  return full_url
386
406
 
387
- def download(self, quality, path, callback=None, mode=Encoding.mp4_h264, no_title=False, use_workaround=False,
407
+ async def download(self, quality, path, callback=None, mode=Encoding.mp4_h264, no_title=False, use_workaround=False,
388
408
  stop_event: threading.Event = None):
389
409
  if not self.enable_html:
390
410
  raise HTML_IS_DISABLED("HTML content is disabled! See Documentation for more details")
@@ -395,13 +415,13 @@ JSONDecodeError: I need your help to fix this error. Please report the URL you'v
395
415
 
396
416
  url = self.direct_download_link(quality, mode)
397
417
  if use_workaround:
398
- response_redirect_url = self.core.fetch(self.direct_download_link(quality, mode),
418
+ response_redirect_url = await self.core.fetch(self.direct_download_link(quality, mode),
399
419
  allow_redirects=True, get_response=True) # Sometimes the site trolls me
400
420
 
401
421
  url = response_redirect_url.url
402
422
 
403
423
  try:
404
- self.core.legacy_download(url=url, callback=callback, path=path, stop_event=stop_event)
424
+ await self.core.legacy_download(url=url, callback=callback, path=path, stop_event=stop_event)
405
425
  return True
406
426
 
407
427
  except Exception:
@@ -412,18 +432,23 @@ JSONDecodeError: I need your help to fix this error. Please report the URL you'v
412
432
 
413
433
 
414
434
  class Pornstar(Helper):
415
- def __init__(self, url: str, enable_html_scraping: bool = False, core: Optional[BaseCore] = None):
435
+ def __init__(self, url: str, enable_html_scraping: bool = False, core: Optional[BaseCore] = None, html_content=None):
416
436
  super().__init__(core=core, video=Video)
417
437
  self.core = core
418
438
  self.url = url
419
439
  self.enable_html_scraping = enable_html_scraping
420
440
  self.logger = setup_logger(name="EPorner API - [Pornstar]", log_file=None, level=logging.CRITICAL)
421
- self.html_content = self.core.fetch(self.url)
441
+ self.html_content = html_content
442
+
443
+ async def init(self):
444
+ if not self.html_content:
445
+ self.html_content = await self.core.fetch(self.url)
446
+ return self
422
447
 
423
448
  def enable_logging(self, log_file: str, level, log_ip: str = None, log_port: int = None):
424
449
  self.logger = setup_logger(name="EPorner API - [Pornstar]", log_file=log_file, level=level, http_ip=log_ip, http_port=log_port)
425
450
 
426
- def videos(self, pages: int = 0, videos_concurrency: int = None, pages_concurrency: int = None) -> Generator[Video, None, None]:
451
+ async def videos(self, pages: int = 0, videos_concurrency: int = None, pages_concurrency: int = None) -> AsyncGenerator[Video, None]:
427
452
  if pages == 0:
428
453
  video_amount = str(self.video_amount).replace(",", "")
429
454
  pages = round(int(video_amount)) / 37 # One page contains 37 videos
@@ -433,8 +458,9 @@ class Pornstar(Helper):
433
458
 
434
459
  pages = round(pages) # Dont ask
435
460
  page_urls = [urljoin(f"{self.url}/", str(page)) for page in range(1, pages + 1)]
436
- yield from self.iterator(page_urls=page_urls, extractor=extractor, pages_concurrency=pages_concurrency,
437
- videos_concurrency=videos_concurrency)
461
+ async for video in self.iterator(page_urls=page_urls, extractor=extractor, pages_concurrency=pages_concurrency,
462
+ videos_concurrency=videos_concurrency):
463
+ yield await video.init()
438
464
 
439
465
  @cached_property
440
466
  def name(self) -> str:
@@ -551,41 +577,45 @@ class Client(Helper):
551
577
  def enable_logging(self, log_file: str, level, log_ip: str = None, log_port: int = None):
552
578
  self.logger = setup_logger(name="EPorner API - [Client]", log_file=log_file, level=level, http_ip=log_ip, http_port=log_port)
553
579
 
554
- def get_video(self, url: str, enable_html_scraping: bool = True) -> Video:
580
+ async def get_video(self, url: str, enable_html_scraping: bool = True) -> Video:
555
581
  """Returns the Video object for a given URL"""
556
582
  self.logger.info(f"Returning video object for: {url} HTML Scraping -> {enable_html_scraping}")
557
- return Video(url, enable_html_scraping=enable_html_scraping, core=self.core)
583
+ video = Video(url, enable_html_scraping=enable_html_scraping, core=self.core)
584
+ return await video.init()
558
585
 
559
- def search_videos(self, query: str, sorting_gay: Union[str, Gay], sorting_order: Union[str, Order],
586
+ async def search_videos(self, query: str, sorting_gay: Union[str, Gay], sorting_order: Union[str, Order],
560
587
  sorting_low_quality: Union[str, LowQuality],
561
- page: int, per_page: int, enable_html_scraping: bool = True) -> Generator[Video, None, None]:
588
+ page: int, per_page: int, enable_html_scraping: bool = True) -> AsyncGenerator[Video, None]:
562
589
 
563
- response = self.core.fetch(f"{ROOT_URL}{API_SEARCH}?query={query}&per_page={per_page}&%page={page}"
590
+ response = await self.core.fetch(f"{ROOT_URL}{API_SEARCH}?query={query}&per_page={per_page}&%page={page}"
564
591
  f"&thumbsize=medium&order={sorting_order}&gay={sorting_gay}&lq="
565
592
  f"{sorting_low_quality}&format=json")
566
593
 
567
594
  json_data = json.loads(response)
568
595
  for video_ in json_data.get("videos", []): # Don't know why this works lmao
569
596
  id_ = video_["url"]
570
- yield Video(id_, enable_html_scraping, core=self.core)
597
+ video = Video(id_, enable_html_scraping, core=self.core)
598
+ yield await video.init()
571
599
 
572
- def get_videos_by_category(self, category: Union[str, Category], enable_html_scraping: bool = False,
573
- videos_concurrency: int = None, pages_concurrency: int = None) -> Generator[Video, None, None]:
600
+ async def get_videos_by_category(self, category: Union[str, Category], enable_html_scraping: bool = False,
601
+ videos_concurrency: int = None, pages_concurrency: int = None) -> AsyncGenerator[Video, None]:
574
602
 
575
603
  page_urls = [f"{ROOT_URL}cat/{category}/{page}" for page in range(1, 100)]
576
604
 
577
605
  videos_concurrency = videos_concurrency or self.core.config.videos_concurrency
578
606
  pages_concurrency = pages_concurrency or self.core.config.pages_concurrency
579
- yield from self.iterator(page_urls=page_urls, videos_concurrency=videos_concurrency,
580
- pages_concurrency=pages_concurrency, extractor=extractor)
607
+ async for video in self.iterator(page_urls=page_urls, videos_concurrency=videos_concurrency,
608
+ pages_concurrency=pages_concurrency, extractor=extractor):
609
+ yield await video.init()
581
610
 
582
611
 
583
- def get_pornstar(self, url: str, enable_html_scraping: bool = True) -> Pornstar:
612
+ async def get_pornstar(self, url: str, enable_html_scraping: bool = True) -> Pornstar:
584
613
  self.logger.info(f"Returning Pornstar object for: {url} HTML Scraping -> {enable_html_scraping}")
585
- return Pornstar(url, enable_html_scraping, core=self.core)
614
+ pornstar = Pornstar(url, enable_html_scraping, core=self.core)
615
+ return await pornstar.init()
586
616
 
587
617
 
588
- def main():
618
+ async def run_main():
589
619
  parser = argparse.ArgumentParser(description="API Command Line Interface")
590
620
  parser.add_argument("--download", metavar="URL (str)", type=str, help="URL to download from")
591
621
  parser.add_argument("--quality", metavar="best,half,worst", type=str, help="The video quality (best,half,worst)",
@@ -602,8 +632,8 @@ def main():
602
632
 
603
633
  if args.download:
604
634
  client = Client()
605
- video = client.get_video(args.download, enable_html_scraping=True)
606
- video.download(quality=args.quality, path=args.output, no_title=no_title)
635
+ video = await client.get_video(args.download, enable_html_scraping=True)
636
+ await video.download(quality=args.quality, path=args.output, no_title=no_title)
607
637
 
608
638
  if args.file:
609
639
  videos = []
@@ -613,11 +643,14 @@ def main():
613
643
  content = file.read().splitlines()
614
644
 
615
645
  for url in content:
616
- videos.append(client.get_video(url, enable_html_scraping=True))
646
+ videos.append(await client.get_video(url, enable_html_scraping=True))
617
647
 
618
648
  for video in videos:
619
- video.download(quality=args.quality, path=args.output, no_title=no_title)
649
+ await video.download(quality=args.quality, path=args.output, no_title=no_title)
620
650
 
621
651
 
652
+ def main():
653
+ asyncio.run(run_main())
654
+
622
655
  if __name__ == "__main__":
623
656
  main()
@@ -1,31 +1,34 @@
1
- import time
2
-
1
+ import pytest
3
2
  from ..eporner_api import Client, Category
4
3
  from base_api import BaseCore
5
- core = BaseCore()
6
- core.config.pages_concurrency = 1
7
- core.config.videos_concurrency = 1
8
-
9
4
 
10
- def test_category():
5
+ @pytest.mark.asyncio
6
+ async def test_category():
7
+ core = BaseCore()
8
+ core.config.pages_concurrency = 1
9
+ core.config.videos_concurrency = 1
10
+
11
11
  videos_1 = Client(core).get_videos_by_category(category=Category.JAPANESE)
12
12
  videos_2 = Client(core).get_videos_by_category(category=Category.HD)
13
13
  videos_3 = Client(core).get_videos_by_category(category=Category.BLONDE)
14
14
 
15
- for idx, video in enumerate(videos_1):
15
+ idx = 0
16
+ async for video in videos_1:
16
17
  if idx == 3:
17
18
  break
18
-
19
19
  assert isinstance(video.title, str) and len(video.title) > 0
20
+ idx += 1
20
21
 
21
- for idx, video in enumerate(videos_2):
22
+ idx = 0
23
+ async for video in videos_2:
22
24
  if idx == 3:
23
25
  break
24
-
25
26
  assert isinstance(video.title, str) and len(video.title) > 0
27
+ idx += 1
26
28
 
27
- for idx, video in enumerate(videos_3):
29
+ idx = 0
30
+ async for video in videos_3:
28
31
  if idx == 3:
29
32
  break
30
-
31
33
  assert isinstance(video.title, str) and len(video.title) > 0
34
+ idx += 1
@@ -1,27 +1,28 @@
1
+ import pytest
1
2
  from ..eporner_api import Client
2
- import time
3
- url = "https://www.eporner.com/pornstar/riley-reid/"
4
3
  from base_api import BaseCore
5
- core = BaseCore()
6
- core.config.pages_concurrency = 1
7
- core.config.videos_concurrency = 1
8
4
 
9
- pornstar = Client(core).get_pornstar(url, enable_html_scraping=True)
5
+ @pytest.mark.asyncio
6
+ async def test_pornstar():
7
+ url = "https://www.eporner.com/pornstar/riley-reid/"
8
+ core = BaseCore()
9
+ core.config.pages_concurrency = 1
10
+ core.config.videos_concurrency = 1
11
+ pornstar = await Client(core).get_pornstar(url, enable_html_scraping=True)
10
12
 
11
-
12
- def test_videos():
13
13
  videos = pornstar.videos(pages=1)
14
-
15
- for idx, video in enumerate(videos):
14
+
15
+ idx = 0
16
+ async for video in videos:
16
17
  assert isinstance(video.title, str) and len(video.title) > 3
17
18
  if idx == 5:
18
19
  break
20
+ idx += 1
19
21
 
20
- def test_information():
21
22
  assert isinstance(pornstar.pornstar_rank, str) and len(pornstar.pornstar_rank) >= 1
22
23
  assert isinstance(pornstar.aliases, list) and len(pornstar.aliases) > 1
23
24
  assert isinstance(pornstar.biography, str) and len(pornstar.biography) > 10
24
- assert isinstance(pornstar.age, str) and len(pornstar.age) >= 2 # would be weird if this is 1-9 lmao (just kidding)
25
+ assert isinstance(pornstar.age, str) and len(pornstar.age) >= 2
25
26
  assert isinstance(pornstar.cup, str) and len(pornstar.cup) >= 1
26
27
  assert isinstance(pornstar.country, str) and len(pornstar.country) >= 2
27
28
  assert isinstance(pornstar.weight, str) and len(pornstar.weight) >= 2
@@ -1,48 +1,53 @@
1
+ import pytest
1
2
  from ..eporner_api import Client, Gay, Order, LowQuality
2
- import time
3
3
 
4
- client = Client()
4
+
5
5
  query = "Mia Khalifa"
6
- pages = 2
7
- per_page = 10
6
+ pages = 1
7
+ per_page = 1
8
+
9
+ @pytest.fixture
10
+ def client():
11
+ return Client()
8
12
 
9
- def test_search_1():
13
+ @pytest.mark.asyncio
14
+ async def test_search_1(client):
10
15
  videos = client.search_videos(query, page=pages, per_page=per_page, sorting_gay=Gay.exclude_gay_content, sorting_order=Order.top_rated, sorting_low_quality=LowQuality.exclude_low_quality_content)
11
- for video in videos:
16
+ async for video in videos:
12
17
  assert len(video.title) > 0
13
18
 
14
-
15
- def test_search_2():
19
+ @pytest.mark.asyncio
20
+ async def test_search_2(client):
16
21
  videos = client.search_videos(query, page=pages, per_page=per_page, sorting_gay=Gay.only_gay_content, sorting_order=Order.latest, sorting_low_quality=LowQuality.only_low_quality_content)
17
- for video in videos:
22
+ async for video in videos:
18
23
  assert len(video.title) > 0
19
24
 
20
-
21
- def test_search_3():
25
+ @pytest.mark.asyncio
26
+ async def test_search_3(client):
22
27
  videos = client.search_videos(query, page=pages, per_page=per_page, sorting_gay=Gay.include_gay_content, sorting_order=Order.longest, sorting_low_quality=LowQuality.include_low_quality_content)
23
- for video in videos:
28
+ async for video in videos:
24
29
  assert len(video.title) > 0
25
30
 
26
-
27
- def test_search_4():
31
+ @pytest.mark.asyncio
32
+ async def test_search_4(client):
28
33
  videos = client.search_videos(query, page=pages, per_page=pages, sorting_gay=Gay.exclude_gay_content, sorting_order=Order.shortest, sorting_low_quality=LowQuality.include_low_quality_content)
29
- for video in videos:
34
+ async for video in videos:
30
35
  assert len(video.title) > 0
31
36
 
32
-
33
- def test_search_5():
37
+ @pytest.mark.asyncio
38
+ async def test_search_5(client):
34
39
  videos = client.search_videos(query, page=pages, per_page=per_page, sorting_order=Gay.include_gay_content, sorting_gay=Order.top_weekly, sorting_low_quality=LowQuality.include_low_quality_content)
35
- for video in videos:
40
+ async for video in videos:
36
41
  assert len(video.title) > 0
37
42
 
38
-
39
- def test_search_6():
43
+ @pytest.mark.asyncio
44
+ async def test_search_6(client):
40
45
  videos = client.search_videos(query, page=pages, per_page=per_page, sorting_order=Order.most_popular, sorting_low_quality=LowQuality.include_low_quality_content, sorting_gay=Gay.only_gay_content)
41
- for video in videos:
46
+ async for video in videos:
42
47
  assert len(video.title) > 0
43
48
 
44
-
45
- def test_search_7():
49
+ @pytest.mark.asyncio
50
+ async def test_search_7(client):
46
51
  videos = client.search_videos(query, page=pages, per_page=per_page, sorting_gay=Gay.include_gay_content, sorting_order=Order.top_monthly, sorting_low_quality=LowQuality.include_low_quality_content)
47
- for video in videos:
52
+ async for video in videos:
48
53
  assert len(video.title) > 0
@@ -1,70 +1,26 @@
1
+ import pytest
1
2
  from ..eporner_api import Client, Encoding, NotAvailable
2
- import time
3
- url = "https://www.eporner.com/video-bTwP6vsFj5U/human-anal-sex-toy/"
4
- video = Client().get_video(url, enable_html_scraping=True)
5
- time.sleep(5) # Lmao
6
3
 
7
- def test_title():
4
+ @pytest.mark.asyncio
5
+ async def test_video():
6
+ url = "https://www.eporner.com/video-bTwP6vsFj5U/human-anal-sex-toy/"
7
+ video = await Client().get_video(url, enable_html_scraping=True)
8
8
  assert isinstance(video.title, str) and len(video.title) > 0
9
-
10
-
11
- def test_video_id():
12
9
  assert isinstance(video.video_id, str) and len(video.video_id) > 0
13
-
14
-
15
- def test_tags():
16
10
  assert isinstance(video.tags, list) and len(video.tags) > 0
17
-
18
-
19
- def test_views():
20
11
  assert isinstance(video.views, int) and video.views > 0
21
-
22
-
23
- def test_rate():
24
12
  assert isinstance(video.rate, str) and len(video.rate) > 0
25
-
26
-
27
- def test_publish_date():
28
13
  assert isinstance(video.publish_date, str) and len(video.publish_date) > 0
29
-
30
-
31
- def test_length_seconds():
32
- assert isinstance(video.length, int) > 0
33
-
34
-
35
- def test_length_minutes():
14
+ assert isinstance(video.length, int) and video.length > 0
36
15
  assert isinstance(video.length_minutes, str) and len(video.length_minutes) > 0
37
-
38
-
39
- def test_embed_url():
40
16
  assert isinstance(video.embed_url, str) and len(video.embed_url) > 0
41
-
42
-
43
- def test_thumbnails():
44
17
  assert isinstance(video.thumbnail, str) and len(video.thumbnail) > 0
45
-
46
-
47
- def test_bitrate():
48
18
  assert isinstance(video.bitrate, str) and len(video.bitrate) > 0
49
-
50
-
51
- def test_source_video_url():
52
19
  assert isinstance(video.source_video_url, str) and len(video.source_video_url) > 0
53
-
54
-
55
- def test_rating():
56
20
  assert isinstance(video.rating, str) and len(video.rating) > 0
57
-
58
-
59
- def test_rating_count():
60
21
  assert isinstance(video.rating_count, str) and len(video.rating_count) > 0
61
-
62
-
63
- def test_author():
64
22
  assert isinstance(video.author, str) and len(video.author) > 0
65
23
 
66
-
67
- def test_direct_download_url():
68
24
  assert isinstance(video.direct_download_link(quality=2160, mode=Encoding.mp4_h264), str)
69
25
  assert isinstance(video.direct_download_link(quality="half", mode=Encoding.mp4_h264), str)
70
26
  assert isinstance(video.direct_download_link(quality="worst", mode=Encoding.mp4_h264), str)
@@ -72,6 +28,5 @@ def test_direct_download_url():
72
28
  assert isinstance(video.direct_download_link(quality="best", mode=Encoding.av1), str)
73
29
  assert isinstance(video.direct_download_link(quality="half", mode=Encoding.av1), str)
74
30
  assert isinstance(video.direct_download_link(quality="worst", mode=Encoding.av1), str)
75
-
76
31
  except NotAvailable:
77
32
  pass
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "Eporner_API"
7
- version = "1.9.6"
7
+ version = "2.0"
8
8
  description = "A Python API for the Porn Site Eporner.com"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.9" # 3.9 due to httpx requirements
@@ -15,14 +15,14 @@ authors = [
15
15
  ]
16
16
  dependencies = [
17
17
  "bs4",
18
- "eaf_base_api",
18
+ "eaf-base-api",
19
19
  ]
20
20
  classifiers = [
21
21
  "Programming Language :: Python",
22
22
  ]
23
23
 
24
24
  [project.optional-dependencies]
25
- full = ["lxml", "httpx[http2]", "httpx[socks]"]
25
+ full = ["lxml"]
26
26
 
27
27
  [project.urls]
28
28
  Homepage = "https://github.com/EchterAlsFake/EPorner_API"
File without changes
File without changes