Files
s-ui/backend/service/inbounds.go
T
2025-01-05 21:52:50 +01:00

263 lines
6.3 KiB
Go

package service
import (
"encoding/json"
"os"
"s-ui/database"
"s-ui/database/model"
"s-ui/util"
"s-ui/util/common"
"strings"
"gorm.io/gorm"
)
type InboundService struct{}
func (s *InboundService) Get(ids string) (*[]map[string]interface{}, error) {
if ids == "" {
return s.GetAll()
}
return s.getById(ids)
}
func (s *InboundService) getById(ids string) (*[]map[string]interface{}, error) {
var inbound []model.Inbound
var result []map[string]interface{}
db := database.GetDB()
err := db.Model(model.Inbound{}).Where("id in ?", strings.Split(ids, ",")).Scan(&inbound).Error
if err != nil {
return nil, err
}
for _, inb := range inbound {
inbData, err := inb.MarshalFull()
if err != nil {
return nil, err
}
result = append(result, *inbData)
}
return &result, nil
}
func (s *InboundService) GetAll() (*[]map[string]interface{}, error) {
db := database.GetDB()
inbounds := []model.Inbound{}
err := db.Model(model.Inbound{}).Scan(&inbounds).Error
if err != nil {
return nil, err
}
var data []map[string]interface{}
for _, inbound := range inbounds {
inbData := map[string]interface{}{
"id": inbound.Id,
"type": inbound.Type,
"tag": inbound.Tag,
"tls_id": inbound.TlsId,
}
if inbound.Options != nil {
var restFields map[string]json.RawMessage
if err := json.Unmarshal(inbound.Options, &restFields); err != nil {
return nil, err
}
inbData["listen"] = restFields["listen"]
inbData["listen_port"] = restFields["listen_port"]
}
data = append(data, inbData)
}
return &data, nil
}
func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error) {
db := database.GetDB()
inbounds := []*model.Inbound{}
err := db.Model(model.Inbound{}).Where("id in ?", ids).Scan(&inbounds).Error
if err != nil {
return nil, err
}
return inbounds, nil
}
func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, hostname string) (uint, error) {
var err error
var id uint
switch act {
case "new", "edit":
var inbound model.Inbound
err = inbound.UnmarshalJSON(data)
if err != nil {
return 0, err
}
id = inbound.Id
if inbound.TlsId > 0 {
err = tx.Model(model.Tls{}).Where("id = ?", inbound.TlsId).Find(&inbound.Tls).Error
if err != nil {
return 0, err
}
}
if corePtr.IsRunning() {
if act == "edit" {
var oldTag string
err = tx.Model(model.Inbound{}).Select("tag").Where("id = ?", inbound.Id).Find(&oldTag).Error
if err != nil {
return 0, err
}
err = corePtr.RemoveInbound(oldTag)
if err != nil && err != os.ErrInvalid {
return 0, err
}
}
inboundConfig, err := inbound.MarshalJSON()
if err != nil {
return 0, err
}
inboundConfig, err = s.addUsers(tx, inboundConfig, inbound.Id, inbound.Type)
if err != nil {
return 0, err
}
err = corePtr.AddInbound(inboundConfig)
if err != nil {
return 0, err
}
}
err = util.FillOutJson(&inbound, hostname)
if err != nil {
return 0, err
}
err = tx.Save(&inbound).Error
if err != nil {
return 0, err
}
case "del":
var tag string
err = json.Unmarshal(data, &tag)
if err != nil {
return 0, err
}
if corePtr.IsRunning() {
err = corePtr.RemoveInbound(tag)
if err != nil && err != os.ErrInvalid {
return 0, err
}
}
err = tx.Model(model.Inbound{}).Select("id").Where("tag = ?", tag).Scan(&id).Error
if err != nil {
return 0, err
}
err = tx.Where("tag = ?", tag).Delete(model.Inbound{}).Error
if err != nil {
return 0, err
}
default:
return 0, common.NewErrorf("unknown action: %s", act)
}
return id, nil
}
func (s *InboundService) UpdateOutJsons(tx *gorm.DB, inboundIds []uint, hostname string) error {
var inbounds []model.Inbound
err := tx.Model(model.Inbound{}).Preload("Tls").Where("id in ?", inboundIds).Find(&inbounds).Error
if err != nil {
return err
}
for _, inbound := range inbounds {
err = util.FillOutJson(&inbound, hostname)
if err != nil {
return err
}
err = tx.Model(model.Inbound{}).Where("tag = ?", inbound.Tag).Update("out_json", inbound.OutJson).Error
if err != nil {
return err
}
}
return nil
}
func (s *InboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error) {
var inboundsJson []json.RawMessage
var inbounds []*model.Inbound
err := db.Model(model.Inbound{}).Preload("Tls").Find(&inbounds).Error
if err != nil {
return nil, err
}
for _, inbound := range inbounds {
inboundJson, err := inbound.MarshalJSON()
if err != nil {
return nil, err
}
inboundJson, err = s.addUsers(db, inboundJson, inbound.Id, inbound.Type)
if err != nil {
return nil, err
}
inboundsJson = append(inboundsJson, inboundJson)
}
return inboundsJson, nil
}
func (s *InboundService) addUsers(db *gorm.DB, inboundJson []byte, inboundId uint, inboundType string) ([]byte, error) {
switch inboundType {
case "mixed", "socks", "http", "shadowsocks", "vmess", "trojan", "naive", "hysteria", "shadowtls", "tuic", "hysteria2", "vless":
break
default:
return inboundJson, nil
}
var inbound map[string]interface{}
err := json.Unmarshal(inboundJson, &inbound)
if err != nil {
return nil, err
}
if inboundType == "shadowsocks" {
method, _ := inbound["method"].(string)
if method == "2022-blake3-aes-128-gcm" {
inboundType = "shadowsocks16"
}
}
var users []string
err = db.Raw(`SELECT json_extract(clients.config, ?)
FROM clients, json_each(clients.inbounds) as je
WHERE clients.enable = true AND je.value = ?;`,
"$."+inboundType, inboundId).Scan(&users).Error
if err != nil {
return nil, err
}
var usersJson []json.RawMessage
for _, user := range users {
usersJson = append(usersJson, json.RawMessage(user))
}
inbound["users"] = usersJson
return json.Marshal(inbound)
}
func (s *InboundService) RestartInbounds(tx *gorm.DB, ids []uint) error {
var inbounds []*model.Inbound
err := tx.Model(model.Inbound{}).Preload("Tls").Where("id in ?", ids).Find(&inbounds).Error
if err != nil {
return err
}
for _, inbound := range inbounds {
err = corePtr.RemoveInbound(inbound.Tag)
if err != nil && err != os.ErrInvalid {
return err
}
inboundConfig, err := inbound.MarshalJSON()
if err != nil {
return err
}
inboundConfig, err = s.addUsers(tx, inboundConfig, inbound.Id, inbound.Type)
err = corePtr.AddInbound(inboundConfig)
if err != nil {
return err
}
}
return nil
}