wxyyxc1992 преди 5 години
родител
ревизия
15398e4e63

+ 1
- 3
.gitignore Целия файл

@@ -7,6 +7,4 @@ node_modules
7 7
 # Project specific stuff
8 8
 .cache-loader
9 9
 @coverage
10
-*.log
11
-dist
12
-build
10
+*.log

+ 3
- 0
package.json Целия файл

@@ -6,6 +6,9 @@
6 6
     "type": "git",
7 7
     "url": "https://git.links123.net/Chevalier/chat-ts-sdk"
8 8
   },
9
+  "main": "./packages/cts-api/dist/cjs/index.js",
10
+  "module": "./packages/cts-api/dist/cjs/index.js",
11
+  "types": "./packages/cts-api/dist/types/index.d.ts",
9 12
   "license": "MIT",
10 13
   "keywords": [
11 14
     "react",

+ 0
- 14
packages/cts-adapter/types.d.ts Целия файл

@@ -1,14 +0,0 @@
1
-declare module '*.less' {
2
-  const styles: Record<string, string>;
3
-  export = styles;
4
-}
5
-
6
-declare module '*.css' {
7
-  const content: any;
8
-  export default content;
9
-}
10
-
11
-declare module '*.svg' {
12
-  const content: string;
13
-  export default content;
14
-}

+ 8
- 0
packages/cts-api/dist/cjs/WebSocketClient.js Целия файл

@@ -0,0 +1,8 @@
1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var WebSocketClient = (function () {
4
+    function WebSocketClient() {
5
+    }
6
+    return WebSocketClient;
7
+}());
8
+exports.WebSocketClient = WebSocketClient;

+ 283
- 0
packages/cts-api/dist/cjs/client.js Целия файл

@@ -0,0 +1,283 @@
1
+"use strict";
2
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+    return new (P || (P = Promise))(function (resolve, reject) {
4
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+    });
9
+};
10
+var __generator = (this && this.__generator) || function (thisArg, body) {
11
+    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+    function verb(n) { return function (v) { return step([n, v]); }; }
14
+    function step(op) {
15
+        if (f) throw new TypeError("Generator is already executing.");
16
+        while (_) try {
17
+            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+            if (y = 0, t) op = [op[0] & 2, t.value];
19
+            switch (op[0]) {
20
+                case 0: case 1: t = op; break;
21
+                case 4: _.label++; return { value: op[1], done: false };
22
+                case 5: _.label++; y = op[1]; op = [0]; continue;
23
+                case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+                default:
25
+                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+                    if (t[2]) _.ops.pop();
30
+                    _.trys.pop(); continue;
31
+            }
32
+            op = body.call(thisArg, _);
33
+        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+    }
36
+};
37
+Object.defineProperty(exports, "__esModule", { value: true });
38
+var packet_1 = require("./packet");
39
+var utils_1 = require("./utils");
40
+var error_1 = require("./error");
41
+var clientError = 400;
42
+var Client = (function () {
43
+    function Client(url, readyStateCallback) {
44
+        this.listeners = new Map();
45
+        this.requestHeader = '';
46
+        this.requestHeader = '';
47
+        this._maxPayload = 1024 * 1024;
48
+        this.url = url;
49
+        this.reconnectTimes = 0;
50
+        this.readyStateCallback = readyStateCallback;
51
+        this._enableLogger = false;
52
+        this.socket = this.connect();
53
+    }
54
+    Object.defineProperty(Client.prototype, "maxPayload", {
55
+        get: function () {
56
+            return this._maxPayload;
57
+        },
58
+        set: function (maxPayload) {
59
+            this._maxPayload = maxPayload;
60
+        },
61
+        enumerable: true,
62
+        configurable: true
63
+    });
64
+    Object.defineProperty(Client.prototype, "enableLogger", {
65
+        get: function () {
66
+            return this._enableLogger;
67
+        },
68
+        set: function (enableLogger) {
69
+            this._enableLogger = enableLogger;
70
+        },
71
+        enumerable: true,
72
+        configurable: true
73
+    });
74
+    Client.prototype.ping = function (param) {
75
+        return __awaiter(this, void 0, void 0, function () {
76
+            var _this = this;
77
+            return __generator(this, function (_a) {
78
+                return [2, new Promise(function (resolve, reject) {
79
+                        if (_this.socket.readyState !== _this.socket.OPEN) {
80
+                            if (_this._enableLogger) {
81
+                                console.log('[ping]: connection refuse');
82
+                            }
83
+                            reject(new error_1.WebsocketError(clientError, 'connection refuse'));
84
+                        }
85
+                        var heartbeatOperator = 0;
86
+                        _this.listeners.set(heartbeatOperator, function (data) {
87
+                            var code = _this.getResponseProperty('code');
88
+                            if (code !== '') {
89
+                                var message = _this.getResponseProperty('message');
90
+                                reject(new error_1.WebsocketError(Number(code), message));
91
+                            }
92
+                            else {
93
+                                resolve(data);
94
+                            }
95
+                        });
96
+                        var p = new packet_1.Packet();
97
+                        _this.send(p.pack(heartbeatOperator, 0, _this.requestHeader, JSON.stringify(param)));
98
+                        if (_this._enableLogger) {
99
+                            console.info('[send data packet]', heartbeatOperator, 0, _this.requestHeader, param);
100
+                        }
101
+                    })];
102
+            });
103
+        });
104
+    };
105
+    Client.prototype.request = function (operator, param) {
106
+        return __awaiter(this, void 0, void 0, function () {
107
+            return __generator(this, function (_a) {
108
+                switch (_a.label) {
109
+                    case 0: return [4, this.asyncSend(operator, param)];
110
+                    case 1: return [2, _a.sent()];
111
+                }
112
+            });
113
+        });
114
+    };
115
+    Client.prototype.addMessageListener = function (operator, listener) {
116
+        this.listeners.set(utils_1.Utils.crc32(operator), listener);
117
+    };
118
+    Client.prototype.removeMessageListener = function (operator) {
119
+        delete this.listeners[utils_1.Utils.crc32(operator)];
120
+    };
121
+    Object.defineProperty(Client.prototype, "readyState", {
122
+        get: function () {
123
+            return this.socket.readyState;
124
+        },
125
+        enumerable: true,
126
+        configurable: true
127
+    });
128
+    Client.prototype.setRequestProperty = function (key, value) {
129
+        var v = this.getRequestProperty(key);
130
+        this.requestHeader = this.requestHeader.replace(key + '=' + v + ';', '');
131
+        this.requestHeader = this.requestHeader + key + '=' + value + ';';
132
+    };
133
+    Client.prototype.getRequestProperty = function (key) {
134
+        if (this.requestHeader !== undefined) {
135
+            var values = this.requestHeader.split(';');
136
+            for (var index in values) {
137
+                var kv = values[index].split('=');
138
+                if (kv[0] === key) {
139
+                    return kv[1];
140
+                }
141
+            }
142
+        }
143
+        return '';
144
+    };
145
+    Client.prototype.setResponseProperty = function (key, value) {
146
+        var v = this.getResponseProperty(key);
147
+        this.responseHeader = this.responseHeader.replace(key + '=' + v + ';', '');
148
+        this.responseHeader = this.responseHeader + key + '=' + value + ';';
149
+    };
150
+    Client.prototype.getResponseProperty = function (key) {
151
+        if (this.responseHeader !== undefined) {
152
+            var values = this.responseHeader.split(';');
153
+            for (var index in values) {
154
+                var kv = values[index].split('=');
155
+                if (kv[0] === key) {
156
+                    return kv[1];
157
+                }
158
+            }
159
+        }
160
+        return '';
161
+    };
162
+    Client.prototype.connect = function () {
163
+        var _this = this;
164
+        var readyStateCallback = this.readyStateCallback;
165
+        var ws = new WebSocket(this.url);
166
+        ws.binaryType = 'blob';
167
+        ws.onopen = function (ev) {
168
+            if (_this._enableLogger) {
169
+                console.info('[websocket] open connection');
170
+            }
171
+            _this.reconnectTimes = 0;
172
+            readyStateCallback.onOpen(ev);
173
+        };
174
+        ws.onclose = function (ev) {
175
+            if (_this._enableLogger) {
176
+                console.info('[websocket] close connection');
177
+            }
178
+            _this.reconnect();
179
+            readyStateCallback.onClose(ev);
180
+        };
181
+        ws.onerror = function (ev) {
182
+            if (_this._enableLogger) {
183
+                console.info('[websocket] error');
184
+            }
185
+            _this.reconnect();
186
+            readyStateCallback.onError(ev);
187
+        };
188
+        ws.onmessage = function (ev) {
189
+            if (ev.data instanceof Blob) {
190
+                var reader_1 = new FileReader();
191
+                reader_1.readAsArrayBuffer(ev.data);
192
+                reader_1.onload = function () {
193
+                    try {
194
+                        var packet = new packet_1.Packet().unPack(reader_1.result);
195
+                        var packetLength = packet.headerLength + packet.bodyLength + 20;
196
+                        if (packetLength > _this._maxPayload) {
197
+                            throw new Error('the packet is big than ' + _this._maxPayload);
198
+                        }
199
+                        var operator = Number(packet.operator) + Number(packet.sequence);
200
+                        if (_this.listeners.has(operator)) {
201
+                            if (packet.body === '') {
202
+                                packet.body = '{}';
203
+                            }
204
+                            _this.responseHeader = packet.header;
205
+                            _this.listeners.get(operator)(JSON.parse(packet.body));
206
+                        }
207
+                        if (_this._enableLogger) {
208
+                            if (operator !== 0 && packet.body !== 'null') {
209
+                                console.info('receive data packet', packet.body);
210
+                            }
211
+                        }
212
+                    }
213
+                    catch (e) {
214
+                        throw new Error(e);
215
+                    }
216
+                };
217
+            }
218
+            else {
219
+                throw new Error('unsupported data format');
220
+            }
221
+        };
222
+        return ws;
223
+    };
224
+    Client.prototype.reconnect = function () {
225
+        var _this = this;
226
+        if (!this.reconnectLock) {
227
+            this.reconnectLock = true;
228
+            if (this._enableLogger) {
229
+                console.info('websocket reconnect in ' + this.reconnectTimes + 's');
230
+            }
231
+            setTimeout(function () {
232
+                _this.reconnectTimes++;
233
+                _this.socket = _this.connect();
234
+                _this.reconnectLock = false;
235
+            }, this.reconnectTimes * 1000);
236
+        }
237
+    };
238
+    Client.prototype.send = function (data) {
239
+        if (this.socket.readyState !== this.socket.OPEN) {
240
+            if (this._enableLogger) {
241
+                console.error('[send] WebSocket is already in CLOSING or CLOSED state.');
242
+            }
243
+            return;
244
+        }
245
+        try {
246
+            this.socket.send(data);
247
+        }
248
+        catch (e) {
249
+            throw new Error('send data error' + e);
250
+        }
251
+    };
252
+    Client.prototype.asyncSend = function (operator, param) {
253
+        var _this = this;
254
+        return new Promise(function (resolve, reject) {
255
+            if (_this.socket.readyState !== _this.socket.OPEN) {
256
+                if (_this._enableLogger) {
257
+                    console.log('[ping]: connection refuse');
258
+                }
259
+                reject(new error_1.WebsocketError(clientError, 'asyncSend: connection refuse'));
260
+            }
261
+            var sequence = new Date().getTime();
262
+            var listener = utils_1.Utils.crc32(operator) + sequence;
263
+            _this.listeners.set(listener, function (data) {
264
+                var code = _this.getResponseProperty('code');
265
+                if (code !== '') {
266
+                    var message = _this.getResponseProperty('message');
267
+                    reject(new error_1.WebsocketError(Number(code), message));
268
+                }
269
+                else {
270
+                    resolve(data);
271
+                }
272
+                delete _this.listeners[listener];
273
+            });
274
+            var p = new packet_1.Packet();
275
+            _this.send(p.pack(utils_1.Utils.crc32(operator), sequence, _this.requestHeader, JSON.stringify(param)));
276
+            if (_this._enableLogger) {
277
+                console.info('[send data packet]', operator, sequence, _this.requestHeader, param);
278
+            }
279
+        });
280
+    };
281
+    return Client;
282
+}());
283
+exports.Client = Client;

+ 1
- 0
packages/cts-api/dist/cjs/config.js Целия файл

@@ -0,0 +1 @@
1
+var PING_INTERVAL = 50 * 1000;

+ 24
- 0
packages/cts-api/dist/cjs/error.js Целия файл

@@ -0,0 +1,24 @@
1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var WebsocketError = (function () {
4
+    function WebsocketError(code, msg) {
5
+        this._code = code;
6
+        this._msg = msg;
7
+    }
8
+    Object.defineProperty(WebsocketError.prototype, "code", {
9
+        get: function () {
10
+            return this._code;
11
+        },
12
+        enumerable: true,
13
+        configurable: true
14
+    });
15
+    Object.defineProperty(WebsocketError.prototype, "msg", {
16
+        get: function () {
17
+            return this._msg;
18
+        },
19
+        enumerable: true,
20
+        configurable: true
21
+    });
22
+    return WebsocketError;
23
+}());
24
+exports.WebsocketError = WebsocketError;

+ 8
- 0
packages/cts-api/dist/cjs/index.js Целия файл

@@ -0,0 +1,8 @@
1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var WebSocketClient_1 = require("./WebSocketClient");
4
+exports.WebSocketClient = WebSocketClient_1.WebSocketClient;
5
+var error_1 = require("./error");
6
+exports.WebsocketError = error_1.WebsocketError;
7
+var client_1 = require("./client");
8
+exports.Client = client_1.Client;

+ 74
- 0
packages/cts-api/dist/cjs/meta.js Целия файл

@@ -0,0 +1,74 @@
1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+function getMetaData() {
4
+    var nAgt = navigator.userAgent;
5
+    var browserName = navigator.appName;
6
+    var fullVersion = "" + parseFloat(navigator.appVersion);
7
+    var majorVersion = parseInt(navigator.appVersion, 10);
8
+    var nameOffset;
9
+    var verOffset;
10
+    var ix;
11
+    if ((verOffset = nAgt.indexOf('Opera')) !== -1) {
12
+        browserName = 'Opera';
13
+        fullVersion = nAgt.substring(verOffset + 6);
14
+        if ((verOffset = nAgt.indexOf('Version')) !== -1)
15
+            fullVersion = nAgt.substring(verOffset + 8);
16
+    }
17
+    else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) {
18
+        browserName = 'Microsoft Internet Explorer';
19
+        fullVersion = nAgt.substring(verOffset + 5);
20
+    }
21
+    else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) {
22
+        browserName = 'Chrome';
23
+        fullVersion = nAgt.substring(verOffset + 7);
24
+    }
25
+    else if ((verOffset = nAgt.indexOf('Safari')) !== -1) {
26
+        browserName = 'Safari';
27
+        fullVersion = nAgt.substring(verOffset + 7);
28
+        if ((verOffset = nAgt.indexOf('Version')) !== -1)
29
+            fullVersion = nAgt.substring(verOffset + 8);
30
+    }
31
+    else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) {
32
+        browserName = 'Firefox';
33
+        fullVersion = nAgt.substring(verOffset + 8);
34
+    }
35
+    else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) {
36
+        browserName = nAgt.substring(nameOffset, verOffset);
37
+        fullVersion = nAgt.substring(verOffset + 1);
38
+        if (browserName.toLowerCase() === browserName.toUpperCase()) {
39
+            browserName = navigator.appName;
40
+        }
41
+    }
42
+    if ((ix = fullVersion.indexOf(';')) !== -1)
43
+        fullVersion = fullVersion.substring(0, ix);
44
+    if ((ix = fullVersion.indexOf(' ')) !== -1)
45
+        fullVersion = fullVersion.substring(0, ix);
46
+    majorVersion = parseInt("" + fullVersion, 10);
47
+    if (isNaN(majorVersion)) {
48
+        fullVersion = "" + parseFloat(navigator.appVersion);
49
+        majorVersion = parseInt(navigator.appVersion, 10);
50
+    }
51
+    var OSName = 'Unknown OS';
52
+    if (navigator.appVersion.indexOf('Win') !== -1)
53
+        OSName = 'Windows';
54
+    if (navigator.appVersion.indexOf('Mac') !== -1)
55
+        OSName = 'MacOS';
56
+    if (navigator.appVersion.indexOf('X11') !== -1)
57
+        OSName = 'UNIX';
58
+    if (navigator.appVersion.indexOf('Linux') !== -1)
59
+        OSName = 'Linux';
60
+    var isMobile = false;
61
+    if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent) ||
62
+        /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0, 4))) {
63
+        isMobile = true;
64
+    }
65
+    return {
66
+        device: isMobile ? 'mobile' : 'pc',
67
+        os: OSName,
68
+        os_version: '',
69
+        app: 'WebLiveClient',
70
+        app_version: fullVersion,
71
+        tag: {}
72
+    };
73
+}
74
+exports.getMetaData = getMetaData;

+ 46
- 0
packages/cts-api/dist/cjs/packet.js Целия файл

@@ -0,0 +1,46 @@
1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var utils_1 = require("./utils");
4
+var node_int64_1 = require("node-int64");
5
+var Packet = (function () {
6
+    function Packet() {
7
+        this.key = 'b8ca9aa66def05ff3f24919274bb4a66';
8
+    }
9
+    Packet.prototype.pack = function (operator, sequence, header, body) {
10
+        header = utils_1.Utils.encrypt(header, this.key, this.key);
11
+        body = utils_1.Utils.encrypt(body, this.key, this.key);
12
+        var headerLength = header.length;
13
+        var bodyLength = body.length;
14
+        var buf = new ArrayBuffer(20 + headerLength + bodyLength);
15
+        var dataView = new DataView(buf);
16
+        var nsBuf = new node_int64_1.default(sequence).toBuffer();
17
+        dataView.setUint32(0, operator);
18
+        dataView.setUint32(12, headerLength);
19
+        dataView.setUint32(16, bodyLength);
20
+        var bufView = new Uint8Array(buf);
21
+        for (var i = 0; i < 8; i++) {
22
+            bufView[4 + i] = nsBuf[i];
23
+        }
24
+        for (var i_1 = 0; i_1 < headerLength; i_1++) {
25
+            bufView[20 + i_1] = header.charCodeAt(i_1);
26
+        }
27
+        for (var i_2 = 0; i_2 < bodyLength; i_2++) {
28
+            bufView[20 + headerLength + i_2] = body.charCodeAt(i_2);
29
+        }
30
+        return buf;
31
+    };
32
+    Packet.prototype.unPack = function (data) {
33
+        var dataView = new DataView(data);
34
+        this.operator = dataView.getUint32(0, false);
35
+        this.sequence = new node_int64_1.default(new Uint8Array(dataView.buffer.slice(4, 12))).toNumber();
36
+        this.headerLength = dataView.getUint32(12, false);
37
+        this.bodyLength = dataView.getUint32(16, false);
38
+        var header = utils_1.Utils.ab2str(dataView.buffer.slice(20, 20 + this.headerLength));
39
+        var body = utils_1.Utils.ab2str(dataView.buffer.slice(20 + this.headerLength));
40
+        this.header = utils_1.Utils.decrypt(header, this.key, this.key);
41
+        this.body = utils_1.Utils.decrypt(body, this.key, this.key);
42
+        return this;
43
+    };
44
+    return Packet;
45
+}());
46
+exports.Packet = Packet;

