bridge.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package bridge
  2. import (
  3. "errors"
  4. "fmt"
  5. "sync"
  6. "time"
  7. log "maunium.net/go/maulogger/v2"
  8. "maunium.net/go/mautrix"
  9. "maunium.net/go/mautrix/appservice"
  10. "maunium.net/go/mautrix/id"
  11. "gitlab.com/beeper/discord/config"
  12. "gitlab.com/beeper/discord/database"
  13. "gitlab.com/beeper/discord/version"
  14. )
  15. const (
  16. reconnectDelay = 10 * time.Second
  17. )
  18. type Bridge struct {
  19. Config *config.Config
  20. log log.Logger
  21. as *appservice.AppService
  22. db *database.Database
  23. eventProcessor *appservice.EventProcessor
  24. matrixHandler *matrixHandler
  25. bot *appservice.IntentAPI
  26. provisioning *ProvisioningAPI
  27. usersByMXID map[id.UserID]*User
  28. usersByID map[string]*User
  29. usersLock sync.Mutex
  30. managementRooms map[id.RoomID]*User
  31. managementRoomsLock sync.Mutex
  32. portalsByMXID map[id.RoomID]*Portal
  33. portalsByID map[database.PortalKey]*Portal
  34. portalsLock sync.Mutex
  35. puppets map[string]*Puppet
  36. puppetsLock sync.Mutex
  37. StateStore *database.SQLStateStore
  38. }
  39. func New(cfg *config.Config) (*Bridge, error) {
  40. // Create the logger.
  41. logger, err := cfg.CreateLogger()
  42. if err != nil {
  43. return nil, err
  44. }
  45. logger.Infoln("Initializing version", version.String)
  46. // Create and initialize the app service.
  47. appservice, err := cfg.CreateAppService()
  48. if err != nil {
  49. return nil, err
  50. }
  51. appservice.Log = log.Sub("matrix")
  52. appservice.Init()
  53. // Create the bot.
  54. bot := appservice.BotIntent()
  55. // Setup the database.
  56. db, err := cfg.CreateDatabase(logger)
  57. if err != nil {
  58. return nil, err
  59. }
  60. // Create the state store
  61. logger.Debugln("Initializing state store")
  62. stateStore := database.NewSQLStateStore(db)
  63. appservice.StateStore = stateStore
  64. // Create the bridge.
  65. bridge := &Bridge{
  66. as: appservice,
  67. db: db,
  68. bot: bot,
  69. Config: cfg,
  70. log: logger,
  71. usersByMXID: make(map[id.UserID]*User),
  72. usersByID: make(map[string]*User),
  73. managementRooms: make(map[id.RoomID]*User),
  74. portalsByMXID: make(map[id.RoomID]*Portal),
  75. portalsByID: make(map[database.PortalKey]*Portal),
  76. puppets: make(map[string]*Puppet),
  77. StateStore: stateStore,
  78. }
  79. if cfg.Appservice.Provisioning.Enabled() {
  80. bridge.provisioning = newProvisioningAPI(bridge)
  81. }
  82. // Setup the event processors
  83. bridge.setupEvents()
  84. return bridge, nil
  85. }
  86. func (b *Bridge) connect() error {
  87. b.log.Debugln("Checking connection to homeserver")
  88. for {
  89. resp, err := b.bot.Whoami()
  90. if err != nil {
  91. if errors.Is(err, mautrix.MUnknownToken) {
  92. b.log.Fatalln("Access token invalid. Is the registration installed in your homeserver correctly?")
  93. return fmt.Errorf("invalid access token")
  94. }
  95. b.log.Errorfln("Failed to connect to homeserver : %v", err)
  96. b.log.Errorfln("reconnecting in %s", reconnectDelay)
  97. time.Sleep(reconnectDelay)
  98. } else if resp.UserID != b.bot.UserID {
  99. b.log.Fatalln("Unexpected user ID in whoami call: got %s, expected %s", resp.UserID, b.bot.UserID)
  100. return fmt.Errorf("expected user id %q but got %q", b.bot.UserID, resp.UserID)
  101. } else {
  102. break
  103. }
  104. }
  105. b.log.Debugln("Connected to homeserver")
  106. return nil
  107. }
  108. func (b *Bridge) Start() error {
  109. b.log.Infoln("Bridge started")
  110. if err := b.connect(); err != nil {
  111. return err
  112. }
  113. b.log.Debugln("Starting application service HTTP server")
  114. go b.as.Start()
  115. b.log.Debugln("Starting event processor")
  116. go b.eventProcessor.Start()
  117. go b.updateBotProfile()
  118. go b.startUsers()
  119. // Finally tell the appservice we're ready
  120. b.as.Ready = true
  121. return nil
  122. }
  123. func (b *Bridge) Stop() {
  124. b.log.Infoln("Bridge stopped")
  125. }