woodenfish-bot 4.4.3 → 4.4.5

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.
Files changed (3) hide show
  1. package/es/index.js +209 -92
  2. package/lib/index.js +209 -92
  3. package/package.json +1 -1
package/es/index.js CHANGED
@@ -1,10 +1,10 @@
1
+ import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
1
2
  import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
2
3
  import _createClass from '@babel/runtime/helpers/createClass';
3
4
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
5
+ import _regeneratorRuntime from '@babel/runtime/regenerator';
4
6
  import resty from 'resty-client';
5
- import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
6
7
  import _typeof from '@babel/runtime/helpers/typeof';
7
- import _regeneratorRuntime from '@babel/runtime/regenerator';
8
8
  import fs from 'fs';
9
9
  import https from 'https';
10
10
  import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn';
@@ -297,7 +297,7 @@ var Guild = /*#__PURE__*/function () {
297
297
  }]);
298
298
  }();
299
299
 
300
- var version = "4.4.3";
300
+ var version = "4.4.5";
301
301
 
302
302
  function getDefaultExportFromCjs (x) {
303
303
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -677,6 +677,9 @@ log.setLevel('info');
677
677
  log.setLevel('trace');
678
678
  var BotLogger = log;
679
679
 
680
+ // 全局token刷新锁,避免并发刷新
681
+ var tokenRefreshPromises = new Map();
682
+
680
683
  // 转为对象
681
684
  var toObject = function toObject(data) {
682
685
  if (Buffer.isBuffer(data)) return JSON.parse(data.toString());
@@ -755,73 +758,150 @@ function getAccessToken(access_token_file, url, data, appID) {
755
758
  });
756
759
  }
757
760
 
