mirror of https://github.com/kha7iq/pingme
commit
2e450056eb
@ -0,0 +1,221 @@
|
||||
package matrix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/urfave/cli/v2"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type matrixPingMe struct {
|
||||
Username string
|
||||
Password string
|
||||
Token string
|
||||
Url string
|
||||
ServerName string
|
||||
Room string
|
||||
RoomID string
|
||||
Domain string
|
||||
Message string
|
||||
AutoJoin bool
|
||||
}
|
||||
|
||||
func Send() *cli.Command {
|
||||
var matrix matrixPingMe
|
||||
return &cli.Command{
|
||||
Name: "matrix",
|
||||
Usage: "Send message via matrix",
|
||||
UsageText: "pingme matrix --token 'syt_YW...E2qD' --room 'LRovrjPJaRChcTKgoK:matrix.org' " +
|
||||
"--url 'matrix-client.matrix.org' --autoJoin --msg 'Hello, Matrix!'",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.Username,
|
||||
Name: "username",
|
||||
Aliases: []string{"u"},
|
||||
Usage: "Matrix username",
|
||||
EnvVars: []string{"MATRIX_USER"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.Password,
|
||||
Name: "password",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "Matrix password",
|
||||
EnvVars: []string{"MATRIX_PASSWORD"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.Token,
|
||||
Name: "token",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "Matrix access token. Can be used instead of username+password",
|
||||
EnvVars: []string{"MATRIX_ACCESS_TOKEN"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.Url,
|
||||
Name: "url",
|
||||
Usage: "Matrix server URL",
|
||||
EnvVars: []string{"MATRIX_SERVER_URL"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.ServerName,
|
||||
Name: "serverName",
|
||||
Usage: "Can be provided if requests should be routed via a particular server",
|
||||
EnvVars: []string{"MATRIX_SERVER_NAME"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.Room,
|
||||
Name: "room",
|
||||
Usage: "Matrix room to send the message to, in the format <roomId>:<domain>",
|
||||
EnvVars: []string{"MATRIX_ROOM"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.RoomID,
|
||||
Name: "roomId",
|
||||
Usage: "Matrix room ID to send the message to. The exclamation mark at the beginning can be excluded.",
|
||||
EnvVars: []string{"MATRIX_ROOM_ID"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.Domain,
|
||||
Name: "domain",
|
||||
Usage: "Used in conjunction with room ID to get the desired room",
|
||||
EnvVars: []string{"MATRIX_DOMAIN"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Destination: &matrix.Message,
|
||||
Name: "msg",
|
||||
Aliases: []string{"m"},
|
||||
Required: true,
|
||||
Usage: "Message to send to matrix",
|
||||
EnvVars: []string{"MATRIX_MESSAGE"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Destination: &matrix.AutoJoin,
|
||||
Name: "autoJoin",
|
||||
Usage: "If enabled, will automatically join the specified room if not already joined",
|
||||
EnvVars: []string{"MATRIX_AUTO_JOIN"},
|
||||
},
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
// Login
|
||||
client, err := matrix.login()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to login to matrix: %v", err)
|
||||
}
|
||||
|
||||
// Parse and set variables
|
||||
err = matrix.setupVars()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If necessary, join the given room
|
||||
err = matrix.joinRoomIfNecessary(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Send the message
|
||||
_, err = client.SendText(matrix.Room, matrix.Message)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send matrix text: %v", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
setupVars will ensure the room ID begins with an exclamation mark and set the room string if not
|
||||
already set, using the room ID and domain. If the room string, room id and domain are not set,
|
||||
an error will be thrown.
|
||||
*/
|
||||
func (m *matrixPingMe) setupVars() error {
|
||||
// Format the room ID
|
||||
if !strings.HasPrefix(m.RoomID, "!") {
|
||||
m.RoomID = "!" + m.RoomID
|
||||
}
|
||||
|
||||
// Create the matrix room string if not already provided
|
||||
if m.Room == "" {
|
||||
if m.RoomID == "" || m.Domain == "" {
|
||||
return fmt.Errorf("matrix room, or room ID and domain must be provided")
|
||||
}
|
||||
|
||||
m.Room = fmt.Sprintf("%s:%s", m.RoomID, m.Domain)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
joinRoomIfNecessary gets all the joined rooms and checks if the desired room is in the list.
|
||||
If not, and autoJoin is set to true - will attempt to join the room. If autoJoin is set to
|
||||
false, an error will be thrown
|
||||
*/
|
||||
func (m *matrixPingMe) joinRoomIfNecessary(client *gomatrix.Client) error {
|
||||
// Get already joined rooms
|
||||
joined, err := client.JoinedRooms()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get joined rooms: %v", err)
|
||||
}
|
||||
|
||||
// Check if we've already joined the desired room
|
||||
foundRoom := false
|
||||
for _, room := range joined.JoinedRooms {
|
||||
if room == m.Room {
|
||||
foundRoom = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If not, try auto join the room
|
||||
if !foundRoom {
|
||||
if !m.AutoJoin {
|
||||
return fmt.Errorf("not joined room '%s' and --autoJoin is set to false", m.Room)
|
||||
}
|
||||
|
||||
_, err = client.JoinRoom(m.Room, m.ServerName, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to auto join room '%s': %v", m.Room, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
login creates a gomatrix.Client instance, connecting to the given URL, using the provided login details
|
||||
*/
|
||||
func (m *matrixPingMe) login() (*gomatrix.Client, error) {
|
||||
// Create a client instance
|
||||
client, err := gomatrix.NewClient(m.Url, "", "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create matrix client: %v", err)
|
||||
}
|
||||
|
||||
// Attempt to log in with whatever login details were provided.
|
||||
// Or, throw an error if no login details were given
|
||||
var resp *gomatrix.RespLogin
|
||||
if m.Token != "" {
|
||||
resp, err = client.Login(&gomatrix.ReqLogin{
|
||||
Type: "m.login.token",
|
||||
Token: m.Token,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if m.Username != "" && m.Password != "" {
|
||||
resp, err = client.Login(&gomatrix.ReqLogin{
|
||||
Type: "m.login.password",
|
||||
User: m.Username,
|
||||
Password: m.Password,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("no token, or username and password provided")
|
||||
}
|
||||
|
||||
// Set the access token for this session
|
||||
client.SetCredentials(resp.UserID, resp.AccessToken)
|
||||
m.Token = resp.AccessToken
|
||||
return client, nil
|
||||
}
|
Loading…
Reference in new issue