add search_file

parent 13f8b8b8
import aiohttp import aiohttp
from urllib.parse import urlencode from urllib.parse import urlencode
from typing import List
from . import models from . import models
...@@ -24,6 +26,13 @@ class BaseAPI: ...@@ -24,6 +26,13 @@ class BaseAPI:
resp.raise_for_status() resp.raise_for_status()
return await resp.json() return await resp.json()
async def post(self, path: str, data: dict = None, json: dict = None):
url = f"{self.BASE_URL}/{path.lstrip('/')}"
async with self.session.post(url, data=data, json=json) as resp:
resp.raise_for_status()
return await resp.json()
async def close(self): async def close(self):
await self.session.close() await self.session.close()
...@@ -37,14 +46,27 @@ class APIInfo: ...@@ -37,14 +46,27 @@ class APIInfo:
return models.APIVersion(**data) return models.APIVersion(**data)
class PackagesetInfo: class PackageInfo:
def __init__(self, client: BaseAPI): def __init__(self, client: BaseAPI):
self.client = client self.client = client
async def packages_by_file_names(self, files: List[str], branch: str, arch: str | None = None) -> models.PackageByFileNameModel:
data = {"files": files,"branch": branch}
if arch:
data["arch"] = arch
data = await self.client.post("/package/packages_by_file_names", json=data)
return models.PackageByFileNameModel(**data)
class PackagesetInfo:
def __init__(self, client: BaseAPI):
self.client = client
async def active_packagesets(self) -> models.PackageSetActivePackageSetsModel: async def active_packagesets(self) -> models.PackageSetActivePackageSetsModel:
data = await self.client.get("/packageset/active_packagesets") data = await self.client.get("/packageset/active_packagesets")
return models.PackageSetActivePackageSetsModel(**data) return models.PackageSetActivePackageSetsModel(**data)
async def repository_statistics(self, branch: str | None = None) -> models.RepositoryStatisticsModel: async def repository_statistics(self, branch: str | None = None) -> models.RepositoryStatisticsModel:
if branch: if branch:
data = await self.client.get("/packageset/repository_statistics", {"branch": branch}) data = await self.client.get("/packageset/repository_statistics", {"branch": branch})
...@@ -66,6 +88,26 @@ class BugInfo: ...@@ -66,6 +88,26 @@ class BugInfo:
return models.BugzillaInfoModel(**data) return models.BugzillaInfoModel(**data)
class FileInfo:
def __init__(self, client: BaseAPI):
self.client = client
async def packages_by_file(self, branch: str, file_name: str) -> models.FilePackagesByFileModel:
data = await self.client.get(
"/file/packages_by_file",
{"branch": branch, "file_name": file_name}
)
return models.FilePackagesByFileModel(**data)
async def search(self, branch: str, file_name: str, limit: int | None = None) -> models.FilesModel:
data = await self.client.get(
"/file/search",
{"branch": branch, "file_name": file_name,
"limit": limit if limit else 1000}
)
return models.FilesModel(**data)
class SiteInfo: class SiteInfo:
def __init__(self, client: BaseAPI): def __init__(self, client: BaseAPI):
self.client = client self.client = client
...@@ -99,8 +141,10 @@ class PackagesAPI: ...@@ -99,8 +141,10 @@ class PackagesAPI:
def __init__(self): def __init__(self):
self._client = BaseAPI() self._client = BaseAPI()
self.api = APIInfo(self._client) self.api = APIInfo(self._client)
self.package = PackageInfo(self._client)
self.packageset = PackagesetInfo(self._client) self.packageset = PackagesetInfo(self._client)
self.bug = BugInfo(self._client) self.bug = BugInfo(self._client)
self.file = FileInfo(self._client)
self.site = SiteInfo(self._client) self.site = SiteInfo(self._client)
async def init(self): async def init(self):
......
...@@ -85,3 +85,47 @@ class BugzillaInfoModel(BaseModel): ...@@ -85,3 +85,47 @@ class BugzillaInfoModel(BaseModel):
request_args: Dict[str, Any] request_args: Dict[str, Any]
length: int length: int
bugs: List[BugzillaInfoElementModel] bugs: List[BugzillaInfoElementModel]
class FilePackagesByFileElementModel(BaseModel):
hash: str
name: str
version: str
release: str
arch: str
class FilePackagesByFileModel(BaseModel):
request_args: Dict[str, Any]
length: int
packages: List[FilePackagesByFileElementModel]
class PackageByFileNameElementModel(BaseModel):
name: str
version: str
release: str
disttag: str
sha1: str
branch: str
arch: str
files: List[str]
class PackageByFileNameModel(BaseModel):
request_args: Dict[str, Any]
length: int
packages: List[PackageByFileNameElementModel]
not_found: List[str]
class FilesElementModel(BaseModel):
file_name: str
file_hashname: str
file_class: str
symlink: str
file_mode: str
class FilesModel(BaseModel):
request_args: Dict[str, Any]
length: int
files: List[FilesElementModel]
\ No newline at end of file
from telegrinder import MESSAGE_FROM_USER, Dispatch, Message, WaiterMachine, CallbackQuery
from telegrinder.rules import Command, PayloadEqRule, Text, IsUser, Markup, Argument
from telegrinder.tools.formatting import HTMLFormatter, link, bold
from aiohttp import ClientResponseError
from database.models import User
from collections import defaultdict
from api import api
from api.models import FilesModel, PackageByFileNameModel
dp = Dispatch()
wm = WaiterMachine(dp)
@dp.message(Command("search_file", Argument("file_name"), Argument("branch", optional=True)))
async def search_file_handler(m: Message, user: User | None, file_name: str, branch: str | None = None) -> None:
if not len(file_name):
return
if not branch:
branch = user.default_branch \
if user.default_branch \
else (await api.packageset.active_packagesets()).packagesets[0]
try:
search_file_data = await api.file.packages_by_file(branch, file_name)
except ClientResponseError:
await m.answer("Ничего не найдено.")
return
search_file_message = "Пакеты:\n\n"
for package in search_file_data.packages:
search_file_message += f"{package.arch} | {package.name} | {package.version}-{package.release}\n"
await m.answer(
search_file_message
)
"""
@dp.message(Command("test_search_file", Argument("file_name"), Argument("branch", optional=True), Argument("pattern", optional=True)))
async def search_file_handler(m: Message, user: User | None, file_name: str, branch: str | None = None, pattern: str | None = None) -> None:
if not len(file_name):
return
if not branch:
branch = user.default_branch \
if user.default_branch \
else (await api.packageset.active_packagesets()).packagesets[0]
try:
search_file_data: FilesModel = await api.file.search(branch, file_name)
except ClientResponseError:
await m.answer("Ничего не найдено.")
return
list_files = [file.file_name for file in search_file_data.files]
search_packages_data: PackageByFileNameModel = await api.package.packages_by_file_names(
list_files, branch, "x86_64"
)
grouped = defaultdict(set)
for pkg in search_packages_data.packages:
key = f"{pkg.name}"
for f in pkg.files:
grouped[key].add(f)
grouped = {k: sorted(v) for k, v in grouped.items()}
search_file_message = "Пакеты:\n\n"
for pkg, files in grouped.items():
if "devel" in pkg and pattern != "devel":
continue
if (pattern and pattern in pkg) or not pattern:
search_file_message += HTMLFormatter(bold(
link(f"https://packages.altlinux.org/ru/{branch}/srpms/{pkg}", text=pkg))) + ":\n"
for i, file in enumerate(files):
search_file_message += f" {file}\n"
if i == 9:
search_file_message += "...\n"
break
search_file_message += "\n"
res = await m.answer(search_file_message)
print(res)
"""
...@@ -27,7 +27,7 @@ async def profile_handler(m: Message, user: User | None, branch: str | None = No ...@@ -27,7 +27,7 @@ async def profile_handler(m: Message, user: User | None, branch: str | None = No
if user: if user:
branch = user.default_branch branch = user.default_branch
else: else:
branch = (await api.packageset.active_packagesets())[0] branch = active_branches[0]
statistics_data = (await api.packageset.repository_statistics(branch)).branches[0] statistics_data = (await api.packageset.repository_statistics(branch)).branches[0]
......
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