This commit is contained in:
+128
-4
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user