mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-29 06:27:14 +00:00
style: adopt golangci-lint v2 and resolve all findings
Add .golangci.yml (v2): the standard linters plus bodyclose, errorlint, noctx, misspell, rowserrcheck, sqlclosecheck, unconvert, usestdlibvars, with gofumpt + goimports formatters. Enable the std-error-handling exclusion preset for idiomatic Close/Remove/Setenv ignores; scope-exclude SA1019 (parser.ParseDir in tools/openapigen) and ST1005 (intentional capitalized user-facing error copy that tests assert verbatim). No inline nolint directives were introduced. Resolve all 217 findings behavior-preserving: gofumpt/goimports formatting, explicit blank assignment on intentionally ignored errors, errors.Is/errors.As and %w wrapping, context-aware stdlib calls (CommandContext/QueryContext/NewRequestWithContext/Dialer), staticcheck simplifications, removed redundant conversions, http.StatusOK and http.MethodGet, inlined the go:fix intPtr helper, and deferred sql rows Close. Add a golangci CI job mirroring the existing Go jobs.
This commit is contained in:
@@ -283,7 +283,7 @@ func (t *Tgbot) Start(i18nFS embed.FS) error {
|
||||
logger.Warning("Failed to parse admin ID from Telegram bot chat ID:", err)
|
||||
return err
|
||||
}
|
||||
parsedAdminIds = append(parsedAdminIds, int64(id))
|
||||
parsedAdminIds = append(parsedAdminIds, id)
|
||||
}
|
||||
}
|
||||
tgBotMutex.Lock()
|
||||
@@ -472,7 +472,7 @@ func StopBot() {
|
||||
userStateMgr.reset()
|
||||
|
||||
if handler != nil {
|
||||
handler.Stop()
|
||||
_ = handler.Stop()
|
||||
}
|
||||
|
||||
if cancel != nil {
|
||||
|
||||
@@ -74,13 +74,13 @@ func (t *Tgbot) BuildClientDraftMessage() string {
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString("📝 *New client draft*\r\n")
|
||||
b.WriteString(fmt.Sprintf("📧 Email: `%s`\r\n", client_Email))
|
||||
b.WriteString(fmt.Sprintf("🔗 Attached: %s\r\n", attached))
|
||||
b.WriteString(fmt.Sprintf("📊 Traffic: %s\r\n", traffic))
|
||||
b.WriteString(fmt.Sprintf("📅 Expire: %s\r\n", expiry))
|
||||
b.WriteString(fmt.Sprintf("🔢 IP limit: %s\r\n", ipLimit))
|
||||
b.WriteString(fmt.Sprintf("👤 TG user: %s\r\n", tgID))
|
||||
b.WriteString(fmt.Sprintf("💬 Comment: %s\r\n", comment))
|
||||
fmt.Fprintf(&b, "📧 Email: `%s`\r\n", client_Email)
|
||||
fmt.Fprintf(&b, "🔗 Attached: %s\r\n", attached)
|
||||
fmt.Fprintf(&b, "📊 Traffic: %s\r\n", traffic)
|
||||
fmt.Fprintf(&b, "📅 Expire: %s\r\n", expiry)
|
||||
fmt.Fprintf(&b, "🔢 IP limit: %s\r\n", ipLimit)
|
||||
fmt.Fprintf(&b, "👤 TG user: %s\r\n", tgID)
|
||||
fmt.Fprintf(&b, "💬 Comment: %s\r\n", comment)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
@@ -216,7 +216,6 @@ func (t *Tgbot) buildSubscriptionURLs(email string) (string, string, error) {
|
||||
}
|
||||
subJsonURL = fmt.Sprintf("%s%s", subJsonURI, client.SubID)
|
||||
} else {
|
||||
|
||||
subJsonURL = fmt.Sprintf("%s://%s%s%s", scheme, host, subJsonPath, client.SubID)
|
||||
}
|
||||
|
||||
@@ -258,7 +257,7 @@ func (t *Tgbot) sendClientIndividualLinks(chatId int64, email string) {
|
||||
}
|
||||
|
||||
// Try to fetch raw subscription links. Prefer plain text response.
|
||||
req, err := http.NewRequest("GET", subURL, nil)
|
||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, subURL, nil)
|
||||
if err != nil {
|
||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation")+"\r\n"+err.Error())
|
||||
return
|
||||
@@ -376,7 +375,7 @@ func (t *Tgbot) sendClientQRLinks(chatId int64, email string) {
|
||||
|
||||
// Also generate a few individual links' QRs (first up to 5)
|
||||
subPageURL := subURL
|
||||
req, err := http.NewRequest("GET", subPageURL, nil)
|
||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, subPageURL, nil)
|
||||
if err == nil {
|
||||
req.Header.Set("Accept", "text/plain, */*;q=0.1")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
@@ -31,7 +31,7 @@ func (t *Tgbot) getInboundUsages() string {
|
||||
|
||||
clients, listErr := t.clientService.ListForInbound(nil, inbound.Id)
|
||||
if listErr == nil {
|
||||
info.WriteString(fmt.Sprintf("👥 Clients: %d\r\n", len(clients)))
|
||||
fmt.Fprintf(&info, "👥 Clients: %d\r\n", len(clients))
|
||||
}
|
||||
|
||||
if inbound.ExpiryTime == 0 {
|
||||
@@ -126,11 +126,9 @@ func (t *Tgbot) getInboundClientsFor(inboundID int, action string) (*telego.Inli
|
||||
for _, client := range clients {
|
||||
buttons = append(buttons, tu.InlineKeyboardButton(client.Email).WithCallbackData(t.encodeQuery(action+" "+client.Email)))
|
||||
}
|
||||
|
||||
} else {
|
||||
return nil, errors.New(t.I18nBot("tgbot.answers.getClientsFailed"))
|
||||
}
|
||||
|
||||
}
|
||||
cols := 0
|
||||
if len(buttons) < 6 {
|
||||
@@ -252,11 +250,9 @@ func (t *Tgbot) getInboundClients(id int) (*telego.InlineKeyboardMarkup, error)
|
||||
for _, client := range clients {
|
||||
buttons = append(buttons, tu.InlineKeyboardButton(client.Email).WithCallbackData(t.encodeQuery("client_get_usage "+client.Email)))
|
||||
}
|
||||
|
||||
} else {
|
||||
return nil, errors.New(t.I18nBot("tgbot.answers.getClientsFailed"))
|
||||
}
|
||||
|
||||
}
|
||||
cols := 0
|
||||
if len(buttons) < 6 {
|
||||
|
||||
@@ -49,7 +49,7 @@ func (t *Tgbot) SendBackupToAdmins() {
|
||||
return
|
||||
}
|
||||
for i, adminId := range adminIds {
|
||||
t.sendBackup(int64(adminId))
|
||||
t.sendBackup(adminId)
|
||||
// Add delay between sends to avoid Telegram rate limits
|
||||
if i < len(adminIds)-1 {
|
||||
time.Sleep(1 * time.Second)
|
||||
@@ -63,7 +63,7 @@ func (t *Tgbot) sendExhaustedToAdmins() {
|
||||
return
|
||||
}
|
||||
for _, adminId := range adminIds {
|
||||
t.getExhausted(int64(adminId))
|
||||
t.getExhausted(adminId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,6 @@ func (t *Tgbot) OnReceive() {
|
||||
userStateMgr.clear(message.Chat.ID)
|
||||
t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
|
||||
}
|
||||
|
||||
} else {
|
||||
if message.UsersShared != nil {
|
||||
if checkAdmin(message.From.ID) {
|
||||
@@ -167,7 +166,7 @@ func (t *Tgbot) OnReceive() {
|
||||
return nil
|
||||
}, th.AnyMessage())
|
||||
|
||||
h.Start()
|
||||
_ = h.Start()
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -205,7 +204,7 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo
|
||||
if isAdmin {
|
||||
t.searchClient(chatId, commandArgs[0])
|
||||
} else {
|
||||
t.getClientUsage(chatId, int64(message.From.ID), commandArgs[0])
|
||||
t.getClientUsage(chatId, message.From.ID, commandArgs[0])
|
||||
}
|
||||
} else {
|
||||
msg += t.I18nBot("tgbot.commands.usage")
|
||||
@@ -595,12 +594,12 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
|
||||
if traffic.ExpiryTime > 0 {
|
||||
if traffic.ExpiryTime-time.Now().Unix()*1000 < 0 {
|
||||
date = -int64(days * 24 * 60 * 60000)
|
||||
date = -(days * 24 * 60 * 60000)
|
||||
} else {
|
||||
date = traffic.ExpiryTime + int64(days*24*60*60000)
|
||||
date = traffic.ExpiryTime + days*24*60*60000
|
||||
}
|
||||
} else {
|
||||
date = traffic.ExpiryTime - int64(days*24*60*60000)
|
||||
date = traffic.ExpiryTime - days*24*60*60000
|
||||
}
|
||||
|
||||
}
|
||||
@@ -685,12 +684,12 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
var date int64
|
||||
if client_ExpiryTime > 0 {
|
||||
if client_ExpiryTime-time.Now().Unix()*1000 < 0 {
|
||||
date = -int64(days * 24 * 60 * 60000)
|
||||
date = -(days * 24 * 60 * 60000)
|
||||
} else {
|
||||
date = client_ExpiryTime + int64(days*24*60*60000)
|
||||
date = client_ExpiryTime + days*24*60*60000
|
||||
}
|
||||
} else {
|
||||
date = client_ExpiryTime - int64(days*24*60*60000)
|
||||
date = client_ExpiryTime - days*24*60*60000
|
||||
}
|
||||
client_ExpiryTime = date
|
||||
|
||||
@@ -1111,7 +1110,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
}
|
||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1458,7 +1456,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
case "get_sorted_traffic_usage_report":
|
||||
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
||||
emails, err := t.inboundService.GetAllEmails()
|
||||
|
||||
if err != nil {
|
||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user