diff --git a/graph2/queries/log.go b/graph2/queries/log.go index 12b1efc..bb7403b 100644 --- a/graph2/queries/log.go +++ b/graph2/queries/log.go @@ -130,7 +130,7 @@ func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportI changes.Submit("Post", "add", token.UserID, true, changekeys.Many(result.Log, result.Posts), result.Posts) }() - log, err := logs.UpdateCharacters(result.Log) + log, err := logs.UpdateCharacters(result.Log, false) if err != nil { log = result.Log } diff --git a/graph2/queries/post.go b/graph2/queries/post.go index f4a62b5..9348fce 100644 --- a/graph2/queries/post.go +++ b/graph2/queries/post.go @@ -59,7 +59,7 @@ func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput return models.Post{}, err } - go logs.UpdateCharacters(log) + go logs.UpdateCharacters(log, false) go changes.Submit("Post", "add", token.UserID, true, changekeys.Many(log, post), post) return post, nil @@ -83,7 +83,7 @@ func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInp return } - logs.UpdateCharacters(log) + logs.UpdateCharacters(log, false) }() } @@ -154,7 +154,7 @@ func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemov return } - logs.UpdateCharacters(log) + logs.UpdateCharacters(log, false) changes.Submit("Post", "remove", token.UserID, true, changekeys.Many(log, post), post) }() diff --git a/models/logs/update-characters.go b/models/logs/update-characters.go index b665853..df32526 100644 --- a/models/logs/update-characters.go +++ b/models/logs/update-characters.go @@ -1,6 +1,7 @@ package logs import ( + "errors" "strings" "time" @@ -8,13 +9,14 @@ import ( "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) (models.Log, error) { +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 @@ -63,6 +65,10 @@ func UpdateCharacters(log models.Log) (models.Log, error) { characterIDs := make([]string, len(characters)) for i, char := range characters { + if char.Name == "(Hidden)" { + continue + } + characterIDs[i] = char.ID } @@ -73,6 +79,23 @@ func UpdateCharacters(log models.Log) (models.Log, error) { 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 } @@ -84,19 +107,31 @@ func RunFullUpdate() error { return err } + err = unknownnicks.BeginUpdate() + if err != nil { + return err + } + log := models.Log{} for iter.Next(&log) { - _, err = UpdateCharacters(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 } diff --git a/models/unknown-nick.go b/models/unknown-nick.go new file mode 100644 index 0000000..a74472f --- /dev/null +++ b/models/unknown-nick.go @@ -0,0 +1,7 @@ +package models + +// UnknownNick represents an unknown nick name. +type UnknownNick struct { + Nick string `bson:"_id"` + Weight int `bson:"weight"` +} diff --git a/models/unknownnicks/db.go b/models/unknownnicks/db.go new file mode 100644 index 0000000..49fe1a0 --- /dev/null +++ b/models/unknownnicks/db.go @@ -0,0 +1,37 @@ +package unknownnicks + +import ( + "log" + + "git.aiterp.net/rpdata/api/internal/store" + "git.aiterp.net/rpdata/api/models" + "github.com/globalsign/mgo" +) + +var collection *mgo.Collection + +func list(query interface{}, limit int) ([]models.UnknownNick, error) { + size := 64 + if limit > 0 { + size = limit + } + posts := make([]models.UnknownNick, 0, size) + + err := collection.Find(query).Limit(limit).Sort("weight").All(&posts) + if err != nil { + return nil, err + } + + return posts, nil +} + +func init() { + store.HandleInit(func(db *mgo.Database) { + collection = db.C("logbot3.unkownnicks") + + err := collection.EnsureIndexKey("weight") + if err != nil { + log.Fatalln("init logbot3.unkownnicks:", err) + } + }) +} diff --git a/models/unknownnicks/list.go b/models/unknownnicks/list.go new file mode 100644 index 0000000..f261ff1 --- /dev/null +++ b/models/unknownnicks/list.go @@ -0,0 +1,10 @@ +package unknownnicks + +import ( + "git.aiterp.net/rpdata/api/models" +) + +// List lists the top N unknown nicks. +func List(limit int) ([]models.UnknownNick, error) { + return list(nil, limit) +} diff --git a/models/unknownnicks/remove.go b/models/unknownnicks/remove.go new file mode 100644 index 0000000..a9c3894 --- /dev/null +++ b/models/unknownnicks/remove.go @@ -0,0 +1 @@ +package unknownnicks diff --git a/models/unknownnicks/update.go b/models/unknownnicks/update.go new file mode 100644 index 0000000..ea94a55 --- /dev/null +++ b/models/unknownnicks/update.go @@ -0,0 +1,55 @@ +package unknownnicks + +import ( + "sync" + + "github.com/globalsign/mgo/bson" +) + +var updateMutex sync.Mutex +var updateMap map[string]int + +// Add adds a nick as unknown. +func Add(nick string) { + updateMap[nick] = updateMap[nick] + 1 +} + +// BeginUpdate starts an add operation +func BeginUpdate() error { + updateMutex.Lock() + + _, err := collection.RemoveAll(bson.M{}) + if err != nil { + updateMutex.Unlock() + return err + } + + if updateMap == nil { + updateMap = make(map[string]int) + } + + for key := range updateMap { + delete(updateMap, key) + } + + return nil +} + +// CancelUpdate cancels an add operation +func CancelUpdate() { + updateMutex.Unlock() +} + +// CommitUpdate commits an add operation to the database. +func CommitUpdate() error { + defer updateMutex.Unlock() + + for nick, weight := range updateMap { + _, err := collection.UpsertId(nick, bson.M{"$set": bson.M{"weight": weight}}) + if err != nil { + return err + } + } + + return nil +}