diff --git a/go.mod b/go.mod index dd66b8d..8359422 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,10 @@ module caatsm go 1.22.5 require ( + github.com/Khan/genqlient v0.7.0 github.com/ThreeDotsLabs/watermill v1.3.5 github.com/ThreeDotsLabs/watermill-nats/v2 v2.0.2 - github.com/hasura/go-graphql-client v0.12.2 + github.com/google/uuid v1.6.0 github.com/nats-io/nats.go v1.34.0 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 @@ -16,17 +17,12 @@ require ( ) require ( - github.com/Khan/genqlient v0.7.0 // indirect - github.com/agnivade/levenshtein v1.1.1 // indirect - github.com/alexflint/go-arg v1.4.2 // indirect - github.com/alexflint/go-scalar v1.0.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/lithammer/shortuuid/v3 v3.0.7 // indirect @@ -49,16 +45,12 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.25.0 // indirect - golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.15.0 // indirect golang.org/x/tools v0.21.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - nhooyr.io/websocket v1.8.11 // indirect ) diff --git a/go.sum b/go.sum index b6c14cf..7274bfe 100644 --- a/go.sum +++ b/go.sum @@ -4,20 +4,14 @@ github.com/ThreeDotsLabs/watermill v1.3.5 h1:50JEPEhMGZQMh08ct0tfO1PsgMOAOhV3zxK github.com/ThreeDotsLabs/watermill v1.3.5/go.mod h1:O/u/Ptyrk5MPTxSeWM5vzTtZcZfxXfO9PK9eXTYiFZY= github.com/ThreeDotsLabs/watermill-nats/v2 v2.0.2 h1:/87LcdSzUEdCKbJptaLE987hOVOs852b+v5pukegggo= github.com/ThreeDotsLabs/watermill-nats/v2 v2.0.2/go.mod h1:uslCjpuzANBzawXYlwx2IDyGjpv9M42U2TQH6JMMQis= -github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= -github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/alexflint/go-arg v1.4.2 h1:lDWZAXxpAnZUq4qwb86p/3rIJJ2Li81EoMbTMujhVa0= -github.com/alexflint/go-arg v1.4.2/go.mod h1:9iRbDxne7LcR/GSvEr7ma++GLpdIU1zrghf2y2768kM= -github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= -github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= -github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -44,8 +38,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hasura/go-graphql-client v0.12.2 h1:cYeQK/CELtvFy2jvik4kG0b5UMGngQRYWTTXQkbGHDo= -github.com/hasura/go-graphql-client v0.12.2/go.mod h1:17qYcHgGSensF/wMAHKUhtMYaRZwZa3TyD7biqH9L3k= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -87,6 +79,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -101,7 +95,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -135,8 +128,6 @@ golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqR golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -150,8 +141,6 @@ golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -195,7 +184,6 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -203,5 +191,3 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= -nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= diff --git a/internal/parsers/aviation_parser.go b/internal/parsers/aviation_parser.go index 376abca..eb99f8d 100644 --- a/internal/parsers/aviation_parser.go +++ b/internal/parsers/aviation_parser.go @@ -27,7 +27,7 @@ var ( eetPattern = regexp.MustCompile(`(?s)(-?EET\/(?P(?:[A-Z]{4}\d{4}\s*)+))`) performancePattern = regexp.MustCompile(`(?s)-?PER\/(?P\w)`) reroutePattern = regexp.MustCompile(`(?m)RIF\/(?P.*)[A-Z]{3}\/`) - otherPatterns = []regexp.Regexp{*navPattern, *remarkPattern, *selPattern, *pbnPattern, *eetPattern, *performancePattern, *reroutePattern} + otherPatterns = []*regexp.Regexp{navPattern, remarkPattern, selPattern, pbnPattern, eetPattern, performancePattern, reroutePattern} ) type BodyParser struct { @@ -51,43 +51,27 @@ func (bp *BodyParser) SetBodyPatterns(patterns map[string]config.BodyConfig) { // Parse attempts to parse the body text using the configured patterns. func (bp *BodyParser) Parse(body string) (string, interface{}, error) { - // log := utils.Logger body = strings.TrimSpace(body) - // log.Info("Parsing body text", body) category := findCategory(body) if category == "" { - // log.Error("No category found in body text") return "", nil, fmt.Errorf("no category found in body text") } - patters := bp.GetBodyPatterns() - // log.Infof("body config [%s] %v\n", category, patters[category]) - if patterConfig := patters[category]; patterConfig.Patterns != nil { - - for _, p := range patterConfig.Patterns { - // log.Infof("Trying pattern %s\n%s\n", p.Comments, p.Pattern) - - re := p.Expression - match := re.FindStringSubmatch(body) - // log.Info("Match: ", match) - if match != nil { - // log.Infof("Matched: %v\n", match) - data := extractData(match, re) + if patternConfig, exists := bp.bodyPatterns[category]; exists && patternConfig.Patterns != nil { + for _, p := range patternConfig.Patterns { + if match := p.Expression.FindStringSubmatch(body); match != nil { + data := extractData(match, p.Expression) return createBodyData(data) } - // log.Infof("No match for pattern %s\n", p.Comments) } - } - return "", nil, fmt.Errorf(" no matching pattern found for body: %s", body) + return "", nil, fmt.Errorf("no matching pattern found for body: %s", body) } +// findCategory extracts the category from the body text using regex. func findCategory(body string) string { - match := categoryRegex.FindStringSubmatch(body) - // utils.Logger.Infof("Match: %v\n", match) - if match != nil { - groups := categoryRegex.SubexpNames() - for i, name := range groups { + if match := categoryRegex.FindStringSubmatch(body); match != nil { + for i, name := range categoryRegex.SubexpNames() { if i != 0 && name == "category" { return match[i] } @@ -96,7 +80,7 @@ func findCategory(body string) string { return "" } -// extractData extracts named groups from the regex match. +// extractData extracts named groups from the regex match and returns them as a map. func extractData(match []string, re *regexp.Regexp) map[string]string { data := make(map[string]string) for i, name := range re.SubexpNames() { @@ -109,8 +93,7 @@ func extractData(match []string, re *regexp.Regexp) map[string]string { // createBodyData creates the appropriate domain object based on the type of message. func createBodyData(data map[string]string) (string, interface{}, error) { - category := data["category"] - switch data["category"] { + switch category := data["category"]; category { case "ARR": return category, &domain.ARR{ Category: data["category"], @@ -156,64 +139,47 @@ func createBodyData(data map[string]string) (string, interface{}, error) { Remarks: otherData["remark"], }, nil default: - return category, nil, fmt.Errorf("invalid message type: %s", category) + return category, nil, fmt.Errorf("cann't parse : %s", category) } } -// Parse parses the raw text message and returns a ParsedMessage. // Parse parses the raw text message and returns a ParsedMessage. func Parse(rawText string) (*domain.ParsedMessage, error) { - // Parse the header of the message message, err := ParseHeader(rawText) if err != nil { return nil, err } - // Initialize a new body parser bodyParser := NewBodyParser() - - // Parse the body and footer of the message category, bodyData, err := bodyParser.Parse(message.BodyAndFooter) - message.Category = category + message.ParsedAt = time.Now() if err != nil { - // Return the message with the parsed header and the error - message.ParsedAt = time.Now() return &message, err } - // Set the parsed time to the current time - message.ParsedAt = time.Now() - - // Assign the parsed body data to the message message.BodyData = bodyData - - // Return the fully parsed message return &message, nil } -// removeEmptyLines removes empty lines from a given text. +// clean removes empty lines from a given text and extracts the body only. func clean(text string) string { cleanedText := emptyLineRemove.ReplaceAllString(text, "") cleanText := strings.ReplaceAll(cleanedText, "\n\n", "\n") - // if bodyOnly != nil { - match := bodyOnly.FindStringSubmatch(cleanText) - if len(match) > 1 { - bodyOnly := match[2] - if bodyOnly[len(bodyOnly)-1] == '\n' { - return bodyOnly[:len(bodyOnly)-1] + if match := bodyOnly.FindStringSubmatch(cleanText); len(match) > 1 { + bodyContent := match[2] + if bodyContent[len(bodyContent)-1] == '\n' { + return bodyContent[:len(bodyContent)-1] } - return bodyOnly + return bodyContent } - // } return "" } -// parseHeader parses the header of the message and returns a ParsedMessage struct. +// ParseHeader parses the header of the message and returns a ParsedMessage struct. func ParseHeader(fullMessage string) (domain.ParsedMessage, error) { fullMessage = clean(fullMessage) - // fullMessage = strings.TrimSpace(fullMessage) lines := strings.Split(fullMessage, "\n") _, messageID, dateTime, err := parseStartIndicator(lines[0]) @@ -221,16 +187,10 @@ func ParseHeader(fullMessage string) (domain.ParsedMessage, error) { return domain.ParsedMessage{}, err } - // priorityIndicator, primaryAddress, err := parsePriorityAndPrimary(lines[1]) - // if err != nil { - // return domain.ParsedMessage{}, err - // } priorityIndicator, primaryAddress := parsePriorityAndPrimary(lines[1]) - secondaryAddresses, originator, originatorDateTime, bodyAndFooter := parseRemainingLines(lines[2:]) return domain.ParsedMessage{ - // StartIndicator: startIndicator, MessageID: messageID, DateTime: dateTime, PriorityIndicator: priorityIndicator, @@ -306,29 +266,26 @@ func parseRemainingLines(lines []string) ([]string, string, string, string) { return secondaryAddresses, originator, originatorDateTime, bodyAndFooter.String() } +// getOriginator extracts originator details from a line of text. func getOriginator(line string) (string, string) { match := originator.FindStringSubmatch(line) if len(match) >= 3 { return match[1], match[2] } return "", "" - } +// parseOther parses additional information from the message body. func parseOther(text string) map[string]string { - // fmt.Printf("Parsing other: %s\n", text) data := make(map[string]string) for _, re := range otherPatterns { - match := re.FindStringSubmatch(text) - if len(match) > 0 { // Corrected condition - // fmt.Println("Matched: ", match) + if match := re.FindStringSubmatch(text); len(match) > 0 { for i, name := range re.SubexpNames() { - // fmt.Printf("index: %d, name: %s\n", i, name) if i != 0 && name != "" { data[name] = strings.TrimSpace(match[i]) } } } } - return data // Return the data map instead of nil + return data }