Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
altlinux-packages-bot
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Unitsaev
altlinux-packages-bot
Commits
c3d58864
Verified
Commit
c3d58864
authored
Jul 12, 2025
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add search_file
parent
13f8b8b8
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
184 additions
and
3 deletions
+184
-3
methods.py
src/api/methods.py
+46
-2
models.py
src/api/models.py
+45
-0
search.py
src/handlers/search.py
+92
-0
statistics.py
src/handlers/statistics.py
+1
-1
No files found.
src/api/methods.py
View file @
c3d58864
import
aiohttp
from
urllib.parse
import
urlencode
from
typing
import
List
from
.
import
models
...
...
@@ -24,6 +26,13 @@ class BaseAPI:
resp
.
raise_for_status
()
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
):
await
self
.
session
.
close
()
...
...
@@ -37,14 +46,27 @@ class APIInfo:
return
models
.
APIVersion
(
**
data
)
class
Package
set
Info
:
class
PackageInfo
:
def
__init__
(
self
,
client
:
BaseAPI
):
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
:
data
=
await
self
.
client
.
get
(
"/packageset/active_packagesets"
)
return
models
.
PackageSetActivePackageSetsModel
(
**
data
)
async
def
repository_statistics
(
self
,
branch
:
str
|
None
=
None
)
->
models
.
RepositoryStatisticsModel
:
if
branch
:
data
=
await
self
.
client
.
get
(
"/packageset/repository_statistics"
,
{
"branch"
:
branch
})
...
...
@@ -66,6 +88,26 @@ class BugInfo:
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
:
def
__init__
(
self
,
client
:
BaseAPI
):
self
.
client
=
client
...
...
@@ -99,8 +141,10 @@ class PackagesAPI:
def
__init__
(
self
):
self
.
_client
=
BaseAPI
()
self
.
api
=
APIInfo
(
self
.
_client
)
self
.
package
=
PackageInfo
(
self
.
_client
)
self
.
packageset
=
PackagesetInfo
(
self
.
_client
)
self
.
bug
=
BugInfo
(
self
.
_client
)
self
.
file
=
FileInfo
(
self
.
_client
)
self
.
site
=
SiteInfo
(
self
.
_client
)
async
def
init
(
self
):
...
...
src/api/models.py
View file @
c3d58864
...
...
@@ -85,3 +85,47 @@ class BugzillaInfoModel(BaseModel):
request_args
:
Dict
[
str
,
Any
]
length
:
int
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
src/handlers/search.py
0 → 100644
View file @
c3d58864
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)
"""
src/handlers/statistics.py
View file @
c3d58864
...
...
@@ -27,7 +27,7 @@ async def profile_handler(m: Message, user: User | None, branch: str | None = No
if
user
:
branch
=
user
.
default_branch
else
:
branch
=
(
await
api
.
packageset
.
active_packagesets
())
[
0
]
branch
=
active_branches
[
0
]
statistics_data
=
(
await
api
.
packageset
.
repository_statistics
(
branch
))
.
branches
[
0
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment