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
73d33c09
Verified
Commit
73d33c09
authored
Aug 08, 2025
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
altrepo: add appstream module
parent
78aa0c97
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
153 additions
and
12 deletions
+153
-12
.gitignore
.gitignore
+2
-0
poetry.lock
poetry.lock
+0
-0
pyproject.toml
pyproject.toml
+2
-1
__init__.py
src/altrepo/__init__.py
+7
-2
__init__.py
src/altrepo/appstream/__init__.py
+1
-0
methods.py
src/altrepo/appstream/methods.py
+92
-0
help.py
src/handlers/help.py
+4
-0
main.py
src/main.py
+23
-9
update_appstream_data.py
src/services/appstream/update_appstream_data.py
+22
-0
No files found.
.gitignore
View file @
73d33c09
...
...
@@ -2,5 +2,6 @@
.venv
*.db
/appstream/
__pycache__/
\ No newline at end of file
poetry.lock
View file @
73d33c09
This diff is collapsed.
Click to expand it.
pyproject.toml
View file @
73d33c09
...
...
@@ -13,7 +13,8 @@ dependencies = [
"pydantic (>=2.11.7,<3.0.0)"
,
"pydantic-settings (>=2.10.1,<3.0.0)"
,
"peewee (>=3.18.2,<4.0.0)"
,
"bs4 (>=0.0.2,<0.0.3)"
"bs4 (>=0.0.2,<0.0.3)"
,
"lxml (>=6.0.0,<7.0.0)"
]
[project.urls]
...
...
src/altrepo/__init__.py
View file @
73d33c09
import
aiohttp
from
.api
import
ALTRepoAPI
from
.appstream
import
ALTRepoAppStream
from
.parser
import
ALTRepoParser
class
ALTRepo
:
...
...
@@ -8,17 +9,21 @@ class ALTRepo:
def
__init__
(
self
):
self
.
_session
:
aiohttp
.
ClientSession
|
None
=
None
self
.
api
:
ALTRepoAPI
|
None
=
None
self
.
appstream
:
ALTRepoAppStream
|
None
=
None
self
.
parser
:
ALTRepoParser
|
None
=
None
async
def
init
(
self
):
async
def
init
(
self
,
appstream_dir
:
str
=
"appstream"
):
if
self
.
_session
is
None
:
self
.
_session
=
aiohttp
.
ClientSession
()
self
.
api
=
ALTRepoAPI
(
self
.
_session
)
self
.
appstream
=
ALTRepoAppStream
(
self
.
_session
,
appstream_dir
)
self
.
parser
=
ALTRepoParser
(
self
.
_session
)
async
def
close
(
self
):
await
self
.
_session
.
close
()
altrepo
=
ALTRepo
()
...
...
src/altrepo/appstream/__init__.py
0 → 100644
View file @
73d33c09
from
.methods
import
ALTRepoAppStream
src/altrepo/appstream/methods.py
0 → 100644
View file @
73d33c09
import
os
import
aiohttp
from
lxml
import
etree
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
):
self
.
session
=
session
async
def
_handle_response
(
self
,
resp
:
aiohttp
.
ClientResponse
):
match
resp
.
status
:
case
200
|
201
:
return
await
resp
.
text
(
encoding
=
"utf-8"
)
case
_
:
return
None
async
def
get
(
self
,
branch
:
str
)
->
str
|
None
:
url
=
self
.
BASE_URL
.
format
(
branch
)
async
with
self
.
session
.
get
(
url
)
as
resp
:
return
await
self
.
_handle_response
(
resp
)
class
DataInfo
:
def
__init__
(
self
,
client
:
AppStreamClient
,
appstream_dir
:
str
):
self
.
client
=
client
self
.
dir
=
appstream_dir
os
.
makedirs
(
self
.
dir
,
exist_ok
=
True
)
async
def
load_by_branch
(
self
,
branch
:
str
,
version
:
str
):
text
=
await
self
.
client
.
get
(
branch
)
if
not
text
:
return
old_file
=
self
.
get_file_path
(
branch
)
if
old_file
:
os
.
remove
(
old_file
)
filename
=
f
"{branch}-{version}.xml"
filepath
=
os
.
path
.
join
(
self
.
dir
,
filename
)
with
open
(
filepath
,
"w"
,
encoding
=
"utf-8"
)
as
f
:
f
.
write
(
text
)
def
get_file_path
(
self
,
branch
:
str
)
->
str
|
None
:
for
fname
in
os
.
listdir
(
self
.
dir
):
if
fname
.
startswith
(
f
"{branch}-"
)
and
fname
.
endswith
(
".xml"
):
return
os
.
path
.
join
(
self
.
dir
,
fname
)
return
None
def
get_current_version
(
self
,
branch
:
str
)
->
str
|
None
:
path
=
self
.
get_file_path
(
branch
)
if
path
:
fname
=
os
.
path
.
basename
(
path
)
return
fname
[
len
(
branch
)
+
1
:
-
4
]
return
None
def
has_file
(
self
,
branch
:
str
)
->
bool
:
return
self
.
get_file_path
(
branch
)
is
not
None
class
PackageInfo
:
def
__init__
(
self
,
client
:
AppStreamClient
,
data
:
DataInfo
):
self
.
client
=
client
self
.
_data
=
data
def
id_by_pkgname
(
self
,
pkgname
:
str
,
branch
:
str
)
->
str
|
None
:
path
=
self
.
_data
.
get_file_path
(
branch
)
if
not
path
:
return
None
context
=
etree
.
iterparse
(
path
,
events
=
(
"end"
,),
recover
=
True
)
for
_
,
elem
in
context
:
if
elem
.
tag
==
"component"
:
if
elem
.
findtext
(
"pkgname"
)
==
pkgname
:
return
elem
.
findtext
(
"id"
)
elem
.
clear
()
while
elem
.
getprevious
()
is
not
None
:
del
elem
.
getparent
()[
0
]
return
None
class
ALTRepoAppStream
:
def
__init__
(
self
,
session
:
aiohttp
.
ClientSession
,
appstream_dir
:
str
):
self
.
_client
=
AppStreamClient
(
session
)
self
.
data
=
DataInfo
(
self
.
_client
,
appstream_dir
)
self
.
package
=
PackageInfo
(
self
.
_client
,
self
.
data
)
src/handlers/help.py
View file @
73d33c09
...
...
@@ -32,6 +32,10 @@ async def info_handler(m: Message) -> None:
f
" Сопровождающих в базе: {DB.maintainer.count()}
\n
"
f
" Пакетов переведено: {DB.package.count()}
\n\n
"
f
"{_bold("
ALTRepo
Bot
AppStream
Data
:
")}
\n
"
f
" Sisyphus: {altrepo.appstream.data.get_current_version("
sisyphus
")}
\n
"
f
" P11: {altrepo.appstream.data.get_current_version("
p11
")}
\n\n
"
f
"{_bold("
Исходный
код
:
")}
\n
"
f
"{repos_formatted}
\n\n
"
...
...
src/main.py
View file @
73d33c09
...
...
@@ -11,12 +11,14 @@ from middlewares import UserMiddleware
from
services.test_api_version
import
test_api_version
from
services.update_maintainers
import
update_maintainers
from
services.appstream.update_appstream_data
import
update_appstream_data
bot
=
Telegrinder
(
tg_api
)
bot
.
dispatch
.
load_from_dir
(
"src/handlers"
)
bot
.
on
.
message
.
register_middleware
(
UserMiddleware
)
@bot.loop_wrapper.lifespan.on_startup
async
def
startup
():
db
.
create_tables
([
Maintainer
,
User
,
Package
])
...
...
@@ -24,31 +26,43 @@ async def startup():
await
altrepo
.
init
()
await
test_api_version
()
await
update_maintainers
()
await
bot
.
api
.
set_my_commands
(
commands
=
[
BotCommand
(
"watch"
,
"Отслеживание по пакетам"
),
BotCommand
(
"bugs"
,
"Отслеживание по ошибкам"
),
BotCommand
(
"ftbfs"
,
"Ошибки пересборки"
),
BotCommand
(
"statistics"
,
"Статистика репозитория"
),
BotCommand
(
"altrepo_info"
,
"Информация о боте"
),
BotCommand
(
"help"
,
"Справка"
)
])
await
update_appstream_data
()
await
bot
.
api
.
set_my_commands
(
commands
=
[
BotCommand
(
"watch"
,
"Отслеживание по пакетам"
),
BotCommand
(
"bugs"
,
"Отслеживание по ошибкам"
),
BotCommand
(
"ftbfs"
,
"Ошибки пересборки"
),
BotCommand
(
"statistics"
,
"Статистика репозитория"
),
BotCommand
(
"altrepo_info"
,
"Информация о боте"
),
BotCommand
(
"help"
,
"Справка"
),
]
)
@bot.loop_wrapper.lifespan.on_shutdown
async
def
shutdown
():
logger
.
info
(
"stopping ALTRepo"
)
await
altrepo
.
close
()
@bot.loop_wrapper.interval
(
days
=
1
)
async
def
api_test
():
await
test_api_version
()
@bot.loop_wrapper.interval
(
days
=
1
)
async
def
update_maintainers_db
():
await
update_maintainers
()
@bot.loop_wrapper.interval
(
days
=
1
)
async
def
update_appstream
():
await
update_appstream_data
()
@bot.on.error
()
async
def
error_handler
(
err
:
Error
[
TooManyRequests
],
m
:
Message
):
await
m
.
answer
(
f
"Слишком много запросов!"
)
bot
.
run_forever
(
skip_updates
=
True
)
src/services/appstream/update_appstream_data.py
0 → 100644
View file @
73d33c09
from
telegrinder.modules
import
logger
from
altrepo
import
altrepo
async
def
update_appstream_data
():
for
branch
in
[
"sisyphus"
,
"p11"
]:
package
=
(
await
altrepo
.
api
.
package
.
package_info
(
"appstream-data-desktop"
,
branch
=
branch
,
source
=
True
)
)
.
packages
[
0
]
current_version
=
altrepo
.
appstream
.
data
.
get_current_version
(
branch
)
package_version
=
f
"{package.version}-{package.release}"
if
(
not
altrepo
.
appstream
.
data
.
has_file
(
branch
)
or
package_version
!=
current_version
):
await
altrepo
.
appstream
.
data
.
load_by_branch
(
branch
,
package_version
)
logger
.
info
(
f
"Update AppStream data for {branch}"
)
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