bridge.go 3.6 KB

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