bridge.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. "go.mau.fi/mautrix-discord/config"
  12. "go.mau.fi/mautrix-discord/database"
  13. "go.mau.fi/mautrix-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. puppetsByCustomMXID map[id.UserID]*Puppet
  37. puppetsLock sync.Mutex
  38. StateStore *database.SQLStateStore
  39. crypto Crypto
  40. }
  41. func New(cfg *config.Config) (*Bridge, error) {
  42. // Create the logger.
  43. logger, err := cfg.CreateLogger()
  44. if err != nil {
  45. return nil, err
  46. }
  47. logger.Infoln("Initializing version", version.String)
  48. // Create and initialize the app service.
  49. appservice, err := cfg.CreateAppService()
  50. if err != nil {
  51. return nil, err
  52. }
  53. appservice.Log = log.Sub("matrix")
  54. appservice.Init()
  55. // Create the bot.
  56. bot := appservice.BotIntent()
  57. // Setup the database.
  58. db, err := cfg.CreateDatabase(logger)
  59. if err != nil {
  60. return nil, err
  61. }
  62. // Create the state store
  63. logger.Debugln("Initializing state store")
  64. stateStore := database.NewSQLStateStore(db)
  65. appservice.StateStore = stateStore
  66. // Create the bridge.
  67. bridge := &Bridge{
  68. as: appservice,
  69. db: db,
  70. bot: bot,
  71. Config: cfg,
  72. log: logger,
  73. usersByMXID: make(map[id.UserID]*User),
  74. usersByID: make(map[string]*User),
  75. managementRooms: make(map[id.RoomID]*User),
  76. portalsByMXID: make(map[id.RoomID]*Portal),
  77. portalsByID: make(map[database.PortalKey]*Portal),
  78. puppets: make(map[string]*Puppet),
  79. puppetsByCustomMXID: make(map[id.UserID]*Puppet),
  80. StateStore: stateStore,
  81. }
  82. bridge.crypto = NewCryptoHelper(bridge)
  83. if cfg.Appservice.Provisioning.Enabled() {
  84. bridge.provisioning = newProvisioningAPI(bridge)
  85. }
  86. // Setup the event processors
  87. bridge.setupEvents()
  88. return bridge, nil
  89. }
  90. func (b *Bridge) connect() error {
  91. b.log.Debugln("Checking connection to homeserver")
  92. for {
  93. resp, err := b.bot.Whoami()
  94. if err != nil {
  95. if errors.Is(err, mautrix.MUnknownToken) {
  96. b.log.Fatalln("Access token invalid. Is the registration installed in your homeserver correctly?")
  97. return fmt.Errorf("invalid access token")
  98. }
  99. b.log.Errorfln("Failed to connect to homeserver : %v", err)
  100. b.log.Errorfln("reconnecting in %s", reconnectDelay)
  101. time.Sleep(reconnectDelay)
  102. } else if resp.UserID != b.bot.UserID {
  103. b.log.Fatalln("Unexpected user ID in whoami call: got %s, expected %s", resp.UserID, b.bot.UserID)
  104. return fmt.Errorf("expected user id %q but got %q", b.bot.UserID, resp.UserID)
  105. } else {
  106. break
  107. }
  108. }
  109. b.log.Debugln("Connected to homeserver")
  110. return nil
  111. }
  112. func (b *Bridge) Start() error {
  113. b.log.Infoln("Bridge started")
  114. if err := b.connect(); err != nil {
  115. return err
  116. }
  117. if b.crypto != nil {
  118. if err := b.crypto.Init(); err != nil {
  119. b.log.Fatalln("Error initializing end-to-bridge encryption:", err)
  120. return err
  121. }
  122. }
  123. b.log.Debugln("Starting application service HTTP server")
  124. go b.as.Start()
  125. b.log.Debugln("Starting event processor")
  126. go b.eventProcessor.Start()
  127. go b.updateBotProfile()
  128. if b.crypto != nil {
  129. go b.crypto.Start()
  130. }
  131. go b.startUsers()
  132. // Finally tell the appservice we're ready
  133. b.as.Ready = true
  134. return nil
  135. }
  136. func (b *Bridge) Stop() {
  137. if b.crypto != nil {
  138. b.crypto.Stop()
  139. }
  140. b.as.Stop()
  141. b.eventProcessor.Stop()
  142. for _, user := range b.usersByMXID {
  143. if user.Session == nil {
  144. continue
  145. }
  146. b.log.Debugln("Disconnecting", user.MXID)
  147. user.Session.Close()
  148. }
  149. b.log.Infoln("Bridge stopped")
  150. }