- This is a Python 3.12
uvproject; trust.python-version,pyproject.toml, anduv.lockover the README Python range. - Run app commands from
app/so absolute imports likefrom config import ...,from core.switchs import ..., andfrom modules.X import ...resolve correctly. - Runtime entrypoint is
app/main.py; it requires a root.envwithOWNER_IDandWS_URL, whileTOKEN,FEISHU_BOT_URL, andFEISHU_BOT_SECRETare optional. - Main long-running command is
uv run python app/main.pyfrom repo root, oruv run python main.pyfromapp/.
- There is no repo-wide pytest/lint/typecheck config at present; do not invent a standard test suite.
- Use
uv run python -m compileall appas the safest broad syntax/import-adjacent check after Python edits. app/modules/FAQSystem/test_FAQSystem.pyis an interactive script, not an automated pytest test.
app/handle_events.pydynamically loads everyapp/modules/*/main.pydirectory that is not prefixed with_and whose__init__.pyhasMODULE_ENABLED=Trueor omits it.- A module is considered loadable only if
main.pyexposes asynchandle_events(websocket, msg). app/modules/Template/is the canonical module skeleton:__init__.pydefinesMODULE_NAME,MODULE_ENABLED,SWITCH_NAME,MODULE_DESCRIPTION,DATA_DIR, andCOMMANDS;main.pydispatches to handler classes by NapCat event type.- Keep using
core.switchsfor module switch imports; it is a compatibility facade over the newercore/switch/package and is what existing modules use.
app/bot.pyconnects to NapCat via WebSocket and schedulesEventHandler.handle_messagewithasyncio.create_task; each registered handler is also run as its own background task.- Module handlers must not assume ordering or synchronous completion across handlers because events are fanned out concurrently.
- Group modules typically handle the switch command before the menu command, then return early unless
is_group_switch_on(group_id, MODULE_NAME)is true. - Menu commands conventionally use
SWITCH_NAME + MENU_COMMANDandMenuManager.get_module_commands_text(MODULE_NAME).
- NapCat API calls such as
send_group_msg,send_private_msg, andget_msgdo not synchronously return usable response data; their responses arrive later as WebSocket messages. - Any feature depending on response data must send a unique
echomarker containing module, feature, and business request ID, for examplesend_group_msg-qfnukjs_empty_classroom_pending=<id>. - Parse that marker only in the module's
ResponseHandler, read data such asdata.message_idthere, and store request context in module state or persistence. - Design these flows for response-before-work-completes, work-before-response, missing response, and failed response cases.
- Runtime data and logs are intentionally ignored by git:
data/,logs/,.env,.venv, and caches should not be committed. - Some modules load their own
.envfrom the module directory, for exampleapp/modules/qfnukjs/.envandapp/modules/SentimentAnalysis/.env; check the module README or.env.examplebefore changing config behavior. - Module
DATA_DIRvalues usually point under repo-rootdata/<MODULE_NAME>and may be created at import time.