Browse Source

the functions handling almost everything I need

master
emile 2 years ago
parent
commit
6c242710d7
Signed by: emile
GPG Key ID: 4D8DD313A751DED7
  1. 32
      join.go
  2. 35
      login.go
  3. 113
      send.go
  4. 72
      structs.go
  5. 96
      sync.go

32
join.go

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
package matrix
import (
"fmt"
"gopkg.in/h2non/gentleman.v2"
"gopkg.in/h2non/gentleman.v2/plugins/query"
)
func join(authinfo Authinfo, roomIdentifier string) error {
cli := gentleman.New()
cli.URL(authinfo.HomeServer)
req := cli.Request()
req.Path(fmt.Sprintf("/_matrix/client/r0/rooms/%s/join", roomIdentifier))
req.Method("POST")
req.Use(query.Set("access_token", authinfo.AccessToken))
res, err := req.Send()
if err != nil {
fmt.Println("ERR1")
return err
}
if !res.Ok {
fmt.Println("ERR2")
fmt.Println(res)
return err
}
return nil
}

35
login.go

@ -3,9 +3,8 @@ package matrix @@ -3,9 +3,8 @@ package matrix
import (
"encoding/json"
"github.com/h2non/gentleman/plugins/body"
"gopkg.in/h2non/gentleman.v2"
"gopkg.in/h2non/gentleman.v2/plugins/query"
"gopkg.in/h2non/gentleman.v2/plugins/body"
)
// Login logs in to the homeserver and returns an Authinfo struct containing
@ -38,38 +37,8 @@ func Login(username, password, homeserver string) (Authinfo, error) { @@ -38,38 +37,8 @@ func Login(username, password, homeserver string) (Authinfo, error) {
if err := json.Unmarshal(res.Bytes(), &authinfo); err != nil {
return Authinfo{}, err
}
return authinfo, nil
}
func Sync(authinfo Authinfo) {
cli := gentleman.New()
cli.URL(authinfo.HomeServer)
req := cli.Request()
req.Path("/_matrix/client/r0/sync")
req.Method("GET")
req.Use(query.Set("access_token", authinfo.AccessToken))
res, err := req.Send()
if err != nil {
return err
}
if !res.Ok {
return err
}
authinfo.HomeServer = homeserver
var authinfo Authinfo
if err := json.Unmarshal(res.Bytes(), &authinfo); err != nil {
return Authinfo{}, err
}
return authinfo, nil
}
// Authinfo defines the fields returned after logging in
type Authinfo struct {
UserID string `json:"user_id"`
HomeServer string `json:"home_server"`
DeviceID string `json:"device_id"`
AccessToken string `json:"access_token"`
}

113
send.go

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
package matrix
import (
"bytes"
"encoding/json"
"fmt"
"time"
"gopkg.in/h2non/gentleman.v2"
"gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/headers"
"gopkg.in/h2non/gentleman.v2/plugins/query"
)
// Send allows sending messages
func Send(authinfo Authinfo, roomID string, message string) error {
cli := gentleman.New()
cli.URL(authinfo.HomeServer)
eventType := "m.room.message"
txID := fmt.Sprintf("%d", time.Now().UnixNano())
req := cli.Request()
req.Path(fmt.Sprintf("/_matrix/client/r0/rooms/%s/send/%s/%s", roomID, eventType, txID))
req.Method("PUT")
formattedMessage := fmt.Sprintf("<pre><samp style=\"font-family: monospace\">%s\n</samp></pre>\n", message)
// Define the JSON payload via body plugin
data := map[string]string{
"msgtype": "m.text",
"body": "A", // notifications
"format": "org.matrix.custom.html",
"formatted_body": formattedMessage,
}
req.Use(body.JSON(data))
req.Use(query.Set("access_token", authinfo.AccessToken))
res, err := req.Send()
if err != nil {
fmt.Println("ERR1")
return err
}
if !res.Ok {
fmt.Println("ERR2")
fmt.Println(res)
return err
}
fmt.Printf("Sent %s\n", message)
return nil
}
// Upload uploads stuff to the matrix homeserver returning the files MXC
func Upload(authinfo Authinfo, filename string, file *bytes.Buffer) (UploadResponse, error) {
cli := gentleman.New()
cli.URL(authinfo.HomeServer)
req := cli.Request()
req.Path("/_matrix/media/r0/upload")
req.Method("POST")
req.Use(headers.Set("Content-Type", "image/png"))
req.Use(headers.Set("filename", filename))
req.Use(body.Reader(file))
req.Use(query.Set("access_token", authinfo.AccessToken))
res, err := req.Send()
if err != nil {
fmt.Println("ERR1")
return UploadResponse{}, err
}
if !res.Ok {
fmt.Println("ERR2")
fmt.Println(res)
return UploadResponse{}, err
}
var uploadResponse UploadResponse
if err := json.Unmarshal(res.Bytes(), &uploadResponse); err != nil {
return UploadResponse{}, err
}
return uploadResponse, nil
}
// SendImage sends the image with the given mxc ID to the room (currently
// hardcoded some lines below)
func SendImage(authinfo Authinfo, roomID string, image map[string]interface{}) error {
cli := gentleman.New()
cli.URL(authinfo.HomeServer)
eventType := "m.room.message"
txID := fmt.Sprintf("%d", time.Now().UnixNano())
req := cli.Request()
req.Path(fmt.Sprintf("/_matrix/client/r0/rooms/%s/send/%s/%s", roomID, eventType, txID))
req.Method("PUT")
req.Use(body.JSON(image))
req.Use(query.Set("access_token", authinfo.AccessToken))
res, err := req.Send()
if err != nil {
fmt.Println("ERR1")
return err
}
if !res.Ok {
fmt.Println("ERR2")
fmt.Println(res)
return err
}
return nil
}

72
structs.go

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
package matrix
// Authinfo defines the fields returned after logging in
type Authinfo struct {
UserID string `json:"user_id"`
HomeServer string `json:"home_server"`
DeviceID string `json:"device_id"`
AccessToken string `json:"access_token"`
}
// RespSync defines the response from the sync
type RespSync struct {
NextBatch string `json:"next_batch"`
AccountData struct {
Events []Event `json:"events"`
} `json:"account_data"`
Presence struct {
Events []Event `json:"events"`
} `json:"presence"`
Rooms struct {
Leave map[string]struct {
State struct {
Events []Event `json:"events"`
} `json:"state"`
Timeline struct {
Events []Event `json:"events"`
Limited bool `json:"limited"`
PrevBatch string `json:"prev_batch"`
} `json:"timeline"`
} `json:"leave"`
Join map[string]struct {
State struct {
Events []Event `json:"events"`
} `json:"state"`
Timeline struct {
Events []Event `json:"events"`
Limited bool `json:"limited"`
PrevBatch string `json:"prev_batch"`
} `json:"timeline"`
} `json:"join"`
Invite map[string]struct {
State struct {
Events []Event
} `json:"invite_state"`
} `json:"invite"`
} `json:"rooms"`
}
// Event defines an event
type Event struct {
StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events.
Sender string `json:"sender"` // The user ID of the sender of the event
Type string `json:"type"` // The event type
Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server
ID string `json:"event_id"` // The unique ID of this event
RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence)
Redacts string `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event
Unsigned map[string]interface{} `json:"unsigned"` // The unsigned portions of the event, such as age and prev_content
Content map[string]interface{} `json:"content"` // The JSON content of the event.
PrevContent map[string]interface{} `json:"prev_content,omitempty"` // The JSON prev_content of the event.
}
// PackagedEvent bundles an event with more information regarding it, such as the roomname in which the event was produced.
type PackagedEvent struct {
RoomName string
Event Event
}
// UploadResponse is the responce recieved from the upload
type UploadResponse struct {
ContentURI string `json:"content_uri,omitempty"`
}

96
sync.go

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
package matrix
import (
"encoding/json"
"fmt"
"gopkg.in/h2non/gentleman.v2"
"gopkg.in/h2non/gentleman.v2/plugins/query"
)
// Sync syncs
func Sync(authinfo Authinfo) (RespSync, error) {
cli := gentleman.New()
cli.URL(authinfo.HomeServer)
req := cli.Request()
req.Path("/_matrix/client/r0/sync")
req.Method("GET")
req.Use(query.Set("access_token", authinfo.AccessToken))
res, err := req.Send()
if err != nil {
fmt.Println("ERR1")
return RespSync{}, err
}
if !res.Ok {
fmt.Println("ERR2")
fmt.Println(res)
return RespSync{}, err
}
var syncReponse RespSync
if err := json.Unmarshal(res.Bytes(), &syncReponse); err != nil {
return RespSync{}, err
}
return syncReponse, nil
}
// SyncPartial syncs the state using sync token obtained in a previous request
// as a timestamp
func SyncPartial(authinfo Authinfo, nextBatch string, eventsChannel chan PackagedEvent) (RespSync, error) {
cli := gentleman.New()
cli.URL(authinfo.HomeServer)
req := cli.Request()
req.Path("/_matrix/client/r0/sync")
req.Method("GET")
req.Use(query.Set("access_token", authinfo.AccessToken))
req.Use(query.Set("since", nextBatch))
req.Use(query.Set("timeout", "1"))
res, err := req.Send()
if err != nil {
fmt.Println("ERR1")
return RespSync{}, err
}
if !res.Ok {
fmt.Println("ERR2")
fmt.Println(res)
return RespSync{}, err
}
// unmarshal the response
var syncReponse RespSync
if err := json.Unmarshal(res.Bytes(), &syncReponse); err != nil {
return RespSync{}, err
}
// accept all room invites
for room := range syncReponse.Rooms.Invite {
err := join(authinfo, room)
if err != nil {
return RespSync{}, fmt.Errorf("could not join room: %s", err)
}
}
// iterate over all new events, insert all new events not from the bot itself into the eventsChannel
for roomname, room := range syncReponse.Rooms.Join {
for _, event := range room.Timeline.Events {
packagedEvent := PackagedEvent{
RoomName: roomname,
Event: event,
}
// if the event recieved is not from ourself, insert the event into the eventsChannel
if event.Sender != authinfo.UserID {
eventsChannel <- packagedEvent
}
}
}
return syncReponse, nil
}
Loading…
Cancel
Save