242 lines
6.7 KiB
Go
242 lines
6.7 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type Client struct {
|
|
baseURL string
|
|
httpClient *http.Client
|
|
token string
|
|
}
|
|
|
|
type Account struct {
|
|
ID int64 `json:"id"`
|
|
AccountNumber string `json:"accountNumber"`
|
|
BalanceUSD float64 `json:"balanceUsd"`
|
|
IsActive bool `json:"isActive"`
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
ActivatedAt *time.Time `json:"activatedAt,omitempty"`
|
|
LastBillingDate time.Time `json:"lastBillingDate"`
|
|
}
|
|
|
|
type Payment struct {
|
|
ID int64 `json:"id"`
|
|
AccountID int64 `json:"accountId"`
|
|
PaymentType string `json:"paymentType"`
|
|
BTCAddress string `json:"btcAddress,omitempty"`
|
|
BTCAmount float64 `json:"btcAmount,omitempty"`
|
|
USDAmount float64 `json:"usdAmount"`
|
|
Confirmations int `json:"confirmations"`
|
|
TxHash string `json:"txHash,omitempty"`
|
|
Status string `json:"status"`
|
|
ExpiresAt *time.Time `json:"expiresAt,omitempty"`
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
ConfirmedAt *time.Time `json:"confirmedAt,omitempty"`
|
|
}
|
|
|
|
type Bucket struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
OwnerID int64 `json:"ownerId"`
|
|
StorageUsedBytes int64 `json:"storageUsedBytes"`
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
}
|
|
|
|
type Object struct {
|
|
ID int64 `json:"id"`
|
|
BucketID int64 `json:"bucketId"`
|
|
Key string `json:"key"`
|
|
SizeBytes int64 `json:"sizeBytes"`
|
|
ContentType string `json:"contentType"`
|
|
LastModified time.Time `json:"lastModified"`
|
|
VersionID string `json:"versionId"`
|
|
MD5Checksum string `json:"md5Checksum"`
|
|
CustomMetadata map[string]interface{} `json:"customMetadata"`
|
|
}
|
|
|
|
func NewClient(baseURL, token string) *Client {
|
|
return &Client{
|
|
baseURL: baseURL,
|
|
httpClient: &http.Client{
|
|
Timeout: 30 * time.Second,
|
|
},
|
|
token: token,
|
|
}
|
|
}
|
|
|
|
func (c *Client) makeRequest(ctx context.Context, method, path string, body interface{}, result interface{}) error {
|
|
var reqBody io.Reader
|
|
if body != nil {
|
|
jsonData, err := json.Marshal(body)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal request body: %w", err)
|
|
}
|
|
reqBody = bytes.NewBuffer(jsonData)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, method, c.baseURL+path, reqBody)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
|
|
if body != nil {
|
|
req.Header.Set("Content-Type", "application/json")
|
|
}
|
|
if c.token != "" {
|
|
req.Header.Set("X-Access-Token", c.token)
|
|
}
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return fmt.Errorf("request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 400 {
|
|
body, _ := io.ReadAll(resp.Body)
|
|
return fmt.Errorf("server error %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
if result != nil && resp.StatusCode != http.StatusNoContent {
|
|
if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
|
|
return fmt.Errorf("failed to decode response: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) CreateAccount(ctx context.Context) (*Account, error) {
|
|
var account Account
|
|
err := c.makeRequest(ctx, "POST", "/api/accounts", nil, &account)
|
|
return &account, err
|
|
}
|
|
|
|
func (c *Client) GetAccount(ctx context.Context) (*Account, error) {
|
|
var account Account
|
|
err := c.makeRequest(ctx, "GET", "/api/account", nil, &account)
|
|
return &account, err
|
|
}
|
|
|
|
func (c *Client) CreatePayment(ctx context.Context, usdAmount float64) (*Payment, error) {
|
|
req := map[string]interface{}{
|
|
"usd_amount": usdAmount,
|
|
}
|
|
var payment Payment
|
|
err := c.makeRequest(ctx, "POST", "/api/payments", req, &payment)
|
|
return &payment, err
|
|
}
|
|
|
|
func (c *Client) GetPayment(ctx context.Context, paymentID int64) (*Payment, error) {
|
|
var payment Payment
|
|
path := fmt.Sprintf("/api/payments/%d", paymentID)
|
|
err := c.makeRequest(ctx, "GET", path, nil, &payment)
|
|
return &payment, err
|
|
}
|
|
|
|
func (c *Client) GetPayments(ctx context.Context) ([]Payment, error) {
|
|
var payments []Payment
|
|
err := c.makeRequest(ctx, "GET", "/api/payments", nil, &payments)
|
|
return payments, err
|
|
}
|
|
|
|
func (c *Client) CreateBucket(ctx context.Context, name string) (*Bucket, error) {
|
|
req := map[string]interface{}{
|
|
"name": name,
|
|
}
|
|
var bucket Bucket
|
|
err := c.makeRequest(ctx, "PUT", "/api/buckets/"+name, req, &bucket)
|
|
return &bucket, err
|
|
}
|
|
|
|
func (c *Client) ListBuckets(ctx context.Context) ([]Bucket, error) {
|
|
var buckets []Bucket
|
|
err := c.makeRequest(ctx, "GET", "/api/buckets", nil, &buckets)
|
|
return buckets, err
|
|
}
|
|
|
|
func (c *Client) GetBucket(ctx context.Context, name string) (*Bucket, error) {
|
|
var bucket Bucket
|
|
path := fmt.Sprintf("/api/buckets/%s", name)
|
|
err := c.makeRequest(ctx, "GET", path, nil, &bucket)
|
|
return &bucket, err
|
|
}
|
|
|
|
func (c *Client) DeleteBucket(ctx context.Context, name string) error {
|
|
path := fmt.Sprintf("/api/buckets/%s", name)
|
|
return c.makeRequest(ctx, "DELETE", path, nil, nil)
|
|
}
|
|
|
|
func (c *Client) ListObjects(ctx context.Context, bucketName string) ([]Object, error) {
|
|
var objects []Object
|
|
path := fmt.Sprintf("/api/buckets/%s/objects", bucketName)
|
|
err := c.makeRequest(ctx, "GET", path, nil, &objects)
|
|
return objects, err
|
|
}
|
|
|
|
func (c *Client) PutObject(ctx context.Context, bucketName, key string, data []byte, contentType string) error {
|
|
req, err := http.NewRequestWithContext(ctx, "PUT",
|
|
fmt.Sprintf("%s/api/buckets/%s/objects/%s", c.baseURL, bucketName, key),
|
|
bytes.NewReader(data))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if contentType != "" {
|
|
req.Header.Set("Content-Type", contentType)
|
|
}
|
|
if c.token != "" {
|
|
req.Header.Set("X-Access-Token", c.token)
|
|
}
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 400 {
|
|
body, _ := io.ReadAll(resp.Body)
|
|
return fmt.Errorf("upload failed %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) GetObject(ctx context.Context, bucketName, key string) ([]byte, error) {
|
|
req, err := http.NewRequestWithContext(ctx, "GET",
|
|
fmt.Sprintf("%s/api/buckets/%s/objects/%s", c.baseURL, bucketName, key), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if c.token != "" {
|
|
req.Header.Set("X-Access-Token", c.token)
|
|
}
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 400 {
|
|
body, _ := io.ReadAll(resp.Body)
|
|
return nil, fmt.Errorf("download failed %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
return io.ReadAll(resp.Body)
|
|
}
|
|
|
|
func (c *Client) DeleteObject(ctx context.Context, bucketName, key string) error {
|
|
path := fmt.Sprintf("/api/buckets/%s/objects/%s", bucketName, key)
|
|
return c.makeRequest(ctx, "DELETE", path, nil, nil)
|
|
}
|