GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.2 KiB

  1. package logs
  2. import (
  3. "errors"
  4. "strings"
  5. "time"
  6. "git.aiterp.net/rpdata/api/internal/task"
  7. "git.aiterp.net/rpdata/api/models"
  8. "git.aiterp.net/rpdata/api/models/characters"
  9. "git.aiterp.net/rpdata/api/models/posts"
  10. "git.aiterp.net/rpdata/api/models/unknownnicks"
  11. "github.com/globalsign/mgo/bson"
  12. )
  13. var updateTask = task.New(time.Second*60, RunFullUpdate)
  14. // UpdateCharacters updates the characters for the given log.
  15. func UpdateCharacters(log models.Log, unknowns map[string]int) (models.Log, error) {
  16. posts, err := posts.List(&posts.Filter{LogID: &log.ShortID, Kind: []string{"action", "text", "chars"}, Limit: 0})
  17. if err != nil {
  18. return models.Log{}, err
  19. }
  20. counts := make(map[string]int)
  21. added := make(map[string]bool)
  22. removed := make(map[string]bool)
  23. for _, post := range posts {
  24. if post.Kind == "text" || post.Kind == "action" {
  25. if strings.HasPrefix(post.Text, "(") || strings.Contains(post.Nick, "(") || strings.Contains(post.Nick, "[E]") || strings.HasSuffix(post.Nick, "|") {
  26. continue
  27. }
  28. // Clean up the nick (remove possessive suffix, comma, formatting stuff)
  29. if strings.HasSuffix(post.Nick, "'s") || strings.HasSuffix(post.Nick, "`s") {
  30. post.Nick = post.Nick[:len(post.Nick)-2]
  31. } else if strings.HasSuffix(post.Nick, "'") || strings.HasSuffix(post.Nick, "`") || strings.HasSuffix(post.Nick, ",") || strings.HasSuffix(post.Nick, "\x0f") {
  32. post.Nick = post.Nick[:len(post.Nick)-1]
  33. }
  34. added[post.Nick] = true
  35. counts[post.Nick]++
  36. }
  37. if post.Kind == "chars" {
  38. tokens := strings.Fields(post.Text)
  39. for _, token := range tokens {
  40. if strings.HasPrefix(token, "-") {
  41. removed[token[1:]] = true
  42. } else {
  43. added[strings.Replace(token, "+", "", 1)] = true
  44. }
  45. }
  46. }
  47. }
  48. nicks := make([]string, 0, len(added))
  49. for nick := range added {
  50. if added[nick] && !removed[nick] {
  51. nicks = append(nicks, nick)
  52. }
  53. }
  54. characters, err := characters.List(&characters.Filter{Nicks: nicks})
  55. if err != nil {
  56. return models.Log{}, err
  57. }
  58. characterIDs := make([]string, len(characters))
  59. for i, char := range characters {
  60. if char.Name == "(Hidden)" {
  61. continue
  62. }
  63. characterIDs[i] = char.ID
  64. }
  65. err = collection.UpdateId(log.ID, bson.M{"$set": bson.M{"characterIds": characterIDs}})
  66. if err != nil {
  67. return models.Log{}, err
  68. }
  69. log.CharacterIDs = characterIDs
  70. if len(nicks) > 0 && unknowns != nil {
  71. NickLoop:
  72. for nick := range added {
  73. if !added[nick] {
  74. continue
  75. }
  76. for _, character := range characters {
  77. if character.HasNick(nick) {
  78. continue NickLoop
  79. }
  80. }
  81. unknowns[nick] += counts[nick]
  82. }
  83. }
  84. return log, nil
  85. }
  86. // RunFullUpdate runs a full update on all logs.
  87. func RunFullUpdate() error {
  88. iter := iter(bson.M{}, 0)
  89. err := iter.Err()
  90. if err != nil {
  91. return err
  92. }
  93. unknowns := make(map[string]int, 256)
  94. log := models.Log{}
  95. for iter.Next(&log) {
  96. _, err = UpdateCharacters(log, unknowns)
  97. if err != nil {
  98. return err
  99. }
  100. }
  101. err = iter.Err()
  102. if err != nil {
  103. return err
  104. }
  105. err = unknownnicks.Update(unknowns)
  106. if err != nil {
  107. return errors.New("Failed to commit unknown nicks update: " + err.Error())
  108. }
  109. return nil
  110. }
  111. // ScheduleFullUpdate runs a full character update within the next 60 seconds.
  112. func ScheduleFullUpdate() {
  113. updateTask.Schedule()
  114. }