user.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package bridge
  2. import (
  3. "github.com/bwmarrin/discordgo"
  4. "github.com/skip2/go-qrcode"
  5. log "maunium.net/go/maulogger/v2"
  6. "maunium.net/go/mautrix/appservice"
  7. "maunium.net/go/mautrix/event"
  8. "maunium.net/go/mautrix/id"
  9. "gitlab.com/beeper/discord/database"
  10. )
  11. type User struct {
  12. *database.User
  13. bridge *Bridge
  14. log log.Logger
  15. }
  16. func (b *Bridge) loadUser(dbUser *database.User, mxid *id.UserID) *User {
  17. // If we weren't passed in a user we attempt to create one if we were given
  18. // a matrix id.
  19. if dbUser == nil {
  20. if mxid == nil {
  21. return nil
  22. }
  23. dbUser = b.db.User.New()
  24. dbUser.MXID = *mxid
  25. dbUser.Insert()
  26. }
  27. user := b.NewUser(dbUser)
  28. // We assume the usersLock was acquired by our caller.
  29. b.usersByMXID[user.MXID] = user
  30. if user.ID != "" {
  31. b.usersByID[user.ID] = user
  32. }
  33. if user.ManagementRoom != "" {
  34. // Lock the management rooms for our update
  35. b.managementRoomsLock.Lock()
  36. b.managementRooms[user.ManagementRoom] = user
  37. b.managementRoomsLock.Unlock()
  38. }
  39. return user
  40. }
  41. func (b *Bridge) GetUserByMXID(userID id.UserID) *User {
  42. // TODO: check if puppet
  43. b.usersLock.Lock()
  44. defer b.usersLock.Unlock()
  45. user, ok := b.usersByMXID[userID]
  46. if !ok {
  47. return b.loadUser(b.db.User.GetByMXID(userID), &userID)
  48. }
  49. return user
  50. }
  51. func (b *Bridge) NewUser(dbUser *database.User) *User {
  52. user := &User{
  53. User: dbUser,
  54. bridge: b,
  55. log: b.log.Sub("User").Sub(string(dbUser.MXID)),
  56. }
  57. return user
  58. }
  59. func (b *Bridge) getAllUsers() []*User {
  60. b.usersLock.Lock()
  61. defer b.usersLock.Unlock()
  62. dbUsers := b.db.User.GetAll()
  63. users := make([]*User, len(dbUsers))
  64. for idx, dbUser := range dbUsers {
  65. user, ok := b.usersByMXID[dbUser.MXID]
  66. if !ok {
  67. user = b.loadUser(dbUser, nil)
  68. }
  69. users[idx] = user
  70. }
  71. return users
  72. }
  73. func (b *Bridge) startUsers() {
  74. b.log.Debugln("Starting users")
  75. for _, user := range b.getAllUsers() {
  76. // if user.ID != "" {
  77. // haveSessions = true
  78. // }
  79. go user.Connect()
  80. }
  81. }
  82. func (u *User) SetManagementRoom(roomID id.RoomID) {
  83. u.bridge.managementRoomsLock.Lock()
  84. defer u.bridge.managementRoomsLock.Unlock()
  85. existing, ok := u.bridge.managementRooms[roomID]
  86. if ok {
  87. // If there's a user already assigned to this management room, clear it
  88. // out.
  89. // I think this is due a name change or something? I dunno, leaving it
  90. // for now.
  91. existing.ManagementRoom = ""
  92. existing.Update()
  93. }
  94. u.ManagementRoom = roomID
  95. u.bridge.managementRooms[u.ManagementRoom] = u
  96. u.Update()
  97. }
  98. func (u *User) HasSession() bool {
  99. return u.User.Session != nil
  100. }
  101. func (u *User) sendQRCode(bot *appservice.IntentAPI, roomID id.RoomID, code string) (id.EventID, error) {
  102. url, err := u.uploadQRCode(code)
  103. if err != nil {
  104. return "", err
  105. }
  106. content := event.MessageEventContent{
  107. MsgType: event.MsgImage,
  108. Body: code,
  109. URL: url.CUString(),
  110. }
  111. resp, err := bot.SendMessageEvent(roomID, event.EventMessage, &content)
  112. if err != nil {
  113. return "", err
  114. }
  115. return resp.EventID, nil
  116. }
  117. func (u *User) uploadQRCode(code string) (id.ContentURI, error) {
  118. qrCode, err := qrcode.Encode(code, qrcode.Low, 256)
  119. if err != nil {
  120. u.log.Errorln("Failed to encode QR code:", err)
  121. return id.ContentURI{}, err
  122. }
  123. bot := u.bridge.as.BotClient()
  124. resp, err := bot.UploadBytes(qrCode, "image/png")
  125. if err != nil {
  126. u.log.Errorln("Failed to upload QR code:", err)
  127. return id.ContentURI{}, err
  128. }
  129. return resp.ContentURI, nil
  130. }
  131. func (u *User) Login(token string) error {
  132. err := u.User.NewSession(token)
  133. if err != nil {
  134. return err
  135. }
  136. return u.Connect()
  137. }
  138. func (u *User) Connect() error {
  139. u.User.Session.AddHandler(u.messageHandler)
  140. u.log.Warnln("logged in, opening websocket")
  141. return u.User.Session.Open()
  142. }
  143. func (u *User) messageHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
  144. u.log.Warnln("received message", m)
  145. }