mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-11 06:46:59 +08:00
fix(telegram): remove 'default' user fallback — resolve user dynamically
- botUserID no longer captured once at startup (was 'default' if no user yet) - resolveBotUser() reads first registered user from DB on demand: * called on every /start (handles: registered after bot launch) * called before every AI message (handles mid-session registration) - If no user registered: clear English error 'No account found. Please register on the web UI first' - start.sh: fix set_env_var appending without newline (token was concatenated to prev line)
This commit is contained in:
4
start.sh
4
start.sh
@@ -115,6 +115,10 @@ set_env_var() {
|
|||||||
sed -i "s|^${var_name}=.*|${var_name}=${var_value}|" .env
|
sed -i "s|^${var_name}=.*|${var_name}=${var_value}|" .env
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
# Ensure .env ends with a newline before appending
|
||||||
|
if [ -s ".env" ] && [ "$(tail -c1 .env | wc -l)" -eq 0 ]; then
|
||||||
|
echo "" >> .env
|
||||||
|
fi
|
||||||
echo "${var_name}=${var_value}" >> .env
|
echo "${var_name}=${var_value}" >> .env
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,27 +79,50 @@ func runBot(token string, cfg *config.Config, st *store.Store) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the real user ID: use the first registered user so that bot-made
|
// botUserID/botToken/agents are resolved lazily on the first message.
|
||||||
// changes (model/exchange configs) are visible in the frontend under that user.
|
// They refresh automatically when the user registers on the web UI.
|
||||||
// Falls back to "default" if no users exist yet (fresh install).
|
var (
|
||||||
botUserID := "default"
|
botUserID string
|
||||||
if ids, err := st.User().GetAllIDs(); err == nil && len(ids) > 0 {
|
botToken string
|
||||||
botUserID = ids[0]
|
agents *agent.Manager
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a bot JWT for authenticated API calls. Re-generated on each bot start.
|
|
||||||
botToken, err := agent.GenerateBotToken(botUserID)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Failed to generate bot JWT: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wire the AI agent manager. API docs are auto-generated from registered routes.
|
|
||||||
agents := agent.NewManager(cfg.APIServerPort, botToken, botUserID,
|
|
||||||
func() mcp.AIClient { return newLLMClient(st, botUserID) },
|
|
||||||
api.GetAPIDocs(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// resolveBotUser reads the first registered user from DB.
|
||||||
|
// Returns true and refreshes botUserID/botToken/agents when the user changes.
|
||||||
|
// Returns false if no user is registered yet (no "default" fallback).
|
||||||
|
resolveBotUser := func() bool {
|
||||||
|
ids, err := st.User().GetAllIDs()
|
||||||
|
if err != nil || len(ids) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
newID := ids[0]
|
||||||
|
if newID == botUserID {
|
||||||
|
return true // already up-to-date
|
||||||
|
}
|
||||||
|
// User changed (or first resolve) — regenerate JWT and agent manager.
|
||||||
|
newToken, tokenErr := agent.GenerateBotToken(newID)
|
||||||
|
if tokenErr != nil {
|
||||||
|
logger.Errorf("Failed to generate bot JWT for user %s: %v", newID, tokenErr)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
prevID := botUserID
|
||||||
|
botUserID = newID
|
||||||
|
botToken = newToken
|
||||||
|
agents = agent.NewManager(cfg.APIServerPort, botToken, botUserID,
|
||||||
|
func() mcp.AIClient { return newLLMClient(st, botUserID) },
|
||||||
|
api.GetAPIDocs(),
|
||||||
|
)
|
||||||
|
if prevID == "" {
|
||||||
|
logger.Infof("Bot: resolved user %s", botUserID)
|
||||||
|
} else {
|
||||||
|
logger.Infof("Bot: user changed %s → %s, agent manager refreshed", prevID, botUserID)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial resolve — may fail if no user registered yet, which is fine.
|
||||||
|
resolveBotUser()
|
||||||
|
|
||||||
u := tgbotapi.NewUpdate(0)
|
u := tgbotapi.NewUpdate(0)
|
||||||
u.Timeout = 60
|
u.Timeout = 60
|
||||||
updates := bot.GetUpdatesChan(u)
|
updates := bot.GetUpdatesChan(u)
|
||||||
@@ -131,17 +154,23 @@ func runBot(token string, cfg *config.Config, st *store.Store) bool {
|
|||||||
|
|
||||||
// Handle /start: auto-bind or language selection / welcome
|
// Handle /start: auto-bind or language selection / welcome
|
||||||
if text == "/start" {
|
if text == "/start" {
|
||||||
|
// Re-resolve user on every /start (handles: registered after bot launch).
|
||||||
|
resolveBotUser()
|
||||||
|
if botUserID == "" {
|
||||||
|
sendMsg(bot, chatID, "No account found. Please register on the web UI first, then send /start.")
|
||||||
|
continue
|
||||||
|
}
|
||||||
if allowedChatID == 0 {
|
if allowedChatID == 0 {
|
||||||
username := update.Message.From.UserName
|
username := update.Message.From.UserName
|
||||||
if err := st.TelegramConfig().BindUser(chatID, "@"+username); err != nil {
|
if err := st.TelegramConfig().BindUser(chatID, "@"+username); err != nil {
|
||||||
logger.Errorf("Failed to bind Telegram user: %v", err)
|
logger.Errorf("Failed to bind Telegram user: %v", err)
|
||||||
sendMsg(bot, chatID, "Binding failed. / 绑定失败。")
|
sendMsg(bot, chatID, "Binding failed. Please try again.")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
allowedChatID = chatID
|
allowedChatID = chatID
|
||||||
logger.Infof("Telegram bound to @%s (chatID: %d)", username, chatID)
|
logger.Infof("Telegram bound to @%s (chatID: %d)", username, chatID)
|
||||||
} else if chatID != allowedChatID {
|
} else if chatID != allowedChatID {
|
||||||
sendMsg(bot, chatID, "This bot is already bound to another user. / 该机器人已被其他用户绑定。")
|
sendMsg(bot, chatID, "This bot is already bound to another user.")
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
agents.Reset(chatID)
|
agents.Reset(chatID)
|
||||||
@@ -173,17 +202,24 @@ func runBot(token string, cfg *config.Config, st *store.Store) bool {
|
|||||||
|
|
||||||
// Access control
|
// Access control
|
||||||
if allowedChatID != 0 && chatID != allowedChatID {
|
if allowedChatID != 0 && chatID != allowedChatID {
|
||||||
sendMsg(bot, chatID, "Unauthorized. / 无权限访问。")
|
sendMsg(bot, chatID, "Unauthorized.")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if allowedChatID == 0 {
|
if allowedChatID == 0 {
|
||||||
sendMsg(bot, chatID, "Send /start first. / 请先发送 /start。")
|
sendMsg(bot, chatID, "Send /start first.")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if text == "" {
|
if text == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Refresh user on every message (handles registration that happened mid-session).
|
||||||
|
resolveBotUser()
|
||||||
|
if botUserID == "" {
|
||||||
|
sendMsg(bot, chatID, "No account found. Please register on the web UI first.")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Direct setup commands (no LLM needed): "configure deepseek sk-xxx" / "配置 deepseek sk-xxx"
|
// Direct setup commands (no LLM needed): "configure deepseek sk-xxx" / "配置 deepseek sk-xxx"
|
||||||
lang := st.TelegramConfig().GetLanguage()
|
lang := st.TelegramConfig().GetLanguage()
|
||||||
if reply, handled := tryHandleSetupCommand(text, cfg.APIServerPort, botToken, st, botUserID, lang); handled {
|
if reply, handled := tryHandleSetupCommand(text, cfg.APIServerPort, botToken, st, botUserID, lang); handled {
|
||||||
|
|||||||
Reference in New Issue
Block a user