rpcfetch/io.go

92 lines
1.8 KiB
Go
Raw Normal View History

package rpcfetch
import (
"encoding/binary"
"encoding/json"
"net"
"os"
"strconv"
)
type Client struct {
id string
dialed bool
active bool
net.Conn
}
// Raw wraps around the Raw method to provide generic json parsing
func Raw[T any](d *Client, opcode uint32, payload any) (uint32, T, error) {
var p T
opcodeResp, payloadResp, err := d.Raw(opcode, payload)
if err != nil {
return opcodeResp, p, err
}
return opcodeResp, p, json.Unmarshal(payloadResp, &p)
}
// Raw writes a raw payload to Discord and returns the response opcode and payload
func (d *Client) Raw(opcode uint32, payload any) (uint32, []byte, error) {
if err := binary.Write(d.Conn, binary.LittleEndian, opcode); err != nil {
return 0, nil, err
}
if p, err := json.Marshal(payload); err != nil {
return 0, nil, err
} else {
if err = binary.Write(d.Conn, binary.LittleEndian, uint32(len(p))); err != nil {
return 0, nil, err
}
if _, err = d.Conn.Write(p); err != nil {
return 0, nil, err
}
}
var (
opcodeResp uint32
lengthResp uint32
)
if err := binary.Read(d.Conn, binary.LittleEndian, &opcodeResp); err != nil {
return 0, nil, err
}
if err := binary.Read(d.Conn, binary.LittleEndian, &lengthResp); err != nil {
return 0, nil, err
}
payloadResp := make([]byte, lengthResp)
_, err := d.Read(payloadResp)
return opcodeResp, payloadResp, err
}
// New sets up and returns the reference to a new Client
func New(id string) *Client {
d := &Client{
id: id,
}
return d
}
func sockPath() string {
snap := "/run/user/" + strconv.Itoa(os.Getuid()) + "/snap.discord"
if _, err := os.Stat(snap); err == nil {
return snap
}
for _, env := range []string{"XDG_RUNTIME_DIR", "TMPDIR", "TMP", "TEMP"} {
if val, ok := os.LookupEnv(env); ok {
return val
}
}
// fallback
return "/tmp"
}