package service import ( "context" "fmt" v1 "github.com/go-nunu/nunu-layout-advanced/api/v1" "github.com/go-nunu/nunu-layout-advanced/internal/model" "github.com/go-nunu/nunu-layout-advanced/internal/repository" "github.com/spf13/viper" "strconv" "strings" ) type GameShieldBackendService interface { GetGameShieldBackend(ctx context.Context, id int64) (*model.GameShieldBackend, error) GameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, int, error) AddGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, error) EditGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, error) DeleteGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, error) GetGameShieldRequired(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (*v1.GetGameShieldRequiredResponse, int, error) } func NewGameShieldBackendService( service *Service, gameShieldBackendRepository repository.GameShieldBackendRepository, gameShieldRepository repository.GameShieldRepository, crawlerService CrawlerService, gameShieldPublicIpService GameShieldPublicIpService, duedate DuedateService, formatter FormatterService, parser ParserService, required RequiredService, conf *viper.Viper, shieldService GameShieldService, ) GameShieldBackendService { return &gameShieldBackendService{ Service: service, gameShieldBackendRepository: gameShieldBackendRepository, gameShieldRepository: gameShieldRepository, crawlerService: crawlerService, gameShieldPublicIpService: gameShieldPublicIpService, duedate: duedate, formatter: formatter, parser: parser, required: required, Url: conf.GetString("crawler.Url"), shieldService: shieldService, } } type gameShieldBackendService struct { *Service gameShieldBackendRepository repository.GameShieldBackendRepository crawlerService CrawlerService gameShieldRepository repository.GameShieldRepository gameShieldPublicIpService GameShieldPublicIpService duedate DuedateService formatter FormatterService Url string parser ParserService required RequiredService shieldService GameShieldService } func (s *gameShieldBackendService) GetGameShieldRequired(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (*v1.GetGameShieldRequiredResponse, int, error) { var res v1.GetGameShieldRequiredResponse var err error var count int if req.Uid == 0 { return nil, 0, fmt.Errorf("uid is required") } res.ExpiredAt, err = s.duedate.NextDueDate(ctx, req.Uid, req.HostId) if err != nil { return nil, 0, err } gameShield, err := s.gameShieldRepository.GetGameShieldByHostId(ctx, req.HostId) if err != nil { return nil, 0, err } res.RuleId = gameShield.RuleId oldBackend, err := s.gameShieldBackendRepository.GetGameShieldBackendByHostId(ctx, req.HostId) if err != nil { return nil, 0, err } if len(oldBackend) != 0 { count = oldBackend[0].KeySort } OldBackend, err := s.formatter.OldFormat(ctx, &oldBackend) res.Backend, err = s.formatter.FormatBackendData(ctx, req, OldBackend, count) if err != nil { return nil, 0, err } res.Cookie, err = s.crawlerService.GetLoginCookie(ctx) if err != nil { return nil, 0, err } res.DunName = gameShield.DunName return &res, count, nil } func (s *gameShieldBackendService) GetGameShieldBackend(ctx context.Context, id int64) (*model.GameShieldBackend, error) { res, err := s.gameShieldBackendRepository.GetGameShieldBackendById(ctx, id) if err != nil { return nil, err } return res, nil } func (s *gameShieldBackendService) GameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, int, error) { require, count, err := s.GetGameShieldRequired(ctx, req) if err != nil { return "", 0, err } tokenUrl := s.Url + "admin/info/rule/edit?&__goadmin_edit_pk=" + strconv.Itoa(require.RuleId) + "_" + require.DunName tokens, err := s.crawlerService.GetFormTokens(ctx, tokenUrl, require.Cookie) if err != nil { return "", 0, err } formData := map[string]interface{}{ "app_name": require.DunName, "gateway_group_id": 4, "backend": require.Backend, "rule_id": require.RuleId, "expired_at": require.ExpiredAt, "max_device_count": 0, "sdk_args": "", "__go_admin_previous_": tokens["previous"], "__go_admin_t_": tokens["t"], } sendUrl := s.Url + "admin/edit/rule" respBody, err := s.crawlerService.SendFormData(ctx, sendUrl, require.Cookie, formData) if err != nil { return "", 0, err } // 解析响应内容中的 alert 消息 res, err := s.parser.ParseAlert(string(respBody)) if err != nil { return "", 0, err } if res != "" { return "", 0, fmt.Errorf(res) } KeyAndField, err := s.required.GetKeyAndField(ctx, require.DunName, "rule_id") if err != nil { return "", 0, err } timeBase, err := s.gameShieldRepository.GetGameShieldNextduedate(ctx, int64(req.Uid), req.HostId) if err != nil { return "", 0, err } timestampSec, err := strconv.ParseInt(timeBase, 10, 64) if err != nil { return "", 0, err } if err := s.gameShieldRepository.UpdateGameShieldByHostId(ctx, &model.GameShield{HostId: req.HostId, Key: KeyAndField.Key, ExpireTime: timestampSec}); err != nil { return "", 0, err } return res, count, nil } func (s *gameShieldBackendService) AddGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, error) { res, count, err := s.GameShieldBackend(ctx, req) if err != nil { return "", err } saveData, err := s.formatter.TidyFormatBackendData(ctx, req, count) if err != nil { return "", err } if err := s.SaveGameShieldBackend(ctx, saveData, req.HostId); err != nil { return "", err } return res, nil } func (s *gameShieldBackendService) EditGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, error) { for _, v := range req.Items { if v.Id == 0 { return "", fmt.Errorf("id 不能为空") } if err := s.gameShieldBackendRepository.EditGameShieldBackend(ctx, &v); err != nil { return "", err } } res, _, err := s.GameShieldBackend(ctx, req) if err != nil { return "", err } return res, nil } func (s *gameShieldBackendService) DeleteGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendArrayRequest) (string, error) { for _, v := range req.Items { if err := s.gameShieldBackendRepository.DeleteGameShieldBackend(ctx, int64(v.Id)); err != nil { return "", err } } res, _, err := s.GameShieldBackend(ctx, &v1.GameShieldBackendArrayRequest{HostId: req.HostId, Uid: req.Uid, Items: nil}) if err != nil { return "", err } return res, nil } func (s *gameShieldBackendService) SaveGameShieldBackend(ctx context.Context, req map[string]v1.SendGameShieldBackend, hostId int) error { for k, v := range req { parts := strings.Split(v.Addr[0], ":") keyName := strings.Split(k, "key")[1] key, err := strconv.Atoi(keyName) if err != nil { return err } if v.Type != "pc" { v.SdkIp = "127.0.0.1" } if err := s.gameShieldBackendRepository.AddGameShieldBackend(ctx, &model.GameShieldBackend{ HostId: hostId, KeySort: key, SourceMachineIP: parts[0], Protocol: v.Protocol, ProxyAddr: v.ProxyAddr, ConnectPort: parts[1], SdkIp: v.SdkIp, SdkPort: strconv.Itoa(v.SdkPort), Type: v.Type, // 可以添加其他字段 }); err != nil { return err } } return nil }