Added log character refresh function to log service.
the build was successful

This commit is contained in:
2019-08-07 12:26:59 +02:00
parent 60dcd8a80f
commit c0687d76ad
7 changed files with 145 additions and 13 deletions
+128 -4
View File
@@ -9,14 +9,18 @@ import (
"git.aiterp.net/rpdata/api/models/channels"
"git.aiterp.net/rpdata/api/repositories"
"git.aiterp.net/rpdata/api/services/parsers"
"golang.org/x/sync/errgroup"
"log"
"strings"
"time"
)
type LogService struct {
logs repositories.LogRepository
posts repositories.PostRepository
changeService *ChangeService
channelService *ChannelService
logs repositories.LogRepository
posts repositories.PostRepository
changeService *ChangeService
channelService *ChannelService
characterService *CharacterService
}
func (s *LogService) Find(ctx context.Context, id string) (*models.Log, error) {
@@ -339,3 +343,123 @@ func (s *LogService) Delete(ctx context.Context, id string) (*models.Log, error)
return log, nil
}
func (s *LogService) RefreshAllLogCharacters(ctx context.Context) error {
start := time.Now()
// Get all logs
logs, err := s.logs.List(ctx, models.LogFilter{})
if err != nil {
return err
}
// Check all characters now instead of later.
characters, err := s.characterService.List(ctx, models.CharacterFilter{})
if err != nil {
return err
}
characterMap := s.makeCharacterMap(characters)
eg := errgroup.Group{}
for i := range logs {
l := logs[i]
eg.Go(func() error {
return s.refreshLogCharacters(ctx, *l, characterMap)
})
}
err = eg.Wait()
if err != nil {
return err
}
log.Printf("Full log character refresh complete; nicks: %d, logs: %d, duration: %s", len(characterMap), len(logs), time.Since(start))
return nil
}
func (s *LogService) RefreshLogCharacters(ctx context.Context, log models.Log) error {
return s.refreshLogCharacters(ctx, log, nil)
}
func (s *LogService) refreshLogCharacters(ctx context.Context, log models.Log, characterMap map[string]*models.Character) error {
posts, err := s.ListPosts(ctx, &models.PostFilter{LogID: &log.ShortID})
if err != nil {
return nil
}
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)
}
}
if characterMap == nil {
characters, err := s.characterService.List(ctx, models.CharacterFilter{Nicks: nicks})
if err != nil {
return err
}
characterMap = s.makeCharacterMap(characters)
}
log.CharacterIDs = log.CharacterIDs[:0]
for key := range added {
delete(added, key)
}
for _, nick := range nicks {
character := characterMap[nick]
if character == nil || added[character.ID] {
continue
}
added[character.ID] = true
log.CharacterIDs = append(log.CharacterIDs, character.ID)
}
_, err = s.logs.Update(ctx, log, models.LogUpdate{CharacterIDs: log.CharacterIDs})
return err
}
func (s *LogService) makeCharacterMap(characters []*models.Character) map[string]*models.Character {
characterMap := make(map[string]*models.Character, len(characters)*3)
for _, character := range characters {
for _, nick := range character.Nicks {
characterMap[nick] = character
}
}
return characterMap
}
+5 -3
View File
@@ -32,9 +32,11 @@ func NewBundle(db database.Database) *Bundle {
changeService: bundle.Changes,
}
bundle.Logs = &LogService{
logs: db.Logs(),
posts: db.Posts(),
changeService: bundle.Changes,
logs: db.Logs(),
posts: db.Posts(),
changeService: bundle.Changes,
channelService: bundle.Channels,
characterService: bundle.Characters,
}
return bundle