116 lines
2.6 KiB
Go
116 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type MatrixClient struct {
|
|
HomeserverURL string
|
|
AccessToken string
|
|
RoomID string
|
|
Limit int
|
|
httpClient *http.Client
|
|
}
|
|
|
|
func newMatrixClientFromEnv() *MatrixClient {
|
|
hs := strings.TrimRight(readEnv("MATRIX_HOMESERVER_URL", ""), "/")
|
|
token := readEnv("MATRIX_ACCESS_TOKEN", "")
|
|
roomID := readEnv("MATRIX_ROOM_ID", "")
|
|
if hs == "" || token == "" || roomID == "" {
|
|
return nil
|
|
}
|
|
|
|
limit := mustInt(readEnv("MATRIX_LIMIT", "25"), 25)
|
|
if limit < 1 {
|
|
limit = 1
|
|
}
|
|
if limit > 100 {
|
|
limit = 100
|
|
}
|
|
|
|
return &MatrixClient{
|
|
HomeserverURL: hs,
|
|
AccessToken: token,
|
|
RoomID: roomID,
|
|
Limit: limit,
|
|
httpClient: &http.Client{
|
|
Timeout: 6 * time.Second,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (m *MatrixClient) FetchRecentMessages(ctx context.Context) ([]MatrixMessage, error) {
|
|
filter := fmt.Sprintf(`{"room":{"rooms":["%s"],"timeline":{"limit":%d}}}`, m.RoomID, m.Limit)
|
|
endpoint := m.HomeserverURL + "/_matrix/client/v3/sync?timeout=0&filter=" + url.QueryEscape(filter)
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Authorization", "Bearer "+m.AccessToken)
|
|
|
|
resp, err := m.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return nil, errors.New("matrix sync failed: " + strconv.Itoa(resp.StatusCode))
|
|
}
|
|
|
|
var syncResp struct {
|
|
Rooms struct {
|
|
Join map[string]struct {
|
|
Timeline struct {
|
|
Events []struct {
|
|
Type string `json:"type"`
|
|
Sender string `json:"sender"`
|
|
OriginServerTS int64 `json:"origin_server_ts"`
|
|
Content struct {
|
|
MsgType string `json:"msgtype"`
|
|
Body string `json:"body"`
|
|
} `json:"content"`
|
|
} `json:"events"`
|
|
} `json:"timeline"`
|
|
} `json:"join"`
|
|
} `json:"rooms"`
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&syncResp); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
room, ok := syncResp.Rooms.Join[m.RoomID]
|
|
if !ok {
|
|
return []MatrixMessage{}, nil
|
|
}
|
|
|
|
out := make([]MatrixMessage, 0, len(room.Timeline.Events))
|
|
for _, ev := range room.Timeline.Events {
|
|
if ev.Type != "m.room.message" {
|
|
continue
|
|
}
|
|
if ev.Content.MsgType != "m.text" && ev.Content.MsgType != "m.notice" {
|
|
continue
|
|
}
|
|
body := strings.TrimSpace(ev.Content.Body)
|
|
if body == "" {
|
|
continue
|
|
}
|
|
ts := time.UnixMilli(ev.OriginServerTS).Local().Format("02.01.2006 15:04")
|
|
out = append(out, MatrixMessage{
|
|
Sender: ev.Sender,
|
|
Body: body,
|
|
Timestamp: ts,
|
|
})
|
|
}
|
|
return out, nil
|
|
}
|