Go
144 lines · 3,029 bytes
package libreauth
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
)
type Client struct {
Name string
OwnerID string
Version string
BaseURL string
SessionID string
EncKey string
Hash string
client *http.Client
}
func New(name, ownerID, version, baseURL string) *Client {
return &Client{
Name: name,
OwnerID: ownerID,
Version: version,
BaseURL: strings.TrimRight(baseURL, "/") + "/",
client: &http.Client{Timeout: 30 * time.Second},
}
}
func (c *Client) Init() (map[string]interface{}, error) {
if c.EncKey == "" {
c.EncKey = randHex(18)
if len(c.EncKey) > 35 {
c.EncKey = c.EncKey[:35]
}
}
body := url.Values{
"type": {"init"},
"name": {c.Name},
"ownerid": {c.OwnerID},
"ver": {c.Version},
"enckey": {c.EncKey},
}
if c.Hash != "" {
body.Set("hash", c.Hash)
}
res, err := c.post(body)
if err != nil {
return nil, err
}
if ok, _ := res["success"].(bool); !ok {
return nil, fmt.Errorf("%v", res["message"])
}
if sid, ok := res["sessionid"].(string); ok {
c.SessionID = sid
}
return res, nil
}
func (c *Client) Login(user, pass, hwid string) (map[string]interface{}, error) {
return c.auth(url.Values{
"type": {"login"},
"username": {user},
"pass": {pass},
"hwid": {hwid},
})
}
func (c *Client) License(key, hwid string) (map[string]interface{}, error) {
return c.auth(url.Values{
"type": {"license"},
"key": {key},
"hwid": {hwid},
})
}
func (c *Client) Register(user, pass, key, hwid string) (map[string]interface{}, error) {
return c.auth(url.Values{
"type": {"register"},
"username": {user},
"pass": {pass},
"key": {key},
"hwid": {hwid},
})
}
func (c *Client) auth(extra url.Values) (map[string]interface{}, error) {
res, err := c.post(extra)
if err != nil {
return nil, err
}
if ok, _ := res["success"].(bool); !ok {
return nil, fmt.Errorf("%v", res["message"])
}
if info, ok := res["info"].(map[string]interface{}); ok {
return info, nil
}
return res, nil
}
func (c *Client) post(extra url.Values) (map[string]interface{}, error) {
extra.Set("name", c.Name)
extra.Set("ownerid", c.OwnerID)
if c.SessionID != "" {
extra.Set("sessionid", c.SessionID)
}
req, err := http.NewRequest(http.MethodPost, c.BaseURL, strings.NewReader(extra.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 429 {
return nil, fmt.Errorf("rate limited")
}
raw, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var out map[string]interface{}
if err := json.Unmarshal(raw, &out); err != nil {
return nil, err
}
return out, nil
}
func randHex(n int) string {
const hex = "0123456789abcdef"
b := make([]byte, n)
for i := range b {
b[i] = hex[time.Now().UnixNano()%16]
time.Sleep(time.Nanosecond)
}
return string(b)
}