Eporner_API 2.1__tar.gz → 2.2__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.
- {eporner_api-2.1 → eporner_api-2.2}/PKG-INFO +2 -2
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/eporner_api.py +20 -6
- eporner_api-2.2/eporner_api/modules/type_hints.py +4 -0
- {eporner_api-2.1 → eporner_api-2.2}/pyproject.toml +2 -2
- {eporner_api-2.1 → eporner_api-2.2}/LICENSE +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/README.md +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/__init__.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/modules/__init__.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/modules/consts.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/modules/errors.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/modules/locals.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/modules/progressbar.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/modules/sorting.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/tests/__init__.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/tests/test_category.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/tests/test_pornstar.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/tests/test_search.py +0 -0
- {eporner_api-2.1 → eporner_api-2.2}/eporner_api/tests/test_video.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Eporner_API
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2
|
|
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,7 +10,7 @@ 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-Python: >=3.
|
|
13
|
+
Requires-Python: >=3.12
|
|
14
14
|
Project-URL: Homepage, https://github.com/EchterAlsFake/EPorner_API
|
|
15
15
|
Provides-Extra: full
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
@@ -8,6 +8,8 @@ import argparse
|
|
|
8
8
|
import traceback
|
|
9
9
|
import threading
|
|
10
10
|
|
|
11
|
+
from eporner_api.modules.type_hints import on_error_hint
|
|
12
|
+
|
|
11
13
|
try:
|
|
12
14
|
from .modules.consts import *
|
|
13
15
|
from .modules.locals import *
|
|
@@ -37,8 +39,8 @@ from typing import AsyncGenerator
|
|
|
37
39
|
from functools import cached_property
|
|
38
40
|
from base_api.modules.config import RuntimeConfig
|
|
39
41
|
from base_api.base import BaseCore, setup_logger, Helper
|
|
40
|
-
from base_api.modules.errors import InvalidProxy, BotProtectionDetected, NetworkingError, UnknownError, VideoFetchError, PageFetchError
|
|
41
42
|
from base_api.modules.static_functions import normalize_quality_value, choose_quality_from_list, str_to_bool
|
|
43
|
+
from base_api.modules.errors import InvalidProxy, BotProtectionDetected, NetworkingError, UnknownError, VideoFetchError, PageFetchError, ResourceGone
|
|
42
44
|
|
|
43
45
|
"""
|
|
44
46
|
Copyright (c) 2024-2026 Johannes Habel
|
|
@@ -70,6 +72,14 @@ If you still need additional functionalities and information from videos / Eporn
|
|
|
70
72
|
HTML Content. See the Documentation for more details.
|
|
71
73
|
"""
|
|
72
74
|
|
|
75
|
+
async def on_error(url: str, error: Exception, attempt: int) -> bool:
|
|
76
|
+
print(f"URL: {url}, ERROR: {error}, Attempt: {attempt}")
|
|
77
|
+
|
|
78
|
+
if isinstance(error, ResourceGone):
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
return True
|
|
82
|
+
|
|
73
83
|
|
|
74
84
|
async def get_html_content(core: BaseCore, url: str, get_json: bool = False) -> str | None | dict:
|
|
75
85
|
# What should I do here?
|
|
@@ -448,7 +458,8 @@ class Pornstar(Helper):
|
|
|
448
458
|
def enable_logging(self, log_file: str, level, log_ip: str | None = None, log_port: int | None = None):
|
|
449
459
|
self.logger = setup_logger(name="EPorner API - [Pornstar]", log_file=log_file, level=level, http_ip=log_ip, http_port=log_port)
|
|
450
460
|
|
|
451
|
-
async def videos(self, pages: int = 0, videos_concurrency: int | None = None, pages_concurrency: int | None = None
|
|
461
|
+
async def videos(self, pages: int = 0, videos_concurrency: int | None = None, pages_concurrency: int | None = None,
|
|
462
|
+
on_video_error: on_error_hint = on_error, on_page_error: on_error_hint = None) -> AsyncGenerator[Video, None]:
|
|
452
463
|
if pages == 0:
|
|
453
464
|
video_amount = str(self.video_amount).replace(",", "")
|
|
454
465
|
pages = round(int(video_amount)) / 37 # One page contains 37 videos
|
|
@@ -460,7 +471,8 @@ class Pornstar(Helper):
|
|
|
460
471
|
pages = round(pages) # Dont ask
|
|
461
472
|
page_urls = [urljoin(f"{self.url}/", str(page)) for page in range(1, pages + 1)]
|
|
462
473
|
async for video in self.iterator(target_page_urls=page_urls, video_link_extractor=extractor, max_page_concurrency=pages_concurrency,
|
|
463
|
-
max_video_concurrency=videos_concurrency
|
|
474
|
+
max_video_concurrency=videos_concurrency,
|
|
475
|
+
on_video_error=on_video_error, on_page_error=on_page_error):
|
|
464
476
|
if isinstance(video, (VideoFetchError, PageFetchError)):
|
|
465
477
|
self.logger.error(f"Error during iteration: {video}")
|
|
466
478
|
continue
|
|
@@ -601,8 +613,9 @@ class Client(Helper):
|
|
|
601
613
|
video = Video(url=id_, core=self.core, enable_html_scraping=enable_html_scraping)
|
|
602
614
|
yield await video.init()
|
|
603
615
|
|
|
604
|
-
async def get_videos_by_category(self, category: str | Category,
|
|
605
|
-
videos_concurrency: int | None = None, pages_concurrency: int | None = None
|
|
616
|
+
async def get_videos_by_category(self, category: str | Category,
|
|
617
|
+
videos_concurrency: int | None = None, pages_concurrency: int | None = None,
|
|
618
|
+
on_video_error: on_error_hint = on_error, on_page_error: on_error_hint = None) -> AsyncGenerator[Video, None]:
|
|
606
619
|
|
|
607
620
|
page_urls = [f"{ROOT_URL}cat/{category}/{page}" for page in range(1, 100)]
|
|
608
621
|
|
|
@@ -610,7 +623,8 @@ class Client(Helper):
|
|
|
610
623
|
pages_concurrency = pages_concurrency or self.core.configuration.pages_concurrency
|
|
611
624
|
assert videos_concurrency and pages_concurrency
|
|
612
625
|
async for video in self.iterator(target_page_urls=page_urls, max_video_concurrency=videos_concurrency,
|
|
613
|
-
max_page_concurrency=pages_concurrency, video_link_extractor=extractor
|
|
626
|
+
max_page_concurrency=pages_concurrency, video_link_extractor=extractor,
|
|
627
|
+
on_video_error=on_video_error, on_page_error=on_page_error):
|
|
614
628
|
if isinstance(video, (VideoFetchError, PageFetchError)):
|
|
615
629
|
self.logger.error(f"Error during iteration: {video}")
|
|
616
630
|
continue
|
|
@@ -4,10 +4,10 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "Eporner_API"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.2"
|
|
8
8
|
description = "A Python API for the Porn Site Eporner.com"
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
11
|
license = "LGPL-3.0-only"
|
|
12
12
|
license-files = ["LICENSE"]
|
|
13
13
|
authors = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|