const crypto = require('crypto'); const config = require('./etc/config.json'); const { default: axios } = require('axios'); const http = require('http'); const moment = require('moment'); const mysql = require('mysql2/promise'); const JSONbig = require('json-bigint') const { HttpsProxyAgent } = require('https-proxy-agent'); const helper = require('./src/helper'); class tools { constructor(redis_help){ this.redis_help = redis_help } init(){ } distributorId = 1814786227164169; secretKey = 'CN6KQ8Bauo8JXg5fFPk86EHdRFIUVnyV'; heiyan_config(){ return { //黑岩配置 chang_pian_user:{ userName:"康帅", password:"Ks25666" }, duan_pian_user:{ userName:"王海泉", password:"My20240088" }, default_user:{ userName:"zhuoyue003", password:"Xuan2026@123" }, } } unixTimestampToDate = function(timestamp) { const date = new Date(timestamp * 1000); // Unix时间戳是秒,JavaScript的Date对象需要毫秒 return date.getTime(); } dateToUnixTimestamp = function (date) { return Math.floor(date.getTime() / 1000); // 将毫秒转换为秒 } calculateTimestampDifference = function(timestamp1, timestamp2) { return Math.abs(timestamp1 - timestamp2); } formatUnixTimestamp = function(timestamp, format = 'YYYY-MM-DD HH:mm:ss') { const date = new Date(timestamp * 1000); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要+1 const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); const formattedDate = format .replace('YYYY', year) .replace('MM', month) .replace('DD', day) .replace('HH', hours) .replace('mm', minutes) .replace('ss', seconds); return formattedDate; } getCurrentUnixTimestamp = function() { return Math.floor(Date.now() / 1000) } getCurrentUnixTimestamp = function() { return Math.floor(Date.now() / 1000) } generateCryptoNumericUUID= function(length = 10) { return crypto.randomInt(Math.pow(10, length - 1), Math.pow(10, length)).toString(); } generateQMSignature = function(url, secretKey) { const urlObj = new URL(url); const params = Array.from(urlObj.searchParams.entries()) .sort(([keyA], [keyB]) => keyA.localeCompare(keyB)) .map(([key, value]) => `${key}=${value}`) .join('&'); // 拼接secret key const stringToSign = params + secretKey; console.log("stringToSign:",stringToSign) // 计算MD5 const md5Hash = crypto.createHash('md5') .update(stringToSign) .digest('hex'); return md5Hash; } getSign = function(distributorId,secretKey) { const params = [distributorId, secretKey, tools.getCurrentUnixTimestamp()]; // 将参数数组中的每个元素转换为字符串并连接成一个单一的字符串 const paramStr = params.map(String).join(''); // 使用 MD5 算法生成哈希值 const hash = crypto.createHash('md5'); hash.update(paramStr); // 返回哈希值的十六进制表示 return hash.digest('hex'); } setHyToken(token){ this.redis_help.setKeyValue("hei_yan_token",token) } async getHyToken (){ return await this.redis_help.getKeyValue("hei_yan_token") } async getQMToken (){ return await this.redis_help.getKeyValue("qi_mao_token") } async getQMMFToken (){ return await this.redis_help.getKeyValue("qi_mao_mf_token") } async tj_api (key){ let create_day = helper.getLocalDate() await this.redis_help.incr(`${create_day}_${key}`) } getSupdate(){ //插入素材域名 return config.isDebug?config.debug_supdate_config:config.release_supdate_config } getCheckDataBaseConfig(){ return config.isDebug?config.debug_check_mysql:config.release_chekc_mysql } getDataBaseConfig(){ return config.isDebug?config.debug_mysql:config.release_mysql } getTaskDataBaseConfig(){ return config.isDebug?config.debug_task_mysql:config.release_task_mysql } getRandomElement(array) { const randomIndex = Math.floor(Math.random() * array.length); return array[randomIndex]; } async getFqSidtt() { let sidtt = '01e060d0cc506bf1340dcb004aea1161' let list = await this.redis_help.getKeyValue("all_fq_key") if(list == null){ return sidtt } list = JSON.parse(list) if(list.length<=0){ return sidtt } let temp = [] for (let index = 0; index < list.length; index++) { const sidtt = list[index]; if(sidtt.canUse==1){ temp.push(sidtt.sid_tt) } } return this.getRandomElement(temp) } async getFqMfSidtt() { let sidtt = '01e060d0cc506bf1340dcb004aea1161' let list = await this.redis_help.getKeyValue("all_fq_mf_key") if(list == null){ return sidtt } list = JSON.parse(list) if(list.length<=0){ return sidtt } let temp = [] for (let index = 0; index < list.length; index++) { const sidtt = list[index]; if(sidtt.canUse==1){ temp.push(sidtt.sid_tt) } } return this.getRandomElement(temp) } async getYwOPENSESSID() { let open_sessid = '9077ffcc5ca974e2c0e78502a24c9053' let list = await this.redis_help.getKeyValue("all_yw_key") if(list == null){ return open_sessid } list = JSON.parse(list) if(list.length<=0){ return open_sessid } for (let index = 0; index < list.length; index++) { const yw_data = list[index]; const old_time = yw_data.create_time; const current_time = moment(); const past_time = moment(old_time); // 计算时间差(小时) const diff_hours = current_time.diff(past_time, 'hours'); // 判断是否小于7小时 const isLessThan7Hours = diff_hours < 7; if(isLessThan7Hours){ this.redis_help.setKeyValue("OPENSESSID",yw_data.open_sessid) }else{ this.redis_help.setKeyValue("OPENSESSID","") } return open_sessid } } getOneNewClinetBuffer(headers=null){ return axios.create({ timeout: 30000, headers:headers||{}, responseType:"arraybuffer", // 使用独立的 agent,不影响其他连接 httpAgent: new http.Agent({ keepAlive: true, maxSockets: 5, // 允许适度的并发 maxFreeSockets: 2, timeout: 30000 }), validateStatus: function (status) { return status >= 200 && status < 300; } }); } getOneProxyNewClinet(headers=null){ let proxyConfig = { host: 'd528.kdltps.com', port: '15818', username: 't13322192973984', password: '7ntreedr' }; let proxyAgent = new HttpsProxyAgent(`http://${proxyConfig.username}:${proxyConfig.password}@${proxyConfig.host}:${proxyConfig.port}`); return axios.create({ timeout: 30000, headers:headers||{}, // 使用独立的 agent,不影响其他连接 httpAgent: proxyAgent, validateStatus: function (status) { return status >= 200 && status < 300; }, transformResponse: [data => { try { // 将大数字存储为字符串 return JSONbig({ storeAsString: true }).parse(data); // 或者使用 BigInt 类型(需要环境支持) // return JSONbig({ useNativeBigInt: true }).parse(data); } catch (e) { console.error('JSON 解析错误:', e); return data; } }] }); } getOneNewClinet(headers=null){ return axios.create({ timeout: 30000, headers:headers||{}, // 使用独立的 agent,不影响其他连接 httpAgent: new http.Agent({ keepAlive: true, maxSockets: 5, // 允许适度的并发 maxFreeSockets: 2, timeout: 30000 }), validateStatus: function (status) { return status >= 200 && status < 300; }, transformResponse: [data => { try { // 将大数字存储为字符串 return JSONbig({ storeAsString: true }).parse(data); // 或者使用 BigInt 类型(需要环境支持) // return JSONbig({ useNativeBigInt: true }).parse(data); } catch (e) { console.error('JSON 解析错误:', e); return data; } }] }); } async getAppletProductDataByButlerId(butler_id,product_id,main_id){ const taskdbConfig = config.isDebug?config.debug_task_mysql:config.release_task_mysql let connection = null try{ connection = await mysql.createConnection({ ...taskdbConfig, multipleStatements: true }); const [rows] = await connection.execute( `SELECT * FROM video_applet_product_${butler_id} WHERE product_id = '${product_id}' AND main_id = ${main_id} LIMIT 1` ); if(rows.length<=0){ return null } return rows[0] }catch(e){ console.error(e) return null }finally{ if(connection!=null){ await connection.end(); } } } async setDzCookie(cookit){ return this.redis_help.setKeyValue("DZ_COOKIT",cookit) } async getDzCookit(){ return this.redis_help.getKeyValue("DZ_COOKIT") } zh_sign(body, app_secret) { // 1. 处理输入参数 let requestBody = body; if (typeof body === 'string') { try { requestBody = JSON.parse(body); } catch (e) { throw new Error('Invalid JSON string'); } } // 2. 获取所有参数名并排序 const keys = Object.keys(requestBody).sort(); // 3. 拼接键值对 let s1 = ''; keys.forEach(key => { // 处理值:如果是对象/数组则转为JSON字符串,否则直接使用 const value = typeof requestBody[key] === 'object' ? JSON.stringify(requestBody[key]) : String(requestBody[key]); s1 += key + value; }); // 4. 追加app_secret const x1 = s1 + app_secret; console.log('拼接后的字符串 x1:', x1); // 调试用 // 5. HmacSha256 签名 const hmac = crypto.createHmac('sha256', app_secret); hmac.update(x1); const b1 = hmac.digest(); // 6. Base64 编码 const s2 = b1.toString('base64'); // 7. 转为大写 const signature = s2.toUpperCase(); return signature; } isObject(value) { return typeof value === 'object' && value !== null; } getOriginVideoId(url){ const match = url.match(/\/video\/(\d+)/); // 2. 提取结果 const videoId = match ? match[1] : null; return videoId } getPreviousDay(dateString) { // 将传入的字符串转换为 Date 对象 const date = new Date(dateString); // 获取前一天的日期 const previousDay = new Date(date); previousDay.setDate(date.getDate() - 1); // 格式化为 YYYY-MM-DD 字符串 const year = previousDay.getFullYear(); const month = String(previousDay.getMonth() + 1).padStart(2, '0'); const day = String(previousDay.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } } module.exports = new tools(require('./src/use_redis'));