Skip to content

Commit dd0a772

Browse files
committed
- you can now use integer values yay
- release 1.9.5
1 parent eef65f9 commit dd0a772

3 files changed

Lines changed: 68 additions & 28 deletions

File tree

eporner_api/eporner_api.py

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
from bs4 import BeautifulSoup
2323
from urllib.parse import urljoin
2424
from functools import cached_property
25-
from typing import Generator, Union, Optional
2625
from base_api.modules.config import RuntimeConfig
26+
from typing import Generator, Union, Optional, List
2727
from base_api.base import BaseCore, setup_logger, Helper
2828

2929
"""
@@ -57,6 +57,40 @@
5757
"""
5858

5959

60+
61+
def _normalize_quality_value(q) -> Union[str, int]:
62+
if isinstance(q, int):
63+
return q
64+
s = str(q).lower().strip()
65+
if s in {"best", "half", "worst"}:
66+
return s
67+
m = re.search(r'(\d{3,4})', s)
68+
if m:
69+
return int(m.group(1))
70+
raise ValueError(f"Invalid quality: {q}")
71+
72+
73+
def _choose_quality_from_list(available: List[str | int], target: Union[str, int]):
74+
# available like ["240", "360", "480", "720", "1080"]
75+
av = sorted({int(x) for x in available})
76+
if isinstance(target, str):
77+
if target == "best":
78+
return av[-1]
79+
if target == "worst":
80+
return av[0]
81+
if target == "half":
82+
return av[len(av) // 2]
83+
raise ValueError("Invalid label.")
84+
# numeric: highest ≤ target, else closest
85+
le = [h for h in av if h <= target]
86+
if le:
87+
return le[-1]
88+
# fallback closest (ties -> higher)
89+
return min(av, key=lambda h: (abs(h - target), -h))
90+
91+
92+
93+
6094
class Video:
6195
def __init__(self, url: str, enable_html_scraping: bool = True, core: Optional[BaseCore] = None):
6296
self.core = core
@@ -291,48 +325,54 @@ def author(self) -> str:
291325

292326
def direct_download_link(self, quality, mode) -> str:
293327
"""
294-
Returns the direct download URL for a given quality
295-
:param quality: 'best', 'half', 'worst', or a specific resolution like '720p'
328+
Returns the direct download URL for a given quality (best/half/worst or a specific resolution).
329+
:param quality: 'best', 'half', 'worst', or a specific resolution like '720', '720p', 1080, etc.
296330
:param mode: The mode to filter links by (e.g., 'video')
297331
:return: str
298332
"""
299333
if not self.enable_html:
300334
raise HTML_IS_DISABLED("HTML content is disabled! See Documentation for more details")
301335

302336
soup = BeautifulSoup(self.html_content, 'lxml')
303-
available_links = []
337+
quality_to_url: dict[int, str] = {}
338+
339+
# Extract resolutions from link text or href (e.g., "1080p", "720", etc.)
340+
# Accept any 3–4 digit height optionally followed by 'p'
341+
_res_rx = re.compile(r'(?<!\d)(\d{3,4})p?(?!\d)')
304342

305-
# Define the quality preferences in descending order
306-
quality_preferences = ['2160p', '1440p', '1080p', '720p', '480p', '360p', '240p']
343+
mode_lc = str(mode).lower().strip()
307344

308-
# Search for all <a> tags and collect links for the specified mode
309345
for a_tag in soup.find_all('a', href=True):
310-
link_text = a_tag.text.lower()
346+
# Combine visible text + href for matching
347+
text = " ".join(a_tag.stripped_strings).lower()
311348
href = a_tag['href']
312-
# Filter links by mode
313-
if str(mode.lower()) in link_text:
314-
for preference in quality_preferences:
315-
if preference in link_text:
316-
available_links.append((preference, href))
317-
break
349+
haystack = f"{text} {href.lower()}"
318350

319-
reversed_links = list(reversed(available_links))
351+
# Filter by mode (same semantics as your original code)
352+
if mode_lc not in haystack:
353+
continue
320354

321-
if quality == "best":
322-
quality, url = reversed_links[0]
355+
m = _res_rx.search(haystack)
356+
if not m:
357+
continue
323358

324-
elif quality == "half":
325-
index_to_use = round(len(available_links) / 2)
326-
quality, url = reversed_links[index_to_use]
359+
height = int(m.group(1)) # e.g., 1080
360+
quality_to_url[height] = href # last one wins; order doesn't matter
327361

328-
elif quality == "worst":
329-
quality, url = reversed_links[-1]
362+
if not quality_to_url:
363+
raise NotAvailable(f"No URLs available for mode '{mode}'")
330364

331-
else:
332-
raise "No URLs available? Please report that"
365+
# Choose the appropriate height using your helpers
366+
available_heights = sorted(quality_to_url.keys()) # e.g., [240, 360, 480, 720, 1080]
367+
qn = _normalize_quality_value(quality) # -> 'best' | 'half' | 'worst' | int
368+
chosen_height = _choose_quality_from_list(available_heights, qn)
369+
370+
# Map back to URL and return absolute URL
371+
chosen_url = quality_to_url[chosen_height]
372+
full_url = urljoin("https://eporner.com", str(chosen_url))
333373

334-
self.logger.error(f"Using direct donwload Link: {str(url)}")
335-
return urljoin("https://eporner.com", str(url))
374+
self.logger.info(f"Using direct download link: {full_url} ({chosen_height}p)")
375+
return full_url
336376

337377
def download(self, quality, path, callback=None, mode=Encoding.mp4_h264, no_title=False, use_workaround=False):
338378
if not self.enable_html:

eporner_api/tests/test_video.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def test_author():
6565

6666

6767
def test_direct_download_url():
68-
assert isinstance(video.direct_download_link(quality="best", mode=Encoding.mp4_h264), str)
68+
assert isinstance(video.direct_download_link(quality=2160, mode=Encoding.mp4_h264), str)
6969
assert isinstance(video.direct_download_link(quality="half", mode=Encoding.mp4_h264), str)
7070
assert isinstance(video.direct_download_link(quality="worst", mode=Encoding.mp4_h264), str)
7171
try:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "Eporner_API"
7-
version = "1.9.4"
7+
version = "1.9.5"
88
description = "A Python API for the Porn Site Eporner.com"
99
readme = "README.md"
1010
requires-python = ">=3.6"

0 commit comments

Comments
 (0)