Browse Source

Improve background URL generation

pull/65/head
Ben Kurtovic 5 months ago
parent
commit
f03a58a802
1 changed files with 45 additions and 51 deletions
  1. +45
    -51
      src/copyvios/background.py

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

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

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

logger = logging.getLogger(__name__)

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


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


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


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


def _get_fresh_from_list() -> BackgroundInfo | None:
@@ -114,19 +92,7 @@ def _get_fresh_from_list() -> BackgroundInfo | None:
except IndexError:
logger.exception(f"Failed to find any images on {page.title!r}")
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 = {
@@ -134,20 +100,48 @@ _BACKGROUNDS = {
"list": _get_fresh_from_list,
}

_BACKGROUND_CACHE: dict[str, BackgroundInfo | None] = {}
_BACKGROUND_INFO_CACHE: dict[str, BackgroundInfo | None] = {}
_LAST_BACKGROUND_UPDATES: dict[str, date] = {
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)
max_age = datetime(next_day.year, next_day.month, next_day.day, tzinfo=UTC)
if datetime.now(UTC) > max_age:
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()
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]:
@@ -161,9 +155,9 @@ def get_background(selected: str) -> tuple[str | None, str | None]:
else:
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

Loading…
Cancel
Save