mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-16 16:20:59 +00:00
feat(tgbot): add Flow picker when creating a VLESS client
The bot's add-client flow already serialised client_Flow into the VLESS JSON template but never exposed a way to set it from Telegram, so every client ended up with an empty flow regardless of the inbound's transport. Added an inline "Flow" row to the VLESS protocol keyboard with three choices — None, xtls-rprx-vision, and xtls-rprx-vision-udp443 — and a matching i18n key in all 13 locale files. The row is only shown when the inbound can actually use Vision flow (mirrors the frontend's canEnableTlsFlow check: VLESS over TCP with TLS or Reality); on other transports it's hidden and any stale client_Flow value is reset, so the generated JSON stays consistent with the inbound's stream settings.
This commit is contained in:
+73
-1
@@ -1398,6 +1398,25 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
|
||||
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
||||
case "add_client_set_flow":
|
||||
if dataArray[1] == "none" {
|
||||
client_Flow = ""
|
||||
} else {
|
||||
client_Flow = dataArray[1]
|
||||
}
|
||||
messageId := callbackQuery.Message.GetMessageID()
|
||||
inbound, err := t.inboundService.GetInbound(receiver_inbound_ID)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
||||
case "add_client_ip_limit_in":
|
||||
@@ -1865,6 +1884,22 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
),
|
||||
)
|
||||
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
||||
case "add_client_ch_default_flow":
|
||||
inlineKeyboard := tu.InlineKeyboard(
|
||||
tu.InlineKeyboardRow(
|
||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
|
||||
),
|
||||
tu.InlineKeyboardRow(
|
||||
tu.InlineKeyboardButton("None").WithCallbackData(t.encodeQuery("add_client_set_flow none")),
|
||||
),
|
||||
tu.InlineKeyboardRow(
|
||||
tu.InlineKeyboardButton("xtls-rprx-vision").WithCallbackData(t.encodeQuery("add_client_set_flow xtls-rprx-vision")),
|
||||
),
|
||||
tu.InlineKeyboardRow(
|
||||
tu.InlineKeyboardButton("xtls-rprx-vision-udp443").WithCallbackData(t.encodeQuery("add_client_set_flow xtls-rprx-vision-udp443")),
|
||||
),
|
||||
)
|
||||
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
||||
case "add_client_ch_default_ip_limit":
|
||||
inlineKeyboard := tu.InlineKeyboard(
|
||||
tu.InlineKeyboardRow(
|
||||
@@ -3345,6 +3380,25 @@ func (t *Tgbot) getCommonClientButtons() [][]telego.InlineKeyboardButton {
|
||||
}
|
||||
}
|
||||
|
||||
// inboundCanEnableTlsFlow mirrors Inbound.canEnableTlsFlow() from the frontend
|
||||
// model: xtls-rprx-vision is only valid on VLESS-over-TCP with TLS or Reality.
|
||||
func inboundCanEnableTlsFlow(ib *model.Inbound) bool {
|
||||
if ib == nil || ib.Protocol != model.VLESS {
|
||||
return false
|
||||
}
|
||||
var stream struct {
|
||||
Network string `json:"network"`
|
||||
Security string `json:"security"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(ib.StreamSettings), &stream); err != nil {
|
||||
return false
|
||||
}
|
||||
if stream.Network != "tcp" {
|
||||
return false
|
||||
}
|
||||
return stream.Security == "tls" || stream.Security == "reality"
|
||||
}
|
||||
|
||||
// addClient handles the process of adding a new client to an inbound.
|
||||
func (t *Tgbot) addClient(chatId int64, msg string, messageID ...int) {
|
||||
inbound, err := t.inboundService.GetInbound(receiver_inbound_ID)
|
||||
@@ -3357,13 +3411,31 @@ func (t *Tgbot) addClient(chatId int64, msg string, messageID ...int) {
|
||||
|
||||
var protocolRows [][]telego.InlineKeyboardButton
|
||||
switch protocol {
|
||||
case model.VMESS, model.VLESS:
|
||||
case model.VMESS:
|
||||
protocolRows = [][]telego.InlineKeyboardButton{
|
||||
tu.InlineKeyboardRow(
|
||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"),
|
||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_id")).WithCallbackData("add_client_ch_default_id"),
|
||||
),
|
||||
}
|
||||
case model.VLESS:
|
||||
protocolRows = [][]telego.InlineKeyboardButton{
|
||||
tu.InlineKeyboardRow(
|
||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"),
|
||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_id")).WithCallbackData("add_client_ch_default_id"),
|
||||
),
|
||||
}
|
||||
if inboundCanEnableTlsFlow(inbound) {
|
||||
flowLabel := t.I18nBot("tgbot.buttons.change_flow")
|
||||
if client_Flow != "" {
|
||||
flowLabel = flowLabel + ": " + client_Flow
|
||||
}
|
||||
protocolRows = append(protocolRows, tu.InlineKeyboardRow(
|
||||
tu.InlineKeyboardButton(flowLabel).WithCallbackData("add_client_ch_default_flow"),
|
||||
))
|
||||
} else if client_Flow != "" {
|
||||
client_Flow = ""
|
||||
}
|
||||
case model.Trojan:
|
||||
protocolRows = [][]telego.InlineKeyboardButton{
|
||||
tu.InlineKeyboardRow(
|
||||
|
||||
Reference in New Issue
Block a user