758
- // 添加 User-Agent
759
- var addAuthorization = /*#__PURE__*/function () {
760
- var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(header, appID, token, clientSecret, apiVersion) {
761
- var now_time, url, data, access_token_file, default_token_json, access_token, expires_in, access_token_json;
762
- return _regeneratorRuntime.wrap(function (_context) {
763
- while (1) switch (_context.prev = _context.next) {
761
+ // 获取或刷新token(带并发控制)
762
+ var getOrRefreshToken = /*#__PURE__*/function () {
763
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(appID, clientSecret) {
764
+ var key, existingPromise, refreshPromise;
765
+ return _regeneratorRuntime.wrap(function (_context2) {
766
+ while (1) switch (_context2.prev = _context2.next) {
764
767
  case 0:
765
- if (!(apiVersion == 'v2')) {
766
- _context.next = 3;
768
+ key = "".concat(appID, ":").concat(clientSecret);
769
+ existingPromise = tokenRefreshPromises.get(key);
770
+ if (!existingPromise) {
771
+ _context2.next = 2;
767
772
  break;
768
773
  }
769
- now_time = getTimeStampNumber();
770
- url = 'https://bots.qq.com/app/getAppAccessToken';
771
- data = {
772
- appId: appID,
773
- clientSecret: clientSecret
774
- };
775
- access_token_file = './access_token.json';
776
- default_token_json = {
777
- bot: _defineProperty({}, appID, {
778
- access_token: "",
779
- expires_in: ""
780
- })
781
- };
782
- access_token = '';
783
- expires_in = 0;
784
- try {
785
- // 判断文件是否存在
786
- if (fs.existsSync(access_token_file)) {
787
- // 执行文件存在时的处理逻辑
788
- access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString()); // 判断是否存在appID
789
- if (access_token_json.hasOwnProperty('bot') && access_token_json['bot'].hasOwnProperty(appID)) {
790
- access_token = access_token_json['bot'][appID]['access_token'];
791
- expires_in = parseInt(access_token_json['bot'][appID]['expires_in']);
774
+ // 如果已经有刷新在进行,等待它完成
775
+ console.log("\u7B49\u5F85\u5DF2\u6709\u7684token\u5237\u65B0\u5B8C\u6210 (appID: ".concat(appID, ")"));
776
+ _context2.next = 1;
777
+ return existingPromise;
778
+ case 1:
779
+ return _context2.abrupt("return", _context2.sent);
780
+ case 2:
781
+ // 创建新的刷新Promise
782
+ refreshPromise = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
783
+ var now_time, url, data, access_token_file, access_token, expires_in, needsRefresh, access_token_json, expiresStr, parsed, default_token_json;
784
+ return _regeneratorRuntime.wrap(function (_context) {
785
+ while (1) switch (_context.prev = _context.next) {
786
+ case 0:
787
+ _context.prev = 0;
788
+ now_time = getTimeStampNumber();
789
+ url = 'https://bots.qq.com/app/getAppAccessToken';
790
+ data = {
791
+ appId: appID,
792
+ clientSecret: clientSecret
793
+ };
794
+ access_token_file = './access_token.json';
795
+ access_token = '';
796
+ expires_in = 0;
797
+ needsRefresh = false;
798
+ try {
799
+ // 判断文件是否存在
800
+ if (fs.existsSync(access_token_file)) {
801
+ // 执行文件存在时的处理逻辑
802
+ access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString()); // 判断是否存在appID
803
+ if (access_token_json.hasOwnProperty('bot') && access_token_json['bot'].hasOwnProperty(appID)) {
804
+ access_token = access_token_json['bot'][appID]['access_token'];
805
+ expiresStr = access_token_json['bot'][appID]['expires_in']; // 改进expires_in解析,防止NaN
806
+ if (expiresStr && typeof expiresStr === 'string') {
807
+ parsed = parseInt(expiresStr);
808
+ if (!isNaN(parsed) && parsed > 0) {
809
+ expires_in = parsed;
810
+ } else {
811
+ console.log('expires_in解析失败,重置为0:', expiresStr);
812
+ expires_in = 0;
813
+ }
814
+ } else {
815
+ expires_in = 0;
816
+ }
817
+ }
818
+ } else {
819
+ // 执行文件不存在时的处理逻辑
820
+ default_token_json = {
821
+ bot: _defineProperty({}, appID, {
822
+ access_token: "",
823
+ expires_in: ""
824
+ })
825
+ };
826
+ fs.writeFileSync(access_token_file, JSON.stringify(default_token_json, null, 2), 'utf-8');
827
+ needsRefresh = true;
828
+ }
829
+ } catch (err) {
830
+ console.error('读取文件时发生错误:', err);
831
+ // 出错时重置expires_in为0,强制重新获取token
832
+ expires_in = 0;
833
+ needsRefresh = true;
834
+ }
835
+
836
+ // 判断是否需要刷新token
837
+ if (!(access_token === '' || now_time > expires_in - 50 || needsRefresh)) {
838
+ _context.next = 2;
839
+ break;
840
+ }
841
+ console.log('检测到access_token需要刷新 - 当前token:', access_token, '过期时间:', expires_in, '当前时间:', now_time);
842
+ _context.next = 1;
843
+ return getAccessToken(access_token_file, url, data, appID);
844
+ case 1:
845
+ access_token = _context.sent;
846
+ console.log('access_token刷新成功,新token:', access_token);
847
+ case 2:
848
+ return _context.abrupt("return", access_token);
849
+ case 3:
850
+ _context.prev = 3;
851
+ // 刷新完成后移除Promise
852
+ tokenRefreshPromises["delete"](key);
853
+ return _context.finish(3);
854
+ case 4:
855
+ case "end":
856
+ return _context.stop();
792
857
  }
793
- } else {
794
- // 执行文件不存在时的处理逻辑
795
- fs.writeFileSync(access_token_file, JSON.stringify(default_token_json, null, 2), 'utf-8');
796
- }
797
- } catch (err) {
798
- console.error('读取文件时发生错误:', err);
799
- }
800
- // 判断access_token是否存在,不存在或者已经过期就重新获取
801
- if (!(access_token === '' || now_time > expires_in - 50)) {
802
- _context.next = 2;
858
+ }, _callee, null, [[0,, 3, 4]]);
859
+ }))(); // 存储Promise以便其他并发请求使用
860
+ tokenRefreshPromises.set(key, refreshPromise);
861
+ _context2.next = 3;
862
+ return refreshPromise;
863
+ case 3:
864
+ return _context2.abrupt("return", _context2.sent);
865
+ case 4:
866
+ case "end":
867
+ return _context2.stop();
868
+ }
869
+ }, _callee2);
870
+ }));
871
+ return function getOrRefreshToken(_x, _x2) {
872
+ return _ref.apply(this, arguments);
873
+ };
874
+ }();
875
+
876
+ // 添加 User-Agent
877
+ var addAuthorization = /*#__PURE__*/function () {
878
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(header, appID, token, clientSecret, apiVersion) {
879
+ var access_token;
880
+ return _regeneratorRuntime.wrap(function (_context3) {
881
+ while (1) switch (_context3.prev = _context3.next) {
882
+ case 0:
883
+ if (!(apiVersion == 'v2')) {
884
+ _context3.next = 2;
803
885
  break;
804
886
  }
805
- console.log('access_token', access_token, 'expire_time', expires_in);
806
- _context.next = 1;
807
- return getAccessToken(access_token_file, url, data, appID);
887
+ _context3.next = 1;
888
+ return getOrRefreshToken(appID, clientSecret);
808
889
  case 1:
809
- access_token = _context.sent;
810
- case 2:
890
+ access_token = _context3.sent;
811
891
  // 更新header['Authorization']
812
892
  header['Authorization'] = "QQBot ".concat(access_token);
813
- _context.next = 4;
893
+ _context3.next = 3;
814
894
  break;
815
- case 3:
895
+ case 2:
816
896
  header['Authorization'] = "Bot ".concat(appID, ".").concat(token);
817
- case 4:
897
+ case 3:
818
898
  case "end":
819
- return _context.stop();
899
+ return _context3.stop();
820
900
  }
821
- }, _callee);
901
+ }, _callee3);
822
902
  }));
823
- return function addAuthorization(_x, _x2, _x3, _x4, _x5) {
824
- return _ref.apply(this, arguments);
903
+ return function addAuthorization(_x3, _x4, _x5, _x6, _x7) {
904
+ return _ref3.apply(this, arguments);
825
905
  };
826
906
  }();
827
907
  // 组装完整Url
@@ -1912,7 +1992,7 @@ var Interaction = /*#__PURE__*/function () {
1912
1992
 
1913
1993
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
1914
1994
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
1915
- var apiVersion = 'v1';
1995
+ var apiVersion = 'v2';
1916
1996
  var OpenAPI = /*#__PURE__*/function () {
1917
1997
  function OpenAPI(config) {
1918
1998
  _classCallCheck(this, OpenAPI);
@@ -1966,41 +2046,78 @@ var OpenAPI = /*#__PURE__*/function () {
1966
2046
  // 基础rest请求
1967
2047
  }, {
1968
2048
  key: "request",
1969
- value: function request(options) {
1970
- var _this$config = this.config,
1971
- appID = _this$config.appID,
1972
- token = _this$config.token,
1973
- clientSecret = _this$config.clientSecret;
1974
- options.headers = _objectSpread({}, options.headers);
1975
- var apiVersion = options.apiVersion || '';
1976
- // 添加 UA
1977
- addUserAgent(options.headers, appID, apiVersion);
1978
- // 添加鉴权信息
1979
- addAuthorization(options.headers, appID, token, clientSecret, apiVersion);
1980
- // 组装完整Url
1981
- var botUrl = buildUrl(options.url, this.config.sandbox);
1982
-
1983
- // 简化错误信息,后续可考虑通过中间件形式暴露给用户自行处理
1984
- resty.useRes(function (result) {
1985
- return result;
1986
- }, function (error) {
1987
- var _error$response, _error$response2;
1988
- var traceid = error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 || (_error$response = _error$response.headers) === null || _error$response === void 0 ? void 0 : _error$response['x-tps-trace-id'];
1989
- if (error !== null && error !== void 0 && (_error$response2 = error.response) !== null && _error$response2 !== void 0 && _error$response2.data) {
1990
- return Promise.reject(_objectSpread(_objectSpread({}, error.response.data), {}, {
1991
- traceid: traceid
1992
- }));
1993
- }
1994
- if (error !== null && error !== void 0 && error.response) {
1995
- return Promise.reject(_objectSpread(_objectSpread({}, error.response), {}, {
1996
- traceid: traceid
1997
- }));
1998
- }
1999
- return Promise.reject(error);
2000
- });
2001
- var client = resty.create(options);
2002
- return client.request(botUrl, options);
2003
- }
2049
+ value: function () {
2050
+ var _request = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) {
2051
+ var _this$config, appID, token, clientSecret, apiVersion, botUrl, client, retryClient, _t, _t2;
2052
+ return _regeneratorRuntime.wrap(function (_context) {
2053
+ while (1) switch (_context.prev = _context.next) {
2054
+ case 0:
2055
+ _this$config = this.config, appID = _this$config.appID, token = _this$config.token, clientSecret = _this$config.clientSecret;
2056
+ options.headers = _objectSpread({}, options.headers);
2057
+ apiVersion = options.apiVersion || 'v2'; // 添加 UA
2058
+ addUserAgent(options.headers, appID, apiVersion);
2059
+ // 添加鉴权信息
2060
+ _context.next = 1;
2061
+ return addAuthorization(options.headers, appID, token, clientSecret, apiVersion);
2062
+ case 1:
2063
+ // 组装完整Url
2064
+ botUrl = buildUrl(options.url, this.config.sandbox); // 简化错误信息,后续可考虑通过中间件形式暴露给用户自行处理
2065
+ resty.useRes(function (result) {
2066
+ return result;
2067
+ }, function (error) {
2068
+ var _error$response, _error$response2;
2069
+ var traceid = error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 || (_error$response = _error$response.headers) === null || _error$response === void 0 ? void 0 : _error$response['x-tps-trace-id'];
2070
+ if (error !== null && error !== void 0 && (_error$response2 = error.response) !== null && _error$response2 !== void 0 && _error$response2.data) {
2071
+ return Promise.reject(_objectSpread(_objectSpread({}, error.response.data), {}, {
2072
+ traceid: traceid
2073
+ }));
2074
+ }
2075
+ if (error !== null && error !== void 0 && error.response) {
2076
+ return Promise.reject(_objectSpread(_objectSpread({}, error.response), {}, {
2077
+ traceid: traceid
2078
+ }));
2079
+ }
2080
+ return Promise.reject(error);
2081
+ });
2082
+ client = resty.create(options);
2083
+ _context.prev = 2;
2084
+ _context.next = 3;
2085
+ return client.request(botUrl, options);
2086
+ case 3:
2087
+ return _context.abrupt("return", _context.sent);
2088
+ case 4:
2089
+ _context.prev = 4;
2090
+ _t = _context["catch"](2);
2091
+ if (!((_t === null || _t === void 0 ? void 0 : _t.code) === 11201 || (_t === null || _t === void 0 ? void 0 : _t.err_code) === 40012001)) {
2092
+ _context.next = 8;
2093
+ break;
2094
+ }
2095
+ console.log('检测到认证失败,尝试重试请求...');
2096
+ _context.prev = 5;
2097
+ // 由于addAuthorization现在是并发安全的,重试时会自动获取最新token
2098
+ retryClient = resty.create(options);
2099
+ _context.next = 6;
2100
+ return retryClient.request(botUrl, options);
2101
+ case 6:
2102
+ return _context.abrupt("return", _context.sent);
2103
+ case 7:
2104
+ _context.prev = 7;
2105
+ _t2 = _context["catch"](5);
2106
+ console.log('重试请求仍然失败:', _t2);
2107
+ throw _t2;
2108
+ case 8:
2109
+ throw _t;
2110
+ case 9:
2111
+ case "end":
2112
+ return _context.stop();
2113
+ }
2114
+ }, _callee, this, [[2, 4], [5, 7]]);
2115
+ }));
2116
+ function request(_x) {
2117
+ return _request.apply(this, arguments);
2118
+ }
2119
+ return request;
2120
+ }()
2004
2121
  }], [{
2005
2122
  key: "newClient",
2006
2123
  value: function newClient(config) {
package/lib/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
3
4
  var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
4
5
  var _createClass = require('@babel/runtime/helpers/createClass');
5
6
  var _defineProperty = require('@babel/runtime/helpers/defineProperty');
7
+ var _regeneratorRuntime = require('@babel/runtime/regenerator');
6
8
  var resty = require('resty-client');
7
- var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
8
9
  var _typeof = require('@babel/runtime/helpers/typeof');
9
- var _regeneratorRuntime = require('@babel/runtime/regenerator');
10
10
  var fs = require('fs');
11
11
  var https = require('https');
12
12
  var _possibleConstructorReturn = require('@babel/runtime/helpers/possibleConstructorReturn');
@@ -299,7 +299,7 @@ var Guild = /*#__PURE__*/function () {
299
299
  }]);
300
300
  }();
301
301
 
302
- var version = "4.4.3";
302
+ var version = "4.4.5";
303
303
 
304
304
  function getDefaultExportFromCjs (x) {
305
305
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -679,6 +679,9 @@ log.setLevel('info');
679
679
  log.setLevel('trace');
680
680
  var BotLogger = log;
681
681
 
682
+ // 全局token刷新锁,避免并发刷新
683
+ var tokenRefreshPromises = new Map();
684
+
682
685
  // 转为对象
683
686
  var toObject = function toObject(data) {
684
687
  if (Buffer.isBuffer(data)) return JSON.parse(data.toString());
@@ -757,73 +760,150 @@ function getAccessToken(access_token_file, url, data, appID) {
757
760
  });
758
761
  }
759
762
 
760
- // 添加 User-Agent
761
- var addAuthorization = /*#__PURE__*/function () {
762
- var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(header, appID, token, clientSecret, apiVersion) {
763
- var now_time, url, data, access_token_file, default_token_json, access_token, expires_in, access_token_json;
764
- return _regeneratorRuntime.wrap(function (_context) {
765
- while (1) switch (_context.prev = _context.next) {
763
+ // 获取或刷新token(带并发控制)
764
+ var getOrRefreshToken = /*#__PURE__*/function () {
765
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(appID, clientSecret) {
766
+ var key, existingPromise, refreshPromise;
767
+ return _regeneratorRuntime.wrap(function (_context2) {
768
+ while (1) switch (_context2.prev = _context2.next) {
766
769
  case 0:
767
- if (!(apiVersion == 'v2')) {
768
- _context.next = 3;
770
+ key = "".concat(appID, ":").concat(clientSecret);
771
+ existingPromise = tokenRefreshPromises.get(key);
772
+ if (!existingPromise) {
773
+ _context2.next = 2;
769
774
  break;
770
775
  }
771
- now_time = getTimeStampNumber();
772
- url = 'https://bots.qq.com/app/getAppAccessToken';
773
- data = {
774
- appId: appID,
775
- clientSecret: clientSecret
776
- };
777
- access_token_file = './access_token.json';
778
- default_token_json = {
779
- bot: _defineProperty({}, appID, {
780
- access_token: "",
781
- expires_in: ""
782
- })
783
- };
784
- access_token = '';
785
- expires_in = 0;
786
- try {
787
- // 判断文件是否存在
788
- if (fs.existsSync(access_token_file)) {
789
- // 执行文件存在时的处理逻辑
790
- access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString()); // 判断是否存在appID
791
- if (access_token_json.hasOwnProperty('bot') && access_token_json['bot'].hasOwnProperty(appID)) {
792
- access_token = access_token_json['bot'][appID]['access_token'];
793
- expires_in = parseInt(access_token_json['bot'][appID]['expires_in']);
776
+ // 如果已经有刷新在进行,等待它完成
777
+ console.log("\u7B49\u5F85\u5DF2\u6709\u7684token\u5237\u65B0\u5B8C\u6210 (appID: ".concat(appID, ")"));
778
+ _context2.next = 1;
779
+ return existingPromise;
780
+ case 1:
781
+ return _context2.abrupt("return", _context2.sent);
782
+ case 2:
783
+ // 创建新的刷新Promise
784
+ refreshPromise = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
785
+ var now_time, url, data, access_token_file, access_token, expires_in, needsRefresh, access_token_json, expiresStr, parsed, default_token_json;
786
+ return _regeneratorRuntime.wrap(function (_context) {
787
+ while (1) switch (_context.prev = _context.next) {
788
+ case 0:
789
+ _context.prev = 0;
790
+ now_time = getTimeStampNumber();
791
+ url = 'https://bots.qq.com/app/getAppAccessToken';
792
+ data = {
793
+ appId: appID,
794
+ clientSecret: clientSecret
795
+ };
796
+ access_token_file = './access_token.json';
797
+ access_token = '';
798
+ expires_in = 0;
799
+ needsRefresh = false;
800
+ try {
801
+ // 判断文件是否存在
802
+ if (fs.existsSync(access_token_file)) {
803
+ // 执行文件存在时的处理逻辑
804
+ access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString()); // 判断是否存在appID
805
+ if (access_token_json.hasOwnProperty('bot') && access_token_json['bot'].hasOwnProperty(appID)) {
806
+ access_token = access_token_json['bot'][appID]['access_token'];
807
+ expiresStr = access_token_json['bot'][appID]['expires_in']; // 改进expires_in解析,防止NaN
808
+ if (expiresStr && typeof expiresStr === 'string') {
809
+ parsed = parseInt(expiresStr);
810
+ if (!isNaN(parsed) && parsed > 0) {
811
+ expires_in = parsed;
812
+ } else {
813
+ console.log('expires_in解析失败,重置为0:', expiresStr);
814
+ expires_in = 0;
815
+ }
816
+ } else {
817
+ expires_in = 0;
818
+ }
819
+ }
820
+ } else {
821
+ // 执行文件不存在时的处理逻辑
822
+ default_token_json = {
823
+ bot: _defineProperty({}, appID, {
824
+ access_token: "",
825
+ expires_in: ""
826
+ })
827
+ };
828
+ fs.writeFileSync(access_token_file, JSON.stringify(default_token_json, null, 2), 'utf-8');
829
+ needsRefresh = true;
830
+ }
831
+ } catch (err) {
832
+ console.error('读取文件时发生错误:', err);
833
+ // 出错时重置expires_in为0,强制重新获取token
834
+ expires_in = 0;
835
+ needsRefresh = true;
836
+ }
837
+
838
+ // 判断是否需要刷新token
839
+ if (!(access_token === '' || now_time > expires_in - 50 || needsRefresh)) {
840
+ _context.next = 2;
841
+ break;
842
+ }
843
+ console.log('检测到access_token需要刷新 - 当前token:', access_token, '过期时间:', expires_in, '当前时间:', now_time);
844
+ _context.next = 1;
845
+ return getAccessToken(access_token_file, url, data, appID);
846
+ case 1:
847
+ access_token = _context.sent;
848
+ console.log('access_token刷新成功,新token:', access_token);
849
+ case 2:
850
+ return _context.abrupt("return", access_token);
851
+ case 3:
852
+ _context.prev = 3;
853
+ // 刷新完成后移除Promise
854
+ tokenRefreshPromises["delete"](key);
855
+ return _context.finish(3);
856
+ case 4:
857
+ case "end":
858
+ return _context.stop();
794
859
  }
795
- } else {
796
- // 执行文件不存在时的处理逻辑
797
- fs.writeFileSync(access_token_file, JSON.stringify(default_token_json, null, 2), 'utf-8');
798
- }
799
- } catch (err) {
800
- console.error('读取文件时发生错误:', err);
801
- }
802
- // 判断access_token是否存在,不存在或者已经过期就重新获取
803
- if (!(access_token === '' || now_time > expires_in - 50)) {
804
- _context.next = 2;
860
+ }, _callee, null, [[0,, 3, 4]]);
861
+ }))(); // 存储Promise以便其他并发请求使用
862
+ tokenRefreshPromises.set(key, refreshPromise);
863
+ _context2.next = 3;
864
+ return refreshPromise;
865
+ case 3:
866
+ return _context2.abrupt("return", _context2.sent);
867
+ case 4:
868
+ case "end":
869
+ return _context2.stop();
870
+ }
871
+ }, _callee2);
872
+ }));
873
+ return function getOrRefreshToken(_x, _x2) {
874
+ return _ref.apply(this, arguments);
875
+ };
876
+ }();
877
+
878
+ // 添加 User-Agent
879
+ var addAuthorization = /*#__PURE__*/function () {
880
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(header, appID, token, clientSecret, apiVersion) {
881
+ var access_token;
882
+ return _regeneratorRuntime.wrap(function (_context3) {
883
+ while (1) switch (_context3.prev = _context3.next) {
884
+ case 0:
885
+ if (!(apiVersion == 'v2')) {
886
+ _context3.next = 2;
805
887
  break;
806
888
  }
807
- console.log('access_token', access_token, 'expire_time', expires_in);
808
- _context.next = 1;
809
- return getAccessToken(access_token_file, url, data, appID);
889
+ _context3.next = 1;
890
+ return getOrRefreshToken(appID, clientSecret);
810
891
  case 1:
811
- access_token = _context.sent;
812
- case 2:
892
+ access_token = _context3.sent;
813
893
  // 更新header['Authorization']
814
894
  header['Authorization'] = "QQBot ".concat(access_token);
815
- _context.next = 4;
895
+ _context3.next = 3;
816
896
  break;
817
- case 3:
897
+ case 2:
818
898
  header['Authorization'] = "Bot ".concat(appID, ".").concat(token);
819
- case 4:
899
+ case 3:
820
900
  case "end":
821
- return _context.stop();
901
+ return _context3.stop();
822
902
  }
823
- }, _callee);
903
+ }, _callee3);
824
904
  }));
