altrepo: make module configurable with ALTRepoConfig dataclass

parent a4016de2
...@@ -2,30 +2,28 @@ import aiohttp ...@@ -2,30 +2,28 @@ import aiohttp
from .api import ALTRepoAPI from .api import ALTRepoAPI
from .appstream import ALTRepoAppStream from .appstream import ALTRepoAppStream
from .config import ALTRepoConfig
from .parser import ALTRepoParser from .parser import ALTRepoParser
class ALTRepo: class ALTRepo:
def __init__(self): def __init__(self, config: ALTRepoConfig | None = None):
self.config = config or ALTRepoConfig()
self._session: aiohttp.ClientSession | None = None self._session: aiohttp.ClientSession | None = None
self.api: ALTRepoAPI | None = None self.api: ALTRepoAPI | None = None
self.appstream: ALTRepoAppStream | None = None self.appstream: ALTRepoAppStream | None = None
self.parser: ALTRepoParser | None = None self.parser: ALTRepoParser | None = None
async def init( async def init(self, session: aiohttp.ClientSession | None = None):
self,
appstream_dir: str = "appstream"
):
if self._session is None: if self._session is None:
self._session = aiohttp.ClientSession() self._session = session or aiohttp.ClientSession()
self.api = ALTRepoAPI(self._session) self.api = ALTRepoAPI(self._session, self.config)
self.appstream = ALTRepoAppStream(self._session, appstream_dir) self.appstream = ALTRepoAppStream(self._session, self.config)
self.parser = ALTRepoParser(self._session) self.parser = ALTRepoParser(self._session, self.config)
async def close(self): async def close(self):
await self._session.close() await self._session.close()
altrepo = ALTRepo() __all__ = ("ALTRepo", "ALTRepoConfig")
__all__ = ("altrepo")
...@@ -8,10 +8,10 @@ from . import errors ...@@ -8,10 +8,10 @@ from . import errors
class BaseAPI: class BaseAPI:
BASE_URL = "https://rdb.altlinux.org/api"
def __init__(self, session: aiohttp.ClientSession): def __init__(self, session: aiohttp.ClientSession, base_url: str):
self.session = session self.session = session
self.BASE_URL = base_url
async def _handle_response(self, resp: aiohttp.ClientResponse): async def _handle_response(self, resp: aiohttp.ClientResponse):
...@@ -1813,9 +1813,9 @@ class VulnInfo: ...@@ -1813,9 +1813,9 @@ class VulnInfo:
class ALTRepoAPI: class ALTRepoAPI:
def __init__(self, session: aiohttp.ClientSession): def __init__(self, session: aiohttp.ClientSession, config: "ALTRepoConfig"):
self.BASE_API_VERSION = "1.25.6" self.BASE_API_VERSION = "1.25.6"
self._client = BaseAPI(session) self._client = BaseAPI(session, config.api_base_url)
self.api = APIInfo(self._client) self.api = APIInfo(self._client)
self.task = TaskInfo(self._client) self.task = TaskInfo(self._client)
self.package = PackageInfo(self._client) self.package = PackageInfo(self._client)
......
...@@ -5,13 +5,10 @@ from lxml import etree ...@@ -5,13 +5,10 @@ from lxml import etree
class AppStreamClient: class AppStreamClient:
BASE_URL = (
"https://git.altlinux.org/gears/a/appstream-data-desktop.git?"
"a=blob_plain;f=xmls/altlinux.xml;hb=refs/heads/{}"
)
def __init__(self, session: aiohttp.ClientSession): def __init__(self, session: aiohttp.ClientSession, appstream_url: str):
self.session = session self.session = session
self._appstream_url = appstream_url
async def _handle_response(self, resp: aiohttp.ClientResponse): async def _handle_response(self, resp: aiohttp.ClientResponse):
...@@ -22,7 +19,7 @@ class AppStreamClient: ...@@ -22,7 +19,7 @@ class AppStreamClient:
return None return None
async def get(self, branch: str) -> str | None: async def get(self, branch: str) -> str | None:
url = self.BASE_URL.format(branch) url = self._appstream_url.format(branch=branch)
async with self.session.get(url) as resp: async with self.session.get(url) as resp:
return await self._handle_response(resp) return await self._handle_response(resp)
...@@ -99,14 +96,14 @@ class PackageInfo: ...@@ -99,14 +96,14 @@ class PackageInfo:
class ALTRepoAppStream: class ALTRepoAppStream:
BRANCHES = ["sisyphus", "p11"]
def __init__(self, session: aiohttp.ClientSession, appstream_dir: str): def __init__(self, session: aiohttp.ClientSession, config: "ALTRepoConfig"):
self._client = AppStreamClient(session) self.branches = config.appstream_branches
self.data = DataInfo(self._client, appstream_dir) self._client = AppStreamClient(session, config.appstream_url)
self.data = DataInfo(self._client, config.appstream_dir)
self.package = PackageInfo(self._client, self.data) self.package = PackageInfo(self._client, self.data)
self.data._on_update = self.package.rebuild_cache self.data._on_update = self.package.rebuild_cache
for branch in self.BRANCHES: for branch in self.branches:
if self.data.has_file(branch): if self.data.has_file(branch):
self.package.rebuild_cache(branch) self.package.rebuild_cache(branch)
from dataclasses import dataclass, field
@dataclass
class ALTRepoConfig:
api_base_url: str = "https://rdb.altlinux.org/api"
cybertalk_url: str = "https://lists.altlinux.org/pipermail/sisyphus-cybertalk/{}/"
ftbfs_url: str = "https://git.altlinux.org/beehive/stats/Sisyphus-x86_64/ftbfs-joined"
watch_url: str = "https://watch.altlinux.org/pub/watch/{by_acl}/{nickname}.txt"
appstream_url: str = (
"https://git.altlinux.org/gears/a/appstream-data-desktop.git?"
"a=blob_plain;f=xmls/altlinux.xml;hb=refs/heads/{branch}"
)
appstream_branches: list[str] = field(default_factory=lambda: ["sisyphus", "p11"])
appstream_dir: str = "appstream"
...@@ -25,11 +25,12 @@ class BaseParser: ...@@ -25,11 +25,12 @@ class BaseParser:
class NewsInfo: class NewsInfo:
def __init__(self, client: BaseParser): def __init__(self, client: BaseParser, cybertalk_url: str):
self.client = client self.client = client
self._cybertalk_url = cybertalk_url
async def news_urls(self) -> models.NewsURL: async def news_urls(self) -> models.NewsURL:
return await urls_parser(self.client) return await urls_parser(self.client, self._cybertalk_url)
async def _get_packages(self, branch: str) -> models.PackagesModel | None: async def _get_packages(self, branch: str) -> models.PackagesModel | None:
url = getattr(await self.news_urls(), branch, None) url = getattr(await self.news_urls(), branch, None)
...@@ -57,7 +58,7 @@ class NewsInfo: ...@@ -57,7 +58,7 @@ class NewsInfo:
async def bugs_by_range( async def bugs_by_range(
self, date_from: date, date_to: date self, date_from: date, date_to: date
) -> dict[str, int] | None: ) -> dict[str, int] | None:
urls = await urls_for_range(self.client, date_from, date_to, "bugs") urls = await urls_for_range(self.client, date_from, date_to, self._cybertalk_url, "bugs")
if not urls: if not urls:
return None return None
...@@ -83,7 +84,7 @@ class NewsInfo: ...@@ -83,7 +84,7 @@ class NewsInfo:
async def packages_by_range( async def packages_by_range(
self, date_from: date, date_to: date self, date_from: date, date_to: date
) -> models.PackagesModel | None: ) -> models.PackagesModel | None:
urls = await urls_for_range(self.client, date_from, date_to) urls = await urls_for_range(self.client, date_from, date_to, self._cybertalk_url)
if not urls: if not urls:
return None return None
...@@ -145,12 +146,13 @@ def _aggregate_packages( ...@@ -145,12 +146,13 @@ def _aggregate_packages(
class PackagesInfo: class PackagesInfo:
def __init__(self, client: BaseParser): def __init__(self, client: BaseParser, ftbfs_url: str, watch_url: str):
self.client = client self.client = client
self._ftbfs_url = ftbfs_url
self._watch_url = watch_url
async def ftbfs(self) -> List[models.FTBFSModel]: async def ftbfs(self) -> List[models.FTBFSModel]:
url = "https://git.altlinux.org/beehive/stats/Sisyphus-x86_64/ftbfs-joined" text = await self.client.get(self._ftbfs_url)
text = await self.client.get(url)
return ftbfs_parser(text) return ftbfs_parser(text)
async def watch_by_maintainer( async def watch_by_maintainer(
...@@ -158,7 +160,7 @@ class PackagesInfo: ...@@ -158,7 +160,7 @@ class PackagesInfo:
maintainer_nickname: str, maintainer_nickname: str,
by_acl: Literal["by-acl", "by-expanded-acl", "by-expanded-leader", "by-leader"], by_acl: Literal["by-acl", "by-expanded-acl", "by-expanded-leader", "by-leader"],
) -> List[models.WatchByMaintainerModel]: ) -> List[models.WatchByMaintainerModel]:
url = f"https://watch.altlinux.org/pub/watch/{by_acl}/{maintainer_nickname}.txt" url = self._watch_url.format(by_acl=by_acl, nickname=maintainer_nickname)
try: try:
text = await self.client.get(url) text = await self.client.get(url)
return watch_parser(text) return watch_parser(text)
...@@ -167,7 +169,7 @@ class PackagesInfo: ...@@ -167,7 +169,7 @@ class PackagesInfo:
class ALTRepoParser: class ALTRepoParser:
def __init__(self, session: aiohttp.ClientSession): def __init__(self, session: aiohttp.ClientSession, config: "ALTRepoConfig"):
self._client = BaseParser(session) self._client = BaseParser(session)
self.news = NewsInfo(self._client) self.news = NewsInfo(self._client, config.cybertalk_url)
self.packages = PackagesInfo(self._client) self.packages = PackagesInfo(self._client, config.ftbfs_url, config.watch_url)
...@@ -5,15 +5,12 @@ from datetime import datetime, date ...@@ -5,15 +5,12 @@ from datetime import datetime, date
from .. import models from .. import models
from config import CYBERTALK_URL async def urls_parser(client, cybertalk_url: str):
async def urls_parser(client):
now = datetime.now() now = datetime.now()
year_month = f"{now.year}-{now.strftime("%B")}" year_month = f"{now.year}-{now.strftime("%B")}"
today = now.strftime("%Y%m%d") today = now.strftime("%Y%m%d")
base_url = CYBERTALK_URL.format(year_month) base_url = cybertalk_url.format(year_month)
html = await client.get(f"{base_url}date.html", "koi8-r") html = await client.get(f"{base_url}date.html", "koi8-r")
soup = BeautifulSoup(html, "html.parser") soup = BeautifulSoup(html, "html.parser")
...@@ -42,7 +39,8 @@ async def urls_parser(client): ...@@ -42,7 +39,8 @@ async def urls_parser(client):
async def urls_for_range( async def urls_for_range(
client, date_from: date, date_to: date, news_type: str = "packages" client, date_from: date, date_to: date,
cybertalk_url: str, news_type: str = "packages",
) -> list[tuple[date, str]]: ) -> list[tuple[date, str]]:
results = [] results = []
pattern = re.compile(rf"Sisyphus-(\d{{8}}) {re.escape(news_type)}") pattern = re.compile(rf"Sisyphus-(\d{{8}}) {re.escape(news_type)}")
...@@ -50,7 +48,7 @@ async def urls_for_range( ...@@ -50,7 +48,7 @@ async def urls_for_range(
current = date_from.replace(day=1) current = date_from.replace(day=1)
while current <= date_to: while current <= date_to:
year_month = f"{current.year}-{current.strftime('%B')}" year_month = f"{current.year}-{current.strftime('%B')}"
base_url = CYBERTALK_URL.format(year_month) base_url = cybertalk_url.format(year_month)
try: try:
html = await client.get(f"{base_url}date.html", "koi8-r") html = await client.get(f"{base_url}date.html", "koi8-r")
except: except:
......
...@@ -5,6 +5,8 @@ from telegrinder.tools.formatting import HTMLFormatter ...@@ -5,6 +5,8 @@ from telegrinder.tools.formatting import HTMLFormatter
from pydantic_settings import BaseSettings, SettingsConfigDict from pydantic_settings import BaseSettings, SettingsConfigDict
from altrepo import ALTRepo
from typing import List from typing import List
...@@ -19,6 +21,7 @@ class Config(BaseSettings): ...@@ -19,6 +21,7 @@ class Config(BaseSettings):
config = Config() config = Config()
altrepo = ALTRepo()
DEFAUIL_BRANCHES = [ DEFAUIL_BRANCHES = [
"sisyphus", "sisyphus",
...@@ -37,7 +40,6 @@ APPSTREAM_SKIP_LIST = [ ...@@ -37,7 +40,6 @@ APPSTREAM_SKIP_LIST = [
TASK_URL = "https://packages.altlinux.org/ru/tasks/" TASK_URL = "https://packages.altlinux.org/ru/tasks/"
BUGS_URL = "https://bugzilla.altlinux.org/" BUGS_URL = "https://bugzilla.altlinux.org/"
PACKAGES_URL = "https://packages.altlinux.org/ru/{repo}/" PACKAGES_URL = "https://packages.altlinux.org/ru/{repo}/"
CYBERTALK_URL = "https://lists.altlinux.org/pipermail/sisyphus-cybertalk/{}/"
INSTALL_APP_URL = "https://appstream.k8s.eterfund.ru/app/{app_id}/" INSTALL_APP_URL = "https://appstream.k8s.eterfund.ru/app/{app_id}/"
# ====== BOT # ====== BOT
......
...@@ -2,7 +2,7 @@ from telegrinder import Dispatch, Message, CallbackQuery ...@@ -2,7 +2,7 @@ from telegrinder import Dispatch, Message, CallbackQuery
from telegrinder.rules import Command, Argument, Text, IsPrivate, CallbackDataMarkup from telegrinder.rules import Command, Argument, Text, IsPrivate, CallbackDataMarkup
from telegrinder.tools.formatting import HTMLFormatter from telegrinder.tools.formatting import HTMLFormatter
from altrepo import altrepo from config import altrepo
from config import BUGS_URL from config import BUGS_URL
from database.models import User from database.models import User
......
from telegrinder import Dispatch, Message, CallbackQuery from telegrinder import Dispatch, Message, CallbackQuery
from telegrinder.rules import Command, Argument, CallbackDataMarkup from telegrinder.rules import Command, Argument, CallbackDataMarkup
from altrepo import altrepo from config import altrepo
from altrepo.api.errors import DataNotFoundError, RequestValidationError from altrepo.api.errors import DataNotFoundError, RequestValidationError
from database.models import User from database.models import User
......
from telegrinder import Dispatch, Message from telegrinder import Dispatch, Message
from telegrinder.rules import Command, Argument from telegrinder.rules import Command, Argument
from altrepo import altrepo from config import altrepo
from database.models import User from database.models import User
from database.func import DB from database.func import DB
......
...@@ -2,7 +2,7 @@ from telegrinder import Dispatch, Message ...@@ -2,7 +2,7 @@ from telegrinder import Dispatch, Message
from telegrinder.rules import Command from telegrinder.rules import Command
from telegrinder.tools.formatting import HTMLFormatter, link from telegrinder.tools.formatting import HTMLFormatter, link
from altrepo import altrepo from config import altrepo
from database.func import DB from database.func import DB
from services.utils import _bold from services.utils import _bold
from config import bot_repositories, bot_developers from config import bot_repositories, bot_developers
......
...@@ -5,7 +5,7 @@ from telegrinder.rules import Command, Argument, CallbackDataMarkup, Text, IsPri ...@@ -5,7 +5,7 @@ from telegrinder.rules import Command, Argument, CallbackDataMarkup, Text, IsPri
from datetime import datetime, timedelta from datetime import datetime, timedelta
from altrepo import altrepo from config import altrepo
from services.news import format_packages, format_bugs from services.news import format_packages, format_bugs
from services.utils import _bold, int_validator, pluralize from services.utils import _bold, int_validator, pluralize
......
...@@ -3,7 +3,7 @@ from telegrinder.rules import Command, Argument ...@@ -3,7 +3,7 @@ from telegrinder.rules import Command, Argument
from telegrinder.tools.formatting import HTMLFormatter, link from telegrinder.tools.formatting import HTMLFormatter, link
from altrepo import altrepo from config import altrepo
from altrepo.api.errors import DataNotFoundError, RequestValidationError from altrepo.api.errors import DataNotFoundError, RequestValidationError
from data.keyboards import package_keyboards from data.keyboards import package_keyboards
......
...@@ -10,7 +10,7 @@ from database.func import DB ...@@ -10,7 +10,7 @@ from database.func import DB
from data.keyboards import profile_keyboards from data.keyboards import profile_keyboards
from modules import scheduler from modules import scheduler
from altrepo import altrepo from config import altrepo
from services.menu import send_menu from services.menu import send_menu
from services.utils import _bold from services.utils import _bold
......
...@@ -8,7 +8,7 @@ from services.utils import _bold ...@@ -8,7 +8,7 @@ from services.utils import _bold
from database.models import User from database.models import User
from collections import defaultdict from collections import defaultdict
from altrepo import altrepo from config import altrepo
dp = Dispatch() dp = Dispatch()
wm = WaiterMachine(dp) wm = WaiterMachine(dp)
......
...@@ -3,7 +3,7 @@ from telegrinder.rules import Command, Text, IsPrivate, Argument ...@@ -3,7 +3,7 @@ from telegrinder.rules import Command, Text, IsPrivate, Argument
from datetime import datetime from datetime import datetime
from altrepo import altrepo from config import altrepo
from database.models import User from database.models import User
from services.utils import _bold from services.utils import _bold
......
...@@ -3,7 +3,7 @@ from telegrinder.rules import Command, Argument, CallbackDataMarkup ...@@ -3,7 +3,7 @@ from telegrinder.rules import Command, Argument, CallbackDataMarkup
from telegrinder.tools.formatting import HTMLFormatter, code_inline from telegrinder.tools.formatting import HTMLFormatter, code_inline
from altrepo import altrepo from config import altrepo
from altrepo.api.errors import DataNotFoundError from altrepo.api.errors import DataNotFoundError
from database.models import User from database.models import User
......
...@@ -2,7 +2,7 @@ from telegrinder import Dispatch, Message, CallbackQuery ...@@ -2,7 +2,7 @@ from telegrinder import Dispatch, Message, CallbackQuery
from telegrinder.rules import Command, Argument, Text, IsPrivate, CallbackDataMarkup from telegrinder.rules import Command, Argument, Text, IsPrivate, CallbackDataMarkup
from telegrinder.tools.formatting import HTMLFormatter from telegrinder.tools.formatting import HTMLFormatter
from altrepo import altrepo from config import altrepo
from database.models import User from database.models import User
from data.keyboards import watch_keyboards from data.keyboards import watch_keyboards
......
...@@ -3,10 +3,10 @@ from telegrinder.modules import logger ...@@ -3,10 +3,10 @@ from telegrinder.modules import logger
from telegrinder.types import BotCommand from telegrinder.types import BotCommand
from telegrinder.node import Error from telegrinder.node import Error
from config import tg_api from config import tg_api, altrepo
from modules import scheduler from modules import scheduler
from altrepo import altrepo
from altrepo.api.errors import TooManyRequests from altrepo.api.errors import TooManyRequests
from database.models import db, Maintainer, User, Package, ScheduledTask from database.models import db, Maintainer, User, Package, ScheduledTask
from middlewares import UserMiddleware from middlewares import UserMiddleware
......
...@@ -2,21 +2,19 @@ import asyncio ...@@ -2,21 +2,19 @@ import asyncio
from telegrinder.modules import logger from telegrinder.modules import logger
from altrepo import altrepo from config import altrepo
BRANCHES = ["sisyphus", "p11"]
async def update_appstream_data(): async def update_appstream_data():
branches = altrepo.appstream.branches
results = await asyncio.gather(*( results = await asyncio.gather(*(
altrepo.api.package.package_info( altrepo.api.package.package_info(
"appstream-data-desktop", branch=branch, source=True "appstream-data-desktop", branch=branch, source=True
) )
for branch in BRANCHES for branch in branches
)) ))
for branch, result in zip(BRANCHES, results): for branch, result in zip(branches, results):
package = result.packages[0] package = result.packages[0]
current_version = altrepo.appstream.data.get_current_version(branch) current_version = altrepo.appstream.data.get_current_version(branch)
package_version = f"{package.version}-{package.release}" package_version = f"{package.version}-{package.release}"
......
...@@ -2,7 +2,7 @@ from telegrinder.tools.formatting import HTMLFormatter ...@@ -2,7 +2,7 @@ from telegrinder.tools.formatting import HTMLFormatter
from config import tg_api from config import tg_api
from altrepo import altrepo from config import altrepo
from database.models import User from database.models import User
from data.keyboards import bugs_keyboards from data.keyboards import bugs_keyboards
......
from telegrinder.modules import logger from telegrinder.modules import logger
from config import config, tg_api from config import config, tg_api
from altrepo import altrepo from config import altrepo
async def test_api_version(): async def test_api_version():
......
from telegrinder.modules import logger from telegrinder.modules import logger
from altrepo import altrepo from config import altrepo
from database.func import DB from database.func import DB
async def update_maintainers(): async def update_maintainers():
......
...@@ -2,7 +2,7 @@ from telegrinder.tools.formatting import HTMLFormatter ...@@ -2,7 +2,7 @@ from telegrinder.tools.formatting import HTMLFormatter
from config import tg_api from config import tg_api
from altrepo import altrepo from config import altrepo
from database.models import User from database.models import User
from data.keyboards import watch_keyboards from data.keyboards import watch_keyboards
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment