package logs import ( "errors" "strings" "time" "git.aiterp.net/rpdata/api/internal/task" "git.aiterp.net/rpdata/api/models" "git.aiterp.net/rpdata/api/models/characters" "git.aiterp.net/rpdata/api/models/posts" "git.aiterp.net/rpdata/api/models/unknownnicks" "github.com/globalsign/mgo/bson" ) var updateTask = task.New(time.Second*60, RunFullUpdate) // UpdateCharacters updates the characters for the given log. func UpdateCharacters(log models.Log, addUnknowns bool) (models.Log, error) { posts, err := posts.List(&posts.Filter{LogID: &log.ShortID, Kind: []string{"action", "text", "chars"}, Limit: 0}) if err != nil { return models.Log{}, err } added := make(map[string]bool) removed := make(map[string]bool) for _, post := range posts { if post.Kind == "text" || post.Kind == "action" { if strings.HasPrefix(post.Text, "(") || strings.Contains(post.Nick, "(") || strings.Contains(post.Nick, "[E]") { continue } // Clean up the nick (remove possessive suffix, comma, formatting stuff) if strings.HasSuffix(post.Nick, "'s") || strings.HasSuffix(post.Nick, "`s") { post.Nick = post.Nick[:len(post.Nick)-2] } else if strings.HasSuffix(post.Nick, "'") || strings.HasSuffix(post.Nick, "`") || strings.HasSuffix(post.Nick, ",") || strings.HasSuffix(post.Nick, "\x0f") { post.Nick = post.Nick[:len(post.Nick)-1] } added[post.Nick] = true } if post.Kind == "chars" { tokens := strings.Fields(post.Text) for _, token := range tokens { if strings.HasPrefix(token, "-") { removed[token[1:]] = true } else { added[strings.Replace(token, "+", "", 1)] = true } } } } nicks := make([]string, 0, len(added)) for nick := range added { if added[nick] && !removed[nick] { nicks = append(nicks, nick) } } characters, err := characters.List(&characters.Filter{Nicks: nicks}) if err != nil { return models.Log{}, err } characterIDs := make([]string, len(characters)) for i, char := range characters { if char.Name == "(Hidden)" { continue } characterIDs[i] = char.ID } err = collection.UpdateId(log.ID, bson.M{"$set": bson.M{"characterIds": characterIDs}}) if err != nil { return models.Log{}, err } log.CharacterIDs = characterIDs if addUnknowns { NickLoop: for nick := range added { if !added[nick] { continue } for _, character := range characters { if character.HasNick(nick) { continue NickLoop } } unknownnicks.Add(nick) } } return log, nil } // RunFullUpdate runs a full update on all logs. func RunFullUpdate() error { iter := iter(bson.M{}, 0) err := iter.Err() if err != nil { return err } err = unknownnicks.BeginUpdate() if err != nil { return err } log := models.Log{} for iter.Next(&log) { _, err = UpdateCharacters(log, true) if err != nil { unknownnicks.CancelUpdate() return err } } err = iter.Err() if err != nil { unknownnicks.CancelUpdate() return err } err = unknownnicks.CommitUpdate() if err != nil { return errors.New("Failed to commit unknown nicks update: " + err.Error()) } return nil } // ScheduleFullUpdate runs a full character update within the next 60 seconds. func ScheduleFullUpdate() { updateTask.Schedule() }