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
030064b2
Verified
Commit
030064b2
authored
Jun 25, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
users: allow profile without maintainer
parent
950d64a6
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
241 additions
and
53 deletions
+241
-53
menu.py
src/data/keyboards/menu.py
+5
-3
profile.py
src/data/keyboards/profile.py
+24
-15
start.py
src/data/keyboards/start.py
+6
-0
func.py
src/database/func.py
+2
-2
models.py
src/database/models.py
+3
-2
admin.py
src/handlers/admin.py
+10
-3
ftbfs.py
src/handlers/ftbfs.py
+4
-1
help.py
src/handlers/help.py
+3
-2
profile.py
src/handlers/profile.py
+117
-18
start.py
src/handlers/start.py
+8
-2
tasks.py
src/handlers/tasks.py
+4
-2
main.py
src/main.py
+41
-0
scheduler.py
src/modules/scheduler.py
+4
-0
bugs.py
src/services/bugs.py
+4
-1
utils.py
src/services/utils.py
+6
-2
No files found.
src/data/keyboards/menu.py
View file @
030064b2
...
...
@@ -4,13 +4,15 @@ from database.func import DB
def
menu_kb
(
user_id
:
int
):
user
=
DB
.
user
.
get
(
user_id
)
user_rules
=
DB
.
user
.
get_roles
(
user_id
)
kb
=
Keyboard
()
kb
.
add
(
Button
(
"Профиль"
))
kb
.
row
()
kb
.
add
(
Button
(
"Отслеживание"
))
kb
.
add
(
Button
(
"Ошибки"
))
if
user
and
user
.
maintainer
:
kb
.
row
()
kb
.
add
(
Button
(
"Отслеживание"
))
kb
.
add
(
Button
(
"Ошибки"
))
kb
.
row
()
if
"news"
in
user_rules
:
kb
.
add
(
Button
(
"Новости"
))
...
...
src/data/keyboards/profile.py
View file @
030064b2
...
...
@@ -9,18 +9,22 @@ profile_kb = (
.
add
(
InlineButton
(
"Настройки"
,
callback_data
=
"profile/settings"
))
)
.
get_markup
()
profile_settings_kb
=
(
InlineKeyboard
()
.
add
(
InlineButton
(
"Рассылки и уведомления"
,
callback_data
=
"profile/mailing"
))
.
row
()
.
add
(
InlineButton
(
"Отслеживаемые пакеты"
,
callback_data
=
"profile/settings/packages"
))
.
row
()
.
add
(
InlineButton
(
"Сменить сопровождающего"
,
callback_data
=
"profile/settings/maintainer"
))
.
row
()
.
add
(
InlineButton
(
"Сменить репозиторий"
,
callback_data
=
"profile/settings/branch"
))
.
row
()
.
add
(
InlineButton
(
"Закрыть"
,
callback_data
=
"profile/close"
))
)
.
get_markup
()
def
profile_settings_kb
(
has_maintainer
:
bool
=
True
):
maintainer_label
=
"Сменить сопровождающего"
if
has_maintainer
else
"Выбрать сопровождающего"
kb
=
InlineKeyboard
()
kb
.
add
(
InlineButton
(
"Рассылки и уведомления"
,
callback_data
=
"profile/mailing"
))
kb
.
row
()
kb
.
add
(
InlineButton
(
"Отслеживаемые пакеты"
,
callback_data
=
"profile/settings/packages"
))
kb
.
row
()
kb
.
add
(
InlineButton
(
maintainer_label
,
callback_data
=
"profile/settings/maintainer"
))
kb
.
row
()
if
has_maintainer
:
kb
.
add
(
InlineButton
(
"Выйти"
,
callback_data
=
"profile/settings/logout"
))
kb
.
row
()
kb
.
add
(
InlineButton
(
"Сменить репозиторий"
,
callback_data
=
"profile/settings/branch"
))
kb
.
row
()
kb
.
add
(
InlineButton
(
"Закрыть"
,
callback_data
=
"profile/close"
))
return
kb
.
get_markup
()
def
profile_settings_branch_kb
():
...
...
@@ -44,14 +48,19 @@ INSTANT_TYPES = [
]
def
mailing_settings_kb
(
schedule
,
enabled
:
list
[
str
]):
def
mailing_settings_kb
(
schedule
,
enabled
:
list
[
str
]
,
has_maintainer
:
bool
=
True
):
kb
=
InlineKeyboard
()
kb
.
add
(
InlineButton
(
"Дни недели"
,
callback_data
=
"profile/mailing/days"
))
kb
.
add
(
InlineButton
(
"Время"
,
callback_data
=
"profile/mailing/set-time"
))
kb
.
row
()
for
type_id
,
label
in
SCHEDULED_TYPES
:
scheduled_types
=
SCHEDULED_TYPES
if
has_maintainer
else
[
item
for
item
in
SCHEDULED_TYPES
if
item
[
0
]
==
"pkg_watch"
]
instant_types
=
INSTANT_TYPES
if
has_maintainer
else
[]
for
type_id
,
label
in
scheduled_types
:
status
=
"вкл"
if
type_id
in
enabled
else
"выкл"
kb
.
add
(
InlineButton
(
f
"{label}: {status}"
,
...
...
@@ -59,7 +68,7 @@ def mailing_settings_kb(schedule, enabled: list[str]):
))
kb
.
row
()
for
type_id
,
label
in
INSTANT_TYPES
:
for
type_id
,
label
in
instant_types
:
status
=
"вкл"
if
type_id
in
enabled
else
"выкл"
kb
.
add
(
InlineButton
(
f
"{label}: {status}"
,
...
...
src/data/keyboards/start.py
View file @
030064b2
...
...
@@ -3,6 +3,12 @@ from telegrinder import Button, Keyboard
from
config
import
DEFAUIL_BRANCHES
def
maintainer_kb
():
kb
=
Keyboard
(
one_time_keyboard
=
True
)
kb
.
add
(
Button
(
"Пропустить"
))
return
kb
.
get_markup
()
def
default_branch_kb
():
kb
=
Keyboard
(
one_time_keyboard
=
True
)
for
branch
in
DEFAUIL_BRANCHES
:
...
...
src/database/func.py
View file @
030064b2
...
...
@@ -60,7 +60,7 @@ class UserMethod:
def
add
(
cls
,
user_id
:
int
,
maintainer
:
Maintainer
,
maintainer
:
Maintainer
|
None
,
default_branch
:
str
=
"sisyphus"
,
):
"""создание записи пользователя"""
...
...
@@ -132,7 +132,7 @@ class UserMethod:
return
False
@classmethod
def
change_maintainer
(
cls
,
user_id
:
int
,
maintainer
:
Maintainer
):
def
change_maintainer
(
cls
,
user_id
:
int
,
maintainer
:
Maintainer
|
None
):
user
=
cls
.
get
(
user_id
)
if
user
is
None
:
return
False
...
...
src/database/models.py
View file @
030064b2
...
...
@@ -36,9 +36,10 @@ class User(BaseModel):
"""модель пользователя"""
user_id
=
IntegerField
()
# id пользователя
maintainer
:
Maintainer
=
ForeignKeyField
(
# сопровождающий
maintainer
:
Maintainer
|
None
=
ForeignKeyField
(
# сопровождающий
Maintainer
,
to_field
=
"nickname"
to_field
=
"nickname"
,
null
=
True
,
)
default_branch
=
TextField
(
# Репозитоий по умолчанию
default
=
"sisyphus"
...
...
src/handlers/admin.py
View file @
030064b2
...
...
@@ -27,7 +27,8 @@ async def alrtrepo_users(m: Message):
users_data
=
DB
.
user
.
get_all
()
user_message
=
""
for
user
in
users_data
:
user_message
+=
f
"{user.user_id} | {user.maintainer.nickname} | {user.default_branch}
\n
"
maintainer
=
user
.
maintainer
.
nickname
if
user
.
maintainer
else
"-"
user_message
+=
f
"{user.user_id} | {maintainer} | {user.default_branch}
\n
"
await
m
.
answer
(
user_message
)
...
...
@@ -43,10 +44,11 @@ async def alrtrepo_users(m: Message, user_id: int):
user
=
(
await
tg_api
.
get_chat
(
chat_id
=
user_id
))
.
unwrap
()
username
=
user
.
username
.
unwrap_or_none
()
username
=
f
"(@{username})
\n
"
if
username
else
"
\n
"
maintainer
=
db_user
.
maintainer
.
nickname
if
db_user
.
maintainer
else
"-"
await
m
.
answer
(
f
"{user.first_name.unwrap_or("")} {user.last_name.unwrap_or("")} {username}"
f
" Сопровождающий: {
db_user.maintainer.nickname
}
\n
"
f
" Сопровождающий: {
maintainer
}
\n
"
f
" Репозиторий: {db_user.default_branch}
\n
"
f
" Роли: {"
,
".join(user_roles) or "
пользователь
"}
\n
"
)
...
...
@@ -70,7 +72,12 @@ async def alrtrepo_users(
if
not
branch
:
branch
=
"sisyphus"
if
DB
.
user
.
add
(
user_id
,
maintainer
,
branch
):
maintainer_obj
=
DB
.
maintainer
.
get
(
maintainer
)
if
not
maintainer_obj
:
await
m
.
answer
(
"Сопровождающий не найден"
)
return
if
DB
.
user
.
add
(
user_id
,
maintainer_obj
,
branch
):
await
m
.
answer
(
"Пользователь добавлен"
)
...
...
src/handlers/ftbfs.py
View file @
030064b2
...
...
@@ -24,9 +24,12 @@ async def ftbfs_handler(m: Message, user: User | None, _maintainer: str | None =
return
else
:
if
user
:
if
user
and
user
.
maintainer
:
maintainer
=
user
.
maintainer
.
nickname
else
:
await
m
.
answer
(
"Команда требует сопровождающего. Укажите ник в команде или выберите сопровождающего в профиле."
)
return
ftbfs_data
=
await
altrepo
.
parser
.
packages
.
ftbfs
()
...
...
src/handlers/help.py
View file @
030064b2
...
...
@@ -78,7 +78,9 @@ async def help_handler(m: Message) -> None:
await
m
.
answer
(
f
"{_bold("
Основные
:
")}
\n
"
" /profile — профиль сопровождающего
\n
"
" /profile — профиль
\n
"
" /login — выбрать сопровождающего
\n
"
" /logout — удалить сопровождающего
\n
"
" /help — помощь
\n
"
" /altrepo_info — информация о боте
\n\n
"
...
...
@@ -103,4 +105,3 @@ async def help_handler(m: Message) -> None:
" /news_range дата_от дата_до — новости за период
\n
"
" /pulse [дней] — пульс Сизифа (по умолчанию 7)
\n
"
)
src/handlers/profile.py
View file @
030064b2
...
...
@@ -25,10 +25,20 @@ DESCRIPTIONS = {
"task_events"
:
"Изменения статуса тасков текущего сопровождающего."
,
}
MAINTAINER_MAILINGS
=
{
"watch"
,
"bugs"
,
"task_events"
}
async
def
_drop_pending_input
(
user_id
:
int
)
->
None
:
try
:
await
wm
.
drop
(
MESSAGE_FROM_USER
,
user_id
)
except
LookupError
:
pass
def
_mailing_text_and_markup
(
user
):
schedule
=
DB
.
schedule
.
get
(
user
)
enabled
=
DB
.
mailing
.
get_enabled
(
user
)
has_maintainer
=
user
.
maintainer
is
not
None
text
=
_bold
(
"Рассылки:
\n\n
"
)
...
...
@@ -39,19 +49,28 @@ def _mailing_text_and_markup(user):
else
:
text
+=
"Расписание: не настроено
\n\n
"
for
type_id
,
label
in
profile_keyboards
.
SCHEDULED_TYPES
:
scheduled_types
=
profile_keyboards
.
SCHEDULED_TYPES
if
has_maintainer
else
[
item
for
item
in
profile_keyboards
.
SCHEDULED_TYPES
if
item
[
0
]
not
in
MAINTAINER_MAILINGS
]
instant_types
=
profile_keyboards
.
INSTANT_TYPES
if
has_maintainer
else
[]
for
type_id
,
label
in
scheduled_types
:
status
=
"вкл"
if
type_id
in
enabled
else
"выкл"
text
+=
_bold
(
f
"{label}: {status}
\n
"
)
text
+=
f
"{DESCRIPTIONS[type_id]}
\n\n
"
text
+=
_bold
(
"Уведомления:
\n\n
"
)
if
instant_types
:
text
+=
_bold
(
"Уведомления:
\n\n
"
)
for
type_id
,
label
in
profile_keyboards
.
INSTANT_TYPES
:
for
type_id
,
label
in
instant_types
:
status
=
"вкл"
if
type_id
in
enabled
else
"выкл"
text
+=
_bold
(
f
"{label}: {status}
\n
"
)
text
+=
f
"{DESCRIPTIONS[type_id]}
\n\n
"
markup
=
profile_keyboards
.
mailing_settings_kb
(
schedule
,
enabled
)
if
not
has_maintainer
:
text
+=
"Рассылки по сопровождающему появятся после выбора сопровождающего в профиле.
\n
"
markup
=
profile_keyboards
.
mailing_settings_kb
(
schedule
,
enabled
,
has_maintainer
)
return
text
,
markup
...
...
@@ -61,6 +80,17 @@ async def profile_handler(m: Message, user: User | None) -> None:
if
user
is
None
:
return
if
not
user
.
maintainer
:
roles
=
DB
.
user
.
get_roles
(
m
.
from_user
.
id
)
await
m
.
answer
(
f
"{_bold("
Профиль
:
\
n
\
n
")}"
"Сопровождающий: не выбран
\n
"
f
"Репозиторий: {user.default_branch}
\n\n
"
f
"Роли в боте: {"
,
".join(roles) or "
пользователь
"}"
,
reply_markup
=
profile_keyboards
.
profile_kb
)
return
nickname
=
user
.
maintainer
.
nickname
maintainer_data
,
watch
,
bugs_data
,
branches_data
,
ftbfs_data
=
await
asyncio
.
gather
(
...
...
@@ -104,9 +134,13 @@ async def profile_handler(m: Message, user: User | None) -> None:
@dp.callback_query
(
PayloadEqRule
(
"profile/settings"
))
async
def
settings_handler
(
cb
:
CallbackQuery
)
->
None
:
await
_drop_pending_input
(
cb
.
from_user
.
id
)
user
=
DB
.
user
.
get
(
cb
.
from_user
.
id
)
await
cb
.
edit_text
(
"Настройки"
,
reply_markup
=
profile_keyboards
.
profile_settings_kb
reply_markup
=
profile_keyboards
.
profile_settings_kb
(
user
is
not
None
and
user
.
maintainer
is
not
None
)
)
await
cb
.
answer
()
...
...
@@ -117,37 +151,93 @@ async def close_handler(cb: CallbackQuery) -> None:
await
cb
.
answer
()
@dp.callback_query
(
PayloadEqRule
(
"profile/settings/maintainer"
))
async
def
maintainer_handler
(
cb
:
CallbackQuery
)
->
None
:
async
def
_login
(
chat_id
:
int
,
user_id
:
int
,
ctx_api
,
edit_cb
:
CallbackQuery
|
None
=
None
)
->
None
:
cancel
=
cancel_kb
(
"profile/settings"
)
await
cb
.
edit_text
(
"Введите никнейм сопровождающего:"
,
reply_markup
=
cancel
)
if
edit_cb
:
await
edit_cb
.
edit_text
(
"Введите никнейм сопровождающего:"
,
reply_markup
=
cancel
)
else
:
await
ctx_api
.
send_message
(
chat_id
=
chat_id
,
text
=
"Введите никнейм сопровождающего:"
,
reply_markup
=
cancel
,
)
try
:
while
True
:
msg
,
_
=
await
wm
.
wait
(
MESSAGE_FROM_USER
,
cb
.
from_user
.
id
,
release
=
HasText
())
msg
,
_
=
await
wm
.
wait
(
MESSAGE_FROM_USER
,
user_
id
,
release
=
HasText
())
maintainer
=
msg
.
text
.
unwrap
()
.
lower
()
await
msg
.
delete
()
maintainer_obj
=
DB
.
maintainer
.
get
(
maintainer
)
if
maintainer_obj
:
DB
.
user
.
change_maintainer
(
cb
.
from_user
.
id
,
maintainer_obj
)
await
cb
.
edit_text
(
f
"Сопровождающий: {maintainer}"
,
reply_markup
=
profile_keyboards
.
profile_settings_kb
)
DB
.
user
.
change_maintainer
(
user_id
,
maintainer_obj
)
text
=
f
"Сопровождающий: {maintainer}"
markup
=
profile_keyboards
.
profile_settings_kb
(
True
)
if
edit_cb
:
await
edit_cb
.
edit_text
(
text
,
reply_markup
=
markup
)
else
:
await
ctx_api
.
send_message
(
chat_id
=
chat_id
,
text
=
text
,
reply_markup
=
markup
)
break
else
:
await
cb
.
edit_text
(
text
=
(
f
"Сопровождающий {maintainer} не найден.
\n
"
"Введите никнейм сопровождающего:"
,
reply_markup
=
cancel
,
"Введите никнейм сопровождающего:"
)
if
edit_cb
:
await
edit_cb
.
edit_text
(
text
,
reply_markup
=
cancel
)
else
:
await
ctx_api
.
send_message
(
chat_id
=
chat_id
,
text
=
text
,
reply_markup
=
cancel
)
except
(
asyncio
.
CancelledError
,
LookupError
):
return
@dp.callback_query
(
PayloadEqRule
(
"profile/settings/maintainer"
))
async
def
maintainer_handler
(
cb
:
CallbackQuery
)
->
None
:
await
_login
(
cb
.
chat_id
.
unwrap
(),
cb
.
from_user
.
id
,
cb
.
ctx_api
,
cb
)
await
cb
.
answer
()
@dp.callback_query
(
PayloadEqRule
(
"profile/settings/logout"
))
async
def
logout_callback_handler
(
cb
:
CallbackQuery
)
->
None
:
user
=
DB
.
user
.
get
(
cb
.
from_user
.
id
)
if
not
user
:
return
DB
.
user
.
change_maintainer
(
cb
.
from_user
.
id
,
None
)
for
mailing_type
in
MAINTAINER_MAILINGS
:
await
scheduler
.
disable_mailing
(
user
,
mailing_type
)
await
cb
.
edit_text
(
"Сопровождающий удалён."
,
reply_markup
=
profile_keyboards
.
profile_settings_kb
(
False
),
)
await
cb
.
answer
()
@dp.message
(
Command
(
"login"
),
IsPrivate
())
async
def
login_handler
(
m
:
Message
,
user
:
User
|
None
)
->
None
:
if
user
is
None
:
await
m
.
answer
(
"Сначала запустите /start."
)
return
await
_login
(
m
.
chat_id
,
m
.
from_user
.
id
,
m
.
ctx_api
)
@dp.message
(
Command
(
"logout"
),
IsPrivate
())
async
def
logout_handler
(
m
:
Message
,
user
:
User
|
None
)
->
None
:
if
user
is
None
:
await
m
.
answer
(
"Сначала запустите /start."
)
return
if
not
user
.
maintainer
:
await
m
.
answer
(
"Сопровождающий не выбран."
)
return
DB
.
user
.
change_maintainer
(
m
.
from_user
.
id
,
None
)
for
mailing_type
in
MAINTAINER_MAILINGS
:
await
scheduler
.
disable_mailing
(
user
,
mailing_type
)
await
m
.
answer
(
"Сопровождающий удалён."
)
@dp.callback_query
(
PayloadEqRule
(
"profile/settings/branch"
))
async
def
branch_handler
(
cb
:
CallbackQuery
)
->
None
:
await
cb
.
edit_text
(
...
...
@@ -159,9 +249,12 @@ async def branch_handler(cb: CallbackQuery) -> None:
@dp.callback_query
(
PayloadMarkupRule
(
"profile/settings/branch/<branch>"
))
async
def
branch_select_handler
(
cb
:
CallbackQuery
,
branch
:
str
)
->
None
:
DB
.
user
.
change_default_branch
(
cb
.
from_user
.
id
,
branch
)
user
=
DB
.
user
.
get
(
cb
.
from_user
.
id
)
await
cb
.
edit_text
(
f
"Репозиторий: {branch}"
,
reply_markup
=
profile_keyboards
.
profile_settings_kb
reply_markup
=
profile_keyboards
.
profile_settings_kb
(
user
is
not
None
and
user
.
maintainer
is
not
None
)
)
await
cb
.
answer
()
...
...
@@ -170,6 +263,7 @@ async def branch_select_handler(cb: CallbackQuery, branch: str) -> None:
@dp.callback_query
(
PayloadEqRule
(
"profile/mailing"
))
async
def
mailing_handler
(
cb
:
CallbackQuery
)
->
None
:
await
_drop_pending_input
(
cb
.
from_user
.
id
)
user
=
DB
.
user
.
get
(
cb
.
from_user
.
id
)
if
not
user
:
return
...
...
@@ -249,6 +343,10 @@ async def mailing_toggle_handler(cb: CallbackQuery, mailing_type: str) -> None:
if
not
user
:
return
if
mailing_type
in
MAINTAINER_MAILINGS
and
not
user
.
maintainer
:
await
cb
.
answer
(
"Сначала выберите сопровождающего."
,
show_alert
=
True
)
return
if
DB
.
mailing
.
is_enabled
(
user
,
mailing_type
):
await
scheduler
.
disable_mailing
(
user
,
mailing_type
)
else
:
...
...
@@ -263,6 +361,7 @@ async def mailing_toggle_handler(cb: CallbackQuery, mailing_type: str) -> None:
@dp.callback_query
(
PayloadEqRule
(
"profile/settings/packages"
))
async
def
user_packages_handler
(
cb
:
CallbackQuery
)
->
None
:
await
_drop_pending_input
(
cb
.
from_user
.
id
)
uid
=
cb
.
from_user
.
id
packages
=
DB
.
watch_list
.
get_list
(
uid
)
...
...
src/handlers/start.py
View file @
030064b2
...
...
@@ -20,11 +20,16 @@ async def start_handler(m: Message, user: User | None) -> None:
if
user
is
None
:
await
m
.
answer
(
"Введите никнейм сопровождающего:"
"Введите никнейм сопровождающего или пропустите этот шаг:"
,
reply_markup
=
start_keyboards
.
maintainer_kb
(),
)
maintainer
=
None
while
True
:
msg
,
_
=
await
wm
.
wait
(
MESSAGE_FROM_USER
,
m
.
from_user
.
id
,
release
=
HasText
())
_maintainer
=
msg
.
text
.
unwrap
()
.
lower
()
if
_maintainer
in
[
"пропустить"
,
"skip"
,
"/skip"
]:
await
m
.
answer
(
"Сопровождающий не выбран."
)
break
maintainer
=
DB
.
maintainer
.
get
(
_maintainer
)
if
maintainer
:
await
m
.
answer
(
...
...
@@ -34,7 +39,8 @@ async def start_handler(m: Message, user: User | None) -> None:
else
:
await
m
.
answer
(
f
"Сопровождающий {_maintainer} не найден.
\n
"
"Введите никнейм сопровождающего:"
"Введите никнейм сопровождающего или пропустите этот шаг:"
,
reply_markup
=
start_keyboards
.
maintainer_kb
(),
)
await
m
.
answer
(
"Выберите репозиторий по умолчанию."
,
...
...
src/handlers/tasks.py
View file @
030064b2
...
...
@@ -45,10 +45,12 @@ async def tasks_handler(m: Message, user: User | None, maintainer: str | None =
maintainer_obj
=
DB
.
maintainer
.
get
(
maintainer
.
lower
())
if
not
maintainer_obj
:
return
await
m
.
answer
(
"Сопровождающий не найден."
)
elif
user
:
elif
user
and
user
.
maintainer
:
maintainer_obj
=
user
.
maintainer
else
:
return
return
await
m
.
answer
(
"Команда требует сопровождающего. Укажите ник в команде или выберите сопровождающего в профиле."
)
try
:
tasks_data
=
await
altrepo
.
api
.
task
.
progress
.
find_tasks
(
...
...
src/main.py
View file @
030064b2
...
...
@@ -55,6 +55,44 @@ def _migrate_scheduled_tasks():
logger
.
info
(
"Migration complete, old table dropped"
)
def
_migrate_nullable_user_maintainer
():
if
not
db
.
table_exists
(
"users"
):
return
columns
=
db
.
execute_sql
(
"PRAGMA table_info(users)"
)
.
fetchall
()
maintainer_column
=
next
((
col
for
col
in
columns
if
col
[
1
]
==
"maintainer_id"
),
None
)
if
maintainer_column
is
None
or
not
maintainer_column
[
3
]:
return
logger
.
info
(
"Migrating users.maintainer_id to nullable"
)
db
.
execute_sql
(
"PRAGMA foreign_keys=off"
)
try
:
db
.
execute_sql
(
"""
CREATE TABLE users_new (
id INTEGER NOT NULL PRIMARY KEY,
user_id INTEGER NOT NULL,
maintainer_id TEXT,
default_branch TEXT NOT NULL,
roles TEXT NOT NULL,
FOREIGN KEY (maintainer_id) REFERENCES maintainers (nickname)
)
"""
)
db
.
execute_sql
(
"""
INSERT INTO users_new (id, user_id, maintainer_id, default_branch, roles)
SELECT id, user_id, maintainer_id, default_branch, roles FROM users
"""
)
db
.
execute_sql
(
"DROP TABLE users"
)
db
.
execute_sql
(
"ALTER TABLE users_new RENAME TO users"
)
db
.
execute_sql
(
"CREATE INDEX user_maintainer_id ON users (maintainer_id)"
)
finally
:
db
.
execute_sql
(
"PRAGMA foreign_keys=on"
)
logger
.
info
(
"Migration complete, users.maintainer_id is nullable"
)
@bot.loop_wrapper.lifespan.on_startup
async
def
startup
():
db
.
create_tables
(
...
...
@@ -69,6 +107,7 @@ async def startup():
]
)
_migrate_nullable_user_maintainer
()
_migrate_scheduled_tasks
()
logger
.
info
(
"initializing ALTRepo"
)
...
...
@@ -89,6 +128,8 @@ async def startup():
BotCommand
(
"pkg_watch"
,
"Обновления отслеживаемых пакетов"
),
BotCommand
(
"ftbfs"
,
"Ошибки пересборки"
),
BotCommand
(
"statistics"
,
"Статистика репозитория"
),
BotCommand
(
"login"
,
"Выбрать сопровождающего"
),
BotCommand
(
"logout"
,
"Удалить сопровождающего"
),
BotCommand
(
"altrepo_info"
,
"Информация о боте"
),
BotCommand
(
"help"
,
"Справка"
),
]
...
...
src/modules/scheduler.py
View file @
030064b2
...
...
@@ -17,6 +17,8 @@ MAILING_HANDLERS = {
),
}
MAINTAINER_MAILINGS
=
{
"watch"
,
"bugs"
}
class
CustomScheduler
:
def
__init__
(
self
):
...
...
@@ -116,6 +118,8 @@ class CustomScheduler:
if
not
user
:
return
for
mailing_type
in
DB
.
mailing
.
get_enabled
(
user
):
if
mailing_type
in
MAINTAINER_MAILINGS
and
not
user
.
maintainer
:
continue
handler
=
MAILING_HANDLERS
.
get
(
mailing_type
)
if
handler
:
await
handler
(
user
)
...
...
src/services/bugs.py
View file @
030064b2
...
...
@@ -15,7 +15,10 @@ async def bugs(
maintainer
:
str
|
None
=
None
)
->
None
:
chat_id
=
chat_id
or
user
.
user_id
if
chat_id
is
None
:
if
user
is
None
:
return
chat_id
=
user
.
user_id
resolved
=
await
resolve_maintainer
(
maintainer
,
user
,
chat_id
)
if
not
resolved
:
...
...
src/services/utils.py
View file @
030064b2
...
...
@@ -18,11 +18,15 @@ async def resolve_maintainer(
if
maintainer_arg
:
maintainer
=
DB
.
maintainer
.
get
(
maintainer_arg
.
lower
())
if
not
maintainer
:
await
tg_api
.
send_message
(
chat_id
,
"Сопровождающий не найден."
)
await
tg_api
.
send_message
(
chat_id
=
chat_id
,
text
=
"Сопровождающий не найден."
)
return
None
return
maintainer
elif
user
:
elif
user
and
user
.
maintainer
:
return
user
.
maintainer
await
tg_api
.
send_message
(
chat_id
=
chat_id
,
text
=
"Команда требует сопровождающего. Укажите ник в команде или выберите сопровождающего в профиле."
,
)
return
None
...
...
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