puppet.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
  2. // Copyright (C) 2020 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. log "maunium.net/go/maulogger/v2"
  20. "maunium.net/go/mautrix/id"
  21. "maunium.net/go/mautrix-whatsapp/types"
  22. )
  23. type PuppetQuery struct {
  24. db *Database
  25. log log.Logger
  26. }
  27. func (pq *PuppetQuery) New() *Puppet {
  28. return &Puppet{
  29. db: pq.db,
  30. log: pq.log,
  31. EnablePresence: true,
  32. }
  33. }
  34. func (pq *PuppetQuery) GetAll() (puppets []*Puppet) {
  35. rows, err := pq.db.Query("SELECT jid, avatar, avatar_url, displayname, name_quality, custom_mxid, access_token, next_batch, enable_presence FROM puppet")
  36. if err != nil || rows == nil {
  37. return nil
  38. }
  39. defer rows.Close()
  40. for rows.Next() {
  41. puppets = append(puppets, pq.New().Scan(rows))
  42. }
  43. return
  44. }
  45. func (pq *PuppetQuery) Get(jid types.WhatsAppID) *Puppet {
  46. row := pq.db.QueryRow("SELECT jid, avatar, avatar_url, displayname, name_quality, custom_mxid, access_token, next_batch, enable_presence FROM puppet WHERE jid=$1", jid)
  47. if row == nil {
  48. return nil
  49. }
  50. return pq.New().Scan(row)
  51. }
  52. func (pq *PuppetQuery) GetByCustomMXID(mxid id.UserID) *Puppet {
  53. row := pq.db.QueryRow("SELECT jid, avatar, avatar_url, displayname, name_quality, custom_mxid, access_token, next_batch, enable_presence FROM puppet WHERE custom_mxid=$1", mxid)
  54. if row == nil {
  55. return nil
  56. }
  57. return pq.New().Scan(row)
  58. }
  59. func (pq *PuppetQuery) GetAllWithCustomMXID() (puppets []*Puppet) {
  60. rows, err := pq.db.Query("SELECT jid, avatar, avatar_url, displayname, name_quality, custom_mxid, access_token, next_batch, enable_presence FROM puppet WHERE custom_mxid<>''")
  61. if err != nil || rows == nil {
  62. return nil
  63. }
  64. defer rows.Close()
  65. for rows.Next() {
  66. puppets = append(puppets, pq.New().Scan(rows))
  67. }
  68. return
  69. }
  70. type Puppet struct {
  71. db *Database
  72. log log.Logger
  73. JID types.WhatsAppID
  74. Avatar string
  75. AvatarURL id.ContentURI
  76. Displayname string
  77. NameQuality int8
  78. CustomMXID id.UserID
  79. AccessToken string
  80. NextBatch string
  81. EnablePresence bool
  82. }
  83. func (puppet *Puppet) Scan(row Scannable) *Puppet {
  84. var displayname, avatar, avatarURL, customMXID, accessToken, nextBatch sql.NullString
  85. var quality sql.NullInt64
  86. var enablePresence sql.NullBool
  87. err := row.Scan(&puppet.JID, &avatar, &avatarURL, &displayname, &quality, &customMXID, &accessToken, &nextBatch, &enablePresence)
  88. if err != nil {
  89. if err != sql.ErrNoRows {
  90. puppet.log.Errorln("Database scan failed:", err)
  91. }
  92. return nil
  93. }
  94. puppet.Displayname = displayname.String
  95. puppet.Avatar = avatar.String
  96. puppet.AvatarURL, _ = id.ParseContentURI(avatarURL.String)
  97. puppet.NameQuality = int8(quality.Int64)
  98. puppet.CustomMXID = id.UserID(customMXID.String)
  99. puppet.AccessToken = accessToken.String
  100. puppet.NextBatch = nextBatch.String
  101. puppet.EnablePresence = enablePresence.Bool
  102. return puppet
  103. }
  104. func (puppet *Puppet) Insert() {
  105. _, err := puppet.db.Exec("INSERT INTO puppet (jid, avatar, avatar_url, displayname, name_quality, custom_mxid, access_token, next_batch, enable_presence) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
  106. puppet.JID, puppet.Avatar, puppet.AvatarURL.String(), puppet.Displayname, puppet.NameQuality, puppet.CustomMXID, puppet.AccessToken, puppet.NextBatch, puppet.EnablePresence)
  107. if err != nil {
  108. puppet.log.Warnfln("Failed to insert %s: %v", puppet.JID, err)
  109. }
  110. }
  111. func (puppet *Puppet) Update() {
  112. _, err := puppet.db.Exec("UPDATE puppet SET displayname=$1, name_quality=$2, avatar=$3, avatar_url=$4, custom_mxid=$5, access_token=$6, next_batch=$7, enable_presence=$8 WHERE jid=$9",
  113. puppet.Displayname, puppet.NameQuality, puppet.Avatar, puppet.AvatarURL.String(), puppet.CustomMXID, puppet.AccessToken, puppet.NextBatch, puppet.EnablePresence, puppet.JID)
  114. if err != nil {
  115. puppet.log.Warnfln("Failed to update %s->%s: %v", puppet.JID, err)
  116. }
  117. }