@team-internet/apiconnector
Version:
Node.js SDK for the insanely fast CentralNic Reseller (fka RRPProxy) API
145 lines (144 loc) • 7.95 kB
JavaScript
import { ResponseTemplateManager as RTM } from "./responsetemplatemanager.js";
function preg_quote(str, delimiter = "") {
// MIT, from: https://locutus.io/php/preg_quote/
return (str + "").replace(new RegExp("[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\" + delimiter + "-]", "g"), "\\$&");
}
/**
* ResponseTranslator class
*/
export class ResponseTranslator {
/**
* Regular Expression Mapping for API DESCRIPTION Property translation
*/
static descriptionRegexMap = {
// HX
"Authorization failed; Operation forbidden by ACL": "Authorization failed; Used Command `{COMMAND}` not white-listed by your Access Control List",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY STATUS (clientTransferProhibited)/WRONG AUTH": "This Domain is locked and the given Authorization Code is wrong. Initiating a Transfer is therefore impossible.",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY STATUS (clientTransferProhibited)": "This Domain is locked. Initiating a Transfer is therefore impossible.",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY STATUS (requested)": "Registration of this Domain Name has not yet completed. Initiating a Transfer is therefore impossible.",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY STATUS (requestedcreate)": "Registration of this Domain Name has not yet completed. Initiating a Transfer is therefore impossible.",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY STATUS (requesteddelete)": "Deletion of this Domain Name has been requested. Initiating a Transfer is therefore impossible.",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY STATUS (pendingdelete)": "Deletion of this Domain Name is pending. Initiating a Transfer is therefore impossible.",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY WRONG AUTH": "The given Authorization Code is wrong. Initiating a Transfer is therefore impossible.",
"Request is not available; DOMAIN TRANSFER IS PROHIBITED BY AGE OF THE DOMAIN": "This Domain Name is within 60 days of initial registration. Initiating a Transfer is therefore impossible.",
"Attribute value is not unique; DOMAIN is already assigned to your account": "You cannot transfer a domain that is already on your account at the registrar's system.",
// CNR
"Missing required attribute; premium domain name. please provide required parameters": "Confirm the Premium pricing by providing the necessary premium domain price data.",
SkipPregQuote: {
// HX
"Invalid attribute value syntax; resource record [(.+)]": "Invalid Syntax for DNSZone Resource Record: $1",
"Missing required attribute; CLASS(?:=| [MUST BE )PREMIUM_([w+]+)[s]]": "Confirm the Premium pricing by providing the parameter CLASS with the value PREMIUM_$1.",
"Syntax error in Parameter DOMAIN ((.+))": "The Domain Name $1 is invalid.",
},
};
/**
* translate a raw api response
* @param raw API raw response
* @param cmd requested API command
* @param ph list of place holder vars
* @returns new translated raw response
*/
static translate(raw, cmd, ph = {}) {
let httperror = "";
let newraw = raw || "empty";
// Hint: Empty API Response (replace {CONNECTION_URL} later)
// curl error handling
const isHTTPError = newraw.substring(0, 10) === "httperror|";
if (isHTTPError) {
[newraw, httperror] = newraw.split("|");
}
// Explicit call for a static template
if (RTM.getInstance().hasTemplate(newraw)) {
// don't use getTemplate as it leads to endless loop as of again
// creating a response instance
newraw = RTM.getInstance().templates[newraw];
if (isHTTPError && httperror.length) {
newraw = newraw.replace(/\{HTTPERROR\}/, " (" + httperror + ")");
}
}
// Missing CODE or DESCRIPTION in API Response
if ((!/description[\s]*=/i.test(newraw) || // missing description
/description[\s]*=\r\n/i.test(newraw) || // empty description
!/code[\s]*=/i.test(newraw)) && // missing code
RTM.getInstance().hasTemplate("invalid")) {
newraw = RTM.getInstance().templates.invalid;
}
// Iterate through the description-to-regex mapping
// generic API response description rewrite
let data = "";
for (const [regex, val] of Object.entries(ResponseTranslator.descriptionRegexMap)) {
// Check if regex should be treated as multiple patterns
if (regex === "SkipPregQuote") {
// Iterate through each temporary pattern in val
for (const [tmpregex, tmpval] of Object.entries(val)) {
// Attempt to find a match using the temporary pattern
data = ResponseTranslator.findMatch(tmpregex, newraw, "" + tmpval, cmd, ph);
// If a match is found, exit the inner loop
if (data) {
newraw = data;
break;
}
}
}
else {
// Escape the pattern and attempt to find a match for it
const escapedregex = preg_quote(regex);
console.log(newraw);
data = ResponseTranslator.findMatch(escapedregex, newraw, val, cmd, ph);
console.log(newraw);
}
// If a match is found, exit the outer loop
if (data) {
newraw = data;
break;
}
}
const cregex = /\{.+\}/;
if (cregex.test(newraw)) {
newraw = newraw.replace(cregex, "");
}
return newraw;
}
/**
* Finds a match in the given text and performs replacements based on patterns and placeholders.
*
* This function searches for a specified regular expression pattern in the provided text and
* performs replacements based on the matched pattern, command data, and placeholder values.
*
* @param regex The regular expression pattern to search for.
* @param newraw The input text where the match will be searched for.
* @param val The value to be used in replacement if a match is found.
* @param cmd The command data containing replacements, if applicable.
* @param ph An array of placeholder values for further replacements.
*
* @return Returns non-empty string if replacements were performed, empty string otherwise.
*/
static findMatch(regex, newraw, val, cmd = {}, ph = {}) {
// match the response for given description
// NOTE: we match if the description starts with the given description
// it would also match if it is followed by additional text
const qregex = new RegExp("/descriptions*=s*" + regex + "([^\\r\\n]+)?/i");
let ret = "";
if (qregex.test(newraw)) {
// If "COMMAND" exists in cmd, replace "{COMMAND}" in val
if (Object.prototype.hasOwnProperty.call(cmd, "COMMAND")) {
val = val.replace("{COMMAND}", cmd.COMMAND);
}
// If $newraw matches $qregex, replace with "description=" . $val
let tmp = newraw.replace(qregex, "description=" + val);
if (newraw !== tmp) {
ret = tmp;
}
}
// Generic replacing of placeholder vars
const vregex = /\{[^}]+\}/;
if (vregex.test(newraw)) {
for (const [tkey, tval] of Object.entries(ph)) {
newraw = newraw.replace("{" + tkey + "}", "" + tval);
}
newraw = newraw.replace(vregex, "");
ret = newraw;
}
return ret;
}
}