Files
awesome-copilot/skills/namecheap/namecheap.sh
T
2026-05-29 13:57:49 -04:00

920 lines
30 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
# Namecheap API CLI wrapper
# Usage: ./namecheap.sh <command> [options]
NAMECHEAP_API_URL="https://api.namecheap.com/xml.response"
CONFIG_FILE="$HOME/.namecheap-api"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
print_error() { echo -e "${RED}Error:${NC} $1" >&2; }
print_success() { echo -e "${GREEN}${NC} $1"; }
print_info() { echo -e "${CYAN}${NC} $1"; }
print_warn() { echo -e "${YELLOW}${NC} $1"; }
# Load configuration
load_config() {
if [[ -f "$CONFIG_FILE" ]]; then
# shellcheck source=/dev/null
source "$CONFIG_FILE"
fi
}
# Check if credentials are configured
check_credentials() {
load_config
if [[ -z "${NAMECHEAP_API_USER:-}" || -z "${NAMECHEAP_API_KEY:-}" ]]; then
print_error "Namecheap API credentials not configured."
echo ""
echo "Run './namecheap.sh setup' to configure your credentials."
echo ""
echo "You need:"
echo " 1. Your Namecheap username"
echo " 2. An API key from: https://ap.www.namecheap.com/settings/tools/apiaccess/"
echo " 3. Your public IP whitelisted in the API settings"
exit 1
fi
}
# Get public IP address
get_public_ip() {
curl -s https://api.ipify.org 2>/dev/null || curl -s https://ifconfig.me 2>/dev/null || echo "unknown"
}
# Make API request
api_request() {
local command="$1"
shift
local extra_params=("$@")
check_credentials
local client_ip
client_ip=$(get_public_ip)
local url="${NAMECHEAP_API_URL}?ApiUser=${NAMECHEAP_API_USER}&ApiKey=${NAMECHEAP_API_KEY}&UserName=${NAMECHEAP_API_USER}&Command=namecheap.${command}&ClientIp=${client_ip}"
for param in "${extra_params[@]}"; do
url="${url}&${param}"
done
local response
response=$(curl -s "$url")
# Check for errors in the response
if echo "$response" | grep -q 'Status="ERROR"'; then
local error_msg
error_msg=$(echo "$response" | grep -oP '(?<=<Err Code=")[^"]*"[^>]*>\K[^<]+' 2>/dev/null || echo "$response" | sed -n 's/.*<Err[^>]*>\(.*\)<\/Err>.*/\1/p')
print_error "API returned error: $error_msg"
return 1
fi
echo "$response"
}
# Parse domain into SLD and TLD
parse_domain() {
local domain="$1"
local tld sld
# Handle multi-part TLDs (e.g., co.uk, com.br)
if echo "$domain" | grep -qE '\.(co|com|net|org|gov)\.[a-z]{2}$'; then
tld=$(echo "$domain" | grep -oE '\.[^.]+\.[^.]+$' | sed 's/^\.//')
sld=$(echo "$domain" | sed "s/\.${tld}$//")
else
tld="${domain##*.}"
sld="${domain%.*}"
fi
echo "$sld" "$tld"
}
# Format XML DNS records as a table
format_dns_records() {
local xml="$1"
# Extract host records
echo ""
printf "%-20s %-8s %-40s %-8s %-6s\n" "HOST" "TYPE" "ADDRESS" "TTL" "MXPREF"
printf "%-20s %-8s %-40s %-8s %-6s\n" "----" "----" "-------" "---" "------"
echo "$xml" | grep -oP '<host[^/]*/>' | while read -r line; do
local name type address ttl mxpref
name=$(echo "$line" | grep -oP 'Name="\K[^"]+' || echo "")
type=$(echo "$line" | grep -oP 'Type="\K[^"]+' || echo "")
address=$(echo "$line" | grep -oP 'Address="\K[^"]+' || echo "")
ttl=$(echo "$line" | grep -oP 'TTL="\K[^"]+' || echo "1800")
mxpref=$(echo "$line" | grep -oP 'MXPref="\K[^"]+' || echo "-")
printf "%-20s %-8s %-40s %-8s %-6s\n" "$name" "$type" "$address" "$ttl" "$mxpref"
done
echo ""
}
# Format domains list as a table
format_domains_list() {
local xml="$1"
echo ""
printf "%-30s %-12s %-12s %-10s\n" "DOMAIN" "EXPIRES" "LOCKED" "AUTO-RENEW"
printf "%-30s %-12s %-12s %-10s\n" "------" "-------" "------" "----------"
echo "$xml" | grep -oP '<Domain[^/]*/>' | while read -r line; do
local name expires locked autorenew
name=$(echo "$line" | grep -oP 'Name="\K[^"]+' || echo "")
expires=$(echo "$line" | grep -oP 'Expires="\K[^"]+' || echo "")
locked=$(echo "$line" | grep -oP 'IsLocked="\K[^"]+' || echo "")
autorenew=$(echo "$line" | grep -oP 'AutoRenew="\K[^"]+' || echo "")
printf "%-30s %-12s %-12s %-10s\n" "$name" "$expires" "$locked" "$autorenew"
done
echo ""
}
# Commands
cmd_setup() {
echo "=== Namecheap API Setup ==="
echo ""
# Show public IP
local public_ip
public_ip=$(get_public_ip)
print_info "Your public IP address is: ${CYAN}${public_ip}${NC}"
echo ""
echo "Make sure this IP is whitelisted at:"
echo " https://ap.www.namecheap.com/settings/tools/apiaccess/"
echo ""
# Check existing config
if [[ -f "$CONFIG_FILE" ]]; then
load_config
if [[ -n "${NAMECHEAP_API_USER:-}" ]]; then
print_info "Existing configuration found for user: ${NAMECHEAP_API_USER}"
echo ""
# Test the connection
echo "Testing API connection..."
if api_request "domains.getList" "PageSize=1" > /dev/null 2>&1; then
print_success "API connection successful!"
else
print_error "API connection failed. Please check your credentials and IP whitelist."
fi
return 0
fi
fi
# Prompt for credentials
echo "Enter your Namecheap credentials:"
echo ""
read -rp " API Username: " api_user
read -rsp " API Key: " api_key
echo ""
echo ""
if [[ -z "$api_user" || -z "$api_key" ]]; then
print_error "Both username and API key are required."
exit 1
fi
# Save configuration
cat > "$CONFIG_FILE" << EOF
NAMECHEAP_API_USER="${api_user}"
NAMECHEAP_API_KEY="${api_key}"
EOF
chmod 600 "$CONFIG_FILE"
print_success "Credentials saved to ${CONFIG_FILE}"
echo ""
# Test connection
load_config
echo "Testing API connection..."
if api_request "domains.getList" "PageSize=1" > /dev/null 2>&1; then
print_success "API connection successful!"
else
print_warn "API connection failed. Please verify:"
echo " 1. API access is enabled (ON) at the Namecheap settings page"
echo " 2. IP address ${public_ip} is whitelisted"
echo " 3. Your API key is correct"
fi
}
cmd_domains_list() {
local list_type="ALL"
local search_term=""
local page="1"
local page_size="20"
while [[ $# -gt 0 ]]; do
case "$1" in
--type) list_type="$2"; shift 2 ;;
--search) search_term="$2"; shift 2 ;;
--page) page="$2"; shift 2 ;;
--page-size) page_size="$2"; shift 2 ;;
*) shift ;;
esac
done
local params=("ListType=${list_type}" "Page=${page}" "PageSize=${page_size}")
if [[ -n "$search_term" ]]; then
params+=("SearchTerm=${search_term}")
fi
print_info "Fetching domain list..."
local response
response=$(api_request "domains.getList" "${params[@]}")
format_domains_list "$response"
}
cmd_dns_get_hosts() {
local domain=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" ]]; then
print_error "Domain is required. Usage: ./namecheap.sh domains.dns.getHosts --domain example.com"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Fetching DNS records for ${domain} (SLD=${sld}, TLD=${tld})..."
local response
response=$(api_request "domains.dns.getHosts" "SLD=${sld}" "TLD=${tld}")
format_dns_records "$response"
}
cmd_dns_set_hosts() {
local domain=""
local hosts_file=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--hosts) hosts_file="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$hosts_file" ]]; then
print_error "Both --domain and --hosts are required."
echo "Usage: ./namecheap.sh domains.dns.setHosts --domain example.com --hosts hosts.json"
exit 1
fi
if [[ ! -f "$hosts_file" ]]; then
print_error "Hosts file not found: ${hosts_file}"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
# Build host parameters from JSON file
local params=("SLD=${sld}" "TLD=${tld}")
local i=1
while IFS= read -r line; do
local hostname recordtype address ttl mxpref
hostname=$(echo "$line" | grep -oP '"HostName"\s*:\s*"\K[^"]+' || echo "")
recordtype=$(echo "$line" | grep -oP '"RecordType"\s*:\s*"\K[^"]+' || echo "")
address=$(echo "$line" | grep -oP '"Address"\s*:\s*"\K[^"]+' || echo "")
ttl=$(echo "$line" | grep -oP '"TTL"\s*:\s*"\K[^"]+' || echo "1800")
mxpref=$(echo "$line" | grep -oP '"MXPref"\s*:\s*"\K[^"]+' || echo "")
if [[ -n "$hostname" && -n "$recordtype" && -n "$address" ]]; then
params+=("HostName${i}=${hostname}")
params+=("RecordType${i}=${recordtype}")
params+=("Address${i}=${address}")
params+=("TTL${i}=${ttl}")
if [[ -n "$mxpref" ]]; then
params+=("MXPref${i}=${mxpref}")
fi
((i++))
fi
done < <(python3 -c "
import json, sys
with open('${hosts_file}') as f:
records = json.load(f)
for r in records:
print(json.dumps(r))
" 2>/dev/null || jq -c '.[]' "$hosts_file")
if [[ $i -eq 1 ]]; then
print_error "No valid host records found in ${hosts_file}"
exit 1
fi
print_info "Setting $((i-1)) DNS records for ${domain}..."
local response
response=$(api_request "domains.dns.setHosts" "${params[@]}")
if echo "$response" | grep -q 'IsSuccess="true"'; then
print_success "DNS records updated successfully for ${domain}!"
else
print_error "Failed to update DNS records."
echo "$response"
fi
}
cmd_dns_add_host() {
local domain="" record_type="" name="" address="" ttl="1800" mxpref=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--type) record_type="$2"; shift 2 ;;
--name) name="$2"; shift 2 ;;
--address) address="$2"; shift 2 ;;
--ttl) ttl="$2"; shift 2 ;;
--mxpref) mxpref="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$record_type" || -z "$name" || -z "$address" ]]; then
print_error "Missing required parameters."
echo "Usage: ./namecheap.sh dns.addHost --domain example.com --type A --name \"@\" --address \"1.2.3.4\" [--ttl 1800] [--mxpref 10]"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
# Fetch existing records
print_info "Fetching existing DNS records for ${domain}..."
local response
response=$(api_request "domains.dns.getHosts" "SLD=${sld}" "TLD=${tld}")
# Build params with existing records + new one
local params=("SLD=${sld}" "TLD=${tld}")
local i=1
# Parse existing records
while IFS= read -r line; do
if [[ -z "$line" ]]; then continue; fi
local h_name h_type h_address h_ttl h_mxpref
h_name=$(echo "$line" | grep -oP 'Name="\K[^"]+' || echo "")
h_type=$(echo "$line" | grep -oP 'Type="\K[^"]+' || echo "")
h_address=$(echo "$line" | grep -oP 'Address="\K[^"]+' || echo "")
h_ttl=$(echo "$line" | grep -oP 'TTL="\K[^"]+' || echo "1800")
h_mxpref=$(echo "$line" | grep -oP 'MXPref="\K[^"]+' || echo "")
if [[ -n "$h_name" && -n "$h_type" && -n "$h_address" ]]; then
params+=("HostName${i}=${h_name}")
params+=("RecordType${i}=${h_type}")
params+=("Address${i}=${h_address}")
params+=("TTL${i}=${h_ttl}")
if [[ -n "$h_mxpref" && "$h_mxpref" != "0" ]]; then
params+=("MXPref${i}=${h_mxpref}")
fi
((i++))
fi
done < <(echo "$response" | grep -oP '<host[^/]*/>')
# Add the new record
params+=("HostName${i}=${name}")
params+=("RecordType${i}=${record_type}")
params+=("Address${i}=${address}")
params+=("TTL${i}=${ttl}")
if [[ -n "$mxpref" ]]; then
params+=("MXPref${i}=${mxpref}")
fi
print_info "Adding ${record_type} record: ${name} -> ${address}"
local set_response
set_response=$(api_request "domains.dns.setHosts" "${params[@]}")
if echo "$set_response" | grep -q 'IsSuccess="true"'; then
print_success "DNS record added successfully!"
else
print_error "Failed to add DNS record."
echo "$set_response"
fi
}
cmd_dns_remove_host() {
local domain="" record_type="" name="" address=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--type) record_type="$2"; shift 2 ;;
--name) name="$2"; shift 2 ;;
--address) address="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$record_type" || -z "$name" ]]; then
print_error "Missing required parameters."
echo "Usage: ./namecheap.sh dns.removeHost --domain example.com --type A --name \"@\" [--address \"1.2.3.4\"]"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
# Fetch existing records
print_info "Fetching existing DNS records for ${domain}..."
local response
response=$(api_request "domains.dns.getHosts" "SLD=${sld}" "TLD=${tld}")
# Build params excluding the record to remove
local params=("SLD=${sld}" "TLD=${tld}")
local i=1
local removed=false
while IFS= read -r line; do
if [[ -z "$line" ]]; then continue; fi
local h_name h_type h_address h_ttl h_mxpref
h_name=$(echo "$line" | grep -oP 'Name="\K[^"]+' || echo "")
h_type=$(echo "$line" | grep -oP 'Type="\K[^"]+' || echo "")
h_address=$(echo "$line" | grep -oP 'Address="\K[^"]+' || echo "")
h_ttl=$(echo "$line" | grep -oP 'TTL="\K[^"]+' || echo "1800")
h_mxpref=$(echo "$line" | grep -oP 'MXPref="\K[^"]+' || echo "")
# Check if this is the record to remove
if [[ "$h_name" == "$name" && "$h_type" == "$record_type" && "$removed" == "false" ]]; then
if [[ -z "$address" || "$h_address" == "$address" ]]; then
removed=true
print_info "Removing record: ${h_name} ${h_type} ${h_address}"
continue
fi
fi
if [[ -n "$h_name" && -n "$h_type" && -n "$h_address" ]]; then
params+=("HostName${i}=${h_name}")
params+=("RecordType${i}=${h_type}")
params+=("Address${i}=${h_address}")
params+=("TTL${i}=${h_ttl}")
if [[ -n "$h_mxpref" && "$h_mxpref" != "0" ]]; then
params+=("MXPref${i}=${h_mxpref}")
fi
((i++))
fi
done < <(echo "$response" | grep -oP '<host[^/]*/>')
if [[ "$removed" == "false" ]]; then
print_error "No matching record found to remove."
exit 1
fi
# If no records left, we still need at least one (Namecheap requirement)
if [[ $i -eq 1 ]]; then
print_error "Cannot remove the last DNS record. Namecheap requires at least one record."
exit 1
fi
print_info "Updating DNS records for ${domain}..."
local set_response
set_response=$(api_request "domains.dns.setHosts" "${params[@]}")
if echo "$set_response" | grep -q 'IsSuccess="true"'; then
print_success "DNS record removed successfully!"
else
print_error "Failed to remove DNS record."
echo "$set_response"
fi
}
cmd_public_ip() {
local ip
ip=$(get_public_ip)
echo "$ip"
}
cmd_dns_get_list() {
local domain=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" ]]; then
print_error "Domain is required. Usage: ./namecheap.sh domains.dns.getList --domain example.com"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Fetching nameservers for ${domain}..."
local response
response=$(api_request "domains.dns.getList" "SLD=${sld}" "TLD=${tld}")
local using_our_dns
using_our_dns=$(echo "$response" | grep -oP 'IsUsingOurDNS="\K[^"]+' || echo "unknown")
echo ""
print_info "Using Namecheap DNS: ${using_our_dns}"
echo ""
echo "Nameservers:"
echo "$response" | grep -oP '<Nameserver>\K[^<]+' | while read -r ns; do
echo " - ${ns}"
done
echo ""
}
cmd_dns_set_default() {
local domain=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" ]]; then
print_error "Domain is required. Usage: ./namecheap.sh domains.dns.setDefault --domain example.com"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Setting ${domain} to use Namecheap default DNS..."
local response
response=$(api_request "domains.dns.setDefault" "SLD=${sld}" "TLD=${tld}")
if echo "$response" | grep -q 'Updated="true"'; then
print_success "Domain ${domain} now uses Namecheap default DNS!"
else
print_error "Failed to set default DNS."
echo "$response"
fi
}
cmd_dns_set_custom() {
local domain="" nameservers=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--nameservers) nameservers="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$nameservers" ]]; then
print_error "Both --domain and --nameservers are required."
echo "Usage: ./namecheap.sh domains.dns.setCustom --domain example.com --nameservers ns1.cloudflare.com,ns2.cloudflare.com"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Setting ${domain} to use custom nameservers: ${nameservers}"
local response
response=$(api_request "domains.dns.setCustom" "SLD=${sld}" "TLD=${tld}" "Nameservers=${nameservers}")
if echo "$response" | grep -q 'Updated="true"'; then
print_success "Domain ${domain} now uses custom nameservers!"
else
print_error "Failed to set custom nameservers."
echo "$response"
fi
}
cmd_dns_get_email_forwarding() {
local domain=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" ]]; then
print_error "Domain is required. Usage: ./namecheap.sh domains.dns.getEmailForwarding --domain example.com"
exit 1
fi
print_info "Fetching email forwarding for ${domain}..."
local response
response=$(api_request "domains.dns.getEmailForwarding" "DomainName=${domain}")
echo ""
printf "%-20s %-40s\n" "MAILBOX" "FORWARDS TO"
printf "%-20s %-40s\n" "-------" "-----------"
echo "$response" | grep -oP '<Forward[^/]*/>' | while read -r line; do
local mailbox forward_to
mailbox=$(echo "$line" | grep -oP 'mailbox="\K[^"]+' || echo "")
forward_to=$(echo "$line" | grep -oP 'ForwardTo="\K[^"]+' || echo "")
printf "%-20s %-40s\n" "${mailbox}@${domain}" "$forward_to"
done
echo ""
}
cmd_dns_set_email_forwarding() {
local domain="" forwards_file=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--forwards) forwards_file="$2"; shift 2 ;;
--mailbox)
# Inline single forwarding rule
local inline_mailbox="$2"; shift 2 ;;
--forward-to)
local inline_forward_to="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" ]]; then
print_error "Domain is required."
echo "Usage: ./namecheap.sh domains.dns.setEmailForwarding --domain example.com --mailbox info --forward-to user@gmail.com"
echo " or: ./namecheap.sh domains.dns.setEmailForwarding --domain example.com --forwards forwards.json"
exit 1
fi
local params=("DomainName=${domain}")
if [[ -n "${inline_mailbox:-}" && -n "${inline_forward_to:-}" ]]; then
# Single inline rule
params+=("MailBox1=${inline_mailbox}" "ForwardTo1=${inline_forward_to}")
elif [[ -n "$forwards_file" ]]; then
if [[ ! -f "$forwards_file" ]]; then
print_error "Forwards file not found: ${forwards_file}"
exit 1
fi
local i=1
while IFS= read -r line; do
local mailbox forward_to
mailbox=$(echo "$line" | grep -oP '"MailBox"\s*:\s*"\K[^"]+' || echo "")
forward_to=$(echo "$line" | grep -oP '"ForwardTo"\s*:\s*"\K[^"]+' || echo "")
if [[ -n "$mailbox" && -n "$forward_to" ]]; then
params+=("MailBox${i}=${mailbox}" "ForwardTo${i}=${forward_to}")
((i++))
fi
done < <(python3 -c "
import json, sys
with open('${forwards_file}') as f:
rules = json.load(f)
for r in rules:
print(json.dumps(r))
" 2>/dev/null || jq -c '.[]' "$forwards_file")
else
print_error "Provide either --mailbox/--forward-to or --forwards <file.json>"
exit 1
fi
print_info "Setting email forwarding for ${domain}..."
local response
response=$(api_request "domains.dns.setEmailForwarding" "${params[@]}")
if echo "$response" | grep -q 'IsSuccess="true"'; then
print_success "Email forwarding updated for ${domain}!"
else
print_error "Failed to set email forwarding."
echo "$response"
fi
}
cmd_ns_create() {
local domain="" nameserver="" ip=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--nameserver) nameserver="$2"; shift 2 ;;
--ip) ip="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$nameserver" || -z "$ip" ]]; then
print_error "Missing required parameters."
echo "Usage: ./namecheap.sh domains.ns.create --domain example.com --nameserver ns1.example.com --ip 1.2.3.4"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Creating nameserver ${nameserver} -> ${ip}..."
local response
response=$(api_request "domains.ns.create" "SLD=${sld}" "TLD=${tld}" "Nameserver=${nameserver}" "IP=${ip}")
if echo "$response" | grep -q 'IsSuccess="true"'; then
print_success "Nameserver ${nameserver} created!"
else
print_error "Failed to create nameserver."
echo "$response"
fi
}
cmd_ns_delete() {
local domain="" nameserver=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--nameserver) nameserver="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$nameserver" ]]; then
print_error "Missing required parameters."
echo "Usage: ./namecheap.sh domains.ns.delete --domain example.com --nameserver ns1.example.com"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Deleting nameserver ${nameserver}..."
local response
response=$(api_request "domains.ns.delete" "SLD=${sld}" "TLD=${tld}" "Nameserver=${nameserver}")
if echo "$response" | grep -q 'IsSuccess="true"'; then
print_success "Nameserver ${nameserver} deleted!"
else
print_error "Failed to delete nameserver."
echo "$response"
fi
}
cmd_ns_get_info() {
local domain="" nameserver=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--nameserver) nameserver="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$nameserver" ]]; then
print_error "Missing required parameters."
echo "Usage: ./namecheap.sh domains.ns.getInfo --domain example.com --nameserver ns1.example.com"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Fetching info for nameserver ${nameserver}..."
local response
response=$(api_request "domains.ns.getInfo" "SLD=${sld}" "TLD=${tld}" "Nameserver=${nameserver}")
local ns_ip
ns_ip=$(echo "$response" | grep -oP 'IP="\K[^"]+' || echo "unknown")
echo ""
echo "Nameserver: ${nameserver}"
echo "IP Address: ${ns_ip}"
local statuses
statuses=$(echo "$response" | grep -oP '<Status>\K[^<]+' | tr '\n' ', ' | sed 's/,$//')
if [[ -n "$statuses" ]]; then
echo "Status: ${statuses}"
fi
echo ""
}
cmd_ns_update() {
local domain="" nameserver="" old_ip="" new_ip=""
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) domain="$2"; shift 2 ;;
--nameserver) nameserver="$2"; shift 2 ;;
--old-ip) old_ip="$2"; shift 2 ;;
--ip) new_ip="$2"; shift 2 ;;
*) shift ;;
esac
done
if [[ -z "$domain" || -z "$nameserver" || -z "$old_ip" || -z "$new_ip" ]]; then
print_error "Missing required parameters."
echo "Usage: ./namecheap.sh domains.ns.update --domain example.com --nameserver ns1.example.com --old-ip 1.2.3.4 --ip 5.6.7.8"
exit 1
fi
local sld tld
read -r sld tld <<< "$(parse_domain "$domain")"
print_info "Updating nameserver ${nameserver}: ${old_ip} -> ${new_ip}..."
local response
response=$(api_request "domains.ns.update" "SLD=${sld}" "TLD=${tld}" "Nameserver=${nameserver}" "OldIP=${old_ip}" "IP=${new_ip}")
if echo "$response" | grep -q 'IsSuccess="true"'; then
print_success "Nameserver ${nameserver} updated to ${new_ip}!"
else
print_error "Failed to update nameserver."
echo "$response"
fi
}
# Help
cmd_help() {
echo "Namecheap DNS Management CLI"
echo ""
echo "Usage: ./namecheap.sh <command> [options]"
echo ""
echo "Commands:"
echo " setup Configure API credentials and test connection"
echo " public-ip Show your public IP address"
echo ""
echo " domains.getList List your Namecheap domains"
echo ""
echo " domains.dns.getList Get nameservers for a domain"
echo " domains.dns.getHosts Get DNS records for a domain"
echo " domains.dns.setHosts Set all DNS records (from JSON file)"
echo " domains.dns.setDefault Use Namecheap default DNS"
echo " domains.dns.setCustom Use custom nameservers"
echo " domains.dns.getEmailForwarding Get email forwarding rules"
echo " domains.dns.setEmailForwarding Set email forwarding rules"
echo ""
echo " domains.ns.create Create a child nameserver (glue record)"
echo " domains.ns.delete Delete a child nameserver"
echo " domains.ns.getInfo Get nameserver info"
echo " domains.ns.update Update nameserver IP"
echo ""
echo " dns.addHost Add a single DNS record (preserves existing)"
echo " dns.removeHost Remove a single DNS record"
echo ""
echo "Options:"
echo " --domain <domain> Domain name (e.g., example.com)"
echo " --type <type> Record type (A, AAAA, CNAME, MX, TXT, etc.)"
echo " --name <hostname> Host name (e.g., @, www, mail)"
echo " --address <value> Record value (IP or target)"
echo " --ttl <seconds> TTL in seconds (default: 1800)"
echo " --mxpref <priority> MX preference (for MX records)"
echo " --hosts <file.json> JSON file with host records"
echo " --nameservers <ns,...> Comma-separated nameservers"
echo " --nameserver <ns> Nameserver hostname"
echo " --ip <address> IP address for nameserver"
echo " --old-ip <address> Current IP (for ns.update)"
echo " --mailbox <name> Email mailbox name"
echo " --forward-to <email> Forward destination email"
echo " --forwards <file.json> JSON file with forwarding rules"
echo " --search <term> Search term for domain list"
echo " --page <n> Page number for domain list"
echo " --page-size <n> Page size for domain list (10-100)"
echo ""
echo "Examples:"
echo " ./namecheap.sh setup"
echo " ./namecheap.sh domains.getList"
echo " ./namecheap.sh domains.dns.getHosts --domain example.com"
echo " ./namecheap.sh dns.addHost --domain example.com --type A --name www --address 1.2.3.4"
echo " ./namecheap.sh dns.removeHost --domain example.com --type A --name www"
echo " ./namecheap.sh domains.dns.setCustom --domain example.com --nameservers ns1.cloudflare.com,ns2.cloudflare.com"
echo " ./namecheap.sh domains.dns.setEmailForwarding --domain example.com --mailbox info --forward-to user@gmail.com"
echo " ./namecheap.sh domains.ns.create --domain example.com --nameserver ns1.example.com --ip 1.2.3.4"
}
# Main dispatch
main() {
local command="${1:-help}"
shift || true
case "$command" in
setup) cmd_setup "$@" ;;
public-ip) cmd_public_ip "$@" ;;
domains.getList) cmd_domains_list "$@" ;;
domains.dns.getList) cmd_dns_get_list "$@" ;;
domains.dns.getHosts) cmd_dns_get_hosts "$@" ;;
domains.dns.setHosts) cmd_dns_set_hosts "$@" ;;
domains.dns.setDefault) cmd_dns_set_default "$@" ;;
domains.dns.setCustom) cmd_dns_set_custom "$@" ;;
domains.dns.getEmailForwarding) cmd_dns_get_email_forwarding "$@" ;;
domains.dns.setEmailForwarding) cmd_dns_set_email_forwarding "$@" ;;
domains.ns.create) cmd_ns_create "$@" ;;
domains.ns.delete) cmd_ns_delete "$@" ;;
domains.ns.getInfo) cmd_ns_get_info "$@" ;;
domains.ns.update) cmd_ns_update "$@" ;;
dns.addHost) cmd_dns_add_host "$@" ;;
dns.removeHost) cmd_dns_remove_host "$@" ;;
help|--help|-h) cmd_help ;;
*)
print_error "Unknown command: ${command}"
echo ""
cmd_help
exit 1
;;
esac
}
main "$@"