diff --git a/cmd/rpdata-server/main.go b/cmd/rpdata-server/main.go index 480686c..057837c 100644 --- a/cmd/rpdata-server/main.go +++ b/cmd/rpdata-server/main.go @@ -44,10 +44,13 @@ func main() { go func() { err := serviceBundle.Logs.RefreshAllLogCharacters(context.Background()) if err != nil { - log.Println(err) + log.Println("Refresh Characters:", err) } - log.Println("Characters updated") + err = serviceBundle.Logs.FixImportDateBug(context.Background()) + if err != nil { + log.Println("Fix date bug:", err) + } }() go logListedChanges(serviceBundle.Changes) diff --git a/services/logs.go b/services/logs.go index 002a901..492959f 100644 --- a/services/logs.go +++ b/services/logs.go @@ -363,6 +363,114 @@ func (s *LogService) Delete(ctx context.Context, id string) (*models.Log, error) return log, nil } +func (s *LogService) FixImportDateBug(ctx context.Context) error { + start := time.Now() + + logs, err := s.logs.List(ctx, models.LogFilter{}) + if err != nil { + return err + } + + eg := errgroup.Group{} + for i := range logs { + l := logs[i] + + eg.Go(func() error { + return s.fixImportDateBug(ctx, *l) + }) + } + err = eg.Wait() + if err != nil { + return err + } + + log.Printf("Date import bug check finished: logs: %d, duration: %s", len(logs), time.Since(start)) + + return nil +} + +func (s *LogService) fixImportDateBug(ctx context.Context, l models.Log) error { + // Find the log's posts. + posts, err := s.ListPosts(ctx, &models.PostFilter{LogID: &l.ShortID}) + if err != nil { + return err + } + if len(posts) < 8 { + return nil + } + + // Find first action post + first := posts[0] + fi := 0 + for first.Kind != "action" && first.Kind != "text" { + fi++ + if fi >= len(posts) { + return nil + } + + first = posts[fi] + } + last := posts[len(posts)-1] + if first == last { + return nil + } + + // Stop here if this log probably isn't affected + if last.Time.Sub(first.Time) < time.Hour*72 { + return nil + } + + // Find the first post past midnight. + midnight := first + mi := fi + for i, post := range posts[fi+1:] { + if post.Time.Hour() < first.Time.Hour() { + midnight = post + mi = fi + 1 + i + break + } + } + if midnight == last { + return nil + } + + if len(posts[mi+1:]) == 1 { + return nil + } + + hits := 0 + prev := midnight + for _, offender := range posts[mi+1:] { + if offender.Time.Day() != prev.Time.Day() { + hits += 1 + } + + prev = offender + } + if hits < ((len(posts[mi+1:]) * 3) / 4) { + return nil + } + + for _, offender := range posts[mi+1:] { + ot := offender.Time.UTC() + mt := midnight.Time.UTC() + + y, m, d := mt.Date() + hr, mi, se, ns := ot.Hour(), ot.Minute(), ot.Second(), ot.Nanosecond() + + newTime := time.Date(y, m, d, hr, mi, se, ns, time.UTC) + + _, err := s.posts.Update(ctx, *offender, models.PostUpdate{Time: &newTime}) + if err != nil { + return err + } + } + + log.Printf("Fixed import date bug in %d posts in log %s", len(posts[mi+1:]), l.ID) + + return nil +} + func (s *LogService) RefreshAllLogCharacters(ctx context.Context) error { start := time.Now()