58 lines
2.7 KiB
Python
58 lines
2.7 KiB
Python
"""Runtime configuration, all from the environment."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
def _int(name: str, default: int) -> int:
|
|
try:
|
|
return int(os.getenv(name, "") or default)
|
|
except ValueError:
|
|
return default
|
|
|
|
|
|
def _opt(name: str) -> str | None:
|
|
# Compose passes unset optionals through as empty strings rather than
|
|
# omitting them, so "" has to mean "absent" here.
|
|
return (os.getenv(name) or "").strip() or None
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Settings:
|
|
auth_token: str = field(default_factory=lambda: os.environ["OWUITOOLS_AUTH_TOKEN"])
|
|
egress_proxy: str = field(default_factory=lambda: os.getenv("OWUITOOLS_EGRESS_PROXY", "http://owuitools-egress:3128"))
|
|
searxng_url: str = field(default_factory=lambda: os.getenv("OWUITOOLS_SEARXNG_URL", "http://owuitools-searxng:8080").rstrip("/"))
|
|
valkey_url: str = field(default_factory=lambda: os.getenv("OWUITOOLS_VALKEY_URL", "redis://owuitools-valkey:6379/0"))
|
|
contact: str = field(default_factory=lambda: os.getenv("OWUITOOLS_CONTACT", "owuitools@localhost"))
|
|
# Optional. Goes in the User-Agent so a site that wants to know who is
|
|
# fetching can look you up. Leave it unset if this is not reachable
|
|
# from outside, which is the normal case.
|
|
public_url: str | None = field(default_factory=lambda: _opt("OWUITOOLS_PUBLIC_URL"))
|
|
|
|
max_response_chars: int = field(default_factory=lambda: _int("OWUITOOLS_MAX_RESPONSE_CHARS", 12000))
|
|
probe_rate_per_hour: int = field(default_factory=lambda: _int("OWUITOOLS_PROBE_RATE_PER_HOUR", 30))
|
|
log_level: str = field(default_factory=lambda: os.getenv("OWUITOOLS_LOG_LEVEL", "INFO").upper())
|
|
|
|
github_token: str | None = field(default_factory=lambda: _opt("OWUITOOLS_GITHUB_TOKEN"))
|
|
stackexchange_key: str | None = field(default_factory=lambda: _opt("OWUITOOLS_STACKEXCHANGE_KEY"))
|
|
nvd_key: str | None = field(default_factory=lambda: _opt("OWUITOOLS_NVD_KEY"))
|
|
|
|
@property
|
|
def user_agent(self) -> str:
|
|
# Wikimedia hard-blocks requests with no User-Agent (verified: 403)
|
|
# and its policy explicitly disallows generic ones like "curl/8.5.0",
|
|
# which pass today and may not tomorrow. OpenAlex and Crossref read
|
|
# the same string to decide whether you get the polite pool.
|
|
#
|
|
# The URL is included only if there is one to give. It used to be
|
|
# one deployment's address, hardcoded - which every other
|
|
# deployment would then have been announcing as its own to every
|
|
# site it fetched from.
|
|
site = f"+{self.public_url}; " if self.public_url else ""
|
|
return f"owuitools/1.0 ({site}{self.contact})"
|
|
|
|
|
|
settings = Settings()
|