Checking using `settings.Allowed` is odd. Not all commands are related to setting configuration settings. Admin commands are coming in the future, for which this is certainly not the case. We now do access checks early on (during command processing), so command handlers can be clean of access checks. If we're inside of a command handler, the user is privileged to run it.
106 lines
2.6 KiB
Go
106 lines
2.6 KiB
Go
package bot
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"regexp"
|
|
"sync"
|
|
|
|
"github.com/getsentry/sentry-go"
|
|
"gitlab.com/etke.cc/go/logger"
|
|
"gitlab.com/etke.cc/linkpearl"
|
|
"maunium.net/go/mautrix/event"
|
|
"maunium.net/go/mautrix/format"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
// Bot represents matrix bot
|
|
type Bot struct {
|
|
noowner bool
|
|
federation bool
|
|
prefix string
|
|
domain string
|
|
allowedUsers []*regexp.Regexp
|
|
allowedAdmins []*regexp.Regexp
|
|
commands commandList
|
|
rooms sync.Map
|
|
log *logger.Logger
|
|
lp *linkpearl.Linkpearl
|
|
mu map[id.RoomID]*sync.Mutex
|
|
handledMembershipEvents sync.Map
|
|
}
|
|
|
|
// New creates a new matrix bot
|
|
func New(
|
|
lp *linkpearl.Linkpearl,
|
|
log *logger.Logger,
|
|
prefix, domain string,
|
|
noowner, federation bool,
|
|
allowedUsers []*regexp.Regexp,
|
|
allowedAdmins []*regexp.Regexp,
|
|
) *Bot {
|
|
b := &Bot{
|
|
noowner: noowner,
|
|
federation: federation,
|
|
prefix: prefix,
|
|
domain: domain,
|
|
allowedUsers: allowedUsers,
|
|
allowedAdmins: allowedAdmins,
|
|
rooms: sync.Map{},
|
|
log: log,
|
|
lp: lp,
|
|
mu: map[id.RoomID]*sync.Mutex{},
|
|
}
|
|
|
|
b.commands = b.buildCommandList()
|
|
|
|
return b
|
|
}
|
|
|
|
// Error message to the log and matrix room
|
|
func (b *Bot) Error(ctx context.Context, roomID id.RoomID, message string, args ...interface{}) {
|
|
b.log.Error(message, args...)
|
|
|
|
sentry.GetHubFromContext(ctx).CaptureException(fmt.Errorf(message, args...))
|
|
if roomID != "" {
|
|
// nolint // if something goes wrong here nobody can help...
|
|
b.lp.Send(roomID, &event.MessageEventContent{
|
|
MsgType: event.MsgNotice,
|
|
Body: "ERROR: " + fmt.Sprintf(message, args...),
|
|
})
|
|
}
|
|
}
|
|
|
|
// Notice sends a notice message to the matrix room
|
|
func (b *Bot) Notice(ctx context.Context, roomID id.RoomID, message string) {
|
|
content := format.RenderMarkdown(message, true, true)
|
|
content.MsgType = event.MsgNotice
|
|
_, err := b.lp.Send(roomID, &content)
|
|
if err != nil {
|
|
sentry.GetHubFromContext(ctx).CaptureException(err)
|
|
}
|
|
}
|
|
|
|
// Start performs matrix /sync
|
|
func (b *Bot) Start(statusMsg string) error {
|
|
if err := b.migrate(); err != nil {
|
|
return err
|
|
}
|
|
if err := b.syncRooms(); err != nil {
|
|
return err
|
|
}
|
|
|
|
b.initSync()
|
|
b.log.Info("Postmoogle has been started")
|
|
return b.lp.Start(statusMsg)
|
|
}
|
|
|
|
// Stop the bot
|
|
func (b *Bot) Stop() {
|
|
err := b.lp.GetClient().SetPresence(event.PresenceOffline)
|
|
if err != nil {
|
|
b.log.Error("cannot set presence = offline: %v", err)
|
|
}
|
|
b.lp.GetClient().StopSync()
|
|
}
|