build: migrate dependency management to uv
This commit is contained in:
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.12
|
||||
@@ -5,8 +5,8 @@ Repository guidance for automated coding tools and contributors.
|
||||
## Running the bot
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
python main.py
|
||||
uv sync
|
||||
uv run python main.py
|
||||
```
|
||||
|
||||
Logs go to `bot.log` by default (rotating, 10 MB, 3 backups). Override with `LOG_FILE=<path>`.
|
||||
@@ -14,7 +14,7 @@ Logs go to `bot.log` by default (rotating, 10 MB, 3 backups). Override with `LOG
|
||||
Run the test suite with:
|
||||
|
||||
```bash
|
||||
python -m unittest discover -s tests -v
|
||||
uv run python -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
## Configuration
|
||||
@@ -36,6 +36,8 @@ AI prompt templates are always loaded from `prompts/MASTER.txt` and `prompts/USE
|
||||
### Boot path
|
||||
`main.py` → `load_app_config()` → `AccountManager` → one Pyrogram (`kurigram`) `Client` per account → `register_common_handlers()` → `pyrogram.idle()`.
|
||||
|
||||
On supported platforms, `main.py` runs the application with `uvloop`; Windows automatically falls back to the standard `asyncio` event loop.
|
||||
|
||||
### Command system (`app/commands/`)
|
||||
|
||||
- **Dispatcher** (`dispatcher.py`): parses `.command` (owner prefix) or `..command` (shared/guest prefix) from message text, resolves to a `CommandDefinition`, runs pre-checks, calls handler.
|
||||
@@ -85,6 +87,7 @@ Shared commands use `..mycommand` for guests and `.mycommand` for the owner. Own
|
||||
## Change guidelines
|
||||
|
||||
- Preserve unrelated local and untracked changes.
|
||||
- Manage dependencies through `pyproject.toml` and `uv.lock`; use `uv sync` instead of `pip install`.
|
||||
- Register commands through `command_registry`; do not add separate Pyrogram handlers for individual commands.
|
||||
- Keep shared commands behind `shared_access_check()` and persist ACL changes through `RuntimeAclStore`.
|
||||
- Add or update focused `unittest` coverage for behavioral changes.
|
||||
|
||||
10
main.py
10
main.py
@@ -10,6 +10,11 @@ from app.config import load_app_config
|
||||
from app.manager import AccountManager
|
||||
from app.pyrogram_compat import install_kurigram_compat
|
||||
|
||||
try:
|
||||
import uvloop
|
||||
except ImportError: # uvloop does not support Windows.
|
||||
uvloop = None
|
||||
|
||||
LOG_FORMAT = "%(asctime)s | %(levelname)s | %(name)s | %(message)s"
|
||||
|
||||
|
||||
@@ -46,4 +51,7 @@ async def main() -> None:
|
||||
|
||||
if __name__ == "__main__":
|
||||
configure_logging(_ROOT)
|
||||
asyncio.run(main())
|
||||
if uvloop is None:
|
||||
asyncio.run(main())
|
||||
else:
|
||||
uvloop.run(main())
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
/*
|
||||
Template variables (both {variable} and {{variable}} syntax are supported):
|
||||
|
||||
caller_user.id
|
||||
caller_user.name
|
||||
caller_user.username
|
||||
|
||||
owner.id
|
||||
owner.name
|
||||
owner.username
|
||||
|
||||
is_owner
|
||||
text
|
||||
|
||||
chat.id
|
||||
chat.title
|
||||
chat.type
|
||||
chat.username
|
||||
|
||||
message.id
|
||||
message.text
|
||||
message.date
|
||||
message.user.id
|
||||
message.user.name
|
||||
message.user.username
|
||||
message.is_reply
|
||||
|
||||
reply.id
|
||||
reply.text
|
||||
reply.user.id
|
||||
reply.user.name
|
||||
reply.user.username
|
||||
|
||||
account.name
|
||||
account.session
|
||||
|
||||
provider
|
||||
thinking
|
||||
context_messages
|
||||
|
||||
Missing Telegram values are rendered as an empty string.
|
||||
*/
|
||||
|
||||
You are a helpful assistant embedded in a Telegram client. Answer in the user's language.
|
||||
|
||||
The caller is {{caller_user.name}} (id={{caller_user.id}}, username={{caller_user.username}}).
|
||||
|
||||
@@ -1,2 +1,45 @@
|
||||
/*
|
||||
Template variables (both {variable} and {{variable}} syntax are supported):
|
||||
|
||||
caller_user.id
|
||||
caller_user.name
|
||||
caller_user.username
|
||||
|
||||
owner.id
|
||||
owner.name
|
||||
owner.username
|
||||
|
||||
is_owner
|
||||
text
|
||||
|
||||
chat.id
|
||||
chat.title
|
||||
chat.type
|
||||
chat.username
|
||||
|
||||
message.id
|
||||
message.text
|
||||
message.date
|
||||
message.user.id
|
||||
message.user.name
|
||||
message.user.username
|
||||
message.is_reply
|
||||
|
||||
reply.id
|
||||
reply.text
|
||||
reply.user.id
|
||||
reply.user.name
|
||||
reply.user.username
|
||||
|
||||
account.name
|
||||
account.session
|
||||
|
||||
provider
|
||||
thinking
|
||||
context_messages
|
||||
|
||||
Missing Telegram values are rendered as an empty string.
|
||||
*/
|
||||
|
||||
[Telegram message from {{message.user.name}} at {{message.date}}; reply={{message.is_reply}}]
|
||||
{{text}}
|
||||
|
||||
@@ -2,4 +2,24 @@
|
||||
name = "multi-bot-tg"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = []
|
||||
dependencies = [
|
||||
"aiohttp",
|
||||
"kurigram==2.2.24",
|
||||
"micro-agents==0.1.5",
|
||||
"micro-agents-tools==0.1.5",
|
||||
"python-dotenv",
|
||||
"tgcrypto",
|
||||
"uvloop; sys_platform != 'win32'",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
package = false
|
||||
|
||||
[[tool.uv.index]]
|
||||
name = "azimkin"
|
||||
url = "https://git.azimkin.dev/api/packages/Azimkin/pypi/simple/"
|
||||
explicit = true
|
||||
|
||||
[tool.uv.sources]
|
||||
micro-agents = { index = "azimkin" }
|
||||
micro-agents-tools = { index = "azimkin" }
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
--index-url https://git.azimkin.dev/api/packages/Azimkin/pypi/simple/
|
||||
--extra-index-url https://pypi.org/simple
|
||||
|
||||
kurigram==2.2.24
|
||||
tgcrypto
|
||||
python-dotenv
|
||||
aiohttp
|
||||
micro-agents==0.1.5
|
||||
micro-agents-tools==0.1.5
|
||||
Reference in New Issue
Block a user