825
- return function addAuthorization(_x, _x2, _x3, _x4, _x5) {
826
- return _ref.apply(this, arguments);
905
+ return function addAuthorization(_x3, _x4, _x5, _x6, _x7) {
906
+ return _ref3.apply(this, arguments);
827
907
  };
828
908
  }();
829
909
  // 组装完整Url
@@ -1914,7 +1994,7 @@ var Interaction = /*#__PURE__*/function () {
1914
1994
 
1915
1995
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
1916
1996
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
1917
- var apiVersion = 'v1';
1997
+ var apiVersion = 'v2';
1918
1998
  var OpenAPI = /*#__PURE__*/function () {
1919
1999
  function OpenAPI(config) {
1920
2000
  _classCallCheck(this, OpenAPI);
@@ -1968,41 +2048,78 @@ var OpenAPI = /*#__PURE__*/function () {
1968
2048
  // 基础rest请求
1969
2049
  }, {
1970
2050
  key: "request",
1971
- value: function request(options) {
1972
- var _this$config = this.config,
1973
- appID = _this$config.appID,
1974
- token = _this$config.token,
1975
- clientSecret = _this$config.clientSecret;
1976
- options.headers = _objectSpread({}, options.headers);
1977
- var apiVersion = options.apiVersion || '';
1978
- // 添加 UA
1979
- addUserAgent(options.headers, appID, apiVersion);
1980
- // 添加鉴权信息
1981
- addAuthorization(options.headers, appID, token, clientSecret, apiVersion);
1982
- // 组装完整Url
1983
- var botUrl = buildUrl(options.url, this.config.sandbox);
1984
-
1985
- // 简化错误信息,后续可考虑通过中间件形式暴露给用户自行处理
1986
- resty.useRes(function (result) {
1987
- return result;
1988
- }, function (error) {
1989
- var _error$response, _error$response2;
1990
- var traceid = error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 || (_error$response = _error$response.headers) === null || _error$response === void 0 ? void 0 : _error$response['x-tps-trace-id'];
1991
- if (error !== null && error !== void 0 && (_error$response2 = error.response) !== null && _error$response2 !== void 0 && _error$response2.data) {
1992
- return Promise.reject(_objectSpread(_objectSpread({}, error.response.data), {}, {
1993
- traceid: traceid
1994
- }));
1995
- }
1996
- if (error !== null && error !== void 0 && error.response) {
1997
- return Promise.reject(_objectSpread(_objectSpread({}, error.response), {}, {
1998
- traceid: traceid
1999
- }));
2000
- }
2001
- return Promise.reject(error);
2002
- });
2003
- var client = resty.create(options);
2004
- return client.request(botUrl, options);
2005
- }
2051
+ value: function () {
2052
+ var _request = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) {
2053
+ var _this$config, appID, token, clientSecret, apiVersion, botUrl, client, retryClient, _t, _t2;
2054
+ return _regeneratorRuntime.wrap(function (_context) {
2055
+ while (1) switch (_context.prev = _context.next) {
2056
+ case 0:
2057
+ _this$config = this.config, appID = _this$config.appID, token = _this$config.token, clientSecret = _this$config.clientSecret;
2058
+ options.headers = _objectSpread({}, options.headers);
2059
+ apiVersion = options.apiVersion || 'v2'; // 添加 UA
2060
+ addUserAgent(options.headers, appID, apiVersion);
2061
+ // 添加鉴权信息
2062
+ _context.next = 1;
2063
+ return addAuthorization(options.headers, appID, token, clientSecret, apiVersion);
2064
+ case 1:
2065
+ // 组装完整Url
2066
+ botUrl = buildUrl(options.url, this.config.sandbox); // 简化错误信息,后续可考虑通过中间件形式暴露给用户自行处理
2067
+ resty.useRes(function (result) {
2068
+ return result;
2069
+ }, function (error) {
2070
+ var _error$response, _error$response2;
2071
+ var traceid = error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 || (_error$response = _error$response.headers) === null || _error$response === void 0 ? void 0 : _error$response['x-tps-trace-id'];
2072
+ if (error !== null && error !== void 0 && (_error$response2 = error.response) !== null && _error$response2 !== void 0 && _error$response2.data) {
2073
+ return Promise.reject(_objectSpread(_objectSpread({}, error.response.data), {}, {
2074
+ traceid: traceid
2075
+ }));
2076
+ }
2077
+ if (error !== null && error !== void 0 && error.response) {
2078
+ return Promise.reject(_objectSpread(_objectSpread({}, error.response), {}, {
2079
+ traceid: traceid
2080
+ }));
2081
+ }
2082
+ return Promise.reject(error);
2083
+ });
2084
+ client = resty.create(options);
2085
+ _context.prev = 2;
2086
+ _context.next = 3;
2087
+ return client.request(botUrl, options);
2088
+ case 3:
2089
+ return _context.abrupt("return", _context.sent);
2090
+ case 4:
2091
+ _context.prev = 4;
2092
+ _t = _context["catch"](2);
2093
+ if (!((_t === null || _t === void 0 ? void 0 : _t.code) === 11201 || (_t === null || _t === void 0 ? void 0 : _t.err_code) === 40012001)) {
2094
+ _context.next = 8;
2095
+ break;
2096
+ }
2097
+ console.log('检测到认证失败,尝试重试请求...');
2098
+ _context.prev = 5;
2099
+ // 由于addAuthorization现在是并发安全的,重试时会自动获取最新token
2100
+ retryClient = resty.create(options);
2101
+ _context.next = 6;
2102
+ return retryClient.request(botUrl, options);
2103
+ case 6:
2104
+ return _context.abrupt("return", _context.sent);
2105
+ case 7:
2106
+ _context.prev = 7;
2107
+ _t2 = _context["catch"](5);
2108
+ console.log('重试请求仍然失败:', _t2);
2109
+ throw _t2;
2110
+ case 8:
2111
+ throw _t;
2112
+ case 9:
2113
+ case "end":
2114
+ return _context.stop();
2115
+ }
2116
+ }, _callee, this, [[2, 4], [5, 7]]);
2117
+ }));
2118
+ function request(_x) {
2119
+ return _request.apply(this, arguments);
2120
+ }
2121
+ return request;
2122
+ }()
2006
2123
  }], [{
2007
2124
  key: "newClient",
2008
2125
  value: function newClient(config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "woodenfish-bot",
3
- "version": "4.4.3",
3
+ "version": "4.4.5",
4
4
  "description": "woodenfish-bot",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"