From 5dd70bd64584104b31cb79ea6ba8e662af7e0682 Mon Sep 17 00:00:00 2001 From: Leigh MacDonald Date: Sun, 14 Apr 2024 21:48:58 -0600 Subject: [PATCH] Start of vote logging --- internal/domain/vote.go | 24 ++++++++++++++ internal/votes/vote_repository.go | 55 +++++++++++++++++++++++++++++++ pkg/logparse/consts.go | 2 ++ pkg/logparse/event.go | 51 ++++++++++++++++++++++++++++ pkg/logparse/log_parser.go | 14 +++++++- pkg/logparse/log_parser_test.go | 14 ++++++++ 6 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 internal/domain/vote.go create mode 100644 internal/votes/vote_repository.go diff --git a/internal/domain/vote.go b/internal/domain/vote.go new file mode 100644 index 000000000..e9ee13067 --- /dev/null +++ b/internal/domain/vote.go @@ -0,0 +1,24 @@ +package domain + +import ( + "context" + "github.com/gofrs/uuid/v5" + "github.com/leighmacdonald/steamid/v4/steamid" +) + +type VoteRepository interface { +} + +type VoteUsecase interface { + Start(ctx context.Context) +} + +type VoteResult struct { + ServerID int + MatchID uuid.UUID + SourceID steamid.SteamID + TargetID steamid.SteamID + Valid int + Name string + Proxy int +} diff --git a/internal/votes/vote_repository.go b/internal/votes/vote_repository.go new file mode 100644 index 000000000..38f00b23f --- /dev/null +++ b/internal/votes/vote_repository.go @@ -0,0 +1,55 @@ +package votes + +import ( + "context" + "github.com/leighmacdonald/gbans/internal/database" + "github.com/leighmacdonald/gbans/internal/domain" + "github.com/leighmacdonald/gbans/pkg/fp" + "github.com/leighmacdonald/gbans/pkg/log" + "github.com/leighmacdonald/gbans/pkg/logparse" + "log/slog" +) + +type voteRepository struct { + db database.Database + personUsecase domain.PersonUsecase + matchUsecase domain.MatchUsecase + broadcaster *fp.Broadcaster[logparse.EventType, logparse.ServerEvent], +} + +func NewVoteRepository(database database.Database, personUsecase domain.PersonUsecase, matchUsecase domain.MatchUsecase, broadcaster *fp.Broadcaster[logparse.EventType, logparse.ServerEvent]) domain.VoteRepository { + return &voteRepository{ + db: database, + personUsecase: personUsecase, + matchUsecase: matchUsecase, + broadcaster: broadcaster, + } +} + +func (r voteRepository) Start(ctx context.Context) { + eventChan := make(chan logparse.ServerEvent) + if errRegister := r.broadcaster.Consume(eventChan, logparse.VoteDetails); errRegister != nil { + slog.Warn("logWriter Tried to register duplicate reader channel", log.ErrAttr(errRegister)) + + return + } + + for { + select { + case <-ctx.Done(): + return + case evt := <-eventChan: + serverEvent, ok := evt.Event.(logparse.VoteKickDetailsEvt) + if !ok { + continue + } + + matchID, _ := r.matchUsecase.GetMatchIDFromServerID(evt.ServerID) + + } + } +} + +func (r voteRepository) AddVoteHistory() error { + +} diff --git a/pkg/logparse/consts.go b/pkg/logparse/consts.go index 8064401a9..abbcf629e 100644 --- a/pkg/logparse/consts.go +++ b/pkg/logparse/consts.go @@ -82,6 +82,8 @@ const ( ServerConfigExec EventType = 1009 SteamAuth EventType = 1010 MapStarted EventType = 1011 + + VoteDetails EventType = 1100 ) type CritType int diff --git a/pkg/logparse/event.go b/pkg/logparse/event.go index 23e8e85e8..1e3e33e96 100644 --- a/pkg/logparse/event.go +++ b/pkg/logparse/event.go @@ -6,6 +6,22 @@ import ( "github.com/leighmacdonald/steamid/v4/steamid" ) +type VoteOption string + +const ( + VoteOption1 VoteOption = "option1" // Yes + VoteOption2 VoteOption = "option2" // No + VoteOption3 VoteOption = "option3" + VoteOption4 VoteOption = "option4" + VoteOption5 VoteOption = "option5" +) + +type VoteReason int + +const ( + VoteReasonUnspecified VoteReason = 0 +) + // TimeStamp is the base event for all other events. It just contains a timestamp. type TimeStamp struct { CreatedOn time.Time `json:"created_on" mapstructure:"created_on"` @@ -88,6 +104,41 @@ type RCONEvt struct { Cmd string `json:"cmd" mapstructure:"cmd"` } +type VoteStartEvt struct { + TimeStamp + SourcePlayer + TargetName string +} + +type VoteCastEvt struct { + TimeStamp + SourcePlayer + TargetName string + Vote string +} + +type VoteFailEEvt struct { + TimeStamp + VoteType string + TargetName string + Reason string +} + +type VoteSuccessEvt struct { + TimeStamp + VoteType string + TargetName string +} + +type VoteKickDetailsEvt struct { + TimeStamp + SID steamid.SteamID `json:"sid" mapstructure:"source_id"` + SID2 steamid.SteamID `json:"sid2" mapstructure:"target_id"` + Valid int `json:"valid,omitempty" mapstructure:"valid"` + Name string `json:"name,omitempty" mapstructure:"name"` + Proxy int `json:"proxy,omitempty" mapstructure:"proxy"` +} + type MapStartedEvt struct { TimeStamp Map string `json:"map" mapstructure:"map"` diff --git a/pkg/logparse/log_parser.go b/pkg/logparse/log_parser.go index 554bbbe69..364d28c7c 100644 --- a/pkg/logparse/log_parser.go +++ b/pkg/logparse/log_parser.go @@ -340,6 +340,7 @@ func NewLogParser() *LogParser { // L 08/12/2023 - 08:47:05: Script not found (scripts/vscripts/mapspawn.nut) // L 08/12/2023 - 08:47:05: "OMEGATRONIC<893><[U:1:918446193]>" changed name to "butt cummer" // L 08/12/2023 - 08:48:07: "sig_etc_ratelimit_exclude_commands" = "" + {regexp.MustCompile(`^L\s(?P.+?):\s+Kick Vote details:\s+VoteInitiatorSteamID:\s+(?P.+?)\s+VoteTargetSteamID:\s+(?P.+?)\s+Valid:\s+(?P\d+)\s+BIndividual:\s+(\d+)\s+Name:\s+(?P.+?)\s+Proxy:\s+(?P\d+)`), VoteDetails}, {regexp.MustCompile(`^L\s(?P.+?):\s+[Ll]og file started\s+(?P.+?)$`), LogStart}, {regexp.MustCompile(`^L\s(?P.+?):\s+[Ll]og file closed.$`), LogStop}, {regexp.MustCompile(`^L\s(?P.+?):\s+server_cvar:\s+"(?P.+?)"\s"(?P.+?)"$`), CVAR}, @@ -664,6 +665,10 @@ func (p *LogParser) processKV(originalKVMap map[string]any) map[string]any { } switch key { + case "source_id": + newKVMap["source_id"] = steamid.New(value) + case "target_id": + newKVMap["target_id"] = steamid.New(value) case "created_on": var t time.Time if ParseDateTime(value, &t) { @@ -1146,6 +1151,13 @@ func (p *LogParser) Parse(logLine string) (*Results, error) { event = parsedEvent case SteamAuth: break + case VoteDetails: + var parsedEvent VoteKickDetailsEvt + if errUnmarshal = p.unmarshal(values, &parsedEvent); errUnmarshal != nil { + return nil, errUnmarshal + } + + event = parsedEvent case MapStarted: var parsedEvent MapStartedEvt if errUnmarshal = p.unmarshal(values, &parsedEvent); errUnmarshal != nil { @@ -1365,7 +1377,7 @@ func (p *LogParser) unmarshal(input any, output any) error { p.decodePlayerClass(), p.decodePos(), p.decodeSID3(), - + //p.decodeSourceSID(), p.decodePickupItem(), p.decodeWeapon(), ), diff --git a/pkg/logparse/log_parser_test.go b/pkg/logparse/log_parser_test.go index b3c109777..03dc54eae 100644 --- a/pkg/logparse/log_parser_test.go +++ b/pkg/logparse/log_parser_test.go @@ -744,6 +744,20 @@ func TestParseWMiniRoundStartEvt(t *testing.T) { }) } +func TestParseVoteDetails(t *testing.T) { + t.Parallel() + + testLogLine(t, `L 02/21/2021 - 06:22:23: Kick Vote details: VoteInitiatorSteamID: [U:1:0000001] VoteTargetSteamID: [U:1:0000002] Valid: 1 BIndividual: 1 Name: Disconnected Proxy: 0"`, + logparse.VoteKickDetailsEvt{ + TimeStamp: logparse.TimeStamp{CreatedOn: time.Date(2021, time.February, 21, 6, 22, 23, 0, time.UTC)}, + SID: steamid.New("[U:1:0000001]"), + SID2: steamid.New("[U:1:0000002]"), + Valid: 1, + Name: "Disconnected", + Proxy: 0, + }) +} + func TestParseMilkAttackEvt(t *testing.T) { t.Parallel()