|
@ -11,7 +11,9 @@ import ( |
|
|
"git.aiterp.net/rpdata/api/services/parsers" |
|
|
"git.aiterp.net/rpdata/api/services/parsers" |
|
|
"golang.org/x/sync/errgroup" |
|
|
"golang.org/x/sync/errgroup" |
|
|
"log" |
|
|
"log" |
|
|
|
|
|
"sort" |
|
|
"strings" |
|
|
"strings" |
|
|
|
|
|
"sync" |
|
|
"time" |
|
|
"time" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
@ -21,6 +23,9 @@ type LogService struct { |
|
|
changeService *ChangeService |
|
|
changeService *ChangeService |
|
|
channelService *ChannelService |
|
|
channelService *ChannelService |
|
|
characterService *CharacterService |
|
|
characterService *CharacterService |
|
|
|
|
|
|
|
|
|
|
|
unknownNicks map[string]int |
|
|
|
|
|
unknownNicksMutex sync.Mutex |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (s *LogService) Find(ctx context.Context, id string) (*models.Log, error) { |
|
|
func (s *LogService) Find(ctx context.Context, id string) (*models.Log, error) { |
|
@ -56,6 +61,24 @@ func (s *LogService) ListPosts(ctx context.Context, filter *models.PostFilter) ( |
|
|
return s.posts.List(ctx, *filter) |
|
|
return s.posts.List(ctx, *filter) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *LogService) ListUnknownNicks() []*models.UnknownNick { |
|
|
|
|
|
s.unknownNicksMutex.Lock() |
|
|
|
|
|
nicks := make([]*models.UnknownNick, 0, len(s.unknownNicks)) |
|
|
|
|
|
for nick, score := range s.unknownNicks { |
|
|
|
|
|
nicks = append(nicks, &models.UnknownNick{ |
|
|
|
|
|
Nick: nick, |
|
|
|
|
|
Score: score, |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
s.unknownNicksMutex.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
sort.Slice(nicks, func(i, j int) bool { |
|
|
|
|
|
return nicks[i].Score > nicks[j].Score |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
return nicks |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
func (s *LogService) Create(ctx context.Context, title, description, channelName, eventName string, open bool) (*models.Log, error) { |
|
|
func (s *LogService) Create(ctx context.Context, title, description, channelName, eventName string, open bool) (*models.Log, error) { |
|
|
if channelName == "" { |
|
|
if channelName == "" { |
|
|
return nil, errors.New("channel name cannot be empty") |
|
|
return nil, errors.New("channel name cannot be empty") |
|
@ -280,8 +303,8 @@ func (s *LogService) SplitLog(ctx context.Context, logId string, startPostId str |
|
|
s.changeService.Submit(ctx, models.ChangeModelPost, "add", true, changekeys.Many(newLog, newPosts), newPosts) |
|
|
s.changeService.Submit(ctx, models.ChangeModelPost, "add", true, changekeys.Many(newLog, newPosts), newPosts) |
|
|
|
|
|
|
|
|
// Refresh character lists.
|
|
|
// Refresh character lists.
|
|
|
_, _ = s.refreshLogCharacters(ctx, *l, nil) |
|
|
|
|
|
newLog2, err := s.refreshLogCharacters(ctx, *newLog, nil) |
|
|
|
|
|
|
|
|
_, _ = s.refreshLogCharacters(ctx, *l, nil, false) |
|
|
|
|
|
newLog2, err := s.refreshLogCharacters(ctx, *newLog, nil, false) |
|
|
if err == nil { |
|
|
if err == nil { |
|
|
newLog = newLog2 |
|
|
newLog = newLog2 |
|
|
} |
|
|
} |
|
@ -339,7 +362,7 @@ func (s *LogService) MergeLogs(ctx context.Context, targetID string, sourceID st |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Refresh characters
|
|
|
// Refresh characters
|
|
|
target2, err := s.refreshLogCharacters(ctx, *target, nil) |
|
|
|
|
|
|
|
|
target2, err := s.refreshLogCharacters(ctx, *target, nil, false) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.Printf("Failed to update characters in log %s: %s", target.ID, err) |
|
|
log.Printf("Failed to update characters in log %s: %s", target.ID, err) |
|
|
} else { |
|
|
} else { |
|
@ -379,7 +402,7 @@ func (s *LogService) AddPost(ctx context.Context, logId string, time time.Time, |
|
|
return nil, err |
|
|
return nil, err |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
l2, err := s.refreshLogCharacters(ctx, *l, nil) |
|
|
|
|
|
|
|
|
l2, err := s.refreshLogCharacters(ctx, *l, nil, false) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.Printf("Failed to update characters in log %s: %s", l.ID, err) |
|
|
log.Printf("Failed to update characters in log %s: %s", l.ID, err) |
|
|
} else { |
|
|
} else { |
|
@ -416,7 +439,7 @@ func (s *LogService) EditPost(ctx context.Context, id string, update models.Post |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_, err = s.refreshLogCharacters(ctx, *l, nil) |
|
|
|
|
|
|
|
|
_, err = s.refreshLogCharacters(ctx, *l, nil, false) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.Printf("Failed to update characters in log %s: %s", l.ID, err) |
|
|
log.Printf("Failed to update characters in log %s: %s", l.ID, err) |
|
|
} |
|
|
} |
|
@ -483,7 +506,7 @@ func (s *LogService) DeletePost(ctx context.Context, id string) (*models.Post, e |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_, err = s.refreshLogCharacters(ctx, *l, nil) |
|
|
|
|
|
|
|
|
_, err = s.refreshLogCharacters(ctx, *l, nil, false) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.Printf("Failed to update characters in log %s: %s", l.ID, err) |
|
|
log.Printf("Failed to update characters in log %s: %s", l.ID, err) |
|
|
} |
|
|
} |
|
@ -638,12 +661,18 @@ func (s *LogService) RefreshAllLogCharacters(ctx context.Context) error { |
|
|
} |
|
|
} |
|
|
characterMap := s.makeCharacterMap(characters) |
|
|
characterMap := s.makeCharacterMap(characters) |
|
|
|
|
|
|
|
|
|
|
|
s.unknownNicksMutex.Lock() |
|
|
|
|
|
for key := range s.unknownNicks { |
|
|
|
|
|
delete(s.unknownNicks, key) |
|
|
|
|
|
} |
|
|
|
|
|
s.unknownNicksMutex.Unlock() |
|
|
|
|
|
|
|
|
eg := errgroup.Group{} |
|
|
eg := errgroup.Group{} |
|
|
for i := range logs { |
|
|
for i := range logs { |
|
|
l := logs[i] |
|
|
l := logs[i] |
|
|
|
|
|
|
|
|
eg.Go(func() error { |
|
|
eg.Go(func() error { |
|
|
_, err := s.refreshLogCharacters(ctx, *l, characterMap) |
|
|
|
|
|
|
|
|
_, err := s.refreshLogCharacters(ctx, *l, characterMap, true) |
|
|
return err |
|
|
return err |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
@ -652,16 +681,20 @@ func (s *LogService) RefreshAllLogCharacters(ctx context.Context) error { |
|
|
return err |
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
log.Printf("Full log character refresh complete; nicks: %d, logs: %d, duration: %s", len(characterMap), len(logs), time.Since(start)) |
|
|
|
|
|
|
|
|
s.unknownNicksMutex.Lock() |
|
|
|
|
|
unknownCount := len(s.unknownNicks) |
|
|
|
|
|
s.unknownNicksMutex.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
log.Printf("Full log character refresh complete; nicks: %d, unknowns: %d, logs: %d, duration: %s", len(characterMap), unknownCount, len(logs), time.Since(start)) |
|
|
|
|
|
|
|
|
return nil |
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (s *LogService) RefreshLogCharacters(ctx context.Context, log models.Log) (*models.Log, error) { |
|
|
func (s *LogService) RefreshLogCharacters(ctx context.Context, log models.Log) (*models.Log, error) { |
|
|
return s.refreshLogCharacters(ctx, log, nil) |
|
|
|
|
|
|
|
|
return s.refreshLogCharacters(ctx, log, nil, false) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (s *LogService) refreshLogCharacters(ctx context.Context, log models.Log, characterMap map[string]*models.Character) (*models.Log, error) { |
|
|
|
|
|
|
|
|
func (s *LogService) refreshLogCharacters(ctx context.Context, log models.Log, characterMap map[string]*models.Character, useUnknownNicks bool) (*models.Log, error) { |
|
|
posts, err := s.ListPosts(ctx, &models.PostFilter{LogID: &log.ShortID}) |
|
|
posts, err := s.ListPosts(ctx, &models.PostFilter{LogID: &log.ShortID}) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return &log, nil |
|
|
return &log, nil |
|
@ -718,9 +751,19 @@ func (s *LogService) refreshLogCharacters(ctx context.Context, log models.Log, c |
|
|
for key := range added { |
|
|
for key := range added { |
|
|
delete(added, key) |
|
|
delete(added, key) |
|
|
} |
|
|
} |
|
|
|
|
|
unknowned := make(map[string]bool) |
|
|
for _, nick := range nicks { |
|
|
for _, nick := range nicks { |
|
|
character := characterMap[nick] |
|
|
character := characterMap[nick] |
|
|
if character == nil || added[character.ID] { |
|
|
|
|
|
|
|
|
if character == nil { |
|
|
|
|
|
if useUnknownNicks && !unknowned[nick] { |
|
|
|
|
|
unknowned[nick] = true |
|
|
|
|
|
s.unknownNicksMutex.Lock() |
|
|
|
|
|
s.unknownNicks[nick]++ |
|
|
|
|
|
s.unknownNicksMutex.Unlock() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
continue |
|
|
|
|
|
} else if added[character.ID] { |
|
|
continue |
|
|
continue |
|
|
} |
|
|
} |
|
|
added[character.ID] = true |
|
|
added[character.ID] = true |
|
|