mirror-nourybot-matrix/cmd/nourybot/main.go

176 lines
4.1 KiB
Go
Raw Normal View History

2023-05-04 05:57:44 +02:00
package main
import (
"context"
"errors"
"flag"
"fmt"
"log"
2023-05-04 05:57:44 +02:00
"os"
"sync"
"time"
"github.com/chzyer/readline"
"github.com/joho/godotenv"
2023-05-07 00:13:13 +02:00
"github.com/lyx0/nourybot-matrix/internal/common"
2023-05-04 05:57:44 +02:00
_ "github.com/mattn/go-sqlite3"
"github.com/rs/zerolog"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto/cryptohelper"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
type config struct {
matrixHomeserver string
matrixUser string
matrixPass string
database string
}
2023-05-06 19:20:31 +02:00
type Application struct {
Mc *mautrix.Client
Log zerolog.Logger
}
2023-05-04 05:57:44 +02:00
var debug = flag.Bool("debug", false, "Enable debug logs")
func main() {
flag.Parse()
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env")
2023-05-04 05:57:44 +02:00
}
var cfg config
cfg.matrixHomeserver = os.Getenv("MATRIX_HOMESERVER")
cfg.matrixUser = os.Getenv("MATRIX_USERNAME")
cfg.matrixPass = os.Getenv("MATRIX_PASSWORD")
cfg.database = os.Getenv("SQLITE_DATABASE")
client, err := mautrix.NewClient(cfg.matrixHomeserver, "", "")
2023-05-04 05:57:44 +02:00
if err != nil {
panic(err)
}
rl, err := readline.New("[no room]> ")
if err != nil {
panic(err)
}
defer rl.Close()
log := zerolog.New(zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) {
w.Out = rl.Stdout()
w.TimeFormat = time.Stamp
})).With().Timestamp().Logger()
if !*debug {
log = log.Level(zerolog.InfoLevel)
}
client.Log = log
var lastRoomID id.RoomID
2023-05-07 00:13:13 +02:00
common.StartTime()
2023-05-06 19:20:31 +02:00
app := &Application{
Mc: client,
Log: log,
}
syncer := app.Mc.Syncer.(*mautrix.DefaultSyncer)
2023-05-04 05:57:44 +02:00
syncer.OnEventType(event.EventMessage, func(source mautrix.EventSource, evt *event.Event) {
lastRoomID = evt.RoomID
rl.SetPrompt(fmt.Sprintf("%s> ", lastRoomID))
// Filter out messages from the bot user account.
if evt.Sender.String() != fmt.Sprintf("@%s:%s", cfg.matrixUser, cfg.matrixHomeserver) {
app.Log.Info().
Str("sender", evt.Sender.String()).
Str("type", evt.Type.String()).
Str("id", evt.ID.String()).
Str("body", evt.Content.AsMessage().Body).
Msg("Received message")
if evt.Content.AsMessage().Body[:1] == "!" {
app.ParseCommand(evt)
return
} else {
app.ParseEvent(evt)
return
}
}
2023-05-04 05:57:44 +02:00
})
syncer.OnEventType(event.StateMember, func(source mautrix.EventSource, evt *event.Event) {
2023-05-06 19:20:31 +02:00
if evt.GetStateKey() == app.Mc.UserID.String() && evt.Content.AsMember().Membership == event.MembershipInvite {
_, err := app.Mc.JoinRoomByID(evt.RoomID)
2023-05-04 05:57:44 +02:00
if err == nil {
lastRoomID = evt.RoomID
rl.SetPrompt(fmt.Sprintf("%s> ", lastRoomID))
2023-05-06 19:20:31 +02:00
app.Log.Info().
2023-05-04 05:57:44 +02:00
Str("room_id", evt.RoomID.String()).
Str("inviter", evt.Sender.String()).
Msg("Joined room after invite")
} else {
2023-05-06 19:20:31 +02:00
app.Log.Error().Err(err).
2023-05-04 05:57:44 +02:00
Str("room_id", evt.RoomID.String()).
Str("inviter", evt.Sender.String()).
Msg("Failed to join room after invite")
}
}
})
2023-05-06 19:20:31 +02:00
cryptoHelper, err := cryptohelper.NewCryptoHelper(app.Mc, []byte("meow"), cfg.database)
2023-05-04 05:57:44 +02:00
if err != nil {
panic(err)
}
cryptoHelper.LoginAs = &mautrix.ReqLogin{
Type: mautrix.AuthTypePassword,
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: cfg.matrixUser},
Password: cfg.matrixPass,
2023-05-04 05:57:44 +02:00
}
err = cryptoHelper.Init()
if err != nil {
panic(err)
}
2023-05-06 19:20:31 +02:00
app.Mc.Crypto = cryptoHelper
2023-05-04 05:57:44 +02:00
2023-05-06 19:20:31 +02:00
app.Log.Info().Msg("Now running")
2023-05-04 05:57:44 +02:00
syncCtx, cancelSync := context.WithCancel(context.Background())
var syncStopWait sync.WaitGroup
syncStopWait.Add(1)
go func() {
2023-05-06 19:20:31 +02:00
err = app.Mc.SyncWithContext(syncCtx)
2023-05-04 05:57:44 +02:00
defer syncStopWait.Done()
if err != nil && !errors.Is(err, context.Canceled) {
panic(err)
}
}()
for {
line, err := rl.Readline()
if err != nil {
break
}
if lastRoomID == "" {
2023-05-06 19:20:31 +02:00
app.Log.Error().Msg("Wait for an incoming message before sending messages")
2023-05-04 05:57:44 +02:00
continue
}
2023-05-06 19:20:31 +02:00
resp, err := app.Mc.SendText(lastRoomID, line)
2023-05-04 05:57:44 +02:00
if err != nil {
2023-05-06 19:20:31 +02:00
app.Log.Error().Err(err).Msg("Failed to send event")
2023-05-04 05:57:44 +02:00
} else {
2023-05-06 19:20:31 +02:00
app.Log.Info().Str("event_id", resp.EventID.String()).Msg("Event sent")
2023-05-04 05:57:44 +02:00
}
}
cancelSync()
syncStopWait.Wait()
err = cryptoHelper.Close()
if err != nil {
2023-05-06 19:20:31 +02:00
app.Log.Error().Err(err).Msg("Error closing database")
2023-05-04 05:57:44 +02:00
}
}