tools.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. const crypto = require('crypto');
  2. const config = require('./etc/config.json');
  3. const { default: axios } = require('axios');
  4. const http = require('http');
  5. const moment = require('moment');
  6. const mysql = require('mysql2/promise');
  7. const JSONbig = require('json-bigint')
  8. const { HttpsProxyAgent } = require('https-proxy-agent');
  9. class tools {
  10. constructor(redis_help){
  11. this.redis_help = redis_help
  12. }
  13. init(){
  14. }
  15. distributorId = 1814786227164169;
  16. secretKey = 'CN6KQ8Bauo8JXg5fFPk86EHdRFIUVnyV';
  17. heiyan_config(){
  18. return { //黑岩配置
  19. chang_pian_user:{
  20. userName:"康帅",
  21. password:"Ks25666"
  22. },
  23. duan_pian_user:{
  24. userName:"王海泉",
  25. password:"My20240088"
  26. },
  27. default_user:{
  28. userName:"zhuoyue003",
  29. password:"Xuan2026@123"
  30. },
  31. }
  32. }
  33. unixTimestampToDate = function(timestamp) {
  34. const date = new Date(timestamp * 1000); // Unix时间戳是秒,JavaScript的Date对象需要毫秒
  35. return date.getTime();
  36. }
  37. dateToUnixTimestamp = function (date) {
  38. return Math.floor(date.getTime() / 1000); // 将毫秒转换为秒
  39. }
  40. calculateTimestampDifference = function(timestamp1, timestamp2) {
  41. return Math.abs(timestamp1 - timestamp2);
  42. }
  43. formatUnixTimestamp = function(timestamp, format = 'YYYY-MM-DD HH:mm:ss') {
  44. const date = new Date(timestamp * 1000);
  45. const year = date.getFullYear();
  46. const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要+1
  47. const day = String(date.getDate()).padStart(2, '0');
  48. const hours = String(date.getHours()).padStart(2, '0');
  49. const minutes = String(date.getMinutes()).padStart(2, '0');
  50. const seconds = String(date.getSeconds()).padStart(2, '0');
  51. const formattedDate = format
  52. .replace('YYYY', year)
  53. .replace('MM', month)
  54. .replace('DD', day)
  55. .replace('HH', hours)
  56. .replace('mm', minutes)
  57. .replace('ss', seconds);
  58. return formattedDate;
  59. }
  60. getCurrentUnixTimestamp = function() {
  61. return Math.floor(Date.now() / 1000)
  62. }
  63. getCurrentUnixTimestamp = function() {
  64. return Math.floor(Date.now() / 1000)
  65. }
  66. generateCryptoNumericUUID= function(length = 10) {
  67. return crypto.randomInt(Math.pow(10, length - 1), Math.pow(10, length)).toString();
  68. }
  69. generateQMSignature = function(url, secretKey) {
  70. const urlObj = new URL(url);
  71. const params = Array.from(urlObj.searchParams.entries())
  72. .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
  73. .map(([key, value]) => `${key}=${value}`)
  74. .join('&');
  75. // 拼接secret key
  76. const stringToSign = params + secretKey;
  77. console.log("stringToSign:",stringToSign)
  78. // 计算MD5
  79. const md5Hash = crypto.createHash('md5')
  80. .update(stringToSign)
  81. .digest('hex');
  82. return md5Hash;
  83. }
  84. getSign = function(distributorId,secretKey) {
  85. const params = [distributorId, secretKey, tools.getCurrentUnixTimestamp()];
  86. // 将参数数组中的每个元素转换为字符串并连接成一个单一的字符串
  87. const paramStr = params.map(String).join('');
  88. // 使用 MD5 算法生成哈希值
  89. const hash = crypto.createHash('md5');
  90. hash.update(paramStr);
  91. // 返回哈希值的十六进制表示
  92. return hash.digest('hex');
  93. }
  94. setHyToken(token){
  95. this.redis_help.setKeyValue("hei_yan_token",token)
  96. }
  97. async getHyToken (){
  98. return await this.redis_help.getKeyValue("hei_yan_token")
  99. }
  100. async getQMToken (){
  101. return await this.redis_help.getKeyValue("qi_mao_token")
  102. }
  103. async getQMMFToken (){
  104. return await this.redis_help.getKeyValue("qi_mao_mf_token")
  105. }
  106. async tj_qm (){
  107. let num = await this.redis_help.getKeyValue("qi_mao_iap_find_iaa",0)
  108. await this.redis_help.setKeyValue("qi_mao_iap_find_iaa",num+1)
  109. }
  110. getSupdate(){ //插入素材域名
  111. return config.isDebug?config.debug_supdate_config:config.release_supdate_config
  112. }
  113. getCheckDataBaseConfig(){
  114. return config.isDebug?config.debug_check_mysql:config.release_chekc_mysql
  115. }
  116. getDataBaseConfig(){
  117. return config.isDebug?config.debug_mysql:config.release_mysql
  118. }
  119. getTaskDataBaseConfig(){
  120. return config.isDebug?config.debug_task_mysql:config.release_task_mysql
  121. }
  122. getRandomElement(array) {
  123. const randomIndex = Math.floor(Math.random() * array.length);
  124. return array[randomIndex];
  125. }
  126. async getFqSidtt() {
  127. let sidtt = '01e060d0cc506bf1340dcb004aea1161'
  128. let list = await this.redis_help.getKeyValue("all_fq_key")
  129. if(list == null){
  130. return sidtt
  131. }
  132. list = JSON.parse(list)
  133. if(list.length<=0){
  134. return sidtt
  135. }
  136. let temp = []
  137. for (let index = 0; index < list.length; index++) {
  138. const sidtt = list[index];
  139. if(sidtt.canUse==1){
  140. temp.push(sidtt.sid_tt)
  141. }
  142. }
  143. return this.getRandomElement(temp)
  144. }
  145. async getFqMfSidtt() {
  146. let sidtt = '01e060d0cc506bf1340dcb004aea1161'
  147. let list = await this.redis_help.getKeyValue("all_fq_mf_key")
  148. if(list == null){
  149. return sidtt
  150. }
  151. list = JSON.parse(list)
  152. if(list.length<=0){
  153. return sidtt
  154. }
  155. let temp = []
  156. for (let index = 0; index < list.length; index++) {
  157. const sidtt = list[index];
  158. if(sidtt.canUse==1){
  159. temp.push(sidtt.sid_tt)
  160. }
  161. }
  162. return this.getRandomElement(temp)
  163. }
  164. async getYwOPENSESSID() {
  165. let open_sessid = '9077ffcc5ca974e2c0e78502a24c9053'
  166. let list = await this.redis_help.getKeyValue("all_yw_key")
  167. if(list == null){
  168. return open_sessid
  169. }
  170. list = JSON.parse(list)
  171. if(list.length<=0){
  172. return open_sessid
  173. }
  174. for (let index = 0; index < list.length; index++) {
  175. const yw_data = list[index];
  176. const old_time = yw_data.create_time;
  177. const current_time = moment();
  178. const past_time = moment(old_time);
  179. // 计算时间差(小时)
  180. const diff_hours = current_time.diff(past_time, 'hours');
  181. // 判断是否小于7小时
  182. const isLessThan7Hours = diff_hours < 7;
  183. if(isLessThan7Hours){
  184. this.redis_help.setKeyValue("OPENSESSID",yw_data.open_sessid)
  185. }else{
  186. this.redis_help.setKeyValue("OPENSESSID","")
  187. }
  188. return open_sessid
  189. }
  190. }
  191. getOneNewClinetBuffer(headers=null){
  192. return axios.create({
  193. timeout: 30000,
  194. headers:headers||{},
  195. responseType:"arraybuffer",
  196. // 使用独立的 agent,不影响其他连接
  197. httpAgent: new http.Agent({
  198. keepAlive: true,
  199. maxSockets: 5, // 允许适度的并发
  200. maxFreeSockets: 2,
  201. timeout: 30000
  202. }),
  203. validateStatus: function (status) {
  204. return status >= 200 && status < 300;
  205. }
  206. });
  207. }
  208. getOneProxyNewClinet(headers=null){
  209. let proxyConfig = {
  210. host: 'd528.kdltps.com',
  211. port: '15818',
  212. username: 't13322192973984',
  213. password: '7ntreedr'
  214. };
  215. let proxyAgent = new HttpsProxyAgent(`http://${proxyConfig.username}:${proxyConfig.password}@${proxyConfig.host}:${proxyConfig.port}`);
  216. return axios.create({
  217. timeout: 30000,
  218. headers:headers||{},
  219. // 使用独立的 agent,不影响其他连接
  220. httpAgent: proxyAgent,
  221. validateStatus: function (status) {
  222. return status >= 200 && status < 300;
  223. },
  224. transformResponse: [data => {
  225. try {
  226. // 将大数字存储为字符串
  227. return JSONbig({ storeAsString: true }).parse(data);
  228. // 或者使用 BigInt 类型(需要环境支持)
  229. // return JSONbig({ useNativeBigInt: true }).parse(data);
  230. } catch (e) {
  231. console.error('JSON 解析错误:', e);
  232. return data;
  233. }
  234. }]
  235. });
  236. }
  237. getOneNewClinet(headers=null){
  238. return axios.create({
  239. timeout: 30000,
  240. headers:headers||{},
  241. // 使用独立的 agent,不影响其他连接
  242. httpAgent: new http.Agent({
  243. keepAlive: true,
  244. maxSockets: 5, // 允许适度的并发
  245. maxFreeSockets: 2,
  246. timeout: 30000
  247. }),
  248. validateStatus: function (status) {
  249. return status >= 200 && status < 300;
  250. },
  251. transformResponse: [data => {
  252. try {
  253. // 将大数字存储为字符串
  254. return JSONbig({ storeAsString: true }).parse(data);
  255. // 或者使用 BigInt 类型(需要环境支持)
  256. // return JSONbig({ useNativeBigInt: true }).parse(data);
  257. } catch (e) {
  258. console.error('JSON 解析错误:', e);
  259. return data;
  260. }
  261. }]
  262. });
  263. }
  264. async getAppletProductDataByButlerId(butler_id,product_id,main_id){
  265. const taskdbConfig = config.isDebug?config.debug_task_mysql:config.release_task_mysql
  266. let connection = null
  267. try{
  268. connection = await mysql.createConnection({
  269. ...taskdbConfig,
  270. multipleStatements: true
  271. });
  272. const [rows] = await connection.execute(
  273. `SELECT * FROM video_applet_product_${butler_id} WHERE product_id = '${product_id}' AND main_id = ${main_id} LIMIT 1`
  274. );
  275. if(rows.length<=0){
  276. return null
  277. }
  278. return rows[0]
  279. }catch(e){
  280. console.error(e)
  281. return null
  282. }finally{
  283. if(connection!=null){
  284. await connection.end();
  285. }
  286. }
  287. }
  288. async setDzCookie(cookit){
  289. return this.redis_help.setKeyValue("DZ_COOKIT",cookit)
  290. }
  291. async getDzCookit(){
  292. return this.redis_help.getKeyValue("DZ_COOKIT")
  293. }
  294. zh_sign(body, app_secret) {
  295. // 1. 处理输入参数
  296. let requestBody = body;
  297. if (typeof body === 'string') {
  298. try {
  299. requestBody = JSON.parse(body);
  300. } catch (e) {
  301. throw new Error('Invalid JSON string');
  302. }
  303. }
  304. // 2. 获取所有参数名并排序
  305. const keys = Object.keys(requestBody).sort();
  306. // 3. 拼接键值对
  307. let s1 = '';
  308. keys.forEach(key => {
  309. // 处理值:如果是对象/数组则转为JSON字符串,否则直接使用
  310. const value = typeof requestBody[key] === 'object'
  311. ? JSON.stringify(requestBody[key])
  312. : String(requestBody[key]);
  313. s1 += key + value;
  314. });
  315. // 4. 追加app_secret
  316. const x1 = s1 + app_secret;
  317. console.log('拼接后的字符串 x1:', x1); // 调试用
  318. // 5. HmacSha256 签名
  319. const hmac = crypto.createHmac('sha256', app_secret);
  320. hmac.update(x1);
  321. const b1 = hmac.digest();
  322. // 6. Base64 编码
  323. const s2 = b1.toString('base64');
  324. // 7. 转为大写
  325. const signature = s2.toUpperCase();
  326. return signature;
  327. }
  328. isObject(value) {
  329. return typeof value === 'object' && value !== null;
  330. }
  331. getOriginVideoId(url){
  332. const match = url.match(/\/video\/(\d+)/);
  333. // 2. 提取结果
  334. const videoId = match ? match[1] : null;
  335. return videoId
  336. }
  337. getPreviousDay(dateString) {
  338. // 将传入的字符串转换为 Date 对象
  339. const date = new Date(dateString);
  340. // 获取前一天的日期
  341. const previousDay = new Date(date);
  342. previousDay.setDate(date.getDate() - 1);
  343. // 格式化为 YYYY-MM-DD 字符串
  344. const year = previousDay.getFullYear();
  345. const month = String(previousDay.getMonth() + 1).padStart(2, '0');
  346. const day = String(previousDay.getDate()).padStart(2, '0');
  347. return `${year}-${month}-${day}`;
  348. }
  349. }
  350. module.exports = new tools(require('./src/use_redis'));