feat(avatar): add BOXIM chat takeover

This commit is contained in:
stefanfeng
2026-08-19 17:56:57 +08:00
parent cfcfe7146e
commit 25fb8fbee5
15 changed files with 1340 additions and 880 deletions
+16 -29
View File
@@ -6,7 +6,6 @@ import logging
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger
import redis as redis_lib
from database import init_db, SessionLocal
from models import Avatar, Authorization, Organization, TokenAccount, TokenPlan
@@ -24,7 +23,6 @@ from responses import ok
logger = logging.getLogger(__name__)
takeover_scheduler = None
takeover_db = None
app = FastAPI(title="会会数字分身 API", version="1.0.0")
@@ -113,7 +111,7 @@ def seed():
@app.on_event("startup")
def on_startup():
global takeover_scheduler, takeover_db
global takeover_scheduler
init_db()
seed()
@@ -123,47 +121,43 @@ def on_startup():
# --- Takeover scheduler ---
try:
# Initialize Redis (optional)
redis_client = None
redis_url = os.getenv("REDIS_URL", "")
if redis_url:
try:
redis_client = redis_lib.from_url(redis_url)
redis_client.ping()
except Exception as e:
logger.warning(f"Redis connection failed, delayed takeover will degrade to immediate: {e}")
# Initialize Box IM client
# BOXIM production endpoints are intentionally separate from the login API.
from services.boxim_client import BoxIMClient
boxim_config = {
"HUIHUI_IM_BASE_URL": os.getenv("HUIHUI_IM_BASE_URL", "http://192.168.1.200:60040"),
"HUIHUI_PLATFORM_BASE_URL": os.getenv(
"HUIHUI_PLATFORM_BASE_URL", "https://open.99hui.com/api"
),
"BOXIM_API_BASE_URL": os.getenv(
"BOXIM_API_BASE_URL", "https://im.99hui.com/api"
),
"HUIHUI_APP_ID": os.getenv("HUIHUI_APP_ID", ""),
"HUIHUI_ACCESS_ID": os.getenv("HUIHUI_ACCESS_ID", ""),
"HUIHUI_ACCESS_SECRET": os.getenv("HUIHUI_ACCESS_SECRET", ""),
"BOXIM_TIMEOUT_SECONDS": os.getenv("BOXIM_TIMEOUT_SECONDS", "20"),
}
boxim_client = BoxIMClient(boxim_config)
# Initialize takeover service
from services.takeover_service import TakeoverService
takeover_db = SessionLocal()
takeover_service = TakeoverService(takeover_db, boxim_client, redis_client)
takeover_service = TakeoverService(SessionLocal, boxim_client)
# AsyncIOScheduler awaits the service coroutine instead of dropping it.
poll_interval = max(0.5, float(os.getenv("BOXIM_POLL_INTERVAL_SECONDS", "1")))
takeover_scheduler = AsyncIOScheduler()
takeover_scheduler.add_job(
takeover_service.poll_and_process_messages,
trigger=IntervalTrigger(seconds=10),
trigger=IntervalTrigger(seconds=poll_interval),
id="takeover_message_poll",
max_instances=1,
coalesce=True,
)
takeover_scheduler.start()
logger.info("Takeover message polling scheduler started (interval=10s)")
logger.info("BOXIM takeover scheduler started (interval=%ss)", poll_interval)
except Exception as e:
stop_takeover_scheduler()
logger.warning(f"Failed to initialize takeover scheduler, app will continue without it: {e}")
def stop_takeover_scheduler():
global takeover_scheduler, takeover_db
global takeover_scheduler
if takeover_scheduler is not None:
try:
@@ -174,13 +168,6 @@ def stop_takeover_scheduler():
finally:
takeover_scheduler = None
if takeover_db is not None:
try:
takeover_db.close()
finally:
takeover_db = None
@app.on_event("shutdown")
def on_shutdown():
stop_takeover_scheduler()