const axios = require('axios'); const API_BASE = 'https://my.zone.id/api'; class ZoneIdAPI { constructor() { this.accessToken = null; this.refreshTokenCookie = null; this.client = axios.create({ baseURL: API_BASE, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'application/json', 'Content-Type': 'application/json', 'Origin': 'https://my.zone.id', 'Referer': 'https://my.zone.id/' } }); this.client.interceptors.request.use((config) => { if (this.accessToken) { config.headers.Authorization = `Bearer ${this.accessToken}`; } if (this.refreshTokenCookie) { config.headers.Cookie = this.refreshTokenCookie; } return config; }); this.client.interceptors.response.use( (response) => response, (error) => { if (error.response) { console.log('API Error:', error.response.status, error.response.data); } return Promise.reject(error); } ); } setAccessToken(token) { this.accessToken = token; } setRefreshTokenCookie(cookie) { this.refreshTokenCookie = cookie; } async refreshAccessToken() { if (!this.refreshTokenCookie) { throw new Error('No refresh token cookie set'); } const response = await this.client.post('/refresh-token'); if (response.data && response.data.token) { this.accessToken = response.data.token; } return response.data; } async getAuthUrl() { const response = await this.client.get('/authurl'); return response.data; } async authorize(code) { const response = await this.client.post('/authorize', { auth_code: code }); return response.data; } async refreshToken() { const response = await this.client.post('/refresh-token'); return response.data; } async logout() { const response = await this.client.post('/logout'); return response.data; } async listSubdomains() { const response = await this.client.get('/subdomains'); return response.data; } async createSubdomain(subdomain, suffix = 'zone.id', mode = 'dns_record', usageType, usageDescription) { const fullSubdomain = `${subdomain}.${suffix}`; console.log('Creating subdomain:', fullSubdomain); const payload = { subdomain: subdomain, suffix: suffix, mode }; if (usageType) payload.usage_type = usageType; if (usageDescription) payload.usage_description = usageDescription; console.log('Payload:', JSON.stringify(payload)); const response = await this.client.post('/subdomains', payload); console.log('Create response:', JSON.stringify(response.data)); if (!response.data || !response.data.id) { console.log('No ID in response, fetching subdomain list...'); const list = await this.listSubdomains(); if (list && list.subdomains) { const created = list.subdomains.find(d => d.subdomain === fullSubdomain); if (created) { console.log('Found created subdomain:', created.id); return created; } } } return response.data; } async getSubdomain(id) { const response = await this.client.get(`/subdomains/${id}`); return response.data; } async updateSubdomain(id, data) { const response = await this.client.patch(`/subdomains/${id}`, data); return response.data; } async deleteSubdomain(id) { const response = await this.client.delete(`/subdomains/${id}`); return response.data; } async getDnsRecords(subdomainId) { const response = await this.client.get(`/subdomains/${subdomainId}/dns`); return response.data; } async createDnsRecord(subdomainId, record) { const normalizedRecord = { type: record.type, hostname: record.hostname || record.name, content: record.content || record.value }; if (record.note) normalizedRecord.note = record.note; const response = await this.client.post(`/subdomains/${subdomainId}/dns`, normalizedRecord); return response.data; } async updateDnsRecord(subdomainId, recordId, record) { const normalizedRecord = {}; if (record.type) normalizedRecord.type = record.type; if (record.hostname || record.name) normalizedRecord.hostname = record.hostname || record.name; if (record.content || record.value) normalizedRecord.content = record.content || record.value; if (record.note) normalizedRecord.note = record.note; const response = await this.client.patch(`/subdomains/${subdomainId}/dns/${recordId}`, normalizedRecord); return response.data; } async deleteDnsRecord(subdomainId, recordId) { const response = await this.client.delete(`/subdomains/${subdomainId}/dns/${recordId}`); return response.data; } async getUrlForwarder(subdomainId) { const response = await this.client.get(`/subdomains/${subdomainId}/url_forwarder`); return response.data; } async createUrlForwarder(subdomainId, forwarder) { const response = await this.client.post(`/subdomains/${subdomainId}/url_forwarder`, forwarder); return response.data; } async getFeatured() { const response = await this.client.get('/featured'); return response.data; } async getOfficial() { const response = await this.client.get('/official'); return response.data; } } module.exports = { ZoneIdAPI };