list domains
This commit is contained in:
parent
2f18893ef2
commit
8498f6f0a7
4 changed files with 146 additions and 10 deletions
|
|
@ -26,6 +26,28 @@ func New(apiKey, secretKey string) *Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) Ping() (*PingResponse, error) {
|
func (c *Client) Ping() (*PingResponse, error) {
|
||||||
reqBody := PingRequest{
|
reqBody := PingRequest{
|
||||||
BaseRequest: BaseRequest{
|
BaseRequest: BaseRequest{
|
||||||
|
|
@ -43,7 +65,7 @@ func (c *Client) Ping() (*PingResponse, error) {
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) post(endpoint string, body interface{}, target interface{}) error {
|
func (c *Client) post(endpoint string, body any, target any) error {
|
||||||
jsonBody, err := json.Marshal(body)
|
jsonBody, err := json.Marshal(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to marshal request body: %w", err)
|
return fmt.Errorf("failed to marshal request body: %w", err)
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,37 @@ type PingResponse struct {
|
||||||
BaseResponse
|
BaseResponse
|
||||||
YourIP string `json:"yourIp"`
|
YourIP string `json:"yourIp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DomainListAllRequest is used for getting a list of all domains.
|
||||||
|
type DomainListAllRequest struct {
|
||||||
|
BaseRequest
|
||||||
|
Start int `json:"start"`
|
||||||
|
IncludeLabels string `json:"includeLabels,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainListAllResponse is the response from the domain list all endpoint.
|
||||||
|
type DomainListAllResponse struct {
|
||||||
|
BaseResponse
|
||||||
|
Domains []Domain `json:"domains"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Domain represents a single domain returned by domain endpoints.
|
||||||
|
type Domain struct {
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
TLD string `json:"tld"`
|
||||||
|
CreateDate string `json:"createDate"`
|
||||||
|
ExpireDate string `json:"expireDate"`
|
||||||
|
SecurityLock string `json:"securityLock"`
|
||||||
|
WhoIsPrivacy string `json:"whoisPrivacy"`
|
||||||
|
AutoRenew any `json:"autoRenew"`
|
||||||
|
NotLocal any `json:"notLocal"`
|
||||||
|
Labels []DomainLabel `json:"labels,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainLabel represents a label associated with a domain.
|
||||||
|
type DomainLabel struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Color string `json:"color"`
|
||||||
|
}
|
||||||
|
|
|
||||||
30
internal/ui/pages/menu/domainitem.go
Normal file
30
internal/ui/pages/menu/domainitem.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package menu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.juancwu.dev/juancwu/porkbacon/internal/porkbun"
|
||||||
|
)
|
||||||
|
|
||||||
|
func renderDomainItem(item *porkbun.Domain) string {
|
||||||
|
var b strings.Builder
|
||||||
|
b.WriteString("Domain: " + item.Domain + "\n")
|
||||||
|
b.WriteString("Status: " + item.Status + "\n")
|
||||||
|
b.WriteString("Create Date: " + item.CreateDate + "\n")
|
||||||
|
b.WriteString("Expire Date: " + item.ExpireDate + "\n")
|
||||||
|
b.WriteString("Security Lock: " + item.SecurityLock + "\n")
|
||||||
|
b.WriteString("Whois Privacy: " + item.WhoIsPrivacy + "\n")
|
||||||
|
b.WriteString(fmt.Sprintln("Auto Renew:", item.AutoRenew))
|
||||||
|
b.WriteString(fmt.Sprintln("Not Local:", item.NotLocal))
|
||||||
|
if len(item.Labels) > 0 {
|
||||||
|
b.WriteString("Labels:\n")
|
||||||
|
}
|
||||||
|
for i, label := range item.Labels {
|
||||||
|
b.WriteString("=> " + label.Title)
|
||||||
|
if i < len(item.Labels)-1 {
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
@ -6,13 +6,20 @@ import (
|
||||||
"git.juancwu.dev/juancwu/porkbacon/internal/porkbun"
|
"git.juancwu.dev/juancwu/porkbacon/internal/porkbun"
|
||||||
"git.juancwu.dev/juancwu/porkbacon/internal/ui/messages"
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/messages"
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
"github.com/charmbracelet/bubbles/paginator"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pingResultMsg struct {
|
type pingResultMsg struct {
|
||||||
IP string
|
IP string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type domainListMsg struct {
|
||||||
|
Status string
|
||||||
|
Domains []string
|
||||||
|
}
|
||||||
|
|
||||||
type menuItem struct {
|
type menuItem struct {
|
||||||
id uint8
|
id uint8
|
||||||
title, desc string
|
title, desc string
|
||||||
|
|
@ -25,7 +32,6 @@ func (i menuItem) FilterValue() string { return i.title }
|
||||||
|
|
||||||
const (
|
const (
|
||||||
domainListAll uint8 = iota
|
domainListAll uint8 = iota
|
||||||
domainGetDetails
|
|
||||||
dnsRetrieveRecords
|
dnsRetrieveRecords
|
||||||
dnsCreateRecord
|
dnsCreateRecord
|
||||||
dnsEditRecord
|
dnsEditRecord
|
||||||
|
|
@ -35,6 +41,8 @@ const (
|
||||||
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
list list.Model
|
list list.Model
|
||||||
|
paginator paginator.Model
|
||||||
|
domains []string
|
||||||
client *porkbun.Client
|
client *porkbun.Client
|
||||||
err error
|
err error
|
||||||
output string
|
output string
|
||||||
|
|
@ -43,7 +51,6 @@ type Model struct {
|
||||||
func New(client *porkbun.Client) *Model {
|
func New(client *porkbun.Client) *Model {
|
||||||
items := []list.Item{
|
items := []list.Item{
|
||||||
menuItem{id: domainListAll, title: "Domain: List All", desc: "List all domains in your account"},
|
menuItem{id: domainListAll, title: "Domain: List All", desc: "List all domains in your account"},
|
||||||
menuItem{id: domainGetDetails, title: "Domain: Get Details", desc: "Get details for a specific domain"},
|
|
||||||
menuItem{id: dnsRetrieveRecords, title: "DNS: Retrieve Records", desc: "Retrieve DNS records for a domain"},
|
menuItem{id: dnsRetrieveRecords, title: "DNS: Retrieve Records", desc: "Retrieve DNS records for a domain"},
|
||||||
menuItem{id: dnsCreateRecord, title: "DNS: Create Record", desc: "Create a new DNS record"},
|
menuItem{id: dnsCreateRecord, title: "DNS: Create Record", desc: "Create a new DNS record"},
|
||||||
menuItem{id: dnsEditRecord, title: "DNS: Edit Record", desc: "Edit an existing DNS record"},
|
menuItem{id: dnsEditRecord, title: "DNS: Edit Record", desc: "Edit an existing DNS record"},
|
||||||
|
|
@ -54,8 +61,15 @@ func New(client *porkbun.Client) *Model {
|
||||||
l := list.New(items, list.NewDefaultDelegate(), 0, 0)
|
l := list.New(items, list.NewDefaultDelegate(), 0, 0)
|
||||||
l.Title = "Porkbun Actions"
|
l.Title = "Porkbun Actions"
|
||||||
|
|
||||||
|
p := paginator.New()
|
||||||
|
p.Type = paginator.Dots
|
||||||
|
p.PerPage = 1
|
||||||
|
p.ActiveDot = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "235", Dark: "252"}).Render("•")
|
||||||
|
p.InactiveDot = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "250", Dark: "238"}).Render("•")
|
||||||
|
|
||||||
return &Model{
|
return &Model{
|
||||||
list: l,
|
list: l,
|
||||||
|
paginator: p,
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +94,16 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(m.domains) > 0 {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.paginator, cmd = m.paginator.Update(msg)
|
||||||
|
if msg.String() == "esc" {
|
||||||
|
m.domains = nil
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
|
||||||
if msg.String() == "enter" {
|
if msg.String() == "enter" {
|
||||||
i, ok := m.list.SelectedItem().(menuItem)
|
i, ok := m.list.SelectedItem().(menuItem)
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -87,6 +111,12 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case domainListMsg:
|
||||||
|
m.paginator.PerPage = 1
|
||||||
|
m.paginator.SetTotalPages(len(msg.Domains))
|
||||||
|
m.paginator.Page = 0
|
||||||
|
m.domains = msg.Domains
|
||||||
|
|
||||||
case pingResultMsg:
|
case pingResultMsg:
|
||||||
m.output = fmt.Sprintf("Ping successful!\nYour IP: %s", msg.IP)
|
m.output = fmt.Sprintf("Ping successful!\nYour IP: %s", msg.IP)
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
@ -105,12 +135,32 @@ func (m *Model) View() string {
|
||||||
if m.output != "" {
|
if m.output != "" {
|
||||||
return fmt.Sprintf("%s\n\n(Press Esc to go back)", m.output)
|
return fmt.Sprintf("%s\n\n(Press Esc to go back)", m.output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(m.domains) > 0 {
|
||||||
|
return fmt.Sprintf("%s\n\n%s\n\n(Press Esc to go back, arrows to navigate)", m.domains[m.paginator.Page], m.paginator.View())
|
||||||
|
}
|
||||||
|
|
||||||
return m.list.View()
|
return m.list.View()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) handleSelection(i menuItem) (tea.Model, tea.Cmd) {
|
func (m *Model) handleSelection(i menuItem) (tea.Model, tea.Cmd) {
|
||||||
// TODO: Implement other actions. For now, just Ping.
|
|
||||||
switch i.id {
|
switch i.id {
|
||||||
|
case domainListAll:
|
||||||
|
return m, func() tea.Msg {
|
||||||
|
resp, err := m.client.DomainListAll(0, true)
|
||||||
|
if err != nil {
|
||||||
|
return messages.ErrorMsg(err)
|
||||||
|
}
|
||||||
|
var domains []string
|
||||||
|
for _, domain := range resp.Domains {
|
||||||
|
view := renderDomainItem(&domain)
|
||||||
|
domains = append(domains, view)
|
||||||
|
}
|
||||||
|
return domainListMsg{
|
||||||
|
Status: resp.Status,
|
||||||
|
Domains: domains,
|
||||||
|
}
|
||||||
|
}
|
||||||
case utilPing:
|
case utilPing:
|
||||||
return m, func() tea.Msg {
|
return m, func() tea.Msg {
|
||||||
resp, err := m.client.Ping()
|
resp, err := m.client.Ping()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue