diff --git a/internal/config/config.go b/internal/config/config.go index 7e7de22..998cb97 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -98,6 +98,8 @@ const ( // - other: any other relevant information, starting with three uppercase letters followed by a forward slash and zero or more characters (including newline) fplPatternString = `\((?P[A-Z]{3})-(?P[A-Z]+\d+)-(?P[A-Z]{2})\n-(?P[A-Z]+\d+\/?[A-Z]?)\n?-(?P.*)\n?-(?P[A-Z]{4})(?P\d{4})\n?-(?P[A-Z]+\d+)(?P[A-Z0-9]+)\s+(?P(.|\n)+)\n-(?P[A-Z]{4})(?P\d{4})\s?(?P(\s[A-Z]{4})+)\n?-([A-Z]{3}\/(?:[A-Z]{4}\d{4}\s?)+)?(?P(?m)[A-Z]{3}\/(.|\n)*)\)$` + + cnlPatternString = `^\((?P[A-Z]{3})-(?P\w+\d+)-?(?P[A-Z]{4})?-?(?[A-Z]{4})\)$` ) // Initialize the bodyPatterns map @@ -129,6 +131,15 @@ var bodyPatterns = map[string]BodyConfig{ }, }, }, + "CNL": { + Patterns: []PatternConfig{ + { + Pattern: cnlPatternString, + Comments: "Pattern for CNL message", + Expression: regexp.MustCompile(cnlPatternString), + }, + }, + }, } func GetBodyPatterns() map[string]BodyConfig { diff --git a/internal/domain/cnl.go b/internal/domain/cnl.go new file mode 100644 index 0000000..d44fe8f --- /dev/null +++ b/internal/domain/cnl.go @@ -0,0 +1,29 @@ +package domain + +import "fmt" + +// CNL represents the structure of a cancellation (CNL) message +type CNL struct { + Category string `json:"category"` // 电报类别 (Message Category) + AircraftID string `json:"aircraft_id"` // 航空器识别标志 (Aircraft Identification) + DepartureAirport string `json:"departure_airport"` // 起飞机场 (Departure Airport) + DestinationAirport string `json:"destination_airport"` // 到达机场 (Destination Airport) + OtherInfo string `json:"other_info,omitempty"` // 其他信息 (optional) (Other Information) +} + +// Validate validates the CNL struct fields +func (c *CNL) Validate() error { + if c.Category == "" { + return fmt.Errorf("telegram category is required") + } + if c.AircraftID == "" { + return fmt.Errorf("aircraft id is required") + } + if c.DepartureAirport == "" { + return fmt.Errorf("departure airport is required") + } + if c.DestinationAirport == "" { + return fmt.Errorf("destination airport is required") + } + return nil +} diff --git a/internal/parsers/aviation_parser.go b/internal/parsers/aviation_parser.go index 39ecb68..b99a3b9 100644 --- a/internal/parsers/aviation_parser.go +++ b/internal/parsers/aviation_parser.go @@ -119,6 +119,13 @@ func (bp *BodyParser) createBodyData(data map[string]string) (string, interface{ DepartureTime: data["departure_time"], Destination: data["arrival"], }, nil + case "CNL": + return category, &domain.CNL{ + Category: data["category"], + AircraftID: data["number"], + DepartureAirport: data["departure"], + DestinationAirport: data["destination"], + }, nil case "FPL": otherData := parseOther(data["other"]) return category, &domain.FPL{ diff --git a/internal/parsers/aviation_parser_test.go b/internal/parsers/aviation_parser_test.go index 78571c0..5e0f568 100644 --- a/internal/parsers/aviation_parser_test.go +++ b/internal/parsers/aviation_parser_test.go @@ -213,6 +213,21 @@ NNNN` }) }) + Context("with CNL body", func() { + // parser := NewBodyParser() + It("should parse the body correctly", func() { + body := "(CNL-YZR7979-ZSPD-ZBTJ)" + parser := NewBodyParser(body) + category, parsedBody, err := parser.Parse() + Expect(err).ToNot(HaveOccurred()) + Expect(parsedBody).ToNot(BeNil()) + Expect(category).To(Equal("CNL")) + Expect(parsedBody).To(BeAssignableToTypeOf(&domain.CNL{})) + cnlMessage := parsedBody.(*domain.CNL) + Expect(cnlMessage.AircraftID).To(Equal("YZR7979")) + }) + }) + }) Describe("Parse whole real message", func() {