123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- const helper = {}
- const crypto = require('crypto');
- const dns = require('dns');
- helper.base64 = function(str){
- return Buffer.from(str).toString('base64')
- }
- // '&channel=rd'
- helper.checkChannel = function(url,key) {
- return url.includes(key);
- }
- helper.capitalize_string = function(K) {
- // 将字符串按 "-" 分割,对每个单词首字母大写,然后重新用 "-" 连接
- return K.split("-")
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
- .join("-");
- }
- helper.query_raw_text = function(K) {
- if (!K || typeof K !== 'object') {
- return "";
- }
- const result = [];
- const replace_dict = {
- "'": "%27",
- "/": "%2F",
- "+": "%2B",
- "=": "%3D",
- "&": "%26",
- "@": "%40",
- "#": "%23",
- ";": "%3B",
- "?": "%3F",
- "%5B": "[",
- "%5D": "]",
- "%20": "+"
- };
- // 自定义编码函数
- function customEncode(str) {
- let encoded = encodeURIComponent(str);
- for (const [char, encoding] of Object.entries(replace_dict)) {
- encoded = encoded.replace(new RegExp(escapeRegExp(char), 'g'), encoding);
- }
- return encoded;
- }
- // 转义正则表达式特殊字符
- function escapeRegExp(string) {
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- }
- for (const [et, value] of Object.entries(K)) {
- if (value === null || value === undefined) {
- continue;
- }
- if (Array.isArray(value)) {
- // 处理数组
- for (const nt of value) {
- result.push(`${et}[]=${customEncode(String(nt))}`);
- }
- } else if (typeof value === 'object') {
- // 处理对象
- let nt = `${et}=${customEncode(JSON.stringify(value))}`;
- nt = nt.replace(/%5B/g, "[").replace(/%5D/g, "]");
- result.push(nt);
- } else {
- // 处理普通值
- result.push(`${et}=${customEncode(String(value))}`);
- }
- }
- return result.join("&");
- }
- helper.get_signature = function(token,K, O = 'agentd3dGiJc651gSQ28w9', H = 'https://new-media-fx.qimao.com/api') {
- // 构建 Authorization 对象
- const et = {
- "Authorization": token
- };
- // 获取排序后的参数字符串
- const nt = helper.params_sort(et);
- const at = helper.params_sort(K.get('data'), false);
- const it = helper.query_raw_text(K.get('params'));
-
- // 确定连接符
- const ot = K['url'].includes('?') ? '&' : '?';
-
- // 构建URL
- let st = K.get('url') + (it ? ot + it : '');
- if (H && st.startsWith(H)) {
- st = st.substring(H.length);
- }
- // 构建最终签名字符串
- const ct = `${st}&${nt}&${at}&${O}`;
-
- // 调试输出
- /*
- console.log('nt:', nt);
- console.log('at:', at);
- console.log('it:', it);
- console.log('ot:', ot);
- console.log('st:', st);
- console.log('ct:', ct);
- */
-
- return helper.sha256_hash(ct);
- }
- helper.params_sort = function(K, O = true) {
- if (!K || typeof K !== 'object') {
- return "";
- }
- // 按照键的字母顺序排序
- const sorted_keys = Object.keys(K).sort();
- const result = [];
- for (const et of sorted_keys) {
- if (K[et] !== null && K[et] !== undefined) {
- // 根据 O 决定是否首字母大写
- const nt = O ? helper.capitalize_string(et) : et;
- // 使用 JSON.stringify 来转换为 JSON 格式的字符串
- result.push(`${nt}=${JSON.stringify(K[et])}`);
- }
- }
- // 拼接成查询字符串
- return result.join("&");
- }
- helper.sha256_hash = function(data) {
- const crypto = require('crypto');
-
- // 创建一个 sha256 哈希对象
- const hash = crypto.createHash('sha256');
-
- // 更新哈希对象,传入数据
- hash.update(data, 'utf-8');
-
- // 获取最终的哈希值,返回一个十六进制字符串
- return hash.digest('hex');
- }
- helper.resolveDomain = async function(domain) {
- // 创建新的DNS解析器实例
- const resolver = new dns.promises.Resolver();
-
- // 尝试不同的DNS服务器
- const dnsServers = [
- '8.8.8.8', // Google DNS
- '8.8.4.4', // Google DNS备用
- '1.1.1.1', // Cloudflare DNS
- '1.0.0.1', // Cloudflare DNS备用
- '223.5.5.5', // 阿里DNS
- '223.6.6.6', // 阿里DNS备用
- '119.29.29.29', // 腾讯DNS
- '114.114.114.114' // 114 DNS
- ];
- for (const dnsServer of dnsServers) {
- try {
- console.log(`\nTrying DNS server: ${dnsServer}`);
- resolver.setServers([dnsServer]);
-
- const addresses = await resolver.resolve4(domain);
- console.log(`Success with DNS server ${dnsServer}:`);
- console.log('IP Addresses:', addresses);
-
- // 如果成功找到IP,尝试ping或TCP连接测试
- for (const ip of addresses) {
- console.log(`Testing connectivity to IP: ${ip}`);
- // 这里可以添加连接测试代码
- }
-
- return addresses;
- } catch (error) {
- console.error(`Failed with DNS server ${dnsServer}:`, error.message);
- }
- }
-
- throw new Error('Failed to resolve domain with all DNS servers');
- }
- helper.md5 = function(text) {
- return crypto.createHash('md5').update(text).digest('hex');
- }
- helper.getSign = function(distributorId,secretKey) {
- const params = [distributorId, secretKey, helper.getCurrentUnixTimestamp()];
- // 将参数数组中的每个元素转换为字符串并连接成一个单一的字符串
- const paramStr = params.map(String).join('');
-
- // 使用 MD5 算法生成哈希值
- const hash = crypto.createHash('md5');
- hash.update(paramStr);
-
- // 返回哈希值的十六进制表示
- return hash.digest('hex');
- }
- helper.getCurrentUnixTimestamp = function() {
- return Math.floor(Date.now() / 1000)
- }
- helper.getFqRequestOpt = function(key,sid_tt='b0390e26648a71801795b3b13c9d7d20'){
- const options = {
- url: `https://api.whbfxb.cn/api/novelsale/reader/get/content/v1/?aid=40013183&device_brand=realme&device_platform=android&device_type=RMX2020&mp_sdk_version=3.21.0&novelsale_app_scene=023001&version_code=230&key=${key}&item_source=1&module_name=ad_link&click_id=__CLICKID__&clickid=__CLICKID__&creativetype=__CTYPE__&demand_id=0&item_id=&media_source=1&mid1=__MID1__&mid2=__MID2__&mid3=__MID3__&mid4=__MID4__&mid5=__MID5__&projectid=__PROJECT_ID__&promotionid=__PROMOTION_ID__&request_id=__REQUESTID__&book_id=&host_novelsale_app_id=40013183`,
- headers: {
- 'cookie': `sid_tt=${sid_tt}; ` +
- 'ssid_ucp_v1=1.0.0-KDU0Nzc2NjZmZjRhNTZkYWM5YTMwN2ZmNzAyODMwNjFjZmQyMzA4OTYKFQjkktCcvMz_ARDGw7W6Bhjv6CA4CBoCbHEiIDhjOTg2NjgwY2Q4NzE2YmEzMmJhMjBjM2MwMmEwOTJk; ' +
- 'is_staff_user=false; ' +
- 'sid_ucp_v1=1.0.0-KDU0Nzc2NjZmZjRhNTZkYWM5YTMwN2ZmNzAyODMwNjFjZmQyMzA4OTYKFQjkktCcvMz_ARDGw7W6Bhjv6CA4CBoCbHEiIDhjOTg2NjgwY2Q4NzE2YmEzMmJhMjBjM2MwMmEwOTJk; ' +
- `sessionid=${sid_tt}; ` +
- 'ttwid=1%7CdTM3VEQ9KwlMsV2FV6Gaxv5CBXmd5i44fjDoZV_a8g8%7C1733124580%7Cc0952b31723a2f5d5e4b9f84a1c29cb7cbde5592906de58798b92a695d3fb292; ' +
- `sessionid_ss=${sid_tt}; ` +
- `sid_guard=${sid_tt}%7C1733124550%7C5184000%7CFri%2C+31-Jan-2025+07%3A29%3A10+GMT; ` +
- 'uid_tt=3361cf574bbdd82820371b4667fc9b91; ' +
- 'passport_csrf_token=f7e1da8668d26b8509725bcf7fa95628; ' +
- 'uid_tt_ss=3361cf574bbdd82820371b4667fc9b91; ' +
- 'passport_csrf_token_default=f7e1da8668d26b8509725bcf7fa95628; ' +
- 'store-region=cn-gs; ' +
- 'store-region-src=uid; ' +
- 'n_mh=9-mIeuD4wZnlYrrOvfzG3MuT6aQmCUtmr8FxV8Kl8xY',
- 'user-agent': 'Mozilla/5.0 (Linux; Android 9; Mi Note 3 Build/PKQ1.181007.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.193 Mobile Safari/537.36 aweme/29.4.0 ToutiaoMicroApp/3.21.0 PluginVersion/29409006',
- 'content-type': 'application/json',
- 'referer': 'https://tmaservice.developer.toutiao.com/?appid=tt1b316d8c8401e42101&version=2.7.0'
- }
- };
- return options
- }
- helper.getHyCreateLinkOpt = function(token){
- const options = {
- url: `https://ms.zhangwenpindu.cn/manage/distribution/createLink`,
- headers: {
- 'Accept': 'application/json, text/plain, */*',
- 'Accept-Language': 'zh-CN,zh;q=0.9',
- 'Cache-Control': 'no-cache',
- 'Connection': 'keep-alive',
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'Origin': 'https://manage.zhangwenpindu.cn',
- 'Pragma': 'no-cache',
- 'Referer': 'https://manage.zhangwenpindu.cn/',
- 'Sec-Fetch-Dest': 'empty',
- 'Sec-Fetch-Mode': 'cors',
- 'Sec-Fetch-Site': 'same-site',
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
- 'sec-ch-ua': '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
- 'sec-ch-ua-mobile': '?0',
- 'sec-ch-ua-platform': '"Windows"'
- }
- };
- options.headers['Authorization'] = `Bearer ${token}`
- return options
- }
- helper.getTimeStampByHourMinute = function(timeStr,otherStr=null) {
- // 解析时间字符串
- const [hours, minutes] = timeStr.split(':').map(Number);
-
- let date;
- if (otherStr) {
- // 如果提供了日期字符串,解析完整的日期时间
- date = new Date(otherStr);
- // 设置时分秒
- date.setHours(hours, minutes, 0, 0);
- } else {
- // 如果没有提供日期,使用今天的日期
- date = new Date();
- date.setHours(hours, minutes, 0, 0);
- }
- return date;
- }
- helper.getLocalDate = function() {
- const d = new Date();
- const year = d.getFullYear();
- const month = String(d.getMonth() + 1).padStart(2, '0');
- const day = String(d.getDate()).padStart(2, '0');
- return `${year}-${month}-${day}`;
- }
- helper.getPaginationParams = function(total, pageSize = 500) {
- const pages = Math.ceil(total / pageSize);
- const result = [];
-
- for(let page = 0; page < pages; page++) {
- const offset = page * pageSize;
- const limit = Math.min(pageSize, total - offset);
- result.push({
- page,
- offset,
- limit
- });
- }
-
- return result;
- }
- module.exports = helper;
|