wgt-node-utils 1.2.45 → 1.2.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wgt-node-utils",
3
- "version": "1.2.45",
3
+ "version": "1.2.47",
4
4
  "description": "WGT工具类包",
5
5
  "main": "dist/bundle.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -17,8 +17,8 @@ class wgtNodeUtils {
17
17
  this.sendFeiShuMessageMap = {};
18
18
  // 是否發送错误信息开关
19
19
  this.filesErrorSendStatus = false;
20
- // 初始化Lark客户端
21
- if (appId && appSecret) {
20
+ // 初始化Lark客户端
21
+ if (appId && appSecret) {
22
22
  this.initClient(appId, appSecret);
23
23
  } else {
24
24
  console.error('Lark客户端初始化失败:未提供appId或appSecret');
@@ -57,7 +57,7 @@ class wgtNodeUtils {
57
57
  const cfAndroid = headers['cloudfront-is-android-viewer'];
58
58
  const cfTablet = headers['cloudfront-is-tablet-viewer'];
59
59
  const cfMobile = headers['cloudfront-is-mobile-viewer'];
60
-
60
+
61
61
  let device = '';
62
62
  if (cfDesktop && cfDesktop === 'true') {
63
63
  device = 'PC';
@@ -71,12 +71,12 @@ class wgtNodeUtils {
71
71
  if (cfTablet && cfTablet === 'true') {
72
72
  device = 'Pad';
73
73
  }
74
-
74
+
75
75
  // 部分手机获取不到是Android还是IOS,统一使用Android
76
76
  if (!device && cfMobile && cfMobile === 'true') {
77
77
  device = 'Android';
78
78
  }
79
-
79
+
80
80
  if (!device) {
81
81
  const system = this.getSystem(headers['user-agent']);
82
82
  if (system.isPC) {
@@ -101,7 +101,7 @@ class wgtNodeUtils {
101
101
  isPhone: device === 'IOS',
102
102
  isTablet: device === 'Pad'
103
103
  };
104
-
104
+
105
105
  // 其它设备均为空的情况下,默认当前设置为pc
106
106
  if (!system.isAndroid && !system.isPhone && !system.isTablet) {
107
107
  system.isPC = true;
@@ -116,24 +116,24 @@ class wgtNodeUtils {
116
116
  */
117
117
  addCommonHeadersInfo = (res) => {
118
118
  // 增加头信息Content-Type, 在开启gzip时会用到
119
- res.setHeader('Content-Type','text/html; charset=utf-8');
119
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
120
120
 
121
121
  // 指定被允许iframe的域名
122
- res.setHeader('Content-Security-Policy','frame-ancestors https://*.enjoy4fun.com https://*.beesads.com');
122
+ res.setHeader('Content-Security-Policy', 'frame-ancestors https://*.enjoy4fun.com https://*.beesads.com');
123
123
 
124
124
  // 通知浏览器应该只通过 HTTPS 访问该站点,并且以后使用 HTTP 访问该站点的所有尝试都应自动重定向到 HTTPS
125
- res.setHeader('Strict-Transport-Security','max-age=63072000; includeSubDomains; preload');
125
+ res.setHeader('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');
126
126
 
127
127
  // 指定客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定
128
- res.setHeader('X-Content-Type-Options','nosniff');
128
+ res.setHeader('X-Content-Type-Options', 'nosniff');
129
129
 
130
130
  // 针对版本 8 及以上的 Internet Explorer,指示浏览器不要直接在浏览器中打开下载
131
- res.setHeader('X-Download-Options','noopen');
131
+ res.setHeader('X-Download-Options', 'noopen');
132
132
 
133
133
  // 当前页的主题标记为观察对象
134
134
  // Topics API 的目的是为调用者(包括运行脚本的页面上的第三方广告技术或广告提供商)提供页面访问者当前可能感兴趣的粗粒度广告主题。
135
135
  // 这些主题将补充上下文来自当前页面的信号可以组合起来以帮助为访问者找到合适的广告。
136
- res.setHeader('Observe-Browsing-Topics','?1');
136
+ res.setHeader('Observe-Browsing-Topics', '?1');
137
137
  }
138
138
  /***
139
139
  * 获取siteId 通过hostname
@@ -148,7 +148,7 @@ class wgtNodeUtils {
148
148
  if (siteId) {
149
149
  return resolve(siteId);
150
150
  }
151
-
151
+
152
152
  axios.get(url, { params: { domain: hostname } }).then((res) => {
153
153
  let siteData = res.data.data;
154
154
  // 如果未获取到数据,使用enjoy4fun.com做为默认数据
@@ -164,6 +164,87 @@ class wgtNodeUtils {
164
164
  });
165
165
  });
166
166
  }
167
+ /***
168
+ * 获取 site相关配置
169
+ * @isMobile 是否为移动端
170
+ * @url 请求后端接口
171
+ * @hostname 网站 hostname
172
+ * @imgDomain 图片地址
173
+ * @creativeId widget creative Id
174
+ * @mobileZoneKeyList 手机端使用zoneKeyList
175
+ * @pcZoneKeyList PC端使用zoneKEyList
176
+ */
177
+ // TODO 还未开发完成
178
+ async getSiteConfigByHostname(isMobile, url, hostname, imgDomain, creativeId, buildName, mobileZoneKeyList = [], pcZoneKeyList = []) {
179
+ const params = {
180
+ domain: hostname,
181
+ creative_id: creativeId
182
+ }
183
+ return new Promise((resolve) => {
184
+ axios.get(url, { params }).then(res => {
185
+ let siteData = res.data.data;
186
+ // 如果未获取到数据,使用做为默认数据
187
+ if (!siteData) {
188
+ siteData = {
189
+ siteId: "site_12",
190
+ zoneMap: {
191
+ 'pad_bottom_300_250': "45330",
192
+ 'pad_bottom_336_280': "45326",
193
+ 'pc_bottom_728_90': "45320",
194
+ 'pc_right_300_250': "45321",
195
+ 'pc_right_300_600': "45322",
196
+ 'pc_right_300_250_2': "45324",
197
+ 'pc_left_160_600': "45323",
198
+ 'mobile_300_250_top': "45327",
199
+ 'mobile_300_250_mid': "45328",
200
+ 'mobile_300_600_bottom': "45329",
201
+ 'interstitial_pc': "45334",
202
+ 'interstitial_mobile': "45335",
203
+ 'pc_bottom_160_90': "45325",
204
+ 'pc_pad_walkthrough_336_280': "45319",
205
+ 'mobile_game': "45331",
206
+ 'pc_game': "45333",
207
+ 'pad_game': "45332",
208
+ 'sidewall': "47185"
209
+ },
210
+ theme: {
211
+ icon: '',
212
+ logo: '',
213
+ title: '',
214
+ bgLeftImg: '',
215
+ bgRightImg: '',
216
+ bgBottomImg: '',
217
+ }
218
+ }
219
+ }
220
+
221
+ // 通过设备清洗zoneKeyMap
222
+ const zoneKeyList = isMobile ? mobileZoneKeyList : pcZoneKeyList;
223
+ let zoneMapForDevice = {};
224
+ const zoneMap = siteData.zoneMap || {};
225
+ zoneKeyList.forEach(zoneKey => {
226
+ if (zoneMap[zoneKey]) {
227
+ zoneMapForDevice[zoneKey] = zoneMap[zoneKey];
228
+ }
229
+ });
230
+ siteData.zoneMap = zoneMapForDevice;
231
+
232
+ // 处理皮肤字段
233
+ const { icon, logo, title, bgLeftImg, bgRightImg, bgBottomImg, ...otherTheme } = siteData.theme || {};
234
+ siteData.theme = {
235
+ icon: icon ? `${imgDomain}/site_icon/${icon}` : `/${buildName}/favicon.ico`,
236
+ logo: logo ? `${imgDomain}/site_logo/${logo}` : `/${buildName}/assets/logo-small.svg`,
237
+ title: title || 'Enjoy4fun',
238
+ bgLeftImg: bgLeftImg ? `${imgDomain}/theme/${bgLeftImg}` : '/gamebridge-web/assets/bg-left-winter.png',
239
+ bgRightImg: bgRightImg ? `${imgDomain}/theme/${bgRightImg}` : '/gamebridge-web/assets/bg-right-winter.png',
240
+ bgBottomImg: bgBottomImg ? `${imgDomain}/theme/${bgBottomImg}` : '/gamebridge-web/assets/bg-bottom-winter.png',
241
+ ...otherTheme
242
+ }
243
+ resolve(siteData);
244
+ });
245
+ });
246
+ }
247
+
167
248
  /***
168
249
  * node启动时将静态资源读取到内存中
169
250
  * @buildName 打包名称
@@ -193,9 +274,9 @@ class wgtNodeUtils {
193
274
  });
194
275
 
195
276
  // 增加preact依赖
196
- this.fileContents['preact.min.js'] = fs.readFileSync(path.join(dirname, `../${buildName}/dist/preact.min.js`),'utf8');
277
+ this.fileContents['preact.min.js'] = fs.readFileSync(path.join(dirname, `../${buildName}/dist/preact.min.js`), 'utf8');
197
278
 
198
- console.log('静态资源列表:');
279
+ console.log('静态资源列表:');
199
280
 
200
281
  const f2eFileLoadStatus = Object.keys(this.fileContents).every((item) => {
201
282
  const file = this.fileContents[item];
@@ -214,12 +295,12 @@ class wgtNodeUtils {
214
295
  console.log('静态资源:读取结束');
215
296
  });
216
297
  };
217
- /***
218
- * node启动时将静态资源读取到内存中
219
- * @appId 打包名称
220
- * @appSecret 打包版本号
221
- *
222
- */
298
+ /***
299
+ * node启动时将静态资源读取到内存中
300
+ * @appId 打包名称
301
+ * @appSecret 打包版本号
302
+ *
303
+ */
223
304
  initClient = (appId, appSecret) => {
224
305
  if (!this.client) {
225
306
  this.client = new lark.Client({
@@ -241,14 +322,14 @@ class wgtNodeUtils {
241
322
  if (!useSendFeiShu) {
242
323
  return;
243
324
  }
244
- // 发送消息
245
- this.client.im.message.create({
325
+ // 发送消息
326
+ this.client.im.message.create({
246
327
  params: {
247
328
  receive_id_type: 'chat_id'
248
329
  },
249
330
  data: {
250
331
  receive_id: receive_id,
251
- msg_type: 'text',
332
+ msg_type: 'text',
252
333
  content: feiShuContent,
253
334
  uuid: ''
254
335
  }
@@ -283,7 +364,7 @@ class wgtNodeUtils {
283
364
  * }
284
365
  *
285
366
  */
286
- appendLog = (message, ENV, components, err, options = {} ) => {
367
+ appendLog = (message, ENV, components, err, options = {}) => {
287
368
  const {
288
369
  usePageUrl = false,
289
370
  req = null,
@@ -291,7 +372,7 @@ class wgtNodeUtils {
291
372
  useSendFeiShu = false
292
373
  } = options;
293
374
  try {
294
- let feiShuContent = `{"text":"<b>前端容器node报错</b>\\ncomponent: ${components}\\nenv: ${ENV}\\nmesssage: ${message}"}`
375
+ let feiShuContent = `{"text":"<b>前端容器node报错</b>\\ncomponent: ${components}\\nenv: ${ENV}\\nmesssage: ${message}"}`
295
376
  if (usePageUrl && req) {
296
377
  const pageUrl = new URL(req.originalUrl, `${req.protocol}://${req.get('host')}`).href;
297
378
  feiShuContent = `{"text":"<b>前端容器node报错</b>\\ncomponent: ${components}\\nenv: ${ENV}\\npageUrl: ${decodeURIComponent(pageUrl)}\\nmesssage: ${message}"}`
@@ -305,7 +386,7 @@ class wgtNodeUtils {
305
386
  console.error(`${message} [${err.config.method}]: ${err.config.url}`);
306
387
  // console.error(`request: {params: ${JSON.stringify(err.config.params)}, data: ${ err.config.data ? JSON.stringify(err.config.data) : ''}}`);
307
388
  // console.error(`response: ${JSON.stringify( this.safeStringify(err.response.data))}`);
308
-
389
+
309
390
  this.sendFeiShu(feiShuContent, receive_id, useSendFeiShu);
310
391
 
311
392
  } else {
@@ -321,13 +402,13 @@ class wgtNodeUtils {
321
402
  safeStringify = (obj) => {
322
403
  const seen = new WeakSet();
323
404
  return JSON.stringify(obj, (key, value) => {
324
- if (typeof value === 'object' && value !== null) {
325
- if (seen.has(value)) {
326
- return; // 忽略循环引用
405
+ if (typeof value === 'object' && value !== null) {
406
+ if (seen.has(value)) {
407
+ return; // 忽略循环引用
408
+ }
409
+ seen.add(value);
327
410
  }
328
- seen.add(value);
329
- }
330
- return value;
411
+ return value;
331
412
  });
332
413
  }
333
414
  /**
@@ -346,34 +427,33 @@ class wgtNodeUtils {
346
427
  /**
347
428
  * 用于渲染游戏卡列表,清理无用字段
348
429
  * @param list 清理数组
430
+ * @param need 需要的字段 [game_id,game_category]
349
431
  */
350
- clearGameCardListData = (list, options = {}) => {
351
- // 支持传入 option 参数,按需求进行字段过滤
352
- // options.fields: 指定需要输出的字段数组,如 ['id', 'name', 'icon']
353
- const defaultFields = [
354
- 'id', 'game_category', 'icon', 'path', 'name', 'icon_video', 'new', 'developer'
355
- ];
356
- const fields = Array.isArray(options.fields) && options.fields.length > 0 ? options.fields : defaultFields;
432
+ clearGameCardListData = (list, need=[]) => {
433
+ // 游戏卡片使用到的字段
357
434
  return list.map((item = {}) => {
358
- // 统一字段映射
359
- const mapping = {
360
- id: item.game_id,
361
- game_category: item.game_category,
362
- icon: item.base_icon,
363
- path: item.game_path,
364
- name: item.game_name,
365
- icon_video: item.icon_video,
366
- developer: item.developer,
367
- new: item.new ? true : undefined // 将false转换为undefined, 用于节省ssr生成的文本长度
368
- };
369
- // 只输出指定字段
370
- const result = {};
371
- fields.forEach(key => {
372
- if (Object.prototype.hasOwnProperty.call(mapping, key)) {
373
- result[key] = mapping[key];
435
+ var result = {};
436
+ if (need.length === 0) {
437
+ return {
438
+ id: item.game_id,
439
+ game_category: item.game_category,
440
+ icon: item.base_icon,
441
+ path: item.game_path,
442
+ name: item.game_name,
443
+ icon_video: item.icon_video,
444
+ new: item.new ? true : undefined // 将false转换为undefined, 用于节省ssr生成的文本长度
374
445
  }
375
- });
376
- return result;
446
+ } else {
447
+ for (var i of need) {
448
+ result[i] = item[i] ? item[i] : '';
449
+ }
450
+ result.name = item.game_name || "";
451
+ result.id = item.game_id || "";
452
+ result.icon = item.base_icon || "";
453
+ result.path = item.game_path || "";
454
+ return result;
455
+ }
456
+
377
457
  });
378
458
  }
379
459
 
@@ -394,8 +474,8 @@ class wgtNodeUtils {
394
474
  let categoryBgColor = '';
395
475
  const categorys = game.categorys.map((item = {}) => {
396
476
  // 抽取第一个存在背景配置的分类
397
- if (!categoryBg.bg_left && !categoryBg.bg_right && !categoryBg.bg_bottom && item.bg_img) {
398
- const bgImg = item.bg_img || {};
477
+ if (!categoryBg.bg_left && !categoryBg.bg_right && !categoryBg.bg_bottom && item.bg_img) {
478
+ const bgImg = item.bg_img || {};
399
479
  categoryBg = {
400
480
  bg_left: bgImg.bg_left ? `${imgDomain}/${bgImg.bg_left}` : '',
401
481
  bg_right: bgImg.bg_right ? `${imgDomain}/${bgImg.bg_right}` : '',
@@ -506,9 +586,9 @@ class wgtNodeUtils {
506
586
  path: path,
507
587
  method: 'GET'
508
588
  };
509
-
589
+
510
590
  const req = https.request(options, (res) => {
511
- console.log(res.statusCode,'状态码')
591
+ console.log(res.statusCode, '状态码')
512
592
  // 如果状态码为 200,则说明域名可访问
513
593
  if (res.statusCode === 200) {
514
594
  resolve(true);
@@ -516,13 +596,13 @@ class wgtNodeUtils {
516
596
  resolve(false);
517
597
  }
518
598
  });
519
-
599
+
520
600
  req.on('error', (error) => {
521
601
  // 发生错误,说明域名不可访问
522
- console.log(error,'错误信息')
602
+ console.log(error, '错误信息')
523
603
  resolve(false);
524
604
  });
525
-
605
+
526
606
  req.end();
527
607
  });
528
608
  }
@@ -553,13 +633,13 @@ class wgtNodeUtils {
553
633
  gameDomain = GAME_DEFAULT_DOMAIN;
554
634
  }
555
635
  }
556
-
636
+
557
637
  // 当前游戏domain 为默认游戏域名
558
638
  if (gameDomain === GAME_DEFAULT_DOMAIN) {
559
- console.log(new Date(), 'gameResourcesMap:存在且等于默认游戏名使用默认link', this.gameResourcesMap,'link', link);
639
+ console.log(new Date(), 'gameResourcesMap:存在且等于默认游戏名使用默认link', this.gameResourcesMap, 'link', link);
560
640
  return link;
561
641
  }
562
-
642
+
563
643
  // 替换游戏链接
564
644
  if (ENV.includes('prod') || ENV.includes('qa')) {
565
645
  gameLink = link.replace(GAME_DEFAULT_DOMAIN, gameDomain);
@@ -570,7 +650,7 @@ class wgtNodeUtils {
570
650
  console.log(error, 'ReplaceGameResourcesError')
571
651
  gameLink = link;
572
652
  }
573
-
653
+
574
654
  return gameLink;
575
655
  };
576
656
  /**
@@ -653,7 +733,7 @@ class wgtNodeUtils {
653
733
 
654
734
  // 预定义的正则表达式(忽略大小写匹配敏感关键词)
655
735
  const regex = /\.(php|env|xml|production|example)/i;
656
- // 转为小写后检查是否匹配
736
+ // 转为小写后检查是否匹配
657
737
  return regex.test(path.toLowerCase());
658
738
  }
659
739
 
@@ -678,7 +758,7 @@ class wgtNodeUtils {
678
758
  const hasSpecialChar = /[^a-zA-Z0-9/_-]/;
679
759
 
680
760
 
681
- // 任意条件满足即为非法路径
761
+ // 任意条件满足即为非法路径
682
762
  return (
683
763
  illegalPatterns.test(path) || // 检测非法文件扩展或关键词
684
764
  hasUpperCase.test(path) || // 检测大写字母
@@ -695,7 +775,7 @@ class wgtNodeUtils {
695
775
  * @param {boolean} option.useSendFeiShu - 是否需要发送飞书
696
776
  * @returns {string} - SDK JS字符串
697
777
  */
698
- getSdkF2eFiles = async(adsTagHref, ENV, option) => {
778
+ getSdkF2eFiles = async (adsTagHref, ENV, option) => {
699
779
  const {
700
780
  components = '容器名称',
701
781
  receive_id = 'oc_aba13955509035daa7a799f30b1b3341',
@@ -705,8 +785,8 @@ class wgtNodeUtils {
705
785
  // // 生产环境使用API_PATH,其他环境使用adsTagHref
706
786
  // const sdkFilesPath = ENV === 'prod' ? `${API_PATH}/sdk?kaimen=08E28C7EEED6A1B3F9A80154D75A150B` : adsTagHref;
707
787
  // 飞书内容
708
- const feiShuContent = `{"text":"<b>前端容器node报错</b>\\ncomponent: ${components}\\nenv: ${ENV}\\nmesssage: SDK获取失败"}`;
709
-
788
+ const feiShuContent = `{"text":"<b>前端容器node报错</b>\\ncomponent: ${components}\\nenv: ${ENV}\\nmesssage: SDK获取失败"}`;
789
+
710
790
  try {
711
791
  const res = await axios.get(adsTagHref);
712
792
  return res.data;
@@ -739,7 +819,7 @@ class wgtNodeUtils {
739
819
  let languageCode = (acceptLanguage ? acceptLanguage.split(',')[0].split('-')[0].toLowerCase() : LANGUAGE_CODE_LIST[0].code) || (countryCode && countryCode.toLowerCase());
740
820
  // 如果都没有,则使用默认的语言代码列表中的第一个语言代码
741
821
  return LANGUAGE_CODE_LIST.some(item => item.code === languageCode) ? languageCode : LANGUAGE_CODE_LIST[0].code;
742
-
822
+
743
823
  }
744
824
 
745
825
  /**
@@ -755,7 +835,7 @@ class wgtNodeUtils {
755
835
  return new Promise((resolve) => {
756
836
  axios.get(url).then(res => {
757
837
  let siteData;
758
-
838
+
759
839
  if (type === 'content') {
760
840
  siteData = res.data && res.data.data && res.data.data;
761
841
  } else if (type === 'novel') {
@@ -767,7 +847,7 @@ class wgtNodeUtils {
767
847
  if (!siteData) {
768
848
  siteData = ['en'];
769
849
  }
770
-
850
+
771
851
  resolve(this.formatLanguageCodeList(siteData));
772
852
  }).catch(err => {
773
853
  resolve(this.formatLanguageCodeList(['en']));