package mirclike import ( "errors" "strconv" "strings" "time" "git.aiterp.net/rpdata/api/models" ) // ErrNotPost is returned by parsePost if the line is empty or not a post. var ErrNotPost = errors.New("not a post") // ParsePost parses a post from a mirc-like line. If the previous post is included (it can be empty), it will be used // to determine whether midnight has passed. func ParsePost(line string, date time.Time, prev models.Post) (models.Post, error) { // Do basic validation line = strings.Trim(line, "  \t\n\r") if len(line) == 0 || !strings.HasPrefix(line, "[") { return models.Post{}, ErrNotPost } // Parse timestamp tsEndIndex := strings.IndexByte(line, ']') if tsEndIndex == -1 || len(line) < tsEndIndex+5 { return models.Post{}, ErrNotPost } tsStr := line[1:tsEndIndex] tsSplit := strings.Split(tsStr, ":") tsUnits := make([]int, len(tsSplit)) if len(tsSplit) < 2 { return models.Post{}, ErrNotPost } for i := range tsSplit { n, err := strconv.Atoi(tsSplit[i]) if err != nil { return models.Post{}, ErrNotPost } tsUnits[i] = n } if len(tsUnits) == 2 { tsUnits = append(tsUnits, 0) } // Determine timestamp from parsed data and previous post. ts := time.Date(date.Year(), date.Month(), date.Day(), tsUnits[0], tsUnits[1], tsUnits[2], 0, date.Location()) if !prev.Time.IsZero() && prev.Time.Sub(ts) > 30*time.Minute { ts = time.Date(prev.Time.Year(), prev.Time.Month(), prev.Time.Day()+1, tsUnits[0], tsUnits[1], tsUnits[2], 0, date.Location()) } if line[tsEndIndex+2] == '*' { split := strings.SplitN(line[tsEndIndex+4:], " ", 2) if len(split) == 1 { return models.Post{}, ErrNotPost } post := models.Post{ ID: "UNASSIGNED", LogID: "UNASSIGNED", Time: ts, Kind: "action", Nick: strings.TrimLeft(split[0], "+@!~"), Text: split[1], Position: prev.Position + 1, } if post.Nick[0] == '=' { post.Kind = "scene" } return post, nil } else if line[tsEndIndex+2] == '<' { split := strings.SplitN(line[tsEndIndex+2:], " ", 2) if len(split) == 1 { return models.Post{}, ErrNotPost } post := models.Post{ ID: "UNASSIGNED", LogID: "UNASSIGNED", Time: ts, Kind: "text", Nick: strings.TrimLeft(split[0][1:len(split[0])-1], "+@!~"), Text: split[1], Position: prev.Position + 1, } if post.Nick[0] == '=' { post.Kind = "scene" } return post, nil } else { return models.Post{}, ErrNotPost } }