woodenfish-bot 4.4.4 → 4.4.6
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/es/index.js +266 -72
- package/lib/index.js +266 -72
- package/package.json +1 -1
package/es/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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
|
|
8
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
8
9
|
import fs from 'fs';
|
|
9
10
|
import https from 'https';
|
|
10
11
|
import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn';
|
|
@@ -297,7 +298,7 @@ var Guild = /*#__PURE__*/function () {
|
|
|
297
298
|
}]);
|
|
298
299
|
}();
|
|
299
300
|
|
|
300
|
-
var version = "4.4.
|
|
301
|
+
var version = "4.4.6";
|
|
301
302
|
|
|
302
303
|
function getDefaultExportFromCjs (x) {
|
|
303
304
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -677,6 +678,45 @@ log.setLevel('info');
|
|
|
677
678
|
log.setLevel('trace');
|
|
678
679
|
var BotLogger = log;
|
|
679
680
|
|
|
681
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: true } : { done: false, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = true, u = false; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = true, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
682
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
683
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
684
|
+
|
|
685
|
+
// 全局token刷新锁,避免并发刷新
|
|
686
|
+
var tokenRefreshPromises = new Map();
|
|
687
|
+
|
|
688
|
+
// 定期清理可能遗留的Promise(防止内存泄漏)
|
|
689
|
+
setInterval(function () {
|
|
690
|
+
var now = Date.now();
|
|
691
|
+
var keysToDelete = [];
|
|
692
|
+
var _iterator = _createForOfIteratorHelper(tokenRefreshPromises.entries()),
|
|
693
|
+
_step;
|
|
694
|
+
try {
|
|
695
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
696
|
+
var _step$value = _slicedToArray(_step.value, 2),
|
|
697
|
+
key = _step$value[0],
|
|
698
|
+
_step$value$ = _step$value[1],
|
|
699
|
+
promise = _step$value$.promise,
|
|
700
|
+
timestamp = _step$value$.timestamp;
|
|
701
|
+
// 如果Promise已经存在超过5分钟,可能出现了问题,清理掉
|
|
702
|
+
if (now - timestamp > 5 * 60 * 1000) {
|
|
703
|
+
keysToDelete.push(key);
|
|
704
|
+
console.warn("\u6E05\u7406\u8D85\u65F6\u7684token\u5237\u65B0Promise (key: ".concat(key, ", \u5B58\u5728\u65F6\u95F4: ").concat((now - timestamp) / 1000, "s)"));
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
} catch (err) {
|
|
708
|
+
_iterator.e(err);
|
|
709
|
+
} finally {
|
|
710
|
+
_iterator.f();
|
|
711
|
+
}
|
|
712
|
+
keysToDelete.forEach(function (key) {
|
|
713
|
+
return tokenRefreshPromises["delete"](key);
|
|
714
|
+
});
|
|
715
|
+
if (keysToDelete.length > 0) {
|
|
716
|
+
console.log("\u6E05\u7406\u4E86 ".concat(keysToDelete.length, " \u4E2A\u8D85\u65F6\u7684token\u5237\u65B0Promise"));
|
|
717
|
+
}
|
|
718
|
+
}, 60000); // 每分钟清理一次
|
|
719
|
+
|
|
680
720
|
// 转为对象
|
|
681
721
|
var toObject = function toObject(data) {
|
|
682
722
|
if (Buffer.isBuffer(data)) return JSON.parse(data.toString());
|
|
@@ -755,17 +795,40 @@ function getAccessToken(access_token_file, url, data, appID) {
|
|
|
755
795
|
});
|
|
756
796
|
}
|
|
757
797
|
|
|
758
|
-
//
|
|
759
|
-
var
|
|
760
|
-
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(
|
|
761
|
-
var
|
|
798
|
+
// 等待Promise完成,带超时机制
|
|
799
|
+
var waitForPromiseWithTimeout = /*#__PURE__*/function () {
|
|
800
|
+
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(promise) {
|
|
801
|
+
var timeoutMs,
|
|
802
|
+
timeoutPromise,
|
|
803
|
+
_args = arguments;
|
|
762
804
|
return _regeneratorRuntime.wrap(function (_context) {
|
|
763
805
|
while (1) switch (_context.prev = _context.next) {
|
|
764
806
|
case 0:
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
807
|
+
timeoutMs = _args.length > 1 && _args[1] !== undefined ? _args[1] : 10000;
|
|
808
|
+
timeoutPromise = new Promise(function (_, reject) {
|
|
809
|
+
setTimeout(function () {
|
|
810
|
+
return reject(new Error("Token refresh timeout after ".concat(timeoutMs, "ms")));
|
|
811
|
+
}, timeoutMs);
|
|
812
|
+
});
|
|
813
|
+
return _context.abrupt("return", Promise.race([promise, timeoutPromise]));
|
|
814
|
+
case 1:
|
|
815
|
+
case "end":
|
|
816
|
+
return _context.stop();
|
|
817
|
+
}
|
|
818
|
+
}, _callee);
|
|
819
|
+
}));
|
|
820
|
+
return function waitForPromiseWithTimeout(_x) {
|
|
821
|
+
return _ref.apply(this, arguments);
|
|
822
|
+
};
|
|
823
|
+
}();
|
|
824
|
+
|
|
825
|
+
// 获取或刷新token(带并发控制和超时保护)
|
|
826
|
+
var getOrRefreshToken = /*#__PURE__*/function () {
|
|
827
|
+
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(appID, clientSecret) {
|
|
828
|
+
var now_time, url, data, access_token_file, access_token, expires_in, needsRefresh, access_token_json, expiresStr, parsed, default_token_json, key, existingEntry, refreshPromise, _t2;
|
|
829
|
+
return _regeneratorRuntime.wrap(function (_context3) {
|
|
830
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
831
|
+
case 0:
|
|
769
832
|
now_time = getTimeStampNumber();
|
|
770
833
|
url = 'https://bots.qq.com/app/getAppAccessToken';
|
|
771
834
|
data = {
|
|
@@ -773,55 +836,149 @@ var addAuthorization = /*#__PURE__*/function () {
|
|
|
773
836
|
clientSecret: clientSecret
|
|
774
837
|
};
|
|
775
838
|
access_token_file = './access_token.json';
|
|
776
|
-
default_token_json = {
|
|
777
|
-
bot: _defineProperty({}, appID, {
|
|
778
|
-
access_token: "",
|
|
779
|
-
expires_in: ""
|
|
780
|
-
})
|
|
781
|
-
};
|
|
782
839
|
access_token = '';
|
|
783
840
|
expires_in = 0;
|
|
841
|
+
needsRefresh = false; // 首先读取当前token状态
|
|
784
842
|
try {
|
|
785
|
-
// 判断文件是否存在
|
|
786
843
|
if (fs.existsSync(access_token_file)) {
|
|
787
|
-
|
|
788
|
-
access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString()); // 判断是否存在appID
|
|
844
|
+
access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString());
|
|
789
845
|
if (access_token_json.hasOwnProperty('bot') && access_token_json['bot'].hasOwnProperty(appID)) {
|
|
790
846
|
access_token = access_token_json['bot'][appID]['access_token'];
|
|
791
|
-
|
|
847
|
+
expiresStr = access_token_json['bot'][appID]['expires_in'];
|
|
848
|
+
if (expiresStr && typeof expiresStr === 'string') {
|
|
849
|
+
parsed = parseInt(expiresStr);
|
|
850
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
851
|
+
expires_in = parsed;
|
|
852
|
+
} else {
|
|
853
|
+
console.log('expires_in解析失败,重置为0:', expiresStr);
|
|
854
|
+
expires_in = 0;
|
|
855
|
+
}
|
|
856
|
+
} else {
|
|
857
|
+
expires_in = 0;
|
|
858
|
+
}
|
|
792
859
|
}
|
|
793
860
|
} else {
|
|
794
|
-
|
|
861
|
+
default_token_json = {
|
|
862
|
+
bot: _defineProperty({}, appID, {
|
|
863
|
+
access_token: "",
|
|
864
|
+
expires_in: ""
|
|
865
|
+
})
|
|
866
|
+
};
|
|
795
867
|
fs.writeFileSync(access_token_file, JSON.stringify(default_token_json, null, 2), 'utf-8');
|
|
868
|
+
needsRefresh = true;
|
|
796
869
|
}
|
|
797
870
|
} catch (err) {
|
|
798
871
|
console.error('读取文件时发生错误:', err);
|
|
872
|
+
expires_in = 0;
|
|
873
|
+
needsRefresh = true;
|
|
799
874
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
875
|
+
|
|
876
|
+
// 如果token有效且不需要刷新,直接返回
|
|
877
|
+
if (!(access_token !== '' && now_time <= expires_in - 50 && !needsRefresh)) {
|
|
878
|
+
_context3.next = 1;
|
|
803
879
|
break;
|
|
804
880
|
}
|
|
805
|
-
|
|
806
|
-
_context.next = 1;
|
|
807
|
-
return getAccessToken(access_token_file, url, data, appID);
|
|
881
|
+
return _context3.abrupt("return", access_token);
|
|
808
882
|
case 1:
|
|
809
|
-
|
|
810
|
-
|
|
883
|
+
// 需要刷新token,进入并发控制逻辑
|
|
884
|
+
key = "".concat(appID, ":").concat(clientSecret);
|
|
885
|
+
existingEntry = tokenRefreshPromises.get(key);
|
|
886
|
+
if (!existingEntry) {
|
|
887
|
+
_context3.next = 5;
|
|
888
|
+
break;
|
|
889
|
+
}
|
|
890
|
+
_context3.prev = 2;
|
|
891
|
+
// 等待已有的刷新完成,但设置超时防止无限等待
|
|
892
|
+
console.log("\u7B49\u5F85\u5DF2\u6709\u7684token\u5237\u65B0\u5B8C\u6210 (appID: ".concat(appID, ")"));
|
|
893
|
+
_context3.next = 3;
|
|
894
|
+
return waitForPromiseWithTimeout(existingEntry.promise, 10000);
|
|
895
|
+
case 3:
|
|
896
|
+
return _context3.abrupt("return", _context3.sent);
|
|
897
|
+
case 4:
|
|
898
|
+
_context3.prev = 4;
|
|
899
|
+
_t2 = _context3["catch"](2);
|
|
900
|
+
console.warn("\u7B49\u5F85token\u5237\u65B0\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u91CD\u65B0\u53D1\u8D77\u5237\u65B0 (appID: ".concat(appID, "):"), _t2);
|
|
901
|
+
// 移除失败的Promise,让新的请求可以重新发起刷新
|
|
902
|
+
tokenRefreshPromises["delete"](key);
|
|
903
|
+
case 5:
|
|
904
|
+
// 创建新的刷新Promise
|
|
905
|
+
refreshPromise = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
906
|
+
var new_token, _t;
|
|
907
|
+
return _regeneratorRuntime.wrap(function (_context2) {
|
|
908
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
909
|
+
case 0:
|
|
910
|
+
_context2.prev = 0;
|
|
911
|
+
console.log('开始刷新access_token - 当前token:', access_token, '过期时间:', expires_in, '当前时间:', now_time);
|
|
912
|
+
_context2.next = 1;
|
|
913
|
+
return getAccessToken(access_token_file, url, data, appID);
|
|
914
|
+
case 1:
|
|
915
|
+
new_token = _context2.sent;
|
|
916
|
+
console.log('access_token刷新成功,新token:', new_token);
|
|
917
|
+
return _context2.abrupt("return", new_token);
|
|
918
|
+
case 2:
|
|
919
|
+
_context2.prev = 2;
|
|
920
|
+
_t = _context2["catch"](0);
|
|
921
|
+
console.error("Token\u5237\u65B0\u5931\u8D25 (appID: ".concat(appID, "):"), _t);
|
|
922
|
+
throw _t;
|
|
923
|
+
case 3:
|
|
924
|
+
_context2.prev = 3;
|
|
925
|
+
// 刷新完成后移除Promise
|
|
926
|
+
tokenRefreshPromises["delete"](key);
|
|
927
|
+
return _context2.finish(3);
|
|
928
|
+
case 4:
|
|
929
|
+
case "end":
|
|
930
|
+
return _context2.stop();
|
|
931
|
+
}
|
|
932
|
+
}, _callee2, null, [[0, 2, 3, 4]]);
|
|
933
|
+
}))(); // 存储Promise和时间戳以便其他并发请求使用和超时清理
|
|
934
|
+
tokenRefreshPromises.set(key, {
|
|
935
|
+
promise: refreshPromise,
|
|
936
|
+
timestamp: Date.now()
|
|
937
|
+
});
|
|
938
|
+
_context3.next = 6;
|
|
939
|
+
return refreshPromise;
|
|
940
|
+
case 6:
|
|
941
|
+
return _context3.abrupt("return", _context3.sent);
|
|
942
|
+
case 7:
|
|
943
|
+
case "end":
|
|
944
|
+
return _context3.stop();
|
|
945
|
+
}
|
|
946
|
+
}, _callee3, null, [[2, 4]]);
|
|
947
|
+
}));
|
|
948
|
+
return function getOrRefreshToken(_x2, _x3) {
|
|
949
|
+
return _ref2.apply(this, arguments);
|
|
950
|
+
};
|
|
951
|
+
}();
|
|
952
|
+
|
|
953
|
+
// 添加 User-Agent
|
|
954
|
+
var addAuthorization = /*#__PURE__*/function () {
|
|
955
|
+
var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(header, appID, token, clientSecret, apiVersion) {
|
|
956
|
+
var access_token;
|
|
957
|
+
return _regeneratorRuntime.wrap(function (_context4) {
|
|
958
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
959
|
+
case 0:
|
|
960
|
+
if (!(apiVersion == 'v2')) {
|
|
961
|
+
_context4.next = 2;
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
_context4.next = 1;
|
|
965
|
+
return getOrRefreshToken(appID, clientSecret);
|
|
966
|
+
case 1:
|
|
967
|
+
access_token = _context4.sent;
|
|
811
968
|
// 更新header['Authorization']
|
|
812
969
|
header['Authorization'] = "QQBot ".concat(access_token);
|
|
813
|
-
|
|
970
|
+
_context4.next = 3;
|
|
814
971
|
break;
|
|
815
|
-
case
|
|
972
|
+
case 2:
|
|
816
973
|
header['Authorization'] = "Bot ".concat(appID, ".").concat(token);
|
|
817
|
-
case
|
|
974
|
+
case 3:
|
|
818
975
|
case "end":
|
|
819
|
-
return
|
|
976
|
+
return _context4.stop();
|
|
820
977
|
}
|
|
821
|
-
},
|
|
978
|
+
}, _callee4);
|
|
822
979
|
}));
|
|
823
|
-
return function addAuthorization(
|
|
824
|
-
return
|
|
980
|
+
return function addAuthorization(_x4, _x5, _x6, _x7, _x8) {
|
|
981
|
+
return _ref4.apply(this, arguments);
|
|
825
982
|
};
|
|
826
983
|
}();
|
|
827
984
|
// 组装完整Url
|
|
@@ -1966,41 +2123,78 @@ var OpenAPI = /*#__PURE__*/function () {
|
|
|
1966
2123
|
// 基础rest请求
|
|
1967
2124
|
}, {
|
|
1968
2125
|
key: "request",
|
|
1969
|
-
value: function
|
|
1970
|
-
var
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2126
|
+
value: function () {
|
|
2127
|
+
var _request = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) {
|
|
2128
|
+
var _this$config, appID, token, clientSecret, apiVersion, botUrl, client, retryClient, _t, _t2;
|
|
2129
|
+
return _regeneratorRuntime.wrap(function (_context) {
|
|
2130
|
+
while (1) switch (_context.prev = _context.next) {
|
|
2131
|
+
case 0:
|
|
2132
|
+
_this$config = this.config, appID = _this$config.appID, token = _this$config.token, clientSecret = _this$config.clientSecret;
|
|
2133
|
+
options.headers = _objectSpread({}, options.headers);
|
|
2134
|
+
apiVersion = options.apiVersion || 'v2'; // 添加 UA
|
|
2135
|
+
addUserAgent(options.headers, appID, apiVersion);
|
|
2136
|
+
// 添加鉴权信息
|
|
2137
|
+
_context.next = 1;
|
|
2138
|
+
return addAuthorization(options.headers, appID, token, clientSecret, apiVersion);
|
|
2139
|
+
case 1:
|
|
2140
|
+
// 组装完整Url
|
|
2141
|
+
botUrl = buildUrl(options.url, this.config.sandbox); // 简化错误信息,后续可考虑通过中间件形式暴露给用户自行处理
|
|
2142
|
+
resty.useRes(function (result) {
|
|
2143
|
+
return result;
|
|
2144
|
+
}, function (error) {
|
|
2145
|
+
var _error$response, _error$response2;
|
|
2146
|
+
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'];
|
|
2147
|
+
if (error !== null && error !== void 0 && (_error$response2 = error.response) !== null && _error$response2 !== void 0 && _error$response2.data) {
|
|
2148
|
+
return Promise.reject(_objectSpread(_objectSpread({}, error.response.data), {}, {
|
|
2149
|
+
traceid: traceid
|
|
2150
|
+
}));
|
|
2151
|
+
}
|
|
2152
|
+
if (error !== null && error !== void 0 && error.response) {
|
|
2153
|
+
return Promise.reject(_objectSpread(_objectSpread({}, error.response), {}, {
|
|
2154
|
+
traceid: traceid
|
|
2155
|
+
}));
|
|
2156
|
+
}
|
|
2157
|
+
return Promise.reject(error);
|
|
2158
|
+
});
|
|
2159
|
+
client = resty.create(options);
|
|
2160
|
+
_context.prev = 2;
|
|
2161
|
+
_context.next = 3;
|
|
2162
|
+
return client.request(botUrl, options);
|
|
2163
|
+
case 3:
|
|
2164
|
+
return _context.abrupt("return", _context.sent);
|
|
2165
|
+
case 4:
|
|
2166
|
+
_context.prev = 4;
|
|
2167
|
+
_t = _context["catch"](2);
|
|
2168
|
+
if (!((_t === null || _t === void 0 ? void 0 : _t.code) === 11201 || (_t === null || _t === void 0 ? void 0 : _t.err_code) === 40012001)) {
|
|
2169
|
+
_context.next = 8;
|
|
2170
|
+
break;
|
|
2171
|
+
}
|
|
2172
|
+
console.log('检测到认证失败,尝试重试请求...');
|
|
2173
|
+
_context.prev = 5;
|
|
2174
|
+
// 由于addAuthorization现在是并发安全的,重试时会自动获取最新token
|
|
2175
|
+
retryClient = resty.create(options);
|
|
2176
|
+
_context.next = 6;
|
|
2177
|
+
return retryClient.request(botUrl, options);
|
|
2178
|
+
case 6:
|
|
2179
|
+
return _context.abrupt("return", _context.sent);
|
|
2180
|
+
case 7:
|
|
2181
|
+
_context.prev = 7;
|
|
2182
|
+
_t2 = _context["catch"](5);
|
|
2183
|
+
console.log('重试请求仍然失败:', _t2);
|
|
2184
|
+
throw _t2;
|
|
2185
|
+
case 8:
|
|
2186
|
+
throw _t;
|
|
2187
|
+
case 9:
|
|
2188
|
+
case "end":
|
|
2189
|
+
return _context.stop();
|
|
2190
|
+
}
|
|
2191
|
+
}, _callee, this, [[2, 4], [5, 7]]);
|
|
2192
|
+
}));
|
|
2193
|
+
function request(_x) {
|
|
2194
|
+
return _request.apply(this, arguments);
|
|
2195
|
+
}
|
|
2196
|
+
return request;
|
|
2197
|
+
}()
|
|
2004
2198
|
}], [{
|
|
2005
2199
|
key: "newClient",
|
|
2006
2200
|
value: function newClient(config) {
|
package/lib/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
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
|
|
10
|
+
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
|
|
10
11
|
var fs = require('fs');
|
|
11
12
|
var https = require('https');
|
|
12
13
|
var _possibleConstructorReturn = require('@babel/runtime/helpers/possibleConstructorReturn');
|
|
@@ -299,7 +300,7 @@ var Guild = /*#__PURE__*/function () {
|
|
|
299
300
|
}]);
|
|
300
301
|
}();
|
|
301
302
|
|
|
302
|
-
var version = "4.4.
|
|
303
|
+
var version = "4.4.6";
|
|
303
304
|
|
|
304
305
|
function getDefaultExportFromCjs (x) {
|
|
305
306
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -679,6 +680,45 @@ log.setLevel('info');
|
|
|
679
680
|
log.setLevel('trace');
|
|
680
681
|
var BotLogger = log;
|
|
681
682
|
|
|
683
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: true } : { done: false, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = true, u = false; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = true, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
684
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
685
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
686
|
+
|
|
687
|
+
// 全局token刷新锁,避免并发刷新
|
|
688
|
+
var tokenRefreshPromises = new Map();
|
|
689
|
+
|
|
690
|
+
// 定期清理可能遗留的Promise(防止内存泄漏)
|
|
691
|
+
setInterval(function () {
|
|
692
|
+
var now = Date.now();
|
|
693
|
+
var keysToDelete = [];
|
|
694
|
+
var _iterator = _createForOfIteratorHelper(tokenRefreshPromises.entries()),
|
|
695
|
+
_step;
|
|
696
|
+
try {
|
|
697
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
698
|
+
var _step$value = _slicedToArray(_step.value, 2),
|
|
699
|
+
key = _step$value[0],
|
|
700
|
+
_step$value$ = _step$value[1],
|
|
701
|
+
promise = _step$value$.promise,
|
|
702
|
+
timestamp = _step$value$.timestamp;
|
|
703
|
+
// 如果Promise已经存在超过5分钟,可能出现了问题,清理掉
|
|
704
|
+
if (now - timestamp > 5 * 60 * 1000) {
|
|
705
|
+
keysToDelete.push(key);
|
|
706
|
+
console.warn("\u6E05\u7406\u8D85\u65F6\u7684token\u5237\u65B0Promise (key: ".concat(key, ", \u5B58\u5728\u65F6\u95F4: ").concat((now - timestamp) / 1000, "s)"));
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
} catch (err) {
|
|
710
|
+
_iterator.e(err);
|
|
711
|
+
} finally {
|
|
712
|
+
_iterator.f();
|
|
713
|
+
}
|
|
714
|
+
keysToDelete.forEach(function (key) {
|
|
715
|
+
return tokenRefreshPromises["delete"](key);
|
|
716
|
+
});
|
|
717
|
+
if (keysToDelete.length > 0) {
|
|
718
|
+
console.log("\u6E05\u7406\u4E86 ".concat(keysToDelete.length, " \u4E2A\u8D85\u65F6\u7684token\u5237\u65B0Promise"));
|
|
719
|
+
}
|
|
720
|
+
}, 60000); // 每分钟清理一次
|
|
721
|
+
|
|
682
722
|
// 转为对象
|
|
683
723
|
var toObject = function toObject(data) {
|
|
684
724
|
if (Buffer.isBuffer(data)) return JSON.parse(data.toString());
|
|
@@ -757,17 +797,40 @@ function getAccessToken(access_token_file, url, data, appID) {
|
|
|
757
797
|
});
|
|
758
798
|
}
|
|
759
799
|
|
|
760
|
-
//
|
|
761
|
-
var
|
|
762
|
-
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(
|
|
763
|
-
var
|
|
800
|
+
// 等待Promise完成,带超时机制
|
|
801
|
+
var waitForPromiseWithTimeout = /*#__PURE__*/function () {
|
|
802
|
+
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(promise) {
|
|
803
|
+
var timeoutMs,
|
|
804
|
+
timeoutPromise,
|
|
805
|
+
_args = arguments;
|
|
764
806
|
return _regeneratorRuntime.wrap(function (_context) {
|
|
765
807
|
while (1) switch (_context.prev = _context.next) {
|
|
766
808
|
case 0:
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
809
|
+
timeoutMs = _args.length > 1 && _args[1] !== undefined ? _args[1] : 10000;
|
|
810
|
+
timeoutPromise = new Promise(function (_, reject) {
|
|
811
|
+
setTimeout(function () {
|
|
812
|
+
return reject(new Error("Token refresh timeout after ".concat(timeoutMs, "ms")));
|
|
813
|
+
}, timeoutMs);
|
|
814
|
+
});
|
|
815
|
+
return _context.abrupt("return", Promise.race([promise, timeoutPromise]));
|
|
816
|
+
case 1:
|
|
817
|
+
case "end":
|
|
818
|
+
return _context.stop();
|
|
819
|
+
}
|
|
820
|
+
}, _callee);
|
|
821
|
+
}));
|
|
822
|
+
return function waitForPromiseWithTimeout(_x) {
|
|
823
|
+
return _ref.apply(this, arguments);
|
|
824
|
+
};
|
|
825
|
+
}();
|
|
826
|
+
|
|
827
|
+
// 获取或刷新token(带并发控制和超时保护)
|
|
828
|
+
var getOrRefreshToken = /*#__PURE__*/function () {
|
|
829
|
+
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(appID, clientSecret) {
|
|
830
|
+
var now_time, url, data, access_token_file, access_token, expires_in, needsRefresh, access_token_json, expiresStr, parsed, default_token_json, key, existingEntry, refreshPromise, _t2;
|
|
831
|
+
return _regeneratorRuntime.wrap(function (_context3) {
|
|
832
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
833
|
+
case 0:
|
|
771
834
|
now_time = getTimeStampNumber();
|
|
772
835
|
url = 'https://bots.qq.com/app/getAppAccessToken';
|
|
773
836
|
data = {
|
|
@@ -775,55 +838,149 @@ var addAuthorization = /*#__PURE__*/function () {
|
|
|
775
838
|
clientSecret: clientSecret
|
|
776
839
|
};
|
|
777
840
|
access_token_file = './access_token.json';
|
|
778
|
-
default_token_json = {
|
|
779
|
-
bot: _defineProperty({}, appID, {
|
|
780
|
-
access_token: "",
|
|
781
|
-
expires_in: ""
|
|
782
|
-
})
|
|
783
|
-
};
|
|
784
841
|
access_token = '';
|
|
785
842
|
expires_in = 0;
|
|
843
|
+
needsRefresh = false; // 首先读取当前token状态
|
|
786
844
|
try {
|
|
787
|
-
// 判断文件是否存在
|
|
788
845
|
if (fs.existsSync(access_token_file)) {
|
|
789
|
-
|
|
790
|
-
access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString()); // 判断是否存在appID
|
|
846
|
+
access_token_json = JSON.parse(fs.readFileSync(access_token_file).toString());
|
|
791
847
|
if (access_token_json.hasOwnProperty('bot') && access_token_json['bot'].hasOwnProperty(appID)) {
|
|
792
848
|
access_token = access_token_json['bot'][appID]['access_token'];
|
|
793
|
-
|
|
849
|
+
expiresStr = access_token_json['bot'][appID]['expires_in'];
|
|
850
|
+
if (expiresStr && typeof expiresStr === 'string') {
|
|
851
|
+
parsed = parseInt(expiresStr);
|
|
852
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
853
|
+
expires_in = parsed;
|
|
854
|
+
} else {
|
|
855
|
+
console.log('expires_in解析失败,重置为0:', expiresStr);
|
|
856
|
+
expires_in = 0;
|
|
857
|
+
}
|
|
858
|
+
} else {
|
|
859
|
+
expires_in = 0;
|
|
860
|
+
}
|
|
794
861
|
}
|
|
795
862
|
} else {
|
|
796
|
-
|
|
863
|
+
default_token_json = {
|
|
864
|
+
bot: _defineProperty({}, appID, {
|
|
865
|
+
access_token: "",
|
|
866
|
+
expires_in: ""
|
|
867
|
+
})
|
|
868
|
+
};
|
|
797
869
|
fs.writeFileSync(access_token_file, JSON.stringify(default_token_json, null, 2), 'utf-8');
|
|
870
|
+
needsRefresh = true;
|
|
798
871
|
}
|
|
799
872
|
} catch (err) {
|
|
800
873
|
console.error('读取文件时发生错误:', err);
|
|
874
|
+
expires_in = 0;
|
|
875
|
+
needsRefresh = true;
|
|
801
876
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
877
|
+
|
|
878
|
+
// 如果token有效且不需要刷新,直接返回
|
|
879
|
+
if (!(access_token !== '' && now_time <= expires_in - 50 && !needsRefresh)) {
|
|
880
|
+
_context3.next = 1;
|
|
805
881
|
break;
|
|
806
882
|
}
|
|
807
|
-
|
|
808
|
-
_context.next = 1;
|
|
809
|
-
return getAccessToken(access_token_file, url, data, appID);
|
|
883
|
+
return _context3.abrupt("return", access_token);
|
|
810
884
|
case 1:
|
|
811
|
-
|
|
812
|
-
|
|
885
|
+
// 需要刷新token,进入并发控制逻辑
|
|
886
|
+
key = "".concat(appID, ":").concat(clientSecret);
|
|
887
|
+
existingEntry = tokenRefreshPromises.get(key);
|
|
888
|
+
if (!existingEntry) {
|
|
889
|
+
_context3.next = 5;
|
|
890
|
+
break;
|
|
891
|
+
}
|
|
892
|
+
_context3.prev = 2;
|
|
893
|
+
// 等待已有的刷新完成,但设置超时防止无限等待
|
|
894
|
+
console.log("\u7B49\u5F85\u5DF2\u6709\u7684token\u5237\u65B0\u5B8C\u6210 (appID: ".concat(appID, ")"));
|
|
895
|
+
_context3.next = 3;
|
|
896
|
+
return waitForPromiseWithTimeout(existingEntry.promise, 10000);
|
|
897
|
+
case 3:
|
|
898
|
+
return _context3.abrupt("return", _context3.sent);
|
|
899
|
+
case 4:
|
|
900
|
+
_context3.prev = 4;
|
|
901
|
+
_t2 = _context3["catch"](2);
|
|
902
|
+
console.warn("\u7B49\u5F85token\u5237\u65B0\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u91CD\u65B0\u53D1\u8D77\u5237\u65B0 (appID: ".concat(appID, "):"), _t2);
|
|
903
|
+
// 移除失败的Promise,让新的请求可以重新发起刷新
|
|
904
|
+
tokenRefreshPromises["delete"](key);
|
|
905
|
+
case 5:
|
|
906
|
+
// 创建新的刷新Promise
|
|
907
|
+
refreshPromise = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
908
|
+
var new_token, _t;
|
|
909
|
+
return _regeneratorRuntime.wrap(function (_context2) {
|
|
910
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
911
|
+
case 0:
|
|
912
|
+
_context2.prev = 0;
|
|
913
|
+
console.log('开始刷新access_token - 当前token:', access_token, '过期时间:', expires_in, '当前时间:', now_time);
|
|
914
|
+
_context2.next = 1;
|
|
915
|
+
return getAccessToken(access_token_file, url, data, appID);
|
|
916
|
+
case 1:
|
|
917
|
+
new_token = _context2.sent;
|
|
918
|
+
console.log('access_token刷新成功,新token:', new_token);
|
|
919
|
+
return _context2.abrupt("return", new_token);
|
|
920
|
+
case 2:
|
|
921
|
+
_context2.prev = 2;
|
|
922
|
+
_t = _context2["catch"](0);
|
|
923
|
+
console.error("Token\u5237\u65B0\u5931\u8D25 (appID: ".concat(appID, "):"), _t);
|
|
924
|
+
throw _t;
|
|
925
|
+
case 3:
|
|
926
|
+
_context2.prev = 3;
|
|
927
|
+
// 刷新完成后移除Promise
|
|
928
|
+
tokenRefreshPromises["delete"](key);
|
|
929
|
+
return _context2.finish(3);
|
|
930
|
+
case 4:
|
|
931
|
+
case "end":
|
|
932
|
+
return _context2.stop();
|
|
933
|
+
}
|
|
934
|
+
}, _callee2, null, [[0, 2, 3, 4]]);
|
|
935
|
+
}))(); // 存储Promise和时间戳以便其他并发请求使用和超时清理
|
|
936
|
+
tokenRefreshPromises.set(key, {
|
|
937
|
+
promise: refreshPromise,
|
|
938
|
+
timestamp: Date.now()
|
|
939
|
+
});
|
|
940
|
+
_context3.next = 6;
|
|
941
|
+
return refreshPromise;
|
|
942
|
+
case 6:
|
|
943
|
+
return _context3.abrupt("return", _context3.sent);
|
|
944
|
+
case 7:
|
|
945
|
+
case "end":
|
|
946
|
+
return _context3.stop();
|
|
947
|
+
}
|
|
948
|
+
}, _callee3, null, [[2, 4]]);
|
|
949
|
+
}));
|
|
950
|
+
return function getOrRefreshToken(_x2, _x3) {
|
|
951
|
+
return _ref2.apply(this, arguments);
|
|
952
|
+
};
|
|
953
|
+
}();
|
|
954
|
+
|
|
955
|
+
// 添加 User-Agent
|
|
956
|
+
var addAuthorization = /*#__PURE__*/function () {
|
|
957
|
+
var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(header, appID, token, clientSecret, apiVersion) {
|
|
958
|
+
var access_token;
|
|
959
|
+
return _regeneratorRuntime.wrap(function (_context4) {
|
|
960
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
961
|
+
case 0:
|
|
962
|
+
if (!(apiVersion == 'v2')) {
|
|
963
|
+
_context4.next = 2;
|
|
964
|
+
break;
|
|
965
|
+
}
|
|
966
|
+
_context4.next = 1;
|
|
967
|
+
return getOrRefreshToken(appID, clientSecret);
|
|
968
|
+
case 1:
|
|
969
|
+
access_token = _context4.sent;
|
|
813
970
|
// 更新header['Authorization']
|
|
814
971
|
header['Authorization'] = "QQBot ".concat(access_token);
|
|
815
|
-
|
|
972
|
+
_context4.next = 3;
|
|
816
973
|
break;
|
|
817
|
-
case
|
|
974
|
+
case 2:
|
|
818
975
|
header['Authorization'] = "Bot ".concat(appID, ".").concat(token);
|
|
819
|
-
case
|
|
976
|
+
case 3:
|
|
820
977
|
case "end":
|
|
821
|
-
return
|
|
978
|
+
return _context4.stop();
|
|
822
979
|
}
|
|
823
|
-
},
|
|
980
|
+
}, _callee4);
|
|
824
981
|
}));
|
|
825
|
-
return function addAuthorization(
|
|
826
|
-
return
|
|
982
|
+
return function addAuthorization(_x4, _x5, _x6, _x7, _x8) {
|
|
983
|
+
return _ref4.apply(this, arguments);
|
|
827
984
|
};
|
|
828
985
|
}();
|
|
829
986
|
// 组装完整Url
|
|
@@ -1968,41 +2125,78 @@ var OpenAPI = /*#__PURE__*/function () {
|
|
|
1968
2125
|
// 基础rest请求
|
|
1969
2126
|
}, {
|
|
1970
2127
|
key: "request",
|
|
1971
|
-
value: function
|
|
1972
|
-
var
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2128
|
+
value: function () {
|
|
2129
|
+
var _request = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) {
|
|
2130
|
+
var _this$config, appID, token, clientSecret, apiVersion, botUrl, client, retryClient, _t, _t2;
|
|
2131
|
+
return _regeneratorRuntime.wrap(function (_context) {
|
|
2132
|
+
while (1) switch (_context.prev = _context.next) {
|
|
2133
|
+
case 0:
|
|
2134
|
+
_this$config = this.config, appID = _this$config.appID, token = _this$config.token, clientSecret = _this$config.clientSecret;
|
|
2135
|
+
options.headers = _objectSpread({}, options.headers);
|
|
2136
|
+
apiVersion = options.apiVersion || 'v2'; // 添加 UA
|
|
2137
|
+
addUserAgent(options.headers, appID, apiVersion);
|
|
2138
|
+
// 添加鉴权信息
|
|
2139
|
+
_context.next = 1;
|
|
2140
|
+
return addAuthorization(options.headers, appID, token, clientSecret, apiVersion);
|
|
2141
|
+
case 1:
|
|
2142
|
+
// 组装完整Url
|
|
2143
|
+
botUrl = buildUrl(options.url, this.config.sandbox); // 简化错误信息,后续可考虑通过中间件形式暴露给用户自行处理
|
|
2144
|
+
resty.useRes(function (result) {
|
|
2145
|
+
return result;
|
|
2146
|
+
}, function (error) {
|
|
2147
|
+
var _error$response, _error$response2;
|
|
2148
|
+
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'];
|
|
2149
|
+
if (error !== null && error !== void 0 && (_error$response2 = error.response) !== null && _error$response2 !== void 0 && _error$response2.data) {
|
|
2150
|
+
return Promise.reject(_objectSpread(_objectSpread({}, error.response.data), {}, {
|
|
2151
|
+
traceid: traceid
|
|
2152
|
+
}));
|
|
2153
|
+
}
|
|
2154
|
+
if (error !== null && error !== void 0 && error.response) {
|
|
2155
|
+
return Promise.reject(_objectSpread(_objectSpread({}, error.response), {}, {
|
|
2156
|
+
traceid: traceid
|
|
2157
|
+
}));
|
|
2158
|
+
}
|
|
2159
|
+
return Promise.reject(error);
|
|
2160
|
+
});
|
|
2161
|
+
client = resty.create(options);
|
|
2162
|
+
_context.prev = 2;
|
|
2163
|
+
_context.next = 3;
|
|
2164
|
+
return client.request(botUrl, options);
|
|
2165
|
+
case 3:
|
|
2166
|
+
return _context.abrupt("return", _context.sent);
|
|
2167
|
+
case 4:
|
|
2168
|
+
_context.prev = 4;
|
|
2169
|
+
_t = _context["catch"](2);
|
|
2170
|
+
if (!((_t === null || _t === void 0 ? void 0 : _t.code) === 11201 || (_t === null || _t === void 0 ? void 0 : _t.err_code) === 40012001)) {
|
|
2171
|
+
_context.next = 8;
|
|
2172
|
+
break;
|
|
2173
|
+
}
|
|
2174
|
+
console.log('检测到认证失败,尝试重试请求...');
|
|
2175
|
+
_context.prev = 5;
|
|
2176
|
+
// 由于addAuthorization现在是并发安全的,重试时会自动获取最新token
|
|
2177
|
+
retryClient = resty.create(options);
|
|
2178
|
+
_context.next = 6;
|
|
2179
|
+
return retryClient.request(botUrl, options);
|
|
2180
|
+
case 6:
|
|
2181
|
+
return _context.abrupt("return", _context.sent);
|
|
2182
|
+
case 7:
|
|
2183
|
+
_context.prev = 7;
|
|
2184
|
+
_t2 = _context["catch"](5);
|
|
2185
|
+
console.log('重试请求仍然失败:', _t2);
|
|
2186
|
+
throw _t2;
|
|
2187
|
+
case 8:
|
|
2188
|
+
throw _t;
|
|
2189
|
+
case 9:
|
|
2190
|
+
case "end":
|
|
2191
|
+
return _context.stop();
|
|
2192
|
+
}
|
|
2193
|
+
}, _callee, this, [[2, 4], [5, 7]]);
|
|
2194
|
+
}));
|
|
2195
|
+
function request(_x) {
|
|
2196
|
+
return _request.apply(this, arguments);
|
|
2197
|
+
}
|
|
2198
|
+
return request;
|
|
2199
|
+
}()
|
|
2006
2200
|
}], [{
|
|
2007
2201
|
key: "newClient",
|
|
2008
2202
|
value: function newClient(config) {
|