+ 2
- 0
packages/cts-api/dist/cjs/types/callback.js Целия файл

@@ -0,0 +1,2 @@
1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });

+ 113
- 0
packages/cts-api/dist/cjs/utils.js Целия файл

@@ -0,0 +1,113 @@
1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var crypto_js_1 = require("crypto-js");
4
+var Utils = (function () {
5
+    function Utils() {
6
+    }
7
+    Utils.crc32 = function (str) {
8
+        var crcTable = window.crcTable || (window.crcTable = Utils.makeCRCTable());
9
+        var crc = 0 ^ -1;
10
+        for (var i = 0; i < str.length; i++) {
11
+            crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xff];
12
+        }
13
+        return (crc ^ -1) >>> 0;
14
+    };
15
+    Utils.ab2str = function (buf) {
16
+        if (buf && buf.byteLength < 1024) {
17
+            return String.fromCharCode.apply(null, new Uint8Array(buf));
18
+        }
19
+        var bufView = new Uint8Array(buf);
20
+        var len = bufView.length;
21
+        var byteStr = new Array(len);
22
+        for (var i = 0; i < len; i++) {
23
+            byteStr[i] = String.fromCharCode.call(null, bufView[i]);
24
+        }
25
+        return byteStr.join('');
26
+    };
27
+    Utils.str2ab = function (str) {
28
+        var buf = new ArrayBuffer(str.length);
29
+        var bufView = new Uint8Array(buf);
30
+        for (var i = 0, strLen = str.length; i < strLen; i++) {
31
+            bufView[i] = str.charCodeAt(i);
32
+        }
33
+        return buf;
34
+    };
35
+    Utils.decrypt = function (data, key, iv) {
36
+        var binData = Utils.stringToBin(data);
37
+        var base64Data = Utils.binToBase64(binData);
38
+        var bytes = crypto_js_1.AES.decrypt(base64Data, crypto_js_1.enc.Latin1.parse(key), {
39
+            iv: crypto_js_1.enc.Latin1.parse(iv),
40
+            mode: crypto_js_1.mode.CBC,
41
+            padding: crypto_js_1.pad.Pkcs7,
42
+        });
43
+        return bytes.toString(crypto_js_1.enc.Utf8);
44
+    };
45
+    Utils.encrypt = function (data, key, iv) {
46
+        var result = crypto_js_1.AES.encrypt(data, crypto_js_1.enc.Latin1.parse(key), {
47
+            iv: crypto_js_1.enc.Latin1.parse(iv),
48
+            mode: crypto_js_1.mode.CBC,
49
+            padding: crypto_js_1.pad.Pkcs7,
50
+        });
51
+        return Utils.binToString(Utils.base64ToBin(result.toString()));
52
+    };
53
+    Utils.binToBase64 = function (bitString) {
54
+        var tail = bitString.length % 6;
55
+        var bitStringTemp1 = bitString.substr(0, bitString.length - tail);
56
+        var result = '';
57
+        var bitStringTemp2 = bitString.substr(bitString.length - tail, tail);
58
+        for (var i = 0; i < bitStringTemp1.length; i += 6) {
59
+            var index = parseInt(bitStringTemp1.substr(i, 6), 2);
60
+            result += Utils.code[index];
61
+        }
62
+        bitStringTemp2 += new Array(7 - tail).join('0');
63
+        if (tail) {
64
+            result += Utils.code[parseInt(bitStringTemp2, 2)];
65
+            result += new Array((6 - tail) / 2 + 1).join('=');
66
+        }
67
+        return result;
68
+    };
69
+    Utils.base64ToBin = function (str) {
70
+        var bitString = '';
71
+        var tail = 0;
72
+        for (var i = 0; i < str.length; i++) {
73
+            if (str[i] !== '=') {
74
+                var decode = this.code.indexOf(str[i]).toString(2);
75
+                bitString += new Array(7 - decode.length).join('0') + decode;
76
+            }
77
+            else {
78
+                tail++;
79
+            }
80
+        }
81
+        return bitString.substr(0, bitString.length - tail * 2);
82
+    };
83
+    Utils.stringToBin = function (str) {
84
+        var result = '';
85
+        for (var i = 0; i < str.length; i++) {
86
+            var charCode = str.charCodeAt(i).toString(2);
87
+            result += new Array(9 - charCode.length).join('0') + charCode;
88
+        }
89
+        return result;
90
+    };
91
+    Utils.binToString = function (bin) {
92
+        var result = '';
93
+        for (var i = 0; i < bin.length; i += 8) {
94
+            result += String.fromCharCode(parseInt(bin.substr(i, 8), 2));
95
+        }
96
+        return result;
97
+    };
98
+    Utils.makeCRCTable = function () {
99
+        var c;
100
+        var crcTable = [];
101
+        for (var n = 0; n < 256; n++) {
102
+            c = n;
103
+            for (var k = 0; k < 8; k++) {
104
+                c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
105
+            }
106
+            crcTable[n] = c;
107
+        }
108
+        return crcTable;
109
+    };
110
+    Utils.code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
111
+    return Utils;
112
+}());
113
+exports.Utils = Utils;

+ 25
- 0
packages/cts-api/dist/index.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 2
- 0
packages/cts-api/dist/types/WebSocketClient.d.ts Целия файл

@@ -0,0 +1,2 @@
1
+export declare class WebSocketClient {
2
+}

+ 30
- 0
packages/cts-api/dist/types/client.d.ts Целия файл

@@ -0,0 +1,30 @@
1
+import { ReadyStateCallback } from './types/callback';
2
+declare class Client {
3
+    private _maxPayload;
4
+    private _enableLogger;
5
+    private listeners;
6
+    private requestHeader;
7
+    private responseHeader;
8
+    private url;
9
+    private reconnectTimes;
10
+    private reconnectLock;
11
+    private socket;
12
+    private readyStateCallback;
13
+    constructor(url: string, readyStateCallback: ReadyStateCallback);
14
+    maxPayload: number;
15
+    enableLogger: boolean;
16
+    ping(param: object): Promise<string>;
17
+    request(operator: string, param: object): Promise<string>;
18
+    addMessageListener(operator: string, listener: (data: string) => void): void;
19
+    removeMessageListener(operator: string): void;
20
+    readonly readyState: number;
21
+    setRequestProperty(key: string, value: string): void;
22
+    getRequestProperty(key: string): string;
23
+    setResponseProperty(key: string, value: string): void;
24
+    getResponseProperty(key: string): string;
25
+    private connect;
26
+    private reconnect;
27
+    private send;
28
+    private asyncSend;
29
+}
30
+export { Client };

+ 1
- 0
packages/cts-api/dist/types/config.d.ts Целия файл

@@ -0,0 +1 @@
1
+declare const PING_INTERVAL: number;

+ 7
- 0
packages/cts-api/dist/types/error.d.ts Целия файл

@@ -0,0 +1,7 @@
1
+export declare class WebsocketError {
2
+    private _code;
3
+    private _msg;
4
+    constructor(code: number, msg: string);
5
+    readonly code: number;
6
+    readonly msg: string;
7
+}

+ 3
- 0
packages/cts-api/dist/types/index.d.ts Целия файл

@@ -0,0 +1,3 @@
1
+export { WebSocketClient } from './WebSocketClient';
2
+export { WebsocketError } from './error';
3
+export { Client } from './client';

+ 8
- 0
packages/cts-api/dist/types/meta.d.ts Целия файл

@@ -0,0 +1,8 @@
1
+export declare function getMetaData(): {
2
+    device: string;
3
+    os: string;
4
+    os_version: string;
5
+    app: string;
6
+    app_version: string;
7
+    tag: {};
8
+};

+ 11
- 0
packages/cts-api/dist/types/packet.d.ts Целия файл

@@ -0,0 +1,11 @@
1
+export declare class Packet {
2
+    private key;
3
+    operator: number;
4
+    sequence: number;
5
+    headerLength: number;
6
+    bodyLength: number;
7
+    header: string;
8
+    body: string;
9
+    pack(operator: number, sequence: number, header: string, body: string): ArrayBuffer;
10
+    unPack(data: ArrayBuffer | SharedArrayBuffer): Packet;
11
+}

