|
@@ -5,6 +5,7 @@ import (
|
|
|
"crypto/rand"
|
|
"crypto/rand"
|
|
|
"embed"
|
|
"embed"
|
|
|
"math/big"
|
|
"math/big"
|
|
|
|
|
+ "net"
|
|
|
"net/url"
|
|
"net/url"
|
|
|
"os"
|
|
"os"
|
|
|
"regexp"
|
|
"regexp"
|
|
@@ -342,15 +343,6 @@ func (t *Tgbot) Start(i18nFS embed.FS) error {
|
|
|
logger.Warning("Failed to get Telegram bot proxy URL:", err)
|
|
logger.Warning("Failed to get Telegram bot proxy URL:", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Fall back to the panel-wide egress bridge when no dedicated bot proxy is
|
|
|
|
|
- // set. Resolved once at bot start: if Xray comes up later, the bot keeps
|
|
|
|
|
- // its direct connection until it is restarted.
|
|
|
|
|
- if tgBotProxy == "" {
|
|
|
|
|
- if egress := t.settingService.PanelEgressProxyURL(); egress != "" && isSupportedBotProxyScheme(egress) {
|
|
|
|
|
- tgBotProxy = egress
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// Get Telegram bot API server URL
|
|
// Get Telegram bot API server URL
|
|
|
tgBotAPIServer, err := t.settingService.GetTgBotAPIServer()
|
|
tgBotAPIServer, err := t.settingService.GetTgBotAPIServer()
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -410,7 +402,7 @@ func isSupportedBotProxyScheme(proxyUrl string) bool {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// createRobustFastHTTPClient creates a fasthttp.Client with proper connection handling
|
|
// createRobustFastHTTPClient creates a fasthttp.Client with proper connection handling
|
|
|
-func (t *Tgbot) createRobustFastHTTPClient(proxyUrl string) *fasthttp.Client {
|
|
|
|
|
|
|
+func (t *Tgbot) createRobustFastHTTPClient(proxyUrl string, panelEgress func() string) *fasthttp.Client {
|
|
|
client := &fasthttp.Client{
|
|
client := &fasthttp.Client{
|
|
|
// Connection timeouts
|
|
// Connection timeouts
|
|
|
ReadTimeout: 30 * time.Second,
|
|
ReadTimeout: 30 * time.Second,
|
|
@@ -437,11 +429,24 @@ func (t *Tgbot) createRobustFastHTTPClient(proxyUrl string) *fasthttp.Client {
|
|
|
} else {
|
|
} else {
|
|
|
client.Dial = fasthttpproxy.FasthttpHTTPDialer(proxyUrl)
|
|
client.Dial = fasthttpproxy.FasthttpHTTPDialer(proxyUrl)
|
|
|
}
|
|
}
|
|
|
|
|
+ } else if panelEgress != nil {
|
|
|
|
|
+ client.Dial = panelEgressDial(panelEgress)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return client
|
|
return client
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// panelEgressDial resolves the panel egress bridge per connection, so a bridge
|
|
|
|
|
+// that comes up after bot start (Xray started later) is used without a restart.
|
|
|
|
|
+func panelEgressDial(resolve func() string) fasthttp.DialFunc {
|
|
|
|
|
+ return func(addr string) (net.Conn, error) {
|
|
|
|
|
+ if bridge := resolve(); bridge != "" {
|
|
|
|
|
+ return fasthttpproxy.FasthttpSocksDialer(bridge)(addr)
|
|
|
|
|
+ }
|
|
|
|
|
+ return fasthttp.Dial(addr)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// NewBot creates a new Telegram bot instance with optional proxy and API server settings.
|
|
// NewBot creates a new Telegram bot instance with optional proxy and API server settings.
|
|
|
func (t *Tgbot) NewBot(token string, proxyUrl string, apiServerUrl string) (*telego.Bot, error) {
|
|
func (t *Tgbot) NewBot(token string, proxyUrl string, apiServerUrl string) (*telego.Bot, error) {
|
|
|
// Validate proxy URL if provided
|
|
// Validate proxy URL if provided
|
|
@@ -467,7 +472,7 @@ func (t *Tgbot) NewBot(token string, proxyUrl string, apiServerUrl string) (*tel
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Create robust fasthttp client
|
|
// Create robust fasthttp client
|
|
|
- client := t.createRobustFastHTTPClient(proxyUrl)
|
|
|
|
|
|
|
+ client := t.createRobustFastHTTPClient(proxyUrl, t.settingService.PanelEgressProxyURL)
|
|
|
|
|
|
|
|
// Build bot options
|
|
// Build bot options
|
|
|
var options []telego.BotOption
|
|
var options []telego.BotOption
|