userportal.go 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
  2. // Copyright (C) 2021 Tulir Asokan
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. package database
  17. import (
  18. "database/sql"
  19. "errors"
  20. "time"
  21. )
  22. func (user *User) GetLastReadTS(portal PortalKey) time.Time {
  23. user.lastReadCacheLock.Lock()
  24. defer user.lastReadCacheLock.Unlock()
  25. if cached, ok := user.lastReadCache[portal]; ok {
  26. return cached
  27. }
  28. var ts int64
  29. err := user.db.QueryRow("SELECT last_read_ts FROM user_portal WHERE user_mxid=$1 AND portal_jid=$2 AND portal_receiver=$3", user.MXID, portal.JID, portal.Receiver).Scan(&ts)
  30. if err != nil && !errors.Is(err, sql.ErrNoRows) {
  31. user.log.Warnfln("Failed to scan last read timestamp from user portal table: %v", err)
  32. }
  33. if ts == 0 {
  34. user.lastReadCache[portal] = time.Time{}
  35. } else {
  36. user.lastReadCache[portal] = time.Unix(ts, 0)
  37. }
  38. return user.lastReadCache[portal]
  39. }
  40. func (user *User) SetLastReadTS(portal PortalKey, ts time.Time) {
  41. user.lastReadCacheLock.Lock()
  42. defer user.lastReadCacheLock.Unlock()
  43. _, err := user.db.Exec(`
  44. INSERT INTO user_portal (user_mxid, portal_jid, portal_receiver, last_read_ts) VALUES ($1, $2, $3, $4)
  45. ON CONFLICT (user_mxid, portal_jid, portal_receiver) DO UPDATE SET last_read_ts=excluded.last_read_ts WHERE user_portal.last_read_ts<excluded.last_read_ts
  46. `, user.MXID, portal.JID, portal.Receiver, ts.Unix())
  47. if err != nil {
  48. user.log.Warnfln("Failed to update last read timestamp: %v", err)
  49. } else {
  50. user.log.Debugfln("Set last read timestamp of %s in %s to %d", user.MXID, portal.String(), ts.Unix())
  51. user.lastReadCache[portal] = ts
  52. }
  53. }
  54. func (user *User) IsInSpace(portal PortalKey) bool {
  55. user.inSpaceCacheLock.Lock()
  56. defer user.inSpaceCacheLock.Unlock()
  57. if cached, ok := user.inSpaceCache[portal]; ok {
  58. return cached
  59. }
  60. var inSpace bool
  61. err := user.db.QueryRow("SELECT in_space FROM user_portal WHERE user_mxid=$1 AND portal_jid=$2 AND portal_receiver=$3", user.MXID, portal.JID, portal.Receiver).Scan(&inSpace)
  62. if err != nil && !errors.Is(err, sql.ErrNoRows) {
  63. user.log.Warnfln("Failed to scan in space status from user portal table: %v", err)
  64. }
  65. user.inSpaceCache[portal] = inSpace
  66. return inSpace
  67. }
  68. func (user *User) MarkInSpace(portal PortalKey) {
  69. user.inSpaceCacheLock.Lock()
  70. defer user.inSpaceCacheLock.Unlock()
  71. _, err := user.db.Exec(`
  72. INSERT INTO user_portal (user_mxid, portal_jid, portal_receiver, in_space) VALUES ($1, $2, $3, true)
  73. ON CONFLICT (user_mxid, portal_jid, portal_receiver) DO UPDATE SET in_space=true
  74. `, user.MXID, portal.JID, portal.Receiver)
  75. if err != nil {
  76. user.log.Warnfln("Failed to update in space status: %v", err)
  77. } else {
  78. user.inSpaceCache[portal] = true
  79. }
  80. }