+ 12
- 0
packages/cts-api/dist/types/types/callback.d.ts Целия файл

@@ -0,0 +1,12 @@
1
+interface ReadyStateCallback {
2
+    onOpen(ev: Event): void;
3
+    onError(ev: Event): void;
4
+    onClose(ev: Event): void;
5
+}
6
+interface RequestCallback {
7
+    onStart(): void;
8
+    onSuccess(data: string): void;
9
+    onError(code: number, message: string): void;
10
+    onEnd(): void;
11
+}
12
+export { ReadyStateCallback, RequestCallback };

+ 19
- 0
packages/cts-api/dist/types/utils.d.ts Целия файл

@@ -0,0 +1,19 @@
1
+declare global {
2
+    interface Window {
3
+        crcTable: number[];
4
+    }
5
+}
6
+declare class Utils {
7
+    private static code;
8
+    static crc32(str: string): number;
9
+    static ab2str(buf: ArrayBuffer): string;
10
+    static str2ab(str: string): ArrayBuffer;
11
+    static decrypt(data: string, key: string, iv: string): string;
12
+    static encrypt(data: string, key: string, iv: string): string;
13
+    static binToBase64(bitString: string): string;
14
+    static base64ToBin(str: string): string;
15
+    static stringToBin(str: string): string;
16
+    static binToString(bin: string): string;
17
+    private static makeCRCTable;
18
+}
19
+export { Utils };

+ 153
- 1
packages/cts-api/src/WebSocketClient.ts Целия файл

