Start of the bot and it's matrix connection

This commit is contained in:
Gary Kramlich
2021-12-07 19:08:58 -06:00
parent 4be28617e0
commit be3982e585
5 changed files with 209 additions and 6 deletions

41
bridge/bot.go Normal file
View File

@@ -0,0 +1,41 @@
package bridge
import (
"maunium.net/go/mautrix/id"
)
func (b *Bridge) updateBotProfile() {
cfg := b.config.Appservice.Bot
// Set the bot's avatar.
if cfg.Avatar != "" {
var err error
var mxc id.ContentURI
if cfg.Avatar == "remove" {
err = b.bot.SetAvatarURL(mxc)
} else {
mxc, err = id.ParseContentURI(cfg.Avatar)
if err == nil {
err = b.bot.SetAvatarURL(mxc)
}
}
b.log.Warnln("failed to update the bot's avatar: %v", err)
}
// Update the bot's display name.
if cfg.Displayname != "" {
var err error
if cfg.Displayname == "remove" {
err = b.bot.SetDisplayName("")
} else {
err = b.bot.SetDisplayName(cfg.Displayname)
}
if err != nil {
b.log.Warnln("failed to update the bot's display name: %v", err)
}
}
}

View File

@@ -1,13 +1,22 @@
package bridge
import (
"errors"
"fmt"
"time"
log "maunium.net/go/maulogger/v2"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/appservice"
"gitlab.com/beeper/discord/config"
"gitlab.com/beeper/discord/version"
)
const (
reconnectDelay = 10 * time.Second
)
type Bridge struct {
config *config.Config
@@ -15,6 +24,7 @@ type Bridge struct {
as *appservice.AppService
eventProcessor *appservice.EventProcessor
matrixHandler *matrixHandler
bot *appservice.IntentAPI
}
@@ -27,27 +37,83 @@ func New(cfg *config.Config) (*Bridge, error) {
logger.Infoln("Initializing version", version.String)
// Create the app service.
// Create and initalize the app service.
appservice, err := cfg.CreateAppService()
if err != nil {
return nil, err
}
appservice.Log = log.Sub("matrix")
appservice.Init()
// Create the bot.
bot := appservice.BotIntent()
// Create the bridge.
bridge := &Bridge{
as: appservice,
bot: bot,
config: cfg,
log: logger,
as: appservice,
}
// Setup the event processors
bridge.setupEvents()
return bridge, nil
}
func (b *Bridge) Start() {
b.log.Infoln("bridge started")
func (b *Bridge) connect() error {
b.log.Debugln("Checking connection to homeserver")
for {
resp, err := b.bot.Whoami()
if err != nil {
if errors.Is(err, mautrix.MUnknownToken) {
b.log.Fatalln("Access token invalid. Is the registration installed in your homeserver correctly?")
return fmt.Errorf("invalid access token")
}
b.log.Errorfln("Failed to connect to homeserver : %v", err)
b.log.Errorfln("reconnecting in %s", reconnectDelay)
time.Sleep(reconnectDelay)
} else if resp.UserID != b.bot.UserID {
b.log.Fatalln("Unexpected user ID in whoami call: got %s, expected %s", resp.UserID, b.bot.UserID)
return fmt.Errorf("expected user id %q but got %q", b.bot.UserID, resp.UserID)
} else {
break
}
}
b.log.Debugln("Connected to homeserver")
return nil
}
func (b *Bridge) Start() error {
b.log.Infoln("Bridge started")
if err := b.connect(); err != nil {
return err
}
b.log.Debugln("Starting application service HTTP server")
go b.as.Start()
b.log.Debugln("Starting event processor")
go b.eventProcessor.Start()
go b.updateBotProfile()
// Finally tell the appservice we're ready
b.as.Ready = true
return nil
}
func (b *Bridge) Stop() {
b.log.Infoln("bridge stopped")
b.log.Infoln("Bridge stopped")
}

87
bridge/matrix.go Normal file
View File

@@ -0,0 +1,87 @@
package bridge
import (
"maunium.net/go/maulogger/v2"
"maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/event"
)
type matrixHandler struct {
as *appservice.AppService
bridge *Bridge
log maulogger.Logger
}
func (b *Bridge) setupEvents() {
b.eventProcessor = appservice.NewEventProcessor(b.as)
b.matrixHandler = &matrixHandler{
as: b.as,
bridge: b,
log: b.log.Sub("Matrix"),
}
b.eventProcessor.On(event.EventMessage, b.matrixHandler.handleMessage)
b.eventProcessor.On(event.StateMember, b.matrixHandler.handleMembership)
}
func (mh *MatrixHandler) join(evt *event.Event, intent *appservice.IntentAPI) *mautrix.RespJoinedMembers {
resp, err := intent.JoinRoomByID(evt.RoomID)
if err != nil {
mh.log.Debugfln("Failed to join room %s as %s with invite from %s: %v", evt.RoomID, intent.UserID, evt.Sender, err)
return nil
}
members, err := intent.JoinedMembers(resp.RoomID)
if err != nil {
intent.LeaveRoom(resp.RoomID)
mh.log.Debugfln("Failed to get members in room %s after accepting invite from %s as %s: %v", resp.RoomID, evt.Sender, intent.UserID, err)
return nil
}
if len(members.Joined) < 2 {
intent.LeaveRoom(resp.RoomID)
mh.log.Debugln("Leaving empty room", resp.RoomID, "after accepting invite from", evt.Sender, "as", intent.UserID)
return nil
}
return members
}
func (mh *matrixHandler) ignoreEvent(evt *event.Event) bool {
return false
}
func (mh *matrixHandler) handleMessage(evt *event.Event) {
if mh.ignoreEvent(evt) {
return
}
mh.log.Debugfln("received message from %q: %q", evt.Sender, evt.Content.AsMessage())
}
func (mh *matrixHandler) handleMembership(evt *event.Event) {
mh.log.Debugfln("recevied invite %#v\n", evt)
// Return early if we're supposed to ignore the event.
if mh.ignoreEvent(evt) {
return
}
// Grab the content of the event.
content := evt.Content.AsMessage()
// TODO: handle invites from ourselfs?
isSelf := id.UserID(evt.GetStateKey()) == evt.Sender
// Handle matrix invites.
if content.Membership == event.MembershipInvite && !isSelf {
//
}
}