2023-05-04 05:57:44 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
2023-05-06 16:01:19 +02:00
|
|
|
"log"
|
2023-05-04 05:57:44 +02:00
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/chzyer/readline"
|
2023-05-06 16:01:19 +02:00
|
|
|
"github.com/joho/godotenv"
|
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"
|
|
|
|
)
|
|
|
|
|
2023-05-06 16:01:19 +02:00
|
|
|
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()
|
2023-05-06 16:01:19 +02:00
|
|
|
|
|
|
|
err := godotenv.Load()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("Error loading .env")
|
2023-05-04 05:57:44 +02:00
|
|
|
}
|
|
|
|
|
2023-05-06 16:01:19 +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-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))
|
2023-05-06 21:37:21 +02:00
|
|
|
|
|
|
|
// 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,
|
2023-05-06 16:01:19 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|