Spaces:
Running
Running
const soap = require('strong-soap').soap; | |
const axios = require('axios'); | |
const crypto = require('crypto'); | |
const fs = require('fs'); | |
class DomainNameAPI { | |
static VERSION = '2.0.13'; | |
constructor( | |
userName = 'ownername', password = 'ownerpass', testMode = false) { | |
this.serviceUsername = userName; | |
this.servicePassword = password; | |
this.serviceUrl = 'https://whmcs.domainnameapi.com/DomainApi.svc?singlewsdl'; | |
this.soapClientPromise = this.createSoapClient(); | |
} | |
createSoapClient() { | |
return new Promise((resolve, reject) => { | |
const options = { | |
strictSSL : false, | |
wsdl_options: { | |
timeout: 20000, | |
}, | |
}; | |
soap.createClient(this.serviceUrl, options, (err, client) => { | |
if (err) { | |
console.error('SOAP Client Creation Error:', err); | |
reject(new Error(`SOAP Connection Error: ${err.message}`)); | |
} | |
else { | |
resolve(client); | |
} | |
}); | |
}); | |
} | |
async AddChildNameServer(domainName, nameServer, ipAddress) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
ChildNameServer: nameServer, | |
IpAddressList: [ipAddress] | |
} | |
}; | |
// callApiFunction ile API çağrısı yapıyoruz | |
return this.callApiFunction('AddChildNameServer', parameters).then((response) => { | |
return { | |
data: { | |
NameServer: parameters.request.ChildNameServer, | |
IPAdresses: parameters.request.IpAddressList | |
}, | |
result: true | |
}; | |
}); | |
} | |
/** | |
* Delete Child Name Server for domain | |
* @param {string} domainName | |
* @param {string} nameServer | |
* @return {Promise<Object>} | |
*/ | |
async DeleteChildNameServer(domainName, nameServer) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
ChildNameServer: nameServer | |
} | |
}; | |
// callApiFunction ile API çağrısı yapıyoruz | |
return this.callApiFunction('DeleteChildNameServer', parameters).then((response) => { | |
return { | |
data: { | |
NameServer: parameters.request.ChildNameServer | |
}, | |
result: true | |
}; | |
}); | |
} | |
/** | |
* Modify Child Name Server for domain | |
* @param {string} domainName | |
* @param {string} nameServer | |
* @param {string} ipAddress | |
* @return {Promise<Object>} | |
*/ | |
async ModifyChildNameServer(domainName, nameServer, ipAddress) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
ChildNameServer: nameServer, | |
IpAddressList: [ipAddress] | |
} | |
}; | |
// callApiFunction ile API çağrısı yapıyoruz | |
return this.callApiFunction('ModifyChildNameServer', parameters).then((response) => { | |
return { | |
data: { | |
NameServer: parameters.request.ChildNameServer, | |
IPAdresses: parameters.request.IpAddressList | |
}, | |
result: true | |
}; | |
}); | |
} | |
/** | |
* Get Contacts for domain, Administrative, Billing, Technical, Registrant | |
* segments will be returned | |
* @param {string} domainName | |
* @return {Promise<Object>} | |
*/ | |
async GetContacts(domainName) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName | |
} | |
}; | |
return this.callApiFunction('GetContacts', parameters).then((response) => { | |
const data = response[Object.keys(response)[0]]; | |
let result = {}; | |
// Eğer ContactInfo geçerli bir nesne ise | |
if (data.AdministrativeContact && typeof data.AdministrativeContact === 'object' && | |
data.TechnicalContact && typeof data.TechnicalContact === 'object' && | |
data.RegistrantContact && typeof data.RegistrantContact === 'object' && | |
data.BillingContact && typeof data.BillingContact === 'object') { | |
result = { | |
data: { | |
contacts: { | |
Administrative: this.parseContactInfo(data.AdministrativeContact), | |
Billing: this.parseContactInfo(data.BillingContact), | |
Registrant: this.parseContactInfo(data.RegistrantContact), | |
Technical: this.parseContactInfo(data.TechnicalContact), | |
} | |
}, | |
result: true | |
}; | |
} else { | |
result = data; | |
} | |
return result; | |
}); | |
} | |
/** | |
* Save Contacts for domain, Contacts segments will be saved as Administrative, | |
* Billing, Technical, Registrant. | |
* @param {string} domainName | |
* @param {Object} contacts | |
* @return {Promise<Object>} | |
*/ | |
async SaveContacts(domainName, contacts) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
AdministrativeContact: contacts.Administrative, | |
BillingContact: contacts.Billing, | |
TechnicalContact: contacts.Technical, | |
RegistrantContact: contacts.Registrant | |
} | |
}; | |
return this.callApiFunction('SaveContacts', parameters).then((response) => { | |
const data = response[Object.keys(response)[0]]; | |
let result = {}; | |
if (data.OperationResult === 'SUCCESS') { | |
result = { | |
result: true | |
}; | |
} else { | |
// Hata durumunu ayarla | |
result = data; | |
} | |
return result; | |
}); | |
} | |
/** | |
* Transfer domain with EPP code and period | |
* @param {string} domainName | |
* @param {string} eppCode | |
* @param {string} period | |
* @return {Promise<Object>} | |
*/ | |
async Transfer(domainName, eppCode, period) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
AuthCode: eppCode, | |
AdditionalAttributes: { | |
KeyValueOfstringstring: [ | |
{ | |
Key: 'TRANSFERPERIOD', | |
Value: period | |
} | |
] | |
} | |
} | |
}; | |
return this.callApiFunction('Transfer', parameters).then((response) => { | |
const data = response[Object.keys(response)[0]]; | |
let result = {}; | |
// Eğer DomainInfo geçerli bir nesne ise | |
if (data.DomainInfo && typeof data.DomainInfo === 'object') { | |
// Domain bilgisini ayrıştır ve döndür | |
result = { | |
result: true, | |
data: this.parseDomainInfo(data.DomainInfo) | |
}; | |
} else { | |
// Hata durumunu ayarla | |
result = data; | |
} | |
return result; | |
}); | |
} | |
/** | |
* Stops Incoming Transfer | |
* @param {string} domainName | |
* @return {Promise<Object>} | |
*/ | |
async CancelTransfer(domainName) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName | |
} | |
}; | |
return this.callApiFunction('CancelTransfer', parameters).then((response) => { | |
const data = response[Object.keys(response)[0]]; | |
return { | |
result: data.result , | |
data: { | |
DomainName: parameters.request.DomainName | |
} | |
}; | |
}); | |
} | |
/** | |
* Approve Outgoing transfer | |
* @param {string} domainName | |
* @return {Promise<Object>} | |
*/ | |
async ApproveTransfer(domainName) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName | |
} | |
}; | |
return this.callApiFunction('ApproveTransfer', parameters).then((response) => { | |
const data = response[Object.keys(response)[0]]; | |
return { | |
result: data.result, | |
data: { | |
DomainName: parameters.request.DomainName | |
} | |
}; | |
}); | |
} | |
/** | |
* Reject Outgoing transfer | |
* @param {string} domainName | |
* @return {Promise<Object>} | |
*/ | |
async RejectTransfer(domainName) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName | |
} | |
}; | |
return this.callApiFunction('RejectTransfer', parameters).then((response) => { | |
const data = response[Object.keys(response)[0]]; | |
return { | |
result: data.result, | |
data: { | |
DomainName: parameters.request.DomainName | |
} | |
}; | |
}); | |
} | |
/** | |
* Renew domain | |
* @param {string} domainName | |
* @param {number} period | |
* @return {Promise<Object>} | |
*/ | |
async Renew(domainName, period) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
Period: period | |
} | |
}; | |
return this.callApiFunction('Renew', parameters).then((response) => { | |
const data = response[Object.keys(response)[0]]; | |
if (data.ExpirationDate) { | |
return { | |
result: true, | |
data: { | |
ExpirationDate: data.ExpirationDate | |
} | |
}; | |
} else { | |
return data; | |
} | |
}); | |
} | |
/** | |
* Register domain with contact information | |
* @param {string} domainName | |
* @param {number} period | |
* @param {Object} contacts | |
* @param {Array<string>} nameServers | |
* @param {boolean} eppLock | |
* @param {boolean} privacyLock | |
* @param {Object} additionalAttributes | |
* @return {Promise<Object>} | |
*/ | |
async RegisterWithContactInfo(domainName, period, contacts, nameServers = ["dns.domainnameapi.com", "web.domainnameapi.com"], eppLock = true, privacyLock = false, additionalAttributes = {}) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
Period: period, | |
NameServerList: { | |
string: nameServers | |
}, | |
LockStatus: eppLock, | |
PrivacyProtectionStatus: privacyLock, | |
AdministrativeContact: contacts.Administrative, | |
BillingContact: contacts.Billing, | |
TechnicalContact: contacts.Technical, | |
RegistrantContact: contacts.Registrant | |
} | |
}; | |
// Format AdditionalAttributes correctly | |
if (Object.keys(additionalAttributes).length > 0) { | |
parameters.request.AdditionalAttributes = { | |
KeyValueOfstringstring: Object.entries(additionalAttributes).map(([key, value]) => ({ | |
Key: key, | |
Value: value | |
})) | |
}; | |
} | |
// API çağrısı yap ve yanıtı işle | |
return this.callApiFunction('RegisterWithContactInfo', parameters).then((response) => { | |
// Handle raw number response | |
if (typeof response === 'number') { | |
return { | |
result: false, | |
level: 'error', | |
message: `Registration failed with code ${response}`, | |
ErrorCode: response | |
}; | |
} | |
const data = response; | |
let result = {}; | |
// Eğer DomainInfo geçerli bir nesne ise | |
if (data.DomainInfo && typeof data.DomainInfo === 'object') { | |
result = { | |
result: true, | |
data: this.parseDomainInfo(data.DomainInfo) | |
}; | |
} else { | |
// Hata durumunu ayarla | |
result = { | |
result: false, | |
level: 'error', | |
message: data.OperationMessage || 'Registration failed', | |
ErrorCode: data.ErrorCode || response | |
}; | |
} | |
return result; | |
}); | |
} | |
/** | |
* Modify privacy protection status of domain | |
* @param {string} domainName | |
* @param {boolean} status | |
* @param {string} [reason="Owner request"] | |
* @return {Promise<Object>} | |
*/ | |
async ModifyPrivacyProtectionStatus(domainName, status, reason = "Owner request") { | |
// Eğer reason boşsa varsayılan değeri ayarla | |
if (reason.trim() === "") { | |
reason = "Owner request"; | |
} | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName, | |
ProtectPrivacy: status, | |
Reason: reason | |
} | |
}; | |
// API çağrısı ve yanıt işleme | |
return this.callApiFunction('ModifyPrivacyProtectionStatus', parameters).then((response) => { | |
return { | |
data: { | |
PrivacyProtectionStatus: parameters.request.ProtectPrivacy | |
}, | |
result: true | |
}; | |
}); | |
} | |
/** | |
* Sync from registry, domain information will be updated from registry | |
* @param {string} domainName | |
* @return {Promise<Object>} | |
*/ | |
async SyncFromRegistry(domainName) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
DomainName: domainName | |
} | |
}; | |
// API çağrısı ve yanıt işleme | |
return this.callApiFunction('SyncFromRegistry', parameters).then((response) => { | |
const data = response; | |
let result = {}; | |
// Eğer DomainInfo geçerli bir nesne ise | |
if (data.DomainInfo && typeof data.DomainInfo === 'object') { | |
result = { | |
data: this.parseDomainInfo(data.DomainInfo), | |
result: true | |
}; | |
} else { | |
// Hata durumu | |
result = data; | |
} | |
return result; | |
}); | |
} | |
/** | |
* Get Current primary Balance for your account | |
* @param {string|number} currencyId | |
* @return {Promise<Object>} | |
*/ | |
async GetCurrentBalance(currencyId = 2) { | |
if (currencyId.toString().toUpperCase() === 'USD') { | |
currencyId = 2; | |
} else if (['TRY', 'TL', '1'].includes(currencyId.toString().toUpperCase())) { | |
currencyId = 1; | |
} else { | |
currencyId = 2; | |
} | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
CurrencyId: currencyId | |
} | |
}; | |
return this.callApiFunction('GetCurrentBalance', parameters).then((response) => { | |
return response; | |
}); | |
} | |
/** | |
* Check Availability, SLD and TLD must be in array | |
* @param {Array<string>} domains | |
* @param {Array<string>} extensions | |
* @param {number} period | |
* @param {string} command | |
* @return {Promise<Array<Object>>} | |
*/ | |
async CheckAvailability(domains, extensions, period=1, command='create') { | |
const parameters = { | |
request: { | |
Password : this.servicePassword, | |
UserName : this.serviceUsername, | |
DomainNameList: { | |
string: domains, // Array of domains | |
}, | |
TldList : { | |
string: extensions, // Array of extensions | |
}, | |
Period : period, | |
Commad : command, | |
}, | |
}; | |
return this.callApiFunction('CheckAvailability', parameters).then((response) => { | |
const data = response; | |
const available = []; | |
if (data.DomainAvailabilityInfoList?.DomainAvailabilityInfo?.Tld) { | |
const buffer = data.DomainAvailabilityInfoList.DomainAvailabilityInfo; | |
data.DomainAvailabilityInfoList = { | |
DomainAvailabilityInfo: [buffer] | |
}; | |
}else{ | |
} | |
data.DomainAvailabilityInfoList.DomainAvailabilityInfo.forEach(value => { | |
available.push({ | |
TLD: value.Tld, | |
DomainName: value.DomainName, | |
Status: value.Status, | |
Command: value.Command, | |
Period: value.Period, | |
IsFee: value.IsFee, | |
Price: value.Price, | |
Currency: value.Currency, | |
Reason: value.Reason | |
}); | |
}); | |
return available; | |
}); | |
} | |
/** | |
* Get Domain List of your account | |
* @param {Object} extraParameters | |
* @return {Promise<Object>} | |
*/ | |
async GetList(extraParameters = {}) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
...extraParameters | |
} | |
}; | |
return this.callApiFunction('GetList', parameters).then((response) => { | |
const data = response; | |
let result = {}; | |
if (data.TotalCount && Number.isInteger(data.TotalCount)) { | |
result.data = { domains: [] }; | |
if (data.DomainInfoList?.DomainInfo?.Id) { | |
result.data.domains.push(data.DomainInfoList.DomainInfo); | |
} else { | |
data.DomainInfoList.DomainInfo.forEach(domainInfo => { | |
result.data.domains.push(this.parseDomainInfo(domainInfo)); | |
}); | |
} | |
result.result = true; | |
result.totalCount = data.TotalCount; | |
} else { | |
result= data; | |
} | |
return result; | |
}); | |
} | |
/** | |
* Return tld list and pricing matrix | |
* @param {number} count | |
* @return {Promise<Object>} | |
*/ | |
async GetTldList(count = 20) { | |
const parameters = { | |
request: { | |
Password: this.servicePassword, | |
UserName: this.serviceUsername, | |
IncludePriceDefinitions: 1, | |
PageSize: count | |
} | |
}; | |
return this.callApiFunction('GetTldList', parameters).then((response) => { | |
const data = response; | |
let result = {}; | |
if (data.TldInfoList.TldInfo.length > 0) { | |
const extensions = data.TldInfoList.TldInfo.map(v => { | |
const pricing = {}; | |
const currencies = {}; | |
v.PriceInfoList.TldPriceInfo.forEach(vp => { | |
pricing[vp.TradeType.toLowerCase()] = { | |
[vp.Period]: vp.Price | |
}; | |
currencies[vp.TradeType.toLowerCase()] = vp.CurrencyName; | |
}); | |
return { | |
id: v.Id, | |
status: v.Status, | |
maxchar: v.MaxCharacterCount, | |
maxperiod: v.MaxRegistrationPeriod, | |
minchar: v.MinCharacterCount, | |
minperiod: v.MinRegistrationPeriod, | |
tld: v.Name, | |
pricing, | |
currencies | |
}; | |
}); | |
result = { data: extensions, result: true }; | |
} else { | |
result = data | |
} | |
return result; | |
}); | |
} | |
/** | |
* Get Domain details | |
* @param {string} domainName | |
* @return {Promise<Object>} | |
*/ | |
async GetDetails(domainName) { | |
const parameters = { | |
request: { | |
Password : this.servicePassword, | |
UserName : this.serviceUsername, | |
DomainName: domainName, | |
}, | |
}; | |
return this.callApiFunction('GetDetails', parameters).then((response) => { | |
const data = response; | |
let result = {}; | |
if (data.DomainInfo && typeof data.DomainInfo === 'object') { | |
result.data = this.parseDomainInfo(data.DomainInfo); | |
result.result = true; | |
} | |
else { | |
result = data; | |
} | |
return result; | |
}); | |
} | |
/** | |
* Get Reseller Details | |
* @returns {Promise<{result: boolean, name: (string|string|*), active: | |
* boolean, id: (string|*)}>} | |
* @constructor | |
*/ | |
async GetResellerDetails() { | |
const parameters = { | |
request: { | |
UserName : this.serviceUsername, | |
Password : this.servicePassword, | |
CurrencyId: 2, | |
}, | |
}; | |
return this.callApiFunction('GetResellerDetails', parameters). | |
then((data) => { | |
if (data && data.ResellerInfo) { | |
let resp = { | |
result: true, | |
id : data.ResellerInfo.Id, | |
active: data.ResellerInfo.Status === 'Active', | |
name : data.ResellerInfo.Name, | |
}; | |
let activeCurrency = data.ResellerInfo.BalanceInfoList.BalanceInfo[0]; | |
let balances = []; | |
data.ResellerInfo.BalanceInfoList.BalanceInfo.forEach((v) => { | |
if (v.CurrencyName === data.ResellerInfo.CurrencyInfo.Code) { | |
activeCurrency = v; | |
} | |
balances.push({ | |
balance : v.Balance, | |
currency: v.CurrencyName, | |
symbol : v.CurrencySymbol, | |
}); | |
}); | |
resp.balance = activeCurrency.Balance; | |
resp.currency = activeCurrency.CurrencyName; | |
resp.symbol = activeCurrency.CurrencySymbol; | |
resp.balances = balances; | |
// Şu noktada resp objesi işleme alınabilir | |
return resp; | |
} | |
else { | |
return {result: false, ...data}; | |
} | |
}); | |
} | |
/** | |
* Parse domain information | |
* @param {Object} data | |
* @return {Object} | |
*/ | |
parseDomainInfo(data) { | |
const result = { | |
ID: data.Id || "", | |
Status: data.Status || "", | |
DomainName: data.DomainName || "", | |
AuthCode: data.Auth || "", | |
LockStatus: typeof data.LockStatus === "boolean" ? data.LockStatus.toString() : "", | |
PrivacyProtectionStatus: typeof data.PrivacyProtectionStatus === "boolean" ? data.PrivacyProtectionStatus.toString() : "", | |
IsChildNameServer: typeof data.IsChildNameServer === "boolean" ? data.IsChildNameServer.toString() : "", | |
Contacts: { | |
Administrative: { ID: data.AdministrativeContactId || "" }, | |
Billing: { ID: data.BillingContactId || "" }, | |
Technical: { ID: data.TechnicalContactId || "" }, | |
Registrant: { ID: data.RegistrantContactId || "" } | |
}, | |
Dates: { | |
Start: data.StartDate || "", | |
Expiration: data.ExpirationDate || "", | |
RemainingDays: data.RemainingDay || "" | |
}, | |
NameServers: data.NameServerList ? (Array.isArray(data.NameServerList) ? data.NameServerList : [data.NameServerList]) : [], | |
Additional: (data.AdditionalAttributes && data.AdditionalAttributes.KeyValueOfstringstring) ? | |
(Array.isArray(data.AdditionalAttributes.KeyValueOfstringstring) ? | |
data.AdditionalAttributes.KeyValueOfstringstring.reduce((acc, attr) => { | |
if (attr.Key && attr.Value) acc[attr.Key] = attr.Value; | |
return acc; | |
}, {}) : | |
{ [data.AdditionalAttributes.KeyValueOfstringstring.Key]: data.AdditionalAttributes.KeyValueOfstringstring.Value }) : {}, | |
ChildNameServers: data.ChildNameServerInfo ? | |
(Array.isArray(data.ChildNameServerInfo) ? | |
data.ChildNameServerInfo.map(server => ({ | |
ns: server.ChildNameServer || "", | |
ip: Array.isArray(server.IpAddress?.string) ? server.IpAddress.string : [server.IpAddress?.string || ""] | |
})) : | |
[{ | |
ns: data.ChildNameServerInfo.ChildNameServer || "", | |
ip: Array.isArray(data.ChildNameServerInfo.IpAddress?.string) ? data.ChildNameServerInfo.IpAddress.string : [data.ChildNameServerInfo.IpAddress?.string || ""] | |
}]) : [] | |
}; | |
return result; | |
} | |
/** | |
* Parse contact information | |
* @param {Object} data | |
* @return {Object} | |
*/ | |
parseContactInfo(data) { | |
return { | |
ID : data.Id || '', | |
Status : data.Status || '', | |
Address : { | |
Line1 : data.AddressLine1 || '', | |
Line2 : data.AddressLine2 || '', | |
Line3 : data.AddressLine3 || '', | |
State : data.State || '', | |
City : data.City || '', | |
Country: data.Country || '', | |
ZipCode: data.ZipCode || '', | |
}, | |
Phone : { | |
Number : data.Phone || '', | |
CountryCode: data.PhoneCountryCode || '', | |
}, | |
Fax : { | |
Number : data.Fax || '', | |
CountryCode: data.FaxCountryCode || '', | |
}, | |
AuthCode : data.Auth || '', | |
FirstName: data.FirstName || '', | |
LastName : data.LastName || '', | |
Company : data.Company || '', | |
EMail : data.EMail || '', | |
Type : data.Type || '', | |
}; | |
} | |
async callApiFunction(apiFunctionName, parameters) { | |
try { | |
const client = await this.soapClientPromise; | |
// Dinamik olarak fonksiyon çağırma | |
const result = await client[`${apiFunctionName}`](parameters); | |
// Derinlik ne olursa olsun ...Result anahtarını bulalım | |
const responseKey = `${apiFunctionName}Result`; | |
let data = result[responseKey] || null; // İlk seviyede arar | |
// Eğer ilk seviyede bulamazsak, ikinci seviyede ararız | |
if (!data) { | |
const firstKey = Object.keys(result)[0]; | |
if (result[firstKey] && result[firstKey][responseKey]) { | |
data = result[firstKey][responseKey]; | |
} | |
} | |
if (!data || typeof data !== 'object') { | |
return {result: false, level: 'fatal', message: 'No data returned', ErrorCode: 0}; | |
} | |
if (data.faultcode) { | |
return {result: false, level: 'fault', message: data.faultstring, ErrorCode: data.faultcode}; | |
} | |
data.result = data.OperationResult === 'SUCCESS'; | |
if (data.result === false) { | |
data.message = data.OperationMessage || 'Operation failed'; | |
data.level = 'error'; | |
// Make sure error code is passed through | |
if (typeof data === 'number') { | |
data = { | |
result: false, | |
level: 'error', | |
message: 'Operation failed', | |
ErrorCode: data | |
}; | |
} | |
} | |
return data; | |
} | |
catch (error) { | |
console.error('API Error:', error); | |
return {result: false, level: 'exception', message: error.message, ErrorCode: error.code || 0}; | |
} | |
} | |
} | |
module.exports = DomainNameAPI; | |