bridge.go 3.3 KB

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