mirror of
				https://github.com/MHSanaei/3x-ui.git
				synced 2025-10-31 04:12:51 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "4d02756e1e251bc555263bebfe319139278bfb37" and "d064e85ecd127450e77727b2fcc90efc6190a186" have entirely different histories.
		
	
	
		
			4d02756e1e
			...
			d064e85ecd
		
	
		
					 5 changed files with 78 additions and 60 deletions
				
			
		
							
								
								
									
										62
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -8,7 +8,6 @@ on: | ||||||
|     branches: |     branches: | ||||||
|       - main |       - main | ||||||
|     paths: |     paths: | ||||||
|       - '.github/workflows/release.yml' |  | ||||||
|       - '**.js' |       - '**.js' | ||||||
|       - '**.css' |       - '**.css' | ||||||
|       - '**.html' |       - '**.html' | ||||||
|  | @ -43,34 +42,51 @@ jobs: | ||||||
|           go-version-file: go.mod |           go-version-file: go.mod | ||||||
|           check-latest: true |           check-latest: true | ||||||
| 
 | 
 | ||||||
|       - name: Build 3X-UI |       - name: Build 3x-ui | ||||||
|         run: | |         run: | | ||||||
|           export CGO_ENABLED=1 |           export CGO_ENABLED=1 | ||||||
|           export GOOS=linux |           export GOOS=linux | ||||||
|           export GOARCH=${{ matrix.platform }} |           export GOARCH=${{ matrix.platform }} | ||||||
|           # Use Bootlin prebuilt cross-toolchains (musl 1.2.5 in stable series) |           TOOLCHAIN_URL="" | ||||||
|  |           MUSL_CC_HOST="https://download.wireguard.com/qemu-test/toolchains/20240917/" | ||||||
|           case "${{ matrix.platform }}" in |           case "${{ matrix.platform }}" in | ||||||
|             amd64) BOOTLIN_ARCH="x86-64" ;; |             amd64) | ||||||
|             arm64) BOOTLIN_ARCH="aarch64" ;; |               TOOLCHAIN_URL="$MUSL_CC_HOST/x86_64-linux-musl-cross.tgz" | ||||||
|             armv7) BOOTLIN_ARCH="armv7-eabihf"; export GOARCH=arm GOARM=7 ;; |               ;; | ||||||
|             armv6) BOOTLIN_ARCH="armv6-eabihf"; export GOARCH=arm GOARM=6 ;; |             arm64) | ||||||
|             armv5) BOOTLIN_ARCH="armv5-eabi"; export GOARCH=arm GOARM=5 ;; |               TOOLCHAIN_URL="$MUSL_CC_HOST/aarch64-linux-musl-cross.tgz" | ||||||
|             386) BOOTLIN_ARCH="x86-i686" ;; |               ;; | ||||||
|             s390x) BOOTLIN_ARCH="s390x-z13" ;; |             armv7) | ||||||
|  |               TOOLCHAIN_URL="$MUSL_CC_HOST/armv7l-linux-musleabihf-cross.tgz" | ||||||
|  |               export GOARCH=arm | ||||||
|  |               export GOARM=7 | ||||||
|  |               ;; | ||||||
|  |             armv6) | ||||||
|  |               TOOLCHAIN_URL="$MUSL_CC_HOST/armv6-linux-musleabihf-cross.tgz" | ||||||
|  |               export GOARCH=arm | ||||||
|  |               export GOARM=6 | ||||||
|  |               ;; | ||||||
|  |             armv5) | ||||||
|  |               TOOLCHAIN_URL="$MUSL_CC_HOST/arm-linux-musleabi-cross.tgz" | ||||||
|  |               export GOARCH=arm | ||||||
|  |               export GOARM=5 | ||||||
|  |               ;; | ||||||
|  |             386) | ||||||
|  |               TOOLCHAIN_URL="$MUSL_CC_HOST/i686-linux-musl-cross.tgz" | ||||||
|  |               ;; | ||||||
|  |             s390x) | ||||||
|  |               TOOLCHAIN_URL="$MUSL_CC_HOST/s390x-linux-musl-cross.tgz" | ||||||
|  |               ;; | ||||||
|           esac |           esac | ||||||
|           echo "Resolving Bootlin musl toolchain for arch=$BOOTLIN_ARCH (platform=${{ matrix.platform }})" |           echo "Downloading musl toolchain for ${{ matrix.platform }}" | ||||||
|           TARBALL_BASE="https://toolchains.bootlin.com/downloads/releases/toolchains/$BOOTLIN_ARCH/tarballs/" |           curl -LO "$TOOLCHAIN_URL" | ||||||
|           TARBALL_URL=$(curl -fsSL "$TARBALL_BASE" | grep -oE "${BOOTLIN_ARCH}--musl--stable-[^\"]+\\.tar\\.xz" | sort -r | head -n1) |           tar -xf *.tgz | ||||||
|           [ -z "$TARBALL_URL" ] && { echo "Failed to locate Bootlin musl toolchain for arch=$BOOTLIN_ARCH" >&2; exit 1; } |           TOOLCHAIN_DIR=$(find . -maxdepth 1 -type d -name "*-cross" | head -n1) | ||||||
|           echo "Downloading: $TARBALL_URL" |           TOOLCHAIN_DIR=$(realpath "$TOOLCHAIN_DIR") | ||||||
|           cd /tmp |           export PATH="$TOOLCHAIN_DIR/bin:$PATH" | ||||||
|           curl -fL -sS -o "$(basename "$TARBALL_URL")" "$TARBALL_BASE/$TARBALL_URL" |           # Detect compiler | ||||||
|           tar -xf "$(basename "$TARBALL_URL")" |           export CC=$(find $TOOLCHAIN_DIR/bin -name '*-gcc' | head -n1) | ||||||
|           TOOLCHAIN_DIR=$(find . -maxdepth 1 -type d -name "${BOOTLIN_ARCH}--musl--stable-*" | head -n1) |           echo "Using CC=$CC" | ||||||
|           export PATH="$(realpath "$TOOLCHAIN_DIR")/bin:$PATH" |  | ||||||
|           export CC=$(realpath "$(find "$TOOLCHAIN_DIR/bin" -name '*-gcc.br_real' -type f -executable | head -n1)") |  | ||||||
|           [ -z "$CC" ] && { echo "No gcc.br_real found in $TOOLCHAIN_DIR/bin" >&2; exit 1; } |  | ||||||
|           cd - |  | ||||||
|           go build -ldflags "-w -s -linkmode external -extldflags '-static'" -o xui-release -v main.go |           go build -ldflags "-w -s -linkmode external -extldflags '-static'" -o xui-release -v main.go | ||||||
|           file xui-release |           file xui-release | ||||||
|           ldd xui-release || echo "Static binary confirmed" |           ldd xui-release || echo "Static binary confirmed" | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| 2.6.6 | 2.6.5 | ||||||
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							|  | @ -9,7 +9,7 @@ require ( | ||||||
| 	github.com/goccy/go-json v0.10.5 | 	github.com/goccy/go-json v0.10.5 | ||||||
| 	github.com/google/uuid v1.6.0 | 	github.com/google/uuid v1.6.0 | ||||||
| 	github.com/joho/godotenv v1.5.1 | 	github.com/joho/godotenv v1.5.1 | ||||||
| 	github.com/mymmrac/telego v1.2.0 | 	github.com/mymmrac/telego v0.32.0 | ||||||
| 	github.com/nicksnyder/go-i18n/v2 v2.6.0 | 	github.com/nicksnyder/go-i18n/v2 v2.6.0 | ||||||
| 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 | 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 | ||||||
| 	github.com/pelletier/go-toml/v2 v2.2.4 | 	github.com/pelletier/go-toml/v2 v2.2.4 | ||||||
|  | @ -34,6 +34,7 @@ require ( | ||||||
| 	github.com/cloudwego/base64x v0.1.6 // indirect | 	github.com/cloudwego/base64x v0.1.6 // indirect | ||||||
| 	github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 // indirect | 	github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 // indirect | ||||||
| 	github.com/ebitengine/purego v0.8.4 // indirect | 	github.com/ebitengine/purego v0.8.4 // indirect | ||||||
|  | 	github.com/fasthttp/router v1.5.4 // indirect | ||||||
| 	github.com/gabriel-vasile/mimetype v1.4.9 // indirect | 	github.com/gabriel-vasile/mimetype v1.4.9 // indirect | ||||||
| 	github.com/gin-contrib/sse v1.1.0 // indirect | 	github.com/gin-contrib/sse v1.1.0 // indirect | ||||||
| 	github.com/go-ole/go-ole v1.3.0 // indirect | 	github.com/go-ole/go-ole v1.3.0 // indirect | ||||||
|  | @ -69,6 +70,7 @@ require ( | ||||||
| 	github.com/rogpeppe/go-internal v1.14.1 // indirect | 	github.com/rogpeppe/go-internal v1.14.1 // indirect | ||||||
| 	github.com/sagernet/sing v0.7.5 // indirect | 	github.com/sagernet/sing v0.7.5 // indirect | ||||||
| 	github.com/sagernet/sing-shadowsocks v0.2.8 // indirect | 	github.com/sagernet/sing-shadowsocks v0.2.8 // indirect | ||||||
|  | 	github.com/savsgio/gotils v0.0.0-20250408102913-196191ec6287 // indirect | ||||||
| 	github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect | 	github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect | ||||||
| 	github.com/tklauser/go-sysconf v0.3.15 // indirect | 	github.com/tklauser/go-sysconf v0.3.15 // indirect | ||||||
| 	github.com/tklauser/numcpus v0.10.0 // indirect | 	github.com/tklauser/numcpus v0.10.0 // indirect | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
								
							|  | @ -19,6 +19,8 @@ github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 h1:ucRHb6/lvW/+mT | ||||||
| github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= | github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= | ||||||
| github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= | github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= | ||||||
| github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= | github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= | ||||||
|  | github.com/fasthttp/router v1.5.4 h1:oxdThbBwQgsDIYZ3wR1IavsNl6ZS9WdjKukeMikOnC8= | ||||||
|  | github.com/fasthttp/router v1.5.4/go.mod h1:3/hysWq6cky7dTfzaaEPZGdptwjwx0qzTgFCKEWRjgc= | ||||||
| github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= | github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= | ||||||
| github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= | github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= | ||||||
| github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= | github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= | ||||||
|  | @ -104,8 +106,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w | ||||||
| github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||||
| github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= | ||||||
| github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | ||||||
| github.com/mymmrac/telego v1.2.0 h1:CHmR9eiugpTiF/ttppmK89E6mcu9d4DmNQS0tMpUs6M= | github.com/mymmrac/telego v0.32.0 h1:4X8C1l3k+opkk86r95+eQE8DxiS2LYlR61L/G7yreDY= | ||||||
| github.com/mymmrac/telego v1.2.0/go.mod h1:OiCm4QjqB/ZY2E4VAmkVH8EeLLhM4QuFuO1KOCuvGoM= | github.com/mymmrac/telego v0.32.0/go.mod h1:qS6NaRhJgcuEEBEMVCV79S2xCAuHq9O+ixwfLuRW31M= | ||||||
| github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ= | github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ= | ||||||
| github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE= | github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE= | ||||||
| github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= | ||||||
|  | @ -136,6 +138,8 @@ github.com/sagernet/sing v0.7.5 h1:gNMwZCLPqR+4e0g6dwi0sSsrvOmoMjpZgqxKsuJZatc= | ||||||
| github.com/sagernet/sing v0.7.5/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= | github.com/sagernet/sing v0.7.5/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= | ||||||
| github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE= | github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE= | ||||||
| github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI= | github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI= | ||||||
|  | github.com/savsgio/gotils v0.0.0-20250408102913-196191ec6287 h1:qIQ0tWF9vxGtkJa24bR+2i53WBCz1nW/Pc47oVYauC4= | ||||||
|  | github.com/savsgio/gotils v0.0.0-20250408102913-196191ec6287/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg= | ||||||
| github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4= | github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4= | ||||||
| github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= | github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= | ||||||
| github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM= | github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM= | ||||||
|  |  | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| package service | package service | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" |  | ||||||
| 	"crypto/rand" | 	"crypto/rand" | ||||||
| 	"embed" | 	"embed" | ||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
|  | @ -149,7 +148,7 @@ func (t *Tgbot) Start(i18nFS embed.FS) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// After bot initialization, set up bot commands with localized descriptions
 | 	// After bot initialization, set up bot commands with localized descriptions
 | ||||||
| 	err = bot.SetMyCommands(context.Background(), &telego.SetMyCommandsParams{ | 	err = bot.SetMyCommands(&telego.SetMyCommandsParams{ | ||||||
| 		Commands: []telego.BotCommand{ | 		Commands: []telego.BotCommand{ | ||||||
| 			{Command: "start", Description: t.I18nBot("tgbot.commands.startDesc")}, | 			{Command: "start", Description: t.I18nBot("tgbot.commands.startDesc")}, | ||||||
| 			{Command: "help", Description: t.I18nBot("tgbot.commands.helpDesc")}, | 			{Command: "help", Description: t.I18nBot("tgbot.commands.helpDesc")}, | ||||||
|  | @ -222,9 +221,8 @@ func (t *Tgbot) SetHostname() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (t *Tgbot) Stop() { | func (t *Tgbot) Stop() { | ||||||
| 	if botHandler != nil { | 	botHandler.Stop() | ||||||
| 		botHandler.Stop() | 	bot.StopLongPolling() | ||||||
| 	} |  | ||||||
| 	logger.Info("Stop Telegram receiver ...") | 	logger.Info("Stop Telegram receiver ...") | ||||||
| 	isRunning = false | 	isRunning = false | ||||||
| 	adminIds = nil | 	adminIds = nil | ||||||
|  | @ -257,29 +255,26 @@ func (t *Tgbot) OnReceive() { | ||||||
| 		Timeout: 10, | 		Timeout: 10, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	updates, _ := bot.UpdatesViaLongPolling(context.Background(), ¶ms) | 	updates, _ := bot.UpdatesViaLongPolling(¶ms) | ||||||
| 
 | 
 | ||||||
| 	botHandler, _ = th.NewBotHandler(bot, updates) | 	botHandler, _ = th.NewBotHandler(bot, updates) | ||||||
| 
 | 
 | ||||||
| 	botHandler.HandleMessage(func(ctx *th.Context, message telego.Message) error { | 	botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { | ||||||
| 		delete(userStates, message.Chat.ID) | 		delete(userStates, message.Chat.ID) | ||||||
| 		t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove()) | 		t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove()) | ||||||
| 		return nil |  | ||||||
| 	}, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard"))) | 	}, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard"))) | ||||||
| 
 | 
 | ||||||
| 	botHandler.HandleMessage(func(ctx *th.Context, message telego.Message) error { | 	botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { | ||||||
| 		delete(userStates, message.Chat.ID) | 		delete(userStates, message.Chat.ID) | ||||||
| 		t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) | 		t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) | ||||||
| 		return nil |  | ||||||
| 	}, th.AnyCommand()) | 	}, th.AnyCommand()) | ||||||
| 
 | 
 | ||||||
| 	botHandler.HandleCallbackQuery(func(ctx *th.Context, query telego.CallbackQuery) error { | 	botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) { | ||||||
| 		delete(userStates, query.Message.GetChat().ID) | 		delete(userStates, query.Message.GetChat().ID) | ||||||
| 		t.answerCallback(&query, checkAdmin(query.From.ID)) | 		t.answerCallback(&query, checkAdmin(query.From.ID)) | ||||||
| 		return nil |  | ||||||
| 	}, th.AnyCallbackQueryWithMessage()) | 	}, th.AnyCallbackQueryWithMessage()) | ||||||
| 
 | 
 | ||||||
| 	botHandler.HandleMessage(func(ctx *th.Context, message telego.Message) error { | 	botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { | ||||||
| 		if userState, exists := userStates[message.Chat.ID]; exists { | 		if userState, exists := userStates[message.Chat.ID]; exists { | ||||||
| 			switch userState { | 			switch userState { | ||||||
| 			case "awaiting_id": | 			case "awaiting_id": | ||||||
|  | @ -289,7 +284,7 @@ func (t *Tgbot) OnReceive() { | ||||||
| 					inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) | 					inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) | ||||||
| 					message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | 					message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | ||||||
| 					t.addClient(message.Chat.ID, message_text) | 					t.addClient(message.Chat.ID, message_text) | ||||||
| 					return nil | 					return | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				client_Id = strings.TrimSpace(message.Text) | 				client_Id = strings.TrimSpace(message.Text) | ||||||
|  | @ -314,7 +309,7 @@ func (t *Tgbot) OnReceive() { | ||||||
| 				if client_TrPassword == strings.TrimSpace(message.Text) { | 				if client_TrPassword == strings.TrimSpace(message.Text) { | ||||||
| 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | ||||||
| 					delete(userStates, message.Chat.ID) | 					delete(userStates, message.Chat.ID) | ||||||
| 					return nil | 					return | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				client_TrPassword = strings.TrimSpace(message.Text) | 				client_TrPassword = strings.TrimSpace(message.Text) | ||||||
|  | @ -339,7 +334,7 @@ func (t *Tgbot) OnReceive() { | ||||||
| 				if client_ShPassword == strings.TrimSpace(message.Text) { | 				if client_ShPassword == strings.TrimSpace(message.Text) { | ||||||
| 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | ||||||
| 					delete(userStates, message.Chat.ID) | 					delete(userStates, message.Chat.ID) | ||||||
| 					return nil | 					return | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				client_ShPassword = strings.TrimSpace(message.Text) | 				client_ShPassword = strings.TrimSpace(message.Text) | ||||||
|  | @ -364,7 +359,7 @@ func (t *Tgbot) OnReceive() { | ||||||
| 				if client_Email == strings.TrimSpace(message.Text) { | 				if client_Email == strings.TrimSpace(message.Text) { | ||||||
| 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | ||||||
| 					delete(userStates, message.Chat.ID) | 					delete(userStates, message.Chat.ID) | ||||||
| 					return nil | 					return | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				client_Email = strings.TrimSpace(message.Text) | 				client_Email = strings.TrimSpace(message.Text) | ||||||
|  | @ -389,7 +384,7 @@ func (t *Tgbot) OnReceive() { | ||||||
| 				if client_Comment == strings.TrimSpace(message.Text) { | 				if client_Comment == strings.TrimSpace(message.Text) { | ||||||
| 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | 					t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) | ||||||
| 					delete(userStates, message.Chat.ID) | 					delete(userStates, message.Chat.ID) | ||||||
| 					return nil | 					return | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				client_Comment = strings.TrimSpace(message.Text) | 				client_Comment = strings.TrimSpace(message.Text) | ||||||
|  | @ -422,7 +417,6 @@ func (t *Tgbot) OnReceive() { | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return nil |  | ||||||
| 	}, th.AnyMessage()) | 	}, th.AnyMessage()) | ||||||
| 
 | 
 | ||||||
| 	botHandler.Start() | 	botHandler.Start() | ||||||
|  | @ -705,7 +699,7 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool | ||||||
| 				} | 				} | ||||||
| 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | ||||||
| 
 | 
 | ||||||
| 				t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId) | 				t.addClient(chatId, message_text, messageId) | ||||||
| 				t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) | 				t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) | ||||||
| 			case "add_client_limit_traffic_in": | 			case "add_client_limit_traffic_in": | ||||||
| 				if len(dataArray) >= 2 { | 				if len(dataArray) >= 2 { | ||||||
|  | @ -920,7 +914,7 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool | ||||||
| 				} | 				} | ||||||
| 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | ||||||
| 
 | 
 | ||||||
| 				t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId) | 				t.addClient(chatId, message_text, messageId) | ||||||
| 				t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) | 				t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) | ||||||
| 			case "add_client_reset_exp_in": | 			case "add_client_reset_exp_in": | ||||||
| 				if len(dataArray) >= 2 { | 				if len(dataArray) >= 2 { | ||||||
|  | @ -1102,7 +1096,7 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool | ||||||
| 				} | 				} | ||||||
| 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | ||||||
| 
 | 
 | ||||||
| 				t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId) | 				t.addClient(chatId, message_text, messageId) | ||||||
| 				t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) | 				t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation")) | ||||||
| 			case "add_client_ip_limit_in": | 			case "add_client_ip_limit_in": | ||||||
| 				if len(dataArray) >= 2 { | 				if len(dataArray) >= 2 { | ||||||
|  | @ -1163,6 +1157,8 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool | ||||||
| 						return | 						return | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | 				t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) | ||||||
|  | 				t.searchClient(chatId, email, callbackQuery.Message.GetMessageID()) | ||||||
| 			case "clear_ips": | 			case "clear_ips": | ||||||
| 				inlineKeyboard := tu.InlineKeyboard( | 				inlineKeyboard := tu.InlineKeyboard( | ||||||
| 					tu.InlineKeyboardRow( | 					tu.InlineKeyboardRow( | ||||||
|  | @ -1289,7 +1285,7 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool | ||||||
| 
 | 
 | ||||||
| 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | 				message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) | ||||||
| 
 | 
 | ||||||
| 				t.addClient(callbackQuery.Message.GetChat().ID, message_text) | 				t.addClient(chatId, message_text) | ||||||
| 			} | 			} | ||||||
| 			return | 			return | ||||||
| 		} else { | 		} else { | ||||||
|  | @ -1863,7 +1859,7 @@ func (t *Tgbot) SendMsgToTgbot(chatId int64, msg string, replyMarkup ...telego.R | ||||||
| 		if len(replyMarkup) > 0 && n == (len(allMessages)-1) { | 		if len(replyMarkup) > 0 && n == (len(allMessages)-1) { | ||||||
| 			params.ReplyMarkup = replyMarkup[0] | 			params.ReplyMarkup = replyMarkup[0] | ||||||
| 		} | 		} | ||||||
| 		_, err := bot.SendMessage(context.Background(), ¶ms) | 		_, err := bot.SendMessage(¶ms) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Warning("Error sending telegram message :", err) | 			logger.Warning("Error sending telegram message :", err) | ||||||
| 		} | 		} | ||||||
|  | @ -2769,7 +2765,7 @@ func (t *Tgbot) sendBackup(chatId int64) { | ||||||
| 			tu.ID(chatId), | 			tu.ID(chatId), | ||||||
| 			tu.File(file), | 			tu.File(file), | ||||||
| 		) | 		) | ||||||
| 		_, err = bot.SendDocument(context.Background(), document) | 		_, err = bot.SendDocument(document) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Error("Error in uploading backup: ", err) | 			logger.Error("Error in uploading backup: ", err) | ||||||
| 		} | 		} | ||||||
|  | @ -2783,7 +2779,7 @@ func (t *Tgbot) sendBackup(chatId int64) { | ||||||
| 			tu.ID(chatId), | 			tu.ID(chatId), | ||||||
| 			tu.File(file), | 			tu.File(file), | ||||||
| 		) | 		) | ||||||
| 		_, err = bot.SendDocument(context.Background(), document) | 		_, err = bot.SendDocument(document) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Error("Error in uploading config.json: ", err) | 			logger.Error("Error in uploading config.json: ", err) | ||||||
| 		} | 		} | ||||||
|  | @ -2807,7 +2803,7 @@ func (t *Tgbot) sendBanLogs(chatId int64, dt bool) { | ||||||
| 				tu.ID(chatId), | 				tu.ID(chatId), | ||||||
| 				tu.File(file), | 				tu.File(file), | ||||||
| 			) | 			) | ||||||
| 			_, err = bot.SendDocument(context.Background(), document) | 			_, err = bot.SendDocument(document) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logger.Error("Error in uploading IPLimitBannedPrevLog: ", err) | 				logger.Error("Error in uploading IPLimitBannedPrevLog: ", err) | ||||||
| 			} | 			} | ||||||
|  | @ -2828,7 +2824,7 @@ func (t *Tgbot) sendBanLogs(chatId int64, dt bool) { | ||||||
| 				tu.ID(chatId), | 				tu.ID(chatId), | ||||||
| 				tu.File(file), | 				tu.File(file), | ||||||
| 			) | 			) | ||||||
| 			_, err = bot.SendDocument(context.Background(), document) | 			_, err = bot.SendDocument(document) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logger.Error("Error in uploading IPLimitBannedLog: ", err) | 				logger.Error("Error in uploading IPLimitBannedLog: ", err) | ||||||
| 			} | 			} | ||||||
|  | @ -2846,7 +2842,7 @@ func (t *Tgbot) sendCallbackAnswerTgBot(id string, message string) { | ||||||
| 		CallbackQueryID: id, | 		CallbackQueryID: id, | ||||||
| 		Text:            message, | 		Text:            message, | ||||||
| 	} | 	} | ||||||
| 	if err := bot.AnswerCallbackQuery(context.Background(), ¶ms); err != nil { | 	if err := bot.AnswerCallbackQuery(¶ms); err != nil { | ||||||
| 		logger.Warning(err) | 		logger.Warning(err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -2857,7 +2853,7 @@ func (t *Tgbot) editMessageCallbackTgBot(chatId int64, messageID int, inlineKeyb | ||||||
| 		MessageID:   messageID, | 		MessageID:   messageID, | ||||||
| 		ReplyMarkup: inlineKeyboard, | 		ReplyMarkup: inlineKeyboard, | ||||||
| 	} | 	} | ||||||
| 	if _, err := bot.EditMessageReplyMarkup(context.Background(), ¶ms); err != nil { | 	if _, err := bot.EditMessageReplyMarkup(¶ms); err != nil { | ||||||
| 		logger.Warning(err) | 		logger.Warning(err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -2872,7 +2868,7 @@ func (t *Tgbot) editMessageTgBot(chatId int64, messageID int, text string, inlin | ||||||
| 	if len(inlineKeyboard) > 0 { | 	if len(inlineKeyboard) > 0 { | ||||||
| 		params.ReplyMarkup = inlineKeyboard[0] | 		params.ReplyMarkup = inlineKeyboard[0] | ||||||
| 	} | 	} | ||||||
| 	if _, err := bot.EditMessageText(context.Background(), ¶ms); err != nil { | 	if _, err := bot.EditMessageText(¶ms); err != nil { | ||||||
| 		logger.Warning(err) | 		logger.Warning(err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -2885,7 +2881,7 @@ func (t *Tgbot) SendMsgToTgbotDeleteAfter(chatId int64, msg string, delayInSecon | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Send the message
 | 	// Send the message
 | ||||||
| 	sentMsg, err := bot.SendMessage(context.Background(), &telego.SendMessageParams{ | 	sentMsg, err := bot.SendMessage(&telego.SendMessageParams{ | ||||||
| 		ChatID:      tu.ID(chatId), | 		ChatID:      tu.ID(chatId), | ||||||
| 		Text:        msg, | 		Text:        msg, | ||||||
| 		ReplyMarkup: replyMarkupParam, // Use the correct replyMarkup value
 | 		ReplyMarkup: replyMarkupParam, // Use the correct replyMarkup value
 | ||||||
|  | @ -2908,7 +2904,7 @@ func (t *Tgbot) deleteMessageTgBot(chatId int64, messageID int) { | ||||||
| 		ChatID:    tu.ID(chatId), | 		ChatID:    tu.ID(chatId), | ||||||
| 		MessageID: messageID, | 		MessageID: messageID, | ||||||
| 	} | 	} | ||||||
| 	if err := bot.DeleteMessage(context.Background(), ¶ms); err != nil { | 	if err := bot.DeleteMessage(¶ms); err != nil { | ||||||
| 		logger.Warning("Failed to delete message:", err) | 		logger.Warning("Failed to delete message:", err) | ||||||
| 	} else { | 	} else { | ||||||
| 		logger.Info("Message deleted successfully") | 		logger.Info("Message deleted successfully") | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue