精简: 去掉 Telegram 机器人+通知: tgbot 包/stats-notify 与 hash 清理 job/登录通知/backuptotgbot/testTgBot/全部 tg* 设置/locale Bot 本地化/SecretClears 机制; 连带清理 Swagger/外部流量/邮件/2FA 的残留测试
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
package job
|
||||
|
||||
import "github.com/mhsanaei/3x-ui/v3/internal/web/service/tgbot"
|
||||
|
||||
// CheckHashStorageJob periodically cleans up expired hash entries from the Telegram bot's hash storage.
|
||||
type CheckHashStorageJob struct {
|
||||
tgbotService tgbot.Tgbot
|
||||
}
|
||||
|
||||
// NewCheckHashStorageJob creates a new hash storage cleanup job instance.
|
||||
func NewCheckHashStorageJob() *CheckHashStorageJob {
|
||||
return new(CheckHashStorageJob)
|
||||
}
|
||||
|
||||
// Run removes expired hash entries from the Telegram bot's hash storage.
|
||||
func (j *CheckHashStorageJob) Run() {
|
||||
storage := j.tgbotService.GetHashStorage()
|
||||
if storage == nil {
|
||||
return
|
||||
}
|
||||
storage.RemoveExpiredHashes()
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package job
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCheckHashStorageJob_RunWithoutPanicWhenStorageNil(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Fatalf("CheckHashStorageJob.Run panicked when storage is nil: %v", r)
|
||||
}
|
||||
}()
|
||||
NewCheckHashStorageJob().Run()
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service/tgbot"
|
||||
)
|
||||
|
||||
// LoginStatus represents the status of a login attempt.
|
||||
type LoginStatus byte
|
||||
|
||||
const (
|
||||
LoginSuccess LoginStatus = 1 // Successful login
|
||||
LoginFail LoginStatus = 0 // Failed login attempt
|
||||
)
|
||||
|
||||
// StatsNotifyJob sends periodic statistics reports via Telegram bot.
|
||||
type StatsNotifyJob struct {
|
||||
xrayService service.XrayService
|
||||
tgbotService tgbot.Tgbot
|
||||
}
|
||||
|
||||
// NewStatsNotifyJob creates a new statistics notification job instance.
|
||||
func NewStatsNotifyJob() *StatsNotifyJob {
|
||||
return new(StatsNotifyJob)
|
||||
}
|
||||
|
||||
// Run sends a statistics report via Telegram bot if Xray is running.
|
||||
func (j *StatsNotifyJob) Run() {
|
||||
if !j.xrayService.IsXrayRunning() {
|
||||
return
|
||||
}
|
||||
j.tgbotService.SendReport()
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
func stallingListener(t *testing.T) (addr string, release func()) {
|
||||
t.Helper()
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go func(c net.Conn) {
|
||||
<-done
|
||||
_ = c.Close()
|
||||
}(conn)
|
||||
go func(c net.Conn) { _, _ = io.Copy(io.Discard, c) }(conn)
|
||||
}
|
||||
}()
|
||||
return ln.Addr().String(), func() {
|
||||
_ = ln.Close()
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalInformClient_StalledReceiverTimesOut(t *testing.T) {
|
||||
addr, release := stallingListener(t)
|
||||
defer release()
|
||||
|
||||
request := fasthttp.AcquireRequest()
|
||||
defer fasthttp.ReleaseRequest(request)
|
||||
request.Header.SetMethod("POST")
|
||||
request.Header.SetContentType("application/json; charset=UTF-8")
|
||||
request.SetBody([]byte(`{"clientTraffics":[],"inboundTraffics":[]}`))
|
||||
request.SetRequestURI("http://" + addr + "/inform")
|
||||
request.Header.SetConnectionClose()
|
||||
|
||||
response := fasthttp.AcquireResponse()
|
||||
defer fasthttp.ReleaseResponse(response)
|
||||
|
||||
start := time.Now()
|
||||
err := externalInformClient.DoTimeout(request, response, externalInformTimeout)
|
||||
elapsed := time.Since(start)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("a receiver that never answers must produce an error, not a completed request")
|
||||
}
|
||||
if !errors.Is(err, fasthttp.ErrTimeout) {
|
||||
t.Errorf("want a timeout error, got %v", err)
|
||||
}
|
||||
if elapsed > externalInformTimeout+2*time.Second {
|
||||
t.Errorf("call took %v, must be bounded by %v", elapsed, externalInformTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalInformClient_HasDeadlines(t *testing.T) {
|
||||
if externalInformClient.ReadTimeout <= 0 || externalInformClient.WriteTimeout <= 0 {
|
||||
t.Fatal("the traffic-notify client must carry read and write deadlines")
|
||||
}
|
||||
if externalInformTimeout >= 5*time.Second {
|
||||
t.Errorf("the call budget (%v) must stay under the 5s traffic poll cadence", externalInformTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInformSkippedWhenNothingToReport(t *testing.T) {
|
||||
j := &XrayTrafficJob{}
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
j.informTrafficToExternalAPI(nil, nil)
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("an empty payload must return before touching settings or the network")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user