├── publish.sh ├── .gitignore ├── bin └── protoc ├── jest.config.js ├── src ├── packet.test.ts ├── proto.test.ts ├── login.ts ├── packet.ts ├── sdk.test.ts ├── proto │ └── common.ts └── sdk.ts ├── sdk ├── packet.test.js.map ├── proto.test.js ├── proto.test.js.map ├── login.js.map ├── packet.js.map ├── packet.test.js ├── packet.js ├── login.js ├── sdk.test.js.map ├── proto │ ├── common.js.map │ └── common.js ├── sdk.test.js └── sdk.js.map ├── proto ├── common.proto └── protocol.proto ├── package.json ├── README.md ├── index.ts ├── tsconfig.json └── LICENSE /publish.sh: -------------------------------------------------------------------------------- 1 | npm run build 2 | npm version patch 3 | npm publish -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .DS_Store 4 | .vscode 5 | index.js -------------------------------------------------------------------------------- /bin/protoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klintcheng/kim_web_sdk/HEAD/bin/protoc -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'jsdom', 5 | }; -------------------------------------------------------------------------------- /src/packet.test.ts: -------------------------------------------------------------------------------- 1 | import { LoginReq } from "./proto/protocol" 2 | import { Command, LogicPkt, MagicLogicPktInt, print } from "./packet" 3 | import log from 'loglevel-es'; 4 | 5 | log.setLevel("debug") 6 | 7 | test('logicpkt', async () => { 8 | const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTYyOTA5MzU0OX0.P_yk1KMB5v9riUy0yW4eOTgC0k0qeB6XRjih4dL1xGk" 9 | let body = LoginReq.encode(LoginReq.fromJSON({ 10 | token: token, 11 | })).finish() 12 | let loginReq = LogicPkt.build(Command.SignIn, "", body) 13 | let buf = loginReq.bytes() 14 | // 验证前面的4字节等于MagicLogicPktInt 15 | expect(buf.readInt32BE()).toEqual(MagicLogicPktInt) 16 | // 反序列化并验证之后的值是否与前面定义相同 17 | let pkt = LogicPkt.from(buf.subarray(4)) 18 | expect(pkt.command).toEqual(Command.SignIn) 19 | expect(pkt.dest).toEqual("") 20 | expect(pkt.sequence).toBeGreaterThan(0) 21 | expect(pkt.payload.length).toEqual(body.length) 22 | // 验证payload消息体 23 | let req = LoginReq.decode(pkt.payload) 24 | expect(req.token).toEqual(token) 25 | }) 26 | -------------------------------------------------------------------------------- /sdk/packet.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"packet.test.js","sourceRoot":"","sources":["../src/packet.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA2C;AAC3C,mCAAqE;AACrE,4DAA8B;AAE9B,qBAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AAErB,IAAI,CAAC,UAAU,EAAE;;;QACP,KAAK,GAAG,8IAA8I,CAAA;QACxJ,IAAI,GAAG,mBAAQ,CAAC,MAAM,CAAC,mBAAQ,CAAC,QAAQ,CAAC;YACzC,KAAK,EAAE,KAAK;SACf,CAAC,CAAC,CAAC,MAAM,EAAE,CAAA;QACR,QAAQ,GAAG,iBAAQ,CAAC,KAAK,CAAC,gBAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,CAAA;QACnD,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAA;QAC1B,6BAA6B;QAC7B,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAgB,CAAC,CAAA;QAE/C,GAAG,GAAG,iBAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QACxC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,gBAAO,CAAC,MAAM,CAAC,CAAA;QAC3C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC5B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAE3C,GAAG,GAAG,mBAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QACtC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;;;KACnC,CAAC,CAAA"} -------------------------------------------------------------------------------- /proto/common.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package pkt; 3 | option go_package = "./pkt"; 4 | 5 | // status is a uint16 value 6 | enum Status { 7 | Success = 0; 8 | // client defined 9 | 10 | // client error 100-200 11 | NoDestination = 100; 12 | InvalidPacketBody = 101; 13 | InvalidCommand = 103; 14 | Unauthorized = 105 ; 15 | // server error 300-400 16 | SystemException = 300; 17 | NotImplemented = 301; 18 | //specific error 19 | SessionNotFound = 404; // session lost 20 | } 21 | 22 | enum MetaType { 23 | int = 0; 24 | string = 1; 25 | float = 2; 26 | } 27 | 28 | enum ContentType { 29 | Protobuf = 0; 30 | Json = 1; 31 | } 32 | 33 | enum Flag { 34 | Request = 0; 35 | Response = 1; 36 | Push = 2; 37 | } 38 | 39 | message Meta { 40 | string key = 1; 41 | string value = 2; 42 | MetaType type = 3; 43 | } 44 | 45 | message Header { 46 | string command = 1; 47 | // sender channel id 48 | string channelId = 2; 49 | uint32 sequence = 3; 50 | Flag flag = 4; 51 | Status status = 5; 52 | // destination is defined as a account,group or room 53 | string dest = 6; 54 | repeated Meta meta = 7; 55 | } 56 | 57 | message InnerHandshakeReq{ 58 | string ServiceId = 1; 59 | } 60 | 61 | message InnerHandshakeResponse{ 62 | uint32 Code = 1; 63 | string Error = 2; 64 | } -------------------------------------------------------------------------------- /src/proto.test.ts: -------------------------------------------------------------------------------- 1 | import { MessagePush } from "./proto/protocol" 2 | 3 | test("msg_decode", () => { 4 | //messageId:1628644843872655000 type:1 body:"hello world" extra:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTYyOTA5MzU0OX0.P_yk1KMB5v9riUy0yW4eOTgC0k0qeB6XRjih4dL1xGk" 5 | let arr = new Uint8Array([8, 152, 173, 180, 194, 180, 251, 134, 205, 22, 16, 1, 26, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 34, 140, 1, 101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 73, 85, 122, 73, 49, 78, 105, 73, 115, 73, 110, 82, 53, 99, 67, 73, 54, 73, 107, 112, 88, 86, 67, 74, 57, 46, 101, 121, 74, 104, 89, 50, 77, 105, 79, 105, 74, 48, 90, 88, 78, 48, 77, 83, 73, 115, 73, 109, 70, 119, 99, 67, 73, 54, 73, 109, 116, 112, 98, 83, 73, 115, 73, 109, 86, 52, 99, 67, 73, 54, 77, 84, 89, 121, 79, 84, 65, 53, 77, 122, 85, 48, 79, 88, 48, 46, 80, 95, 121, 107, 49, 75, 77, 66, 53, 118, 57, 114, 105, 85, 121, 48, 121, 87, 52, 101, 79, 84, 103, 67, 48, 107, 48, 113, 101, 66, 54, 88, 82, 106, 105, 104, 52, 100, 76, 49, 120, 71, 107]) 6 | let req = MessagePush.decode(arr) 7 | expect(req.messageId.toString()).toEqual("1628644843872655000") 8 | expect(req.body).toEqual("hello world") 9 | expect(req.extra).toEqual("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTYyOTA5MzU0OX0.P_yk1KMB5v9riUy0yW4eOTgC0k0qeB6XRjih4dL1xGk") 10 | expect(req.type).toEqual(1) 11 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kingim", 3 | "version": "1.1.0", 4 | "description": "king im sdk", 5 | "main": "index.ts", 6 | "scripts": { 7 | "test": "jest --verbose --force-exit ", 8 | "run": "ts-node index.ts", 9 | "build": "tsc" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/klintcheng/kim_web_sdk.git" 14 | }, 15 | "keywords": [ 16 | "im", 17 | "sdk" 18 | ], 19 | "author": "klintcheng", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/klintcheng/kim_web_sdk/issues" 23 | }, 24 | "homepage": "https://github.com/klintcheng/kim_web_sdk#readme", 25 | "dependencies": { 26 | "@types/websocket": "^1.0.2", 27 | "buffer": "^6.0.3", 28 | "localforage": "^1.10.0", 29 | "loglevel-es": "^1.7.1", 30 | "websocket": "^1.0.34" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.15.0", 34 | "@babel/preset-env": "^7.15.0", 35 | "@babel/preset-typescript": "^7.15.0", 36 | "@types/jest": "^27.0.1", 37 | "babel-jest": "^27.0.6", 38 | "jest": "^27.0.6", 39 | "jest-localstorage-mock": "^2.4.16", 40 | "mock-local-storage": "^1.1.17", 41 | "ts-jest": "^27.0.4", 42 | "ts-node": "^10.2.0", 43 | "ts-proto": "^1.82.5", 44 | "typescript": "^4.3.5" 45 | }, 46 | "jest": { 47 | "resetMocks": false, 48 | "setupFiles": [ 49 | "jest-localstorage-mock" 50 | ] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /sdk/proto.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var protocol_1 = require("./proto/protocol"); 4 | test("msg_decode", function () { 5 | //messageId:1628644843872655000 type:1 body:"hello world" extra:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTYyOTA5MzU0OX0.P_yk1KMB5v9riUy0yW4eOTgC0k0qeB6XRjih4dL1xGk" 6 | var arr = new Uint8Array([8, 152, 173, 180, 194, 180, 251, 134, 205, 22, 16, 1, 26, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 34, 140, 1, 101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 73, 85, 122, 73, 49, 78, 105, 73, 115, 73, 110, 82, 53, 99, 67, 73, 54, 73, 107, 112, 88, 86, 67, 74, 57, 46, 101, 121, 74, 104, 89, 50, 77, 105, 79, 105, 74, 48, 90, 88, 78, 48, 77, 83, 73, 115, 73, 109, 70, 119, 99, 67, 73, 54, 73, 109, 116, 112, 98, 83, 73, 115, 73, 109, 86, 52, 99, 67, 73, 54, 77, 84, 89, 121, 79, 84, 65, 53, 77, 122, 85, 48, 79, 88, 48, 46, 80, 95, 121, 107, 49, 75, 77, 66, 53, 118, 57, 114, 105, 85, 121, 48, 121, 87, 52, 101, 79, 84, 103, 67, 48, 107, 48, 113, 101, 66, 54, 88, 82, 106, 105, 104, 52, 100, 76, 49, 120, 71, 107]); 7 | var req = protocol_1.MessagePush.decode(arr); 8 | expect(req.messageId.toString()).toEqual("1628644843872655000"); 9 | expect(req.body).toEqual("hello world"); 10 | expect(req.extra).toEqual("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTYyOTA5MzU0OX0.P_yk1KMB5v9riUy0yW4eOTgC0k0qeB6XRjih4dL1xGk"); 11 | expect(req.type).toEqual(1); 12 | }); 13 | //# sourceMappingURL=proto.test.js.map -------------------------------------------------------------------------------- /sdk/proto.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"proto.test.js","sourceRoot":"","sources":["../src/proto.test.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kim_web_sdk 2 | 3 | 本项目是King IM CLoud的web版本SDK。 4 | 5 | ## 安装 6 | 7 | > npm i kingim 8 | 9 | ## Quick Start 10 | 11 | 我们再次回顾下客户端的生命周期状态图,**在SDK端所有逻辑都离不开这个状态图**: 12 | 13 | ![sdk_status.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ec4ee25597564dd2b17c14dd61e60ef2~tplv-k3u1fbpfcp-watermark.image) 14 | 15 | 一个简单的调用流程如下: 16 | 17 | ```ts 18 | const tags = ["web"] 19 | // 1. 初始化 20 | let cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 21 | 22 | // 2. 注册监听器 23 | let evts = [KIMEvent.Closed, KIMEvent.Reconnecting, KIMEvent.Reconnected, KIMEvent.Kickout] 24 | cli.register(evts, eventcallback) 25 | cli.onmessage(messagecallback) 26 | cli.onofflinemessage(offmessagecallback) 27 | 28 | // 3. 登录 29 | let { success, err } = await cli.login() 30 | if (!success) { 31 | log.error(err) 32 | return 33 | } 34 | 35 | // 4. 发送消息 36 | let { status, resp, err: err2 } = await cli.talkToUser("test2", new Content("hello")) 37 | if (status != Status.Success) { 38 | log.error(err) 39 | return 40 | } 41 | log.info(`resp - ${resp?.messageId} ${resp?.sendTime.toString()}`) 42 | 43 | await sleep(10) 44 | 45 | // 5. 登出 46 | await cli.logout() 47 | ``` 48 | 49 | **我们主要了解下其中三个监听器**: 50 | 51 | - **eventcallback**:事件监听器回调方法。在Client的生命周期图中,状态随着主动或被动的事件触发而发现改变。比如断线重连时两种状态`Reconnecting`和`Reconnected`,虽然SDK可能在几秒内就自动重连成功,但是这个变动过程还是要通知给上层,让业务决定是否显现给用户。 52 | 53 | ```ts 54 | let eventcallback = (evt: KIMEvent) => { 55 | log.info(`event ${evt}`) 56 | }; 57 | ``` 58 | 59 | - messagecallback:用于接收`在线消息`的回调方法。 60 | 61 | ```ts 62 | let messagecallback = (m: Message) => { 63 | log.info(m) 64 | } 65 | ``` 66 | 67 | - offmessagecallback:`离线消息`回调方法。通常是**dologin**成功并且同步离线索引完成之后,才会回调给上层,如下是调用示例: 68 | 69 | ```ts 70 | let offmessagecallback = (om: OfflineMessages) => { 71 | // 离线时的发送方用户列表 72 | let users = om.listUsers() 73 | if (users.length > 0) { 74 | log.info(`offline messages from users of ${users}`) 75 | // lazy load the first page messages from 'users[0]' 76 | let messages = om.loadUser(users[0], 1) 77 | log.info(messages) 78 | } 79 | // 离线的群列表 80 | let groups = om.listGroups() 81 | if(groups.length > 0) { 82 | log.info(`offline messages from groups of ${groups}`) 83 | } 84 | } 85 | ``` 86 | 87 | - `om.loadUser(users[0], 1)` 表示加载users[0]的第一页离线消息。 88 | 89 | -------------------------------------------------------------------------------- /sdk/login.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"login.js","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { KIMClient, KIMEvent, Message, OfflineMessages, Content, sleep } from "./src/sdk"; 2 | import log from 'loglevel-es'; 3 | import 'mock-local-storage' 4 | import { Status } from "./src/proto/common"; 5 | 6 | //三个测试账号 test1 ,test2 ,test3 7 | const tokens = [ 8 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDQ4Nn0.YsjY42O9A1hIZaxgbgyUXjQul2RBmwFiAufdlZe3boo", 9 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MiIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDUxNX0.LnlacfRur79dyVnFAoYiGXTSwSiO__hHVnVm8B2f-IY", 10 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MyIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDYwOX0.VsBg31LfmgFwfbgHmHWK8u72PI4elAoz3K9p3oKq6EI", 11 | ] 12 | 13 | const gatewayURL = "ws://119.3.4.216:8000" 14 | 15 | log.setLevel("DEBUG") 16 | 17 | let main = async () => { 18 | const tags = ["web"] 19 | // 初始化 20 | let cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 21 | let eventcallback = (evt: KIMEvent) => { 22 | log.info(`event ${evt}`) 23 | }; 24 | let messagecallback = (m: Message) => { 25 | log.info(m) 26 | } 27 | let offmessagecallback = (om: OfflineMessages) => { 28 | // 离线时的发送方用户列表 29 | let users = om.listUsers() 30 | if (users.length > 0) { 31 | log.info(`offline messages from users of ${users}`) 32 | // lazy load the first page messages from 'users[0]' 33 | let messages = om.loadUser(users[0], 1) 34 | log.info(messages) 35 | } 36 | // 离线的群列表 37 | let groups = om.listGroups() 38 | if (groups.length > 0) { 39 | log.info(`offline messages from groups of ${groups}`) 40 | } 41 | } 42 | // 2.注册事件 43 | let evts = [KIMEvent.Closed, KIMEvent.Reconnecting, KIMEvent.Reconnected, KIMEvent.Kickout] 44 | cli.register(evts, eventcallback) 45 | cli.onmessage(messagecallback) 46 | cli.onofflinemessage(offmessagecallback) 47 | // 3. 登录 48 | let { success, err } = await cli.login() 49 | if (!success) { 50 | log.error(err) 51 | return 52 | } 53 | 54 | // 4. 发送消息 55 | let { status, resp, err: err2 } = await cli.talkToUser("test2", new Content("hello")) 56 | if (status != Status.Success) { 57 | log.error(err) 58 | return 59 | } 60 | log.info(`resp - ${resp?.messageId} ${resp?.sendTime.toString()}`) 61 | 62 | await sleep(10) 63 | 64 | // 5. 登出 65 | await cli.logout() 66 | } 67 | 68 | main() -------------------------------------------------------------------------------- /src/login.ts: -------------------------------------------------------------------------------- 1 | 2 | import { w3cwebsocket } from 'websocket'; 3 | import { Buffer } from 'buffer'; 4 | import log from 'loglevel-es'; 5 | import { Command, LogicPkt } from './packet'; 6 | import { Status } from './proto/common'; 7 | import { LoginReq, LoginResp } from './proto/protocol'; 8 | 9 | const loginTimeout = 10 * 1000 // 10 seconds 10 | 11 | export class LoginBody { 12 | token: string; 13 | tags?: string[]; 14 | constructor(token: string, tags?: string[]) { 15 | this.token = token; 16 | this.tags = tags; 17 | } 18 | } 19 | 20 | export let doLogin = async (url: string, req: LoginBody): Promise<{ success: boolean, err?: Error, channelId?: string, account?: string, conn: w3cwebsocket }> => { 21 | return new Promise((resolve, _) => { 22 | let conn = new w3cwebsocket(url) 23 | conn.binaryType = "arraybuffer" 24 | 25 | // 设置一个登陆超时器 26 | let tr = setTimeout(() => { 27 | clearTimeout(tr) 28 | resolve({ success: false, err: new Error("timeout"), conn: conn }); 29 | }, loginTimeout); 30 | 31 | conn.onopen = () => { 32 | if (conn.readyState == w3cwebsocket.OPEN) { 33 | log.info(`connection established, send ${req.token}`) 34 | // send handshake request 35 | let pbreq = LoginReq.encode(LoginReq.fromJSON(req)).finish() 36 | let loginpkt = LogicPkt.build(Command.SignIn, "", pbreq) 37 | let buf = loginpkt.bytes() 38 | log.debug(`dologin send [${buf.join(",")}]`) 39 | conn.send(buf) 40 | } 41 | } 42 | conn.onerror = (error: Error) => { 43 | clearTimeout(tr) 44 | log.warn(error) 45 | resolve({ success: false, err: error, conn: conn }); 46 | } 47 | 48 | conn.onmessage = (evt) => { 49 | if (typeof evt.data === 'string') { 50 | log.warn("Received: '" + evt.data + "'"); 51 | return 52 | } 53 | clearTimeout(tr) 54 | // wating for login response 55 | let buf = Buffer.from(evt.data) 56 | let loginResp = LogicPkt.from(buf) 57 | if (loginResp.status != Status.Success) { 58 | log.error("Login failed: " + loginResp.status) 59 | resolve({ success: false, err: new Error(`response status is ${loginResp.status}`), conn: conn }); 60 | return 61 | } 62 | let resp = LoginResp.decode(loginResp.payload) 63 | resolve({ success: true, channelId: resp.channelId, account: resp.account, conn: conn }); 64 | } 65 | 66 | }) 67 | } 68 | -------------------------------------------------------------------------------- /proto/protocol.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package pkt; 3 | option go_package = "./pkt"; 4 | 5 | message LoginReq { 6 | string token = 1; 7 | string isp = 2; 8 | string zone = 3; // location code 9 | repeated string tags = 4; 10 | } 11 | 12 | message LoginResp { 13 | string channelId = 1; 14 | string account = 2; 15 | } 16 | 17 | message KickoutNotify { 18 | string channelId = 1; 19 | } 20 | 21 | message Session { 22 | string channelId = 1;// session id 23 | string gateId = 2; // gateway ID 24 | string account = 3; 25 | string zone = 4; 26 | string isp = 5; 27 | string remoteIP = 6; 28 | string device = 7; 29 | string app = 8; 30 | repeated string tags = 9; 31 | } 32 | 33 | // chat message 34 | message MessageReq { 35 | int32 type = 1; 36 | string body = 2; 37 | string extra = 3; 38 | } 39 | 40 | message MessageResp { 41 | int64 messageId = 1; 42 | int64 sendTime = 2; 43 | } 44 | 45 | message MessagePush { 46 | int64 messageId = 1; 47 | int32 type = 2; 48 | string body = 3; 49 | string extra = 4; 50 | string sender = 5; 51 | int64 sendTime = 6; 52 | } 53 | 54 | message ErrorResp { 55 | string message= 1; 56 | } 57 | 58 | message MessageAckReq { 59 | int64 messageId = 1; 60 | } 61 | 62 | message GroupCreateReq { 63 | string name = 1; 64 | string avatar = 2; 65 | string introduction = 3; 66 | string owner = 4; 67 | repeated string members = 5; 68 | } 69 | 70 | message GroupCreateResp { 71 | string group_id = 1; 72 | } 73 | 74 | message GroupCreateNotify { 75 | string group_id = 1; 76 | repeated string members = 2; 77 | } 78 | 79 | message GroupJoinReq { 80 | string account = 1; 81 | string group_id = 2; 82 | } 83 | 84 | message GroupQuitReq { 85 | string account = 1; 86 | string group_id = 2; 87 | } 88 | 89 | message GroupGetReq { 90 | string group_id = 1; 91 | } 92 | 93 | message Member { 94 | string account = 1; 95 | string alias = 2; 96 | string avatar = 3; 97 | int64 join_time = 4; 98 | } 99 | 100 | message GroupGetResp { 101 | string id = 1; 102 | string name = 2; 103 | string avatar = 3; 104 | string introduction = 4; 105 | string owner = 5; 106 | repeated Member members = 6; 107 | int64 created_at = 7; 108 | } 109 | 110 | message GroupJoinNotify { 111 | string group_id = 1; 112 | string account = 2; 113 | } 114 | 115 | message GroupQuitNotify { 116 | string group_id = 1; 117 | string account = 2; 118 | } 119 | 120 | message MessageIndexReq { 121 | int64 message_id = 1; 122 | } 123 | 124 | message MessageIndexResp { 125 | repeated MessageIndex indexes = 1; 126 | } 127 | 128 | message MessageIndex { 129 | int64 message_id = 1; 130 | int32 direction = 2; 131 | int64 send_time = 3; 132 | string accountB = 4; 133 | string group = 5; 134 | } 135 | 136 | message MessageContentReq { 137 | repeated int64 message_ids = 1; 138 | } 139 | 140 | message MessageContent { 141 | int64 messageId = 1; 142 | int32 type = 2; 143 | string body = 3; 144 | string extra = 4; 145 | } 146 | 147 | message MessageContentResp { 148 | repeated MessageContent contents = 1; 149 | } 150 | 151 | // message Pkt { 152 | // uint32 Source = 1; 153 | // uint64 Sequence = 3; 154 | // bytes Data = 5; 155 | // } -------------------------------------------------------------------------------- /sdk/packet.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"packet.js","sourceRoot":"","sources":["../src/packet.ts"],"names":[],"mappings":";;;AACA,yCAAsD;AAGtD;IAAA;IAOA,CAAC;IALU,QAAI,GAAX;QACI,GAAG,CAAC,GAAG,EAAE,CAAA;QACT,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,KAAK,CAAA;QACzB,OAAO,GAAG,CAAC,GAAG,CAAA;IAClB,CAAC;IALM,OAAG,GAAW,CAAC,CAAA;IAM1B,UAAC;CAAA,AAPD,IAOC;AAPY,kBAAG;AAShB,IAAY,OAmBX;AAnBD,WAAY,OAAO;IACf,QAAQ;IACR,kCAAuB,CAAA;IACvB,oCAAyB,CAAA;IAEzB,OAAO;IACP,0CAA+B,CAAA;IAC/B,4CAAiC,CAAA;IACjC,wCAA6B,CAAA;IAE7B,KAAK;IACL,8CAAmC,CAAA;IACnC,kDAAuC,CAAA;IAEvC,MAAM;IACN,4CAAiC,CAAA;IACjC,wCAA6B,CAAA;IAC7B,wCAA6B,CAAA;IAC7B,4CAAiC,CAAA;AACrC,CAAC,EAnBW,OAAO,GAAP,eAAO,KAAP,eAAO,QAmBlB;AAED,IAAM,aAAa,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAC9D,IAAM,aAAa,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAEjD,QAAA,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAA;AAC3D,QAAA,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAA;AAExE,IAAY,WAKX;AALD,WAAY,WAAW;IACnB,6CAAQ,CAAA;IACR,+CAAS,CAAA;IACT,+CAAS,CAAA;IACT,+CAAS,CAAA;AACb,CAAC,EALW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAKtB;AAEY,QAAA,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAC3D,QAAA,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAExE;IAQI;QALA,aAAQ,GAAW,CAAC,CAAC;QAErB,WAAM,GAAW,eAAM,CAAC,OAAO,CAAC;QAI5B,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;IACpC,CAAC;IACM,cAAK,GAAZ,UAAa,OAAe,EAAE,IAAY,EAAE,OAAsC;QAAtC,wBAAA,EAAA,cAA0B,UAAU,EAAE;QAC9E,iBAAiB;QACjB,IAAI,OAAO,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC5B,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;QACzB,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;QAC7B,OAAO,CAAC,IAAI,GAAG,IAAI,CAAA;QACnB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;YACpB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;SAC5B;QACD,OAAO,OAAO,CAAA;IAClB,CAAC;IACM,aAAI,GAAX,UAAY,GAAW;QACnB,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,IAAI,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QACnC,IAAI,IAAI,GAAG,CAAC,CAAA;QACZ,mBAAmB;QACnB,IAAI,KAAK,IAAI,wBAAgB,EAAE;YAC3B,MAAM,IAAI,CAAC,CAAA;SACd;QACD,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAC9B,MAAM,IAAI,CAAC,CAAA;QACX,aAAa;QACb,IAAI,MAAM,GAAG,eAAM,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;QAC/D,MAAM,IAAI,IAAI,CAAA;QACd,IAAI,OAAO,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC5B,0BAA0B;QAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC9B,YAAY;QACZ,IAAI,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAClC,MAAM,IAAI,CAAC,CAAA;QACX,OAAO,CAAC,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAA;QACrD,OAAO,OAAO,CAAA;IAClB,CAAC;IACD,wBAAK,GAAL;QACI,IAAI,WAAW,GAAG,eAAM,CAAC,MAAM,CAAC,eAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAA;QAC/D,IAAI,IAAI,GAAG,WAAW,CAAC,MAAM,CAAA;QAC7B,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAA;QAC9B,kFAAkF;QAClF,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;QAC/C,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QAC/C,MAAM,IAAI,CAAC,CAAA;QACX,uBAAuB;QACvB,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACvC,SAAS;QACT,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QAC7C,MAAM,IAAI,IAAI,CAAA;QACd,wBAAwB;QACxB,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACvC,UAAU;QACV,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QAC9C,OAAO,GAAG,CAAA;IACd,CAAC;IACL,eAAC;AAAD,CAAC,AAhED,IAgEC;AAhEY,4BAAQ;AAkEd,IAAI,KAAK,GAAG,UAAC,GAAe;IAC/B,IAAI,GAAG,IAAI,IAAI,EAAE;QACb,OAAM;KACT;IACD,OAAO,CAAC,IAAI,CAAC,MAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAG,CAAC,CAAA;AACtC,CAAC,CAAA;AALU,QAAA,KAAK,SAKf"} -------------------------------------------------------------------------------- /sdk/packet.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | var __generator = (this && this.__generator) || function (thisArg, body) { 12 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 13 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 14 | function verb(n) { return function (v) { return step([n, v]); }; } 15 | function step(op) { 16 | if (f) throw new TypeError("Generator is already executing."); 17 | while (_) try { 18 | 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; 19 | if (y = 0, t) op = [op[0] & 2, t.value]; 20 | switch (op[0]) { 21 | case 0: case 1: t = op; break; 22 | case 4: _.label++; return { value: op[1], done: false }; 23 | case 5: _.label++; y = op[1]; op = [0]; continue; 24 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 25 | default: 26 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 27 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 28 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 29 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 30 | if (t[2]) _.ops.pop(); 31 | _.trys.pop(); continue; 32 | } 33 | op = body.call(thisArg, _); 34 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 35 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 36 | } 37 | }; 38 | var __importDefault = (this && this.__importDefault) || function (mod) { 39 | return (mod && mod.__esModule) ? mod : { "default": mod }; 40 | }; 41 | Object.defineProperty(exports, "__esModule", { value: true }); 42 | var protocol_1 = require("./proto/protocol"); 43 | var packet_1 = require("./packet"); 44 | var loglevel_es_1 = __importDefault(require("loglevel-es")); 45 | loglevel_es_1.default.setLevel("debug"); 46 | test('logicpkt', function () { return __awaiter(void 0, void 0, void 0, function () { 47 | var token, body, loginReq, buf, pkt, req; 48 | return __generator(this, function (_a) { 49 | token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTYyOTA5MzU0OX0.P_yk1KMB5v9riUy0yW4eOTgC0k0qeB6XRjih4dL1xGk"; 50 | body = protocol_1.LoginReq.encode(protocol_1.LoginReq.fromJSON({ 51 | token: token, 52 | })).finish(); 53 | loginReq = packet_1.LogicPkt.build(packet_1.Command.SignIn, "", body); 54 | buf = loginReq.bytes(); 55 | // 验证前面的4字节等于MagicLogicPktInt 56 | expect(buf.readInt32BE()).toEqual(packet_1.MagicLogicPktInt); 57 | pkt = packet_1.LogicPkt.from(buf.subarray(4)); 58 | expect(pkt.command).toEqual(packet_1.Command.SignIn); 59 | expect(pkt.dest).toEqual(""); 60 | expect(pkt.sequence).toBeGreaterThan(0); 61 | expect(pkt.payload.length).toEqual(body.length); 62 | req = protocol_1.LoginReq.decode(pkt.payload); 63 | expect(req.token).toEqual(token); 64 | return [2 /*return*/]; 65 | }); 66 | }); }); 67 | //# sourceMappingURL=packet.test.js.map -------------------------------------------------------------------------------- /src/packet.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Header, Flag, Status } from './proto/common'; 3 | import log from 'loglevel-es'; 4 | 5 | import * as buffer from "buffer"; 6 | 7 | if (typeof (window as any).global === "undefined") { 8 | (window as any).global = window; 9 | } 10 | if (typeof (window as any).Buffer === "undefined") { 11 | (window as any).Buffer = buffer.Buffer; 12 | } 13 | 14 | export class Seq { 15 | static num: number = 0 16 | static Next() { 17 | Seq.num++ 18 | Seq.num = Seq.num % 65536 19 | return Seq.num 20 | } 21 | } 22 | 23 | export enum Command { 24 | // login 25 | SignIn = "login.signin", 26 | SignOut = "login.signout", 27 | 28 | // chat 29 | ChatUserTalk = "chat.user.talk", 30 | ChatGroupTalk = "chat.group.talk", 31 | ChatTalkAck = "chat.talk.ack", 32 | 33 | // 离线 34 | OfflineIndex = "chat.offline.index", 35 | OfflineContent = "chat.offline.content", 36 | 37 | // 群管理 38 | GroupCreate = "chat.group.create", 39 | GroupJoin = "chat.group.join", 40 | GroupQuit = "chat.group.quit", 41 | GroupDetail = "chat.group.detail", 42 | } 43 | 44 | const MagicLogicPkt = new Uint8Array([0xc3, 0x11, 0xa3, 0x65]) 45 | const MagicBasicPkt = new Uint8Array([0xc3, 0x15, 0xa7, 0x65]) 46 | 47 | export const MagicLogicPktInt = Buffer.from(MagicLogicPkt).readInt32BE() 48 | export const MagicBasicPktInt = Buffer.from(MagicBasicPkt).readInt32BE() 49 | 50 | export enum MessageType { 51 | Text = 1, // 文本 52 | Image = 2, // 图片 53 | Voice = 3, // 语音 54 | Video = 4, //视频 55 | } 56 | 57 | export const Ping = new Uint8Array([0xc3, 0x15, 0xa7, 0x65, 0, 1, 0, 0]) 58 | export const Pong = new Uint8Array([0xc3, 0x15, 0xa7, 0x65, 0, 2, 0, 0]) 59 | 60 | export class LogicPkt { 61 | command?: string; 62 | channelId?: string; 63 | sequence: number = 0; 64 | flag?: number; 65 | status: number = Status.Success; 66 | dest?: string; 67 | payload: Uint8Array 68 | constructor() { 69 | this.payload = new Uint8Array(); 70 | } 71 | static build(command: string, dest: string, payload: Uint8Array = new Uint8Array()): LogicPkt { 72 | // build LogicPkt 73 | let message = new LogicPkt() 74 | message.command = command 75 | message.sequence = Seq.Next() 76 | message.dest = dest 77 | if (payload.length > 0) { 78 | message.payload = payload 79 | } 80 | return message 81 | } 82 | static from(buf: Buffer): LogicPkt { 83 | let offset = 0 84 | let magic = buf.readInt32BE(offset) 85 | let hlen = 0 86 | // 判断前面四个字节是否为Magic 87 | if (magic == MagicLogicPktInt) { 88 | offset += 4 89 | } 90 | hlen = buf.readInt32BE(offset) 91 | offset += 4 92 | // 反序列化Header 93 | let header = Header.decode(buf.subarray(offset, offset + hlen)) 94 | offset += hlen 95 | let message = new LogicPkt() 96 | // 把header中的属性copy到message 97 | Object.assign(message, header) 98 | // 读取payload 99 | let plen = buf.readInt32BE(offset) 100 | offset += 4 101 | message.payload = buf.subarray(offset, offset + plen) 102 | return message 103 | } 104 | bytes(): Buffer { 105 | let headerArray = Header.encode(Header.fromJSON(this)).finish() 106 | let hlen = headerArray.length 107 | let plen = this.payload.length 108 | //| 4bytes magic | 4bytes Header Length| header | 4bytes Payload Length| payload | 109 | let buf = Buffer.alloc(4 + 4 + hlen + 4 + plen) 110 | let offset = 0 111 | Buffer.from(MagicLogicPkt).copy(buf, offset, 0) 112 | offset += 4 113 | // 4bytes Header Length 114 | offset = buf.writeInt32BE(hlen, offset) 115 | // header 116 | Buffer.from(headerArray).copy(buf, offset, 0) 117 | offset += hlen 118 | // 4bytes Payload Length 119 | offset = buf.writeInt32BE(plen, offset) 120 | // payload 121 | Buffer.from(this.payload).copy(buf, offset, 0) 122 | return buf 123 | } 124 | } 125 | 126 | export let print = (arr: Uint8Array) => { 127 | if (arr == null) { 128 | return 129 | } 130 | console.info(`[${arr.join(",")}]`) 131 | } -------------------------------------------------------------------------------- /sdk/packet.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.print = exports.LogicPkt = exports.Pong = exports.Ping = exports.MessageType = exports.MagicBasicPktInt = exports.MagicLogicPktInt = exports.Command = exports.Seq = void 0; 4 | var common_1 = require("./proto/common"); 5 | var Seq = /** @class */ (function () { 6 | function Seq() { 7 | } 8 | Seq.Next = function () { 9 | Seq.num++; 10 | Seq.num = Seq.num % 65536; 11 | return Seq.num; 12 | }; 13 | Seq.num = 0; 14 | return Seq; 15 | }()); 16 | exports.Seq = Seq; 17 | var Command; 18 | (function (Command) { 19 | // login 20 | Command["SignIn"] = "login.signin"; 21 | Command["SignOut"] = "login.signout"; 22 | // chat 23 | Command["ChatUserTalk"] = "chat.user.talk"; 24 | Command["ChatGroupTalk"] = "chat.group.talk"; 25 | Command["ChatTalkAck"] = "chat.talk.ack"; 26 | // 离线 27 | Command["OfflineIndex"] = "chat.offline.index"; 28 | Command["OfflineContent"] = "chat.offline.content"; 29 | // 群管理 30 | Command["GroupCreate"] = "chat.group.create"; 31 | Command["GroupJoin"] = "chat.group.join"; 32 | Command["GroupQuit"] = "chat.group.quit"; 33 | Command["GroupDetail"] = "chat.group.detail"; 34 | })(Command = exports.Command || (exports.Command = {})); 35 | var MagicLogicPkt = new Uint8Array([0xc3, 0x11, 0xa3, 0x65]); 36 | var MagicBasicPkt = new Uint8Array([0xc3, 0x15, 0xa7, 0x65]); 37 | exports.MagicLogicPktInt = Buffer.from(MagicLogicPkt).readInt32BE(); 38 | exports.MagicBasicPktInt = Buffer.from(MagicBasicPkt).readInt32BE(); 39 | var MessageType; 40 | (function (MessageType) { 41 | MessageType[MessageType["Text"] = 1] = "Text"; 42 | MessageType[MessageType["Image"] = 2] = "Image"; 43 | MessageType[MessageType["Voice"] = 3] = "Voice"; 44 | MessageType[MessageType["Video"] = 4] = "Video"; 45 | })(MessageType = exports.MessageType || (exports.MessageType = {})); 46 | exports.Ping = new Uint8Array([0xc3, 0x15, 0xa7, 0x65, 0, 1, 0, 0]); 47 | exports.Pong = new Uint8Array([0xc3, 0x15, 0xa7, 0x65, 0, 2, 0, 0]); 48 | var LogicPkt = /** @class */ (function () { 49 | function LogicPkt() { 50 | this.sequence = 0; 51 | this.status = common_1.Status.Success; 52 | this.payload = new Uint8Array(); 53 | } 54 | LogicPkt.build = function (command, dest, payload) { 55 | if (payload === void 0) { payload = new Uint8Array(); } 56 | // build LogicPkt 57 | var message = new LogicPkt(); 58 | message.command = command; 59 | message.sequence = Seq.Next(); 60 | message.dest = dest; 61 | if (payload.length > 0) { 62 | message.payload = payload; 63 | } 64 | return message; 65 | }; 66 | LogicPkt.from = function (buf) { 67 | var offset = 0; 68 | var magic = buf.readInt32BE(offset); 69 | var hlen = 0; 70 | // 判断前面四个字节是否为Magic 71 | if (magic == exports.MagicLogicPktInt) { 72 | offset += 4; 73 | } 74 | hlen = buf.readInt32BE(offset); 75 | offset += 4; 76 | // 反序列化Header 77 | var header = common_1.Header.decode(buf.subarray(offset, offset + hlen)); 78 | offset += hlen; 79 | var message = new LogicPkt(); 80 | // 把header中的属性copy到message 81 | Object.assign(message, header); 82 | // 读取payload 83 | var plen = buf.readInt32BE(offset); 84 | offset += 4; 85 | message.payload = buf.subarray(offset, offset + plen); 86 | return message; 87 | }; 88 | LogicPkt.prototype.bytes = function () { 89 | var headerArray = common_1.Header.encode(common_1.Header.fromJSON(this)).finish(); 90 | var hlen = headerArray.length; 91 | var plen = this.payload.length; 92 | //| 4bytes magic | 4bytes Header Length| header | 4bytes Payload Length| payload | 93 | var buf = Buffer.alloc(4 + 4 + hlen + 4 + plen); 94 | var offset = 0; 95 | Buffer.from(MagicLogicPkt).copy(buf, offset, 0); 96 | offset += 4; 97 | // 4bytes Header Length 98 | offset = buf.writeInt32BE(hlen, offset); 99 | // header 100 | Buffer.from(headerArray).copy(buf, offset, 0); 101 | offset += hlen; 102 | // 4bytes Payload Length 103 | offset = buf.writeInt32BE(plen, offset); 104 | // payload 105 | Buffer.from(this.payload).copy(buf, offset, 0); 106 | return buf; 107 | }; 108 | return LogicPkt; 109 | }()); 110 | exports.LogicPkt = LogicPkt; 111 | var print = function (arr) { 112 | if (arr == null) { 113 | return; 114 | } 115 | console.info("[" + arr.join(",") + "]"); 116 | }; 117 | exports.print = print; 118 | //# sourceMappingURL=packet.js.map -------------------------------------------------------------------------------- /sdk/login.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | var __generator = (this && this.__generator) || function (thisArg, body) { 12 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 13 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 14 | function verb(n) { return function (v) { return step([n, v]); }; } 15 | function step(op) { 16 | if (f) throw new TypeError("Generator is already executing."); 17 | while (_) try { 18 | 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; 19 | if (y = 0, t) op = [op[0] & 2, t.value]; 20 | switch (op[0]) { 21 | case 0: case 1: t = op; break; 22 | case 4: _.label++; return { value: op[1], done: false }; 23 | case 5: _.label++; y = op[1]; op = [0]; continue; 24 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 25 | default: 26 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 27 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 28 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 29 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 30 | if (t[2]) _.ops.pop(); 31 | _.trys.pop(); continue; 32 | } 33 | op = body.call(thisArg, _); 34 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 35 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 36 | } 37 | }; 38 | var __importDefault = (this && this.__importDefault) || function (mod) { 39 | return (mod && mod.__esModule) ? mod : { "default": mod }; 40 | }; 41 | Object.defineProperty(exports, "__esModule", { value: true }); 42 | exports.doLogin = exports.LoginBody = void 0; 43 | var websocket_1 = require("websocket"); 44 | var buffer_1 = require("buffer"); 45 | var loglevel_es_1 = __importDefault(require("loglevel-es")); 46 | var packet_1 = require("./packet"); 47 | var common_1 = require("./proto/common"); 48 | var protocol_1 = require("./proto/protocol"); 49 | var loginTimeout = 10 * 1000; // 10 seconds 50 | var LoginBody = /** @class */ (function () { 51 | function LoginBody(token, tags) { 52 | this.token = token; 53 | this.tags = tags; 54 | } 55 | return LoginBody; 56 | }()); 57 | exports.LoginBody = LoginBody; 58 | var doLogin = function (url, req) { return __awaiter(void 0, void 0, void 0, function () { 59 | return __generator(this, function (_a) { 60 | return [2 /*return*/, new Promise(function (resolve, _) { 61 | var conn = new websocket_1.w3cwebsocket(url); 62 | conn.binaryType = "arraybuffer"; 63 | // 设置一个登陆超时器 64 | var tr = setTimeout(function () { 65 | clearTimeout(tr); 66 | resolve({ success: false, err: new Error("timeout"), conn: conn }); 67 | }, loginTimeout); 68 | conn.onopen = function () { 69 | if (conn.readyState == websocket_1.w3cwebsocket.OPEN) { 70 | loglevel_es_1.default.info("connection established, send " + req.token); 71 | // send handshake request 72 | var pbreq = protocol_1.LoginReq.encode(protocol_1.LoginReq.fromJSON(req)).finish(); 73 | var loginpkt = packet_1.LogicPkt.build(packet_1.Command.SignIn, "", pbreq); 74 | var buf = loginpkt.bytes(); 75 | loglevel_es_1.default.debug("dologin send [" + buf.join(",") + "]"); 76 | conn.send(buf); 77 | } 78 | }; 79 | conn.onerror = function (error) { 80 | clearTimeout(tr); 81 | loglevel_es_1.default.warn(error); 82 | resolve({ success: false, err: error, conn: conn }); 83 | }; 84 | conn.onmessage = function (evt) { 85 | if (typeof evt.data === 'string') { 86 | loglevel_es_1.default.warn("Received: '" + evt.data + "'"); 87 | return; 88 | } 89 | clearTimeout(tr); 90 | // wating for login response 91 | var buf = buffer_1.Buffer.from(evt.data); 92 | var loginResp = packet_1.LogicPkt.from(buf); 93 | if (loginResp.status != common_1.Status.Success) { 94 | loglevel_es_1.default.error("Login failed: " + loginResp.status); 95 | resolve({ success: false, err: new Error("response status is " + loginResp.status), conn: conn }); 96 | return; 97 | } 98 | var resp = protocol_1.LoginResp.decode(loginResp.payload); 99 | resolve({ success: true, channelId: resp.channelId, account: resp.account, conn: conn }); 100 | }; 101 | })]; 102 | }); 103 | }); }; 104 | exports.doLogin = doLogin; 105 | //# sourceMappingURL=login.js.map -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | /* Basic Options */ 5 | // "incremental": true, /* Enable incremental compilation */ 6 | "target": "ES5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 7 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 8 | // "lib": [], /* Specify library files to be included in the compilation. */ 9 | // "allowJs": true, /* Allow javascript files to be compiled. */ 10 | // "checkJs": true, /* Report errors in .js files. */ 11 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 12 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 13 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 14 | "sourceMap": true, /* Generates corresponding '.map' file. */ 15 | // "outFile": "./", /* Concatenate and emit output to single file. */ 16 | "outDir": "./sdk/", /* Redirect output structure to the directory. */ 17 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 18 | // "composite": true, /* Enable project compilation */ 19 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 20 | // "removeComments": true, /* Do not emit comments to output. */ 21 | // "noEmit": true, /* Do not emit outputs. */ 22 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 23 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 24 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 25 | /* Strict Type-Checking Options */ 26 | "strict": true, /* Enable all strict type-checking options. */ 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | /* Additional Checks */ 35 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 36 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 37 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 38 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 39 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 40 | /* Module Resolution Options */ 41 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 45 | // "typeRoots": [], /* List of folders to include type definitions from. */ 46 | // "types": [], /* Type declaration files to be included in compilation. */ 47 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 48 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 49 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 50 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 51 | /* Source Map Options */ 52 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 53 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 54 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 55 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 56 | /* Experimental Options */ 57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 59 | /* Advanced Options */ 60 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 61 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 62 | }, 63 | "include": [ 64 | "src/**/*" 65 | ], 66 | "exclude": [ 67 | "node_modules", 68 | "proto", 69 | "bin" 70 | ] 71 | } -------------------------------------------------------------------------------- /src/sdk.test.ts: -------------------------------------------------------------------------------- 1 | import { Content, KIMClient, KIMEvent, Store, Message, OfflineMessages, sleep } from "./sdk" 2 | import log from 'loglevel-es'; 3 | import { doLogin } from "./login"; 4 | import { Status } from "./proto/common"; 5 | import { MessageType } from "./packet"; 6 | import Long from 'long'; 7 | import 'jest-localstorage-mock'; 8 | log.setLevel("info") 9 | jest.setTimeout(30 * 1000) 10 | 11 | // https://jestjs.io/docs/cli 12 | 13 | //三个测试账号 test1 ,test2 ,test3 14 | const tokens = [ 15 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDQ4Nn0.YsjY42O9A1hIZaxgbgyUXjQul2RBmwFiAufdlZe3boo", 16 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MiIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDUxNX0.LnlacfRur79dyVnFAoYiGXTSwSiO__hHVnVm8B2f-IY", 17 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MyIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDYwOX0.VsBg31LfmgFwfbgHmHWK8u72PI4elAoz3K9p3oKq6EI", 18 | ] 19 | 20 | const gatewayURL = "ws://119.3.4.216:8000" 21 | 22 | test('doLogin', async () => { 23 | const tags = ["web"] 24 | let { success, channelId, account, conn } = await doLogin(gatewayURL, { token: tokens[0], tags }) 25 | expect(success).toBeTruthy() 26 | log.info(account, channelId) 27 | expect(channelId).toContain("test1") 28 | expect(account).toEqual("test1") 29 | conn.onclose = () => { 30 | log.info("closed") 31 | } 32 | conn.close() 33 | }) 34 | 35 | test('doLoginfail', async () => { 36 | const tags = ["web"] 37 | let { success, err } = await doLogin(gatewayURL, { token: "", tags }) 38 | expect(success).toBeFalsy() 39 | log.error(err) 40 | }) 41 | 42 | test('store', async () => { 43 | let ok = await Store.insert(new Message(Long.fromNumber(1), Long.fromNumber(1))) 44 | expect(ok).toBeTruthy() 45 | 46 | let msg = await Store.get(Long.fromNumber(1)) 47 | expect(msg?.messageId).toEqual(Long.fromNumber(1)) 48 | log.info(msg) 49 | await Store.setAck(Long.fromNumber(1)) 50 | 51 | let id = await Store.lastId() 52 | log.info("id - ", id) 53 | expect(id).toEqual(Long.fromNumber(1)) 54 | }) 55 | 56 | test('clilogin', async () => { 57 | // test1 58 | const tags = ["web"] 59 | let cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 60 | let { success, err } = await cli.login() 61 | expect(success).toBeTruthy() 62 | let callback = jest.fn((evt: KIMEvent) => { 63 | log.info("--------", evt) 64 | }); 65 | cli.register([KIMEvent.Closed], callback) 66 | expect(cli.account).toEqual("test1") 67 | await cli.logout() 68 | await sleep(2) 69 | // Closed回调方法必须被调用一次 70 | expect(callback).toBeCalledTimes(1) 71 | }) 72 | 73 | test('dokickout', async () => { 74 | // test1 75 | const tags = ["web"] 76 | let cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 77 | let { success, err } = await cli.login() 78 | expect(success).toBeTruthy() 79 | cli.register([KIMEvent.Kickout], (evt: KIMEvent) => { 80 | log.info("--------", evt) 81 | expect(evt).toEqual(KIMEvent.Kickout) 82 | }) 83 | 84 | cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 85 | await cli.login() 86 | await sleep(1) 87 | await cli.logout() 88 | }) 89 | 90 | test('usertalk', async () => { 91 | // test1 92 | const tags = ["web"] 93 | let cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 94 | let { success, err } = await cli.login() 95 | expect(err).toBeUndefined() 96 | expect(success).toBeTruthy() 97 | 98 | let cli2 = new KIMClient(gatewayURL, { token: tokens[1], tags }); 99 | let onmessage = jest.fn(async (m: Message) => { 100 | expect(m.sender).toEqual(cli.account) 101 | expect(m.receiver).toEqual(cli2.account) 102 | expect(m.body).toEqual("hello") 103 | expect(m.type).toEqual(MessageType.Text) 104 | 105 | await cli.logout() 106 | await cli2.logout() 107 | }); 108 | 109 | cli2.onmessage(onmessage) 110 | let { success: suc } = await cli2.login() 111 | expect(suc).toBeTruthy() 112 | // { type: 1, body: "hello" } 113 | let { status, resp } = await cli.talkToUser(cli2.account, new Content("hello")) 114 | expect(status).toEqual(Status.Success) 115 | expect(resp?.messageId.greaterThan(1000)).toBeTruthy() 116 | expect(resp?.sendTime.greaterThan(1000)).toBeTruthy() 117 | await sleep(1) 118 | expect(onmessage).toBeCalledTimes(1) 119 | }) 120 | 121 | test('offline', async () => { 122 | // test1 123 | const tags = ["web"] 124 | let cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 125 | cli.onofflinemessage(async (om: OfflineMessages) => { 126 | 127 | }) 128 | let { success, err } = await cli.login() 129 | expect(err).toBeUndefined() 130 | expect(success).toBeTruthy() 131 | 132 | // { type: 1, body: "hello" } 133 | let { status, resp, err: er } = await cli.talkToUser("test2", new Content("hello")) 134 | expect(status).toEqual(Status.Success) 135 | if (er) { 136 | log.error("---", er.message) 137 | } 138 | expect(resp?.messageId.greaterThan(1000)).toBeTruthy() 139 | expect(resp?.sendTime.greaterThan(1000)).toBeTruthy() 140 | 141 | let cli2 = new KIMClient(gatewayURL, { token: tokens[1], tags }); 142 | let cb = jest.fn(async (om: OfflineMessages) => { 143 | let users = om.listUsers() 144 | log.info("onofflinemessage -- load ", users) 145 | 146 | expect(users.length).toBeGreaterThanOrEqual(1) 147 | log.info("--- lazy load messages") 148 | let msgs = await om.loadUser(users[0], 1) 149 | expect(msgs.length).toBeGreaterThanOrEqual(1) 150 | expect(msgs[0].body).toEqual("hello") 151 | // load again 152 | log.info("--- load again") 153 | msgs = await om.loadUser(users[0], 1) 154 | expect(msgs[0].body).toEqual("hello") 155 | await cli.logout() 156 | await cli2.logout() 157 | }); 158 | cli2.onofflinemessage(cb) 159 | let { success: suc } = await cli2.login() 160 | expect(suc).toBeTruthy() 161 | expect(cb).toBeCalledTimes(1) 162 | await sleep(3) 163 | }) 164 | 165 | test('group', async () => { 166 | // test1 167 | const tags = ["web"] 168 | let cli = new KIMClient(gatewayURL, { token: tokens[0], tags }); 169 | let { success, err } = await cli.login() 170 | expect(err).toBeUndefined() 171 | expect(success).toBeTruthy() 172 | 173 | let resp = await cli.createGroup({ 174 | name: "group_sdk", 175 | avatar: "", 176 | introduction: "test", 177 | members: ["test2"], 178 | }) 179 | expect(resp.status).toEqual(Status.Success) 180 | expect(resp.resp?.groupId).not.toBeNull() 181 | 182 | let groupId = resp.resp?.groupId||"" 183 | let resp2 = await cli.GetGroup({ groupId }) 184 | expect(resp2.status).toEqual(Status.Success) 185 | expect(resp2.resp?.members.length).toEqual(2) 186 | 187 | let resp3 = await cli.joinGroup({ groupId, account: "test3" }) 188 | expect(resp3.status).toEqual(Status.Success) 189 | 190 | let resp4 = await cli.GetGroup({ groupId }) 191 | expect(resp4.status).toEqual(Status.Success) 192 | expect(resp4.resp?.members.length).toEqual(3) 193 | log.info(resp4) 194 | 195 | let resp5 = await cli.quitGroup({ groupId, account: "test3" }) 196 | expect(resp5.status).toEqual(Status.Success) 197 | 198 | let resp6 = await cli.GetGroup({ groupId }) 199 | expect(resp6.status).toEqual(Status.Success) 200 | expect(resp6.resp?.members.length).toEqual(2) 201 | 202 | await cli.logout() 203 | }) -------------------------------------------------------------------------------- /sdk/sdk.test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"sdk.test.js","sourceRoot":"","sources":["../src/sdk.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6BAA4F;AAC5F,4DAA8B;AAC9B,iCAAkC;AAClC,yCAAwC;AACxC,mCAAuC;AACvC,8CAAwB;AACxB,kCAAgC;AAChC,qBAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AACpB,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,CAAC,CAAA;AAE1B,6BAA6B;AAE7B,4BAA4B;AAC5B,IAAM,MAAM,GAAG;IACX,8IAA8I;IAC9I,8IAA8I;IAC9I,8IAA8I;CACjJ,CAAA;AAED,IAAM,UAAU,GAAG,uBAAuB,CAAA;AAE1C,IAAI,CAAC,SAAS,EAAE;;;;;gBACN,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;gBACwB,qBAAM,eAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,EAAA;;gBAA7F,KAAwC,SAAqD,EAA3F,OAAO,aAAA,EAAE,SAAS,eAAA,EAAE,OAAO,aAAA,EAAE,IAAI,UAAA;gBACvC,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,CAAA;gBAC5B,qBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;gBAC5B,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;gBACpC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;gBAChC,IAAI,CAAC,OAAO,GAAG;oBACX,qBAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;gBACtB,CAAC,CAAA;gBACD,IAAI,CAAC,KAAK,EAAE,CAAA;;;;KACf,CAAC,CAAA;AAEF,IAAI,CAAC,aAAa,EAAE;;;;;gBACV,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;gBACG,qBAAM,eAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,MAAA,EAAE,CAAC,EAAA;;gBAAjE,KAAmB,SAA8C,EAA/D,OAAO,aAAA,EAAE,GAAG,SAAA;gBAClB,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,CAAA;gBAC3B,qBAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;;;;KACjB,CAAC,CAAA;AAEF,IAAI,CAAC,OAAO,EAAE;;;;oBACD,qBAAM,WAAK,CAAC,MAAM,CAAC,IAAI,aAAO,CAAC,cAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,cAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAA;;gBAA5E,EAAE,GAAG,SAAuE;gBAChF,MAAM,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAA;gBAEb,qBAAM,WAAK,CAAC,GAAG,CAAC,cAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAA;;gBAAzC,GAAG,GAAG,SAAmC;gBAC7C,MAAM,CAAC,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,SAAS,CAAC,CAAC,OAAO,CAAC,cAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;gBAClD,qBAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBACb,qBAAM,WAAK,CAAC,MAAM,CAAC,cAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAA;;gBAAtC,SAAsC,CAAA;gBAE7B,qBAAM,WAAK,CAAC,MAAM,EAAE,EAAA;;gBAAzB,EAAE,GAAG,SAAoB;gBAC7B,qBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;gBACrB,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,cAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;;;;KACzC,CAAC,CAAA;AAEF,IAAI,CAAC,UAAU,EAAE;;;;;gBAEP,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;gBAChB,GAAG,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBACzC,qBAAM,GAAG,CAAC,KAAK,EAAE,EAAA;;gBAApC,KAAmB,SAAiB,EAAlC,OAAO,aAAA,EAAE,GAAG,SAAA;gBAClB,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,CAAA;gBACxB,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,UAAC,GAAa;oBACjC,qBAAG,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;gBAC7B,CAAC,CAAC,CAAC;gBACH,GAAG,CAAC,QAAQ,CAAC,CAAC,cAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAA;gBACzC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;gBACpC,qBAAM,GAAG,CAAC,MAAM,EAAE,EAAA;;gBAAlB,SAAkB,CAAA;gBAClB,qBAAM,WAAK,CAAC,CAAC,CAAC;oBACd,oBAAoB;kBADN;;gBAAd,SAAc,CAAA;gBACd,oBAAoB;gBACpB,MAAM,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;;;;KACtC,CAAC,CAAA;AAEF,IAAI,CAAC,WAAW,EAAE;;;;;gBAER,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;gBAChB,GAAG,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBACzC,qBAAM,GAAG,CAAC,KAAK,EAAE,EAAA;;gBAApC,KAAmB,SAAiB,EAAlC,OAAO,aAAA,EAAE,GAAG,SAAA;gBAClB,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,CAAA;gBAC5B,GAAG,CAAC,QAAQ,CAAC,CAAC,cAAQ,CAAC,OAAO,CAAC,EAAE,UAAC,GAAa;oBAC3C,qBAAG,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;oBACzB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAQ,CAAC,OAAO,CAAC,CAAA;gBACzC,CAAC,CAAC,CAAA;gBAEF,GAAG,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBAC5D,qBAAM,GAAG,CAAC,KAAK,EAAE,EAAA;;gBAAjB,SAAiB,CAAA;gBACjB,qBAAM,WAAK,CAAC,CAAC,CAAC,EAAA;;gBAAd,SAAc,CAAA;gBACd,qBAAM,GAAG,CAAC,MAAM,EAAE,EAAA;;gBAAlB,SAAkB,CAAA;;;;KACrB,CAAC,CAAA;AAEF,IAAI,CAAC,UAAU,EAAE;;;;;gBAEP,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;gBAChB,GAAG,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBACzC,qBAAM,GAAG,CAAC,KAAK,EAAE,EAAA;;gBAApC,KAAmB,SAAiB,EAAlC,OAAO,aAAA,EAAE,GAAG,SAAA;gBAClB,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAA;gBAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,CAAA;gBAExB,IAAI,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBAC7D,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,UAAO,CAAU;;;;gCACrC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gCACrC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gCACxC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;gCAC/B,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,oBAAW,CAAC,IAAI,CAAC,CAAA;gCAExC,qBAAM,GAAG,CAAC,MAAM,EAAE,EAAA;;gCAAlB,SAAkB,CAAA;gCAClB,qBAAM,IAAI,CAAC,MAAM,EAAE,EAAA;;gCAAnB,SAAmB,CAAA;;;;qBACtB,CAAC,CAAC;gBAEH,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;gBACF,qBAAM,IAAI,CAAC,KAAK,EAAE,EAAA;;gBAA1B,GAAG,GAAK,CAAA,SAAkB,CAAA,QAAvB;gBAClB,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAA;gBAED,qBAAM,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,aAAO,CAAC,OAAO,CAAC,CAAC,EAAA;;gBAA3E,KAAmB,SAAwD,EAAzE,MAAM,YAAA,EAAE,IAAI,UAAA;gBAClB,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBACtC,MAAM,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;gBACtD,MAAM,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;gBACrD,qBAAM,WAAK,CAAC,CAAC,CAAC,EAAA;;gBAAd,SAAc,CAAA;gBACd,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;;;;KACvC,CAAC,CAAA;AAEF,IAAI,CAAC,SAAS,EAAE;;;;;gBAEN,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;gBAChB,GAAG,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBAChE,GAAG,CAAC,gBAAgB,CAAC,UAAO,EAAmB;;;;qBAE9C,CAAC,CAAA;gBACqB,qBAAM,GAAG,CAAC,KAAK,EAAE,EAAA;;gBAApC,KAAmB,SAAiB,EAAlC,OAAO,aAAA,EAAE,GAAG,SAAA;gBAClB,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAA;gBAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,CAAA;gBAGI,qBAAM,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,aAAO,CAAC,OAAO,CAAC,CAAC,EAAA;;gBAA/E,KAA4B,SAAmD,EAA7E,MAAM,YAAA,EAAE,IAAI,UAAA,EAAO,EAAE,SAAA;gBAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBACtC,IAAI,EAAE,EAAE;oBACJ,qBAAG,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,CAAA;iBAC/B;gBACD,MAAM,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;gBACtD,MAAM,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;gBAEjD,IAAI,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBAC7D,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,UAAO,EAAmB;;;;;gCACnC,KAAK,GAAG,EAAE,CAAC,SAAS,EAAE,CAAA;gCAC1B,qBAAG,CAAC,IAAI,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAA;gCAE5C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAA;gCAC9C,qBAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;gCACvB,qBAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAA;;gCAArC,IAAI,GAAG,SAA8B;gCACzC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAA;gCAC7C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;gCACrC,aAAa;gCACb,qBAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;gCACnB,qBAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAA;;gCAArC,IAAI,GAAG,SAA8B,CAAA;gCACrC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;gCACrC,qBAAM,GAAG,CAAC,MAAM,EAAE,EAAA;;gCAAlB,SAAkB,CAAA;gCAClB,qBAAM,IAAI,CAAC,MAAM,EAAE,EAAA;;gCAAnB,SAAmB,CAAA;;;;qBACtB,CAAC,CAAC;gBACH,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;gBACF,qBAAM,IAAI,CAAC,KAAK,EAAE,EAAA;;gBAA1B,GAAG,GAAK,CAAA,SAAkB,CAAA,QAAvB;gBAClB,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAA;gBACxB,MAAM,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;gBAC7B,qBAAM,WAAK,CAAC,CAAC,CAAC,EAAA;;gBAAd,SAAc,CAAA;;;;KACjB,CAAC,CAAA;AAEF,IAAI,CAAC,OAAO,EAAE;;;;;;gBAEJ,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;gBAChB,GAAG,GAAG,IAAI,eAAS,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;gBACzC,qBAAM,GAAG,CAAC,KAAK,EAAE,EAAA;;gBAApC,KAAmB,SAAiB,EAAlC,OAAO,aAAA,EAAE,GAAG,SAAA;gBAClB,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAA;gBAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,CAAA;gBAEjB,qBAAM,GAAG,CAAC,WAAW,CAAC;wBAC7B,IAAI,EAAE,WAAW;wBACjB,MAAM,EAAE,EAAE;wBACV,YAAY,EAAE,MAAM;wBACpB,OAAO,EAAE,CAAC,OAAO,CAAC;qBACrB,CAAC,EAAA;;gBALE,IAAI,GAAG,SAKT;gBACF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBAC3C,MAAM,CAAC,MAAA,IAAI,CAAC,IAAI,0CAAE,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;gBAErC,OAAO,GAAG,CAAA,MAAA,IAAI,CAAC,IAAI,0CAAE,OAAO,KAAE,EAAE,CAAA;gBACxB,qBAAM,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,SAAA,EAAE,CAAC,EAAA;;gBAAvC,KAAK,GAAG,SAA+B;gBAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBAC5C,MAAM,CAAC,MAAA,KAAK,CAAC,IAAI,0CAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;gBAEjC,qBAAM,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,SAAA,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAA;;gBAA1D,KAAK,GAAG,SAAkD;gBAC9D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBAEhC,qBAAM,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,SAAA,EAAE,CAAC,EAAA;;gBAAvC,KAAK,GAAG,SAA+B;gBAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBAC5C,MAAM,CAAC,MAAA,KAAK,CAAC,IAAI,0CAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;gBAC7C,qBAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAEH,qBAAM,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,SAAA,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAA;;gBAA1D,KAAK,GAAG,SAAkD;gBAC9D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBAEhC,qBAAM,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,SAAA,EAAE,CAAC,EAAA;;gBAAvC,KAAK,GAAG,SAA+B;gBAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAM,CAAC,OAAO,CAAC,CAAA;gBAC5C,MAAM,CAAC,MAAA,KAAK,CAAC,IAAI,0CAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;gBAE7C,qBAAM,GAAG,CAAC,MAAM,EAAE,EAAA;;gBAAlB,SAAkB,CAAA;;;;KACrB,CAAC,CAAA"} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /sdk/proto/common.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/proto/common.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /sdk/sdk.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | var __generator = (this && this.__generator) || function (thisArg, body) { 12 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 13 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 14 | function verb(n) { return function (v) { return step([n, v]); }; } 15 | function step(op) { 16 | if (f) throw new TypeError("Generator is already executing."); 17 | while (_) try { 18 | 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; 19 | if (y = 0, t) op = [op[0] & 2, t.value]; 20 | switch (op[0]) { 21 | case 0: case 1: t = op; break; 22 | case 4: _.label++; return { value: op[1], done: false }; 23 | case 5: _.label++; y = op[1]; op = [0]; continue; 24 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 25 | default: 26 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 27 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 28 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 29 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 30 | if (t[2]) _.ops.pop(); 31 | _.trys.pop(); continue; 32 | } 33 | op = body.call(thisArg, _); 34 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 35 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 36 | } 37 | }; 38 | var __importDefault = (this && this.__importDefault) || function (mod) { 39 | return (mod && mod.__esModule) ? mod : { "default": mod }; 40 | }; 41 | Object.defineProperty(exports, "__esModule", { value: true }); 42 | var sdk_1 = require("./sdk"); 43 | var loglevel_es_1 = __importDefault(require("loglevel-es")); 44 | var login_1 = require("./login"); 45 | var common_1 = require("./proto/common"); 46 | var packet_1 = require("./packet"); 47 | var long_1 = __importDefault(require("long")); 48 | require("jest-localstorage-mock"); 49 | loglevel_es_1.default.setLevel("info"); 50 | jest.setTimeout(30 * 1000); 51 | // https://jestjs.io/docs/cli 52 | //三个测试账号 test1 ,test2 ,test3 53 | var tokens = [ 54 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MSIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDQ4Nn0.YsjY42O9A1hIZaxgbgyUXjQul2RBmwFiAufdlZe3boo", 55 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MiIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDUxNX0.LnlacfRur79dyVnFAoYiGXTSwSiO__hHVnVm8B2f-IY", 56 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2MiOiJ0ZXN0MyIsImFwcCI6ImtpbSIsImV4cCI6MTY2MDYzNDYwOX0.VsBg31LfmgFwfbgHmHWK8u72PI4elAoz3K9p3oKq6EI", 57 | ]; 58 | var gatewayURL = "ws://119.3.4.216:8000"; 59 | test('doLogin', function () { return __awaiter(void 0, void 0, void 0, function () { 60 | var tags, _a, success, channelId, account, conn; 61 | return __generator(this, function (_b) { 62 | switch (_b.label) { 63 | case 0: 64 | tags = ["web"]; 65 | return [4 /*yield*/, login_1.doLogin(gatewayURL, { token: tokens[0], tags: tags })]; 66 | case 1: 67 | _a = _b.sent(), success = _a.success, channelId = _a.channelId, account = _a.account, conn = _a.conn; 68 | expect(success).toBeTruthy(); 69 | loglevel_es_1.default.info(account, channelId); 70 | expect(channelId).toContain("test1"); 71 | expect(account).toEqual("test1"); 72 | conn.onclose = function () { 73 | loglevel_es_1.default.info("closed"); 74 | }; 75 | conn.close(); 76 | return [2 /*return*/]; 77 | } 78 | }); 79 | }); }); 80 | test('doLoginfail', function () { return __awaiter(void 0, void 0, void 0, function () { 81 | var tags, _a, success, err; 82 | return __generator(this, function (_b) { 83 | switch (_b.label) { 84 | case 0: 85 | tags = ["web"]; 86 | return [4 /*yield*/, login_1.doLogin(gatewayURL, { token: "", tags: tags })]; 87 | case 1: 88 | _a = _b.sent(), success = _a.success, err = _a.err; 89 | expect(success).toBeFalsy(); 90 | loglevel_es_1.default.error(err); 91 | return [2 /*return*/]; 92 | } 93 | }); 94 | }); }); 95 | test('store', function () { return __awaiter(void 0, void 0, void 0, function () { 96 | var ok, msg, id; 97 | return __generator(this, function (_a) { 98 | switch (_a.label) { 99 | case 0: return [4 /*yield*/, sdk_1.Store.insert(new sdk_1.Message(long_1.default.fromNumber(1), long_1.default.fromNumber(1)))]; 100 | case 1: 101 | ok = _a.sent(); 102 | expect(ok).toBeTruthy(); 103 | return [4 /*yield*/, sdk_1.Store.get(long_1.default.fromNumber(1))]; 104 | case 2: 105 | msg = _a.sent(); 106 | expect(msg === null || msg === void 0 ? void 0 : msg.messageId).toEqual(long_1.default.fromNumber(1)); 107 | loglevel_es_1.default.info(msg); 108 | return [4 /*yield*/, sdk_1.Store.setAck(long_1.default.fromNumber(1))]; 109 | case 3: 110 | _a.sent(); 111 | return [4 /*yield*/, sdk_1.Store.lastId()]; 112 | case 4: 113 | id = _a.sent(); 114 | loglevel_es_1.default.info("id - ", id); 115 | expect(id).toEqual(long_1.default.fromNumber(1)); 116 | return [2 /*return*/]; 117 | } 118 | }); 119 | }); }); 120 | test('clilogin', function () { return __awaiter(void 0, void 0, void 0, function () { 121 | var tags, cli, _a, success, err, callback; 122 | return __generator(this, function (_b) { 123 | switch (_b.label) { 124 | case 0: 125 | tags = ["web"]; 126 | cli = new sdk_1.KIMClient(gatewayURL, { token: tokens[0], tags: tags }); 127 | return [4 /*yield*/, cli.login()]; 128 | case 1: 129 | _a = _b.sent(), success = _a.success, err = _a.err; 130 | expect(success).toBeTruthy(); 131 | callback = jest.fn(function (evt) { 132 | loglevel_es_1.default.info("--------", evt); 133 | }); 134 | cli.register([sdk_1.KIMEvent.Closed], callback); 135 | expect(cli.account).toEqual("test1"); 136 | return [4 /*yield*/, cli.logout()]; 137 | case 2: 138 | _b.sent(); 139 | return [4 /*yield*/, sdk_1.sleep(2) 140 | // Closed回调方法必须被调用一次 141 | ]; 142 | case 3: 143 | _b.sent(); 144 | // Closed回调方法必须被调用一次 145 | expect(callback).toBeCalledTimes(1); 146 | return [2 /*return*/]; 147 | } 148 | }); 149 | }); }); 150 | test('dokickout', function () { return __awaiter(void 0, void 0, void 0, function () { 151 | var tags, cli, _a, success, err; 152 | return __generator(this, function (_b) { 153 | switch (_b.label) { 154 | case 0: 155 | tags = ["web"]; 156 | cli = new sdk_1.KIMClient(gatewayURL, { token: tokens[0], tags: tags }); 157 | return [4 /*yield*/, cli.login()]; 158 | case 1: 159 | _a = _b.sent(), success = _a.success, err = _a.err; 160 | expect(success).toBeTruthy(); 161 | cli.register([sdk_1.KIMEvent.Kickout], function (evt) { 162 | loglevel_es_1.default.info("--------", evt); 163 | expect(evt).toEqual(sdk_1.KIMEvent.Kickout); 164 | }); 165 | cli = new sdk_1.KIMClient(gatewayURL, { token: tokens[0], tags: tags }); 166 | return [4 /*yield*/, cli.login()]; 167 | case 2: 168 | _b.sent(); 169 | return [4 /*yield*/, sdk_1.sleep(1)]; 170 | case 3: 171 | _b.sent(); 172 | return [4 /*yield*/, cli.logout()]; 173 | case 4: 174 | _b.sent(); 175 | return [2 /*return*/]; 176 | } 177 | }); 178 | }); }); 179 | test('usertalk', function () { return __awaiter(void 0, void 0, void 0, function () { 180 | var tags, cli, _a, success, err, cli2, onmessage, suc, _b, status, resp; 181 | return __generator(this, function (_c) { 182 | switch (_c.label) { 183 | case 0: 184 | tags = ["web"]; 185 | cli = new sdk_1.KIMClient(gatewayURL, { token: tokens[0], tags: tags }); 186 | return [4 /*yield*/, cli.login()]; 187 | case 1: 188 | _a = _c.sent(), success = _a.success, err = _a.err; 189 | expect(err).toBeUndefined(); 190 | expect(success).toBeTruthy(); 191 | cli2 = new sdk_1.KIMClient(gatewayURL, { token: tokens[1], tags: tags }); 192 | onmessage = jest.fn(function (m) { return __awaiter(void 0, void 0, void 0, function () { 193 | return __generator(this, function (_a) { 194 | switch (_a.label) { 195 | case 0: 196 | expect(m.sender).toEqual(cli.account); 197 | expect(m.receiver).toEqual(cli2.account); 198 | expect(m.body).toEqual("hello"); 199 | expect(m.type).toEqual(packet_1.MessageType.Text); 200 | return [4 /*yield*/, cli.logout()]; 201 | case 1: 202 | _a.sent(); 203 | return [4 /*yield*/, cli2.logout()]; 204 | case 2: 205 | _a.sent(); 206 | return [2 /*return*/]; 207 | } 208 | }); 209 | }); }); 210 | cli2.onmessage(onmessage); 211 | return [4 /*yield*/, cli2.login()]; 212 | case 2: 213 | suc = (_c.sent()).success; 214 | expect(suc).toBeTruthy(); 215 | return [4 /*yield*/, cli.talkToUser(cli2.account, new sdk_1.Content("hello"))]; 216 | case 3: 217 | _b = _c.sent(), status = _b.status, resp = _b.resp; 218 | expect(status).toEqual(common_1.Status.Success); 219 | expect(resp === null || resp === void 0 ? void 0 : resp.messageId.greaterThan(1000)).toBeTruthy(); 220 | expect(resp === null || resp === void 0 ? void 0 : resp.sendTime.greaterThan(1000)).toBeTruthy(); 221 | return [4 /*yield*/, sdk_1.sleep(1)]; 222 | case 4: 223 | _c.sent(); 224 | expect(onmessage).toBeCalledTimes(1); 225 | return [2 /*return*/]; 226 | } 227 | }); 228 | }); }); 229 | test('offline', function () { return __awaiter(void 0, void 0, void 0, function () { 230 | var tags, cli, _a, success, err, _b, status, resp, er, cli2, cb, suc; 231 | return __generator(this, function (_c) { 232 | switch (_c.label) { 233 | case 0: 234 | tags = ["web"]; 235 | cli = new sdk_1.KIMClient(gatewayURL, { token: tokens[0], tags: tags }); 236 | cli.onofflinemessage(function (om) { return __awaiter(void 0, void 0, void 0, function () { 237 | return __generator(this, function (_a) { 238 | return [2 /*return*/]; 239 | }); 240 | }); }); 241 | return [4 /*yield*/, cli.login()]; 242 | case 1: 243 | _a = _c.sent(), success = _a.success, err = _a.err; 244 | expect(err).toBeUndefined(); 245 | expect(success).toBeTruthy(); 246 | return [4 /*yield*/, cli.talkToUser("test2", new sdk_1.Content("hello"))]; 247 | case 2: 248 | _b = _c.sent(), status = _b.status, resp = _b.resp, er = _b.err; 249 | expect(status).toEqual(common_1.Status.Success); 250 | if (er) { 251 | loglevel_es_1.default.error("---", er.message); 252 | } 253 | expect(resp === null || resp === void 0 ? void 0 : resp.messageId.greaterThan(1000)).toBeTruthy(); 254 | expect(resp === null || resp === void 0 ? void 0 : resp.sendTime.greaterThan(1000)).toBeTruthy(); 255 | cli2 = new sdk_1.KIMClient(gatewayURL, { token: tokens[1], tags: tags }); 256 | cb = jest.fn(function (om) { return __awaiter(void 0, void 0, void 0, function () { 257 | var users, msgs; 258 | return __generator(this, function (_a) { 259 | switch (_a.label) { 260 | case 0: 261 | users = om.listUsers(); 262 | loglevel_es_1.default.info("onofflinemessage -- load ", users); 263 | expect(users.length).toBeGreaterThanOrEqual(1); 264 | loglevel_es_1.default.info("--- lazy load messages"); 265 | return [4 /*yield*/, om.loadUser(users[0], 1)]; 266 | case 1: 267 | msgs = _a.sent(); 268 | expect(msgs.length).toBeGreaterThanOrEqual(1); 269 | expect(msgs[0].body).toEqual("hello"); 270 | // load again 271 | loglevel_es_1.default.info("--- load again"); 272 | return [4 /*yield*/, om.loadUser(users[0], 1)]; 273 | case 2: 274 | msgs = _a.sent(); 275 | expect(msgs[0].body).toEqual("hello"); 276 | return [4 /*yield*/, cli.logout()]; 277 | case 3: 278 | _a.sent(); 279 | return [4 /*yield*/, cli2.logout()]; 280 | case 4: 281 | _a.sent(); 282 | return [2 /*return*/]; 283 | } 284 | }); 285 | }); }); 286 | cli2.onofflinemessage(cb); 287 | return [4 /*yield*/, cli2.login()]; 288 | case 3: 289 | suc = (_c.sent()).success; 290 | expect(suc).toBeTruthy(); 291 | expect(cb).toBeCalledTimes(1); 292 | return [4 /*yield*/, sdk_1.sleep(3)]; 293 | case 4: 294 | _c.sent(); 295 | return [2 /*return*/]; 296 | } 297 | }); 298 | }); }); 299 | test('group', function () { return __awaiter(void 0, void 0, void 0, function () { 300 | var tags, cli, _a, success, err, resp, groupId, resp2, resp3, resp4, resp5, resp6; 301 | var _b, _c, _d, _e, _f; 302 | return __generator(this, function (_g) { 303 | switch (_g.label) { 304 | case 0: 305 | tags = ["web"]; 306 | cli = new sdk_1.KIMClient(gatewayURL, { token: tokens[0], tags: tags }); 307 | return [4 /*yield*/, cli.login()]; 308 | case 1: 309 | _a = _g.sent(), success = _a.success, err = _a.err; 310 | expect(err).toBeUndefined(); 311 | expect(success).toBeTruthy(); 312 | return [4 /*yield*/, cli.createGroup({ 313 | name: "group_sdk", 314 | avatar: "", 315 | introduction: "test", 316 | members: ["test2"], 317 | })]; 318 | case 2: 319 | resp = _g.sent(); 320 | expect(resp.status).toEqual(common_1.Status.Success); 321 | expect((_b = resp.resp) === null || _b === void 0 ? void 0 : _b.groupId).not.toBeNull(); 322 | groupId = ((_c = resp.resp) === null || _c === void 0 ? void 0 : _c.groupId) || ""; 323 | return [4 /*yield*/, cli.GetGroup({ groupId: groupId })]; 324 | case 3: 325 | resp2 = _g.sent(); 326 | expect(resp2.status).toEqual(common_1.Status.Success); 327 | expect((_d = resp2.resp) === null || _d === void 0 ? void 0 : _d.members.length).toEqual(2); 328 | return [4 /*yield*/, cli.joinGroup({ groupId: groupId, account: "test3" })]; 329 | case 4: 330 | resp3 = _g.sent(); 331 | expect(resp3.status).toEqual(common_1.Status.Success); 332 | return [4 /*yield*/, cli.GetGroup({ groupId: groupId })]; 333 | case 5: 334 | resp4 = _g.sent(); 335 | expect(resp4.status).toEqual(common_1.Status.Success); 336 | expect((_e = resp4.resp) === null || _e === void 0 ? void 0 : _e.members.length).toEqual(3); 337 | loglevel_es_1.default.info(resp4); 338 | return [4 /*yield*/, cli.quitGroup({ groupId: groupId, account: "test3" })]; 339 | case 6: 340 | resp5 = _g.sent(); 341 | expect(resp5.status).toEqual(common_1.Status.Success); 342 | return [4 /*yield*/, cli.GetGroup({ groupId: groupId })]; 343 | case 7: 344 | resp6 = _g.sent(); 345 | expect(resp6.status).toEqual(common_1.Status.Success); 346 | expect((_f = resp6.resp) === null || _f === void 0 ? void 0 : _f.members.length).toEqual(2); 347 | return [4 /*yield*/, cli.logout()]; 348 | case 8: 349 | _g.sent(); 350 | return [2 /*return*/]; 351 | } 352 | }); 353 | }); }); 354 | //# sourceMappingURL=sdk.test.js.map -------------------------------------------------------------------------------- /src/proto/common.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Long from "long"; 3 | import _m0 from "protobufjs/minimal"; 4 | 5 | export const protobufPackage = "pkt"; 6 | 7 | /** status is a uint16 value */ 8 | export enum Status { 9 | /** Success - client defined */ 10 | Success = 0, 11 | /** NoDestination - client error 100-200 */ 12 | NoDestination = 100, 13 | InvalidPacketBody = 101, 14 | InvalidCommand = 103, 15 | Unauthorized = 105, 16 | /** SystemException - server error 300-400 */ 17 | SystemException = 300, 18 | NotImplemented = 301, 19 | /** SessionNotFound - specific error */ 20 | SessionNotFound = 404, 21 | UNRECOGNIZED = -1, 22 | } 23 | 24 | export function statusFromJSON(object: any): Status { 25 | switch (object) { 26 | case 0: 27 | case "Success": 28 | return Status.Success; 29 | case 100: 30 | case "NoDestination": 31 | return Status.NoDestination; 32 | case 101: 33 | case "InvalidPacketBody": 34 | return Status.InvalidPacketBody; 35 | case 103: 36 | case "InvalidCommand": 37 | return Status.InvalidCommand; 38 | case 105: 39 | case "Unauthorized": 40 | return Status.Unauthorized; 41 | case 300: 42 | case "SystemException": 43 | return Status.SystemException; 44 | case 301: 45 | case "NotImplemented": 46 | return Status.NotImplemented; 47 | case 404: 48 | case "SessionNotFound": 49 | return Status.SessionNotFound; 50 | case -1: 51 | case "UNRECOGNIZED": 52 | default: 53 | return Status.UNRECOGNIZED; 54 | } 55 | } 56 | 57 | export function statusToJSON(object: Status): string { 58 | switch (object) { 59 | case Status.Success: 60 | return "Success"; 61 | case Status.NoDestination: 62 | return "NoDestination"; 63 | case Status.InvalidPacketBody: 64 | return "InvalidPacketBody"; 65 | case Status.InvalidCommand: 66 | return "InvalidCommand"; 67 | case Status.Unauthorized: 68 | return "Unauthorized"; 69 | case Status.SystemException: 70 | return "SystemException"; 71 | case Status.NotImplemented: 72 | return "NotImplemented"; 73 | case Status.SessionNotFound: 74 | return "SessionNotFound"; 75 | default: 76 | return "UNKNOWN"; 77 | } 78 | } 79 | 80 | export enum MetaType { 81 | int = 0, 82 | string = 1, 83 | float = 2, 84 | UNRECOGNIZED = -1, 85 | } 86 | 87 | export function metaTypeFromJSON(object: any): MetaType { 88 | switch (object) { 89 | case 0: 90 | case "int": 91 | return MetaType.int; 92 | case 1: 93 | case "string": 94 | return MetaType.string; 95 | case 2: 96 | case "float": 97 | return MetaType.float; 98 | case -1: 99 | case "UNRECOGNIZED": 100 | default: 101 | return MetaType.UNRECOGNIZED; 102 | } 103 | } 104 | 105 | export function metaTypeToJSON(object: MetaType): string { 106 | switch (object) { 107 | case MetaType.int: 108 | return "int"; 109 | case MetaType.string: 110 | return "string"; 111 | case MetaType.float: 112 | return "float"; 113 | default: 114 | return "UNKNOWN"; 115 | } 116 | } 117 | 118 | export enum ContentType { 119 | Protobuf = 0, 120 | Json = 1, 121 | UNRECOGNIZED = -1, 122 | } 123 | 124 | export function contentTypeFromJSON(object: any): ContentType { 125 | switch (object) { 126 | case 0: 127 | case "Protobuf": 128 | return ContentType.Protobuf; 129 | case 1: 130 | case "Json": 131 | return ContentType.Json; 132 | case -1: 133 | case "UNRECOGNIZED": 134 | default: 135 | return ContentType.UNRECOGNIZED; 136 | } 137 | } 138 | 139 | export function contentTypeToJSON(object: ContentType): string { 140 | switch (object) { 141 | case ContentType.Protobuf: 142 | return "Protobuf"; 143 | case ContentType.Json: 144 | return "Json"; 145 | default: 146 | return "UNKNOWN"; 147 | } 148 | } 149 | 150 | export enum Flag { 151 | Request = 0, 152 | Response = 1, 153 | Push = 2, 154 | UNRECOGNIZED = -1, 155 | } 156 | 157 | export function flagFromJSON(object: any): Flag { 158 | switch (object) { 159 | case 0: 160 | case "Request": 161 | return Flag.Request; 162 | case 1: 163 | case "Response": 164 | return Flag.Response; 165 | case 2: 166 | case "Push": 167 | return Flag.Push; 168 | case -1: 169 | case "UNRECOGNIZED": 170 | default: 171 | return Flag.UNRECOGNIZED; 172 | } 173 | } 174 | 175 | export function flagToJSON(object: Flag): string { 176 | switch (object) { 177 | case Flag.Request: 178 | return "Request"; 179 | case Flag.Response: 180 | return "Response"; 181 | case Flag.Push: 182 | return "Push"; 183 | default: 184 | return "UNKNOWN"; 185 | } 186 | } 187 | 188 | export interface Meta { 189 | key: string; 190 | value: string; 191 | type: MetaType; 192 | } 193 | 194 | export interface Header { 195 | command: string; 196 | /** sender channel id */ 197 | channelId: string; 198 | sequence: number; 199 | flag: Flag; 200 | status: Status; 201 | /** destination is defined as a account,group or room */ 202 | dest: string; 203 | meta: Meta[]; 204 | } 205 | 206 | export interface InnerHandshakeReq { 207 | ServiceId: string; 208 | } 209 | 210 | export interface InnerHandshakeResponse { 211 | Code: number; 212 | Error: string; 213 | } 214 | 215 | const baseMeta: object = { key: "", value: "", type: 0 }; 216 | 217 | export const Meta = { 218 | encode(message: Meta, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 219 | if (message.key !== "") { 220 | writer.uint32(10).string(message.key); 221 | } 222 | if (message.value !== "") { 223 | writer.uint32(18).string(message.value); 224 | } 225 | if (message.type !== 0) { 226 | writer.uint32(24).int32(message.type); 227 | } 228 | return writer; 229 | }, 230 | 231 | decode(input: _m0.Reader | Uint8Array, length?: number): Meta { 232 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 233 | let end = length === undefined ? reader.len : reader.pos + length; 234 | const message = { ...baseMeta } as Meta; 235 | while (reader.pos < end) { 236 | const tag = reader.uint32(); 237 | switch (tag >>> 3) { 238 | case 1: 239 | message.key = reader.string(); 240 | break; 241 | case 2: 242 | message.value = reader.string(); 243 | break; 244 | case 3: 245 | message.type = reader.int32() as any; 246 | break; 247 | default: 248 | reader.skipType(tag & 7); 249 | break; 250 | } 251 | } 252 | return message; 253 | }, 254 | 255 | fromJSON(object: any): Meta { 256 | const message = { ...baseMeta } as Meta; 257 | if (object.key !== undefined && object.key !== null) { 258 | message.key = String(object.key); 259 | } else { 260 | message.key = ""; 261 | } 262 | if (object.value !== undefined && object.value !== null) { 263 | message.value = String(object.value); 264 | } else { 265 | message.value = ""; 266 | } 267 | if (object.type !== undefined && object.type !== null) { 268 | message.type = metaTypeFromJSON(object.type); 269 | } else { 270 | message.type = 0; 271 | } 272 | return message; 273 | }, 274 | 275 | toJSON(message: Meta): unknown { 276 | const obj: any = {}; 277 | message.key !== undefined && (obj.key = message.key); 278 | message.value !== undefined && (obj.value = message.value); 279 | message.type !== undefined && (obj.type = metaTypeToJSON(message.type)); 280 | return obj; 281 | }, 282 | 283 | fromPartial(object: DeepPartial): Meta { 284 | const message = { ...baseMeta } as Meta; 285 | if (object.key !== undefined && object.key !== null) { 286 | message.key = object.key; 287 | } else { 288 | message.key = ""; 289 | } 290 | if (object.value !== undefined && object.value !== null) { 291 | message.value = object.value; 292 | } else { 293 | message.value = ""; 294 | } 295 | if (object.type !== undefined && object.type !== null) { 296 | message.type = object.type; 297 | } else { 298 | message.type = 0; 299 | } 300 | return message; 301 | }, 302 | }; 303 | 304 | const baseHeader: object = { 305 | command: "", 306 | channelId: "", 307 | sequence: 0, 308 | flag: 0, 309 | status: 0, 310 | dest: "", 311 | }; 312 | 313 | export const Header = { 314 | encode( 315 | message: Header, 316 | writer: _m0.Writer = _m0.Writer.create() 317 | ): _m0.Writer { 318 | if (message.command !== "") { 319 | writer.uint32(10).string(message.command); 320 | } 321 | if (message.channelId !== "") { 322 | writer.uint32(18).string(message.channelId); 323 | } 324 | if (message.sequence !== 0) { 325 | writer.uint32(24).uint32(message.sequence); 326 | } 327 | if (message.flag !== 0) { 328 | writer.uint32(32).int32(message.flag); 329 | } 330 | if (message.status !== 0) { 331 | writer.uint32(40).int32(message.status); 332 | } 333 | if (message.dest !== "") { 334 | writer.uint32(50).string(message.dest); 335 | } 336 | for (const v of message.meta) { 337 | Meta.encode(v!, writer.uint32(58).fork()).ldelim(); 338 | } 339 | return writer; 340 | }, 341 | 342 | decode(input: _m0.Reader | Uint8Array, length?: number): Header { 343 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 344 | let end = length === undefined ? reader.len : reader.pos + length; 345 | const message = { ...baseHeader } as Header; 346 | message.meta = []; 347 | while (reader.pos < end) { 348 | const tag = reader.uint32(); 349 | switch (tag >>> 3) { 350 | case 1: 351 | message.command = reader.string(); 352 | break; 353 | case 2: 354 | message.channelId = reader.string(); 355 | break; 356 | case 3: 357 | message.sequence = reader.uint32(); 358 | break; 359 | case 4: 360 | message.flag = reader.int32() as any; 361 | break; 362 | case 5: 363 | message.status = reader.int32() as any; 364 | break; 365 | case 6: 366 | message.dest = reader.string(); 367 | break; 368 | case 7: 369 | message.meta.push(Meta.decode(reader, reader.uint32())); 370 | break; 371 | default: 372 | reader.skipType(tag & 7); 373 | break; 374 | } 375 | } 376 | return message; 377 | }, 378 | 379 | fromJSON(object: any): Header { 380 | const message = { ...baseHeader } as Header; 381 | message.meta = []; 382 | if (object.command !== undefined && object.command !== null) { 383 | message.command = String(object.command); 384 | } else { 385 | message.command = ""; 386 | } 387 | if (object.channelId !== undefined && object.channelId !== null) { 388 | message.channelId = String(object.channelId); 389 | } else { 390 | message.channelId = ""; 391 | } 392 | if (object.sequence !== undefined && object.sequence !== null) { 393 | message.sequence = Number(object.sequence); 394 | } else { 395 | message.sequence = 0; 396 | } 397 | if (object.flag !== undefined && object.flag !== null) { 398 | message.flag = flagFromJSON(object.flag); 399 | } else { 400 | message.flag = 0; 401 | } 402 | if (object.status !== undefined && object.status !== null) { 403 | message.status = statusFromJSON(object.status); 404 | } else { 405 | message.status = 0; 406 | } 407 | if (object.dest !== undefined && object.dest !== null) { 408 | message.dest = String(object.dest); 409 | } else { 410 | message.dest = ""; 411 | } 412 | if (object.meta !== undefined && object.meta !== null) { 413 | for (const e of object.meta) { 414 | message.meta.push(Meta.fromJSON(e)); 415 | } 416 | } 417 | return message; 418 | }, 419 | 420 | toJSON(message: Header): unknown { 421 | const obj: any = {}; 422 | message.command !== undefined && (obj.command = message.command); 423 | message.channelId !== undefined && (obj.channelId = message.channelId); 424 | message.sequence !== undefined && (obj.sequence = message.sequence); 425 | message.flag !== undefined && (obj.flag = flagToJSON(message.flag)); 426 | message.status !== undefined && (obj.status = statusToJSON(message.status)); 427 | message.dest !== undefined && (obj.dest = message.dest); 428 | if (message.meta) { 429 | obj.meta = message.meta.map((e) => (e ? Meta.toJSON(e) : undefined)); 430 | } else { 431 | obj.meta = []; 432 | } 433 | return obj; 434 | }, 435 | 436 | fromPartial(object: DeepPartial
): Header { 437 | const message = { ...baseHeader } as Header; 438 | message.meta = []; 439 | if (object.command !== undefined && object.command !== null) { 440 | message.command = object.command; 441 | } else { 442 | message.command = ""; 443 | } 444 | if (object.channelId !== undefined && object.channelId !== null) { 445 | message.channelId = object.channelId; 446 | } else { 447 | message.channelId = ""; 448 | } 449 | if (object.sequence !== undefined && object.sequence !== null) { 450 | message.sequence = object.sequence; 451 | } else { 452 | message.sequence = 0; 453 | } 454 | if (object.flag !== undefined && object.flag !== null) { 455 | message.flag = object.flag; 456 | } else { 457 | message.flag = 0; 458 | } 459 | if (object.status !== undefined && object.status !== null) { 460 | message.status = object.status; 461 | } else { 462 | message.status = 0; 463 | } 464 | if (object.dest !== undefined && object.dest !== null) { 465 | message.dest = object.dest; 466 | } else { 467 | message.dest = ""; 468 | } 469 | if (object.meta !== undefined && object.meta !== null) { 470 | for (const e of object.meta) { 471 | message.meta.push(Meta.fromPartial(e)); 472 | } 473 | } 474 | return message; 475 | }, 476 | }; 477 | 478 | const baseInnerHandshakeReq: object = { ServiceId: "" }; 479 | 480 | export const InnerHandshakeReq = { 481 | encode( 482 | message: InnerHandshakeReq, 483 | writer: _m0.Writer = _m0.Writer.create() 484 | ): _m0.Writer { 485 | if (message.ServiceId !== "") { 486 | writer.uint32(10).string(message.ServiceId); 487 | } 488 | return writer; 489 | }, 490 | 491 | decode(input: _m0.Reader | Uint8Array, length?: number): InnerHandshakeReq { 492 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 493 | let end = length === undefined ? reader.len : reader.pos + length; 494 | const message = { ...baseInnerHandshakeReq } as InnerHandshakeReq; 495 | while (reader.pos < end) { 496 | const tag = reader.uint32(); 497 | switch (tag >>> 3) { 498 | case 1: 499 | message.ServiceId = reader.string(); 500 | break; 501 | default: 502 | reader.skipType(tag & 7); 503 | break; 504 | } 505 | } 506 | return message; 507 | }, 508 | 509 | fromJSON(object: any): InnerHandshakeReq { 510 | const message = { ...baseInnerHandshakeReq } as InnerHandshakeReq; 511 | if (object.ServiceId !== undefined && object.ServiceId !== null) { 512 | message.ServiceId = String(object.ServiceId); 513 | } else { 514 | message.ServiceId = ""; 515 | } 516 | return message; 517 | }, 518 | 519 | toJSON(message: InnerHandshakeReq): unknown { 520 | const obj: any = {}; 521 | message.ServiceId !== undefined && (obj.ServiceId = message.ServiceId); 522 | return obj; 523 | }, 524 | 525 | fromPartial(object: DeepPartial): InnerHandshakeReq { 526 | const message = { ...baseInnerHandshakeReq } as InnerHandshakeReq; 527 | if (object.ServiceId !== undefined && object.ServiceId !== null) { 528 | message.ServiceId = object.ServiceId; 529 | } else { 530 | message.ServiceId = ""; 531 | } 532 | return message; 533 | }, 534 | }; 535 | 536 | const baseInnerHandshakeResponse: object = { Code: 0, Error: "" }; 537 | 538 | export const InnerHandshakeResponse = { 539 | encode( 540 | message: InnerHandshakeResponse, 541 | writer: _m0.Writer = _m0.Writer.create() 542 | ): _m0.Writer { 543 | if (message.Code !== 0) { 544 | writer.uint32(8).uint32(message.Code); 545 | } 546 | if (message.Error !== "") { 547 | writer.uint32(18).string(message.Error); 548 | } 549 | return writer; 550 | }, 551 | 552 | decode( 553 | input: _m0.Reader | Uint8Array, 554 | length?: number 555 | ): InnerHandshakeResponse { 556 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 557 | let end = length === undefined ? reader.len : reader.pos + length; 558 | const message = { ...baseInnerHandshakeResponse } as InnerHandshakeResponse; 559 | while (reader.pos < end) { 560 | const tag = reader.uint32(); 561 | switch (tag >>> 3) { 562 | case 1: 563 | message.Code = reader.uint32(); 564 | break; 565 | case 2: 566 | message.Error = reader.string(); 567 | break; 568 | default: 569 | reader.skipType(tag & 7); 570 | break; 571 | } 572 | } 573 | return message; 574 | }, 575 | 576 | fromJSON(object: any): InnerHandshakeResponse { 577 | const message = { ...baseInnerHandshakeResponse } as InnerHandshakeResponse; 578 | if (object.Code !== undefined && object.Code !== null) { 579 | message.Code = Number(object.Code); 580 | } else { 581 | message.Code = 0; 582 | } 583 | if (object.Error !== undefined && object.Error !== null) { 584 | message.Error = String(object.Error); 585 | } else { 586 | message.Error = ""; 587 | } 588 | return message; 589 | }, 590 | 591 | toJSON(message: InnerHandshakeResponse): unknown { 592 | const obj: any = {}; 593 | message.Code !== undefined && (obj.Code = message.Code); 594 | message.Error !== undefined && (obj.Error = message.Error); 595 | return obj; 596 | }, 597 | 598 | fromPartial( 599 | object: DeepPartial 600 | ): InnerHandshakeResponse { 601 | const message = { ...baseInnerHandshakeResponse } as InnerHandshakeResponse; 602 | if (object.Code !== undefined && object.Code !== null) { 603 | message.Code = object.Code; 604 | } else { 605 | message.Code = 0; 606 | } 607 | if (object.Error !== undefined && object.Error !== null) { 608 | message.Error = object.Error; 609 | } else { 610 | message.Error = ""; 611 | } 612 | return message; 613 | }, 614 | }; 615 | 616 | type Builtin = 617 | | Date 618 | | Function 619 | | Uint8Array 620 | | string 621 | | number 622 | | boolean 623 | | undefined 624 | | Long; 625 | export type DeepPartial = T extends Builtin 626 | ? T 627 | : T extends Array 628 | ? Array> 629 | : T extends ReadonlyArray 630 | ? ReadonlyArray> 631 | : T extends {} 632 | ? { [K in keyof T]?: DeepPartial } 633 | : Partial; 634 | 635 | if (_m0.util.Long !== Long) { 636 | _m0.util.Long = Long as any; 637 | _m0.configure(); 638 | } 639 | -------------------------------------------------------------------------------- /sdk/sdk.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /sdk/proto/common.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __assign = (this && this.__assign) || function () { 3 | __assign = Object.assign || function(t) { 4 | for (var s, i = 1, n = arguments.length; i < n; i++) { 5 | s = arguments[i]; 6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) 7 | t[p] = s[p]; 8 | } 9 | return t; 10 | }; 11 | return __assign.apply(this, arguments); 12 | }; 13 | var __importDefault = (this && this.__importDefault) || function (mod) { 14 | return (mod && mod.__esModule) ? mod : { "default": mod }; 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | exports.InnerHandshakeResponse = exports.InnerHandshakeReq = exports.Header = exports.Meta = exports.flagToJSON = exports.flagFromJSON = exports.Flag = exports.contentTypeToJSON = exports.contentTypeFromJSON = exports.ContentType = exports.metaTypeToJSON = exports.metaTypeFromJSON = exports.MetaType = exports.statusToJSON = exports.statusFromJSON = exports.Status = exports.protobufPackage = void 0; 18 | /* eslint-disable */ 19 | var long_1 = __importDefault(require("long")); 20 | var minimal_1 = __importDefault(require("protobufjs/minimal")); 21 | exports.protobufPackage = "pkt"; 22 | /** status is a uint16 value */ 23 | var Status; 24 | (function (Status) { 25 | /** Success - client defined */ 26 | Status[Status["Success"] = 0] = "Success"; 27 | /** NoDestination - client error 100-200 */ 28 | Status[Status["NoDestination"] = 100] = "NoDestination"; 29 | Status[Status["InvalidPacketBody"] = 101] = "InvalidPacketBody"; 30 | Status[Status["InvalidCommand"] = 103] = "InvalidCommand"; 31 | Status[Status["Unauthorized"] = 105] = "Unauthorized"; 32 | /** SystemException - server error 300-400 */ 33 | Status[Status["SystemException"] = 300] = "SystemException"; 34 | Status[Status["NotImplemented"] = 301] = "NotImplemented"; 35 | /** SessionNotFound - specific error */ 36 | Status[Status["SessionNotFound"] = 404] = "SessionNotFound"; 37 | Status[Status["UNRECOGNIZED"] = -1] = "UNRECOGNIZED"; 38 | })(Status = exports.Status || (exports.Status = {})); 39 | function statusFromJSON(object) { 40 | switch (object) { 41 | case 0: 42 | case "Success": 43 | return Status.Success; 44 | case 100: 45 | case "NoDestination": 46 | return Status.NoDestination; 47 | case 101: 48 | case "InvalidPacketBody": 49 | return Status.InvalidPacketBody; 50 | case 103: 51 | case "InvalidCommand": 52 | return Status.InvalidCommand; 53 | case 105: 54 | case "Unauthorized": 55 | return Status.Unauthorized; 56 | case 300: 57 | case "SystemException": 58 | return Status.SystemException; 59 | case 301: 60 | case "NotImplemented": 61 | return Status.NotImplemented; 62 | case 404: 63 | case "SessionNotFound": 64 | return Status.SessionNotFound; 65 | case -1: 66 | case "UNRECOGNIZED": 67 | default: 68 | return Status.UNRECOGNIZED; 69 | } 70 | } 71 | exports.statusFromJSON = statusFromJSON; 72 | function statusToJSON(object) { 73 | switch (object) { 74 | case Status.Success: 75 | return "Success"; 76 | case Status.NoDestination: 77 | return "NoDestination"; 78 | case Status.InvalidPacketBody: 79 | return "InvalidPacketBody"; 80 | case Status.InvalidCommand: 81 | return "InvalidCommand"; 82 | case Status.Unauthorized: 83 | return "Unauthorized"; 84 | case Status.SystemException: 85 | return "SystemException"; 86 | case Status.NotImplemented: 87 | return "NotImplemented"; 88 | case Status.SessionNotFound: 89 | return "SessionNotFound"; 90 | default: 91 | return "UNKNOWN"; 92 | } 93 | } 94 | exports.statusToJSON = statusToJSON; 95 | var MetaType; 96 | (function (MetaType) { 97 | MetaType[MetaType["int"] = 0] = "int"; 98 | MetaType[MetaType["string"] = 1] = "string"; 99 | MetaType[MetaType["float"] = 2] = "float"; 100 | MetaType[MetaType["UNRECOGNIZED"] = -1] = "UNRECOGNIZED"; 101 | })(MetaType = exports.MetaType || (exports.MetaType = {})); 102 | function metaTypeFromJSON(object) { 103 | switch (object) { 104 | case 0: 105 | case "int": 106 | return MetaType.int; 107 | case 1: 108 | case "string": 109 | return MetaType.string; 110 | case 2: 111 | case "float": 112 | return MetaType.float; 113 | case -1: 114 | case "UNRECOGNIZED": 115 | default: 116 | return MetaType.UNRECOGNIZED; 117 | } 118 | } 119 | exports.metaTypeFromJSON = metaTypeFromJSON; 120 | function metaTypeToJSON(object) { 121 | switch (object) { 122 | case MetaType.int: 123 | return "int"; 124 | case MetaType.string: 125 | return "string"; 126 | case MetaType.float: 127 | return "float"; 128 | default: 129 | return "UNKNOWN"; 130 | } 131 | } 132 | exports.metaTypeToJSON = metaTypeToJSON; 133 | var ContentType; 134 | (function (ContentType) { 135 | ContentType[ContentType["Protobuf"] = 0] = "Protobuf"; 136 | ContentType[ContentType["Json"] = 1] = "Json"; 137 | ContentType[ContentType["UNRECOGNIZED"] = -1] = "UNRECOGNIZED"; 138 | })(ContentType = exports.ContentType || (exports.ContentType = {})); 139 | function contentTypeFromJSON(object) { 140 | switch (object) { 141 | case 0: 142 | case "Protobuf": 143 | return ContentType.Protobuf; 144 | case 1: 145 | case "Json": 146 | return ContentType.Json; 147 | case -1: 148 | case "UNRECOGNIZED": 149 | default: 150 | return ContentType.UNRECOGNIZED; 151 | } 152 | } 153 | exports.contentTypeFromJSON = contentTypeFromJSON; 154 | function contentTypeToJSON(object) { 155 | switch (object) { 156 | case ContentType.Protobuf: 157 | return "Protobuf"; 158 | case ContentType.Json: 159 | return "Json"; 160 | default: 161 | return "UNKNOWN"; 162 | } 163 | } 164 | exports.contentTypeToJSON = contentTypeToJSON; 165 | var Flag; 166 | (function (Flag) { 167 | Flag[Flag["Request"] = 0] = "Request"; 168 | Flag[Flag["Response"] = 1] = "Response"; 169 | Flag[Flag["Push"] = 2] = "Push"; 170 | Flag[Flag["UNRECOGNIZED"] = -1] = "UNRECOGNIZED"; 171 | })(Flag = exports.Flag || (exports.Flag = {})); 172 | function flagFromJSON(object) { 173 | switch (object) { 174 | case 0: 175 | case "Request": 176 | return Flag.Request; 177 | case 1: 178 | case "Response": 179 | return Flag.Response; 180 | case 2: 181 | case "Push": 182 | return Flag.Push; 183 | case -1: 184 | case "UNRECOGNIZED": 185 | default: 186 | return Flag.UNRECOGNIZED; 187 | } 188 | } 189 | exports.flagFromJSON = flagFromJSON; 190 | function flagToJSON(object) { 191 | switch (object) { 192 | case Flag.Request: 193 | return "Request"; 194 | case Flag.Response: 195 | return "Response"; 196 | case Flag.Push: 197 | return "Push"; 198 | default: 199 | return "UNKNOWN"; 200 | } 201 | } 202 | exports.flagToJSON = flagToJSON; 203 | var baseMeta = { key: "", value: "", type: 0 }; 204 | exports.Meta = { 205 | encode: function (message, writer) { 206 | if (writer === void 0) { writer = minimal_1.default.Writer.create(); } 207 | if (message.key !== "") { 208 | writer.uint32(10).string(message.key); 209 | } 210 | if (message.value !== "") { 211 | writer.uint32(18).string(message.value); 212 | } 213 | if (message.type !== 0) { 214 | writer.uint32(24).int32(message.type); 215 | } 216 | return writer; 217 | }, 218 | decode: function (input, length) { 219 | var reader = input instanceof minimal_1.default.Reader ? input : new minimal_1.default.Reader(input); 220 | var end = length === undefined ? reader.len : reader.pos + length; 221 | var message = __assign({}, baseMeta); 222 | while (reader.pos < end) { 223 | var tag = reader.uint32(); 224 | switch (tag >>> 3) { 225 | case 1: 226 | message.key = reader.string(); 227 | break; 228 | case 2: 229 | message.value = reader.string(); 230 | break; 231 | case 3: 232 | message.type = reader.int32(); 233 | break; 234 | default: 235 | reader.skipType(tag & 7); 236 | break; 237 | } 238 | } 239 | return message; 240 | }, 241 | fromJSON: function (object) { 242 | var message = __assign({}, baseMeta); 243 | if (object.key !== undefined && object.key !== null) { 244 | message.key = String(object.key); 245 | } 246 | else { 247 | message.key = ""; 248 | } 249 | if (object.value !== undefined && object.value !== null) { 250 | message.value = String(object.value); 251 | } 252 | else { 253 | message.value = ""; 254 | } 255 | if (object.type !== undefined && object.type !== null) { 256 | message.type = metaTypeFromJSON(object.type); 257 | } 258 | else { 259 | message.type = 0; 260 | } 261 | return message; 262 | }, 263 | toJSON: function (message) { 264 | var obj = {}; 265 | message.key !== undefined && (obj.key = message.key); 266 | message.value !== undefined && (obj.value = message.value); 267 | message.type !== undefined && (obj.type = metaTypeToJSON(message.type)); 268 | return obj; 269 | }, 270 | fromPartial: function (object) { 271 | var message = __assign({}, baseMeta); 272 | if (object.key !== undefined && object.key !== null) { 273 | message.key = object.key; 274 | } 275 | else { 276 | message.key = ""; 277 | } 278 | if (object.value !== undefined && object.value !== null) { 279 | message.value = object.value; 280 | } 281 | else { 282 | message.value = ""; 283 | } 284 | if (object.type !== undefined && object.type !== null) { 285 | message.type = object.type; 286 | } 287 | else { 288 | message.type = 0; 289 | } 290 | return message; 291 | }, 292 | }; 293 | var baseHeader = { 294 | command: "", 295 | channelId: "", 296 | sequence: 0, 297 | flag: 0, 298 | status: 0, 299 | dest: "", 300 | }; 301 | exports.Header = { 302 | encode: function (message, writer) { 303 | if (writer === void 0) { writer = minimal_1.default.Writer.create(); } 304 | if (message.command !== "") { 305 | writer.uint32(10).string(message.command); 306 | } 307 | if (message.channelId !== "") { 308 | writer.uint32(18).string(message.channelId); 309 | } 310 | if (message.sequence !== 0) { 311 | writer.uint32(24).uint32(message.sequence); 312 | } 313 | if (message.flag !== 0) { 314 | writer.uint32(32).int32(message.flag); 315 | } 316 | if (message.status !== 0) { 317 | writer.uint32(40).int32(message.status); 318 | } 319 | if (message.dest !== "") { 320 | writer.uint32(50).string(message.dest); 321 | } 322 | for (var _i = 0, _a = message.meta; _i < _a.length; _i++) { 323 | var v = _a[_i]; 324 | exports.Meta.encode(v, writer.uint32(58).fork()).ldelim(); 325 | } 326 | return writer; 327 | }, 328 | decode: function (input, length) { 329 | var reader = input instanceof minimal_1.default.Reader ? input : new minimal_1.default.Reader(input); 330 | var end = length === undefined ? reader.len : reader.pos + length; 331 | var message = __assign({}, baseHeader); 332 | message.meta = []; 333 | while (reader.pos < end) { 334 | var tag = reader.uint32(); 335 | switch (tag >>> 3) { 336 | case 1: 337 | message.command = reader.string(); 338 | break; 339 | case 2: 340 | message.channelId = reader.string(); 341 | break; 342 | case 3: 343 | message.sequence = reader.uint32(); 344 | break; 345 | case 4: 346 | message.flag = reader.int32(); 347 | break; 348 | case 5: 349 | message.status = reader.int32(); 350 | break; 351 | case 6: 352 | message.dest = reader.string(); 353 | break; 354 | case 7: 355 | message.meta.push(exports.Meta.decode(reader, reader.uint32())); 356 | break; 357 | default: 358 | reader.skipType(tag & 7); 359 | break; 360 | } 361 | } 362 | return message; 363 | }, 364 | fromJSON: function (object) { 365 | var message = __assign({}, baseHeader); 366 | message.meta = []; 367 | if (object.command !== undefined && object.command !== null) { 368 | message.command = String(object.command); 369 | } 370 | else { 371 | message.command = ""; 372 | } 373 | if (object.channelId !== undefined && object.channelId !== null) { 374 | message.channelId = String(object.channelId); 375 | } 376 | else { 377 | message.channelId = ""; 378 | } 379 | if (object.sequence !== undefined && object.sequence !== null) { 380 | message.sequence = Number(object.sequence); 381 | } 382 | else { 383 | message.sequence = 0; 384 | } 385 | if (object.flag !== undefined && object.flag !== null) { 386 | message.flag = flagFromJSON(object.flag); 387 | } 388 | else { 389 | message.flag = 0; 390 | } 391 | if (object.status !== undefined && object.status !== null) { 392 | message.status = statusFromJSON(object.status); 393 | } 394 | else { 395 | message.status = 0; 396 | } 397 | if (object.dest !== undefined && object.dest !== null) { 398 | message.dest = String(object.dest); 399 | } 400 | else { 401 | message.dest = ""; 402 | } 403 | if (object.meta !== undefined && object.meta !== null) { 404 | for (var _i = 0, _a = object.meta; _i < _a.length; _i++) { 405 | var e = _a[_i]; 406 | message.meta.push(exports.Meta.fromJSON(e)); 407 | } 408 | } 409 | return message; 410 | }, 411 | toJSON: function (message) { 412 | var obj = {}; 413 | message.command !== undefined && (obj.command = message.command); 414 | message.channelId !== undefined && (obj.channelId = message.channelId); 415 | message.sequence !== undefined && (obj.sequence = message.sequence); 416 | message.flag !== undefined && (obj.flag = flagToJSON(message.flag)); 417 | message.status !== undefined && (obj.status = statusToJSON(message.status)); 418 | message.dest !== undefined && (obj.dest = message.dest); 419 | if (message.meta) { 420 | obj.meta = message.meta.map(function (e) { return (e ? exports.Meta.toJSON(e) : undefined); }); 421 | } 422 | else { 423 | obj.meta = []; 424 | } 425 | return obj; 426 | }, 427 | fromPartial: function (object) { 428 | var message = __assign({}, baseHeader); 429 | message.meta = []; 430 | if (object.command !== undefined && object.command !== null) { 431 | message.command = object.command; 432 | } 433 | else { 434 | message.command = ""; 435 | } 436 | if (object.channelId !== undefined && object.channelId !== null) { 437 | message.channelId = object.channelId; 438 | } 439 | else { 440 | message.channelId = ""; 441 | } 442 | if (object.sequence !== undefined && object.sequence !== null) { 443 | message.sequence = object.sequence; 444 | } 445 | else { 446 | message.sequence = 0; 447 | } 448 | if (object.flag !== undefined && object.flag !== null) { 449 | message.flag = object.flag; 450 | } 451 | else { 452 | message.flag = 0; 453 | } 454 | if (object.status !== undefined && object.status !== null) { 455 | message.status = object.status; 456 | } 457 | else { 458 | message.status = 0; 459 | } 460 | if (object.dest !== undefined && object.dest !== null) { 461 | message.dest = object.dest; 462 | } 463 | else { 464 | message.dest = ""; 465 | } 466 | if (object.meta !== undefined && object.meta !== null) { 467 | for (var _i = 0, _a = object.meta; _i < _a.length; _i++) { 468 | var e = _a[_i]; 469 | message.meta.push(exports.Meta.fromPartial(e)); 470 | } 471 | } 472 | return message; 473 | }, 474 | }; 475 | var baseInnerHandshakeReq = { ServiceId: "" }; 476 | exports.InnerHandshakeReq = { 477 | encode: function (message, writer) { 478 | if (writer === void 0) { writer = minimal_1.default.Writer.create(); } 479 | if (message.ServiceId !== "") { 480 | writer.uint32(10).string(message.ServiceId); 481 | } 482 | return writer; 483 | }, 484 | decode: function (input, length) { 485 | var reader = input instanceof minimal_1.default.Reader ? input : new minimal_1.default.Reader(input); 486 | var end = length === undefined ? reader.len : reader.pos + length; 487 | var message = __assign({}, baseInnerHandshakeReq); 488 | while (reader.pos < end) { 489 | var tag = reader.uint32(); 490 | switch (tag >>> 3) { 491 | case 1: 492 | message.ServiceId = reader.string(); 493 | break; 494 | default: 495 | reader.skipType(tag & 7); 496 | break; 497 | } 498 | } 499 | return message; 500 | }, 501 | fromJSON: function (object) { 502 | var message = __assign({}, baseInnerHandshakeReq); 503 | if (object.ServiceId !== undefined && object.ServiceId !== null) { 504 | message.ServiceId = String(object.ServiceId); 505 | } 506 | else { 507 | message.ServiceId = ""; 508 | } 509 | return message; 510 | }, 511 | toJSON: function (message) { 512 | var obj = {}; 513 | message.ServiceId !== undefined && (obj.ServiceId = message.ServiceId); 514 | return obj; 515 | }, 516 | fromPartial: function (object) { 517 | var message = __assign({}, baseInnerHandshakeReq); 518 | if (object.ServiceId !== undefined && object.ServiceId !== null) { 519 | message.ServiceId = object.ServiceId; 520 | } 521 | else { 522 | message.ServiceId = ""; 523 | } 524 | return message; 525 | }, 526 | }; 527 | var baseInnerHandshakeResponse = { Code: 0, Error: "" }; 528 | exports.InnerHandshakeResponse = { 529 | encode: function (message, writer) { 530 | if (writer === void 0) { writer = minimal_1.default.Writer.create(); } 531 | if (message.Code !== 0) { 532 | writer.uint32(8).uint32(message.Code); 533 | } 534 | if (message.Error !== "") { 535 | writer.uint32(18).string(message.Error); 536 | } 537 | return writer; 538 | }, 539 | decode: function (input, length) { 540 | var reader = input instanceof minimal_1.default.Reader ? input : new minimal_1.default.Reader(input); 541 | var end = length === undefined ? reader.len : reader.pos + length; 542 | var message = __assign({}, baseInnerHandshakeResponse); 543 | while (reader.pos < end) { 544 | var tag = reader.uint32(); 545 | switch (tag >>> 3) { 546 | case 1: 547 | message.Code = reader.uint32(); 548 | break; 549 | case 2: 550 | message.Error = reader.string(); 551 | break; 552 | default: 553 | reader.skipType(tag & 7); 554 | break; 555 | } 556 | } 557 | return message; 558 | }, 559 | fromJSON: function (object) { 560 | var message = __assign({}, baseInnerHandshakeResponse); 561 | if (object.Code !== undefined && object.Code !== null) { 562 | message.Code = Number(object.Code); 563 | } 564 | else { 565 | message.Code = 0; 566 | } 567 | if (object.Error !== undefined && object.Error !== null) { 568 | message.Error = String(object.Error); 569 | } 570 | else { 571 | message.Error = ""; 572 | } 573 | return message; 574 | }, 575 | toJSON: function (message) { 576 | var obj = {}; 577 | message.Code !== undefined && (obj.Code = message.Code); 578 | message.Error !== undefined && (obj.Error = message.Error); 579 | return obj; 580 | }, 581 | fromPartial: function (object) { 582 | var message = __assign({}, baseInnerHandshakeResponse); 583 | if (object.Code !== undefined && object.Code !== null) { 584 | message.Code = object.Code; 585 | } 586 | else { 587 | message.Code = 0; 588 | } 589 | if (object.Error !== undefined && object.Error !== null) { 590 | message.Error = object.Error; 591 | } 592 | else { 593 | message.Error = ""; 594 | } 595 | return message; 596 | }, 597 | }; 598 | if (minimal_1.default.util.Long !== long_1.default) { 599 | minimal_1.default.util.Long = long_1.default; 600 | minimal_1.default.configure(); 601 | } 602 | //# sourceMappingURL=common.js.map -------------------------------------------------------------------------------- /src/sdk.ts: -------------------------------------------------------------------------------- 1 | import { w3cwebsocket, IMessageEvent, ICloseEvent } from 'websocket'; 2 | import { Buffer } from 'buffer'; 3 | import log from 'loglevel-es'; 4 | import { Command, LogicPkt, MagicBasicPktInt, MessageType, Ping } from './packet'; 5 | import { Flag, Status } from './proto/common'; 6 | import { LoginReq, LoginResp, MessageReq, MessageResp, MessagePush, GroupCreateResp, GroupGetResp, MessageIndexResp, MessageContentResp, ErrorResp, KickoutNotify, MessageAckReq, MessageIndexReq, MessageIndex, MessageContentReq, MessageContent, GroupCreateReq, GroupJoinReq, GroupQuitReq, GroupGetReq } from './proto/protocol'; 7 | import { doLogin, LoginBody } from './login'; 8 | import Long from 'long'; 9 | import localforage from 'localforage'; 10 | 11 | const heartbeatInterval = 55 * 1000 // seconds 12 | const sendTimeout = 5 * 1000 // 10 seconds 13 | 14 | enum TimeUnit { 15 | Second = 1000, 16 | Millisecond = 1, 17 | } 18 | 19 | export let sleep = async (second: number, Unit: TimeUnit = TimeUnit.Second): Promise => { 20 | return new Promise((resolve, _) => { 21 | setTimeout(() => { 22 | resolve() 23 | }, second * Unit) 24 | }) 25 | } 26 | 27 | export enum State { 28 | INIT, 29 | CONNECTING, 30 | CONNECTED, 31 | RECONNECTING, 32 | CLOSEING, 33 | CLOSED, 34 | } 35 | 36 | // 客户端自定义的状态码范围 [10, 100) 37 | export enum KIMStatus { 38 | RequestTimeout = 10, 39 | SendFailed = 11, 40 | } 41 | 42 | export enum KIMEvent { 43 | Reconnecting = "Reconnecting", //重连中 44 | Reconnected = "Reconnected", //重连成功 45 | Closed = "Closed", 46 | Kickout = "Kickout", // 被踢 47 | } 48 | 49 | export class Response { 50 | status: number 51 | dest?: string 52 | payload: Uint8Array 53 | constructor(status: number, dest?: string, payload: Uint8Array = new Uint8Array()) { 54 | this.status = status; 55 | this.dest = dest; 56 | this.payload = payload; 57 | } 58 | } 59 | 60 | export class Request { 61 | sendTime: number 62 | data: LogicPkt 63 | callback: (response: LogicPkt) => void 64 | constructor(data: LogicPkt, callback: (response: LogicPkt) => void) { 65 | this.sendTime = Date.now() 66 | this.data = data 67 | this.callback = callback 68 | } 69 | } 70 | 71 | const pageCount = 50 72 | 73 | export class OfflineMessages { 74 | private cli: KIMClient 75 | private groupmessages = new Map() 76 | private usermessages = new Map() 77 | constructor(cli: KIMClient, indexes: MessageIndex[]) { 78 | this.cli = cli 79 | // 通常离线消息的读取是从下向上,因此这里提前倒序下 80 | for (let index = indexes.length - 1; index >= 0; index--) { 81 | const idx = indexes[index]; 82 | let message = new Message(idx.messageId, idx.sendTime) 83 | if (idx.direction == 1) { 84 | message.sender = cli.account 85 | message.receiver = idx.accountB 86 | } else { 87 | message.sender = idx.accountB 88 | message.receiver = cli.account 89 | } 90 | 91 | if (!!idx.group) { 92 | if (!this.groupmessages.has(idx.group)) { 93 | this.groupmessages.set(idx.group, new Array()) 94 | } 95 | this.groupmessages.get(idx.group)?.push(message) 96 | } else { 97 | if (!this.usermessages.has(idx.accountB)) { 98 | this.usermessages.set(idx.accountB, new Array()) 99 | } 100 | this.usermessages.get(idx.accountB)?.push(message) 101 | } 102 | } 103 | } 104 | /** 105 | * 获取离线消息群列表 106 | */ 107 | listGroups(): Array { 108 | let arr = new Array() 109 | this.groupmessages.forEach((_, key) => { 110 | arr.push(key) 111 | }) 112 | return arr 113 | } 114 | /** 115 | * 获取离线消息用户列表 116 | */ 117 | listUsers(): Array { 118 | let arr = new Array() 119 | this.usermessages.forEach((_, key) => { 120 | arr.push(key) 121 | }) 122 | return arr 123 | } 124 | /** 125 | * lazy load group offline messages, the page count is 50 126 | * @param page page number, start from one 127 | */ 128 | async loadGroup(group: string, page: number): Promise { 129 | let messages = this.groupmessages.get(group) 130 | if (!messages) { 131 | return new Array(); 132 | } 133 | let msgs = await this.lazyLoad(messages, page); 134 | return msgs 135 | } 136 | async loadUser(account: string, page: number): Promise { 137 | let messages = this.usermessages.get(account) 138 | if (!messages) { 139 | return new Array(); 140 | } 141 | let msgs = await this.lazyLoad(messages, page); 142 | return msgs 143 | } 144 | /** 145 | * 获取指定群的离线消息数据 146 | * @param group 群ID 147 | */ 148 | getGroupMessagesCount(group: string): number { 149 | let messages = this.groupmessages.get(group) 150 | if (!messages) { 151 | return 0 152 | } 153 | return messages.length 154 | } 155 | /** 156 | * 获取指定用户的离线消息数量 157 | * @param account 用户 158 | */ 159 | getUserMessagesCount(account: string): number { 160 | let messages = this.usermessages.get(account) 161 | if (!messages) { 162 | return 0 163 | } 164 | return messages.length 165 | } 166 | private async lazyLoad(messages: Array, page: number): Promise> { 167 | let i = (page - 1) * pageCount 168 | let msgs = messages.slice(i, i + pageCount) 169 | log.debug(msgs) 170 | if (!msgs || msgs.length == 0) { 171 | return new Array(); 172 | } 173 | if (!!msgs[0].body) { 174 | return msgs 175 | } 176 | //load from server 177 | let { status, contents } = await this.loadcontent(msgs.map(idx => idx.messageId)) 178 | if (status != Status.Success) { 179 | return msgs 180 | } 181 | log.debug(`load content ${contents.map(c => c.body)}`) 182 | if (contents.length == msgs.length) { 183 | for (let index = 0; index < msgs.length; index++) { 184 | let msg = msgs[index]; 185 | let original = messages[i + index] 186 | let content = contents[index] 187 | Object.assign(msg, content) 188 | Object.assign(original, content) 189 | } 190 | } 191 | return msgs 192 | } 193 | private async loadcontent(messageIds: Long[]): Promise<{ status: number, contents: MessageContent[] }> { 194 | let req = MessageContentReq.encode({ messageIds }) 195 | let pkt = LogicPkt.build(Command.OfflineContent, "", req.finish()) 196 | let resp = await this.cli.request(pkt) 197 | if (resp.status != Status.Success) { 198 | let err = ErrorResp.decode(pkt.payload) 199 | log.error(err) 200 | return { status: resp.status, contents: new Array() } 201 | } 202 | log.info(resp) 203 | let respbody = MessageContentResp.decode(resp.payload) 204 | return { status: resp.status, contents: respbody.contents } 205 | } 206 | } 207 | 208 | export class Message { 209 | messageId: Long; 210 | type?: number; 211 | body?: string; 212 | extra?: string; 213 | sender?: string; 214 | receiver?: string; 215 | group?: string; 216 | sendTime: Long; 217 | arrivalTime: number; 218 | constructor(messageId: Long, sendTime: Long) { 219 | this.messageId = messageId 220 | this.sendTime = sendTime 221 | this.arrivalTime = Date.now() 222 | } 223 | } 224 | 225 | export class Content { 226 | type?: number; 227 | body: string; 228 | extra?: string; 229 | constructor(body: string, type: number = MessageType.Text, extra?: string) { 230 | this.type = type 231 | this.body = body 232 | this.extra = extra 233 | } 234 | } 235 | 236 | export class KIMClient { 237 | wsurl: string 238 | private req: LoginBody 239 | state = State.INIT 240 | channelId: string 241 | account: string 242 | private conn?: w3cwebsocket 243 | private lastRead: number 244 | private lastMessage?: Message 245 | private unack: number = 0 246 | private listeners = new Map void>() 247 | private messageCallback: (m: Message) => void 248 | private offmessageCallback: (m: OfflineMessages) => void 249 | private closeCallback?: () => void 250 | // 全双工请求队列 251 | private sendq = new Map() 252 | constructor(url: string, req: LoginBody) { 253 | this.wsurl = url 254 | this.req = req 255 | this.lastRead = Date.now() 256 | this.channelId = "" 257 | this.account = "" 258 | this.messageCallback = (m: Message) => { 259 | log.warn(`throw a message from ${m.sender} -- ${m.body}\nPlease check you had register a onmessage callback method before login`) 260 | } 261 | this.offmessageCallback = (m: OfflineMessages) => { 262 | log.warn(`throw OfflineMessages.\nPlease check you had register a onofflinemessage callback method before login`) 263 | } 264 | } 265 | register(events: string[], callback: (e: KIMEvent) => void) { 266 | // 注册事件到Client中。 267 | events.forEach((event) => { 268 | this.listeners.set(event, callback) 269 | }) 270 | } 271 | onmessage(cb: (m: Message) => void) { 272 | this.messageCallback = cb 273 | } 274 | onofflinemessage(cb: (m: OfflineMessages) => void) { 275 | this.offmessageCallback = cb 276 | } 277 | // 1、登录 278 | async login(): Promise<{ success: boolean, err?: Error }> { 279 | if (this.state == State.CONNECTED) { 280 | return { success: false, err: new Error("client has already been connected") } 281 | } 282 | this.state = State.CONNECTING 283 | let { success, err, channelId, account, conn } = await doLogin(this.wsurl, this.req) 284 | if (!success) { 285 | this.state = State.INIT 286 | return { success, err } 287 | } 288 | log.info("login - ", success) 289 | // overwrite onmessage 290 | conn.onmessage = (evt: IMessageEvent) => { 291 | try { 292 | // 重置lastRead 293 | this.lastRead = Date.now() 294 | let buf = Buffer.from(evt.data) 295 | let magic = buf.readInt32BE() 296 | if (magic == MagicBasicPktInt) {//目前只有心跳包pong 297 | log.debug(`recv a basic packet - ${buf.join(",")}`) 298 | return 299 | } 300 | let pkt = LogicPkt.from(buf) 301 | this.packetHandler(pkt) 302 | } catch (error) { 303 | log.error(evt.data, error) 304 | } 305 | } 306 | conn.onerror = (error) => { 307 | log.info("websocket error: ", error) 308 | this.errorHandler(error) 309 | } 310 | conn.onclose = (e: ICloseEvent) => { 311 | log.debug("event[onclose] fired") 312 | if (this.state == State.CLOSEING) { 313 | this.onclose("logout") 314 | return 315 | } 316 | this.errorHandler(new Error(e.reason)) 317 | } 318 | this.conn = conn 319 | this.channelId = channelId || "" 320 | this.account = account || "" 321 | await this.loadOfflineMessage() 322 | // success 323 | this.state = State.CONNECTED 324 | this.heartbeatLoop() 325 | this.readDeadlineLoop() 326 | this.messageAckLoop() 327 | return { success, err } 328 | } 329 | logout(): Promise { 330 | return new Promise((resolve, _) => { 331 | if (this.state === State.CLOSEING) { 332 | return 333 | } 334 | this.state = State.CLOSEING 335 | if (!this.conn) { 336 | return 337 | } 338 | let tr = setTimeout(() => { 339 | log.debug("oh no,logout is timeout~") 340 | this.onclose("logout") 341 | resolve() 342 | }, 1500) 343 | 344 | this.closeCallback = async () => { 345 | clearTimeout(tr) 346 | await sleep(1) 347 | resolve() 348 | } 349 | 350 | this.conn.close() 351 | log.info("Connection closing...") 352 | }) 353 | } 354 | /** 355 | * 给用户dest发送一条消息 356 | * @param dest 用户账号 357 | * @param req 请求的消息内容 358 | * @returns status KIMStatus|Status 359 | */ 360 | async talkToUser(dest: string, req: Content, retry: number = 3): Promise<{ status: number, resp?: MessageResp, err?: ErrorResp }> { 361 | return this.talk(Command.ChatUserTalk, dest, MessageReq.fromJSON(req), retry) 362 | } 363 | /** 364 | * 给群dest发送一条消息 365 | * @param dest 群ID 366 | * @param req 请求的消息内容 367 | * @returns status KIMStatus|Status 368 | */ 369 | async talkToGroup(dest: string, req: Content, retry: number = 3): Promise<{ status: number, resp?: MessageResp, err?: ErrorResp }> { 370 | return this.talk(Command.ChatGroupTalk, dest, MessageReq.fromJSON(req), retry) 371 | } 372 | async createGroup(req: { 373 | name: string; 374 | avatar?: string; 375 | introduction?: string; 376 | members: string[]; 377 | }): Promise<{ status: number, resp?: GroupCreateResp, err?: ErrorResp }> { 378 | let req2 = GroupCreateReq.fromJSON(req) 379 | req2.owner = this.account 380 | if (!req2.members.find(v => v == this.account)) { 381 | req2.members.push(this.account) 382 | } 383 | let pbreq = GroupCreateReq.encode(req2).finish() 384 | let pkt = LogicPkt.build(Command.GroupCreate, "", pbreq) 385 | let resp = await this.request(pkt) 386 | if (resp.status != Status.Success) { 387 | let err = ErrorResp.decode(resp.payload) 388 | return { status: resp.status, err: err } 389 | } 390 | return { status: Status.Success, resp: GroupCreateResp.decode(resp.payload) } 391 | } 392 | async joinGroup(req: GroupJoinReq): Promise<{ status: number, err?: ErrorResp }> { 393 | let pbreq = GroupJoinReq.encode(req).finish() 394 | let pkt = LogicPkt.build(Command.GroupJoin, "", pbreq) 395 | let resp = await this.request(pkt) 396 | if (resp.status != Status.Success) { 397 | let err = ErrorResp.decode(resp.payload) 398 | return { status: resp.status, err: err } 399 | } 400 | return { status: Status.Success } 401 | } 402 | async quitGroup(req: GroupQuitReq): Promise<{ status: number, err?: ErrorResp }> { 403 | let pbreq = GroupQuitReq.encode(req).finish() 404 | let pkt = LogicPkt.build(Command.GroupQuit, "", pbreq) 405 | let resp = await this.request(pkt) 406 | if (resp.status != Status.Success) { 407 | let err = ErrorResp.decode(resp.payload) 408 | return { status: resp.status, err: err } 409 | } 410 | return { status: Status.Success } 411 | } 412 | async GetGroup(req: GroupGetReq): Promise<{ status: number, resp?: GroupGetResp, err?: ErrorResp }> { 413 | let pbreq = GroupGetReq.encode(req).finish() 414 | let pkt = LogicPkt.build(Command.GroupDetail, "", pbreq) 415 | let resp = await this.request(pkt) 416 | if (resp.status != Status.Success) { 417 | let err = ErrorResp.decode(resp.payload) 418 | return { status: resp.status, err: err } 419 | } 420 | return { status: Status.Success, resp: GroupGetResp.decode(resp.payload) } 421 | } 422 | private async talk(command: string, dest: string, req: MessageReq, retry: number): Promise<{ status: number, resp?: MessageResp, err?: ErrorResp }> { 423 | let pbreq = MessageReq.encode(req).finish() 424 | for (let index = 0; index < retry + 1; index++) { 425 | let pkt = LogicPkt.build(command, dest, pbreq) 426 | let resp = await this.request(pkt) 427 | if (resp.status == Status.Success) { 428 | return { status: Status.Success, resp: MessageResp.decode(resp.payload) } 429 | } 430 | if (resp.status >= 300 && resp.status < 400) { 431 | // 消息重发 432 | log.warn("retry to send message") 433 | await sleep(2) 434 | continue 435 | } 436 | let err = ErrorResp.decode(resp.payload) 437 | return { status: resp.status, err: err } 438 | } 439 | return { status: KIMStatus.SendFailed, err: new Error("over max retry times") } 440 | } 441 | async request(data: LogicPkt): Promise { 442 | return new Promise((resolve, _) => { 443 | let seq = data.sequence 444 | 445 | let tr = setTimeout(() => { 446 | // remove from sendq 447 | this.sendq.delete(seq) 448 | resolve(new Response(KIMStatus.RequestTimeout)) 449 | }, sendTimeout) 450 | 451 | // asynchronous wait ack from server 452 | let callback = (pkt: LogicPkt) => { 453 | clearTimeout(tr) 454 | // remove from sendq 455 | this.sendq.delete(seq) 456 | resolve(new Response(pkt.status, pkt.dest, pkt.payload)) 457 | } 458 | log.debug(`request seq:${seq} command:${data.command}`) 459 | 460 | this.sendq.set(seq, new Request(data, callback)) 461 | if (!this.send(data.bytes())) { 462 | resolve(new Response(KIMStatus.SendFailed)) 463 | } 464 | }) 465 | } 466 | private fireEvent(event: KIMEvent) { 467 | let listener = this.listeners.get(event) 468 | if (!!listener) { 469 | listener(event) 470 | } 471 | } 472 | private async packetHandler(pkt: LogicPkt) { 473 | log.debug("received packet: ", pkt) 474 | if (pkt.status >= 400) { 475 | log.info(`need relogin due to status ${pkt.status}`) 476 | this.conn?.close() 477 | return 478 | } 479 | if (pkt.flag == Flag.Response) { 480 | let req = this.sendq.get(pkt.sequence) 481 | if (req) { 482 | req.callback(pkt) 483 | } else { 484 | log.error(`req of ${pkt.sequence} no found in sendq`) 485 | } 486 | return 487 | } 488 | switch (pkt.command) { 489 | case Command.ChatUserTalk: 490 | case Command.ChatGroupTalk: 491 | let push = MessagePush.decode(pkt.payload) 492 | let message = new Message(push.messageId, push.sendTime) 493 | Object.assign(message, push) 494 | message.receiver = this.account 495 | if (pkt.command == Command.ChatGroupTalk) { 496 | message.group = pkt.dest 497 | } 498 | if (!await Store.exist(message.messageId)) { 499 | // 确保状态处于CONNECTED,才能执行消息ACK 500 | if (this.state == State.CONNECTED) { 501 | this.lastMessage = message 502 | this.unack++ 503 | try { 504 | this.messageCallback(message) 505 | } catch (error) { 506 | log.error(error) 507 | } 508 | } 509 | // 消息保存到数据库中。 510 | await Store.insert(message) 511 | } 512 | break; 513 | case Command.SignIn: 514 | let ko = KickoutNotify.decode(pkt.payload) 515 | if (ko.channelId == this.channelId) { 516 | this.logout() 517 | this.fireEvent(KIMEvent.Kickout) 518 | } 519 | break; 520 | } 521 | } 522 | // 2、心跳 523 | private heartbeatLoop() { 524 | log.debug("heartbeatLoop start") 525 | let start = Date.now() 526 | let loop = () => { 527 | if (this.state != State.CONNECTED) { 528 | log.debug("heartbeatLoop exited") 529 | return 530 | } 531 | if (Date.now() - start >= heartbeatInterval) { 532 | log.debug(`>>> send ping ; state is ${this.state}`) 533 | start = Date.now() 534 | this.send(Ping) 535 | } 536 | setTimeout(loop, 500) 537 | } 538 | setTimeout(loop, 500) 539 | } 540 | // 3、读超时 541 | private readDeadlineLoop() { 542 | log.debug("deadlineLoop start") 543 | let loop = () => { 544 | if (this.state != State.CONNECTED) { 545 | log.debug("deadlineLoop exited") 546 | return 547 | } 548 | if ((Date.now() - this.lastRead) > 3 * heartbeatInterval) { 549 | // 如果超时就调用errorHandler处理 550 | this.errorHandler(new Error("read timeout")) 551 | } 552 | setTimeout(loop, 500) 553 | } 554 | setTimeout(loop, 500) 555 | } 556 | private messageAckLoop() { 557 | let start = Date.now() 558 | const delay = 500 //ms 559 | let loop = async () => { 560 | if (this.state != State.CONNECTED) { 561 | log.debug("messageAckLoop exited") 562 | return 563 | } 564 | let msg = this.lastMessage // lock this message 565 | if (!!msg && (Date.now() - start > 3000)) { 566 | let overflow = this.unack > 10 567 | this.unack = 0 // reset unack before ack 568 | this.lastMessage = undefined //reset last message 569 | 570 | let diff = Date.now() - msg.arrivalTime 571 | if (!overflow && diff < delay) { 572 | await sleep(delay - diff, TimeUnit.Millisecond) 573 | } 574 | let req = MessageAckReq.encode({ messageId: msg.messageId }) 575 | let pkt = LogicPkt.build(Command.ChatTalkAck, "", req.finish()) 576 | start = Date.now() 577 | this.send(pkt.bytes()) 578 | // 修改本地存储中最后一条ACK消息记录 579 | await Store.setAck(msg.messageId) 580 | } 581 | setTimeout(loop, 500) 582 | } 583 | setTimeout(loop, 500) 584 | } 585 | private async loadOfflineMessage() { 586 | log.debug("loadOfflineMessage start") 587 | // 1. 加载消息索引 588 | let loadIndex = async (messageId: Long = Long.ZERO): Promise<{ status: number, indexes?: MessageIndex[] }> => { 589 | let req = MessageIndexReq.encode({ messageId }) 590 | let pkt = LogicPkt.build(Command.OfflineIndex, "", req.finish()) 591 | let resp = await this.request(pkt) 592 | if (resp.status != Status.Success) { 593 | let err = ErrorResp.decode(pkt.payload) 594 | log.error(err) 595 | return { status: resp.status } 596 | } 597 | let respbody = MessageIndexResp.decode(resp.payload) 598 | return { status: resp.status, indexes: respbody.indexes } 599 | } 600 | let offmessages = new Array(); 601 | let messageId = await Store.lastId() 602 | while (true) { 603 | let { status, indexes } = await loadIndex(messageId) 604 | if (status != Status.Success) { 605 | break 606 | } 607 | if (!indexes || !indexes.length) { 608 | break 609 | } 610 | messageId = indexes[indexes.length - 1].messageId 611 | offmessages = offmessages.concat(indexes) 612 | } 613 | log.info(`load offline indexes - ${offmessages.map(msg => msg.messageId.toString())}`) 614 | let om = new OfflineMessages(this, offmessages) 615 | this.offmessageCallback(om) 616 | } 617 | // 表示连接中止 618 | private onclose(reason: string) { 619 | if (this.state == State.CLOSED) { 620 | return 621 | } 622 | this.state = State.CLOSED 623 | 624 | log.info("connection closed due to " + reason) 625 | this.conn = undefined 626 | this.channelId = "" 627 | this.account = "" 628 | // 通知上层应用 629 | this.fireEvent(KIMEvent.Closed) 630 | if (this.closeCallback) { 631 | this.closeCallback() 632 | } 633 | } 634 | // 4. 自动重连 635 | private async errorHandler(error: Error) { 636 | // 如果是主动断开连接,就没有必要自动重连 637 | // 比如收到被踢,或者主动调用logout()方法 638 | if (this.state == State.CLOSED || this.state == State.CLOSEING) { 639 | return 640 | } 641 | this.state = State.RECONNECTING 642 | this.fireEvent(KIMEvent.Reconnecting) 643 | // 重连10次 644 | for (let index = 0; index < 10; index++) { 645 | await sleep(3) 646 | try { 647 | log.info("try to relogin") 648 | let { success, err } = await this.login() 649 | if (success) { 650 | this.fireEvent(KIMEvent.Reconnected) 651 | return 652 | } 653 | log.info(err) 654 | } catch (error) { 655 | log.warn(error) 656 | } 657 | } 658 | this.onclose("reconnect timeout") 659 | } 660 | private send(data: Buffer | Uint8Array): boolean { 661 | try { 662 | if (this.conn == null) { 663 | return false 664 | } 665 | this.conn.send(data) 666 | } catch (error) { 667 | // handle write error 668 | this.errorHandler(new Error("write timeout")) 669 | return false 670 | } 671 | return true 672 | } 673 | } 674 | 675 | class MsgStorage { 676 | constructor() { 677 | localforage.config({ 678 | name: 'kim', 679 | storeName: "kim", 680 | }); 681 | } 682 | private keymsg(id: Long): string { 683 | return `msg_${id.toString()}` 684 | } 685 | private keylast(): string { 686 | return `last_id` 687 | } 688 | // 记录一条消息 689 | async insert(msg: Message): Promise { 690 | await localforage.setItem(this.keymsg(msg.messageId), msg) 691 | return true 692 | } 693 | // 检查消息是否已经保存 694 | async exist(id: Long): Promise { 695 | try { 696 | let val = await localforage.getItem(this.keymsg(id)) 697 | return !!val 698 | } catch (err) { 699 | log.warn(err); 700 | } 701 | return false; 702 | } 703 | async get(id: Long): Promise { 704 | try { 705 | let message = await localforage.getItem(this.keymsg(id)) 706 | return message 707 | } catch (err) { 708 | log.warn(err); 709 | } 710 | return null 711 | } 712 | async setAck(id: Long): Promise { 713 | await localforage.setItem(this.keylast(), id) 714 | return true 715 | } 716 | async lastId(): Promise { 717 | let id = await localforage.getItem(this.keylast()) 718 | return id || Long.ZERO 719 | } 720 | } 721 | 722 | export let Store = new MsgStorage(); --------------------------------------------------------------------------------