173 lines
3.9 KiB
Go
173 lines
3.9 KiB
Go
package porkbun
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
const BaseURL = "https://api.porkbun.com/api/json/v3"
|
|
|
|
type Client struct {
|
|
APIKey string
|
|
SecretAPIKey string
|
|
HTTPClient *http.Client
|
|
}
|
|
|
|
func New(apiKey, secretKey string) *Client {
|
|
return &Client{
|
|
APIKey: apiKey,
|
|
SecretAPIKey: secretKey,
|
|
HTTPClient: &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Get all domain names in account. Domains are returned in chunks of 1000.
|
|
func (c *Client) DomainListAll(start int, includeLabels bool) (*DomainListAllResponse, error) {
|
|
reqBody := DomainListAllRequest{
|
|
BaseRequest: BaseRequest{
|
|
APIKey: c.APIKey,
|
|
SecretAPIKey: c.SecretAPIKey,
|
|
},
|
|
Start: start,
|
|
IncludeLabels: "no",
|
|
}
|
|
if includeLabels {
|
|
reqBody.IncludeLabels = "yes"
|
|
}
|
|
|
|
var resp DomainListAllResponse
|
|
err := c.post("/domain/listAll", reqBody, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &resp, nil
|
|
}
|
|
|
|
func (c *Client) RetrieveDNSRecords(domain string) (*DNSRecordsResponse, error) {
|
|
reqBody := DNSRecordsRequest{
|
|
BaseRequest: BaseRequest{
|
|
APIKey: c.APIKey,
|
|
SecretAPIKey: c.SecretAPIKey,
|
|
},
|
|
}
|
|
|
|
var resp DNSRecordsResponse
|
|
err := c.post("/dns/retrieve/"+domain, reqBody, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &resp, nil
|
|
}
|
|
|
|
func (c *Client) CreateDNSRecord(domain string, record DNSRecord) error {
|
|
reqBody := struct {
|
|
BaseRequest
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Content string `json:"content"`
|
|
TTL string `json:"ttl,omitempty"`
|
|
Priority string `json:"prio,omitempty"`
|
|
}{
|
|
BaseRequest: BaseRequest{
|
|
APIKey: c.APIKey,
|
|
SecretAPIKey: c.SecretAPIKey,
|
|
},
|
|
Name: record.Name,
|
|
Type: record.Type,
|
|
Content: record.Content,
|
|
TTL: fmt.Sprintf("%v", record.TTL),
|
|
Priority: fmt.Sprintf("%v", record.Priority),
|
|
}
|
|
|
|
var resp BaseResponse
|
|
return c.post("/dns/create/"+domain, reqBody, &resp)
|
|
}
|
|
|
|
func (c *Client) EditDNSRecord(domain string, id string, record DNSRecord) error {
|
|
reqBody := struct {
|
|
BaseRequest
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Content string `json:"content"`
|
|
TTL string `json:"ttl,omitempty"`
|
|
Priority string `json:"prio,omitempty"`
|
|
}{
|
|
BaseRequest: BaseRequest{
|
|
APIKey: c.APIKey,
|
|
SecretAPIKey: c.SecretAPIKey,
|
|
},
|
|
Name: record.Name,
|
|
Type: record.Type,
|
|
Content: record.Content,
|
|
TTL: fmt.Sprintf("%v", record.TTL),
|
|
Priority: fmt.Sprintf("%v", record.Priority),
|
|
}
|
|
|
|
var resp BaseResponse
|
|
return c.post("/dns/edit/"+domain+"/"+id, reqBody, &resp)
|
|
}
|
|
|
|
func (c *Client) DeleteDNSRecord(domain, id string) error {
|
|
reqBody := struct {
|
|
BaseRequest
|
|
}{
|
|
BaseRequest: BaseRequest{
|
|
APIKey: c.APIKey,
|
|
SecretAPIKey: c.SecretAPIKey,
|
|
},
|
|
}
|
|
var resp BaseResponse
|
|
return c.post("/dns/delete/"+domain+"/"+id, reqBody, &resp)
|
|
}
|
|
|
|
func (c *Client) Ping() (*PingResponse, error) {
|
|
reqBody := PingRequest{
|
|
BaseRequest: BaseRequest{
|
|
APIKey: c.APIKey,
|
|
SecretAPIKey: c.SecretAPIKey,
|
|
},
|
|
}
|
|
|
|
var resp PingResponse
|
|
err := c.post("/ping", reqBody, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &resp, nil
|
|
}
|
|
|
|
func (c *Client) post(endpoint string, body any, target any) error {
|
|
jsonBody, err := json.Marshal(body)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal request body: %w", err)
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", BaseURL+endpoint, bytes.NewBuffer(jsonBody))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
res, err := c.HTTPClient.Do(req)
|
|
if err != nil {
|
|
return fmt.Errorf("request failed: %w", err)
|
|
}
|
|
defer res.Body.Close()
|
|
|
|
if res.StatusCode >= 400 {
|
|
return fmt.Errorf("API returned error status: %d", res.StatusCode)
|
|
}
|
|
|
|
if err := json.NewDecoder(res.Body).Decode(target); err != nil {
|
|
return fmt.Errorf("failed to decode response: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|