Sfoglia il codice sorgente

Improve background URL generation

pull/65/head
Ben Kurtovic 5 mesi fa
parent
commit
f03a58a802
1 ha cambiato i file con 45 aggiunte e 51 eliminazioni
  1. +45
    -51
      src/copyvios/background.py

+ 45
- 51
src/copyvios/background.py Vedi File

@@ -1,11 +1,10 @@
__all__ = ["get_background"] __all__ = ["get_background"]


import bisect
import functools
import json import json
import logging import logging
import random import random
import re import re
import urllib.parse
from dataclasses import dataclass from dataclasses import dataclass
from datetime import UTC, date, datetime, timedelta from datetime import UTC, date, datetime, timedelta
from typing import Self from typing import Self
@@ -18,16 +17,16 @@ from .cookies import get_cookies


logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)


THUMB_SIZES = [20, 40, 60, 120, 250, 330, 500, 960, 1280, 1920, 3840]



@dataclass(frozen=True) @dataclass(frozen=True)
class BackgroundInfo: class BackgroundInfo:
filename: str filename: str


@dataclass(frozen=True)
class BackgroundURLs:
url: str url: str
descurl: str descurl: str
width: int
height: int




@dataclass(frozen=True) @dataclass(frozen=True)
@@ -54,27 +53,6 @@ def _get_commons_site() -> Site:
return cache.bot.wiki.add_site(project="wikimedia", lang="commons") return cache.bot.wiki.add_site(project="wikimedia", lang="commons")




def _load_file(site: Site, filename: str) -> BackgroundInfo | None:
prefix = "File:"
try:
data = site.api_query(
action="query",
prop="imageinfo",
iiprop="url|size|canonicaltitle",
titles=prefix + filename,
)
res = list(data["query"]["pages"].values())[0]["imageinfo"][0]
name = res["canonicaltitle"]
assert isinstance(name, str), name
except Exception:
logger.exception(f"Failed to get info for file {prefix + filename!r}")
return None
name = name.removeprefix(prefix).replace(" ", "_")
return BackgroundInfo(
name, res["url"], res["descriptionurl"], res["width"], res["height"]
)


def _get_fresh_from_potd() -> BackgroundInfo | None: def _get_fresh_from_potd() -> BackgroundInfo | None:
site = _get_commons_site() site = _get_commons_site()
date = datetime.now(UTC).strftime("%Y-%m-%d") date = datetime.now(UTC).strftime("%Y-%m-%d")
@@ -93,7 +71,7 @@ def _get_fresh_from_potd() -> BackgroundInfo | None:
if not filename: if not filename:
logger.exception(f"Failed to extract POTD from {page.title!r}") logger.exception(f"Failed to extract POTD from {page.title!r}")
return None return None
return _load_file(site, filename)
return BackgroundInfo(filename)




def _get_fresh_from_list() -> BackgroundInfo | None: def _get_fresh_from_list() -> BackgroundInfo | None:
@@ -114,19 +92,7 @@ def _get_fresh_from_list() -> BackgroundInfo | None:
except IndexError: except IndexError:
logger.exception(f"Failed to find any images on {page.title!r}") logger.exception(f"Failed to find any images on {page.title!r}")
return None return None
return _load_file(site, filename)


def _build_url(screen: ScreenInfo, background: BackgroundInfo) -> str:
width = screen.width
if background.width / background.height > screen.width / screen.height:
width = int(background.width / background.height * screen.height)
i = bisect.bisect_right(THUMB_SIZES, width)
width = THUMB_SIZES[i] if i < len(THUMB_SIZES) else background.width
if width >= background.width:
return background.url
url = background.url.replace("/commons/", "/commons/thumb/")
return f"{url}/{width}px-{urllib.parse.quote(background.filename)}"
return BackgroundInfo(filename)




_BACKGROUNDS = { _BACKGROUNDS = {
@@ -134,20 +100,48 @@ _BACKGROUNDS = {
"list": _get_fresh_from_list, "list": _get_fresh_from_list,
} }


_BACKGROUND_CACHE: dict[str, BackgroundInfo | None] = {}
_BACKGROUND_INFO_CACHE: dict[str, BackgroundInfo | None] = {}
_LAST_BACKGROUND_UPDATES: dict[str, date] = { _LAST_BACKGROUND_UPDATES: dict[str, date] = {
key: datetime.min.date() for key in _BACKGROUNDS key: datetime.min.date() for key in _BACKGROUNDS
} }




def _get_background(selected: str) -> BackgroundInfo | None:
def _get_background_info(selected: str) -> BackgroundInfo | None:
next_day = _LAST_BACKGROUND_UPDATES[selected] + timedelta(days=1) next_day = _LAST_BACKGROUND_UPDATES[selected] + timedelta(days=1)
max_age = datetime(next_day.year, next_day.month, next_day.day, tzinfo=UTC) max_age = datetime(next_day.year, next_day.month, next_day.day, tzinfo=UTC)
if datetime.now(UTC) > max_age: if datetime.now(UTC) > max_age:
update_func = _BACKGROUNDS.get(selected, _get_fresh_from_list) update_func = _BACKGROUNDS.get(selected, _get_fresh_from_list)
_BACKGROUND_CACHE[selected] = update_func()
_BACKGROUND_INFO_CACHE[selected] = update_func()
_LAST_BACKGROUND_UPDATES[selected] = datetime.now(UTC).date() _LAST_BACKGROUND_UPDATES[selected] = datetime.now(UTC).date()
return _BACKGROUND_CACHE[selected]
return _BACKGROUND_INFO_CACHE[selected]


@functools.lru_cache(maxsize=256)
def _get_background_urls(
background: BackgroundInfo, screen_width: int
) -> BackgroundURLs | None:
site = _get_commons_site()
prefix = "File:"
try:
data = site.api_query(
action="query",
prop="imageinfo",
iiprop="url|canonicaltitle",
iiurlwidth=screen_width,
titles=prefix + background.filename,
)
res = list(data["query"]["pages"].values())[0]["imageinfo"][0]
name = res["canonicaltitle"]
assert isinstance(name, str), name
url = res["thumburl"]
descurl = res["descriptionurl"]
except Exception:
logger.exception(
f"Failed to get info for file {prefix + background.filename!r}"
)
return None
name = name.removeprefix(prefix).replace(" ", "_")
return BackgroundURLs(url=url, descurl=descurl)




def get_background(selected: str) -> tuple[str | None, str | None]: def get_background(selected: str) -> tuple[str | None, str | None]:
@@ -161,9 +155,9 @@ def get_background(selected: str) -> tuple[str | None, str | None]:
else: else:
screen = ScreenInfo() screen = ScreenInfo()


background = _get_background(selected)
if background:
bg_url = _build_url(screen, background)
return bg_url, background.descurl
else:
return None, None
bg_info = _get_background_info(selected)
if bg_info is not None:
bg_urls = _get_background_urls(bg_info, screen.width)
if bg_urls is not None:
return bg_urls.url, bg_urls.descurl
return None, None

Caricamento…
Annulla
Salva