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.

141 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, addUnknowns bool) (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. added := make(map[string]bool)
  21. removed := make(map[string]bool)
  22. for _, post := range posts {
  23. if post.Kind == "text" || post.Kind == "action" {
  24. if strings.HasPrefix(post.Text, "(") || strings.Contains(post.Nick, "(") || strings.Contains(post.Nick, "[E]") {
  25. continue
  26. }
  27. // Clean up the nick (remove possessive suffix, comma, formatting stuff)
  28. if strings.HasSuffix(post.Nick, "'s") || strings.HasSuffix(post.Nick, "`s") {
  29. post.Nick = post.Nick[:len(post.Nick)-2]
  30. } else if strings.HasSuffix(post.Nick, "'") || strings.HasSuffix(post.Nick, "`") || strings.HasSuffix(post.Nick, ",") || strings.HasSuffix(post.Nick, "\x0f") {
  31. post.Nick = post.Nick[:len(post.Nick)-1]
  32. }
  33. added[post.Nick] = true
  34. }
  35. if post.Kind == "chars" {
  36. tokens := strings.Fields(post.Text)
  37. for _, token := range tokens {
  38. if strings.HasPrefix(token, "-") {
  39. removed[token[1:]] = true
  40. } else {
  41. added[strings.Replace(token, "+", "", 1)] = true
  42. }
  43. }
  44. }
  45. }
  46. nicks := make([]string, 0, len(added))
  47. for nick := range added {
  48. if added[nick] && !removed[nick] {
  49. nicks = append(nicks, nick)
  50. }
  51. }
  52. characters, err := characters.List(&characters.Filter{Nicks: nicks})
  53. if err != nil {
  54. return models.Log{}, err
  55. }
  56. characterIDs := make([]string, len(characters))
  57. for i, char := range characters {
  58. if char.Name == "(Hidden)" {
  59. continue
  60. }
  61. characterIDs[i] = char.ID
  62. }
  63. err = collection.UpdateId(log.ID, bson.M{"$set": bson.M{"characterIds": characterIDs}})
  64. if err != nil {
  65. return models.Log{}, err
  66. }
  67. log.CharacterIDs = characterIDs
  68. if addUnknowns {
  69. NickLoop:
  70. for nick := range added {
  71. if !added[nick] {
  72. continue
  73. }
  74. for _, character := range characters {
  75. if character.HasNick(nick) {
  76. continue NickLoop
  77. }
  78. }
  79. unknownnicks.Add(nick)
  80. }
  81. }
  82. return log, nil
  83. }
  84. // RunFullUpdate runs a full update on all logs.
  85. func RunFullUpdate() error {
  86. iter := iter(bson.M{}, 0)
  87. err := iter.Err()
  88. if err != nil {
  89. return err
  90. }
  91. err = unknownnicks.BeginUpdate()
  92. if err != nil {
  93. return err
  94. }
  95. log := models.Log{}
  96. for iter.Next(&log) {
  97. _, err = UpdateCharacters(log, true)
  98. if err != nil {
  99. unknownnicks.CancelUpdate()
  100. return err
  101. }
  102. }
  103. err = iter.Err()
  104. if err != nil {
  105. unknownnicks.CancelUpdate()
  106. return err
  107. }
  108. err = unknownnicks.CommitUpdate()
  109. if err != nil {
  110. return errors.New("Failed to commit unknown nicks update: " + err.Error())
  111. }
  112. return nil
  113. }
  114. // ScheduleFullUpdate runs a full character update within the next 60 seconds.
  115. func ScheduleFullUpdate() {
  116. updateTask.Schedule()
  117. }