chore: import deployable mai-bot source tree

This commit is contained in:
2026-05-11 00:51:12 +00:00
parent 4813699b3e
commit 7a54015f94
1009 changed files with 312999 additions and 16 deletions

View File

@@ -0,0 +1,21 @@
FROM python:3.13-slim
WORKDIR /MaiMBot
ENV MAIBOT_LEGACY_0X_UPGRADE_CONFIRMED=1
ENV PATH="/MaiMBot/.venv/bin:${PATH}"
COPY pyproject.toml uv.lock ./
RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir uv
RUN uv sync --frozen --no-dev --no-install-project
COPY . .
RUN chmod +x deploy/server-maibot/docker-entrypoint.offline.sh
EXPOSE 8001
ENTRYPOINT ["./deploy/server-maibot/docker-entrypoint.offline.sh"]

View File

@@ -0,0 +1,31 @@
Server runtime directory: /root/maibot-offline
Release archive directory: /srv/maibot/releases
Repo-managed deployment files:
- deploy/server-maibot/Dockerfile.offline
- deploy/server-maibot/docker-entrypoint.offline.sh
- deploy/server-maibot/docker-compose.server.yml
- deploy/server-maibot/activate-release.sh
- deploy/server-maibot/bot.lecspace.com.nginx.conf
Persistent files that stay on the server and do not go into Git:
- /root/maibot-offline/docker-config/mmc/*
- /root/maibot-offline/docker-config/napcat/*
- /root/maibot-offline/data/*
- /root/maibot-offline/depends-data/*
- /root/maibot-offline/bot.lecspace.com.key
- /root/maibot-offline/bot.lecspace.com_bundle.pem
Gitea workflow:
- .gitea/workflows/release-offline.yml
Suggested Gitea secrets:
- MAIBOT_RELEASE_HOST
- MAIBOT_RELEASE_USER
- MAIBOT_RELEASE_PORT
- MAIBOT_RELEASE_ROOT
- MAIBOT_RUNTIME_ROOT
- MAIBOT_SSH_KEY
- MAIBOT_GIT_REPO_URL (optional)
- MAIBOT_GITEA_USER (optional)
- MAIBOT_GITEA_TOKEN (optional)

View File

@@ -0,0 +1,79 @@
#!/usr/bin/env bash
set -euo pipefail
release_dir="${1:?usage: activate-release.sh <release-dir>}"
runtime_root="${MAIBOT_RUNTIME_ROOT:-/root/maibot-offline}"
case "$runtime_root" in
/root/maibot-offline|/root/maibot-offline/*) ;;
*)
echo "runtime root must stay under /root/maibot-offline" >&2
exit 1
;;
esac
if [ ! -d "$release_dir" ]; then
echo "release dir not found: $release_dir" >&2
exit 1
fi
mkdir -p \
"$runtime_root" \
"$runtime_root/data/MaiMBot" \
"$runtime_root/data/MaiMBot/emoji" \
"$runtime_root/data/MaiMBot/plugins" \
"$runtime_root/data/MaiMBot/logs" \
"$runtime_root/data/qq" \
"$runtime_root/depends-data" \
"$runtime_root/docker-config/mmc" \
"$runtime_root/docker-config/napcat"
python3 - "$release_dir" "$runtime_root" <<'PY'
from pathlib import Path
import shutil
import sys
src = Path(sys.argv[1]).resolve()
dst = Path(sys.argv[2]).resolve()
skip_names = {
".git",
".gitea",
".github",
".venv",
"data",
"docker-config",
"depends-data",
"logs",
"plugins",
"acme",
"backups",
"bin",
"_staging",
}
skip_suffixes = {".pem", ".key", ".tar", ".tgz", ".zip"}
for item in src.iterdir():
if item.name in skip_names or item.suffix in skip_suffixes:
continue
target = dst / item.name
if target.exists():
if target.is_dir() and not target.is_symlink():
shutil.rmtree(target)
else:
target.unlink()
if item.is_dir():
shutil.copytree(
item,
target,
ignore=shutil.ignore_patterns("__pycache__", "*.pyc", "*.pyo"),
)
else:
shutil.copy2(item, target)
PY
cd "$runtime_root"
docker build -f deploy/server-maibot/Dockerfile.offline -t maibot-offline:latest .
docker compose -f deploy/server-maibot/docker-compose.server.yml up -d

View File

@@ -0,0 +1,37 @@
server {
listen 80;
server_name bot.lecspace.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name bot.lecspace.com;
resolver 127.0.0.11 ipv6=off valid=30s;
ssl_certificate /etc/nginx/certs/bot.lecspace.com_bundle.pem;
ssl_certificate_key /etc/nginx/certs/bot.lecspace.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
location / {
set $maibot_upstream http://maibot-core:8001;
proxy_pass $maibot_upstream;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
}
}

View File

@@ -0,0 +1,51 @@
services:
core:
container_name: maibot-core
image: ${MAIBOT_CORE_IMAGE:-maibot-offline:latest}
environment:
- TZ=Asia/Shanghai
- EULA_AGREE=1b662741904d7155d1ce1c00b3530d0d
- PRIVACY_AGREE=9943b855e72199d0f5016ea39052f1b6
- MAIBOT_LEGACY_0X_UPGRADE_CONFIRMED=1
- MAIBOT_STATISTICS_REPORT_PATH=/MaiMBot/data/maibot_statistics.html
ports:
- "18001:8001"
volumes:
- ./docker-config/mmc:/MaiMBot/config
- ./data/MaiMBot:/MaiMBot/data
- ./data/MaiMBot/emoji:/data/emoji
- ./data/MaiMBot/plugins:/MaiMBot/plugins
- ./data/MaiMBot/logs:/MaiMBot/logs
- ./depends-data:/MaiMBot/depends-data
restart: always
networks:
maibot_net: {}
smartflow-full_default:
aliases:
- maibot-core
napcat:
container_name: maibot-napcat
image: ${NAPCAT_IMAGE:-mlikiowa/napcat-docker:latest}
environment:
- NAPCAT_UID=1000
- NAPCAT_GID=1000
- TZ=Asia/Shanghai
volumes:
- ./docker-config/napcat:/app/napcat/config
- ./data/qq:/app/.config/QQ
- ./data/MaiMBot:/MaiMBot/data
restart: always
networks:
maibot_net:
aliases:
- napcat
smartflow-full_default:
aliases:
- napcat
networks:
maibot_net:
driver: bridge
smartflow-full_default:
external: true

View File

@@ -0,0 +1,40 @@
#!/bin/sh
set -eu
ADAPTER_TEMPLATE="/MaiMBot/plugin-templates/MaiBot-Napcat-Adapter"
ADAPTER_TARGET="/MaiMBot/plugins/MaiBot-Napcat-Adapter"
CONFIG_DIR="/MaiMBot/config"
BOT_CONFIG_PATH="$CONFIG_DIR/bot_config.toml"
MODEL_CONFIG_PATH="$CONFIG_DIR/model_config.toml"
mkdir -p /MaiMBot/plugins
mkdir -p "$CONFIG_DIR"
if [ ! -e "$ADAPTER_TARGET" ] && [ -d "$ADAPTER_TEMPLATE" ]; then
cp -a "$ADAPTER_TEMPLATE" "$ADAPTER_TARGET"
fi
if [ ! -f "$BOT_CONFIG_PATH" ] || [ ! -f "$MODEL_CONFIG_PATH" ]; then
/MaiMBot/.venv/bin/python -c "from src.config.config import config_manager; print('config initialized')"
fi
if [ -f "$BOT_CONFIG_PATH" ]; then
/MaiMBot/.venv/bin/python - "$BOT_CONFIG_PATH" <<'PY'
import re
import sys
from pathlib import Path
path = Path(sys.argv[1])
content = path.read_text(encoding="utf-8")
updated = re.sub(
r'(^host\s*=\s*)"(127\.0\.0\.1|localhost)"',
r'\1"0.0.0.0"',
content,
flags=re.MULTILINE,
)
if updated != content:
path.write_text(updated, encoding="utf-8")
PY
fi
exec /MaiMBot/.venv/bin/python bot.py "$@"