Files
postmoogle/bot/bot.go
2023-10-03 00:03:29 +03:00

144 lines
3.2 KiB
Go

package bot
import (
"context"
"fmt"
"regexp"
"sync"
"github.com/rs/zerolog"
"gitlab.com/etke.cc/linkpearl"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
"gitlab.com/etke.cc/postmoogle/bot/config"
"gitlab.com/etke.cc/postmoogle/bot/queue"
"gitlab.com/etke.cc/postmoogle/utils"
)
// Mailboxes config
type MBXConfig struct {
Reserved []string
Forwarded []string
Activation string
}
// Bot represents matrix bot
type Bot struct {
prefix string
mbxc MBXConfig
domains []string
allowedUsers []*regexp.Regexp
allowedAdmins []*regexp.Regexp
adminRooms []id.RoomID
ignoreBefore int64 // mautrix 0.15.x migration
commands commandList
rooms sync.Map
proxies []string
sendmail func(string, string, string) error
cfg *config.Manager
log *zerolog.Logger
lp *linkpearl.Linkpearl
mu utils.Mutex
q *queue.Queue
handledMembershipEvents sync.Map
}
// New creates a new matrix bot
func New(
q *queue.Queue,
lp *linkpearl.Linkpearl,
log *zerolog.Logger,
cfg *config.Manager,
proxies []string,
prefix string,
domains []string,
admins []string,
mbxc MBXConfig,
) (*Bot, error) {
b := &Bot{
domains: domains,
prefix: prefix,
rooms: sync.Map{},
adminRooms: []id.RoomID{},
proxies: proxies,
mbxc: mbxc,
cfg: cfg,
log: log,
lp: lp,
mu: utils.NewMutex(),
q: q,
}
users, err := b.initBotUsers()
if err != nil {
return nil, err
}
allowedUsers, uerr := parseMXIDpatterns(users, "")
if uerr != nil {
return nil, uerr
}
b.allowedUsers = allowedUsers
allowedAdmins, aerr := parseMXIDpatterns(admins, "")
if aerr != nil {
return nil, aerr
}
b.allowedAdmins = allowedAdmins
b.commands = b.initCommands()
return b, nil
}
// Error message to the log and matrix room
func (b *Bot) Error(ctx context.Context, message string, args ...any) {
evt := eventFromContext(ctx)
threadID := threadIDFromContext(ctx)
if threadID == "" {
threadID = linkpearl.EventParent(evt.ID, evt.Content.AsMessage())
}
err := fmt.Errorf(message, args...) //nolint:goerr113 // we have to
b.log.Error().Err(err).Msg(err.Error())
if evt == nil {
return
}
var noThreads bool
cfg, cerr := b.cfg.GetRoom(evt.RoomID)
if cerr == nil {
noThreads = cfg.NoThreads()
}
var relatesTo *event.RelatesTo
if threadID != "" {
relatesTo = linkpearl.RelatesTo(threadID, noThreads)
}
b.lp.SendNotice(evt.RoomID, "ERROR: "+err.Error(), relatesTo)
}
// Start performs matrix /sync
func (b *Bot) Start(statusMsg string) error {
if err := b.migrateMautrix015(); err != nil {
return err
}
if err := b.syncRooms(); err != nil {
return err
}
b.initSync()
b.log.Info().Msg("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().Err(err).Msg("cannot set presence = offline")
}
b.lp.GetClient().StopSync()
}