webapi_imlog.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package state
  2. import (
  3. "sort"
  4. "strings"
  5. )
  6. // WebAPIStoredIM is one message in a Web AIM session's in-memory IM log.
  7. // The Web AIM client expects fetchStoredIMs entries with sender, message, msgId, and date.
  8. type WebAPIStoredIM struct {
  9. Sender string
  10. Message string
  11. MsgID string
  12. Date int64 // Unix seconds
  13. }
  14. // AddStoredIM appends a message to the per-partner log for this session.
  15. func (s *WebAPISession) AddStoredIM(partnerAimID, sender, message, msgID string, date int64) {
  16. if s == nil || partnerAimID == "" || message == "" {
  17. return
  18. }
  19. s.imLogMu.Lock()
  20. defer s.imLogMu.Unlock()
  21. if s.imLog == nil {
  22. s.imLog = make(map[string][]WebAPIStoredIM)
  23. }
  24. s.imLog[normalizeWebAPIAimID(partnerAimID)] = append(s.imLog[normalizeWebAPIAimID(partnerAimID)], WebAPIStoredIM{
  25. Sender: sender,
  26. Message: message,
  27. MsgID: msgID,
  28. Date: date,
  29. })
  30. }
  31. // StoredIMQuery describes filters for fetchStoredIMs.
  32. type StoredIMQuery struct {
  33. PartnerAimID string
  34. StartTime int64
  35. EndTime int64
  36. NToGet int
  37. SortOrder string
  38. SkipMsgID string
  39. StopMsgID string
  40. }
  41. // GetStoredIMs returns stored messages for a conversation partner, filtered and sorted
  42. // per the Web AIM client's fetchStoredIMs parameters.
  43. func (s *WebAPISession) GetStoredIMs(q StoredIMQuery) []map[string]interface{} {
  44. if s == nil || q.PartnerAimID == "" {
  45. return nil
  46. }
  47. s.imLogMu.Lock()
  48. msgs := append([]WebAPIStoredIM(nil), s.imLog[normalizeWebAPIAimID(q.PartnerAimID)]...)
  49. s.imLogMu.Unlock()
  50. if len(msgs) == 0 {
  51. return []map[string]interface{}{}
  52. }
  53. filtered := make([]WebAPIStoredIM, 0, len(msgs))
  54. for _, msg := range msgs {
  55. if q.StartTime > 0 && msg.Date < q.StartTime {
  56. continue
  57. }
  58. if q.EndTime > 0 && msg.Date > q.EndTime {
  59. continue
  60. }
  61. filtered = append(filtered, msg)
  62. }
  63. descending := strings.EqualFold(q.SortOrder, "descendingDate")
  64. sort.Slice(filtered, func(i, j int) bool {
  65. if descending {
  66. return filtered[i].Date > filtered[j].Date
  67. }
  68. return filtered[i].Date < filtered[j].Date
  69. })
  70. if q.SkipMsgID != "" {
  71. for i, msg := range filtered {
  72. if msg.MsgID == q.SkipMsgID {
  73. filtered = filtered[i+1:]
  74. break
  75. }
  76. }
  77. }
  78. if q.StopMsgID != "" {
  79. for i, msg := range filtered {
  80. if msg.MsgID == q.StopMsgID {
  81. filtered = filtered[:i]
  82. break
  83. }
  84. }
  85. }
  86. n := q.NToGet
  87. if n <= 0 {
  88. n = 100
  89. }
  90. if len(filtered) > n {
  91. filtered = filtered[:n]
  92. }
  93. out := make([]map[string]interface{}, len(filtered))
  94. for i, msg := range filtered {
  95. out[i] = map[string]interface{}{
  96. "sender": msg.Sender,
  97. "message": msg.Message,
  98. "msgId": msg.MsgID,
  99. "date": float64(msg.Date),
  100. }
  101. }
  102. return out
  103. }
  104. // normalizeWebAPIAimID keys the IM log by the same normalization the web client
  105. // applies to aimIds, so a partner stored from a display screen name is still
  106. // found when the client queries by aimId.
  107. func normalizeWebAPIAimID(aimID string) string {
  108. return NewIdentScreenName(aimID).String()
  109. }