package actions import ( "fmt" "encoding/json" "context" "errors" "sync" "time" _ "github.com/mattn/go-sqlite3" "maunium.net/go/mautrix" "maunium.net/go/mautrix/id" "maunium.net/go/mautrix/crypto/cryptohelper" "github.com/k4lipso/gokill/internal" ) type SendMatrix struct { Homeserver string `json:"homeserver"` Username string `json:"username"` Password string `json:"password"` Database string `json:"database"` RoomId string `json:"roomId"` Message string `json:"message"` TestMessage string `json:"testMessage"` ActionChan ActionResultChan } func (s SendMatrix) sendMessage(message string) error { client, err := mautrix.NewClient(s.Homeserver, "", "") if err != nil { return err } cryptoHelper, err := cryptohelper.NewCryptoHelper(client, []byte("meow"), s.Database) if err != nil { return err } cryptoHelper.LoginAs = &mautrix.ReqLogin{ Type: mautrix.AuthTypePassword, Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: s.Username}, Password: s.Password, } err = cryptoHelper.Init() if err != nil { return err } client.Crypto = cryptoHelper internal.LogDoc(s).Info("Matrix Client Now running") syncCtx, cancelSync := context.WithCancel(context.Background()) var syncStopWait sync.WaitGroup syncStopWait.Add(1) go func() { err = client.SyncWithContext(syncCtx) defer syncStopWait.Done() if err != nil && !errors.Is(err, context.Canceled) { return } }() time.Sleep(5 * time.Second) resp, err := client.SendText(id.RoomID(s.RoomId), message) if err != nil { return fmt.Errorf("Failed to send event") } else { internal.LogDoc(s).Info("Matrix Client: Message sent") internal.LogDoc(s).Infof("Matrix Client: event_id: %s", resp.EventID.String()) } cancelSync() syncStopWait.Wait() err = cryptoHelper.Close() if err != nil { return fmt.Errorf("Error closing database") } return nil } func (s SendMatrix) DryExecute() { internal.LogDoc(s).Info("SendMatrix: Trying to send test message") err := s.sendMessage(s.TestMessage) if err != nil { internal.LogDoc(s).Info("SendMatrix: failed to send test message") } s.ActionChan <- err } func (s SendMatrix) Execute() { internal.LogDoc(s).Info("SendMatrix: Trying to send message") err := s.sendMessage(s.Message) if err != nil { internal.LogDoc(s).Info("SendMatrix: failed to send message") } s.ActionChan <- err } func CreateSendMatrix(config internal.ActionConfig, c ActionResultChan) (SendMatrix, error) { result := SendMatrix{} err := json.Unmarshal(config.Options, &result) if err != nil { return SendMatrix{}, err } if result.Homeserver == "" { return SendMatrix{}, internal.OptionMissingError{"homeserver"} } if result.Username == "" { return SendMatrix{}, internal.OptionMissingError{"username"} } if result.Password == "" { return SendMatrix{}, internal.OptionMissingError{"password"} } if result.Database == "" { return SendMatrix{}, internal.OptionMissingError{"database"} } if result.RoomId == "" { return SendMatrix{}, internal.OptionMissingError{"roomId"} } if result.Message == "" { return SendMatrix{}, internal.OptionMissingError{"message"} } if result.TestMessage == "" { return SendMatrix{}, internal.OptionMissingError{"testMessage"} } result.ActionChan = c return result, nil } func (s SendMatrix) Create(config internal.ActionConfig, c ActionResultChan) (Action, error) { return CreateSendMatrix(config, c) } func (p SendMatrix) GetName() string { return "SendMatrix" } func (p SendMatrix) GetDescription() string { return "Sends a message to a given room. The user needs to be part of that room already." } func (p SendMatrix) GetExample() string { return ` { "type": "SendMatrix", "options": { "homeserver": "matrix.org", "username": "testuser", "password": "super-secret", "database": "/etc/gokill/matrix.db", "roomId": "!Balrthajskensaw:matrix.org", "message": "attention, intruders got my device!", "testMessage": "this is just a test, no worries" } } ` } func (p SendMatrix) GetOptions() []internal.ConfigOption { return []internal.ConfigOption{ { Name: "homeserver", Type: "string", Description: "homeserver address.", Default: "", }, { Name: "username", Type: "string", Description: "username (localpart, wihout homeserver address)", Default: "", }, { Name: "password", Type: "string", Description: "password in clear text", Default: "", }, { Name: "database", Type: "string", Description: "path to database file, will be created if not existing. this is necessary to sync keys for encryption.", Default: "", }, { Name: "roomId", Type: "string", Description: "", Default: "", }, { Name: "message", Type: "string", Description: "actual message that should be sent", Default: "", }, { Name: "testMessage", Type: "string", Description: "message sent during test run", Default: "", }, } }