GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

138 lines
3.2 KiB

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, unknowns map[string]int) (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
}
counts := make(map[string]int)
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]") || strings.HasSuffix(post.Nick, "|") {
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
counts[post.Nick]++
}
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 len(nicks) > 0 && unknowns != nil {
NickLoop:
for nick := range added {
if !added[nick] {
continue
}
for _, character := range characters {
if character.HasNick(nick) {
continue NickLoop
}
}
unknowns[nick] += counts[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
}
unknowns := make(map[string]int, 256)
log := models.Log{}
for iter.Next(&log) {
_, err = UpdateCharacters(log, unknowns)
if err != nil {
return err
}
}
err = iter.Err()
if err != nil {
return err
}
err = unknownnicks.Update(unknowns)
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()
}