[add] initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
1035
Cargo.lock
generated
Normal file
1035
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "namesilo_cli"
|
||||
version = "0.1.0"
|
||||
authors = ["Pascal"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
reqwest = { version = "0.10", features = ["blocking", "json"] } # MIT/Apache-2.0
|
||||
url = { version = "2.1.1" } # MIT/Apache-2.0
|
||||
xml-rs = { version = "0.8" } # MIT/Apache-2.0
|
||||
80
src/api/constants.rs
Normal file
80
src/api/constants.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
// operation constants
|
||||
pub(crate) const REGISTERDOMAIN: &str = "registerDomain"; // Register a new domain name
|
||||
pub(crate) const REGISTERDOMAINDROP: &str = "registerDomainDrop"; // Register a new domain name using drop-catching
|
||||
pub(crate) const RENEWDOMAIN: &str = "renewDomain"; // Renew a domain name
|
||||
pub(crate) const TRANSFERDOMAIN: &str = "transferDomain"; // Transfer a domain name into your NameSilo account
|
||||
pub(crate) const CHECKTRANSFERSTATUS: &str = "checkTransferStatus"; // Check the status of a domain transfer
|
||||
pub(crate) const TRANSFERUPDATECHANGEEPPCODE: &str = "transferUpdateChangeEPPCode"; // Add/Change the EPP code for a domain transfer
|
||||
pub(crate) const TRANSFERUPDATERESENDADMINEMAIL: &str = "transferUpdateResendAdminEmail"; // Update a Transfer to Re-Send the Admin Verification Email
|
||||
pub(crate) const TRANSFERUPDATERESUBMITTOREGISTRY: &str = "transferUpdateResubmitToRegistry"; // Update a Transfer to Re-Submit the transfer to the registry
|
||||
pub(crate) const CHECKREGISTERAVAILABILITY: &str = "checkRegisterAvailability"; // Determine if up to 200 domains can be registered at this time
|
||||
pub(crate) const CHECKTRANSFERAVAILABILITY: &str = "checkTransferAvailability"; // Determine if up to 200 domains can be transferred into your account at this time
|
||||
pub(crate) const LISTDOMAINS: &str = "listDomains"; // A list of all active domains within your account
|
||||
pub(crate) const GETDOMAININFO: &str = "getDomainInfo"; // Get essential information on a domain within your account
|
||||
pub(crate) const CONTACTLIST: &str = "contactList"; // View all contact profiles in your account
|
||||
pub(crate) const CONTACTADD: &str = "contactAdd"; // Add a contact profile to your account
|
||||
pub(crate) const CONTACTUPDATE: &str = "contactUpdate"; // Update a contact profile in account
|
||||
pub(crate) const CONTACTDELETE: &str = "contactDelete"; // Delete a contact profile in account
|
||||
pub(crate) const CONTACTDOMAINASSOCIATE: &str = "contactDomainAssociate"; // Associate contact profiles with a domain
|
||||
pub(crate) const CHANGENAMESERVERS: &str = "changeNameServers"; // Change the NameServers for up to 200 domains
|
||||
pub(crate) const DNSLISTRECORDS: &str = "dnsListRecords"; // View all DNS records associated with your domain
|
||||
pub(crate) const DNSADDRECORD: &str = "dnsAddRecord"; // Add a new DNS resource record
|
||||
pub(crate) const DNSUPDATERECORD: &str = "dnsUpdateRecord"; // Update an existing DNS resource record
|
||||
pub(crate) const DNSDELETERECORD: &str = "dnsDeleteRecord"; // Delete an existing DNS resource record
|
||||
pub(crate) const DNSSECLISTRECORDS: &str = "dnsSecListRecords"; // View all DS (DNSSEC) records associated with your domain
|
||||
pub(crate) const DNSSECADDRECORD: &str = "dnsSecAddRecord"; // Add a DS record (DNSSEC) to your domain
|
||||
pub(crate) const DNSSECDELETERECORD: &str = "dnsSecDeleteRecord"; // Delete a DS record (DNSSEC) from your domain
|
||||
pub(crate) const PORTFOLIOLIST: &str = "portfolioList"; // List the active portfolios within your account
|
||||
pub(crate) const PORTFOLIOADD: &str = "portfolioAdd"; // Add a portfolio to your account
|
||||
pub(crate) const PORTFOLIODELETE: &str = "portfolioDelete"; // Delete a portfolio from your account
|
||||
pub(crate) const PORTFOLIODOMAINASSOCIATE: &str = "portfolioDomainAssociate"; // Add up to 200 domains to a portfolio
|
||||
pub(crate) const LISTREGISTEREDNAMESERVERS: &str = "listRegisteredNameServers"; // List the Registered NameServers associated with one of your domains
|
||||
pub(crate) const ADDREGISTEREDNAMESERVER: &str = "addRegisteredNameServer"; // Add a Registered NameServer for one of your domains
|
||||
pub(crate) const MODIFYREGISTEREDNAMESERVER: &str = "modifyRegisteredNameServer"; // Modify a Registered NameServer
|
||||
pub(crate) const DELETEREGISTEREDNAMESERVER: &str = "deleteRegisteredNameServer"; // Delete a Registered NameServer
|
||||
pub(crate) const ADDPRIVACY: &str = "addPrivacy"; // Add WHOIS Privacy to a domain
|
||||
pub(crate) const REMOVEPRIVACY: &str = "removePrivacy"; // Remove WHOIS Privacy from a domain
|
||||
pub(crate) const ADDAUTORENEWAL: &str = "addAutoRenewal"; // Set your domain to be auto-renewed
|
||||
pub(crate) const REMOVEAUTORENEWAL: &str = "removeAutoRenewal"; // Remove the auto-renewal setting from your domain
|
||||
pub(crate) const RETRIEVEAUTHCODE: &str = "retrieveAuthCode"; // Have the EPP authorization code for the domain emailed to the administrative contact
|
||||
pub(crate) const DOMAINFORWARD: &str = "domainForward"; // Forward your domain
|
||||
pub(crate) const DOMAINFORWARDSUBDOMAIN: &str = "domainForwardSubDomain"; // Forward a sub-domain
|
||||
pub(crate) const DOMAINFORWARDSUBDOMAINDELETE: &str = "domainForwardSubDomainDelete"; // Delete a sub-domain forward
|
||||
pub(crate) const DOMAINLOCK: &str = "domainLock"; // Lock your domain
|
||||
pub(crate) const DOMAINUNLOCK: &str = "domainUnlock"; // Unlock your domain
|
||||
pub(crate) const LISTEMAILFORWARDS: &str = "listEmailForwards"; // List all email forwards for your domain
|
||||
pub(crate) const CONFIGUREEMAILFORWARD: &str = "configureEmailForward"; // Add or modify an email forward for your domain
|
||||
pub(crate) const DELETEEMAILFORWARD: &str = "deleteEmailForward"; // Delete an email forward for your domain
|
||||
pub(crate) const REGISTRANTVERIFICATIONSTATUS: &str = "registrantVerificationStatus"; // See the verification status of any Registrant email addresses
|
||||
pub(crate) const EMAILVERIFICATION: &str = "emailVerification"; // Verify a Registrant email address
|
||||
pub(crate) const GETACCOUNTBALANCE: &str = "getAccountBalance"; // View your NameSilo account funds balance
|
||||
pub(crate) const ADDACCOUNTFUNDS: &str = "addAccountFunds"; // Increase your NameSilo account funds
|
||||
pub(crate) const MARKETPLACEACTIVESALESOVERVIEW: &str = "marketplaceActiveSalesOverview"; // Returns a list and specifics for all of your active Marketplace sales
|
||||
pub(crate) const MARKETPLACEADDORMODIFYSALE: &str = "marketplaceAddOrModifySale"; // Allows you to add a new Marketplace sale or modify and existing sale
|
||||
pub(crate) const MARKETPLACELANDINGPAGEUPDATE: &str = "marketplaceLandingPageUpdate"; // Allows you to update the appearance of your Marketplace Landing Page
|
||||
pub(crate) const GETPRICES: &str = "getPrices"; // Returns our price list customized optionally based upon your account's specific pricing
|
||||
pub(crate) const LISTORDERS: &str = "listOrders"; // Returns a list of all orders placed in your account
|
||||
pub(crate) const ORDERDETAILS: &str = "orderDetails"; // Provides details for the provided order number
|
||||
|
||||
// input constants
|
||||
pub(crate) const KEY_VALUE_SEP: &str = "=";
|
||||
|
||||
// url constants
|
||||
const BASE_URL: &'static str = "https://www.namesilo.com/api/";
|
||||
const API_VERSION: &'static str = "1";
|
||||
const API_TYPE: &'static str = "xml";
|
||||
pub(crate) fn api_url(operation: &str, api_key: &str, args: &HashMap<String, String>) -> String {
|
||||
let mut params = String::new();
|
||||
for (k, v) in args {
|
||||
params.push_str(&format!("&{}={}", k, v))
|
||||
}
|
||||
format!("{}{}?version={}&type={}&key={}{}", BASE_URL, operation, API_VERSION, API_TYPE, api_key, params )
|
||||
}
|
||||
|
||||
// filter constants
|
||||
pub(crate) type Range = (char, char);
|
||||
pub(crate) const FILTER_LETTER_NUMBER: &[Range; 2] = &[('a','z'), ('0','9')];
|
||||
pub(crate) const FILTER_LETTER: &[Range; 1] = &[('a','z')];
|
||||
pub(crate) const WHITELIST_SYMBOLS: &str = "._-";
|
||||
24
src/api/functions.rs
Normal file
24
src/api/functions.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::lib::nerror::NError;
|
||||
use crate::lib::utils::{parse_args, check_args, send_api_request, Response};
|
||||
use crate::api::constants::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub(crate) fn list_domains(api_key: &str, _: &str) -> Result<Response, NError> {
|
||||
|
||||
let result: String = send_api_request(LISTDOMAINS, api_key, &HashMap::new())?;
|
||||
|
||||
Ok(Response::with_string(result))
|
||||
}
|
||||
|
||||
pub(crate) fn get_domain_info(api_key: &str, args: &str) -> Result<Response, NError> {
|
||||
let args: HashMap<String, String> = parse_args(args,
|
||||
(FILTER_LETTER, ""),
|
||||
(FILTER_LETTER_NUMBER, WHITELIST_SYMBOLS));
|
||||
|
||||
// check args, return error otherwise
|
||||
check_args(&args, &["domain"], &[])?;
|
||||
|
||||
let result: String = send_api_request(GETDOMAININFO, api_key, &args)?;
|
||||
|
||||
Ok(Response::with_string(result))
|
||||
}
|
||||
3
src/api/mod.rs
Normal file
3
src/api/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod constants;
|
||||
pub mod functions;
|
||||
pub mod operations;
|
||||
75
src/api/operations.rs
Normal file
75
src/api/operations.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use crate::api::functions::*;
|
||||
use crate::api::constants::*;
|
||||
use std::collections::HashMap;
|
||||
use crate::lib::nerror::NError;
|
||||
use crate::lib::utils::Response;
|
||||
|
||||
pub(crate) type Operation = fn(&str, &str) -> Result<Response, NError>;
|
||||
|
||||
pub fn get_operation(op_name: &str) -> Result<Operation, NError> {
|
||||
let mut operation_mapping: HashMap<String, Result<Operation, NError>> = hashmap![type(String, Result<Operation, NError>)
|
||||
REGISTERDOMAIN.to_lowercase() => Err(NError::NyiOpError(REGISTERDOMAIN.to_string())),
|
||||
REGISTERDOMAINDROP.to_lowercase() => Err(NError::NyiOpError(REGISTERDOMAINDROP.to_string())),
|
||||
RENEWDOMAIN.to_lowercase() => Err(NError::NyiOpError(RENEWDOMAIN.to_string())),
|
||||
TRANSFERDOMAIN.to_lowercase() => Err(NError::NyiOpError(TRANSFERDOMAIN.to_string())),
|
||||
CHECKTRANSFERSTATUS.to_lowercase() => Err(NError::NyiOpError(CHECKTRANSFERSTATUS.to_string())),
|
||||
TRANSFERUPDATECHANGEEPPCODE.to_lowercase() => Err(NError::NyiOpError(TRANSFERUPDATECHANGEEPPCODE.to_string())),
|
||||
TRANSFERUPDATERESENDADMINEMAIL.to_lowercase() => Err(NError::NyiOpError(TRANSFERUPDATERESENDADMINEMAIL.to_string())),
|
||||
TRANSFERUPDATERESUBMITTOREGISTRY.to_lowercase() => Err(NError::NyiOpError(TRANSFERUPDATERESUBMITTOREGISTRY.to_string())),
|
||||
CHECKREGISTERAVAILABILITY.to_lowercase() => Err(NError::NyiOpError(CHECKREGISTERAVAILABILITY.to_string())),
|
||||
CHECKTRANSFERAVAILABILITY.to_lowercase() => Err(NError::NyiOpError(CHECKTRANSFERAVAILABILITY.to_string())),
|
||||
LISTDOMAINS.to_lowercase() => Ok(list_domains),
|
||||
GETDOMAININFO.to_lowercase() => Ok(get_domain_info),
|
||||
CONTACTLIST.to_lowercase() => Err(NError::NyiOpError(CONTACTLIST.to_string())),
|
||||
CONTACTADD.to_lowercase() => Err(NError::NyiOpError(CONTACTADD.to_string())),
|
||||
CONTACTUPDATE.to_lowercase() => Err(NError::NyiOpError(CONTACTUPDATE.to_string())),
|
||||
CONTACTDELETE.to_lowercase() => Err(NError::NyiOpError(CONTACTDELETE.to_string())),
|
||||
CONTACTDOMAINASSOCIATE.to_lowercase() => Err(NError::NyiOpError(CONTACTDOMAINASSOCIATE.to_string())),
|
||||
CHANGENAMESERVERS.to_lowercase() => Err(NError::NyiOpError(CHANGENAMESERVERS.to_string())),
|
||||
DNSLISTRECORDS.to_lowercase() => Err(NError::NyiOpError(DNSLISTRECORDS.to_string())),
|
||||
DNSADDRECORD.to_lowercase() => Err(NError::NyiOpError(DNSADDRECORD.to_string())),
|
||||
DNSUPDATERECORD.to_lowercase() => Err(NError::NyiOpError(DNSUPDATERECORD.to_string())),
|
||||
DNSDELETERECORD.to_lowercase() => Err(NError::NyiOpError(DNSDELETERECORD.to_string())),
|
||||
DNSSECLISTRECORDS.to_lowercase() => Err(NError::NyiOpError(DNSSECLISTRECORDS.to_string())),
|
||||
DNSSECADDRECORD.to_lowercase() => Err(NError::NyiOpError(DNSSECADDRECORD.to_string())),
|
||||
DNSSECDELETERECORD.to_lowercase() => Err(NError::NyiOpError(DNSSECDELETERECORD.to_string())),
|
||||
PORTFOLIOLIST.to_lowercase() => Err(NError::NyiOpError(PORTFOLIOLIST.to_string())),
|
||||
PORTFOLIOADD.to_lowercase() => Err(NError::NyiOpError(PORTFOLIOADD.to_string())),
|
||||
PORTFOLIODELETE.to_lowercase() => Err(NError::NyiOpError(PORTFOLIODELETE.to_string())),
|
||||
PORTFOLIODOMAINASSOCIATE.to_lowercase() => Err(NError::NyiOpError(PORTFOLIODOMAINASSOCIATE.to_string())),
|
||||
LISTREGISTEREDNAMESERVERS.to_lowercase() => Err(NError::NyiOpError(LISTREGISTEREDNAMESERVERS.to_string())),
|
||||
ADDREGISTEREDNAMESERVER.to_lowercase() => Err(NError::NyiOpError(ADDREGISTEREDNAMESERVER.to_string())),
|
||||
MODIFYREGISTEREDNAMESERVER.to_lowercase() => Err(NError::NyiOpError(MODIFYREGISTEREDNAMESERVER.to_string())),
|
||||
DELETEREGISTEREDNAMESERVER.to_lowercase() => Err(NError::NyiOpError(DELETEREGISTEREDNAMESERVER.to_string())),
|
||||
ADDPRIVACY.to_lowercase() => Err(NError::NyiOpError(ADDPRIVACY.to_string())),
|
||||
REMOVEPRIVACY.to_lowercase() => Err(NError::NyiOpError(REMOVEPRIVACY.to_string())),
|
||||
ADDAUTORENEWAL.to_lowercase() => Err(NError::NyiOpError(ADDAUTORENEWAL.to_string())),
|
||||
REMOVEAUTORENEWAL.to_lowercase() => Err(NError::NyiOpError(REMOVEAUTORENEWAL.to_string())),
|
||||
RETRIEVEAUTHCODE.to_lowercase() => Err(NError::NyiOpError(RETRIEVEAUTHCODE.to_string())),
|
||||
DOMAINFORWARD.to_lowercase() => Err(NError::NyiOpError(DOMAINFORWARD.to_string())),
|
||||
DOMAINFORWARDSUBDOMAIN.to_lowercase() => Err(NError::NyiOpError(DOMAINFORWARDSUBDOMAIN.to_string())),
|
||||
DOMAINFORWARDSUBDOMAINDELETE.to_lowercase() => Err(NError::NyiOpError(DOMAINFORWARDSUBDOMAINDELETE.to_string())),
|
||||
DOMAINLOCK.to_lowercase() => Err(NError::NyiOpError(DOMAINLOCK.to_string())),
|
||||
DOMAINUNLOCK.to_lowercase() => Err(NError::NyiOpError(DOMAINUNLOCK.to_string())),
|
||||
LISTEMAILFORWARDS.to_lowercase() => Err(NError::NyiOpError(LISTEMAILFORWARDS.to_string())),
|
||||
CONFIGUREEMAILFORWARD.to_lowercase() => Err(NError::NyiOpError(CONFIGUREEMAILFORWARD.to_string())),
|
||||
DELETEEMAILFORWARD.to_lowercase() => Err(NError::NyiOpError(DELETEEMAILFORWARD.to_string())),
|
||||
REGISTRANTVERIFICATIONSTATUS.to_lowercase() => Err(NError::NyiOpError(REGISTRANTVERIFICATIONSTATUS.to_string())),
|
||||
EMAILVERIFICATION.to_lowercase() => Err(NError::NyiOpError(EMAILVERIFICATION.to_string())),
|
||||
GETACCOUNTBALANCE.to_lowercase() => Err(NError::NyiOpError(GETACCOUNTBALANCE.to_string())),
|
||||
ADDACCOUNTFUNDS.to_lowercase() => Err(NError::NyiOpError(ADDACCOUNTFUNDS.to_string())),
|
||||
MARKETPLACEACTIVESALESOVERVIEW.to_lowercase() => Err(NError::NyiOpError(MARKETPLACEACTIVESALESOVERVIEW.to_string())),
|
||||
MARKETPLACEADDORMODIFYSALE.to_lowercase() => Err(NError::NyiOpError(MARKETPLACEADDORMODIFYSALE.to_string())),
|
||||
MARKETPLACELANDINGPAGEUPDATE.to_lowercase() => Err(NError::NyiOpError(MARKETPLACELANDINGPAGEUPDATE.to_string())),
|
||||
GETPRICES.to_lowercase() => Err(NError::NyiOpError(GETPRICES.to_string())),
|
||||
LISTORDERS.to_lowercase() => Err(NError::NyiOpError(LISTORDERS.to_string())),
|
||||
ORDERDETAILS.to_lowercase() => Err(NError::NyiOpError(ORDERDETAILS.to_string()))
|
||||
];
|
||||
|
||||
let op: Option<Result<Operation, NError>> = operation_mapping.remove(&op_name.to_lowercase());
|
||||
match op {
|
||||
Some(v) => v,
|
||||
None => Err(NError::InvalidOpError(op_name.to_string()))
|
||||
}
|
||||
|
||||
}
|
||||
13
src/lib/macros.rs
Normal file
13
src/lib/macros.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
#[macro_use]
|
||||
macro_rules! hashmap {
|
||||
($( $key: expr => $val: expr ),*) => {{
|
||||
let mut map = ::std::collections::HashMap::new();
|
||||
$( map.insert($key, $val); )*
|
||||
map
|
||||
}};
|
||||
( type($key_type: ty, $value_type: ty) $( $key: expr => $val: expr ),* ) => {{
|
||||
let mut map: HashMap<$key_type, $value_type> = ::std::collections::HashMap::new();
|
||||
$( map.insert($key, $val); )*
|
||||
map
|
||||
}}
|
||||
}
|
||||
4
src/lib/mod.rs
Normal file
4
src/lib/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod nerror;
|
||||
pub mod utils;
|
||||
54
src/lib/nerror.rs
Normal file
54
src/lib/nerror.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use std::fmt;
|
||||
use std::error::Error;
|
||||
|
||||
pub enum NError {
|
||||
ReqwestError(reqwest::Error),
|
||||
ParserError(url::ParseError),
|
||||
ResponseError(u16),
|
||||
InvalidArgError(String),
|
||||
MissArgError(String),
|
||||
InvalidOpError(String),
|
||||
NyiOpError(String)
|
||||
}
|
||||
|
||||
impl fmt::Display for NError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
NError::ReqwestError(e) => <dyn Error as fmt::Display>::fmt(e, f),
|
||||
NError::ParserError(e) => <dyn Error as fmt::Display>::fmt(e, f),
|
||||
NError::ResponseError(e) => write!(f, "Server replied with Status Code [{}]", e),
|
||||
NError::InvalidArgError(arg) => write!(f, "Wrong argument [{}]", arg),
|
||||
NError::MissArgError(arg) => write!(f, "Missing argument [{}]", arg),
|
||||
NError::InvalidOpError(op) => write!(f, "Operation [{}] does not exist", op),
|
||||
NError::NyiOpError(op) => write!(f, "Operation [{}] is not yet implemented", op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for NError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
NError::ReqwestError(e) => <dyn Error as fmt::Debug>::fmt(e, f),
|
||||
NError::ParserError(e) => <dyn Error as fmt::Debug>::fmt(e, f),
|
||||
NError::ResponseError(e) => write!(f, "Server replied with Status Code [{}]", e),
|
||||
NError::InvalidArgError(arg) => write!(f, "Wrong argument [{}]", arg),
|
||||
NError::MissArgError(arg) => write!(f, "Missing argument [{}]", arg),
|
||||
NError::InvalidOpError(op) => write!(f, "Operation [{}] does not exist", op),
|
||||
NError::NyiOpError(op) => write!(f, "Operation [{}] is not yet implemented", op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for NError {
|
||||
fn from(e: reqwest::Error) -> NError {
|
||||
NError::ReqwestError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::ParseError> for NError {
|
||||
fn from(e: url::ParseError) -> NError {
|
||||
NError::ParserError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for NError {}
|
||||
92
src/lib/utils.rs
Normal file
92
src/lib/utils.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::api::constants::*;
|
||||
use crate::lib::nerror::NError;
|
||||
use reqwest::Url;
|
||||
use reqwest::StatusCode;
|
||||
|
||||
pub(crate) fn parse_args(args: &str, key_filter: (&[Range], &str), value_filter: (&[Range], &str)) -> HashMap<String, String> {
|
||||
let args_vector: Vec<&str> = args.split_ascii_whitespace().collect();
|
||||
if args_vector.is_empty() { return HashMap::new() }
|
||||
let mut args_map: HashMap<String, String> = HashMap::new();
|
||||
for arg in args_vector {
|
||||
let kv: Vec<&str> = arg.split(KEY_VALUE_SEP).collect();
|
||||
if kv.len() < 2 { continue; }
|
||||
args_map.insert(sanitize_string(kv[0], &key_filter.0, &key_filter.1),
|
||||
sanitize_string(kv[1], &value_filter.0, &value_filter.1));
|
||||
}
|
||||
args_map
|
||||
}
|
||||
|
||||
pub(crate) fn sanitize_string(s: &str, ranges: &[Range], whitelist: &str) -> String {
|
||||
let s_lower: String = s.to_lowercase();
|
||||
let mut result: String = String::new();
|
||||
|
||||
// helper function to check if c is in any range
|
||||
let in_range = |c: char| {
|
||||
for range in ranges {
|
||||
if c >= range.0 && c <= range.1 { return true; }
|
||||
}
|
||||
false
|
||||
};
|
||||
|
||||
for c in s_lower.chars() {
|
||||
if whitelist.contains(c) || in_range(c) {
|
||||
result.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
|
||||
}
|
||||
|
||||
pub(crate) fn check_args(args: &HashMap<String, String>, required: &[&str], optional: &[&str]) -> Result<(), NError> {
|
||||
|
||||
// check if all required fields are present
|
||||
for required_param in required {
|
||||
if !args.contains_key(&required_param.to_string()) {
|
||||
return Err(NError::MissArgError(required_param.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
// check if all fields are valid
|
||||
for (k, _) in args {
|
||||
if !(required.contains(&k.as_str()) || optional.contains(&k.as_str())) {
|
||||
return Err(NError::InvalidArgError(k.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn send_request(url: Url) -> Result<String, NError> {
|
||||
let resp: reqwest::blocking::Response = reqwest::blocking::get(url)?;
|
||||
if resp.status() != StatusCode::OK {
|
||||
return Err(NError::ResponseError(resp.status().as_u16()));
|
||||
}
|
||||
let result: String = resp.text()?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub(crate) fn send_api_request(operation: &str, api_key: &str, args: &HashMap<String, String>) -> Result<String, NError> {
|
||||
let url: String = api_url(operation, api_key, &args);
|
||||
Ok(send_request(reqwest::Url::parse(url.as_str())?)?)
|
||||
}
|
||||
|
||||
pub struct Response {
|
||||
string: String
|
||||
}
|
||||
|
||||
impl Response {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new() -> Response {
|
||||
Response { string: String::new() }
|
||||
}
|
||||
pub(crate) fn with_string(string: String) -> Response {
|
||||
Response { string }
|
||||
}
|
||||
|
||||
pub fn get_string(&self) -> &String {
|
||||
&self.string
|
||||
}
|
||||
}
|
||||
22
src/main.rs
Normal file
22
src/main.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
#[macro_use]
|
||||
mod lib;
|
||||
mod api;
|
||||
|
||||
use crate::lib::nerror::NError;
|
||||
use crate::api::operations::get_operation;
|
||||
|
||||
fn main() -> Result<(), NError> {
|
||||
|
||||
let api_key = "";
|
||||
let domain = "";
|
||||
|
||||
let result = get_operation("listDomains")?(api_key, "")?;
|
||||
|
||||
println!("result: {}", result.get_string());
|
||||
|
||||
let result = get_operation("getDomainInfo")?(api_key, domain)?;
|
||||
|
||||
println!("result: {}", result.get_string());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user