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
6d1ebf42
Verified
Commit
6d1ebf42
authored
Jul 21, 2025
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
base: add roles system
parent
3f2f4a62
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
161 additions
and
29 deletions
+161
-29
__init__.py
src/data/keyboards/__init__.py
+1
-0
admin.py
src/data/keyboards/admin.py
+6
-0
menu.py
src/data/keyboards/menu.py
+18
-9
func.py
src/database/func.py
+37
-0
models.py
src/database/models.py
+1
-0
admin.py
src/handlers/admin.py
+67
-7
profile.py
src/handlers/profile.py
+6
-3
start.py
src/handlers/start.py
+6
-2
bot_admin.py
src/rules/bot_admin.py
+5
-1
menu.py
src/services/menu.py
+14
-7
No files found.
src/data/keyboards/__init__.py
View file @
6d1ebf42
from
.
import
admin
as
admin_keyboards
from
.
import
start
as
start_keyboards
from
.
import
start
as
start_keyboards
from
.
import
menu
as
menu_keyboards
from
.
import
menu
as
menu_keyboards
from
.
import
profile
as
profile_keyboards
from
.
import
profile
as
profile_keyboards
...
...
src/data/keyboards/admin.py
0 → 100644
View file @
6d1ebf42
from
telegrinder
import
InlineKeyboard
,
InlineButton
set_rule_kb
=
(
InlineKeyboard
()
.
add
(
InlineButton
(
"Продолжить"
,
callback_data
=
"command/menu"
))
)
.
get_markup
()
src/data/keyboards/menu.py
View file @
6d1ebf42
from
telegrinder
import
Button
,
Keyboard
from
telegrinder
import
Button
,
Keyboard
menu_kb
=
(
from
database.func
import
DB
Keyboard
()
.
add
(
Button
(
"Профиль"
))
.
row
()
def
menu_kb
(
user_id
:
int
):
.
add
(
Button
(
"Отслеживание"
))
user_rules
=
DB
.
user
.
get_roles
(
user_id
)
.
add
(
Button
(
"Ошибки"
))
.
row
()
kb
=
Keyboard
()
.
add
(
Button
(
"Статистика"
))
kb
.
add
(
Button
(
"Профиль"
))
)
.
get_markup
()
kb
.
row
()
kb
.
add
(
Button
(
"Отслеживание"
))
kb
.
add
(
Button
(
"Ошибки"
))
kb
.
row
()
if
"news"
in
user_rules
:
kb
.
add
(
Button
(
"Новости"
))
kb
.
row
()
kb
.
add
(
Button
(
"Статистика"
))
return
kb
.
get_markup
()
src/database/func.py
View file @
6d1ebf42
import
json
from
.models
import
User
from
.models
import
User
...
@@ -17,6 +18,20 @@ class UserMethod:
...
@@ -17,6 +18,20 @@ class UserMethod:
user
.
save
()
user
.
save
()
return
True
return
True
return
False
return
False
@classmethod
def
add_role
(
cls
,
user_id
:
int
,
role
:
str
):
"""добавление ролей пользователя"""
user
=
cls
.
get
(
user_id
)
roles
=
cls
.
get_roles
(
user_id
)
if
user
is
None
:
return
False
if
role
not
in
roles
:
roles
.
append
(
role
)
user
.
roles
=
json
.
dumps
(
roles
)
user
.
save
()
return
True
return
False
@classmethod
@classmethod
def
get
(
cls
,
user_id
:
int
)
->
User
|
None
:
def
get
(
cls
,
user_id
:
int
)
->
User
|
None
:
...
@@ -28,6 +43,14 @@ class UserMethod:
...
@@ -28,6 +43,14 @@ class UserMethod:
def
get_all
(
cls
):
def
get_all
(
cls
):
"""Получение записей всех пользователей"""
"""Получение записей всех пользователей"""
return
[
user
for
user
in
User
.
select
()]
return
[
user
for
user
in
User
.
select
()]
@classmethod
def
get_roles
(
cls
,
user_id
:
int
):
"""получение ролей пользователя"""
user
=
cls
.
get
(
user_id
)
if
user
is
None
:
return
[]
return
json
.
loads
(
user
.
roles
)
@classmethod
@classmethod
def
delete
(
cls
,
user_id
:
int
):
def
delete
(
cls
,
user_id
:
int
):
...
@@ -37,6 +60,20 @@ class UserMethod:
...
@@ -37,6 +60,20 @@ class UserMethod:
return
False
return
False
user
.
delete_instance
()
user
.
delete_instance
()
return
True
return
True
@classmethod
def
remove_role
(
cls
,
user_id
:
int
,
role
:
str
):
"""удаление ролей пользователя"""
user
=
cls
.
get
(
user_id
)
roles
=
cls
.
get_roles
(
user_id
)
if
user
is
None
:
return
False
if
role
in
roles
:
roles
.
remove
(
role
)
user
.
roles
=
json
.
dumps
(
roles
)
user
.
save
()
return
True
return
False
@classmethod
@classmethod
def
change_maintainer
(
cls
,
user_id
:
int
,
maintainer
:
str
):
def
change_maintainer
(
cls
,
user_id
:
int
,
maintainer
:
str
):
...
...
src/database/models.py
View file @
6d1ebf42
...
@@ -26,6 +26,7 @@ class User(BaseModel):
...
@@ -26,6 +26,7 @@ class User(BaseModel):
default_branch
=
TextField
(
# Репозитоий по умолчанию
default_branch
=
TextField
(
# Репозитоий по умолчанию
default
=
"sisyphus"
default
=
"sisyphus"
)
)
roles
=
TextField
(
default
=
"[]"
)
class
Meta
:
class
Meta
:
table_name
=
"users"
table_name
=
"users"
src/handlers/admin.py
View file @
6d1ebf42
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
data.keyboards
import
admin_keyboards
from
database.func
import
DB
from
database.func
import
DB
from
rules
import
BotAdmin
from
rules
import
BotAdmin
from
config
import
tg_api
from
config
import
tg_api
dp
=
Dispatch
()
dp
=
Dispatch
()
dp
.
message
.
auto_rules
=
BotAdmin
()
dp
.
message
.
auto_rules
=
BotAdmin
()
@dp.message
(
Command
(
"altrepo_users"
))
@dp.message
(
Command
(
"altrepo_users"
))
async
def
alrtrepo_users
(
m
:
Message
):
async
def
alrtrepo_users
(
m
:
Message
):
users_data
=
DB
.
user
.
get_all
()
users_data
=
DB
.
user
.
get_all
()
user_message
=
""
user_message
=
""
for
user
in
users_data
:
for
user
in
users_data
:
user_message
+=
f
"{user.user_id} | {user.maintainer} | {user.default_branch}
\n
"
user_message
+=
f
"{user.user_id} | {user.maintainer} | {user.default_branch}
\n
"
await
m
.
answer
(
user_message
)
await
m
.
answer
(
user_message
)
@dp.message
(
Command
(
"altrepo_user"
,
Argument
(
"user_id"
)))
@dp.message
(
Command
(
"altrepo_user"
,
Argument
(
"user_id"
)))
async
def
alrtrepo_users
(
m
:
Message
,
user_id
:
int
):
async
def
alrtrepo_users
(
m
:
Message
,
user_id
:
int
):
if
not
user_id
:
if
not
user_id
:
return
return
db_user
=
DB
.
user
.
get
(
user_id
)
db_user
=
DB
.
user
.
get
(
user_id
)
user_roles
=
DB
.
user
.
get_roles
(
user_id
)
user
=
(
await
tg_api
.
get_chat
(
chat_id
=
user_id
))
.
unwrap
()
user
=
(
await
tg_api
.
get_chat
(
chat_id
=
user_id
))
.
unwrap
()
username
=
user
.
username
.
unwrap_or_none
()
username
=
user
.
username
.
unwrap_or_none
()
username
=
f
"(@{username})
\n
"
if
username
else
"
\n
"
username
=
f
"(@{username})
\n
"
if
username
else
"
\n
"
await
m
.
answer
(
await
m
.
answer
(
f
"{user.first_name.unwrap
()} {user.last_name.unwrap(
)} {username}"
f
"{user.first_name.unwrap
_or("")} {user.last_name.unwrap_or(""
)} {username}"
f
" Сопровождающий: {db_user.maintainer}
\n
"
f
" Сопровождающий: {db_user.maintainer}
\n
"
f
" Репозиторий: {db_user.default_branch}
\n
"
f
" Репозиторий: {db_user.default_branch}
\n
"
f
" Роли: {"
,
".join(user_roles) or "
пользователь
"}
\n
"
)
@dp.message
(
Command
(
"altrepo_add_user"
,
Argument
(
"user_id"
),
Argument
(
"maintainer"
),
Argument
(
"branch"
,
optional
=
True
),
)
)
)
async
def
alrtrepo_users
(
m
:
Message
,
user_id
:
int
,
maintainer
:
str
,
branch
:
str
|
None
=
None
):
if
not
user_id
or
not
maintainer
:
return
if
not
branch
:
branch
=
"sisyphus"
if
DB
.
user
.
add
(
user_id
,
maintainer
,
branch
):
await
m
.
answer
(
"Пользователь добавлен"
)
@dp.message
(
Command
(
"altrepo_add_role"
,
Argument
(
"user_id"
),
Argument
(
"role"
)))
async
def
alrtrepo_users
(
m
:
Message
,
user_id
:
int
,
role
:
str
):
if
not
user_id
or
not
role
:
return
if
DB
.
user
.
add_role
(
user_id
,
role
):
await
m
.
answer
(
"Роль добавлена"
)
await
tg_api
.
send_message
(
chat_id
=
user_id
,
text
=
f
"Вам была выдана роль {role}"
,
reply_markup
=
admin_keyboards
.
set_rule_kb
,
)
@dp.message
(
Command
(
"altrepo_remove_role"
,
Argument
(
"user_id"
),
Argument
(
"role"
)))
async
def
alrtrepo_users
(
m
:
Message
,
user_id
:
int
,
role
:
str
):
if
not
user_id
or
not
role
:
return
print
(
1
)
if
DB
.
user
.
remove_role
(
user_id
,
role
):
print
(
2
)
await
m
.
answer
(
"Роль удалена"
)
await
tg_api
.
send_message
(
chat_id
=
user_id
,
text
=
f
"C вас была снята роль {role}"
,
reply_markup
=
admin_keyboards
.
set_rule_kb
,
)
src/handlers/profile.py
View file @
6d1ebf42
...
@@ -22,6 +22,8 @@ async def profile_handler(m: Message, user: User | None) -> None:
...
@@ -22,6 +22,8 @@ async def profile_handler(m: Message, user: User | None) -> None:
maintainer_data
=
await
altrepo
.
api
.
site
.
maintainer_info
(
user
.
default_branch
,
user
.
maintainer
)
maintainer_data
=
await
altrepo
.
api
.
site
.
maintainer_info
(
user
.
default_branch
,
user
.
maintainer
)
maintainer
=
maintainer_data
.
information
maintainer
=
maintainer_data
.
information
roles
=
DB
.
user
.
get_roles
(
m
.
from_user
.
id
)
bugs_data
=
await
altrepo
.
api
.
bug
.
bugzilla_by_maintainer
(
user
.
maintainer
)
bugs_data
=
await
altrepo
.
api
.
bug
.
bugzilla_by_maintainer
(
user
.
maintainer
)
unresolved_bugs
=
[
bug
for
bug
in
bugs_data
.
bugs
if
bug
.
status
not
in
[
"RESOLVED"
,
"CLOSED"
]]
unresolved_bugs
=
[
bug
for
bug
in
bugs_data
.
bugs
if
bug
.
status
not
in
[
"RESOLVED"
,
"CLOSED"
]]
...
@@ -31,7 +33,8 @@ async def profile_handler(m: Message, user: User | None) -> None:
...
@@ -31,7 +33,8 @@ async def profile_handler(m: Message, user: User | None) -> None:
f
"Исходные пакеты: {maintainer.count_source_pkg}
\n
"
f
"Исходные пакеты: {maintainer.count_source_pkg}
\n
"
"
\n
"
"
\n
"
f
"Всего багов: {bugs_data.length}
\n
"
f
"Всего багов: {bugs_data.length}
\n
"
f
"Открытых багов: {len(unresolved_bugs)}
\n
"
,
f
"Открытых багов: {len(unresolved_bugs)}
\n\n
"
f
"Роли в боте: {"
,
".join(roles) or "
пользователь
"}"
,
reply_markup
=
profile_keyboards
.
profile_kb
reply_markup
=
profile_keyboards
.
profile_kb
)
)
...
@@ -99,8 +102,8 @@ async def callback_confirm_handler(cb: CallbackQuery, branch: str) -> None:
...
@@ -99,8 +102,8 @@ async def callback_confirm_handler(cb: CallbackQuery, branch: str) -> None:
@dp.callback_query
(
PayloadEqRule
(
"command/menu"
))
@dp.callback_query
(
PayloadEqRule
(
"command/menu"
))
async
def
menu_handler
(
cb
:
CallbackQuery
):
async
def
menu_handler
(
cb
:
CallbackQuery
):
send_menu
(
cb
)
await
send_menu
(
cb
=
cb
)
@dp.message
(
Command
([
"menu"
,
"меню"
])
|
Text
([
"меню"
,
"menu"
]),
IsPrivate
())
@dp.message
(
Command
([
"menu"
,
"меню"
])
|
Text
([
"меню"
,
"menu"
]),
IsPrivate
())
async
def
menu_handler
(
m
:
Message
):
async
def
menu_handler
(
m
:
Message
):
await
send_menu
(
m
)
await
send_menu
(
m
=
m
)
src/handlers/start.py
View file @
6d1ebf42
...
@@ -9,7 +9,7 @@ from altrepo import altrepo
...
@@ -9,7 +9,7 @@ from altrepo import altrepo
from
services.menu
import
send_menu
from
services.menu
import
send_menu
from
config
import
DEFAUIL_BRANCHES
from
config
import
config
,
DEFAUIL_BRANCHES
dp
=
Dispatch
()
dp
=
Dispatch
()
wm
=
WaiterMachine
(
dp
)
wm
=
WaiterMachine
(
dp
)
...
@@ -66,4 +66,8 @@ async def start_handler(m: Message, user: User | None) -> None:
...
@@ -66,4 +66,8 @@ async def start_handler(m: Message, user: User | None) -> None:
maintainer
,
maintainer
,
branch
branch
)
)
await
send_menu
(
m
)
if
m
.
from_user
.
id
in
config
.
admins
:
DB
.
user
.
add_role
(
m
.
from_user
.
id
,
"admin"
)
await
send_menu
(
m
=
m
)
src/rules/bot_admin.py
View file @
6d1ebf42
from
telegrinder
import
Message
from
telegrinder
import
Message
from
telegrinder.bot.rules.abc
import
ABCRule
from
telegrinder.bot.rules.abc
import
ABCRule
from
database.func
import
DB
from
config
import
config
from
config
import
config
class
BotAdmin
(
ABCRule
):
class
BotAdmin
(
ABCRule
):
async
def
check
(
self
,
m
:
Message
)
->
bool
:
async
def
check
(
self
,
m
:
Message
)
->
bool
:
return
m
.
from_user
.
id
in
config
.
admins
user_rules
=
DB
.
user
.
get_roles
(
m
.
from_user
.
id
)
return
m
.
from_user
.
id
in
config
.
admins
or
"admin"
in
user_rules
src/services/menu.py
View file @
6d1ebf42
from
telegrinder
import
Message
from
telegrinder
import
Message
,
CallbackQuery
from
data.keyboards
import
menu_keyboards
from
data.keyboards
import
menu_keyboards
async
def
send_menu
(
m
:
Message
)
->
None
:
await
m
.
answer
(
async
def
send_menu
(
m
:
Message
|
None
=
None
,
cb
:
CallbackQuery
|
None
=
None
)
->
None
:
"menu:"
,
if
m
:
reply_markup
=
menu_keyboards
.
menu_kb
await
m
.
answer
(
)
"menu:"
,
\ No newline at end of file
reply_markup
=
menu_keyboards
.
menu_kb
(
m
.
from_user
.
id
)
)
elif
cb
:
await
cb
.
ctx_api
.
send_message
(
chat_id
=
cb
.
chat_id
.
unwrap
(),
text
=
"menu:"
,
reply_markup
=
menu_keyboards
.
menu_kb
(
cb
.
from_user
.
id
)
)
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