account data only; integrate smtp server; logging

This commit is contained in:
Aine
2022-08-21 23:00:20 +03:00
parent c4b7a16e21
commit c746c91dbb
9 changed files with 157 additions and 99 deletions

View File

@@ -2,21 +2,27 @@ package bot
import (
"context"
"errors"
"fmt"
"strings"
"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 {
prefix string
domain string
log *logger.Logger
lp *linkpearl.Linkpearl
prefix string
domain string
rooms map[string]id.RoomID
roomsmu *sync.Mutex
log *logger.Logger
lp *linkpearl.Linkpearl
}
// New creates a new matrix bot
@@ -52,6 +58,10 @@ func (b *Bot) Start() error {
if err := b.migrate(); err != nil {
return err
}
ctx := sentry.SetHubOnContext(context.Background(), sentry.CurrentHub().Clone())
if err := b.syncRooms(ctx); err != nil {
return err
}
if err := b.lp.GetClient().SetPresence(event.PresenceOnline); err != nil {
return err
}
@@ -61,6 +71,39 @@ func (b *Bot) Start() error {
return b.lp.GetClient().Sync()
}
// Send email to matrix room
func (b *Bot) Send(from, to, subject, body string) error {
roomID, ok := b.rooms[to]
if !ok || roomID == "" {
return errors.New("room not found")
}
var text strings.Builder
text.WriteString("From: ")
text.WriteString(from)
text.WriteString("\n\n")
text.WriteString("# ")
text.WriteString(subject)
text.WriteString("\n\n")
text.WriteString(format.HTMLToMarkdown(body))
content := format.RenderMarkdown(text.String(), true, true)
_, err := b.lp.Send(roomID, content)
return err
}
// GetMappings returns mapping of mailbox = room
func (b *Bot) GetMappings(ctx context.Context) (map[string]id.RoomID, error) {
if len(b.rooms) == 0 {
err := b.syncRooms(ctx)
if err != nil {
return nil, err
}
}
return b.rooms, nil
}
// Stop the bot
func (b *Bot) Stop() {
err := b.lp.GetClient().SetPresence(event.PresenceOffline)

View File

@@ -9,14 +9,7 @@ import (
const settingskey = "cc.etke.postmoogle.settings"
var migrations = []string{
`
CREATE TABLE IF NOT EXISTS settings (
room_id VARCHAR(255),
mailbox VARCHAR(255)
)
`,
}
var migrations = []string{}
// settings of a room
type settings struct {
@@ -57,21 +50,7 @@ func (b *Bot) getSettings(ctx context.Context, roomID id.RoomID) (*settings, err
defer span.Finish()
var config settings
query := "SELECT * FROM settings WHERE room_id = "
switch b.lp.GetStore().GetDialect() {
case "postgres":
query += "$1"
case "sqlite3":
query += "?"
}
row := b.lp.GetDB().QueryRow(query, roomID)
err := row.Scan(&config.Mailbox)
if err == nil {
return &config, nil
}
b.log.Error("cannot find settings in database: %v", err)
err = b.lp.GetClient().GetRoomAccountData(roomID, settingskey, &config)
err := b.lp.GetClient().GetRoomAccountData(roomID, settingskey, &config)
return &config, err
}
@@ -79,47 +58,5 @@ func (b *Bot) getSettings(ctx context.Context, roomID id.RoomID) (*settings, err
func (b *Bot) setSettings(ctx context.Context, roomID id.RoomID, cfg *settings) error {
span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("setSettings"))
defer span.Finish()
tx, err := b.lp.GetDB().Begin()
if err == nil {
var insert string
switch b.lp.GetStore().GetDialect() {
case "postgres":
insert = "INSERT INTO settings VALUES ($1) ON CONFLICT (room_id) DO UPDATE SET mailbox = $1"
case "sqlite3":
insert = "INSERT INTO settings VALUES (?) ON CONFLICT (room_id) DO UPDATE SET mailbox = ?"
}
_, err = tx.Exec(insert, cfg.Mailbox)
if err != nil {
b.log.Error("cannot insert settigs: %v", err)
// nolint // no need to check error here
tx.Rollback()
}
if err != nil {
err = tx.Commit()
if err != nil {
b.log.Error("cannot commit transaction: %v", err)
}
}
}
return b.lp.GetClient().SetRoomAccountData(roomID, settingskey, cfg)
}
// FindRoomID by mailbox
func (b *Bot) FindRoomID(mailbox string) (id.RoomID, error) {
query := "SELECT room_id FROM settings WHERE mailbox = "
switch b.lp.GetStore().GetDialect() {
case "postgres":
query += "$1"
case "sqlite3":
query += "?"
}
var roomID string
row := b.lp.GetDB().QueryRow(query, mailbox)
err := row.Scan(&roomID)
return id.RoomID(roomID), err
}

View File

@@ -6,8 +6,34 @@ import (
"github.com/getsentry/sentry-go"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id"
)
func (b *Bot) syncRooms(ctx context.Context) error {
b.roomsmu.Lock()
defer b.roomsmu.Unlock()
span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("syncRooms"))
defer span.Finish()
resp, err := b.lp.GetClient().JoinedRooms()
if err != nil {
return err
}
b.rooms = make(map[string]id.RoomID, len(resp.JoinedRooms))
for _, roomID := range resp.JoinedRooms {
cfg, serr := b.getSettings(span.Context(), roomID)
if serr != nil {
b.Error(span.Context(), roomID, "cannot get room settings: %v", err)
continue
}
if cfg.Mailbox != "" {
b.rooms[cfg.Mailbox] = roomID
}
}
return nil
}
func (b *Bot) handleMailbox(ctx context.Context, evt *event.Event, command []string) {
if len(command) == 1 {
b.getMailbox(ctx, evt)
@@ -43,6 +69,15 @@ func (b *Bot) setMailbox(ctx context.Context, evt *event.Event, mailbox string)
span := sentry.StartSpan(ctx, "http.server", sentry.TransactionName("setMailbox"))
defer span.Finish()
existingID, ok := b.rooms[mailbox]
if ok && existingID != "" && existingID != evt.RoomID {
content := format.RenderMarkdown("Mailbox "+mailbox+"@"+b.domain+" already taken", true, true)
content.MsgType = event.MsgNotice
_, err := b.lp.Send(evt.RoomID, content)
if err != nil {
b.Error(span.Context(), evt.RoomID, "cannot send message: %v", err)
}
}
cfg, err := b.getSettings(span.Context(), evt.RoomID)
if err != nil {
b.log.Warn("cannot get settings: %v", err)
@@ -57,6 +92,10 @@ func (b *Bot) setMailbox(ctx context.Context, evt *event.Event, mailbox string)
return
}
b.roomsmu.Lock()
b.rooms[mailbox] = evt.RoomID
b.roomsmu.Unlock()
content := format.RenderMarkdown("Mailbox of this room set to **"+cfg.Mailbox+"@"+b.domain+"**", true, true)
content.MsgType = event.MsgNotice
_, err = b.lp.Send(evt.RoomID, content)