From 24214ebc3a64caa55ed36cdea6727afb0590e490 Mon Sep 17 00:00:00 2001 From: shmyga Date: Fri, 4 Sep 2026 10:23:00 +0300 Subject: [PATCH] refactor: add headers module --- .pm.toml | 9 ++++++- gallery/painting/rp5/api.py | 23 ++--------------- gallery/painting/yandextv/api.py | 34 +++----------------------- gallery/sketch/headers.py | 42 ++++++++++++++++++++++++++++++++ gallery/sketch/source.py | 10 ++------ 5 files changed, 57 insertions(+), 61 deletions(-) create mode 100644 gallery/sketch/headers.py diff --git a/.pm.toml b/.pm.toml index f323a7e..fa71ff0 100644 --- a/.pm.toml +++ b/.pm.toml @@ -1,2 +1,9 @@ [presets.python.tasks.setup.playwright] -commands = [".venv/bin/playwright install chromium --with-deps --only-shell"] \ No newline at end of file +conditions = ["{{ '.venv/bin/playwright' | file }}"] +commands = [".venv/bin/playwright install chromium --with-deps --only-shell"] + +[presets.locales.tasks.build.locales] +priority = 1 +conditions = ["{{ 'locales/ru/LC_MESSAGES' | file }}"] +cwd = "locales/ru/LC_MESSAGES" +commands = ["msgfmt messages.po"] diff --git a/gallery/painting/rp5/api.py b/gallery/painting/rp5/api.py index 759193f..1403445 100644 --- a/gallery/painting/rp5/api.py +++ b/gallery/painting/rp5/api.py @@ -14,36 +14,17 @@ from gallery.sketch.weather.model import ( from gallery.sketch.weather.util import merge_weather_values from gallery.util import TimeUnit +from ...sketch.headers import build_headers from .parser import parse_page logger = logging.getLogger("rp5") -HEADERS: dict[str, str] = { - "Accept": "application/json, text/javascript, */*; q=0.01", - "Accept-Encoding": "gzip, deflate, br, zstd", - "Accept-Language": "en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7,uk;q=0.6", - "Connection": "keep-alive", - "Host": "rp5.ru", - "Referer": "https://rp5.ru/", - "Sec-Fetch-Dest": "empty", - "Sec-Fetch-Mode": "cors", - "Sec-Fetch-Site": "same-origin", - "User-Agent": ApiSource.DEFAULT_USER_AGENT, - "X-Requested-With": "XMLHttpRequest", - "sec-ch-ua": '"Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150"', - "sec-ch-ua-mobile": "?0", - "sec-ch-ua-platform": '"Linux"', -} - class RP5WeatherApi(WeatherApi): PROVIDER = "rp5" def _build_source(self) -> ApiSource: - return ApiSource( - "https://rp5.ru", - headers=HEADERS, - ) + return ApiSource("https://rp5.ru", headers=build_headers("rp5.ru")) async def find_locations(self, query: str) -> list[Location]: endpoint = "docs/search/ru" diff --git a/gallery/painting/yandextv/api.py b/gallery/painting/yandextv/api.py index a1f7ae0..9e1416c 100644 --- a/gallery/painting/yandextv/api.py +++ b/gallery/painting/yandextv/api.py @@ -8,44 +8,16 @@ from gallery.sketch.schedule.api import ScheduleApi from gallery.sketch.schedule.model import Channel, Schedule, ScheduleValue from gallery.sketch.source import ApiSource +from ...sketch.headers import build_headers + logger = logging.getLogger("matchtv") -HEADERS: dict[str, str] = { - "Accept": ( - "text/html," - "application/xhtml+xml," - "application/xml;q=0.9," - "image/avif,image/webp," - "image/apng,*/*;q=0.8," - "application/signed-exchange;v=b3;q=0.9" - ), - "Accept-Encoding": "gzip, deflate, br", - "Accept-Language": "en-US,en;q=0.9", - "Connection": "keep-alive", - "Host": "tv.yandex.ru", - "sec-ch-ua": '"Chromium";v="100", " Not A;Brand";v="99"', - "sec-ch-ua-mobile": "?0", - "sec-ch-ua-platform": '"Linux"', - "Sec-Fetch-Dest": "document", - "Sec-Fetch-Mode": "navigate", - "Sec-Fetch-Site": "none", - "Sec-Fetch-User": "?1", - "Upgrade-Insecure-Requests": "1", - "User-Agent": ( - "Mozilla/5.0 (X11; Linux x86_64) " - "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/100.0.4896.133 " - "Safari/537.36" - ), -} - - class YandexTvApi(ScheduleApi): PROVIDER = "yandextv" def _build_source(self) -> ApiSource: - return ApiSource("https://tv.yandex.ru", headers=HEADERS) + return ApiSource("https://tv.yandex.ru", headers=build_headers("tv.yandex.ru")) async def find_channels(self, query: str) -> list[Channel]: url = ( diff --git a/gallery/sketch/headers.py b/gallery/sketch/headers.py new file mode 100644 index 0000000..dddcd8e --- /dev/null +++ b/gallery/sketch/headers.py @@ -0,0 +1,42 @@ +DEFAULT_USER_AGENT = ( + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36" +) + +DEFAULT_ACCEPT = ( + "text/html," + "application/xhtml+xml," + "application/xml;q=0.9," + "image/avif," + "image/webp," + "image/apng," + "*/*;q=0.8," + "application/signed-exchange;v=b3;q=0.7" +) + +DEFAULT_HEADERS = { + "Accept": DEFAULT_ACCEPT, + "Accept-Encoding": "gzip, deflate, br, zstd", + "Accept-Language": "en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7,uk;q=0.6", + "Cache-Control": "max-age=0", + "Connection": "keep-alive", + "Host": None, + "Referer": None, + "Sec-Fetch-Dest": "document", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-Site": "none", + "Sec-Fetch-User": "?1", + "Upgrade-Insecure-Requests": "1", + "User-Agent": DEFAULT_USER_AGENT, + "sec-ch-ua": '"Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Linux"', +} + + +def build_headers(host: str, *, user_agent: str | None = None) -> dict[str, str]: + result = DEFAULT_HEADERS.copy() + result["Host"] = host + result["Referer"] = f"https://{host}/" + if user_agent is not None: + result["User-Agent"] = user_agent + return result diff --git a/gallery/sketch/source.py b/gallery/sketch/source.py index 54345f2..61c7626 100644 --- a/gallery/sketch/source.py +++ b/gallery/sketch/source.py @@ -10,25 +10,20 @@ logger = logging.getLogger("source") RequestMode = Literal["base", "browser"] DEFAULT_REQUEST_MODE: RequestMode = "base" -DEFAULT_METHOD = "GET" +DEFAULT_METHOD: str = "GET" class ApiSource: - DEFAULT_USER_AGENT = ( - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" - ) DEFAULT_TIMEOUT = 30.0 def __init__( self, base_url, - user_agent: str = DEFAULT_USER_AGENT, timeout: float = DEFAULT_TIMEOUT, cookies: dict[str, str] | None = None, headers: dict[str, str] | None = None, ): self._base_url = base_url - self._user_agent = user_agent self._timeout = timeout self._cookies = cookies self._headers = headers @@ -39,9 +34,8 @@ class ApiSource: method: str = DEFAULT_METHOD, data: Any | None = None, ) -> str: - headers = {"User-Agent": self._user_agent, **(self._headers or {})} async with aiohttp.ClientSession( - headers=headers, + headers=self._headers, cookies=self._cookies, raise_for_status=True, ) as session: