import { createAxiosService, HttpClient, ILogger } from "@certd/basic";
import { PageRes, PageSearch } from "@certd/pipeline";
import { DomainRecord } from "@certd/plugin-lib";
import qs from "qs";
import { Dns51Access } from "./access.js";
export class Dns51Client {
logger: ILogger;
access: Dns51Access;
http: HttpClient;
cryptoJs: any;
isLogined = false;
_token = "";
_cookie = "";
constructor(options: {
logger: ILogger;
access: Dns51Access;
}) {
this.logger = options.logger;
this.access = options.access;
this.http = createAxiosService({
logger: this.logger
});
}
aes(val: string) {
if (!this.cryptoJs) {
throw new Error("crypto-js not init");
}
const CryptoJS = this.cryptoJs;
var k = CryptoJS.enc.Utf8.parse("1234567890abcDEF");
var iv = CryptoJS.enc.Utf8.parse("1234567890abcDEF");
return CryptoJS.AES.encrypt(val, k, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
}).toString();
}
async init() {
if (this.cryptoJs) {
return;
}
const CryptoJSModule = await import("crypto-js");
this.cryptoJs = CryptoJSModule.default;
}
async login() {
if (this.isLogined) {
return;
}
await this.init();
const res = await this.http.request({
url: "https://www.51dns.com/login.html",
method: "get",
withCredentials: true,
logRes: false,
returnOriginRes: true,
headers: {
// 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36',
'Origin': 'https://www.51dns.com',
'Referer': 'https://www.51dns.com',
},
});
let setCookie = res.headers['set-cookie']
let cookie = setCookie.map((item: any) => {
return item.split(';')[0]
}).join(';')
//提取 var csrfToken = "ieOfM21eDd9nWJv3OZtMJF6ogDsnPKQHJ17dlMck";
const _token = res.data.match(/var csrfToken = "(.*?)"/)[1];
this.logger.info("_token:", _token);
this._token = _token;
var obj = {
"email_or_phone": this.aes(this.access.username),
"password": this.aes(this.access.password),
"type": this.aes("account"),
"redirectTo": "https://www.51dns.com/domain",
"_token": _token
};
const res2 = await this.http.request({
url: "https://www.51dns.com/login",
method: "post",
data: {
...obj
},
withCredentials: true,
logRes: false,
returnOriginRes: true,
headers: {
'Origin': 'https://www.51dns.com',
'Referer': 'https://www.51dns.com',
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': cookie,
'X-Requested-With': 'XMLHttpRequest'
}
});
this.logger.info("return headers:", JSON.stringify(res2.headers))
if (res2.data.code == 0) {
setCookie = res2.headers['set-cookie']
this._cookie = setCookie.map((item: any) => {
return item.split(';')[0]
}).join(';')
this.logger.info("cookie:", this._cookie)
this.logger.info("登录成功")
} else {
throw new Error("登录失败:", res2.data)
}
const res3 = await this.http.request({
url: 'https://www.51dns.com/domain',
method: 'get',
withCredentials: true,
logRes: false,
returnOriginRes: true,
headers: {
// 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36',
'Origin': 'https://www.51dns.com',
'Referer': 'https://www.51dns.com/login.html',
'Cookie': this._cookie,
}
})
const success2 = res3.data.includes('DNS解析')
if (!success2) {
throw new Error("检查登录失败")
}
this.logger.info("检查登录成功")
this.isLogined = true;
}
async getDomainId(domain: string) {
await this.login();
const res = await this.http.request({
url: `https://www.51dns.com/domain?domain=${domain}&status=`,
method: "get",
withCredentials: true,
logRes: false,
returnOriginRes: true,
headers: this.getRequestHeaders()
});
// 提取 certd.top
const regExp = new RegExp(`]*>${domain}<\\/a>`, "i");
const matched = res.data.match(regExp);
if (!matched || matched.length < 1) {
throw new Error(`域名${domain}不存在`);
}
const domainId = matched[1];
this.logger.info(`域名${domain}的id为${domainId}`)
return parseInt(domainId);
}
private getRequestHeaders() {
return {
'Origin': 'https://www.51dns.com',
'Referer': 'https://www.51dns.com',
'Cookie': this._cookie
};
}
async createRecord(param: { domain: string, data: any; domainId: number; host: string; ttl: number; type: string }) {
const {domain, data, host, type} = param;
const domainId = await this.getDomainId(domain);
const url = "https://www.51dns.com/domain/storenNewRecord";
const req = {
_token: this._token,
domain_id: domainId,
record: host,
type: type,
value: data,
ttl: 300,
mx:"",
view_id: 0
};
this.logger.info("req:", JSON.stringify(req))
const res = await this.http.request({
url,
method: "post",
data: req,
withCredentials: true,
headers: {
...this.getRequestHeaders(),
'Content-Type': 'application/x-www-form-urlencoded'
}
});
if (res.status !== 200) {
throw new Error(`创建域名解析失败:${res.msg}`);
}
const id = res.data.id;
return {
id,
domainId
};
}
async deleteRecord(param: { domainId: number; id: number }) {
const url = "https://www.51dns.com/domain/operateRecord"
/*
type: delete
ids[0]: 601019779
domain_id: 193341603
_token: ieOfM21eDd9nWJv3OZtMJF6ogDsnPKQHJ17dlMck
*/
const body = {
type: "delete",
ids: [param.id],
domain_id: param.domainId,
_token: this._token
}
const res = await this.http.request({
url,
method: "post",
data: body,
withCredentials: true,
headers: {
...this.getRequestHeaders(),
'Content-Type': 'application/x-www-form-urlencoded'
}
});
if (res.status !== 200) {
throw new Error(`删除域名解析失败:${res.msg}`);
}
}
async getDomainListPage(req: PageSearch): Promise> {
if (req.pageNo >=2) { //不知道翻页查询的参数是什么
return {
total: 0,
list: []
}
}
await this.login();
const query = {
//domain=&id=&status=&perPage=500
perPage: 1000,
}
const res = await this.http.request({
url: 'https://www.51dns.com/domain?' + qs.stringify(query),
method: 'get',
withCredentials: true,
logRes: false,
returnOriginRes: true,
headers: this.getRequestHeaders()
});
//提取记录
const content = res.data || ""
const startIndex = content.indexOf(``)
if (startIndex < 0) {
throw new Error("解析域名列表失败,未找到域名列表")
}
const endIndex = content.indexOf(`
`, startIndex)
const tableContent = content.substring(startIndex, endIndex + 8)
//
// docmirror.cn
const list: DomainRecord[] = []
const trArr = tableContent.split(`
`)
for (const tr of trArr) {
const lines = tr.trim().split("\n")
const row:any = {}
for (const line of lines) {
if (line.includes(`(.*?)<\/a>/i)[1];
row.domain = domain;
}
}
if (row.domain) {
list.push(row)
}
}
return {
total: list.length,
list
}
}
}