mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-04 05:02:06 +03:00
7c84ca9689
Invariant: a client whose stats row is switched off is served by no local runtime of any inbound it is attached to. client_traffics is email-keyed, and AddClientStat re-points its inbound_id at the last inbound attached, yet the runtime push builder and the MTProto, TUIC and AmneziaWG desired- instance builders looked the row up by inbound_id. On every other inbound of a multi-inbound client the depletion filter saw nothing, so a depleted client stayed served there whenever its settings entry still read enabled - the state the stale settings writes left in existing databases. All four now resolve the flag through trafficDisabledEmails, keyed by the emails the inbound actually lists. GetXrayConfig already backfills sibling rows by email (backfillClientStats) and is unchanged.
78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
|
"github.com/mhsanaei/3x-ui/v3/internal/logger"
|
|
"github.com/mhsanaei/3x-ui/v3/internal/tuic"
|
|
)
|
|
|
|
func (s *InboundService) DesiredTuicInstances() ([]tuic.Instance, error) {
|
|
db := database.GetDB()
|
|
var inbounds []*model.Inbound
|
|
err := db.Model(model.Inbound{}).
|
|
Where("protocol = ? AND enable = ? AND node_id IS NULL", model.TUIC, true).
|
|
Find(&inbounds).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(inbounds) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
instances := make([]tuic.Instance, 0, len(inbounds))
|
|
for _, ib := range inbounds {
|
|
inst, ok := tuic.InstanceFromInbound(ib)
|
|
if !ok {
|
|
continue
|
|
}
|
|
instances = append(instances, inst)
|
|
}
|
|
emails := make([]string, 0)
|
|
for _, inst := range instances {
|
|
for _, e := range inst.Clients {
|
|
emails = append(emails, e.Email)
|
|
}
|
|
}
|
|
disabled, err := trafficDisabledEmails(db, emails)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
served := instances[:0]
|
|
for _, inst := range instances {
|
|
kept := make([]tuic.TuicClientSettings, 0, len(inst.Clients))
|
|
for _, e := range inst.Clients {
|
|
if _, off := disabled[e.Email]; !off {
|
|
kept = append(kept, e)
|
|
}
|
|
}
|
|
inst.Clients = kept
|
|
if len(kept) > 0 {
|
|
served = append(served, inst)
|
|
}
|
|
}
|
|
return served, nil
|
|
}
|
|
|
|
func (s *InboundService) applyLocalTuic(inboundId int) {
|
|
inbound, err := s.GetInbound(inboundId)
|
|
if err != nil || inbound == nil || inbound.Protocol != model.TUIC || inbound.NodeID != nil {
|
|
return
|
|
}
|
|
rt, err := s.runtimeFor(inbound)
|
|
if err != nil {
|
|
return
|
|
}
|
|
payload := inbound
|
|
if inbound.Enable {
|
|
if built, bErr := s.buildInboundForLocalRuntime(database.GetDB(), inbound); bErr == nil {
|
|
payload = built
|
|
}
|
|
}
|
|
if err := rt.UpdateInbound(context.Background(), inbound, payload); err != nil {
|
|
logger.Debug("tuic: immediate client apply failed for inbound", inboundId, ":", err)
|
|
}
|
|
}
|