@@ -1 +1,153 @@
1
-export class WebSocketClient {}
1
+import { Client, getClient, WebSocketResp } from './client';
2
+import { getMetaData } from './meta';
3
+
4
+export interface WebSocketClientStatus {
5
+  created: boolean;
6
+  connected: boolean;
7
+  login: boolean;
8
+}
9
+
10
+export type ListenerCallback = (data: WebSocketResp) => void;
11
+
12
+const meta = getMetaData();
13
+
14
+export class WebSocketClient {
15
+  client: Client;
16
+  interval: NodeJS.Timeout;
17
+
18
+  wsUrl: string;
19
+  token: string;
20
+  sid: string;
21
+  chatToken: object;
22
+
23
+  status: WebSocketClientStatus = {
24
+    created: false,
25
+    connected: false,
26
+    login: false
27
+  };
28
+
29
+  /** 默认构造函数 */
30
+  constructor(wsUrl: string, token: string, sid: string, chatToken: object) {
31
+    this.wsUrl = wsUrl;
32
+    this.token = token;
33
+    this.chatToken = chatToken;
34
+    this.sid = sid;
35
+  }
36
+
37
+  async init() {
38
+    return this.create();
39
+  }
40
+
41
+  getStatus() {
42
+    return this.status;
43
+  }
44
+
45
+  async create() {
46
+    const url = this.wsUrl;
47
+
48
+    return new Promise((resolve, reject) => {
49
+      if (!url) {
50
+        throw new Error('websocket url is required.');
51
+      }
52
+      this.client = getClient(url, {
53
+        onOpen: async () => {
54
+          try {
55
+            this.ping();
56
+            this.interval = setInterval(() => {
57
+              this.ping();
58
+            }, PING_INTERVAL);
59
+          } catch (err) {
60
+            this.client.reconnect();
61
+          }
62
+
63
+          const data = await this.connect();
64
+          await this.authentication();
65
+          resolve(data.value);
66
+        },
67
+        onError: err => {
68
+          resolve(false);
69
+        },
70
+        onClose: CloseEvent => {
71
+          clearInterval(this.interval);
72
+        }
73
+      });
74
+    });
75
+  }
76
+
77
+  on(url: string, callback: (data: WebSocketResp) => void) {
78
+    if (!url) {
79
+      throw new Error('url is required.');
80
+    }
81
+
82
+    this.client.addMessageListener(url, callback);
83
+  }
84
+
85
+  off(url: string) {
86
+    this.client.removeMessageListener(url);
87
+  }
88
+
89
+  async request(url: string, data: object) {
90
+    let error;
91
+
92
+    if (this.client.readyState !== 1) {
93
+      error = 'websocket connection not ready!';
94
+      throw new Error(error);
95
+    }
96
+
97
+    try {
98
+      return this.client.asyncSend(url, data);
99
+    } catch (e) {
100
+      console.error(e);
101
+      throw e;
102
+    }
103
+  }
104
+
105
+  async connect() {
106
+    const { sid } = this;
107
+    if (sid) {
108
+      this.client.setRequestProperty('sid', sid);
109
+    }
110
+
111
+    const data = await this.request('/v1/session/start', {
112
+      ...this.chatToken,
113
+      ...meta
114
+    });
115
+
116
+    if (data && data.value) {
117
+      const id = data.value as string;
118
+      this.sid = id;
119
+      this.client.setRequestProperty('sid', id);
120
+    }
121
+    return data || true;
122
+  }
123
+
124
+  ping() {
125
+    return this.client.ping({});
126
+  }
127
+
128
+  async authentication() {
129
+    const tk = this.token;
130
+    const data = this.request('/v1/session/bind/uid/by/token', { token: tk });
131
+    return data || true;
132
+  }
133
+
134
+  onMessage(callback: ListenerCallback) {
135
+    this.on('/v1/message/listener', callback);
136
+  }
137
+
138
+  sendMessage(data: object) {
139
+    return this.request('/v1/send/message', data);
140
+  }
141
+
142
+  markServiced(data: object) {
143
+    return this.request('/v1/mark/message/serviced', data);
144
+  }
145
+
146
+  /**
147
+   *
148
+   * @param {*} data contact_id chat_type start_time limit
149
+   */
150
+  getHistoryMessage(data: object) {
151
+    return this.request('/v1/history/message', data);
152
+  }
153
+}

+ 29
- 13
packages/cts-api/src/client.ts Целия файл

@@ -5,13 +5,17 @@ import { WebsocketError } from './error';
5 5
 
6 6
 const clientError = 400;
7 7
 
8
+export interface WebSocketResp {
9
+  value: object | string;
10
+}
11
+
8 12
 /**
9 13
  * 初始化链接以及收发数据
10 14
  */
11 15
 class Client {
12 16
   private _maxPayload: number;
13 17
   private _enableLogger: boolean;
14
-  private listeners: Map<number, (data: string) => void>;
18
+  private listeners: Map<number, (data: WebSocketResp) => void>;
15 19
   private requestHeader: string;
16 20
   private responseHeader: string;
17 21
   private url: string;
@@ -26,7 +30,7 @@ class Client {
26 30
    * @param readyStateCallback 链接状态回调,可以处理onOpen、onClose、onError
27 31
    */
28 32
   public constructor(url: string, readyStateCallback: ReadyStateCallback) {
29
-    this.listeners = new Map<number, (data: string) => void>();
33
+    this.listeners = new Map<number, (data: WebSocketResp) => void>();
30 34
     this.requestHeader = '';
31 35
     this.requestHeader = '';
32 36
     this._maxPayload = 1024 * 1024;
@@ -70,9 +74,9 @@ class Client {
70 74
    * 发送ping请求,来保持长连接
71 75
    * @param param 请求参数,比如{"hello":"world"}
72 76
    */
73
-  public async ping(param: object): Promise<string> {
77
+  public async ping(param: object): Promise<WebSocketResp> {
74 78
     return new Promise(
75
-      (resolve: (data: string) => void, reject: (err: WebsocketError) => void): void => {
79
+      (resolve: (data: WebSocketResp) => void, reject: (err: WebsocketError) => void): void => {
76 80
         if (this.socket.readyState !== this.socket.OPEN) {
77 81
           if (this._enableLogger) {
78 82
             console.log('[ping]: connection refuse');
@@ -85,7 +89,7 @@ class Client {
85 89
 
86 90
         this.listeners.set(
87 91
           heartbeatOperator,
88
-          (data: string): void => {
92
+          (data: WebSocketResp): void => {
89 93
             const code = this.getResponseProperty('code');
90 94
             if (code !== '') {
91 95
               const message = this.getResponseProperty('message');
@@ -112,7 +116,7 @@ class Client {
112 116
    * @param param 请求参数,比如{"hello":"world"}
113 117
    * @param callback 请求状态回调处理
114 118
    */
115
-  public async request(operator: string, param: object): Promise<string> {
119
+  public async request(operator: string, param: object): Promise<WebSocketResp> {
116 120
     return await this.asyncSend(operator, param);
117 121
   }
118 122
 
@@ -122,7 +126,7 @@ class Client {
122 126
    * @param operator 消息监听地址
123 127
    * @param listener 定义如何处理从服务端返回的消息
124 128
    */
125
-  public addMessageListener(operator: string, listener: (data: string) => void): void {
129
+  public addMessageListener(operator: string, listener: (data: WebSocketResp) => void): void {
126 130
     this.listeners.set(Utils.crc32(operator), listener);
127 131
   }
128 132
 
@@ -261,7 +265,9 @@ class Client {
261 265
 
262 266
               this.responseHeader = packet.header;
263 267
 
264
-              (this.listeners.get(operator) as (data: string) => void)(JSON.parse(packet.body));
268
+              (this.listeners.get(operator) as (data: WebSocketResp) => void)(
269
+                JSON.parse(packet.body)
270
+              );
265 271
             }
266 272
 
267 273
             if (this._enableLogger) {
@@ -284,7 +290,7 @@ class Client {
284 290
   /**
285 291
    * 断线重连
286 292
    */
287
-  private reconnect(): void {
293
+  reconnect(): void {
288 294
     if (!this.reconnectLock) {
289 295
       this.reconnectLock = true;
290 296
       if (this._enableLogger) {
@@ -326,9 +332,9 @@ class Client {
326 332
    * @param param 请求参数,比如{"hello":"world"}
327 333
    * @param callback 请求状态回调处理
328 334
    */
329
-  private asyncSend(operator: string, param: object): Promise<string> {
335
+  asyncSend(operator: string, param: object): Promise<WebSocketResp> {
330 336
     return new Promise(
331
-      (resolve: (data: string) => void, reject: (err: WebsocketError) => void): void => {
337
+      (resolve: (data: WebSocketResp) => void, reject: (err: WebsocketError) => void): void => {
332 338
         if (this.socket.readyState !== this.socket.OPEN) {
333 339
           if (this._enableLogger) {
334 340
             console.log('[ping]: connection refuse');
@@ -341,7 +347,7 @@ class Client {
341 347
         const listener = Utils.crc32(operator) + sequence;
342 348
         this.listeners.set(
343 349
           listener,
344
-          (data: string): void => {
350
+          (data: WebSocketResp): void => {
345 351
             const code = this.getResponseProperty('code');
346 352
             if (code !== '') {
347 353
               const message = this.getResponseProperty('message');
@@ -367,4 +373,14 @@ class Client {
367 373
   }
368 374
 }
369 375
 
370
-export { Client };
376
+let client: Client;
377
+
378
+function getClient(url: string, callback: ReadyStateCallback) {
379
+  if (!client) {
380
+    client = new Client(url, callback);
381
+  }
382
+
383
+  return client;
384
+}
385
+
386
+export { Client, getClient };