├── LICENSE
├── README.md
├── dest
├── RongIMClient.js
└── RongIMClient.js.map
├── external
├── WebSocketMain.zip
├── protobuf.js
├── swfobject.js
└── xhrpolling.js
├── index.html
├── modules
├── Embedded.js
├── emoji-0.9.2.js
├── indexedDB.js
├── loadImage.js
└── voice-0.9.1.js
├── package.json
├── src
├── IMClient
│ ├── IMEnum.js
│ ├── RongIMClient.js
│ ├── affiliatedMessage.js
│ ├── coustomMessage.js
│ ├── entry.js
│ └── shim.js
├── binary.js
├── core
│ ├── bridge.js
│ ├── channel.js
│ ├── client.js
│ ├── messageCallback.js
│ ├── messageHandler.js
│ └── messageParser.js
├── enum.js
├── io
│ ├── base.js
│ ├── factory.js
│ ├── polling.js
│ └── websocket.js
├── mapping.js
├── md5.js
├── message
│ ├── Message.js
│ ├── MessageEntity.js
│ ├── msgEnum.js
│ └── throttleStream.js
├── ready.js
└── tool.js
├── test
└── Junit.js
├── web_SDK_文件结构说明.txt
└── webpack.config.js
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 融云 RongCloud
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rongcloud-web-im-sdk v1 [已废弃]
2 |
3 | 请移步 Web IM SDK 2.0 [https://github.com/rongcloud/rongcloud-web-im-sdk-v2](https://github.com/rongcloud/rongcloud-web-im-sdk-v2)
4 |
5 | 官方不再对 v1 版本提供技术支持。
6 |
7 |
8 | -----------------------------------------------------------
9 |
10 | ## 融云 Web SDK 0.9.x 版本 Demo 如何使用
11 |
12 | [文档参考](http://docs.rongcloud.cn/api/js/index.html " SDK 文档")
13 |
14 | [使用说明请见](https://github.com/rongcloud/demo-web-sdk/blob/master/README.md " 说明文档")
15 |
16 | #### 安装 `webpack`
17 | ```
18 | $ npm install webpack -g
19 | ```
20 |
21 | #### 执行 `webpack`
22 |
23 | ```
24 | $ webpack
25 | ```
26 |
27 | #### 具体配置请见 `webpack.config.js`
28 |
29 | 测试前请修改index.html中的token,因为token可能不可用.
30 |
31 | *注意:为了更好的展现模块化,此次更新demo使用webpack来组织代码.*
32 | *本事例进攻参考,更多请关注rongcloud-web-im-sdk v2*
33 |
--------------------------------------------------------------------------------
/external/WebSocketMain.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rongcloud/rongcloud-web-im-sdk/e1eaa23c30ad553adba537537ccf3b3c420b7904/external/WebSocketMain.zip
--------------------------------------------------------------------------------
/external/xhrpolling.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yataozhang on 15/1/23.
3 | */
4 | (function (d) {
5 | if (!('now' in Date)) {
6 | Date.now = function () {
7 | var d = new Date();
8 | return d.getTime();
9 | }
10 | }
11 | var e = {
12 | NotifyMsg: function () {
13 | var a = {};
14 | this.setType = function (b) {
15 | a.type = b
16 | };
17 | this.setTime = function (b) {
18 | a.time = b;
19 | };
20 | this.toArrayBuffer = function () {
21 | return a;
22 | }
23 | },
24 | SyncRequestMsg: function () {
25 | var a = {};
26 | this.setSyncTime = function (b) {
27 | a.syncTime = b || 0;
28 | };
29 | this.setIspolling = function (b) {
30 | a.ispolling = !!b
31 | };
32 | this.toArrayBuffer = function () {
33 | return a
34 | }
35 | },
36 | UpStreamMessage: function () {
37 | var a = {};
38 | this.setSessionId = function (b) {
39 | a.sessionId = b
40 | };
41 | this.setClassname = function (b) {
42 | a.classname = b
43 | };
44 | this.setContent = function (b) {
45 | if (b) a.content = b;
46 | };
47 | this.setPushText = function (b) {
48 | a.pushText = b
49 | };
50 | this.toArrayBuffer = function () {
51 | return a
52 | }
53 | },
54 | DownStreamMessages: function () {
55 | var a = {};
56 | this.setList = function (b) {
57 | a.list = b
58 | };
59 | this.setSyncTime = function (b) {
60 | a.syncTime = b;
61 | };
62 | this.toArrayBuffer = function () {
63 | return a
64 | }
65 | },
66 | DownStreamMessage: function () {
67 | var a = {};
68 | this.setFromUserId = function (b) {
69 | a.fromUserId = b
70 | };
71 | this.setType = function (b) {
72 | a.type = b
73 | };
74 | this.setGroupId = function (b) {
75 | a.groupId = b
76 | };
77 | this.setClassname = function (b) {
78 | a.classname = b
79 | };
80 | this.setContent = function (b) {
81 | if (b)
82 | a.content = b
83 | };
84 | this.setDataTime = function (b) {
85 | a.dataTime = b
86 | };
87 | this.setStatus = function (b) {
88 | a.status = b
89 | };
90 | this.toArrayBuffer = function () {
91 | return a
92 | }
93 | },
94 | CreateDiscussionInput: function () {
95 | var a = {};
96 | this.setName = function (b) {
97 | a.name = b
98 | };
99 | this.toArrayBuffer = function () {
100 | return a
101 | }
102 | },
103 | CreateDiscussionOutput: function () {
104 | var a = {};
105 | this.setId = function (b) {
106 | a.id = b
107 | };
108 | this.toArrayBuffer = function () {
109 | return a
110 | }
111 | },
112 | ChannelInvitationInput: function () {
113 | var a = {};
114 | this.setUsers = function (b) {
115 | a.users = b
116 | };
117 | this.toArrayBuffer = function () {
118 | return a
119 | }
120 | },
121 | LeaveChannelInput: function () {
122 | var a = {};
123 | this.setNothing = function (b) {
124 | a.nothing = b
125 | };
126 | this.toArrayBuffer = function () {
127 | return a
128 | }
129 | },
130 | ChannelEvictionInput: function () {
131 | var a = {};
132 | this.setUser = function (b) {
133 | a.user = b
134 | };
135 | this.toArrayBuffer = function () {
136 | return a
137 | }
138 | },
139 | RenameChannelInput: function () {
140 | var a = {};
141 | this.setName = function (b) {
142 | a.name = b
143 | };
144 | this.toArrayBuffer = function () {
145 | return a
146 | }
147 | },
148 | ChannelInfoInput: function () {
149 | var a = {};
150 | this.setNothing = function (b) {
151 | a.nothing = b
152 | };
153 | this.toArrayBuffer = function () {
154 | return a
155 | }
156 | },
157 | ChannelInfoOutput: function () {
158 | var a = {};
159 | this.setType = function (b) {
160 | a.type = b
161 | };
162 | this.setChannelId = function (b) {
163 | a.channelId = b
164 | };
165 | this.setChannelName = function (b) {
166 | a.channelName = b
167 | };
168 | this.setAdminUserId = function (b) {
169 | a.adminUserId = b
170 | };
171 | this.setFirstTenUserIds = function (b) {
172 | a.firstTenUserIds = b
173 | };
174 | this.setOpenStatus = function (b) {
175 | a.openStatus = b
176 | };
177 | this.toArrayBuffer = function () {
178 | return a
179 | }
180 | },
181 | ChannelInfosInput: function () {
182 | var a = {};
183 | this.setPage = function (b) {
184 | a.page = b
185 | };
186 | this.setNumber = function (b) {
187 | a.number = b
188 | };
189 | this.toArrayBuffer = function () {
190 | return a
191 | }
192 | },
193 | ChannelInfosOutput: function () {
194 | var a = {};
195 | this.setChannels = function (b) {
196 | a.channels = b
197 | };
198 | this.setTotal = function (b) {
199 | a.total = b
200 | };
201 | this.toArrayBuffer = function () {
202 | return a
203 | }
204 | },
205 | MemberInfo: function () {
206 | var a = {};
207 | this.setUserId = function (b) {
208 | a.userId = b
209 | };
210 | this.setUserName = function (b) {
211 | a.userName = b
212 | };
213 | this.setUserPortrait = function (b) {
214 | a.userPortrait = b
215 | };
216 | this.setExtension = function (b) {
217 | a.extension = b
218 | };
219 | this.toArrayBuffer = function () {
220 | return a
221 | }
222 | },
223 | GroupMembersInput: function () {
224 | var a = {};
225 | this.setPage = function (b) {
226 | a.page = b
227 | };
228 | this.setNumber = function (b) {
229 | a.number = b
230 | };
231 | this.toArrayBuffer = function () {
232 | return a
233 | }
234 | },
235 | GroupMembersOutput: function () {
236 | var a = {};
237 | this.setMembers = function (b) {
238 | a.members = b
239 | };
240 | this.setTotal = function (b) {
241 | a.total = b
242 | };
243 | this.toArrayBuffer = function () {
244 | return a
245 | }
246 | },
247 | GetUserInfoInput: function () {
248 | var a = {};
249 | this.setNothing = function (b) {
250 | a.nothing = b
251 | };
252 | this.toArrayBuffer = function () {
253 | return a
254 | }
255 | },
256 | GetUserInfoOutput: function () {
257 | var a = {};
258 | this.setUserId = function (b) {
259 | a.userId = b
260 | };
261 | this.setUserName = function (b) {
262 | a.userName = b
263 | };
264 | this.setUserPortrait = function (b) {
265 | a.userPortrait = b
266 | };
267 | this.toArrayBuffer = function () {
268 | return a
269 | }
270 | },
271 | GetSessionIdInput: function () {
272 | var a = {};
273 | this.setNothing = function (b) {
274 | a.nothing = b
275 | };
276 | this.toArrayBuffer = function () {
277 | return a
278 | }
279 | },
280 | GetSessionIdOutput: function () {
281 | var a = {};
282 | this.setSessionId = function (b) {
283 | a.sessionId = b
284 | };
285 | this.toArrayBuffer = function () {
286 | return a
287 | }
288 | },
289 | GetQNupTokenInput: function () {
290 | var a = {};
291 | this.setType = function (b) {
292 | a.type = b;
293 | }
294 | this.toArrayBuffer = function () {
295 | return a
296 | }
297 | },
298 | GetQNupTokenOutput: function () {
299 | var a = {};
300 | this.setDeadline = function (b) {
301 | a.deadline = b
302 | };
303 | this.setToken = function (b) {
304 | a.token = b;
305 | };
306 | this.toArrayBuffer = function () {
307 | return a
308 | }
309 | },
310 | GetQNdownloadUrlInput: function () {
311 | var a = {};
312 | this.setType = function (b) {
313 | a.type = b;
314 | };
315 | this.setKey = function (b) {
316 | a.key = b;
317 | };
318 | this.toArrayBuffer = function () {
319 | return a
320 | }
321 | },
322 | GetQNdownloadUrlOutput: function () {
323 | var a = {};
324 | this.setDownloadUrl = function (b) {
325 | a.downloadUrl = b;
326 | };
327 | this.toArrayBuffer = function () {
328 | return a
329 | }
330 | },
331 | Add2BlackListInput: function () {
332 | var a = {};
333 | this.setUserId = function (b) {
334 | a.userId = b;
335 | };
336 | this.toArrayBuffer = function () {
337 | return a
338 | }
339 | },
340 | RemoveFromBlackListInput: function () {
341 | var a = {};
342 | this.setUserId = function (b) {
343 | a.userId = b;
344 | };
345 | this.toArrayBuffer = function () {
346 | return a
347 | }
348 | },
349 | QueryBlackListInput: function () {
350 | var a = {};
351 | this.setNothing = function (b) {
352 | a.nothing = b;
353 | };
354 | this.toArrayBuffer = function () {
355 | return a
356 | }
357 | },
358 | QueryBlackListOutput: function () {
359 | var a = {};
360 | this.setUserIds = function (b) {
361 | a.userIds = b;
362 | };
363 | this.toArrayBuffer = function () {
364 | return a
365 | }
366 | },
367 | BlackListStatusInput: function () {
368 | var a = {};
369 | this.setUserId = function (b) {
370 | a.userId = b;
371 | };
372 | this.toArrayBuffer = function () {
373 | return a
374 | }
375 | },
376 | BlockPushInput: function () {
377 | var a = {};
378 | this.setBlockeeId = function (b) {
379 | a.blockeeId = b;
380 | };
381 | this.toArrayBuffer = function () {
382 | return a
383 | }
384 | },
385 | ModifyPermissionInput: function () {
386 | var a = {};
387 | this.setOpenStatus = function (b) {
388 | a.openStatus = b;
389 | };
390 | this.toArrayBuffer = function () {
391 | return a
392 | }
393 | },
394 | GroupInput: function () {
395 | var a = {};
396 | this.setGroupInfo = function (b) {
397 | for (var i = 0, arr = []; i < b.length; i++) {
398 | arr.push({id: b[i].getContent().id, name: b[i].getContent().name})
399 | }
400 | a.groupInfo = arr;
401 | };
402 | this.toArrayBuffer = function () {
403 | return a
404 | }
405 | },
406 | GroupOutput: function () {
407 | var a = {};
408 | this.setNothing = function (b) {
409 | a.nothing = b;
410 | };
411 | this.toArrayBuffer = function () {
412 | return a
413 | }
414 | },
415 | GroupInfo: function () {
416 | var a = {};
417 | this.setId = function (b) {
418 | a.id = b;
419 | };
420 | this.setName = function (b) {
421 | a.name = b;
422 | };
423 | this.getContent = function () {
424 | return a;
425 | };
426 | this.toArrayBuffer = function () {
427 | return a
428 | }
429 | },
430 | GroupHashInput: function () {
431 | var a = {};
432 | this.setUserId = function (b) {
433 | a.userId = b;
434 | };
435 | this.setGroupHashCode = function (b) {
436 | a.groupHashCode = b;
437 | };
438 | this.toArrayBuffer = function () {
439 | return a
440 | }
441 | },
442 | GroupHashOutput: function () {
443 | var a = {};
444 | this.setResult = function (b) {
445 | a.result = b;
446 | };
447 | this.toArrayBuffer = function () {
448 | return a
449 | }
450 | },
451 | ChrmInput: function () {
452 | var a = {};
453 | this.setNothing = function (b) {
454 | a.nothing = b;
455 | };
456 | this.toArrayBuffer = function () {
457 | return a
458 | }
459 | },
460 | ChrmOutput: function () {
461 | var a = {};
462 | this.setNothing = function (b) {
463 | a.nothing = b;
464 | };
465 | this.toArrayBuffer = function () {
466 | return a
467 | }
468 | },
469 | ChrmPullMsg: function () {
470 | var a = {};
471 | this.setSyncTime = function (b) {
472 | a.syncTime = b
473 | };
474 | this.setCount = function (b) {
475 | a.count = b;
476 | };
477 | this.toArrayBuffer = function () {
478 | return a
479 | }
480 | },
481 | RelationsInput: function () {
482 | var a = {};
483 | this.setType = function (b) {
484 | a.type = b;
485 | };
486 | this.toArrayBuffer = function () {
487 | return a
488 | }
489 | },
490 | RelationsOutput: function () {
491 | var a = {};
492 | this.setInfo = function (b) {
493 | a.info = b;
494 | };
495 | this.toArrayBuffer = function () {
496 | return a
497 | }
498 | },
499 | RelationInfo: function () {
500 | var a = {};
501 | this.setType = function (b) {
502 | a.type = b;
503 | };
504 | this.setUserId = function (b) {
505 | a.userId = b;
506 | };
507 | this.toArrayBuffer = function () {
508 | return a
509 | }
510 | },
511 | HistoryMessageInput: function () {
512 | var a={};
513 | this.setTargetId=function(b){
514 | a.targetId=b;
515 | };
516 | this.setDataTime=function(b){
517 | a.dataTime=b;
518 | };
519 | this.setSize=function(b){
520 | a.size=b;
521 | };
522 | this.toArrayBuffer = function () {
523 | return a
524 | }
525 | },
526 | HistoryMessagesOuput: function () {
527 | var a={};
528 | this.setList=function(b){
529 | a.list=b;
530 | };
531 | this.setSyncTime=function(b){
532 | a.syncTime=b;
533 | };
534 | this.setHasMsg=function(b){
535 | a.hasMsg=b;
536 | };
537 | this.toArrayBuffer = function () {
538 | return a
539 | }
540 | }
541 | };
542 | for (var f in e) {
543 | e[f].decode = function (b) {
544 | var back = {}, val = JSON.parse(b) || eval("(" + b + ")");
545 | for (var i in val) {
546 | back[i]=val[i];
547 | back["get"+ i.charAt(0).toUpperCase()+i.slice(1)]=function(){
548 | return val[i];
549 | }
550 | }
551 | return back;
552 | }
553 | }
554 | d.Modules = e;
555 | })(window);
556 | (function (g) {
557 | if (g.RongIMClient) {
558 | if (RongIMClient.connect.token) {
559 | RongIMClient.getInstance().connect(RongIMClient.connect.token, RongIMClient.connect.callback);
560 | }
561 | } else {
562 | require(['../bin/RongIMClient'], function (r) {
563 | if (r.connect.token) {
564 | r.getInstance().connect(r.connect.token, r.connect.callback);
565 | }
566 | })
567 | }
568 | })(this);
569 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
221 |
222 |
223 |
224 | 用户id
225 |
233 | 接受的内容:
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
248 |
249 |
250 |
--------------------------------------------------------------------------------
/modules/emoji-0.9.2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 表情帮助库
3 | * 具体参考文档 https://github.com/rongcloud/demo-web-sdk#表情帮助库如何使用
4 | * */
5 |
6 | (function (b) {
7 | if (b.RongIMClient) {
8 | var c = {u1F600: {en: "grinning", zh: "\u72de\u7b11", tag: "\ud83d\ude00", "bp": "-1539px 0"}, u1F601: {en: "grin", zh: "\u9732\u9f7f\u800c\u7b11", tag: "\ud83d\ude01", "bp": "-1566px 0"}, u1F602: {en: "joy", zh: "\u6b22\u4e50", tag: "\ud83d\ude02", "bp": "-1593px 0"}, u1F603: {en: "smile", zh: "\u5fae\u7b11", tag: "\ud83d\ude03", "bp": "-1620px 0"}, u1F605: {en: "sweat_smile", zh: "\u8d54\u7b11", tag: "\ud83d\ude05", "bp": "-1647px 0"}, u1F606: {en: "satisfied",
9 | zh: "\u6ee1\u610f", tag: "\ud83d\ude06", "bp": "-1674px 0"}, u1F607: {en: "innocent", zh: "\u65e0\u8f9c", tag: "\ud83d\ude07", "bp": "-1701px 0"}, u1F608: {en: "smiling_imp", zh: "\u574f\u7b11", tag: "\ud83d\ude08", "bp": "-1728px 0"}, u1F609: {en: "wink", zh: "\u7728\u773c", tag: "\ud83d\ude09", "bp": "-1755px 0"}, u1F611: {en: "expressionless", zh: "\u9762\u65e0\u8868\u60c5", tag: "\ud83d\ude11", "bp": "-1944px 0"}, u1F612: {en: "unamused", zh: "\u4e00\u8138\u4e0d\u5feb",
10 | tag: "\ud83d\ude12", "bp": "-1971px 0"}, u1F613: {en: "sweat", zh: "\u6c57", tag: "\ud83d\ude13", "bp": "0 -27px"}, u1F614: {en: "pensive", zh: "\u54c0\u601d", tag: "\ud83d\ude14", "bp": "-27px -27px"}, u1F615: {en: "confused", zh: "\u8ff7\u832b", tag: "\ud83d\ude15", "bp": "-54px -27px"}, u1F616: {en: "confounded", zh: "\u56f0\u60d1\u7684", tag: "\ud83d\ude16", "bp": "-81px -27px"}, u1F618: {en: "kissing_heart", zh: "\u4eb2\u4e00\u4e2a", tag: "\ud83d\ude18",
11 | "bp": "-108px -27px"}, u1F621: {en: "rage", zh: "\u6124\u6012", tag: "\ud83d\ude21", "bp": "-270px -27px"}, u1F622: {en: "cry", zh: "\u54ed", tag: "\ud83d\ude22", "bp": "-297px -27px"}, u1F623: {en: "persevere", zh: "\u4f7f\u52b2", tag: "\ud83d\ude23", "bp": "-324px -27px"}, u1F624: {en: "triumph", zh: "\u751f\u6c14", tag: "\ud83d\ude24", "bp": "-351px -27px"}, u1F628: {en: "fearful", zh: "\u53ef\u6015", tag: "\ud83d\ude28", "bp": "-378px -27px"},
12 | u1F629: {en: "weary", zh: "\u538c\u5026", tag: "\ud83d\ude29", "bp": "-405px -27px"}, u1F630: {en: "cold_sweat", zh: "\u51b7\u6c57", tag: "\ud83d\ude30", "bp": "-567px -27px"}, u1F631: {en: "scream", zh: "\u60ca\u53eb", tag: "\ud83d\ude31", "bp": "-594px -27px"}, u1F632: {en: "astonished", zh: "\u60ca\u8bb6", tag: "\ud83d\ude32", "bp": "-621px -27px"}, u1F633: {en: "flushed", zh: "\u5446\u4f4f", tag: "\ud83d\ude33", "bp": "-648px -27px"}, u1F634: {en: "sleeping",
13 | zh: "\u7761\u7720", tag: "\ud83d\ude34", "bp": "-675px -27px"}, u1F635: {en: "dizzy_face", zh: "\u65ad\u7535\u4e86", tag: "\ud83d\ude35", "bp": "-702px -27px"}, u1F636: {en: "no_mouth", zh: "\u65e0\u53e3", tag: "\ud83d\ude36", "bp": "-729px -27px"}, u1F637: {en: "mask", zh: "\u75c5\u4e86", tag: "\ud83d\ude37", "bp": "-756px -27px"}, u1F3A4: {en: "microphone", zh: "KTV", tag: "\ud83c\udfa4", "bp": "-486px 0"}, u1F3B2: {en: "game_die", zh: "\u8272\u5b50", tag: "\ud83c\udfb2",
14 | "bp": "-513px 0"}, u1F3B5: {en: "musical_note", zh: "\u97f3\u4e50", tag: "\ud83c\udfb5", "bp": "-540px 0"}, u1F3C0: {en: "basketball", zh: "\u7bee\u7403", tag: "\ud83c\udfc0", "bp": "-567px 0"}, u1F3C2: {en: "snowboarder", zh: "\u5355\u677f\u6ed1\u96ea", tag: "\ud83c\udfc2", "bp": "-594px 0"}, u1F3E1: {en: "house_with_garden", zh: "\u623f\u5b50", tag: "\ud83c\udfe1", "bp": "-621px 0"}, u1F004: {en: "mahjong", zh: "\u9ebb\u5c06", tag: "\ud83c\udc04", "bp": "0 0"},
15 | u1F4A1: {en: "bulb", zh: "\u706f\u6ce1", tag: "\ud83d\udca1", "bp": "-1188px 0"}, u1F4A2: {en: "anger", zh: "\u6124\u6012", tag: "\ud83d\udca2", "bp": "-1215px 0"}, u1F4A3: {en: "bomb", zh: "\u70b8\u5f39", tag: "\ud83d\udca3", "bp": "-1242px 0"}, u1F4A4: {en: "zzz", zh: "ZZZ", tag: "\ud83d\udca4", "bp": "-1269px 0"}, u1F4A9: {en: "shit", zh: "\u72d7\u5c41", tag: "\ud83d\udca9", "bp": "-1296px 0"}, u1F4AA: {en: "muscle", zh: "\u808c\u8089", tag: "\ud83d\udcaa", "bp": "-1323px 0"},
16 | u1F4B0: {en: "moneybag", zh: "\u94b1\u888b", tag: "\ud83d\udcb0", "bp": "-1350px 0"}, u1F4DA: {en: "books", zh: "\u4e66\u7c4d", tag: "\ud83d\udcda", "bp": "-1377px 0"}, u1F4DE: {en: "telephone_receiver", zh: "\u7535\u8bdd", tag: "\ud83d\udcde", "bp": "-1404px 0"}, u1F4E2: {en: "loudspeaker", zh: "\u6269\u97f3\u5668", tag: "\ud83d\udce2", "bp": "-1431px 0"}, u1F6AB: {en: "stop", zh: "\u505c\u6b62", tag: "\ud83d\udeab", "bp": "-918px -27px"}, u1F6BF: {en: "shower",
17 | zh: "\u6dcb\u6d74", tag: "\ud83d\udebf", "bp": "-945px -27px"}, u1F30F: {en: "earth_asia", zh: "\u571f", tag: "\ud83c\udf0f", "bp": "-27px 0"}, u1F33B: {en: "sunflower", zh: "\u5411\u65e5\u8475", tag: "\ud83c\udf3b", "bp": "-135px 0"}, u1F35A: {en: "rice", zh: "\u996d", tag: "\ud83c\udf5a", "bp": "-216px 0"}, u1F36B: {en: "chocolate_bar", zh: "\u5de7\u514b\u529b", tag: "\ud83c\udf6b", "bp": "-270px 0"}, u1F37B: {en: "beers", zh: "\u5564\u9152", tag: "\ud83c\udf7b",
18 | "bp": "-324px 0"}, u1F44A: {en: "punch", zh: "\u62f3", tag: "\ud83d\udc4a", "bp": "-729px 0"}, u1F44C: {en: "ok_hand", zh: "\u6ca1\u95ee\u9898", tag: "\ud83d\udc4c", "bp": "-756px 0"}, u1F44D: {en: "1", zh: "1", tag: "\ud83d\udc4d", "bp": "-783px 0"}, u1F44E: {en: "-1", zh: "-1", tag: "\ud83d\udc4e", "bp": "-810px 0"}, u1F44F: {en: "clap", zh: "\u62cd", tag: "\ud83d\udc4f", "bp": "-837px 0"}, u1F46A: {en: "family", zh: "\u5bb6\u5ead", tag: "\ud83d\udc6a",
19 | "bp": "-891px 0"}, u1F46B: {en: "couple", zh: "\u60c5\u4fa3", tag: "\ud83d\udc6b", "bp": "-918px 0"}, u1F47B: {en: "ghost", zh: "\u9b3c", tag: "\ud83d\udc7b", "bp": "-945px 0"}, u1F47C: {en: "angel", zh: "\u5929\u4f7f", tag: "\ud83d\udc7c", "bp": "-972px 0"}, u1F47D: {en: "alien", zh: "\u5916\u661f\u4eba", tag: "\ud83d\udc7d", "bp": "-999px 0"}, u1F47F: {en: "imp", zh: "\u6076\u9b54", tag: "\ud83d\udc7f", "bp": "-1026px 0"}, u1F48A: {en: "pill",
20 | zh: "\u836f", tag: "\ud83d\udc8a", "bp": "-1080px 0"}, u1F48B: {en: "kiss", zh: "\u543b", tag: "\ud83d\udc8b", "bp": "-1107px 0"}, u1F48D: {en: "ring", zh: "\u6212\u6307", tag: "\ud83d\udc8d", "bp": "-1134px 0"}, u1F52B: {en: "gun", zh: "\u67aa", tag: "\ud83d\udd2b", "bp": "-1485px 0"}, u1F60A: {en: "blush", zh: "\u8138\u7ea2", tag: "\ud83d\ude0a", "bp": "-1782px 0"}, u1F60B: {en: "yum", zh: "\u998b", tag: "\ud83d\ude0b", "bp": "-1809px 0"}, u1F60C: {en: "relieved",
21 | zh: "\u5b89\u5fc3", tag: "\ud83d\ude0c", "bp": "-1836px 0"}, u1F60D: {en: "heart_eyes", zh: "\u8272\u8272", tag: "\ud83d\ude0d", "bp": "-1863px 0"}, u1F60E: {en: "sunglasses", zh: "\u58a8\u955c", tag: "\ud83d\ude0e", "bp": "-1890px 0"}, u1F60F: {en: "smirk", zh: "\u50bb\u7b11", tag: "\ud83d\ude0f", "bp": "-1917px 0"}, u1F61A: {en: "kissing_closed_eyes", zh: "\u63a5\u543b", tag: "\ud83d\ude1a", "bp": "-135px -27px"}, u1F61C: {en: "stuck_out_tongue_winking_eye",
22 | zh: "\u641e\u602a", tag: "\ud83d\ude1c", "bp": "-162px -27px"}, u1F61D: {en: "stuck_out_tongue_closed_eyes", zh: "\u6076\u4f5c\u5267", tag: "\ud83d\ude1d", "bp": "-189px -27px"}, u1F61E: {en: "disappointed", zh: "\u5931\u671b\u7684", tag: "\ud83d\ude1e", "bp": "-216px -27px"}, u1F61F: {en: "anguished", zh: "\u82e6\u6da9", tag: "\ud83d\ude1f", "bp": "-243px -27px"}, u1F62A: {en: "sleepy", zh: "\u56f0", tag: "\ud83d\ude2a", "bp": "-432px -27px"}, u1F62B: {en: "tired_face",
23 | zh: "\u6293\u72c2", tag: "\ud83d\ude2b", "bp": "-459px -27px"}, u1F62C: {en: "grimacing", zh: "\u9b3c\u8138", tag: "\ud83d\ude2c", "bp": "-486px -27px"}, u1F62D: {en: "sob", zh: "\u54ed\u6ce3", tag: "\ud83d\ude2d", "bp": "-513px -27px"}, u1F62F: {en: "hushed", zh: "\u5bc2\u9759", tag: "\ud83d\ude2f", "bp": "-540px -27px"}, u1F64A: {en: "speak_no_evil", zh: "\u4e0d\u8bf4\u8bdd", tag: "\ud83d\ude4a", "bp": "-837px -27px"}, u1F64F: {en: "pray", zh: "\u7948\u7977",
24 | tag: "\ud83d\ude4f", "bp": "-864px -27px"}, u1F319: {en: "moon", zh: "\u6708\u4eae", tag: "\ud83c\udf19", "bp": "-54px 0"}, u1F332: {en: "evergreen_tree", zh: "\u6811", tag: "\ud83c\udf32", "bp": "-81px 0"}, u1F339: {en: "rose", zh: "\u73ab\u7470", tag: "\ud83c\udf39", "bp": "-108px 0"}, u1F349: {en: "watermelon", zh: "\u897f\u74dc", tag: "\ud83c\udf49", "bp": "-162px 0"}, u1F356: {en: "meat_on_bone", zh: "\u8089", tag: "\ud83c\udf56", "bp": "-189px 0"},
25 | u1F366: {en: "icecream", zh: "\u51b0\u6dc7\u6dcb", tag: "\ud83c\udf66", "bp": "-243px 0"}, u1F377: {en: "wine_glass", zh: "\u9152", tag: "\ud83c\udf77", "bp": "-297px 0"}, u1F381: {en: "gift", zh: "\u793c\u7269", tag: "\ud83c\udf81", "bp": "-351px 0"}, u1F382: {en: "birthday", zh: "\u751f\u65e5", tag: "\ud83c\udf82", "bp": "-378px 0"}, u1F384: {en: "christmas_tree", zh: "\u5723\u8bde", tag: "\ud83c\udf84", "bp": "-405px 0"}, u1F389: {en: "tada", zh: "\u793c\u82b1",
26 | tag: "\ud83c\udf89", "bp": "-432px 0"}, u1F393: {en: "mortar_board", zh: "\u6bd5\u4e1a", tag: "\ud83c\udf93", "bp": "-459px 0"}, u1F434: {en: "horse", zh: "\u9a6c", tag: "\ud83d\udc34", "bp": "-648px 0"}, u1F436: {en: "dog", zh: "\u72d7", tag: "\ud83d\udc36", "bp": "-675px 0"}, u1F437: {en: "pig", zh: "\u732a", tag: "\ud83d\udc37", "bp": "-702px 0"}, u1F451: {en: "crown", zh: "\u738b\u51a0", tag: "\ud83d\udc51", "bp": "-864px 0"}, u1F484: {en: "lipstick",
27 | zh: "\u53e3\u7ea2", tag: "\ud83d\udc84", "bp": "-1053px 0"}, u1F494: {en: "broken_heart", zh: "\u4f24\u5fc3", tag: "\ud83d\udc94", "bp": "-1161px 0"}, u1F525: {en: "fire", zh: "\u706b\u4e86", tag: "\ud83d\udd25", "bp": "-1458px 0"}, u1F556: {en: "time", zh: "\u65f6\u95f4", tag: "\ud83d\udd56", "bp": "-1512px 0"}, u1F648: {en: "see_no_evil", zh: "\u4e0d\u770b", tag: "\ud83d\ude48", "bp": "-783px -27px"}, u1F649: {en: "hear_no_evil", zh: "\u4e0d\u542c", tag: "\ud83d\ude49",
28 | "bp": "-810px -27px"}, u1F680: {en: "rocket", zh: "\u706b\u7bad", tag: "\ud83d\ude80", "bp": "-891px -27px"}, u2B50: {en: "star", zh: "\u661f\u661f", tag: "\u2b50", "bp": "-1431px -27px"}, u23F0: {en: "alarm_clock", zh: "\u949f\u8868", tag: "\u23f0", "bp": "-972px -27px"}, u23F3: {en: "hourglass_flowing_sand", zh: "\u6c99\u6f0f", tag: "\u23f3", "bp": "-999px -27px"}, u26A1: {en: "zap", zh: "\u95ea\u7535", tag: "\u26a1", "bp": "-1188px -27px"},
29 | u26BD: {en: "soccer", zh: "\u8db3\u7403", tag: "\u26bd", "bp": "-1215px -27px"}, u26C4: {en: "snowman", zh: "\u96ea\u4eba", tag: "\u26c4", "bp": "-1242px -27px"}, u26C5: {en: "partly_sunny", zh: "\u591a\u4e91", tag: "\u26c5", "bp": "-1269px -27px"}, u261D: {en: "point_up", zh: "\u7b2c\u4e00", tag: "\u261d", "bp": "-1134px -27px"}, u263A: {en: "relaxed", zh: "\u8f7b\u677e", tag: "\u263a", "bp": "-1161px -27px"}, u270A: {en: "fist", zh: "\u62f3\u5934", tag: "\u270a",
30 | "bp": "-1296px -27px"}, u270B: {en: "hand", zh: "\u624b", tag: "\u270b", "bp": "-1323px -27px"}, u270C: {en: "v", zh: "v ", tag: "\u270c", "bp": "-1350px -27px"}, u270F: {en: "pencil2", zh: "\u7b14", tag: "\u270f", "bp": "-1377px -27px"}, u2600: {en: "sunny", zh: "\u6674\u6717", tag: "\u2600", "bp": "-1026px -27px"}, u2601: {en: "cloud", zh: "\u4e91", tag: "\u2601", "bp": "-1053px -27px"}, u2614: {en: "umbrella", zh: "\u4f1e", tag: "\u2614", "bp": "-1080px -27px"},
31 | u2615: {en: "coffee", zh: "\u5496\u5561", tag: "\u2615", "bp": "-1107px -27px"}, u2744: {en: "snowflake", zh: "\u96ea\u82b1", tag: "\u2744", "bp": "-1404px -27px"}};
32 | //根据浏览器初始化css
33 | function initCss() {
34 | var head = document.getElementsByTagName("head")[0] || document.createElement("head");
35 | if (document.createStyleSheet) {
36 | initBtag = function (position) {
37 | var e = document.createElement("b");
38 | e.style.width = '22px';
39 | e.style.height = '22px';
40 | e.style.backgroundImage = 'url(http://res.websdk.rongcloud.cn/css-sprite_bg.png)';
41 | e.style.display = 'inline';
42 | e.style.display = 'inline-block';
43 | e.style.zoom = '1';
44 | e.style.backgroundPosition = position;
45 | return e;
46 | };
47 | } else {
48 | var _style = document.createElement("style");
49 | _style.type = "text/css";
50 | _style.innerHTML = ".RC_Expression {width:22px;height:22px;background-image:url(http://res.websdk.rongcloud.cn/css-sprite_bg.png);display:inline-block}";
51 | head.appendChild(_style);
52 | }
53 | }
54 |
55 | var initBtag = function (position) {
56 | var e = document.createElement("b");
57 | e.className = "RC_Expression";
58 | e.style.backgroundPosition = position;
59 | return e;
60 | };
61 | b.RongIMClient.Expression = new function () {
62 | initCss();
63 | var e = this;
64 | //得到所有表情对象 0-127
65 | this.getAllExpression = function (a, b) {
66 | if (0 < a && -1 < b && 127 > a + b) {
67 | var h = [], d = 0, f;
68 | for (f in c) {
69 | if (d >= b + a)break;
70 | if (d >= b) {
71 | var e = initBtag(c[f]["bp"]);
72 | h.push({englishName: c[f].en, chineseName: c[f].zh, img: e, tag: c[f].tag});
73 | }
74 | d++;
75 | }
76 | return h;
77 | }
78 | throw Error("Wrong parameter");
79 | };
80 | //根据c的key得到表情对象
81 | this.getEmojiByContent = function (a) {
82 | if (a in c) {
83 | var b = initBtag(c[a]["bp"]);
84 | return{englishName: c[a].en, chineseName: c[a].zh, img: b, tag: c[a].tag};
85 | }
86 | };
87 | //计算utf
88 | this.calcUTF = function (d) {
89 | if (61440 < d.charCodeAt(0)) {
90 | var b = c[escape(d).replace("%u", "u1")];
91 | if (b)return b.tag;
92 | }
93 | return d;
94 | };
95 | //根据英文名称或中文名称得到表情对象
96 | this.getEmojiObjByEnglishNameOrChineseName = function (a) {
97 | for (var b in c) {
98 | if (c[b].en == a || c[b].zh == a) {
99 | var e = initBtag(c[b]["bp"]);
100 | return {img: e, englishName: c[b].en, chineseName: c[b].zh, tag: c[b].tag};
101 | }
102 | }
103 | return{};
104 | };
105 | var k = /(\ud83d\ude00|\ud83d\ude01|\ud83d\ude02|\ud83d\ude03|\ud83d\ude05|\ud83d\ude06|\ud83d\ude07|\ud83d\ude08|\ud83d\ude09|\ud83d\ude11|\ud83d\ude12|\ud83d\ude13|\ud83d\ude14|\ud83d\ude15|\ud83d\ude16|\ud83d\ude18|\ud83d\ude21|\ud83d\ude22|\ud83d\ude23|\ud83d\ude24|\ud83d\ude28|\ud83d\ude29|\ud83d\ude30|\ud83d\ude31|\ud83d\ude32|\ud83d\ude33|\ud83d\ude34|\ud83d\ude35|\ud83d\ude36|\ud83d\ude37|\ud83c\udfa4|\ud83c\udfb2|\ud83c\udfb5|\ud83c\udfc0|\ud83c\udfc2|\ud83c\udfe1|\ud83c\udc04|\ud83d\udca1|\ud83d\udca2|\ud83d\udca3|\ud83d\udca4|\ud83d\udca9|\ud83d\udcaa|\ud83d\udcb0|\ud83d\udcda|\ud83d\udcde|\ud83d\udce2|\ud83d\udeab|\ud83d\udebf|\ud83c\udf0f|\ud83c\udf3b|\ud83c\udf5a|\ud83c\udf6b|\ud83c\udf7b|\ud83d\udc4a|\ud83d\udc4c|\ud83d\udc4d|\ud83d\udc4e|\ud83d\udc4f|\ud83d\udc6a|\ud83d\udc6b|\ud83d\udc7b|\ud83d\udc7c|\ud83d\udc7d|\ud83d\udc7f|\ud83d\udc8a|\ud83d\udc8b|\ud83d\udc8d|\ud83d\udd2b|\ud83d\ude0a|\ud83d\ude0b|\ud83d\ude0c|\ud83d\ude0d|\ud83d\ude0e|\ud83d\ude0f|\ud83d\ude1a|\ud83d\ude1c|\ud83d\ude1d|\ud83d\ude1e|\ud83d\ude1f|\ud83d\ude2a|\ud83d\ude2b|\ud83d\ude2c|\ud83d\ude2d|\ud83d\ude2f|\ud83d\ude4a|\ud83d\ude4f|\ud83c\udf19|\ud83c\udf32|\ud83c\udf39|\ud83c\udf49|\ud83c\udf56|\ud83c\udf66|\ud83c\udf77|\ud83c\udf81|\ud83c\udf82|\ud83c\udf84|\ud83c\udf89|\ud83c\udf93|\ud83d\udc34|\ud83d\udc36|\ud83d\udc37|\ud83d\udc51|\ud83d\udc84|\ud83d\udc94|\ud83d\udd25|\ud83d\udd56|\ud83d\ude48|\ud83d\ude49|\ud83d\ude80|\u2b50|\u23f0|\u23f3|\u26a1|\u26bd|\u26c4|\u26c5|\u261d|\u263a|\u270a|\u270b|\u270c|\u270f|\u2600|\u2601|\u2614|\u2615|\u2744)/g;
106 | //解析一段字符串得到表情
107 | this.retrievalEmoji = function (a, b) {
108 | return a.replace(k, function (a) {
109 | var d;
110 | a:{
111 | for (d in c)if (c[d].tag == a)break a;
112 | d = a
113 | }
114 | return d != a ? b(e.getEmojiByContent(d)) : a;
115 | })
116 | }
117 | };
118 | } else {
119 | throw new Error("Please load RongIMClient.min.js,http://res.websdk.rong.io/RongIMClient.min.js")
120 | }
121 | })(window);
--------------------------------------------------------------------------------
/modules/indexedDB.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yataozhang on 15/4/13.
3 | * 内部存储帮助库
4 | * 文档地址 https://github.com/rongcloud/demo-web-sdk#web-端本地存储帮助库如何使用
5 | */
6 | (function (global, rong) {
7 | var db;
8 |
9 | global.indexedDB = global.indexedDB || global.mozIndexedDB || global.webkitIndexedDB || global.msIndexedDB;
10 |
11 | if (!global.indexedDB)
12 | throw new Error("The browser does not support this function");
13 | if (!rong)
14 | throw new Error("Please load RongIMClient.min.js,http://res.websdk.rongcloud.cn/RongIMClient.min.js")
15 |
16 | var DBOpenRequest = global.indexedDB.open('rongcloud', 1);
17 |
18 | DBOpenRequest.onsuccess = function (event) {
19 | db = event.target.result;
20 | };
21 |
22 | DBOpenRequest.onupgradeneeded = function (event) {
23 | var db = event.currentTarget.result;
24 |
25 | db.onerror = function (event) {
26 | throw new Error(event);
27 | };
28 |
29 | var objectStore = db.createObjectStore('messageObject', { keyPath: 'messageId' });
30 | objectStore.createIndex('ConversationType', 'ConversationType', { unique: true });
31 | };
32 |
33 | function getDB(mode) {
34 | var transaction = db.transaction(['messageObject'], mode);
35 | var objectStore = transaction.objectStore('messageObject');
36 | return {
37 | transaction: transaction,
38 | objectStore: objectStore
39 | }
40 | }
41 |
42 | function displayData(f) {
43 | var obj = getDB('readonly'), arr = [];
44 | obj.objectStore.openCursor(null, "prev").onsuccess = function (event) {
45 | var cursor = event.target.result;
46 | if (cursor) {
47 | arr.push(cursor.value);
48 | cursor.continue();
49 | }
50 | };
51 | obj.transaction.oncomplete = function () {
52 | f(arr);
53 | }
54 | }
55 |
56 | function getCount(func) {
57 | var obj = getDB('readwrite');
58 | var num = obj.objectStore.count();
59 | obj.transaction.oncomplete = function () {
60 | func(num.result);
61 | };
62 | }
63 |
64 | function addMessageObject(msg,func) {
65 | function add() {
66 | var obj = getDB("readwrite");
67 | obj.objectStore.put(msg);
68 | obj.transaction.oncomplete = function () {
69 | func();
70 | };
71 | }
72 |
73 | getCount(function (count) {
74 | if (count <= 20) {
75 | add();
76 | } else {
77 | deleteResult(null, function (err) {
78 | if (!err) {
79 | add();
80 | }
81 | });
82 | }
83 | })
84 | }
85 |
86 | function deleteResult(k, f) {
87 | var obj = getDB('readwrite');
88 | var request = {};
89 | obj.objectStore.openCursor().onsuccess = function (event) {
90 | var cursor = event.target.result;
91 | if (cursor) {
92 | if (k) {
93 | if (k && cursor.value.messageId == k) {
94 | request = cursor.delete();
95 | }
96 | cursor.continue();
97 | } else {
98 | request = cursor.delete();
99 | }
100 | request.onsuccess = function () {
101 | f(null);
102 | };
103 | request.onerror = function () {
104 | f(new Error("delete fail"));
105 | }
106 | }
107 | };
108 | }
109 | rong.indexedDB = {
110 | getMessageListFromIndexedDB: function (func) {
111 | displayData(func);
112 | },
113 | addMessageToIndexedDB: function (message, func) {
114 | if(message instanceof RongIMClient.RongIMMessage){
115 | addMessageObject(JSON.parse(message.toJSONString()), func)
116 | }
117 | }, deleteMessageFromIndexedDB: function (messageid, func) {
118 | deleteResult(messageid, func)
119 | }, getMessageListCountFromIndexedDB: function (func) {
120 | getCount(func)
121 | }
122 | }
123 | })(window, RongIMClient);
--------------------------------------------------------------------------------
/modules/loadImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yataozhang on 14/11/3.
3 | */
4 | (function (win) {
5 | if (win.RongIMClient) {
6 | var token = "", isinit = false,xdomain = null;
7 | function getToken() {
8 | RongIMClient.getInstance().getUploadToken({
9 | onSuccess: function (data) {
10 | token = data.token;
11 | isinit = true;
12 | }, onError: function () {
13 | throw new Error("Get token failure");
14 | }
15 | })
16 | }
17 |
18 | win.RongIMClient.loadPicture = new function () {
19 | function create(con, callback) {
20 | if(!window.FormData){
21 | return;
22 | }
23 | if (XMLHttpRequest) {
24 | xdomain = new XMLHttpRequest();
25 | xdomain.onreadystatechange = function () {
26 | if (xdomain.readyState == 4 && xdomain.status == 200) {
27 | var resu = io.util.JSONParse(xdomain.responseText);
28 | if (resu)
29 | callback(resu);
30 | }
31 | };
32 | }
33 | else if (XDomainRequest) {
34 | xdomain = new XDomainRequest();
35 | xdomain.onerror = function () {
36 | };
37 | xdomain.onload = function () {
38 | var resu = io.util.JSONParse(xdr.responseText)
39 | if (resu)
40 | callback(resu);
41 | };
42 | } else {
43 | throw new Error("The browser version is not supported");
44 | }
45 | xdomain.setRequestHeader("content-type","application/json");
46 | xdomain.open("post", 'http://localhost:8080/qwer',true);
47 | xdomain.send({token:token,data:con,userId:RongIMClient.getInstance().getCurrentUserInfo().getUserId()});
48 | }
49 |
50 | this.load = function (DataURL, callback) {
51 | if (isinit) {
52 | create(DataURL, callback);
53 | }
54 | else
55 | throw new Error("please init")
56 | };
57 | this.showImage = function (url, callback) {
58 | var img = new Image();
59 | img.url = url;
60 | callback(img);
61 | };
62 | };
63 |
64 | win.RongIMClient.loadPicture.init = function () {
65 | getToken();
66 | }
67 | }
68 | else {
69 | throw new Error("Please load RongIMClient.min.js,http://res.websdk.rong.io/RongIMClient.min.js");
70 | }
71 | })
72 | (window)
--------------------------------------------------------------------------------
/modules/voice-0.9.1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yataozhang on 14/11/3.
3 | * 音频帮助库
4 | * 文档地址 https://github.com/rongcloud/demo-web-sdk#音频播放帮助库如何使用
5 | */
6 | (function (win) {
7 | if (win.RongIMClient) {
8 | win.RongIMClient.voice = new function () {
9 | var isinit = false;
10 | this.init = function () {
11 | if (/IE/.test(navigator.userAgent) || isinit)//ie内核版本不支持此功能
12 | return;
13 | for (var list = ["http://res.websdk.rongcloud.cn/libamr.js", "http://res.websdk.rongcloud.cn/pcmdata.min.js", "http://res.websdk.rongcloud.cn/amr.js"], i = 0; i < list.length; i++) {
14 | var script = document.createElement("script");
15 | script.src = list[i];
16 | document.head.appendChild(script);
17 | }
18 | return (isinit = true);
19 | };
20 | this.play = function (DataURL, duration) {
21 | if (isinit&&+duration==duration) {
22 | if (window.handleFileSelect)
23 | window.handleFileSelect(DataURL);
24 | else
25 | throw new Error("Has not been initialized, please wait");
26 | if(!duration)
27 | return;
28 | duration=Math.ceil(duration);
29 | this.onprogress(0);
30 | var self = this, c = 1, timer = setInterval(function () {
31 | self.onprogress(c / duration);
32 | c++;
33 | if (c >= duration) {
34 | clearInterval(timer);
35 | }
36 | }, 1000);
37 | } else {
38 | throw new Error("the voice is not init,please init;WARNING:IE core is not supported This feature ");
39 | }
40 | };
41 | this.onprogress = function () {
42 |
43 | };
44 | };
45 | } else {
46 | throw new Error("Please load RongIMClient.min.js,http://res.websdk.rong.io/RongIMClient.min.js");
47 | }
48 | })(window);
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rongcloud-web-im-sdk",
3 | "version": "0.9.10",
4 | "description": "RongCloud web sdk resource code",
5 | "main": "RongIMClient.js",
6 | "contributors": [
7 | "yataozhang "
8 | ],
9 | "bin": {
10 | "rongcloud_web_SDK": "RongIMClient.js"
11 | },
12 | "directories": {
13 | "test": "test"
14 | },
15 | "scripts": {
16 | "test": "echo \"Error: no test specified\" && exit 1"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/rongcloud/demo-web-sdk.git"
21 | },
22 | "keywords": [
23 | "im",
24 | "rongcloud",
25 | "websdk",
26 | "sdk"
27 | ],
28 | "author": "zhangyatao",
29 | "license": "MIT",
30 | "bugs": {
31 | "url": "https://github.com/rongcloud/rongcloud-web-im-sdk/issues"
32 | },
33 | "homepage": "https://github.com/rongcloud/rongcloud-web-im-sdk"
34 | }
35 |
--------------------------------------------------------------------------------
/src/IMClient/IMEnum.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhangyatao on 16/1/11.
3 | */
4 | var RongIMClient = require('./RongIMClient');
5 | var tool = require('../tool');
6 | var msgEnum = require('../message/msgEnum');
7 | var en = require('../enum');
8 | var ConnectionState = msgEnum.ConnectionState;
9 | //create enum object 枚举对象,详情可参考API文档
10 | var _enum = {
11 | 'MessageTag': {
12 | 'ISPERSISTED': 'ISPERSISTED',
13 | 'ISCOUNTED': 'ISCOUNTED',
14 | 'NONE': 'NONE',
15 | 'ISDISPLAYED': "ISDISPLAYED"
16 | },
17 | 'ConversationNotificationStatus': ['DO_NOT_DISTURB', 'NOTIFY'],
18 | 'ConversationType': ['CHATROOM', 'CUSTOMER_SERVICE', 'DISCUSSION', 'GROUP', 'PRIVATE', 'SYSTEM'],
19 | 'SentStatus': ['DESTROYED', 'FAILED', 'READ', 'RECEIVED', 'SENDING', 'SENT'],
20 | 'DiscussionInviteStatus': ['CLOSED', 'OPENED'],
21 | 'MediaType': ['AUDIO', 'FILE', 'IMAGE', 'VIDEO'],
22 | 'MessageDirection': ['RECEIVE', 'SEND'],
23 | 'MessageType': ['DiscussionNotificationMessage', 'TextMessage', 'ImageMessage', 'VoiceMessage', 'RichContentMessage', 'HandshakeMessage', 'UnknownMessage', 'SuspendMessage', 'LocationMessage', 'InformationNotificationMessage', 'ContactNotificationMessage', 'ProfileNotificationMessage', 'CommandNotificationMessage'],
24 | 'SendErrorStatus': {
25 | 'REJECTED_BY_BLACKLIST': 405,
26 | 'NOT_IN_DISCUSSION': 21406,
27 | 'NOT_IN_GROUP': 22406,
28 | 'NOT_IN_CHATROOM': 23406
29 | },
30 | 'BlacklistStatus': ['EXIT_BLACK_LIST', 'NOT_EXIT_BLACK_LIST'],
31 | 'ConnectionStatus': ['CONNECTED', 'CONNECTING', 'RECONNECT', 'OTHER_DEVICE_LOGIN', 'CLOSURE', 'UNKNOWN_ERROR', 'LOGOUT', 'BLOCK']
32 | };
33 | //生产枚举对象
34 | tool.each(_enum, function (_name, option) {
35 | var val = {};
36 | if (tool.isArray(option)) {
37 | tool.forEach(option, function (x, i) {
38 | val[x] = i;
39 | })
40 | } else {
41 | val = option;
42 | }
43 | RongIMClient[_name] = en(val);
44 | });
45 | RongIMClient.ConnectErrorStatus = ConnectionState;
46 | //回调基类
47 | RongIMClient.callback = function (d, a) {
48 | this.onError = a;
49 | this.onSuccess = d
50 | };
51 | //回调错误枚举值
52 | RongIMClient.callback.ErrorCode = en({
53 | TIMEOUT: -1,
54 | UNKNOWN_ERROR: -2
55 | });
--------------------------------------------------------------------------------
/src/IMClient/affiliatedMessage.js:
--------------------------------------------------------------------------------
1 | var RongIMClient=require('./RongIMClient');
2 | var tool=require('../tool');
3 | //把具体的消息类型转化为protobuf格式的类
4 | RongIMClient.MessageContent = function (f) {
5 | if (!(f instanceof RongIMClient.RongIMMessage)) {
6 | throw new Error("wrong parameter")
7 | }
8 | };
9 | RongIMClient.MessageContent.prototype.getMessage = function () {
10 | return f
11 | };
12 | RongIMClient.MessageContent.prototype.encode = function () {
13 | var c = new Modules.UpStreamMessage();
14 | c.setSessionId(0);
15 | c.setClassname(f.getObjectName());
16 | c.setContent(tool.JSON.stringify(f.getDetail()));
17 | var val = c.toArrayBuffer();
18 | if (Object.prototype.toString.call(val) == "[object ArrayBuffer]") {
19 | return [].slice.call(new Int8Array(val))
20 | }
21 | return val
22 | };
23 | //发送中处理消息的类,sendMessage方法的第三个参数就是这个对象
24 | RongIMClient.MessageHandler = function (a) {
25 | if (typeof a == "function") {
26 | this.process = a;
27 | } else {
28 | throw new Error("MessageHandler:arguments type is error")
29 | }
30 | };
31 | //接收状态
32 | RongIMClient.ReceivedStatus = function (d) {
33 | var a = d || 1;
34 | this.getFlag = function () {
35 | return a
36 | };
37 | this.isDownload = function () {
38 | return a == 1
39 | };
40 | this.isListened = function () {
41 | return a == 2
42 | };
43 | this.isRead = function () {
44 | return a == 3
45 | };
46 | this.setDownload = function () {
47 | a = 1
48 | };
49 | this.setListened = function () {
50 | a = 2
51 | };
52 | this.setRead = function () {
53 | a = 3
54 | };
55 | };
56 | //用户信息
57 | RongIMClient.UserInfo = function (h, l, a) {
58 | var k = h,
59 | j = l,
60 | i = a;
61 | this.getUserName = function () {
62 | return j
63 | };
64 | this.getPortraitUri = function () {
65 | return i
66 | };
67 | this.getUserId = function () {
68 | return k
69 | };
70 | this.setUserName = function (c) {
71 | j = c
72 | };
73 | this.setPortraitUri = function (c) {
74 | i = c
75 | };
76 | this.setUserId = function (c) {
77 | k = c
78 | }
79 | };
80 | //会话信息
81 | RongIMClient.Conversation = function () {
82 | var s = this,
83 | a = (new Date).getTime(),
84 | D, v, B, w, E, G, t, F, y, C, A, H, x, u = 0, por,
85 | z = RongIMClient.ConversationNotificationStatus.NOTIFY;
86 | this.getConversationTitle = function () {
87 | return G
88 | };
89 | this.toJSON = function () {
90 | var c = {
91 | "senderUserName": E,
92 | lastTime: a,
93 | "objectName": D,
94 | "senderUserId": v,
95 | "receivedTime": B,
96 | "conversationTitle": G,
97 | "conversationType": t,
98 | "latestMessageId": C,
99 | "sentTime": H,
100 | "targetId": x,
101 | "notificationStatus": z
102 | };
103 | return tool.JSON.stringify(c)
104 | };
105 | this.setReceivedStatus = function (c) {
106 | w = c
107 | };
108 | this.getReceivedStatus = function () {
109 | return w
110 | };
111 | this.getConversationType = function () {
112 | return t
113 | };
114 | this.getDraft = function () {
115 | return F
116 | };
117 | this.getLatestMessage = function () {
118 | return y
119 | };
120 | this.getLatestMessageId = function () {
121 | return C
122 | };
123 | this.getNotificationStatus = function () {
124 | return z
125 | };
126 | this.getObjectName = function () {
127 | return D
128 | };
129 | this.getReceivedTime = function () {
130 | return B
131 | };
132 | this.getSenderUserId = function () {
133 | return v
134 | };
135 | this.getSentStatus = function () {
136 | return A
137 | };
138 | this.getSentTime = function () {
139 | return H
140 | };
141 | this.getTargetId = function () {
142 | return x
143 | };
144 | this.getUnreadMessageCount = function () {
145 | return u
146 | };
147 | this.isTop = function () {
148 | var e = RongIMClient.getInstance().getConversationList();
149 | return e[0] != undefined && e[0].getTargetId() == this.getTargetId() && e[0].getConversationType() == this.getConversationType();
150 | };
151 | this.setConversationTitle = function (c) {
152 | G = c
153 | };
154 | this.getConversationPortrait = function () {
155 | return por;
156 | };
157 | this.setConversationPortrait = function (p) {
158 | por = p;
159 | };
160 | this.setConversationType = function (c) {
161 | t = c
162 | };
163 | this.setDraft = function (c) {
164 | F = c
165 | };
166 | this.setSenderUserName = function (c) {
167 | E = c
168 | };
169 | this.setLatestMessage = function (c) {
170 | y = c
171 | };
172 | this.setLatestMessageId = function (c) {
173 | C = c
174 | };
175 | this.setNotificationStatus = function (c) {
176 | z = c instanceof RongIMClient.ConversationNotificationStatus ? c : RongIMClient.ConversationNotificationStatus.setValue(c);
177 | };
178 | this.setObjectName = function (c) {
179 | D = c
180 | };
181 | this.setReceivedTime = function (c) {
182 | a = B = c
183 | };
184 | this.setSenderUserId = function (c) {
185 | v = c
186 | };
187 | this.getLatestTime = function () {
188 | return a
189 | };
190 | this.setSentStatus = function (c) {
191 | return !!(A = c)
192 | };
193 | this.setSentTime = function (c) {
194 | a = H = c
195 | };
196 | this.setTargetId = function (c) {
197 | x = c
198 | };
199 | this.setTop = function () {
200 | if (s.getTargetId() == undefined || this.isTop()) {
201 | return
202 | }
203 | RongIMClient.getInstance().getConversationList().add(this);
204 | };
205 | this.setUnreadMessageCount = function (c) {
206 | u = c
207 | }
208 | };
209 | //讨论组信息
210 | RongIMClient.Discussion = function (m, l, a, q, p) {
211 | var s = m,
212 | t = l,
213 | r = a,
214 | o = q,
215 | n = p;
216 | this.getCreatorId = function () {
217 | return r
218 | };
219 | this.getId = function () {
220 | return s
221 | };
222 | this.getMemberIdList = function () {
223 | return n
224 | };
225 | this.getName = function () {
226 | return t
227 | };
228 | this.isOpen = function () {
229 | return o
230 | };
231 | this.setCreatorId = function (c) {
232 | r = c
233 | };
234 | this.setId = function (c) {
235 | s = c
236 | };
237 | this.setMemberIdList = function (c) {
238 | n = c
239 | };
240 | this.setName = function (c) {
241 | t = c
242 | };
243 | this.setOpen = function (c) {
244 | o = !!c
245 | }
246 | };
247 | //群信息
248 | RongIMClient.Group = function (j, l, a) {
249 | var h = j,
250 | k = l,
251 | i = a;
252 | this.getId = function () {
253 | return h
254 | };
255 | this.getName = function () {
256 | return k
257 | };
258 | this.getPortraitUri = function () {
259 | return i
260 | };
261 | this.setId = function (c) {
262 | h = c
263 | };
264 | this.setName = function (c) {
265 | k = c
266 | };
267 | this.setPortraitUri = function (c) {
268 | i = c
269 | }
270 | };
271 |
--------------------------------------------------------------------------------
/src/IMClient/coustomMessage.js:
--------------------------------------------------------------------------------
1 | var RongIMClient=require('./RongIMClient');
2 | var tool=require('../tool');
3 | //消息基类,此类是对安卓消息基类的重新实现
4 | RongIMClient.RongIMMessage = function (content) {
5 | var x = "unknown",
6 | u, z = content || {},
7 | o, q, t, y, a, p, s, v, r;
8 | this.getDetail = function () {
9 | return z;
10 | };
11 | this.getMessageTag = function () {
12 | return [RongIMClient.MessageTag.ISPERSISTED, RongIMClient.MessageTag.ISCOUNTED, RongIMClient.MessageTag.ISDISPLAYED];
13 | };
14 | this.getContent = function () {
15 | return z.content
16 | };
17 | this.getConversationType = function () {
18 | return o
19 | };
20 | this.getExtra = function () {
21 | return z.extra;
22 | };
23 | this.getMessageDirection = function () {
24 | return q
25 | };
26 | this.getMessageId = function () {
27 | return t
28 | };
29 | this.getObjectName = function () {
30 | return y
31 | };
32 | this.getReceivedStatus = function () {
33 | return a
34 | };
35 | this.getReceivedTime = function () {
36 | return u
37 | };
38 | this.getSenderUserId = function () {
39 | return p
40 | };
41 | this.getSentStatus = function () {
42 | return s
43 | };
44 | this.getTargetId = function () {
45 | return r
46 | };
47 | this.setContent = function (c, d) {
48 | z[d || "content"] = c
49 | };
50 | this.setConversationType = function (c) {
51 | o = c
52 | };
53 | this.setExtra = function (c) {
54 | z.extra = c;
55 | };
56 | this.setMessageDirection = function (c) {
57 | q = c
58 | };
59 | this.setMessageId = function (c) {
60 | t = c
61 | };
62 | this.setObjectName = function (c) {
63 | y = c
64 | };
65 | this.setReceivedStatus = function (c) {
66 | a = c
67 | };
68 | this.setSenderUserId = function (c) {
69 | p = c
70 | };
71 | this.setSentStatus = function (c) {
72 | return !!(s = c)
73 | };
74 | this.setSentTime = function (c) {
75 | v = tool.int64ToTimestamp(c);
76 | };
77 | this.getSentTime = function () {
78 | return v;
79 | };
80 | this.setTargetId = function (c) {
81 | r = c
82 | };
83 | this.setReceivedTime = function (c) {
84 | u = c
85 | };
86 | this.toJSON = function () {
87 | var c = {
88 | "receivedTime": u,
89 | "messageType": x,
90 | "details": z,
91 | "conversationType": o,
92 | "direction": q,
93 | "messageId": t,
94 | "objectName": y,
95 | "senderUserId": p,
96 | "sendTime": v,
97 | "targetId": r
98 | };
99 | return tool.JSON.stringify(c)
100 | };
101 | this.getMessageType = function () {
102 | return x
103 | };
104 | this.setMessageType = function (c) {
105 | x = c
106 | }
107 | };
108 | //通知类型消息基类,继承自RongIMMessage
109 | RongIMClient.NotificationMessage = function (c) {
110 | RongIMClient.RongIMMessage.call(this, c);
111 | this.getMessageTag = function () {
112 | return [RongIMClient.MessageTag.ISPERSISTED, RongIMClient.MessageTag.ISDISPLAYED];
113 | };
114 | };
115 | tool.inherit(RongIMClient.NotificationMessage, RongIMClient.RongIMMessage, true);
116 | //状态类型消息基类,继承自RongIMMessage
117 | RongIMClient.StatusMessage = function (c) {
118 | RongIMClient.RongIMMessage.call(this, c);
119 | this.getMessageTag = function () {
120 | return ['NONE'];
121 | };
122 | };
123 | tool.inherit(RongIMClient.StatusMessage, RongIMClient.RongIMMessage, true);
124 | //文本消息
125 | RongIMClient.TextMessage = function (c) {
126 | RongIMClient.RongIMMessage.call(this, c);
127 | this.setMessageType(RongIMClient.MessageType.TextMessage);
128 | this.setObjectName("RC:TxtMsg");
129 | };
130 | RongIMClient.TextMessage.obtain = function (text) {
131 | return new RongIMClient.TextMessage({
132 | content: text,
133 | extra: ""
134 | })
135 | };
136 | tool.inherit(RongIMClient.TextMessage, RongIMClient.RongIMMessage, true);
137 | //图片消息
138 | RongIMClient.ImageMessage = function (c) {
139 | RongIMClient.RongIMMessage.call(this, c);
140 | this.setMessageType(RongIMClient.MessageType.ImageMessage);
141 | this.setObjectName("RC:ImgMsg");
142 | this.setImageUri = function (a) {
143 | this.setContent(a, "imageUri")
144 | };
145 | this.getImageUri = function () {
146 | return this.getDetail().imageUri
147 | };
148 | };
149 | RongIMClient.ImageMessage.obtain = function (content, imageUri) {
150 | return new RongIMClient.ImageMessage({
151 | content: content,
152 | imageUri: imageUri,
153 | extra: ""
154 | });
155 | };
156 | tool.inherit(RongIMClient.ImageMessage, RongIMClient.RongIMMessage, true);
157 | //图文消息
158 | RongIMClient.RichContentMessage = function (c) {
159 | RongIMClient.RongIMMessage.call(this, c);
160 | this.setMessageType(RongIMClient.MessageType.RichContentMessage);
161 | this.setObjectName("RC:ImgTextMsg");
162 | this.setTitle = function (a) {
163 | this.setContent(a, "title")
164 | };
165 | this.getTitle = function () {
166 | return this.getDetail().title;
167 | };
168 | this.setImageUri = function (a) {
169 | this.setContent(a, "imageUri")
170 | };
171 | this.getImageUri = function () {
172 | return this.getDetail().imageUri;
173 | };
174 | };
175 | RongIMClient.RichContentMessage.obtain = function (title, content, imageUri) {
176 | return new RongIMClient.RichContentMessage({
177 | title: title,
178 | content: content,
179 | imageUri: imageUri,
180 | extra: ""
181 | })
182 | };
183 | tool.inherit(RongIMClient.RichContentMessage, RongIMClient.RongIMMessage, true);
184 | //音频消息
185 | RongIMClient.VoiceMessage = function (c) {
186 | RongIMClient.RongIMMessage.call(this, c);
187 | this.setObjectName("RC:VcMsg");
188 | this.setMessageType(RongIMClient.MessageType.VoiceMessage);
189 | this.setDuration = function (a) {
190 | this.setContent(a, "duration")
191 | };
192 | this.getDuration = function () {
193 | return this.getDetail().duration;
194 | };
195 | };
196 | RongIMClient.VoiceMessage.obtain = function (content, duration) {
197 | return new RongIMClient.VoiceMessage({
198 | content: content,
199 | duration: duration,
200 | extra: ""
201 | })
202 | };
203 | tool.inherit(RongIMClient.VoiceMessage, RongIMClient.RongIMMessage, true);
204 | //客服握手消息
205 | RongIMClient.HandshakeMessage = function () {
206 | RongIMClient.RongIMMessage.call(this);
207 | this.setMessageType(RongIMClient.MessageType.HandshakeMessage);
208 | this.setObjectName("RC:HsMsg");
209 | };
210 | tool.inherit(RongIMClient.HandshakeMessage, RongIMClient.RongIMMessage, true);
211 | //中断客服消息
212 | RongIMClient.SuspendMessage = function () {
213 | RongIMClient.RongIMMessage.call(this);
214 | this.setMessageType(RongIMClient.MessageType.SuspendMessage);
215 | this.setObjectName("RC:SpMsg");
216 | };
217 | tool.inherit(RongIMClient.SuspendMessage, RongIMClient.RongIMMessage, true);
218 | //未知消息
219 | RongIMClient.UnknownMessage = function (c, o) {
220 | RongIMClient.RongIMMessage.call(this, c);
221 | this.setMessageType(RongIMClient.MessageType.UnknownMessage);
222 | this.setObjectName(o);
223 | };
224 | tool.inherit(RongIMClient.UnknownMessage, RongIMClient.RongIMMessage, true);
225 | //地理位置消息
226 | RongIMClient.LocationMessage = function (c) {
227 | RongIMClient.RongIMMessage.call(this, c);
228 | this.setMessageType(RongIMClient.MessageType.LocationMessage);
229 | this.setObjectName("RC:LBSMsg");
230 | this.setLatitude = function (a) {
231 | this.setContent(a, "latitude")
232 | };
233 | this.getLatitude = function () {
234 | return this.getDetail().latitude;
235 | };
236 | this.setLongitude = function (a) {
237 | this.setContent(a, "longitude")
238 | };
239 | this.getLongitude = function () {
240 | return this.getDetail().longitude;
241 | };
242 | this.setPoi = function (a) {
243 | this.setContent(a, "poi")
244 | };
245 | this.getPoi = function () {
246 | return this.getDetail().poi;
247 | };
248 | };
249 | RongIMClient.LocationMessage.obtain = function (content, latitude, longitude, poi) {
250 | return new RongIMClient.LocationMessage({
251 | content: content,
252 | latitude: latitude,
253 | longitude: longitude,
254 | poi: poi,
255 | extra: ""
256 | })
257 | };
258 | tool.inherit(RongIMClient.LocationMessage, RongIMClient.RongIMMessage, true);
259 | //讨论组通知消息
260 | RongIMClient.DiscussionNotificationMessage = function (c) {
261 | RongIMClient.NotificationMessage.call(this, c);
262 | this.setMessageType(RongIMClient.MessageType.DiscussionNotificationMessage);
263 | this.setObjectName("RC:DizNtf");
264 | var isReceived = false;
265 | this.getExtension = function () {
266 | return this.getDetail().extension;
267 | };
268 | this.getOperator = function () {
269 | return this.getDetail().operator;
270 | };
271 | this.getType = function () {
272 | return this.getDetail().type;
273 | };
274 | this.isHasReceived = function () {
275 | return isReceived;
276 | };
277 | this.setExtension = function (a) {
278 | this.setContent(a, "extension")
279 | };
280 | this.setHasReceived = function (x) {
281 | isReceived = !!x;
282 | };
283 | this.setOperator = function (a) {
284 | this.setContent(a, "operator")
285 | };
286 | this.setType = function (a) {
287 | this.setContent(a, "type");
288 | //1:加入讨论组 2:退出讨论组 3:讨论组改名 4:讨论组群主T人
289 | };
290 | };
291 | tool.inherit(RongIMClient.DiscussionNotificationMessage, RongIMClient.NotificationMessage, true);
292 | //信息通知消息,继承自NotificationMessage
293 | RongIMClient.InformationNotificationMessage = function (c) {
294 | RongIMClient.NotificationMessage.call(this, c);
295 | this.setMessageType(RongIMClient.MessageType.InformationNotificationMessage);
296 | this.setObjectName("RC:InfoNtf");
297 | };
298 | RongIMClient.InformationNotificationMessage.obtain = function (content) {
299 | return new RongIMClient.InformationNotificationMessage({
300 | content: content,
301 | extra: ""
302 | })
303 | };
304 | tool.inherit(RongIMClient.InformationNotificationMessage, RongIMClient.NotificationMessage, true);
305 | //加删好友消息
306 | RongIMClient.ContactNotificationMessage = function (c) {
307 | RongIMClient.NotificationMessage.call(this, c);
308 | this.setMessageType(RongIMClient.MessageType.ContactNotificationMessage);
309 | this.setObjectName("RC:ContactNtf");
310 | this.getOperation = function () {
311 | return this.getDetail().operation;
312 | };
313 | this.setOperation = function (o) {
314 | this.setContent(o, 'operation');
315 | };
316 | this.setMessage = function (m) {
317 | this.setContent(m, 'message');
318 | };
319 | this.getMessage = function () {
320 | return this.getDetail().message;
321 | };
322 | this.getSourceUserId = function () {
323 | return this.getDetail().sourceUserId;
324 | };
325 | this.setSourceUserId = function (m) {
326 | this.setContent(m, 'sourceUserId');
327 | };
328 | this.getTargetUserId = function () {
329 | return this.getDetail().targetUserId;
330 | };
331 | this.setTargetUserId = function (m) {
332 | this.setContent(m, 'targetUserId');
333 | };
334 | };
335 | RongIMClient.ContactNotificationMessage.obtain = function (operation, sourceUserId, targetUserId, message) {
336 | return new RongIMClient.ContactNotificationMessage({
337 | operation: operation,
338 | sourceUserId: sourceUserId,
339 | targetUserId: targetUserId,
340 | message: message,
341 | extra: ""
342 | });
343 | };
344 | //允许加好友
345 | RongIMClient.ContactNotificationMessage.CONTACT_OPERATION_ACCEPT_RESPONSE = 'ContactOperationAcceptResponse';
346 | //拒绝加好友
347 | RongIMClient.ContactNotificationMessage.CONTACT_OPERATION_REJECT_RESPONSE = 'ContactOperationRejectResponse';
348 | //发起加好友请求
349 | RongIMClient.ContactNotificationMessage.CONTACT_OPERATION_REQUEST = 'ContactOperationRequest';
350 | tool.inherit(RongIMClient.ContactNotificationMessage, RongIMClient.NotificationMessage, true);
351 | //个人信息通知消息
352 | RongIMClient.ProfileNotificationMessage = function (c) {
353 | RongIMClient.NotificationMessage.call(this, c);
354 | this.setMessageType(RongIMClient.MessageType.ProfileNotificationMessage);
355 | this.setObjectName("RC:ProfileNtf");
356 | this.getOperation = function () {
357 | return this.getDetail().operation;
358 | };
359 | this.setOperation = function (o) {
360 | this.setContent(o, 'operation');
361 | };
362 | this.getData = function () {
363 | return this.getDetail().data;
364 | };
365 | this.setData = function (o) {
366 | this.setContent(o, 'data');
367 | };
368 | };
369 | RongIMClient.ProfileNotificationMessage.obtain = function (operation, data) {
370 | return new RongIMClient.ProfileNotificationMessage({
371 | operation: operation,
372 | data: data,
373 | extra: ""
374 | });
375 | };
376 | tool.inherit(RongIMClient.ProfileNotificationMessage, RongIMClient.NotificationMessage, true);
377 | //命令通知消息
378 | RongIMClient.CommandNotificationMessage = function (c) {
379 | RongIMClient.NotificationMessage.call(this, c);
380 | this.setMessageType(RongIMClient.MessageType.CommandNotificationMessage);
381 | this.setObjectName("RC:CmdNtf");
382 | this.getData = function () {
383 | return this.getDetail().data;
384 | };
385 | this.setData = function (o) {
386 | this.setContent(o, "data");
387 | };
388 | this.getName = function () {
389 | return this.getDetail().name;
390 | };
391 | this.setName = function (o) {
392 | this.setContent(o, 'name');
393 | };
394 | };
395 | RongIMClient.CommandNotificationMessage.obtain = function (x, data) {
396 | return new RongIMClient.CommandNotificationMessage({
397 | name: x,
398 | data: data,
399 | extra: ""
400 | });
401 | };
402 | tool.inherit(RongIMClient.CommandNotificationMessage, RongIMClient.NotificationMessage, true);
--------------------------------------------------------------------------------
/src/IMClient/entry.js:
--------------------------------------------------------------------------------
1 | var RongIMClient = require('./RongIMClient');
2 | var tool = require('../tool');
3 | var mapping = require('../mapping');
4 | require('../ready');
5 | require('./affiliatedMessage');
6 | require('./coustomMessage');
7 | require('./IMEnum');
8 | //版本号
9 | RongIMClient.version = "0.9.10";
10 | // RongIMClient.connect静态方法,执行连接操作
11 | RongIMClient.connect = function (d, a) {
12 | if (!RongIMClient.getInstance) {
13 | throw new Error("please init")
14 | }
15 | //判断protobuf文件加载是否完成
16 | if (global.Modules) {
17 | //完成执行connect方法
18 | RongIMClient.getInstance().connect(d, a);
19 | } else {
20 | //把token、回调函数赋值给RongIMClient.connect,让protobuf文件自己来触发连接操作
21 | RongIMClient.connect.token = d;
22 | RongIMClient.connect.callback = a
23 | }
24 | };
25 | //是否有未接收的消息,jsonp方法
26 | RongIMClient.hasUnreadMessages = function (appkey, token, callback) {
27 | tool.jsonp("http://api.cn.rong.io/message/exist.js?appKey=" +
28 | encodeURIComponent(appkey) + "&token=" + encodeURIComponent(token),
29 | "callBack", function (x) {
30 | callback.onSuccess(!!+x.status);
31 | }, function () {
32 | callback.onError(RongIMClient.callback.ErrorCode.UNKNOWN_ERROR);
33 | });
34 | };
35 | //初始化。生成一个RongIMClient单例
36 | RongIMClient.init = function (d, conf) {
37 |
38 | mapping.WEB_SOCKET_FORCE_FLASH = !!conf.WEB_SOCKET_FORCE_FLASH;
39 | mapping.WEB_XHR_POLLING = !!conf.WEB_XHR_POLLING;
40 | mapping.FORCE_LOCAL_STORAGE = !!conf.FORCE_LOCAL_STORAGE;
41 |
42 | var instance = null;
43 | RongIMClient.getInstance === undefined && (RongIMClient.getInstance = function () {
44 | if (instance == null) {
45 | instance = new RongIMClient(d);
46 | }
47 | return instance;
48 | });
49 | };
50 | //注册自定义消息
51 | RongIMClient.registerMessageType = function (regMsg) {
52 | if (!RongIMClient.getInstance) {
53 | throw new Error("unInitException")
54 | }
55 | if ("messageType" in regMsg && "objectName" in regMsg && "fieldName" in regMsg) {
56 | mapping.registerMessageTypeMapping[regMsg.objectName] = regMsg.messageType;
57 | var temp = RongIMClient[regMsg.messageType] = function (c) {
58 | RongIMClient.RongIMMessage.call(this, c);
59 | RongIMClient.MessageType[regMsg.messageType] = regMsg.messageType;
60 | this.setMessageType(regMsg.messageType);
61 | this.setObjectName(regMsg.objectName);
62 | for (var i = 0; i < regMsg.fieldName.length; i++) {
63 | var item = regMsg.fieldName[i];
64 | this["set" + item] = (function (na) {
65 | return function (a) {
66 | this.setContent(a, na);
67 | }
68 | })(item);
69 | this["get" + item] = (function (na) {
70 | return function () {
71 | return this.getDetail()[na];
72 | }
73 | })(item);
74 | }
75 | };
76 | tool.inherit(temp, RongIMClient.RongIMMessage, true);
77 | } else
78 | throw new Error("registerMessageType:arguments type is error");
79 | };
80 | //设置连接状态监听器
81 | RongIMClient.setConnectionStatusListener = function (a) {
82 | if (!RongIMClient.getInstance) {
83 | throw new Error("unInitException")
84 | }
85 | RongIMClient.getInstance().setConnectionStatusListener(a)
86 | };
87 | window.RongIMClient = RongIMClient;
--------------------------------------------------------------------------------
/src/IMClient/shim.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhangyatao on 16/1/11.
3 | */
4 | //存储会话列表的类
5 | var _func = function () {
6 | //添加会话,当前列表没有该会话则将该会话加到队列最后,有的话将该会话放到队列最开始
7 | this.add = function (x) {
8 | for (var i = 0; i < this.length; i++) {
9 | if (this[i].getTargetId() === x.getTargetId() && i != 0 && this[i].getConversationType() == x.getConversationType()) {
10 | this.unshift(this.splice(i, 1)[0]);
11 | return;
12 | }
13 | }
14 | this.unshift(x);
15 | };
16 | //根据会话类型和tagetid从列表中得到会话
17 | this.get = function (conver, tarid) {
18 | for (var i = 0; i < this.length; i++) {
19 | if (this[i].getTargetId() == tarid && this[i].getConversationType() == conver) {
20 | return this[i]
21 | }
22 | }
23 | return null;
24 | }
25 | };
26 | _func.prototype = [];
27 | //本地会话类型和服务器端会话类型映射关系
28 | var C2S = {
29 | "4": 1,
30 | "2": 2,
31 | "3": 3,
32 | "1": 5
33 | };
34 | var sessionStore = global.sessionStorage || new function () {
35 | var c = {};
36 | this.length = 0;
37 | this.clear = function () {
38 | c = {};
39 | this.length = 0
40 | };
41 | this.setItem = function (e, f) {
42 | !c[e] && this.length++;
43 | c[e] = f;
44 | return e in c
45 | };
46 | this.getItem = function (e) {
47 | return c[e]
48 | };
49 | this.removeItem = function (f) {
50 | if (f in c) {
51 | delete c[f];
52 | this.length--;
53 | return true;
54 | }
55 | return false;
56 | }
57 | };
58 | var LimitableMap = function (limit) {
59 | this.limit = limit || 10;
60 | this.map = {};
61 | this.keys = [];
62 | };
63 | LimitableMap.prototype.set = function (key, value) {
64 | var map = this.map;
65 | var keys = this.keys;
66 | if (!map.hasOwnProperty(key)) {
67 | if (keys.length === this.limit) {
68 | var firstKey = keys.shift();
69 | delete map[firstKey];
70 | }
71 | keys.push(key)
72 | }
73 | map[key] = value;
74 | };
75 | LimitableMap.prototype.get = function (key) {
76 | return this.map[key] || 0;
77 | };
78 | module.exports = {
79 | list: _func,
80 | C2S: C2S,
81 | sessionStore: sessionStore,
82 | LimitableMap: LimitableMap
83 | };
--------------------------------------------------------------------------------
/src/binary.js:
--------------------------------------------------------------------------------
1 | var global = window;
2 | var binaryPot = global.RongBinaryHelper = {
3 | /**
4 | * 初始化字节流,把-128至128的区间改为0-256的区间.便于计算
5 | * @param {Array} array 字节流数组
6 | * @return {Array} 转化好的字节流数组
7 | */
8 | init: function (array) {
9 | for (var i = 0; i < array.length; i++) {
10 | array[i] *= 1;
11 | if (array[i] < 0) {
12 | array[i] += 256
13 | }
14 | if (array[i] > 255) {
15 | throw new Error('不合法字节流')
16 | }
17 | }
18 | return array;
19 | },
20 | /**
21 | * 把一段字符串按照utf8编码写到缓冲区中
22 | * @param {String} str 将要写入缓冲区的字符串
23 | * @param {Boolean} isGetBytes 是否只得到内容字节(不包括最开始的两位占位字节)
24 | * @returns {Array} 字节流
25 | */
26 | writeUTF: function (str, isGetBytes) {
27 | var back = [],
28 | byteSize = 0;
29 | for (var i = 0; i < str.length; i++) {
30 | var code = str.charCodeAt(i);
31 | if (code >= 0 && code <= 127) {
32 | byteSize += 1;
33 | back.push(code);
34 | } else if (code >= 128 && code <= 2047) {
35 | byteSize += 2;
36 | back.push((192 | (31 & (code >> 6))));
37 | back.push((128 | (63 & code)))
38 | } else if (code >= 2048 && code <= 65535) {
39 | byteSize += 3;
40 | back.push((224 | (15 & (code >> 12))));
41 | back.push((128 | (63 & (code >> 6))));
42 | back.push((128 | (63 & code)))
43 | }
44 | }
45 | for (i = 0; i < back.length; i++) {
46 | if (back[i] > 255) {
47 | back[i] &= 255
48 | }
49 | }
50 | if (isGetBytes) {
51 | return back
52 | }
53 | if (byteSize <= 255) {
54 | return [0, byteSize].concat(back);
55 | } else {
56 | return [byteSize >> 8, byteSize & 255].concat(back);
57 | }
58 | },
59 | /**
60 | * 把一串字节流按照utf8编码读取出来
61 | * @param arr 字节流
62 | * @returns {String} 读取出来的字符串
63 | */
64 | readUTF: function (arr) {
65 | if (Object.prototype.toString.call(arr) == "[object String]") {
66 | return arr;
67 | }
68 | var UTF = "",
69 | _arr = this.init(arr);
70 | for (var i = 0; i < _arr.length; i++) {
71 | var one = _arr[i].toString(2),
72 | v = one.match(/^1+?(?=0)/);
73 | if (v && one.length == 8) {
74 | var bytesLength = v[0].length,
75 | store = _arr[i].toString(2).slice(7 - bytesLength);
76 | for (var st = 1; st < bytesLength; st++) {
77 | store += _arr[st + i].toString(2).slice(2)
78 | }
79 | UTF += String.fromCharCode(parseInt(store, 2));
80 | i += bytesLength - 1
81 | } else {
82 | UTF += String.fromCharCode(_arr[i])
83 | }
84 | }
85 | return UTF
86 | },
87 | /**
88 | * 转换成Stream对象
89 | * @param x
90 | * @returns {TinyStream}
91 | */
92 | convertStream: function (x) {
93 | if (x instanceof TinyStream) {
94 | return x
95 | } else {
96 | return new TinyStream(x)
97 | }
98 | },
99 | /**
100 | * 把一段字符串转为mqtt格式
101 | * @param str
102 | * @returns {*|Array}
103 | */
104 | toMQttString: function (str) {
105 | return this.writeUTF(str)
106 | }
107 | };
108 | /**
109 | * 读取指定长度的字节流到指定数组中
110 | * @param {TinyStream} m Stream实例
111 | * @param {number} i 读取的长度
112 | * @param {Array} a 存入的数组
113 | * @returns {Array} 存入的数组
114 | */
115 | function baseRead(m, i, a) {
116 | var t = a ? a : [];
117 | for (var start = 0; start < i; start++) {
118 | t[start] = m.pool[m.position++]
119 | }
120 | return t
121 | }
122 | /**
123 | * 判断浏览器是否支持ArrayBuffer
124 | */
125 | var supportArrayBuffer = (function () {
126 | return !!window.ArrayBuffer;
127 | })();
128 | /**
129 | * 字节流处理实体类
130 | * @param {String|Array} array 初始化字节流,如果是字符串则按照UTF8的格式写入缓冲区
131 | * @constructor
132 | */
133 | function TinyStream(array) {
134 | if (!(this instanceof TinyStream)) {
135 | return new TinyStream(array);
136 | }
137 | /**
138 | * 字节流缓冲区
139 | * @type {Array}
140 | */
141 | this.pool = [];
142 | if (Object.prototype.toString.call(array) === '[object Array]') {
143 | this.pool = binaryPot.init(array);
144 | } else if (Object.prototype.toString.call(array) == "[object ArrayBuffer]") {
145 | var arr = new Int8Array(array);
146 | this.pool = binaryPot.init([].slice.call(arr));
147 | } else if (typeof array === 'string') {
148 | this.pool = binaryPot.writeUTF(array);
149 | }
150 | var self = this;
151 | //当前流执行的起始位置
152 | this.position = 0;
153 | //当前流写入的多少字节
154 | this.writen = 0;
155 | //返回当前流执行的起始位置是否已经大于整个流的长度
156 | this.check = function () {
157 | return self.position >= self.pool.length
158 | };
159 | }
160 | /**
161 | * 强制转换为Stream对象
162 | * @param x
163 | * @returns {*|TinyStream}
164 | */
165 | TinyStream.parse = function (x) {
166 | return binaryPot.convertStream(x);
167 | };
168 | TinyStream.toMQTString = function (x) {
169 | return binaryPot.toMQttString(x);
170 | };
171 | TinyStream.prototype = {
172 | /**
173 | * 从缓冲区读取4个字节的长度并转换为int值,position往后移4位
174 | * @returns {Number} 读取到的数字
175 | * @description 如果position大于等于缓冲区的长度则返回-1
176 | */
177 | readInt: function () {
178 | if (this.check()) {
179 | return -1
180 | }
181 | var end = "";
182 | for (var i = 0; i < 4; i++) {
183 | end += this.pool[this.position++].toString(16)
184 | }
185 | return parseInt(end, 16);
186 | },
187 | /**
188 | * 从缓冲区读取1个字节,position往后移1位
189 | * @returns {Number}
190 | * @description 如果position大于等于缓冲区的长度则返回-1
191 | */
192 | readByte: function () {
193 | if (this.check()) {
194 | return -1
195 | }
196 | var val = this.pool[this.position++];
197 | if (val > 255) {
198 | val &= 255;
199 | }
200 | return val;
201 | },
202 | /**
203 | * 从缓冲区读取1个字节,或读取指定长度的字节到传入的数组中,position往后移1或bytesArray.length位
204 | * @param {Array|undefined} bytesArray
205 | * @returns {Array|Number}
206 | */
207 | read: function (bytesArray) {
208 | if (this.check()) {
209 | return -1
210 | }
211 | if (bytesArray) {
212 | return baseRead(this, bytesArray.length | 0, bytesArray)
213 | } else {
214 | return this.readByte();
215 | }
216 | },
217 | /**
218 | * 从缓冲区的position位置按UTF8的格式读取字符串,position往后移指定的长度
219 | * @returns {String} 读取的字符串
220 | */
221 | readUTF: function () {
222 | var big = (this.readByte() << 8) | this.readByte();
223 | return binaryPot.readUTF(this.pool.slice(this.position, this.position += big));
224 | },
225 | /**
226 | * 把字节流写入缓冲区,writen往后移指定的位
227 | * @param {Number|Array} _byte 写入缓冲区的字节(流)
228 | * @returns {Array} 写入的字节流
229 | */
230 | write: function (_byte) {
231 | var b = _byte;
232 | if (Object.prototype.toString.call(b).toLowerCase() == "[object array]") {
233 | [].push.apply(this.pool, b);
234 | this.writen += b.length;
235 | } else {
236 | if (+b == b) {
237 | if (b > 255) {
238 | b &= 255;
239 | }
240 | this.pool.push(b);
241 | this.writen++
242 | }
243 | }
244 | return b
245 | },
246 | /**
247 | * 把参数当成char类型写入缓冲区,writen往后移2位
248 | * @param {Number} v 写入缓冲区的字节
249 | */
250 | writeChar: function (v) {
251 | if (+v != v) {
252 | throw new Error("writeChar:arguments type is error")
253 | }
254 | this.write((v >> 8) & 255);
255 | this.write(v & 255);
256 | this.writen += 2
257 | },
258 | /**
259 | * 把字符串按照UTF8的格式写入缓冲区,writen往后移指定的位
260 | * @param {String} str 字符串
261 | * @return {Array} 缓冲区
262 | */
263 | writeUTF: function (str) {
264 | var val = binaryPot.writeUTF(str);
265 | [].push.apply(this.pool, val);
266 | this.writen += val.length;
267 | },
268 | /**
269 | * 把缓冲区字节流的格式从0至256的区间改为-128至128的区间
270 | * @returns {Array} 转换后的字节流
271 | */
272 | toComplements: function () {
273 | var _tPool = this.pool;
274 | for (var i = 0; i < _tPool.length; i++) {
275 | if (_tPool[i] > 128) {
276 | _tPool[i] -= 256
277 | }
278 | }
279 | return _tPool
280 | },
281 | /**
282 | * 获取整个缓冲区的字节
283 | * @param {Boolean} isCom 是否转换字节流区间
284 | * @returns {Array} 转换后的缓冲区
285 | */
286 | getBytesArray: function (isCom) {
287 | if (isCom) {
288 | return this.toComplements()
289 | }
290 | return this.pool
291 | },
292 | /**
293 | * 把缓冲区的字节流转换为ArrayBuffer
294 | * @returns {ArrayBuffer}
295 | * @throw {Error} 不支持ArrayBuffer
296 | */
297 | toArrayBuffer: function () {
298 | if (supportArrayBuffer) {
299 | return new ArrayBuffer(this.getBytesArray());
300 | } else {
301 | throw new Error('not support arraybuffer');
302 | }
303 | },
304 | clear: function () {
305 | this.pool = [];
306 | this.writen = this.position = 0;
307 | }
308 | };
309 | module.exports = TinyStream;
--------------------------------------------------------------------------------
/src/core/bridge.js:
--------------------------------------------------------------------------------
1 | var mapping = require('../mapping');
2 | var client = require('./client');
3 | var e = require('../message/msgEnum');
4 | var Qos = e.Qos;
5 |
6 | var Bridge = function (_appkey, _token, _callback) {
7 | this.context = client.connect(_appkey, _token, _callback);
8 | Bridge.getInstance = function () {
9 | return this;
10 | }
11 | };
12 | Bridge.prototype.setListener = function (_changer) {
13 | if (typeof _changer == "object") {
14 | if (typeof _changer.onChanged == 'function') {
15 | mapping._ConnectionStatusListener = _changer;
16 | } else if (typeof _changer.onReceived == 'function') {
17 | mapping._ReceiveMessageListener = _changer;
18 | }
19 | }
20 | };
21 | //重连
22 | Bridge.prototype.reConnect = function (callback) {
23 | this.context.channel.reconnect(callback)
24 | };
25 | //断连
26 | Bridge.prototype.disConnect = function () {
27 | this.context.clearHeartbeat();
28 | this.context.channel.disconnect()
29 | };
30 | //执行queryMessage请求
31 | Bridge.prototype.queryMsg = function (topic, content, targetId, callback, pbname) {
32 | if (typeof topic != "string") {
33 | topic = mapping.topic[topic]
34 | }
35 | this.context.queryMessage(topic, content, targetId, Qos.AT_MOST_ONCE, callback, pbname)
36 | };
37 | //执行publishMessage请求
38 | Bridge.prototype.pubMsg = function (topic, content, targetId, callback, msg) {
39 | this.context.publishMessage(mapping.topic[10][topic], content, targetId, callback, msg)
40 | };
41 | module.exports = Bridge;
42 |
--------------------------------------------------------------------------------
/src/core/channel.js:
--------------------------------------------------------------------------------
1 | var mapping = require('../mapping');
2 | var msgEnum = require('../message/msgEnum');
3 | var factory = require('../io/factory');
4 | var tool = require('../tool');
5 | function Channel(address, cb, self) {
6 | //连接服务器
7 | this.context = self;
8 | this.socket = factory(address.host +
9 | "/websocket?appId=" + this.context.appId +
10 | "&token=" + encodeURIComponent(this.context.token) +
11 | "&sdkVer=" + this.context.sdkVer +
12 | "&apiVer=" + this.context.apiVer,
13 | cb);
14 | //注册状态改变观察者
15 | if ("onChanged" in mapping._ConnectionStatusListener) {
16 | this.socket.on("StatusChanged", function (code) {
17 | //如果参数为DisconnectionStatus,就停止心跳,其他的不停止心跳。每3min连接一次服务器
18 | if (code instanceof msgEnum.DisconnectionStatus) {
19 | mapping._ConnectionStatusListener.onChanged(RongIMClient.ConnectionStatus.setValue(code + 2));
20 | self.clearHeartbeat();
21 | return;
22 | }
23 | mapping._ConnectionStatusListener.onChanged(RongIMClient.ConnectionStatus.setValue(code))
24 | })
25 | } else {
26 | throw new Error("setConnectStatusListener:Parameter format is incorrect")
27 | }
28 | //注册message观察者
29 | this.socket.on("message", this.context.handler.handleMessage);
30 | //注册断开连接观察者
31 | var that = this;
32 | this.socket.on("disconnect", function () {
33 | that.socket.fire("StatusChanged", 4);
34 | });
35 | }
36 | //发送,如果通道可写就发送,不可写就重连服务器
37 | Channel.prototype.writeAndFlush = function (val) {
38 | var that = this;
39 | if (this.isWritable()) {
40 | this.socket.send(val);
41 | } else {
42 | this.reconnect({
43 | onSuccess: function () {
44 | that.socket.send(val);
45 | },
46 | onError: function () {
47 | throw new Error("reconnect fail")
48 | }
49 | })
50 | }
51 | };
52 | //重连并清空messageid
53 | Channel.prototype.reconnect = function (callback) {
54 | tool.messageIdHandler.clearMessageId();
55 | this.socket = this.socket.reconnect();
56 | if (callback) {
57 | mapping.reconnectSet = callback;
58 | }
59 | };
60 | Channel.prototype.disconnect = function (x) {
61 | this.socket.disconnect(x);
62 | };
63 | //通道是否可写
64 | Channel.prototype.isWritable = function () {
65 | return this.socket.connected || this.socket.connecting;
66 | };
67 | module.exports = Channel;
--------------------------------------------------------------------------------
/src/core/client.js:
--------------------------------------------------------------------------------
1 | var entity = require('../message/MessageEntity');
2 | var handler = require('./messageHandler');
3 | var channel = require('./channel');
4 | var ack = require('./messageCallback');
5 | var mapping = require('../mapping');
6 | var md5 = require('../md5');
7 | var tool = require('../tool');
8 | var en = require('../message/msgEnum');
9 | var Qos = en.Qos;
10 | var global = window;
11 | //初始化通道对象
12 | ack.ConnectAck.redirect = function (callback) {
13 | Client.getInstance().channel = new channel(Client.Endpoint, callback, Client.getInstance());
14 | };
15 | //连接端类,逻辑处理全在此类中
16 | function Client(_to, _ap) {
17 | this.timeoutMillis = 100000;
18 | this.timeout_ = 0;
19 | this.appId = _ap;
20 | this.token = _to;
21 | this.sdkVer = "1.0.0";
22 | this.apiVer = "1.0.0";
23 | this.channel = null;
24 | this.handler = null;
25 | this.userId = "";
26 | this.heartbeat = 0;
27 | this.chatroomId = '';
28 | //用于心跳启动定时器
29 | }
30 | Client.prototype.resumeTimer = function () {
31 | var self = this;
32 | if (!this.timeout_) {
33 | this.timeout_ = setTimeout(function () {
34 | if (!self.timeout_) {
35 | return;
36 | }
37 | try {
38 | self.channel.disconnect()
39 | } catch (e) {
40 | }
41 | clearTimeout(self.timeout_);
42 | self.timeout_ = 0;
43 | self.channel.reconnect();
44 | self.channel.socket.fire("StatusChanged", 5);
45 | }, self.timeoutMillis)
46 | }
47 | };
48 | //销毁心跳定时器
49 | Client.prototype.pauseTimer = function () {
50 | if (this.timeout_) {
51 | clearTimeout(this.timeout_);
52 | this.timeout_ = 0;
53 | }
54 | };
55 | //连接服务器
56 | Client.prototype.connect = function (_callback) {
57 | var self = this;
58 | //判断navi是否已经返回地址
59 | if (mapping.Endpoint.host) {
60 | if (tool.getTransportType() == "websocket") {
61 | if (!global.WebSocket) {
62 | _callback.onError(RongIMClient.ConnectErrorStatus.setValue(1));
63 | return;
64 | }
65 | //判断是否是flashsocket 是的话就加载代理文件
66 | 'loadFlashPolicyFile' in WebSocket && WebSocket.loadFlashPolicyFile();
67 | }
68 | //实例消息处理类
69 | this.handler = new handler(this);
70 | //设置连接回调
71 | this.handler.setConnectCallback(_callback);
72 | //实例通道类型
73 | this.channel = new channel(mapping.Endpoint, function () {
74 | tool.getTransportType() == "websocket" && self.keepLive()
75 | }, this);
76 | //触发状态改变观察者
77 | this.channel.socket.fire("StatusChanged", 1)
78 | } else {
79 | //没有返回地址就手动抛出错误
80 | _callback.onError(RongIMClient.ConnectErrorStatus.setValue(5));
81 | }
82 | };
83 | //心跳启动方法
84 | Client.prototype.keepLive = function () {
85 | var self = this;
86 | if (this.heartbeat > 0) {
87 | clearInterval(this.heartbeat);
88 | }
89 | this.heartbeat = setInterval(function () {
90 | self.resumeTimer();
91 | self.channel.writeAndFlush(new entity.PingReqMessage());
92 | console.log("keep live pingReqMessage sending appId " + self.appId);
93 | }, 180000);
94 | };
95 | //心跳停止方法
96 | Client.prototype.clearHeartbeat = function () {
97 | clearInterval(this.heartbeat);
98 | this.heartbeat = 0;
99 | this.pauseTimer();
100 | };
101 | //发送publishMessage消息
102 | Client.prototype.publishMessage = function (_topic, _data, _targetId, _callback, _msg) {
103 | var msgId = tool.messageIdHandler.messageIdPlus(this.channel.reconnect);
104 | if (!msgId) {
105 | return;
106 | }
107 | var msg = new entity.PublishMessage(_topic, _data, _targetId);
108 | msg.setMessageId(msgId);
109 | if (_callback) {
110 | msg.setQos(Qos.AT_LEAST_ONCE);
111 | this.handler.putCallback(new ack.PublishCallback(_callback.onSuccess, _callback.onError), msg.getMessageId(), _msg)
112 | } else {
113 | msg.setQos(Qos.AT_MOST_ONCE);
114 | }
115 | this.channel.writeAndFlush(msg);
116 | };
117 | //发送queryMessage消息
118 | Client.prototype.queryMessage = function (_topic, _data, _targetId, _qos, _callback, pbtype) {
119 | //如果topic是userinfo,就去userinfo缓存对象里拿,没有的话再去请求服务器拉取userinfo
120 | if (_topic == "userInf") {
121 | if (mapping.userInfoMapping[_targetId]) {
122 | _callback.onSuccess(mapping.userInfoMapping[_targetId]);
123 | return;
124 | }
125 | }
126 | var msgId = tool.messageIdHandler.messageIdPlus(this.channel.reconnect);
127 | if (!msgId) {
128 | return;
129 | }
130 | var msg = new entity.QueryMessage(_topic, _data, _targetId);
131 | msg.setMessageId(msgId);
132 | msg.setQos(_qos);
133 | this.handler.putCallback(new ack.QueryCallback(_callback.onSuccess, _callback.onError), msg.getMessageId(), pbtype);
134 | this.channel.writeAndFlush(msg)
135 | };
136 | //同步消息
137 | Client.prototype.syncTime = function (_type, pullTime) {
138 | SyncTimeQueue.push({type: _type, pulltime: pullTime});
139 | //如果队列中只有一个成员并且状态已经完成就执行invoke方法
140 | if (SyncTimeQueue.length == 1 && SyncTimeQueue.state == "complete") {
141 | invoke()
142 | }
143 | };
144 | //声明Client.connect静态方法,返回Client实例
145 | Client.connect = function (appId, token, callback) {
146 | //如果appid和本地存储的不一样,清空所有本地存储数据
147 | var oldAppId = tool.cookieHelper.getItem("appId");
148 | if (oldAppId && oldAppId != appId) {
149 | tool.cookieHelper.clear();
150 | tool.cookieHelper.setItem("appId", appId);
151 | }
152 | var client = new Client(token, appId);
153 | Client.getInstance = function () {
154 | return client;
155 | };
156 | //请求navi导航
157 | Client.getServerEndpoint(token, appId, callback, true);
158 | return client;
159 | };
160 | Client.getServerEndpoint = function (_token, _appId, callback, unignore) {
161 | if (unignore) {
162 | //根据token生成MD5截取8-16下标的数据与本地存储的导航信息进行比对
163 | //如果信息和上次的通道类型都一样,不执行navi请求,用本地存储的导航信息连接服务器
164 | var naviStr = md5(_token).slice(8, 16),
165 | _old = tool.cookieHelper.getItem("navi\\w+?"),
166 | _new = tool.cookieHelper.getItem("navi" + naviStr);
167 | if (_old == _new && _new !== null && tool.cookieHelper.getItem("rongSDK") == tool.getTransportType()) {
168 | var obj = unescape(_old).split(",");
169 | setTimeout(function () {
170 | RongBinaryHelper.__host = mapping.Endpoint.host = obj[0];
171 | mapping.Endpoint.userId = obj[1];
172 | Client.getInstance().connect(callback);
173 | }, 500);
174 | return;
175 | }
176 | }
177 | //导航信息,切换Url对象的key进行线上线下测试操作
178 | var Url = {
179 | //测试环境
180 | "navUrl-Debug": "http://nav.sunquan.rongcloud.net:9001/",
181 | //线上环境
182 | "navUrl-Release": "http://nav.cn.rong.io/"
183 | };
184 | tool.jsonp(Url["navUrl-Release"] +
185 | (tool.getTransportType() == "xhr-polling" ? "cometnavi.js" : "navi.js") +
186 | "?appId=" + _appId + "&token=" + encodeURIComponent(_token),
187 | "callBack",
188 | function (data) {
189 | Client.getInstance().connect(callback);
190 | //把导航返回的server字段赋值给RongBinaryHelper.__host,因为flash widget需要使用
191 | RongBinaryHelper.__host = mapping.Endpoint.host = data["server"];
192 | mapping.Endpoint.userId = data.userId;
193 | //替换本地存储的导航信息
194 | var temp = document.cookie.match(new RegExp("(^| )navi\\w+?=([^;]*)(;|$)"));
195 | temp !== null && tool.cookieHelper.removeItem(temp[0].split("=")[0].replace(/^\s/, ""));
196 | tool.cookieHelper.setItem("navi" + md5(Client.getInstance().token).slice(8, 16), data["server"] + "," + (data.userId || ""));
197 | }, function () {
198 | callback.onError(RongIMClient.ConnectErrorStatus.setValue(4));
199 | });
200 | };
201 | //同步消息队列
202 | var SyncTimeQueue = [];
203 | //队列的执行状态
204 | SyncTimeQueue.state = "complete";
205 | function invoke() {
206 | var time, modules, str, target;
207 | //从队列开头取出一个赋值给temp变量
208 | var temp = SyncTimeQueue.shift();
209 | var self = Client.getInstance();
210 | if (!temp) {
211 | return;
212 | }
213 | //改变状态为pending
214 | SyncTimeQueue.state = "pending";
215 | if (temp.type != 2) {
216 | //普通消息
217 | time = tool.cookieHelper.getItem(self.userId) || 0;
218 | modules = new Modules.SyncRequestMsg();
219 | modules.setIspolling(false);
220 | str = 'pullMsg';
221 | target = self.userId;
222 | } else {
223 | //聊天室消息
224 | time = tool.cookieHelper.getItem(self.userId + "CST") || 0;
225 | modules = new Modules.ChrmPullMsg();
226 | modules.setCount(0);
227 | str = 'chrmPull';
228 | if (self.chatroomId === '') {
229 | //受到聊天室消息,但是本地没有加入聊天室就手动抛出一个错误
230 | throw new Error("syncTime:Received messages of chatroom but was not init");
231 | }
232 | target = self.chatroomId;
233 | }
234 | //判断服务器给的时间是否消息本地存储的时间,小于的话不执行拉取操作,进行一下步队列操作
235 | if (temp.pulltime <= time) {
236 | SyncTimeQueue.state = "complete";
237 | invoke();
238 | return;
239 | }
240 | modules.setSyncTime(time);
241 | //发送queryMessage请求
242 | self.queryMessage(str, tool.arrayFrom(modules.toArrayBuffer()), target, Qos.AT_LEAST_ONCE, {
243 | onSuccess: function (collection) {
244 | var sync = tool.int64ToTimestamp(collection.syncTime),
245 | symbol = self.userId;
246 | if (str == "chrmPull") {
247 | symbol += 'CST';
248 | }
249 | //把返回时间戳存入本地,普通消息key为userid,聊天室消息key为userid+'CST';value都为服务器返回的时间戳
250 | tool.cookieHelper.setItem(symbol, sync);
251 | //把拉取到的消息逐条传给消息监听器
252 | var list = collection.list;
253 | for (var i = 0; i < list.length; i++) {
254 | Client.getInstance().handler.onReceived(list[i])
255 | }
256 | SyncTimeQueue.state = "complete";
257 | invoke();
258 | },
259 | onError: function () {
260 | SyncTimeQueue.state = "complete";
261 | invoke();
262 | }
263 | }, "DownStreamMessages");
264 | }
265 | module.exports = Client;
--------------------------------------------------------------------------------
/src/core/messageCallback.js:
--------------------------------------------------------------------------------
1 | var tool = require('../tool');
2 | var mapping = require('../mapping');
3 | var factory = require('../io/factory');
4 | //protobuf映射
5 | function callbackMapping(entity, tag) {
6 | switch (tag) {
7 | case "GetUserInfoOutput":
8 | var userInfo = new RongIMClient.UserInfo();
9 | userInfo.setUserId(entity.userId);
10 | userInfo.setUserName(entity.userName);
11 | userInfo.setPortraitUri(entity.userPortrait);
12 | return userInfo;
13 | case "GetQNupTokenOutput":
14 | return {
15 | deadline: util.int64ToTimestamp(entity.deadline),
16 | token: entity.token
17 | };
18 | case "GetQNdownloadUrlOutput":
19 | return {
20 | downloadUrl: entity.downloadUrl
21 | };
22 | case "CreateDiscussionOutput":
23 | return entity.id;
24 | case "ChannelInfoOutput":
25 | var disInfo = new RongIMClient.Discussion();
26 | disInfo.setCreatorId(entity.adminUserId);
27 | disInfo.setId(entity.channelId);
28 | disInfo.setMemberIdList(entity.firstTenUserIds);
29 | disInfo.setName(entity.channelName);
30 | disInfo.setOpen(RongIMClient.DiscussionInviteStatus.setValue(entity.openStatus));
31 | return disInfo;
32 | case "GroupHashOutput":
33 | return entity.result;
34 | case "QueryBlackListOutput":
35 | return entity.userIds;
36 | default:
37 | return entity;
38 | }
39 | }
40 | function MessageCallback(error) {
41 | var timeoutMillis, me = this;
42 | this.timeout = null;
43 | this.onError = null;
44 | if (error && typeof error == "number") {
45 | timeoutMillis = error
46 | } else {
47 | timeoutMillis = 6000;
48 | this.onError = error;
49 | }
50 | this.resumeTimer = function () {
51 | if (timeoutMillis > 0 && !this.timeout) {
52 | this.timeout = setTimeout(function () {
53 | me.readTimeOut(true);
54 | }, timeoutMillis)
55 | }
56 | }
57 | }
58 | MessageCallback.prototype = {
59 | pauseTimer: function () {
60 | if (this.timeout) {
61 | clearTimeout(this.timeout);
62 | this.timeout = null
63 | }
64 | }, readTimeOut: function (isTimeout) {
65 | if (isTimeout && this.onError) {
66 | this.onError(RongIMClient.callback.ErrorCode.TIMEOUT)
67 | } else {
68 | this.pauseTimer()
69 | }
70 | }
71 | };
72 | //发送PublishMessage消息回调类
73 | function PublishCallback(cb, _timeout) {
74 | MessageCallback.call(this, _timeout);
75 | this.done = cb || function () {
76 | };
77 | this.fail = _timeout || function () {
78 | };
79 | }
80 | tool.inherit(PublishCallback, MessageCallback);
81 | PublishCallback.prototype.process = function (_staus, _serverTime, _msg) {
82 | this.readTimeOut();
83 | if (_staus == 0) {
84 | if (_msg) {
85 | //把发送的消息发送状态改为已接收
86 | _msg.setSentStatus(RongIMClient.SentStatus.RECEIVED)
87 | }
88 | this.done();
89 | } else {
90 | this.fail(RongIMClient.SendErrorStatus.setValue(_staus));
91 | }
92 | };
93 | PublishCallback.prototype.readTimeOut = function (x) {
94 | PublishCallback.super_.prototype.readTimeOut.call(this, x)
95 | };
96 |
97 | //发送QueryMessage消息回调类
98 | function QueryCallback(cb, _timeout) {
99 | MessageCallback.call(this, _timeout);
100 | this.done = cb || function () {
101 | };
102 | this.fail = _timeout || function () {
103 | };
104 | }
105 | tool.inherit(QueryCallback, MessageCallback);
106 | QueryCallback.prototype.process = function (status, data, serverTime, pbtype) {
107 | this.readTimeOut();
108 | if (pbtype && data && status == 0) {
109 | try {
110 | data = callbackMapping(Modules[pbtype].decode(data), pbtype);
111 | } catch (e) {
112 | this.fail(RongIMClient.callback.ErrorCode.UNKNOWN_ERROR);
113 | return;
114 | }
115 | if ("GetUserInfoOutput" == pbtype) {
116 | //pb类型为GetUserInfoOutput的话就把data放入userinfo缓存队列
117 | mapping.userInfoMapping[data.getUserId()] = data;
118 | }
119 | this.done(data);
120 | } else {
121 | status > 0 ? this.fail(status) : this.done(status)
122 | }
123 | };
124 | QueryCallback.prototype.readTimeOut = function (x) {
125 | QueryCallback.super_.prototype.readTimeOut.call(this, x)
126 | };
127 |
128 | //连接回调类
129 | function ConnectAck(cb, _timeout, context) {
130 | MessageCallback.call(this, _timeout);
131 | this.context = context;
132 | this.done = cb || function () {
133 | };
134 | this.fail = _timeout || function () {
135 | };
136 | }
137 | tool.inherit(ConnectAck, MessageCallback);
138 | ConnectAck.prototype.process = function (status, userId) {
139 | this.readTimeOut();
140 | if (status == 0) {
141 | mapping.userId = this.context.userId = userId;
142 | if (!RongIMClient.isNotPullMsg) {
143 | this.context.syncTime();
144 | }
145 | if (mapping.reconnectSet.onSuccess) {
146 | mapping.reconnectSet.onSuccess(userId);
147 | try {
148 | delete mapping.reconnectSet.onSuccess;
149 | } catch (e) {
150 | }
151 | } else {
152 | this.done(userId);
153 | }
154 | factory.getInstance().fire("StatusChanged", 0);
155 | factory.getInstance()._doQueue()
156 | } else if (status == 6) {
157 | var that = this;
158 | ConnectAck.redirect(this.context.token, this.context.appId, function () {
159 | that.context.clearHeartbeat();
160 | ConnectAck.redirect();
161 | that.context.channel.socket.fire("StatusChanged", 2);
162 | }, function () {
163 | that.fail();
164 | }, false);
165 | } else {
166 | if (mapping.reconnectSet.onError) {
167 | mapping.reconnectSet.onError(RongIMClient.ConnectErrorStatus.setValue(status));
168 | delete mapping.reconnectSet.onError;
169 | } else {
170 | this.fail(RongIMClient.ConnectErrorStatus.setValue(status))
171 | }
172 | }
173 | };
174 | ConnectAck.prototype.readTimeOut = function (x) {
175 | ConnectAck.super_.prototype.readTimeOut.call(this, x)
176 | };
177 | ConnectAck.redirect = function () {
178 | };
179 |
180 | module.exports = {
181 | MessageCallback: MessageCallback,
182 | PublishCallback: PublishCallback,
183 | QueryCallback: QueryCallback,
184 | ConnectAck: ConnectAck
185 | };
--------------------------------------------------------------------------------
/src/core/messageHandler.js:
--------------------------------------------------------------------------------
1 | var parser = require('./messageParser');
2 | var mapping = require('../mapping');
3 | var ack = require('./messageCallback');
4 | var tool = require('../tool');
5 | var entity=require('../message/MessageEntity');
6 | var self = null;
7 | function MessageHandler(client) {
8 | if (!mapping._ReceiveMessageListener) {
9 | throw new Error("please set onReceiveMessageListener");
10 | }
11 | self = this;
12 | this.context = client;
13 | this._map = {};
14 | this._onReceived = mapping._ReceiveMessageListener.onReceived;
15 | this.connectCallback = null;
16 | }
17 | MessageHandler.prototype.putCallback = function (callbackObj, _publishMessageId, _msg) {
18 | var item = {
19 | Callback: callbackObj,
20 | Message: _msg
21 | };
22 | item.Callback.resumeTimer();
23 | this._map[_publishMessageId] = item;
24 | };
25 | //设置连接回调对象,启动定时器
26 | MessageHandler.prototype.setConnectCallback = function (_connectCallback) {
27 | if (_connectCallback) {
28 | this.connectCallback = new ack.ConnectAck(_connectCallback.onSuccess, _connectCallback.onError, this.context);
29 | this.connectCallback.resumeTimer();
30 | }
31 | };
32 | //处理具体的消息对象
33 | MessageHandler.prototype.onReceived = function (msg) {
34 | //实体对象
35 | var entity;
36 | if (msg.constructor._name != "PublishMessage") {
37 | //如果msg不是一个内置消息对象,直接赋值给实体,进行下一步处理
38 | entity = msg;
39 | tool.cookieHelper.setItem(this.context.userId, tool.int64ToTimestamp(entity.dataTime));
40 | } else {
41 | if (msg.getTopic() == "s_ntf") {
42 | entity = Modules.NotifyMsg.decode(msg.getData());
43 | this.context.syncTime(entity.type, tool.int64ToTimestamp(entity.time));
44 | return;
45 | } else if (msg.getTopic() == "s_msg") {
46 | entity = Modules.DownStreamMessage.decode(msg.getData());
47 | tool.cookieHelper.setItem(this.context.userId, tool.int64ToTimestamp(entity.dataTime));
48 | } else {
49 | return;
50 | }
51 | }
52 | //解析实体对象为消息对象。
53 | var message = parser(entity);
54 | if (message.getObjectName() in mapping.sysNtf) {
55 | this._onReceived(message);
56 | return;
57 | }
58 | //创建会话对象
59 | var con = RongIMClient.getInstance().getConversationList().get(message.getConversationType(), message.getTargetId());
60 | if (!con) {
61 | con = RongIMClient.getInstance().createConversation(message.getConversationType(), message.getTargetId(), "");
62 | }
63 | //根据messageTag判断是否进行消息数累加
64 | if (/ISCOUNTED/.test(message.getMessageTag())) {
65 | con.getConversationType() != 0 && con.setUnreadMessageCount(con.getUnreadMessageCount() + 1);
66 | }
67 | con.setReceivedTime((new Date).getTime());
68 | con.setReceivedStatus(new RongIMClient.ReceivedStatus());
69 | con.setSenderUserId(message.getSenderUserId());
70 | con.setObjectName(message.getObjectName());
71 | con.setNotificationStatus(RongIMClient.ConversationNotificationStatus.DO_NOT_DISTURB);
72 | con.setLatestMessageId(message.getMessageId());
73 | con.setLatestMessage(message);
74 | con.setTop();
75 | //把消息传递给消息监听器
76 | this._onReceived(message);
77 | };
78 | //处理通道对象传送过来的内置消息对象
79 | MessageHandler.prototype.handleMessage = function (msg) {
80 | if (!msg) {
81 | return
82 | }
83 | switch (msg.constructor._name) {
84 | case "ConnAckMessage":
85 | self.connectCallback.process(msg.getStatus(), msg.getUserId());
86 | break;
87 | case "PublishMessage":
88 | if (msg.getQos() != 0) {
89 | self.context.channel.writeAndFlush(new entity.PubAckMessage(msg.getMessageId()));
90 | }
91 | //如果是PublishMessage就把该对象给onReceived方法执行处理
92 | self.onReceived(msg);
93 | break;
94 | case "QueryAckMessage":
95 | if (msg.getQos() != 0) {
96 | self.context.channel.writeAndFlush(new entity.QueryConMessage(msg.getMessageId()))
97 | }
98 | var temp = self._map[msg.getMessageId()];
99 | if (temp) {
100 | //执行回调操作
101 | temp.Callback.process(msg.getStatus(), msg.getData(), msg.getDate(), temp.Message);
102 | delete self._map[msg.getMessageId()];
103 | }
104 | break;
105 | case "PubAckMessage":
106 | var item = self._map[msg.getMessageId()];
107 | if (item) {
108 | //执行回调操作
109 | item.Callback.process(msg.getStatus() || 0, msg.getDate(), item.Message);
110 | delete self._map[msg.getMessageId()];
111 | }
112 | break;
113 | case "PingRespMessage":
114 | self.context.pauseTimer();
115 | break;
116 | case "DisconnectMessage":
117 | self.context.channel.disconnect(msg.getStatus());
118 | break;
119 | default:
120 | }
121 | };
122 | module.exports = MessageHandler;
--------------------------------------------------------------------------------
/src/core/messageParser.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhangyatao on 16/1/7.
3 | */
4 |
5 | var com = require('../mapping');
6 | var tool=require('../tool');
7 | //消息转换方法
8 | function messageParser(entity) {
9 | var message, content = entity.content;
10 | var result, objectName = entity.classname;
11 |
12 | try {
13 | result = JSON.parse(RongBinaryHelper.readUTF(content.offset ? tool.arrayFrom(content.buffer).slice(content.offset, content.limit) : content))
14 | } catch (ex) {
15 | return null;
16 | }
17 |
18 | //处理表情
19 | if ("Expression" in RongIMClient && "RC:TxtMsg" == objectName && result.content) {
20 | result.content = result.content.replace(/[\uf000-\uf700]/g, function (x) {
21 | return RongIMClient.Expression.calcUTF(x) || x;
22 | })
23 | }
24 |
25 | //映射为具体消息对象
26 | if (objectName in com.typeMapping) {
27 | message = new RongIMClient[com.typeMapping[objectName]](result);
28 | } else if (objectName in com.sysNtf) {
29 | message = new RongIMClient[com.sysNtf[objectName]](result);
30 | } else if (objectName in com.registerMessageTypeMapping) {
31 | //自定义消息
32 | message = new RongIMClient[com.registerMessageTypeMapping[objectName]](result);
33 | } else {
34 | //未知消息
35 | message = new RongIMClient.UnknownMessage(result, objectName);
36 | }
37 |
38 | //根据实体对象设置message对象
39 | message.setSentTime(tool.int64ToTimestamp(entity.dataTime));
40 | message.setSenderUserId(entity.fromUserId);
41 | message.setConversationType(RongIMClient.ConversationType.setValue(com.mapping[entity.type]));
42 | message.setTargetId(/^[234]$/.test(entity.type || entity.getType()) ? entity.groupId : message.getSenderUserId());
43 | if (entity.fromUserId == com.userId) {
44 | message.setMessageDirection(RongIMClient.MessageDirection.SEND);
45 | } else {
46 | message.setMessageDirection(RongIMClient.MessageDirection.RECEIVE);
47 | }
48 | message.setReceivedTime((new Date).getTime());
49 | message.setMessageId(message.getConversationType() + "_" + ~~(Math.random() * 0xffffff));
50 | message.setReceivedStatus(new RongIMClient.ReceivedStatus());
51 | return message;
52 | }
53 | module.exports = messageParser;
--------------------------------------------------------------------------------
/src/enum.js:
--------------------------------------------------------------------------------
1 | function inherit(superCtor) {
2 | var f = function () {
3 | };
4 | f.prototype = superCtor;
5 | return new f;
6 | }
7 | var Enum = function (namesToValues) {
8 | var enumeration = function () {
9 | throw "can't Instantiate Enumerations";
10 | };
11 | enumeration.setValue = function (x) {
12 | var val = null;
13 | enumeration.foreach(function (i) {
14 | if (i.value == x || i.name == x) {
15 | val = enumeration[i.name];
16 | }
17 | }, null);
18 | return val;
19 | };
20 |
21 |
22 | var proto = enumeration.prototype = {
23 | constructor: enumeration,
24 | toString: function () {
25 | return this.name;
26 | },
27 | valueOf: function () {
28 | return this.value;
29 | },
30 | toJSON: function () {
31 | return this.name;
32 | }
33 | };
34 | enumeration.values = [];
35 | for (var _name in namesToValues) {
36 | var e = inherit(proto);
37 | e.name = _name;
38 | e.value = namesToValues[_name];
39 | enumeration[_name] = e;
40 | enumeration.values.push(e);
41 | }
42 | enumeration.foreach = function (f, c) {
43 | for (var i = 0; i < this.values.length; i++) {
44 | f.call(c, this.values[i]);
45 | }
46 | };
47 | return enumeration;
48 | };
49 | module.exports = Enum;
--------------------------------------------------------------------------------
/src/io/base.js:
--------------------------------------------------------------------------------
1 | var util = require('../tool');
2 | var IOstream = require('../Message/throttleStream');
3 | var mapping=require('../mapping');
4 | var global = window;
5 | //获取消息id标识符对象,如果是comet消息通道就将messageid放入本地存储(localstorage或cookie)中。其他消息通道则放入内存中。
6 |
7 | var Transport = function (base, options) {
8 | this.base = base;
9 | this.options = {
10 | timeout: 30000
11 | };
12 | util.merge(this.options, options)
13 | };
14 | Transport.prototype.send = function () {
15 | throw new Error("No rewrite send() method")
16 | };
17 | Transport.prototype.connect = function () {
18 | throw new Error("No rewrite connect() method")
19 | };
20 | Transport.prototype.disconnect = function () {
21 | throw new Error("No rewrite disconnect() method")
22 | };
23 | //此方法只有comet用到
24 | Transport.prototype._encode = function (x) {
25 | var str = "?messageid=" + x.getMessageId() + "&header=" + x.getHeaderFlag() + "&sessionid=" + util.cookieHelper.getItem(mapping.Endpoint.userId + "sId");
26 | if (!/(PubAckMessage|QueryConMessage)/.test(x.constructor._name)) {
27 | str += "&topic=" + x.getTopic() + "&targetid=" + (x.getTargetId() || "");
28 | }
29 | return {
30 | url: str,
31 | data: "getData" in x ? x.getData() : ""
32 | };
33 | };
34 | //转化服务器返回的二进制数组为一个具体的消息对象
35 | Transport.prototype._decode = function (data) {
36 | if (!data) {
37 | return;
38 | }
39 | if (util.isArray(data)) {
40 | this._onMessage(new IOstream.MessageInputStream(data).readMessage());
41 | } else if (util.getType(data) === "ArrayBuffer") {
42 | this._onMessage(new IOstream.MessageInputStream(util.arrayFrom(data)).readMessage());
43 | }
44 | };
45 | //此方法只有comet用到。接收服务器返回的json对象
46 | Transport.prototype._onData = function (data, header) {
47 | if (!data || data == "lost params") {
48 | return;
49 | }
50 | if (header) {
51 | util.cookieHelper.getItem(mapping.Endpoint.userId + "sId") || util.cookieHelper.setItem(mapping.Endpoint.userId + "sId", header);
52 | }
53 | var self = this, val = util.JSON.parse(data);
54 | if (!util.isArray(val)) {
55 | val = [val];
56 | }
57 | util.forEach(val, function (x) {
58 | self._onMessage(new IOstream.MessageInputStream(x, true).readMessage());
59 | });
60 | };
61 | Transport.prototype._onMessage = function (message) {
62 | this.base._onMessage(message)
63 | };
64 | Transport.prototype._onConnect = function () {
65 | this.connected = true;
66 | this.connecting = false;
67 | this.base._onConnect()
68 | };
69 | Transport.prototype._onDisconnect = function () {
70 | this.connecting = false;
71 | this.connected = false;
72 | this.base._onDisconnect()
73 | };
74 | Transport.prototype._baseConnect = function () {
75 | this.base.connect(null, null);
76 | };
77 |
78 | module.exports = Transport;
--------------------------------------------------------------------------------
/src/io/factory.js:
--------------------------------------------------------------------------------
1 | //var io = require('./base');
2 | var util = require('../tool');
3 | var WS = require('./websocket');
4 | var XHR = require('./polling');
5 | var _Transport = {
6 | 'websocket': WS,
7 | 'xhr-polling': XHR
8 | };
9 | var Socket = function () {
10 | this.options = {
11 | token: "",
12 | transports: ["websocket", "xhr-polling"]//主要有两种(websocket,flashsocket)、comet
13 | };
14 | this.connected = false;
15 | this.connecting = false;
16 | this._events = {};
17 | this.currentURL = "";
18 | this.transport = this.getTransport(util.getTransportType());
19 | if (this.transport === null) {
20 | throw new Error("the channel was not supported")
21 | }
22 | };
23 | //此方法用于生产通道对象
24 | Socket.prototype.getTransport = function (override) {
25 | var i = 0,
26 | transport = override || this.options.transports[i];
27 | if (_Transport[transport] && _Transport[transport].check() && _Transport[transport].XDomainCheck()) {
28 | return new _Transport[transport](this, {})
29 | }
30 | return null;
31 | };
32 | //连接服务器
33 | Socket.prototype.connect = function (url, cb) {
34 | if (this.transport && arguments.length == 2) {
35 | if (url) {
36 | this.on("connect", cb || function () {
37 | })
38 | }
39 | if (this.connecting || this.connected) {
40 | this.disconnect()
41 | }
42 | this.connecting = true;
43 | if (url) {
44 | this.currentURL = url
45 | }
46 | this.transport.connect(this.currentURL); //是否重连
47 | }
48 | return this
49 | };
50 | Socket.prototype.send = function (data) {
51 | if (!this.transport || !this.connected) {
52 | //如果通道不可用,把消息压入队列中,等到通道可用时处理
53 | return this._queue(data)
54 | }
55 | this.transport.send(data)
56 | };
57 | Socket.prototype.disconnect = function (callback) {
58 | if (callback) {
59 | //出发状态改变观察者
60 | this.fire("StatusChanged", callback)
61 | }
62 | this.transport.disconnect();
63 | return this;
64 | };
65 | Socket.prototype.reconnect = function () {
66 | if (this.currentURL) {
67 | return this.connect(null, null);
68 | } else {
69 | throw new Error("reconnect:no have URL");
70 | }
71 | };
72 | Socket.prototype.fire = function (x, args) {
73 | if (x in this._events) {
74 | for (var i = 0, ii = this._events[x].length; i < ii; i++) {
75 | this._events[x][i](args);
76 | }
77 | }
78 | return this
79 | };
80 | Socket.prototype.removeEvent = function (x, fn) {
81 | if (x in this._events) {
82 | for (var a = 0, l = this._events[x].length; a < l; a++) {
83 | if (this._events[x][a] == fn) {
84 | this._events[x].splice(a, 1)
85 | }
86 | }
87 | }
88 | return this
89 | };
90 | Socket.prototype._queue = function (message) {
91 | if (!("_queueStack" in this)) {
92 | this._queueStack = []
93 | }
94 | this._queueStack.push(message);
95 | return this
96 | };
97 | Socket.prototype._doQueue = function () {
98 | if (!("_queueStack" in this) || !this._queueStack.length) {
99 | return this
100 | }
101 | for (var i = 0; i < this._queueStack.length; i++) {
102 | this.transport.send(this._queueStack[i])
103 | }
104 | this._queueStack = [];
105 | return this
106 | };
107 | Socket.prototype._onConnect = function () {
108 | this.connected = true;
109 | this.connecting = false;
110 | util.cookieHelper.setItem("rongSDK",util.getTransportType());
111 | this.fire("connect");
112 | };
113 | Socket.prototype._onMessage = function (data) {
114 | this.fire("message", data)
115 | };
116 | Socket.prototype._onDisconnect = function () {
117 | var wasConnected = this.connected;
118 | this.connected = false;
119 | this.connecting = false;
120 | this._queueStack = [];
121 | if (wasConnected) {
122 | this.fire("disconnect")
123 | }
124 | };
125 | //注册观察者
126 | Socket.prototype.on = function (x, func) {
127 | if (!(typeof func == "function" && x)) {
128 | return this
129 | }
130 | if (x in this._events) {
131 | util.indexOf(this._events, func) == -1 && this._events[x].push(func)
132 | } else {
133 | this._events[x] = [func];
134 | }
135 | return this
136 | };
137 |
138 | var connect = function (token, args) {
139 | var instance = new Socket();
140 | connect.getInstance = function () {
141 | return instance
142 | };
143 | instance.connect(token, args);
144 | return instance;
145 | };
146 |
147 | module.exports = connect;
--------------------------------------------------------------------------------
/src/io/polling.js:
--------------------------------------------------------------------------------
1 | var Transport = require('./base');
2 | var util = require('../tool');
3 | var mapping=require('../mapping');
4 | var global = window;
5 | var empty = new Function;
6 | //利用withCredentials判断是否支持跨域操作
7 | var XMLHttpRequestCORS = (function () {
8 | if (!('XMLHttpRequest' in global))
9 | return false;
10 | var a = new XMLHttpRequest();
11 | return a.withCredentials !== undefined;
12 | })();
13 | //生成跨域传输对象
14 | var request = function () {
15 | if ('XDomainRequest' in global)
16 | return new global["XDomainRequest"]();
17 | if ('XMLHttpRequest' in global && XMLHttpRequestCORS)
18 | return new XMLHttpRequest();
19 | return false;
20 | };
21 | var XHR = Transport.XHR = function () {
22 | Transport.apply(this, arguments);
23 | };
24 | util.inherit(XHR, Transport);
25 | //comet链接服务器,先从本地存储对象里是否存有当前登陆人员的sessionid,如果有的话就不再从服务器申请sessionid,直接用本地存储的sessionid链接服务器。
26 | XHR.prototype.connect = function (url) {
27 | var sid = util.cookieHelper.getItem(mapping.Endpoint.userId + "sId"),
28 | _that = this;
29 | if (sid) {
30 | //io.getInstance().currentURL = url;
31 | setTimeout(function () {
32 | _that.onopen("{\"status\":0,\"userId\":\"" + mapping.Endpoint.userId + "\",\"headerCode\":32,\"messageId\":0,\"sessionid\":\"" + sid + "\"}");
33 | _that._onConnect();
34 | }, 500);
35 | return this;
36 | }
37 | this._get(url);
38 | return this;
39 | };
40 | XHR.prototype._checkSend = function (data) {
41 | //格式化数据为comet指定的数据格式,然后发送
42 | var encoded = this._encode(data);
43 | this._send(encoded);
44 | };
45 | XHR.prototype.send = function (data) {
46 | this._checkSend(data);
47 | return this;
48 | };
49 | //利用post方法发送数据,有数据返回就执行_onData(responseText)方法
50 | XHR.prototype._send = function (data) {
51 | var self = this;
52 | this._sendXhr = this._request(mapping.Endpoint.host + "/websocket" + data.url, 'POST');
53 | if ("onload" in this._sendXhr) {
54 | this._sendXhr.onload = function () {
55 | this.onload = empty;
56 | self._onData(this.responseText);
57 | };
58 | this._sendXhr.onerror = function () {
59 | this.onerror = empty;
60 | };
61 | } else {
62 | this._sendXhr.onreadystatechange = function () {
63 | if (this.readyState == 4) {
64 | this.onreadystatechange = empty;
65 | if (/^(202|200)$/.test(this.status)) {
66 | self._onData(this.responseText);
67 | }
68 | }
69 | };
70 | }
71 | this._sendXhr.send(util.JSON.stringify(data.data));
72 | };
73 | XHR.prototype.disconnect = function () {
74 | this._onDisconnect();
75 | return this;
76 | };
77 | //断开连接,强制中止所有正在连接的http请求
78 | XHR.prototype._onDisconnect = function (isrecon) {
79 | if (this._xhr) {
80 | this._xhr.onreadystatechange = this._xhr.onload = empty;
81 | this._xhr.abort();
82 | this._xhr = null;
83 | }
84 | if (this._sendXhr) {
85 | this._sendXhr.onreadystatechange = this._sendXhr.onload = empty;
86 | this._sendXhr.abort();
87 | this._sendXhr = null;
88 | }
89 | if (isrecon === undefined) {
90 | Transport.prototype._onDisconnect.call(this);
91 | }
92 | };
93 | //打开跨域请求对象
94 | XHR.prototype._request = function (url, method, multipart) {
95 | var req = request();
96 | if (multipart)
97 | req.multipart = true;
98 | req.open(method || 'GET', "http://" + url);
99 | if (method == 'POST' && 'setRequestHeader' in req) {
100 | req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');
101 | }
102 | return req;
103 | };
104 | XHR.check = function () {
105 | try {
106 | if (request())
107 | return true;
108 | } catch (e) {
109 | }
110 | return false;
111 | };
112 | XHR.XDomainCheck = function () {
113 | return XHR.check();
114 | };
115 | XHR.request = request;
116 | var XHRPolling = Transport['xhr-polling'] = function () {
117 | Transport.XHR.apply(this, arguments);
118 | };
119 | util.inherit(XHRPolling, Transport.XHR);
120 | XHRPolling.prototype.type = 'xhr-polling';
121 | //链接服务器,如果是ios和安卓就等10毫秒执行。
122 | XHRPolling.prototype.connect = function (x) {
123 | if (util.ios || util.android) {
124 | var self = this;
125 | util.load(function () {
126 | setTimeout(function () {
127 | Transport.XHR.prototype.connect.call(self, x);
128 | }, 10);
129 | });
130 | } else {
131 | Transport.XHR.prototype.connect.call(this, x);
132 | }
133 | };
134 | //发送pullmsg.js请求,这里是一个死循环调用。用于保持pullmsg.js请求
135 | XHRPolling.prototype.onopen = function (a, b) {
136 | this._onData(a, b);
137 | if (/"headerCode":-32,/.test(a)) {
138 | return;
139 | }
140 | this._get(mapping.Endpoint.host + "/pullmsg.js?sessionid=" + util.cookieHelper.getItem(mapping.Endpoint.userId + "sId"), true);
141 | };
142 | //http状态码对应执行对象
143 | var status = {
144 | //arg参数有值说明是链接服务器请求,直接_onConnect方法
145 | 200: function (self, text, arg) {
146 | var txt = text.match(/"sessionid":"\S+?(?=")/);
147 | self.onopen(text, txt ? txt[0].slice(13) : void 0);
148 | arg || self._onConnect();
149 | },
150 | //http状态码为400,断开连接
151 | 400: function (self) {
152 | util.cookieHelper.removeItem(mapping.Endpoint.userId + "sId");
153 | self._onDisconnect(true);
154 | self._baseConnect();
155 | }
156 | };
157 | //用于接收pullmsg.js请求中服务器返回的消息数据
158 | XHRPolling.prototype._get = function (symbol, arg) {
159 | var self = this;
160 | this._xhr = this._request(symbol, 'GET');
161 | if ("onload" in this._xhr) {
162 | this._xhr.onload = function () {
163 | this.onload = empty;
164 | if (this.responseText == 'lost params') {
165 | status['400'](self);
166 | } else {
167 | status['200'](self, this.responseText, arg);
168 | }
169 | };
170 | this._xhr.onerror = function () {
171 | self._onDisconnect();
172 | }
173 | } else {
174 | this._xhr.onreadystatechange = function () {
175 | if (this.readyState == 4) {
176 | this.onreadystatechange = empty;
177 | if (/^(200|202)$/.test(this.status)) {
178 | status['200'](self, this.responseText, arg);
179 | } else if (/^(400|403)$/.test(this.status)) {
180 | status['400'](self);
181 | } else {
182 | self._onDisconnect();
183 | }
184 | }
185 | };
186 | }
187 | this._xhr.send();
188 | };
189 | XHRPolling.check = function () {
190 | return Transport.XHR.check();
191 | };
192 | XHRPolling.XDomainCheck = function () {
193 | return Transport.XHR.XDomainCheck();
194 | };
195 | module.exports = XHRPolling;
--------------------------------------------------------------------------------
/src/io/websocket.js:
--------------------------------------------------------------------------------
1 | var Transport = require('./base');
2 | var util = require('../tool');
3 | var tinyStream = require('../binary');
4 | var IOStream = require('../message/throttleStream');
5 | var mapping = require('../mapping');
6 | var WS = Transport.websocket = function () {
7 | Transport.apply(this, arguments)
8 | };
9 | util.inherit(WS, Transport);
10 | WS.prototype.type = "websocket";
11 | WS.prototype.connect = function (url) {
12 | var self = this;
13 | //操作html5 websocket API
14 | this.socket = new WebSocket("ws://" + url);
15 | this.socket.binaryType = "arraybuffer";
16 | this.socket.onopen = function () {
17 | self._onConnect();
18 | };
19 | this.socket.onmessage = function (ev) {
20 | //判断数据是不是字符串,如果是字符串那么就是flash传过来的。
21 | if (typeof ev.data == "string") {
22 | self._decode(ev.data.split(","))
23 | } else {
24 | self._decode(ev.data)
25 | }
26 | };
27 | this.socket.onclose = function () {
28 | self._onClose()
29 | };
30 | this.socket.onerror = function () {
31 | //当websocket执行出错的时候,判断是否已经注册了重连对象。有的话就执行重连对象的onError,没有的话主动抛出一个错误
32 | if (mapping.reconnectSet.onError) {
33 | mapping.reconnectSet.onError(RongIMClient.ConnectErrorStatus.setValue(2));
34 | delete mapping.reconnectSet.onError;
35 | } else {
36 | throw new Error("network is unavailable or unknown error");
37 | }
38 | };
39 | return this
40 | };
41 | //发送数据到服务器
42 | WS.prototype.send = function (data) {
43 | var stream = new tinyStream([]),
44 | msg = new IOStream.MessageOutputStream(stream);
45 | msg.writeMessage(data);
46 | var val = stream.getBytesArray(true);
47 | if (this.socket.readyState == 1) {
48 | if (util.getType(global.Int8Array) === 'Function' && !mapping.globalConf.WEB_SOCKET_FORCE_FLASH) {
49 | //Int8Array为html5 API
50 | var binary = new Int8Array(val);
51 | this.socket.send(binary.buffer)
52 | } else {
53 | this.socket.send(val + "")
54 | }
55 | }
56 | return this
57 | };
58 | WS.prototype.disconnect = function () {
59 | if (this.socket) {
60 | this.socket.close()
61 | }
62 | return this
63 | };
64 | WS.prototype._onClose = function () {
65 | this._onDisconnect();
66 | return this
67 | };
68 | WS.check = function () {
69 | return "WebSocket" in global && WebSocket.prototype && WebSocket.prototype.send && typeof WebSocket !== "undefined"
70 | };
71 | WS.XDomainCheck = function () {
72 | return true;
73 | };
74 | module.exports = WS;
--------------------------------------------------------------------------------
/src/mapping.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by zhangyatao on 16/1/7.
3 | */
4 | module.exports = {
5 | mapping: {
6 | "1": 4,
7 | "2": 2,
8 | "3": 3,
9 | "4": 0,
10 | "5": 1,
11 | "6": 5
12 | },
13 | //objectname映射
14 | typeMapping: {
15 | "RC:TxtMsg": "TextMessage",
16 | "RC:ImgMsg": "ImageMessage",
17 | "RC:VcMsg": "VoiceMessage",
18 | "RC:ImgTextMsg": "RichContentMessage",
19 | "RC:LBSMsg": "LocationMessage"
20 | },
21 | //通知类型映射
22 | sysNtf: {
23 | "RC:InfoNtf": "InformationNotificationMessage",
24 | "RC:ContactNtf": "ContactNotificationMessage",
25 | "RC:ProfileNtf": "ProfileNotificationMessage",
26 | "RC:CmdNtf": "CommandNotificationMessage",
27 | "RC:DizNtf": "DiscussionNotificationMessage"
28 | },
29 | //消息监听器
30 | _ReceiveMessageListener: null,
31 | //连接状态监听器
32 | _ConnectionStatusListener: null,
33 | registerMessageTypeMapping: {},
34 | userInfoMapping: {},
35 | topic: ["invtDiz", "crDiz", "qnUrl", "userInf", "dizInf", "userInf", "joinGrp", "quitDiz", "exitGrp", "evctDiz", ["chatMsg", "pcMsgP", "pdMsgP", "pgMsgP", "ppMsgP"], "pdOpen", "rename", "uGcmpr", "qnTkn", 'destroyChrm', 'createChrm', 'exitChrm', 'queryChrm', 'joinChrm', "pGrps", "addBlack", "rmBlack", "getBlack", "blackStat", "addRelation", 'qryRelation', 'delRelation'],
36 | globalConf: {
37 | WEB_SOCKET_FORCE_FLASH: null,
38 | WEB_XHR_POLLING: null,
39 | FORCE_LOCAL_STORAGE: null
40 | },
41 | Endpoint:{},
42 | userId:'',
43 | reconnectSet:{
44 |
45 | },
46 | chatroomId:''
47 | };
--------------------------------------------------------------------------------
/src/md5.js:
--------------------------------------------------------------------------------
1 | var MD5 = function (e) {
2 | function n(d) {
3 | for (var a = 0, b = ""; 3 >= a; a++)b += "0123456789abcdef".charAt(d >> 8 * a + 4 & 15) + "0123456789abcdef".charAt(d >> 8 * a & 15);
4 | return b
5 | }
6 |
7 | function m(a, b) {
8 | var d = (a & 65535) + (b & 65535);
9 | return (a >> 16) + (b >> 16) + (d >> 16) << 16 | d & 65535
10 | }
11 |
12 | function h(a, b, d, c, e, f) {
13 | a = m(m(b, a), m(c, f));
14 | return m(a << e | a >>> 32 - e, d)
15 | }
16 |
17 | function g(a, b, d, c, e, f, g) {
18 | return h(b & d | ~b & c, a, b, e, f, g)
19 | }
20 |
21 | function k(a, b, d, c, e, f, g) {
22 | return h(b & c | d & ~c, a, b, e, f, g)
23 | }
24 |
25 | function l(a, b, d, c, e, f, g) {
26 | return h(d ^ (b | ~c), a, b, e, f, g)
27 | }
28 |
29 | e = function (a) {
30 | for (var b =
31 | (a.length + 8 >> 6) + 1, d = Array(16 * b), c = 0; c < 16 * b; c++)d[c] = 0;
32 | for (c = 0; c < a.length; c++)d[c >> 2] |= a.charCodeAt(c) << c % 4 * 8;
33 | d[c >> 2] |= 128 << c % 4 * 8;
34 | d[16 * b - 2] = 8 * a.length;
35 | return d
36 | }(e);
37 | for (var d = 1732584193, a = -271733879, b = -1732584194, c = 271733878, f = 0; f < e.length; f += 16)var p = d, q = a, r = b, t = c, d = g(d, a, b, c, e[f + 0], 7, -680876936), c = g(c, d, a, b, e[f + 1], 12, -389564586), b = g(b, c, d, a, e[f + 2], 17, 606105819), a = g(a, b, c, d, e[f + 3], 22, -1044525330), d = g(d, a, b, c, e[f + 4], 7, -176418897), c = g(c, d, a, b, e[f + 5], 12, 1200080426), b = g(b, c, d, a, e[f + 6], 17, -1473231341),
38 | a = g(a, b, c, d, e[f + 7], 22, -45705983), d = g(d, a, b, c, e[f + 8], 7, 1770035416), c = g(c, d, a, b, e[f + 9], 12, -1958414417), b = g(b, c, d, a, e[f + 10], 17, -42063), a = g(a, b, c, d, e[f + 11], 22, -1990404162), d = g(d, a, b, c, e[f + 12], 7, 1804603682), c = g(c, d, a, b, e[f + 13], 12, -40341101), b = g(b, c, d, a, e[f + 14], 17, -1502002290), a = g(a, b, c, d, e[f + 15], 22, 1236535329), d = k(d, a, b, c, e[f + 1], 5, -165796510), c = k(c, d, a, b, e[f + 6], 9, -1069501632), b = k(b, c, d, a, e[f + 11], 14, 643717713), a = k(a, b, c, d, e[f + 0], 20, -373897302), d = k(d, a, b, c, e[f + 5], 5, -701558691), c = k(c, d, a, b, e[f + 10], 9, 38016083),
39 | b = k(b, c, d, a, e[f + 15], 14, -660478335), a = k(a, b, c, d, e[f + 4], 20, -405537848), d = k(d, a, b, c, e[f + 9], 5, 568446438), c = k(c, d, a, b, e[f + 14], 9, -1019803690), b = k(b, c, d, a, e[f + 3], 14, -187363961), a = k(a, b, c, d, e[f + 8], 20, 1163531501), d = k(d, a, b, c, e[f + 13], 5, -1444681467), c = k(c, d, a, b, e[f + 2], 9, -51403784), b = k(b, c, d, a, e[f + 7], 14, 1735328473), a = k(a, b, c, d, e[f + 12], 20, -1926607734), d = h(a ^ b ^ c, d, a, e[f + 5], 4, -378558), c = h(d ^ a ^ b, c, d, e[f + 8], 11, -2022574463), b = h(c ^ d ^ a, b, c, e[f + 11], 16, 1839030562), a = h(b ^ c ^ d, a, b, e[f + 14], 23, -35309556), d = h(a ^ b ^ c, d, a, e[f +
40 | 1], 4, -1530992060), c = h(d ^ a ^ b, c, d, e[f + 4], 11, 1272893353), b = h(c ^ d ^ a, b, c, e[f + 7], 16, -155497632), a = h(b ^ c ^ d, a, b, e[f + 10], 23, -1094730640), d = h(a ^ b ^ c, d, a, e[f + 13], 4, 681279174), c = h(d ^ a ^ b, c, d, e[f + 0], 11, -358537222), b = h(c ^ d ^ a, b, c, e[f + 3], 16, -722521979), a = h(b ^ c ^ d, a, b, e[f + 6], 23, 76029189), d = h(a ^ b ^ c, d, a, e[f + 9], 4, -640364487), c = h(d ^ a ^ b, c, d, e[f + 12], 11, -421815835), b = h(c ^ d ^ a, b, c, e[f + 15], 16, 530742520), a = h(b ^ c ^ d, a, b, e[f + 2], 23, -995338651), d = l(d, a, b, c, e[f + 0], 6, -198630844), c = l(c, d, a, b, e[f + 7], 10, 1126891415), b = l(b, c, d, a, e[f + 14], 15,
41 | -1416354905), a = l(a, b, c, d, e[f + 5], 21, -57434055), d = l(d, a, b, c, e[f + 12], 6, 1700485571), c = l(c, d, a, b, e[f + 3], 10, -1894986606), b = l(b, c, d, a, e[f + 10], 15, -1051523), a = l(a, b, c, d, e[f + 1], 21, -2054922799), d = l(d, a, b, c, e[f + 8], 6, 1873313359), c = l(c, d, a, b, e[f + 15], 10, -30611744), b = l(b, c, d, a, e[f + 6], 15, -1560198380), a = l(a, b, c, d, e[f + 13], 21, 1309151649), d = l(d, a, b, c, e[f + 4], 6, -145523070), c = l(c, d, a, b, e[f + 11], 10, -1120210379), b = l(b, c, d, a, e[f + 2], 15, 718787259), a = l(a, b, c, d, e[f + 9], 21, -343485551), d = m(d, p), a = m(a, q), b = m(b, r), c = m(c, t);
42 | return n(d) +
43 | n(a) + n(b) + n(c)
44 | };
45 | module.exports = MD5;
--------------------------------------------------------------------------------
/src/message/Message.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 消息类,对java逻辑的重新实现
3 | * */
4 | var e = require('./msgEnum');
5 | var TinyStream = require('../binary');
6 | var Qos = e.Qos;
7 | var Type = e.Type;
8 | function Message(argu) {
9 | var _header, _headerCode, lengthSize = 0;
10 | if (argu instanceof Header) {
11 | _header = argu
12 | } else {
13 | _header = new Header(argu, false, Qos.AT_MOST_ONCE, false)
14 | }
15 | this.write = function (Out) {
16 | var out = TinyStream.parse(Out);
17 | _headerCode = this.getHeaderFlag();
18 | out.write(_headerCode);
19 | this.writeMessage(out);
20 | return out
21 | };
22 | this.getHeaderFlag = function () {
23 | return _header.encode();
24 | };
25 | this.getLengthSize = function () {
26 | return lengthSize
27 | };
28 | this.setRetained = function (retain) {
29 | _header.retain = retain
30 | };
31 | this.isRetained = function () {
32 | return _header.retain
33 | };
34 | this.setQos = function (qos) {
35 | _header.qos = qos instanceof Qos ? qos : Qos.setValue(qos);
36 | };
37 | this.getQos = function () {
38 | return _header.qos
39 | };
40 | this.setDup = function (dup) {
41 | _header.dup = dup
42 | };
43 | this.isDup = function () {
44 | return _header.dup
45 | };
46 | this.getType = function () {
47 | return _header.type
48 | };
49 | }
50 | Message._name = "Message";
51 | Message.prototype = {
52 | read: function (In, length) {
53 | this.readMessage(In, length)
54 | },
55 | toBytes: function () {
56 | return this.write([]).getBytesArray()
57 | }, messageLength: function () {
58 | return 0
59 | }, writeMessage: function (out) {
60 | }, readMessage: function (In) {
61 | }, init: function (args) {
62 | var valName, nana;
63 | for (nana in args) {
64 | if (!args.hasOwnProperty(nana))
65 | continue;
66 | valName = nana.replace(/^\w/, function (x) {
67 | var tt = x.charCodeAt(0);
68 | return 'set' + (tt >= 0x61 ? String.fromCharCode(tt & ~32) : x)
69 | });
70 | if (valName in this) {
71 | this[valName](args[nana])
72 | }
73 | }
74 | }
75 | };
76 | function Header(_type, _retain, _qos, _dup) {
77 | this.type = null;
78 | this.retain = false;
79 | this.qos = Qos.AT_LEAST_ONCE;
80 | this.dup = false;
81 | if (_type && +_type == _type && arguments.length == 1) {
82 | this.retain = (_type & 1) > 0;
83 | this.qos = Qos.setValue((_type & 6) >> 1);
84 | this.dup = (_type & 8) > 0;
85 | this.type = Type.setValue((_type >> 4) & 15);
86 | } else {
87 | this.type = Type.setValue(_type);
88 | this.retain = _retain;
89 | this.qos = Qos.setValue(_qos);
90 | this.dup = _dup;
91 | }
92 | }
93 | Header.prototype = {
94 | getType: function () {
95 | return this.type
96 | }, encode: function () {
97 | var _byte = (this.type << 4);
98 | _byte |= this.retain ? 1 : 0;
99 | _byte |= this.qos << 1;
100 | _byte |= this.dup ? 8 : 0;
101 | return _byte
102 | }, toString: function () {
103 | return "Header [type=" + this.type + ",retain=" + this.retain + ",qos=" + this.qos + ",dup=" + this.dup + "]"
104 | }
105 | };
106 | module.exports = {
107 | Message: Message,
108 | Header: Header
109 | };
--------------------------------------------------------------------------------
/src/message/MessageEntity.js:
--------------------------------------------------------------------------------
1 | var msg = require('./Message');
2 | var TinyStream = require('../binary');
3 | var e = require('./msgEnum');
4 | var util = require('../tool');
5 | var Message = msg.Message;
6 | var Header = msg.Header;
7 | var Type = e.Type;
8 | var ConnectionState = e.ConnectionState;
9 | var DisconnectionStatus = e.DisconnectionStatus;
10 | function ConnectMessage() {
11 | var CONNECT_HEADER_SIZE = 12,
12 | protocolId = "RCloud",
13 | protocolVersion = 3,
14 | clientId, keepAlive, appId, token, cleanSession, willTopic, will, willQos, retainWill, hasAppId, hasToken, hasWill;
15 | switch (arguments.length) {
16 | case 0:
17 | Message.call(this, Type.CONNECT);
18 | break;
19 | case 1:
20 | Message.call(this, arguments[0]);
21 | break;
22 | case 3:
23 | Message.call(this, Type.CONNECT);
24 | if (!arguments[0] || arguments[0].length > 64) {
25 | throw new Error("ConnectMessage:Client Id cannot be null and must be at most 64 characters long: " + arguments[0])
26 | }
27 | clientId = arguments[0];
28 | cleanSession = arguments[1];
29 | keepAlive = arguments[2];
30 | break
31 | }
32 | this.messageLength = function () {
33 | var payloadSize = TinyStream.toMQTString(clientId).length;
34 | payloadSize += TinyStream.toMQTString(willTopic).length;
35 | payloadSize += TinyStream.toMQTString(will).length;
36 | payloadSize += TinyStream.toMQTString(appId).length;
37 | payloadSize += TinyStream.toMQTString(token).length;
38 | return payloadSize + CONNECT_HEADER_SIZE
39 | };
40 | this.readMessage = function (In) {
41 | var stream = TinyStream.parse(In);
42 | protocolId = stream.readUTF();
43 | protocolVersion = stream.readByte();
44 | var cFlags = stream.readByte();
45 | hasAppId = (cFlags & 128) > 0;
46 | hasToken = (cFlags & 64) > 0;
47 | retainWill = (cFlags & 32) > 0;
48 | willQos = cFlags >> 3 & 3;
49 | hasWill = (cFlags & 4) > 0;
50 | cleanSession = (cFlags & 32) > 0;
51 | keepAlive = stream.read() * 256 + stream.read();
52 | clientId = stream.readUTF();
53 | if (hasWill) {
54 | willTopic = stream.readUTF();
55 | will = stream.readUTF()
56 | }
57 | if (hasAppId) {
58 | try {
59 | appId = stream.readUTF()
60 | } catch (ex) {
61 | }
62 | }
63 | if (hasToken) {
64 | try {
65 | token = stream.readUTF()
66 | } catch (ex) {
67 | }
68 | }
69 | return stream
70 | };
71 | this.writeMessage = function (out) {
72 | var stream = TinyStream.parse(out);
73 | stream.writeUTF(protocolId);
74 | stream.write(protocolVersion);
75 | var flags = cleanSession ? 2 : 0;
76 | flags |= hasWill ? 4 : 0;
77 | flags |= willQos ? willQos >> 3 : 0;
78 | flags |= retainWill ? 32 : 0;
79 | flags |= hasToken ? 64 : 0;
80 | flags |= hasAppId ? 128 : 0;
81 | stream.write(flags);
82 | stream.writeChar(keepAlive);
83 | stream.writeUTF(clientId);
84 | if (hasWill) {
85 | stream.writeUTF(willTopic);
86 | stream.writeUTF(will)
87 | }
88 | if (hasAppId) {
89 | stream.writeUTF(appId)
90 | }
91 | if (hasToken) {
92 | stream.writeUTF(token)
93 | }
94 | return stream
95 | };
96 | }
97 | ConnectMessage._name = "ConnectMessage";
98 | util.inherit(ConnectMessage, Message, true);
99 | function ConnAckMessage() {
100 | var status, userId, MESSAGE_LENGTH = 2;
101 | switch (arguments.length) {
102 | case 0:
103 | Message.call(this, Type.CONNACK);
104 | break;
105 | case 1:
106 | if (arguments[0] instanceof Header) {
107 | Message.call(this, arguments[0])
108 | } else {
109 | if (arguments[0] instanceof ConnectionState) {
110 | Message.call(this, Type.CONNACK);
111 | if (arguments[0] == null) {
112 | throw new Error("ConnAckMessage:The status of ConnAskMessage can't be null")
113 | }
114 | status = arguments[0]
115 | }
116 | }
117 | }
118 | this.messageLength = function () {
119 | var length = MESSAGE_LENGTH;
120 | if (userId) {
121 | length += TinyStream.toMQTString(userId).length
122 | }
123 | return length
124 | };
125 | this.readMessage = function (In, msglength) {
126 | var stream = TinyStream.parse(In);
127 | stream.read();
128 | var result = +stream.read();
129 | if (result >= 0 && result <= 9) {
130 | this.setStatus(result);
131 | } else {
132 | throw new Error("Unsupported CONNACK code:" + result)
133 | }
134 | if (msglength > MESSAGE_LENGTH) {
135 | this.setUserId(stream.readUTF())
136 | }
137 | };
138 | this.writeMessage = function (out) {
139 | var stream = TinyStream.parse(out);
140 | stream.write(128);
141 | switch (+status) {
142 | case 0:
143 | case 1:
144 | case 2:
145 | case 5:
146 | case 6:
147 | stream.write(+status);
148 | break;
149 | case 3:
150 | case 4:
151 | stream.write(3);
152 | break;
153 | default:
154 | throw new Error("Unsupported CONNACK code:" + status);
155 | }
156 | if (userId) {
157 | stream.writeUTF(userId)
158 | }
159 | return stream
160 | };
161 | this.getStatus = function () {
162 | return status
163 | };
164 | this.setStatus = function (x) {
165 | status = x instanceof ConnectionState ? x : ConnectionState.setValue(x);
166 | };
167 | this.setUserId = function (_userId) {
168 | userId = _userId
169 | };
170 | this.getUserId = function () {
171 | return userId
172 | };
173 | }
174 | ConnAckMessage._name = "ConnAckMessage";
175 | util.inherit(ConnAckMessage, Message, true);
176 | function DisconnectMessage(one) {
177 | var status;
178 | this.MESSAGE_LENGTH = 2;
179 | if (one instanceof Header) {
180 | Message.call(this, one)
181 | } else {
182 | Message.call(this, Type.DISCONNECT);
183 | if (one instanceof DisconnectionStatus) {
184 | status = one
185 | }
186 | }
187 | this.messageLength = function () {
188 | return this.MESSAGE_LENGTH
189 | };
190 | this.readMessage = function (In) {
191 | var _in = TinyStream.parse(In);
192 | _in.read();
193 | var result = +_in.read();
194 | if (result >= 0 && result <= 5) {
195 | this.setStatus(result);
196 | } else {
197 | throw new Error("Unsupported CONNACK code:" + result)
198 | }
199 | };
200 | this.writeMessage = function (Out) {
201 | var out = TinyStream.parse(Out);
202 | out.write(0);
203 | if (+status >= 1 && +status <= 3) {
204 | out.write((+status) - 1);
205 | } else {
206 | throw new Error("Unsupported CONNACK code:" + status)
207 | }
208 | };
209 | this.setStatus = function (x) {
210 | status = x instanceof DisconnectionStatus ? x : DisconnectionStatus.setValue(x);
211 | };
212 | this.getStatus = function () {
213 | return status
214 | };
215 | }
216 | DisconnectMessage._name = "DisconnectMessage";
217 | util.inherit(DisconnectMessage, Message, true);
218 | function PingReqMessage(header) {
219 | if (header && header instanceof Header) {
220 | Message.call(this, header)
221 | } else {
222 | Message.call(this, Type.PINGREQ)
223 | }
224 | }
225 | PingReqMessage._name = "PingReqMessage";
226 | util.inherit(PingReqMessage, Message, true);
227 | function PingRespMessage(header) {
228 | if (header && header instanceof Header) {
229 | Message.call(this, header)
230 | } else {
231 | Message.call(this, Type.PINGRESP)
232 | }
233 | }
234 | PingRespMessage._name = "PingRespMessage";
235 | util.inherit(PingRespMessage, Message, true);
236 | function RetryableMessage(argu) {
237 | var messageId;
238 | Message.call(this, argu);
239 | this.messageLength = function () {
240 | return 2
241 | };
242 | this.writeMessage = function (Out) {
243 | var out = TinyStream.parse(Out),
244 | Id = this.getMessageId(),
245 | lsb = Id & 255,
246 | msb = (Id & 65280) >> 8;
247 | out.write(msb);
248 | out.write(lsb);
249 | return out
250 | };
251 | this.readMessage = function (In) {
252 | var _in = TinyStream.parse(In),
253 | msgId = _in.read() * 256 + _in.read();
254 | this.setMessageId(parseInt(msgId, 10));
255 | };
256 | this.setMessageId = function (_messageId) {
257 | messageId = _messageId
258 | };
259 | this.getMessageId = function () {
260 | return messageId
261 | }
262 | }
263 | RetryableMessage._name = "RetryableMessage";
264 | util.inherit(RetryableMessage, Message, true);
265 | function PubAckMessage(args) {
266 | var status, msgLen = 2,
267 | date = 0;
268 | if (args instanceof Header) {
269 | RetryableMessage.call(this, args)
270 | } else {
271 | RetryableMessage.call(this, Type.PUBACK);
272 | this.setMessageId(args)
273 | }
274 | this.messageLength = function () {
275 | return msgLen
276 | };
277 | this.writeMessage = function (Out) {
278 | var out = TinyStream.parse(Out);
279 | PubAckMessage.prototype.writeMessage.call(this, out)
280 | };
281 | this.readMessage = function (In) {
282 | var _in = TinyStream.parse(In);
283 | PubAckMessage.prototype.readMessage.call(this, _in);
284 | date = _in.readInt();
285 | status = _in.read() * 256 + _in.read()
286 | };
287 | this.setStatus = function (x) {
288 | status = x;
289 | };
290 | this.getStatus = function () {
291 | return status
292 | };
293 | this.getDate = function () {
294 | return date
295 | };
296 | }
297 | PubAckMessage._name = "PubAckMessage";
298 | util.inherit(PubAckMessage, RetryableMessage, true);
299 | function PublishMessage(one, two, three) {
300 | var topic, data, targetId, date;
301 | if (arguments.length == 1 && one instanceof Header) {
302 | RetryableMessage.call(this, one)
303 | } else {
304 | if (arguments.length == 3) {
305 | RetryableMessage.call(this, Type.PUBLISH);
306 | topic = one;
307 | targetId = three;
308 | data = typeof two == "string" ? TinyStream.toMQTString(two) : two;
309 | }
310 | }
311 | this.messageLength = function () {
312 | var length = 10;
313 | length += TinyStream.toMQTString(topic).length;
314 | length += TinyStream.toMQTString(targetId).length;
315 | length += data.length;
316 | return length
317 | };
318 | this.writeMessage = function (Out) {
319 | var out = TinyStream.parse(Out);
320 | out.writeUTF(topic);
321 | out.writeUTF(targetId);
322 | PublishMessage.prototype.writeMessage.apply(this, arguments);
323 | out.write(data)
324 | };
325 | this.readMessage = function (In, msgLength) {
326 | var pos = 6,
327 | _in = TinyStream.parse(In);
328 | date = _in.readInt();
329 | topic = _in.readUTF();
330 | pos += TinyStream.toMQTString(topic).length;
331 | PublishMessage.prototype.readMessage.apply(this, arguments);
332 | data = new Array(msgLength - pos);
333 | _in.read(data)
334 | };
335 | this.setTopic = function (x) {
336 | topic = x;
337 | };
338 | this.setData = function (x) {
339 | data = x;
340 | };
341 | this.setTargetId = function (x) {
342 | targetId = x;
343 | };
344 | this.setDate = function (x) {
345 | date = x;
346 | };
347 | this.setData = function (x) {
348 | data = x;
349 | };
350 | this.getTopic = function () {
351 | return topic
352 | };
353 | this.getData = function () {
354 | return data
355 | };
356 | this.getTargetId = function () {
357 | return targetId
358 | };
359 | this.getDate = function () {
360 | return date
361 | }
362 | }
363 | PublishMessage._name = "PublishMessage";
364 | util.inherit(PublishMessage, RetryableMessage, true);
365 | function QueryMessage(one, two, three) {
366 | var topic, data, targetId;
367 | if (one instanceof Header) {
368 | RetryableMessage.call(this, one)
369 | } else {
370 | if (arguments.length == 3) {
371 | RetryableMessage.call(this, Type.QUERY);
372 | data = typeof two == "string" ? TinyStream.toMQTString(two) : two;
373 | topic = one;
374 | targetId = three;
375 | }
376 | }
377 | this.messageLength = function () {
378 | var length = 0;
379 | length += TinyStream.toMQTString(topic).length;
380 | length += TinyStream.toMQTString(targetId).length;
381 | length += 2;
382 | length += data.length;
383 | return length
384 | };
385 | this.writeMessage = function (Out) {
386 | var out = TinyStream.parse(Out);
387 | out.writeUTF(topic);
388 | out.writeUTF(targetId);
389 | this.constructor.prototype.writeMessage.call(this, out);
390 | out.write(data)
391 | };
392 | this.readMessage = function (In, msgLength) {
393 | var pos = 0,
394 | _in = TinyStream.parse(In);
395 | topic = _in.readUTF();
396 | targetId = _in.readUTF();
397 | pos += TinyStream.toMQTString(topic).length;
398 | pos += TinyStream.toMQTString(targetId).length;
399 | this.constructor.prototype.readMessage.apply(this, arguments);
400 | pos += 2;
401 | data = new Array(msgLength - pos);
402 | _in.read(data)
403 | };
404 | this.setTopic = function (x) {
405 | topic = x;
406 | };
407 | this.setData = function (x) {
408 | data = x;
409 | };
410 | this.setTargetId = function (x) {
411 | targetId = x;
412 | };
413 | this.getTopic = function () {
414 | return topic
415 | };
416 | this.getData = function () {
417 | return data
418 | };
419 | this.getTargetId = function () {
420 | return targetId
421 | };
422 | }
423 | QueryMessage._name = "QueryMessage";
424 | util.inherit(QueryMessage, RetryableMessage, true);
425 | function QueryConMessage(messageId) {
426 | if (messageId instanceof Header) {
427 | RetryableMessage.call(this, messageId)
428 | } else {
429 | RetryableMessage.call(this, Type.QUERYCON);
430 | this.setMessageId(messageId)
431 | }
432 | }
433 | QueryConMessage._name = "QueryConMessage";
434 | util.inherit(QueryConMessage, RetryableMessage, true);
435 | function QueryAckMessage(header) {
436 | var data, status, date;
437 | RetryableMessage.call(this, header);
438 | this.readMessage = function (In, msgLength) {
439 | var _in = TinyStream.parse(In);
440 | QueryAckMessage.prototype.readMessage.call(this, _in);
441 | date = _in.readInt();
442 | status = _in.read() * 256 + _in.read();
443 | if (msgLength > 0) {
444 | data = new Array(msgLength - 8);
445 | _in.read(data)
446 | }
447 | };
448 | this.getStatus = function () {
449 | return status
450 | };
451 | this.getDate = function () {
452 | return date
453 | };
454 | this.setDate = function (x) {
455 | date = x;
456 | };
457 | this.setStatus = function (x) {
458 | status = x;
459 | };
460 | this.setData = function (x) {
461 | data = x;
462 | };
463 | this.getData = function () {
464 | return data
465 | };
466 | }
467 | QueryAckMessage._name = "QueryAckMessage";
468 | util.inherit(QueryAckMessage, RetryableMessage, true);
469 | module.exports = {
470 | ConnectMessage: ConnectMessage,
471 | ConnAckMessage: ConnAckMessage,
472 | DisconnectMessage: DisconnectMessage,
473 | PingReqMessage: PingReqMessage,
474 | PingRespMessage: PingRespMessage,
475 | RetryableMessage: RetryableMessage,
476 | PubAckMessage: PubAckMessage,
477 | PublishMessage: PublishMessage,
478 | QueryMessage: QueryMessage,
479 | QueryConMessage: QueryConMessage,
480 | QueryAckMessage: QueryAckMessage
481 | };
482 |
483 |
--------------------------------------------------------------------------------
/src/message/msgEnum.js:
--------------------------------------------------------------------------------
1 | var myEnum = require('../enum');
2 | var Qos = myEnum({AT_MOST_ONCE: 0, AT_LEAST_ONCE: 1, EXACTLY_ONCE: 2, DEFAULT: 3}),
3 | Type = myEnum({
4 | CONNECT: 1,
5 | CONNACK: 2,
6 | PUBLISH: 3,
7 | PUBACK: 4,
8 | QUERY: 5,
9 | QUERYACK: 6,
10 | QUERYCON: 7,
11 | SUBSCRIBE: 8,
12 | SUBACK: 9,
13 | UNSUBSCRIBE: 10,
14 | UNSUBACK: 11,
15 | PINGREQ: 12,
16 | PINGRESP: 13,
17 | DISCONNECT: 14
18 | }),
19 | DisconnectionStatus = myEnum({
20 | RECONNECT: 0,
21 | OTHER_DEVICE_LOGIN: 1,
22 | CLOSURE: 2,
23 | UNKNOWN_ERROR: 3,
24 | LOGOUT: 4,
25 | BLOCK: 5
26 | }),
27 | ConnectionState = myEnum({
28 | ACCEPTED: 0,
29 | UNACCEPTABLE_PROTOCOL_VERSION: 1,
30 | IDENTIFIER_REJECTED: 2,
31 | SERVER_UNAVAILABLE: 3,
32 | TOKEN_INCORRECT: 4,
33 | NOT_AUTHORIZED: 5,
34 | REDIRECT: 6,
35 | PACKAGE_ERROR: 7,
36 | APP_BLOCK_OR_DELETE: 8,
37 | BLOCK: 9,
38 | TOKEN_EXPIRE: 10,
39 | DEVICE_ERROR: 11
40 | });
41 | module.exports = {
42 | Qos: Qos,
43 | Type: Type,
44 | DisconnectionStatus: DisconnectionStatus,
45 | ConnectionState: ConnectionState
46 | };
47 |
--------------------------------------------------------------------------------
/src/message/throttleStream.js:
--------------------------------------------------------------------------------
1 | var TinyStream = require('../binary');
2 | var Message = require('./Message');
3 | var eneity = require('./MessageEntity');
4 |
5 | function output(_out) {
6 | var out = TinyStream.parse(_out);
7 | this.writeMessage = function (msg) {
8 | if (msg instanceof Message.Message) {
9 | msg.write(out)
10 | }
11 | }
12 | }
13 | //converted input stream to message object ,that was server send to client,把服务器返回的二进制流生成具体的消息对象
14 | function input(In, isPolling) {
15 | var flags, header, msg = null;
16 | if (!isPolling) {
17 | var _in = TinyStream.parse(In);
18 | flags = _in.readByte();
19 | } else {
20 | flags = In["headerCode"];
21 | }
22 | header = new Message.Header(flags);
23 | this.readMessage = function () {
24 | switch (+header.getType()) {
25 | case 2:
26 | msg = new eneity.ConnAckMessage(header);
27 | break;
28 | case 3:
29 | msg = new eneity.PublishMessage(header);
30 | break;
31 | case 4:
32 | msg = new eneity.PubAckMessage(header);
33 | break;
34 | case 5:
35 | msg = new eneity.QueryMessage(header);
36 | break;
37 | case 6:
38 | msg = new eneity.QueryAckMessage(header);
39 | break;
40 | case 7:
41 | msg = new eneity.QueryConMessage(header);
42 | break;
43 | case 9:
44 | case 11:
45 | case 13:
46 | msg = new eneity.PingRespMessage(header);
47 | break;
48 | case 1:
49 | msg = new eneity.ConnectMessage(header);
50 | break;
51 | case 8:
52 | case 10:
53 | case 12:
54 | msg = new eneity.PingReqMessage(header);
55 | break;
56 | case 14:
57 | msg = new eneity.DisconnectMessage(header);
58 | break;
59 | default:
60 | throw new Error("No support for deserializing " + header.getType() + " messages")
61 | }
62 | if (isPolling) {
63 | msg.init(In);
64 | } else {
65 | msg.read(_in, In.length - 1);
66 | }
67 | return msg
68 | }
69 | }
70 | module.exports = {
71 | MessageOutputStream: output,
72 | MessageInputStream: input
73 | };
--------------------------------------------------------------------------------
/src/ready.js:
--------------------------------------------------------------------------------
1 | var global = window;
2 | var tool = require('./tool');
3 | var mappding = require('./mapping');
4 | var config = {
5 | canFlashWidget: (function () {
6 | if ('navigator' in global && 'plugins' in navigator && navigator.plugins['Shockwave Flash']) {
7 | return !!navigator.plugins['Shockwave Flash'].description;
8 | }
9 | if ('ActiveXObject' in global) {
10 | try {
11 | return !!new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
12 | } catch (e) {
13 | }
14 | }
15 | return false;
16 | })(),
17 | supportedWebSocket: function () {
18 | return "WebSocket" in global && "ArrayBuffer" in global && WebSocket.prototype.CLOSED === 3 && !mappding.globalConf.WEB_SOCKET_FORCE_FLASH && !mappding.globalConf.WEB_XHR_POLLING;
19 | },
20 | supportedFlash: function () {
21 | return !/opera/i.test(navigator.userAgent) && !mappding.globalConf.WEB_XHR_POLLING && this.canFlashWidget
22 | }
23 | };
24 | // 程序入口
25 | tool.ready(function () {
26 | var src = '';
27 | //此属性为通道标识。根据这个标识生产通道对象,默认为websocket
28 | tool.setTransportType('websocket');
29 | //当前浏览器是否支持webSocket,并且window.WEB_SOCKET_FORCE_FLASH 和 !window.WEB_XHR_POLLING都是false
30 | if (config.supportedWebSocket()) {
31 | //加载protobuf
32 | src = "http://res.websdk.rongcloud.cn/protobuf-0.2.min.js";
33 | //是否支持flash widget
34 | } else if (config.supportedFlash()) {
35 | //加载flash widget帮助库
36 | src = "http://res.websdk.rongcloud.cn/swfobject-0.2.min.js";
37 | } else {
38 | //如果上述条件都不支持则执行comet逻辑
39 | tool.setTransportType('xhr-polling');
40 | //加载comet帮助库
41 | src = "http://res.websdk.rongcloud.cn/xhrpolling-0.2.min.js";
42 | }
43 | tool.loadScript(src);
44 | });
--------------------------------------------------------------------------------
/src/tool.js:
--------------------------------------------------------------------------------
1 | var mapping = require('./mapping');
2 | var doc = document;
3 | var global = window;
4 | var transportType = '';
5 | var tool = {
6 | //注册页面加载事件
7 | load: function (fn) {
8 | if (doc.readyState == "complete" || this._pageLoaded) {
9 | return fn()
10 | }
11 | if (global.attachEvent) {
12 | global.attachEvent("onload", fn)
13 | } else {
14 | global.addEventListener("load", fn, false)
15 | }
16 | },
17 | //继承
18 | inherit: function (ctor, superCtor,isClassExt) {
19 | var f = function () {
20 | };
21 | if(isClassExt){
22 | f.prototype = new superCtor;
23 | }else{
24 | f.prototype = superCtor.prototype;
25 | }
26 | ctor.super_ = superCtor;
27 | ctor.prototype = new f();
28 | ctor.prototype.constructor = ctor;
29 | },
30 | //查找数组中位于指定下标的元素
31 | indexOf: function (arr, item, from) {
32 | for (var l = arr.length, i = (from < 0) ? Math.max(0, +from) : from || 0; i < l; i++) {
33 | if (arr[i] == item) {
34 | return i
35 | }
36 | }
37 | return -1
38 | },
39 | //判断是否为数组
40 | isArray: function (obj) {
41 | return Object.prototype.toString.call(obj) == "[object Array]";
42 | },
43 | //遍历,只能遍历数组
44 | forEach: (function () {
45 | if ([].forEach) {
46 | return function (arr, func) {
47 | [].forEach.call(arr, func)
48 | }
49 | } else {
50 | return function (arr, func) {
51 | for (var i = 0; i < arr.length; i++) {
52 | func.call(arr, arr[i], i, arr)
53 | }
54 | }
55 | }
56 | })(),
57 | //遍历,可遍历对象也可遍历数组
58 | each: function (obj, callback) {
59 | if (this.isArray(obj)) {
60 | this.forEach(x, callback);
61 | } else {
62 | for (var _name in obj) {
63 | if (obj.hasOwnProperty(_name)) {
64 | callback.call(obj, _name, obj[_name]);
65 | }
66 | }
67 | }
68 | },
69 | //合并
70 | merge: function (target, additional) {
71 | for (var i in additional) {
72 | if (additional.hasOwnProperty(i)) {
73 | target[i] = additional[i]
74 | }
75 | }
76 | },
77 | //把类数组转换为数组
78 | arrayFrom: function (typedarray) {
79 | if (Object.prototype.toString.call(typedarray) == "[object ArrayBuffer]") {
80 | var arr = new Int8Array(typedarray);
81 | return [].slice.call(arr)
82 | }
83 | return typedarray;
84 | },
85 | //删除数组指定项
86 | remove: function (array, func) {
87 | for (var i = 0; i < array.length; i++) {
88 | if (func(array[i])) {
89 | return array.splice(i, 1)[0]
90 | }
91 | }
92 | return null
93 | },
94 | //把int64的时间对象转为时间戳
95 | int64ToTimestamp: function (obj, isDate) {
96 | if (obj.low === undefined) {
97 | return obj;
98 | }
99 | var low = obj.low;
100 | if (low < 0) {
101 | low += 0xffffffff + 1;
102 | }
103 | low = low.toString(16);
104 | var timestamp = parseInt(obj.high.toString(16) + "00000000".replace(new RegExp('0{' + low.length + '}$'), low), 16);
105 | if (isDate) {
106 | return new Date(timestamp)
107 | }
108 | return timestamp;
109 | },
110 | getType: function (obj) {
111 | return Object.prototype.toString.call(obj).slice(8, -1);
112 | },
113 | ready: function (callback) {
114 | if (doc.readyState == "interactive" || doc.readyState == "complete") {
115 | callback();
116 | } else if (doc.addEventListener) {
117 | doc.addEventListener("DOMContentLoaded", function () {
118 | doc.removeEventListener("DOMContentLoaded", arguments.callee, false);
119 | callback();
120 | }, false)
121 | } else if (doc.attachEvent) {
122 | doc.attachEvent("onreadystatechange", function () {
123 | if (doc.readyState === "interactive" || doc.readyState === "complete") {
124 | doc.detachEvent("onreadystatechange", arguments.callee);
125 | callback()
126 | }
127 | })
128 | }
129 | },
130 | loadScript: function (src, callback) {
131 | var script = doc.createElement("script");
132 | var body = doc.body || doc.getElementsByTagName("body")[0];
133 | script.src = src;
134 | body.appendChild(script);
135 | if ('onload' in script) {
136 | script.onload = function () {
137 | callback && callback();
138 | }
139 | } else {
140 | script.onreadystatechange = function () {
141 | if (script.readyState === 'complete') {
142 | callback && callback();
143 | }
144 | }
145 | }
146 | },
147 | jsonp: function (src, jsonpCallback, callback, onFail) {
148 | var cbName = 'cb' + jsonpCount++;
149 | var cbAck = 'window.RongIMClient.jsonpPool.' + cbName;
150 | if (global.RongIMClient.jsonpPool === void 0) {
151 | global.RongIMClient.jsonpPool = {};
152 | }
153 | global.RongIMClient.jsonpPool[cbName] = function (data) {
154 | try {
155 | callback(data);
156 | } finally {
157 | delete global.RongIMClient.jsonpPool[cbName];
158 | script.parentNode.removeChild(script);
159 | }
160 | };
161 | var script = doc.createElement('script');
162 | script.src = src + '&' + jsonpCallback + '=' + cbAck;
163 | script.onerror = function () {
164 | onFail();
165 | };
166 | doc.body.appendChild(script);
167 | },
168 | getTransportType: function () {
169 | return transportType;
170 | },
171 | setTransportType: function (t) {
172 | transportType = t;
173 | },
174 | //是否为ios
175 | ios: /iphone|ipad/i.test(navigator.userAgent),
176 | //是否为安卓
177 | android: /android/i.test(navigator.userAgent),
178 | _pageLoaded: false
179 | };
180 | var jsonpCount = 1;
181 | //此方法判断是否设置FORCE_LOCAL_STORAGE为true,如果是true则在localstorage中存储。否则在cookie中存储。
182 | tool.cookieHelper = (function () {
183 | var obj, old;
184 | if (mapping.globalConf.FORCE_LOCAL_STORAGE === true) {
185 | old = localStorage.setItem;
186 | localStorage.setItem = function (x, value) {
187 | if (localStorage.length == 15) {
188 | localStorage.removeItem(localStorage.key(0));
189 | }
190 | old.call(localStorage, x, value);
191 | };
192 | obj = localStorage;
193 | } else {
194 | obj = {
195 | getItem: function (x) {
196 | var arr = doc.cookie.match(new RegExp("(^| )" + x + "=([^;]*)(;|$)"));
197 | if (arr != null) {
198 | return (arr[2]);
199 | }
200 | return null;
201 | },
202 | setItem: function (x, value) {
203 | var exp = new Date();
204 | exp.setTime(exp.getTime() + 15 * 24 * 3600 * 1000);
205 | doc.cookie = x + "=" + escape(value) + ";path=/;expires=" + exp.toGMTString();
206 | },
207 | removeItem: function (x) {
208 | if (this.getItem(x)) {
209 | doc.cookie = x + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT";
210 | }
211 | },
212 | clear: function () {
213 | var keys = doc.cookie.match(/[^ =;]+(?=\=)/g);
214 | if (keys) {
215 | for (var i = keys.length; i--;)
216 | doc.cookie = keys[i] + '=0;path=/;expires=' + new Date(0).toUTCString();
217 | }
218 | }
219 | }
220 | }
221 | return obj;
222 | })();
223 | tool.load(function () {
224 | tool._pageLoaded = true;
225 | if (!global.JSON) {
226 | tool.JSON = {
227 | parse: function (sJSON) {
228 | return eval('(' + sJSON + ')');
229 | },
230 | stringify: (function () {
231 | var toString = Object.prototype.toString;
232 | var isArray = Array.isArray || function (a) {
233 | return toString.call(a) === '[object Array]';
234 | };
235 | var escMap = {
236 | '"': '\\"',
237 | '\\': '\\\\',
238 | '\b': '\\b',
239 | '\f': '\\f',
240 | '\n': '\\n',
241 | '\r': '\\r',
242 | '\t': '\\t'
243 | };
244 | var escFunc = function (m) {
245 | return escMap[m] || '\\u' + (m.charCodeAt(0) + 0x10000).toString(16).substr(1);
246 | };
247 | var escRE = new RegExp('[\\"' + unescape("%00-%1F%u2028%u2029") + ']', 'g');
248 | return function stringify(value) {
249 | if (value == null) {
250 | return 'null';
251 | } else if (typeof value === 'number') {
252 | return isFinite(value) ? value.toString() : 'null';
253 | } else if (typeof value === 'boolean') {
254 | return value.toString();
255 | } else if (typeof value === 'object') {
256 | if (typeof value.toJSON === 'function') {
257 | return stringify(value.toJSON());
258 | } else if (isArray(value)) {
259 | var res = '[';
260 | for (var i = 0; i < value.length; i++)
261 | res += (i ? ', ' : '') + stringify(value[i]);
262 | return res + ']';
263 | } else if (toString.call(value) === '[object Object]') {
264 | var tmp = [];
265 | for (var k in value) {
266 | if (value.hasOwnProperty(k))
267 | tmp.push(stringify(k) + ': ' + stringify(value[k]));
268 | }
269 | return '{' + tmp.join(', ') + '}';
270 | }
271 | }
272 | return '"' + value.toString().replace(escRE, escFunc) + '"';
273 | };
274 | })()
275 | };
276 | } else {
277 | tool.JSON = global.JSON;
278 | }
279 | tool.messageIdHandler = (function () {
280 | var messageId = 0,
281 | isXHR = tool.getTransportType() === "xhr-polling",
282 | init = function () {
283 | messageId = +(tool.cookieHelper.getItem("msgId") || tool.cookieHelper.setItem("msgId", 0) || 0);
284 | };
285 | isXHR && init();
286 | return {
287 | //messageid 加一并返回
288 | messageIdPlus: function (method) {
289 | isXHR && init();
290 | if (messageId >= 0xffff) {
291 | method();
292 | return false;
293 | }
294 | messageId++;
295 | isXHR && tool.cookieHelper.setItem("msgId", messageId);
296 | return messageId;
297 | },
298 | //清空messageid
299 | clearMessageId: function () {
300 | messageId = 0;
301 | isXHR && tool.cookieHelper.setItem("msgId", messageId);
302 | },
303 | //返回当前messageid
304 | getMessageId: function () {
305 | isXHR && init();
306 | return messageId;
307 | }
308 | }
309 | })()
310 | });
311 | module.exports = tool;
--------------------------------------------------------------------------------
/test/Junit.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yataozhang on 15/4/8.
3 | * 单元测试
4 | */
5 | (function (rong) {
6 | //promise模块
7 | var _promise = function (affair) {
8 | this.state = "waiting";
9 | this.affair = affair || function (o) {
10 | return o
11 | };
12 | this.handles = [];
13 | };
14 | _promise.prototype.then = function (nextaffair) {
15 | var p = new _promise();
16 | if (this.state != "waiting") {
17 | this._fire(p, nextaffair);
18 | } else {
19 | this._push(p, nextaffair);
20 | }
21 | return p;
22 | };
23 | _promise.prototype.delay = function (time) {
24 | return this.then(function (data) {
25 | var p = new _promise();
26 | setTimeout(function () {
27 | p.resolve(data);
28 | }, time);
29 | return p;
30 | });
31 | };
32 | _promise.prototype.resolve = function (obj) {
33 | if (this.state != "waiting") {
34 | throw new Error("all done");
35 | }
36 | this.state = "done";
37 | this.result = this.affair(obj);
38 | for (var i = 0; i < this.handles.length; i++) {
39 | var tmp = this.handles[i];
40 | this._fire(tmp.nextPromise, tmp.nextAffair);
41 | }
42 | return this;
43 | };
44 | _promise.prototype._push = function (nextPromise, nextAffair) {
45 | this.handles.push({
46 | nextPromise: nextPromise,
47 | nextAffair: nextAffair
48 | });
49 | };
50 | _promise.prototype._fire = function (nextPromise, nextAffair) {
51 | if (this.result == false) {
52 | console.warn("终止操作");
53 | return;
54 | }
55 |
56 | var nextVal = nextAffair(this.result);
57 | if (nextVal instanceof _promise) {
58 | nextVal.then(function (obj) {
59 | nextPromise.resolve(obj);
60 | })
61 | } else {
62 | nextPromise.resolve(nextVal);
63 | }
64 | };
65 |
66 |
67 | var log = function (x) {
68 | console.log(x);
69 | } , error = function (x) {
70 | console.error("fail", x);
71 | return false;
72 | } , info = function (x) {
73 | console.info("done");
74 | if (x) {
75 | console.info(x);
76 | }
77 | return true;
78 | };
79 | var Junit = window.Junit = {}, instance, _default = {
80 | ConversationType: RongIMClient.ConversationType.setValue(4),
81 | targetId: "2189",
82 | content: "开始测试了",
83 | discussId: "ee23c0d6-4d38-4aaf-97a7-8155f0b93518",
84 | chatroomId: "tr002",
85 | groupId: "group001"
86 | };
87 | Junit.init = function () {
88 | instance = rong.getInstance();
89 | };
90 | Junit.config = function (obj) {
91 | for (var s in obj) {
92 | _default[s] = obj[s];
93 | }
94 | };
95 | Junit.baseFuncTest = function () {
96 | var pro = new _promise(function (data) {
97 | log(data);
98 | log("保存草稿,输入内容为:123456789");
99 | instance.saveTextMessageDraft(_default.ConversationType, _default.targetId, "123456789")
100 | return info();
101 | });
102 | pro.then(function () {
103 | log("得到草稿,预期值为123456789");
104 | if (instance.getTextMessageDraft(_default.ConversationType, _default.targetId) == "123456789") {
105 | return info();
106 | } else {
107 | return error("getTextMessageDraft");
108 | }
109 | }).then(function () {
110 | log("删除草稿,预期值为null");
111 | instance.clearTextMessageDraft(_default.ConversationType, _default.targetId);
112 | if (instance.getTextMessageDraft(_default.ConversationType, _default.targetId)) {
113 | return error("clearTextMessageDraft");
114 | } else {
115 | return info();
116 | }
117 | }).then(function () {
118 | log("得到会话列表");
119 | log(instance.getConversationList());
120 | return true;
121 | })
122 | // .then(function () {
123 | // log("同步会话列表");
124 | // instance.getConversationList().length = 0;
125 | // instance.syncConversationList();
126 | // }).delay(5000)
127 | .then(function () {
128 | // if (instance.getConversationList().length == 0 && instance.getIO()._TransportType != "xhr-polling") {
129 | // return error("syncConversationList");
130 | // }
131 | log("创建会话列表");
132 | if (instance.createConversation(_default.ConversationType, _default.targetId, "test")) {
133 | return info();
134 | } else {
135 | return error("createConversation");
136 | }
137 | }).then(function () {
138 | log("得到会话列表");
139 | if (instance.getConversation(_default.ConversationType, _default.targetId)) {
140 | return info();
141 | } else {
142 | return error("getConversation");
143 | }
144 | }).then(function () {
145 | log("得到会话通知类型");
146 | instance.getConversationNotificationStatus(_default.ConversationType, _default.targetId, {
147 | onSuccess: function (x) {
148 | log(x)
149 | }, onError: function (x) {
150 | error(x);
151 | error("getConversationNotificationStatus")
152 | }
153 | });
154 | return true;
155 | }).then(function () {
156 | log("清除某类型会话");
157 | instance.clearConversations([_default.ConversationType]);
158 | if (instance.getConversation(_default.ConversationType, _default.targetId) == null) {
159 | return info();
160 | } else {
161 | return error("clearConversations");
162 | }
163 | }).then(function () {
164 | log("得到群类型会话列表");
165 | instance.createConversation(RongIMClient.ConversationType.GROUP, _default.groupId, "群一");
166 | if (instance.getGroupConversationList().length != 0) {
167 | return info();
168 | } else {
169 | return error("getGroupConversationList");
170 | }
171 | }).then(function () {
172 | log("删除指定会话");
173 | instance.removeConversation(RongIMClient.ConversationType.GROUP, _default.groupId);
174 | if (instance.getConversation(RongIMClient.ConversationType.GROUP, _default.groupId)) {
175 | return error("removeConversation")
176 | } else {
177 | return info();
178 | }
179 | }).then(function () {
180 | log("设置会话通知类型");
181 | instance.createConversation(_default.ConversationType, _default.targetId, "test");
182 | instance.setConversationNotificationStatus(_default.ConversationType, _default.targetId, RongIMClient.ConversationNotificationStatus.NOTIFY, {
183 | onSuccess: function (x) {
184 | console.info(x);
185 | }, onError: function (x) {
186 | error(x)
187 | }
188 | });
189 | return true;
190 | }).then(function () {
191 | log("会话置顶");
192 | instance.createConversation(RongIMClient.ConversationType.GROUP, _default.groupId, "群一");
193 | instance.setConversationToTop(_default.ConversationType, _default.targetId);
194 | var val = instance.getConversationList()[0];
195 | if (val.getTargetId() == _default.targetId && val.getConversationType() == _default.ConversationType) {
196 | return info();
197 | } else {
198 | return error("setConversationToTop");
199 | }
200 | }).then(function () {
201 | log("设置会话名称");
202 | instance.setConversationName(_default.ConversationType, _default.targetId, "修改名称");
203 | if (instance.getConversation(_default.ConversationType, _default.targetId).getConversationTitle() == "修改名称") {
204 | return info();
205 | } else {
206 | return error("setConversationName");
207 | }
208 | }).then(function () {
209 | log("得到登陆人员信息");
210 | instance.getCurrentUserInfo({
211 | onSuccess: function (x) {
212 | info(x);
213 | }, onError: function (x) {
214 | error(x);
215 | error("getCurrentUserInfo");
216 | }
217 | });
218 | return true;
219 | }).then(function () {
220 | log("发送消息");
221 | instance.sendMessage(_default.ConversationType, _default.targetId, RongIMClient.TextMessage.obtain(_default.content), new RongIMClient.MessageHandler(function () {
222 | console.log("发送消息中")
223 | }), {
224 | onSuccess: function () {
225 | info("发送消息成功")
226 | }, onError: function (x) {
227 | error(x);
228 | error("sendMessage")
229 | }
230 | });
231 | return true;
232 | }).then(function () {
233 | log("得到所有未读消息数量");
234 | info("未读消息数量:", instance.getTotalUnreadCount());
235 | return true;
236 | }).then(function () {
237 | log("得到指定会话未读消息数量");
238 | info("指定会话未读消息数量:", instance.getUnreadCount(_default.ConversationType, _default.targetId));
239 | return true;
240 | }).then(function () {
241 | log("清空未读消息数量");
242 | if (instance.clearMessagesUnreadStatus(_default.ConversationType, _default.targetId)) {
243 | return info("~~~~~基础功能测试完成~~~~~~\n以下开始高级功能测试");
244 | } else {
245 | return error("clearMessagesUnreadStatus");
246 | }
247 | }).then(function () {
248 | log("加入聊天室");
249 | instance.joinChatRoom(_default.chatroomId, 10, {
250 | onSuccess: function () {
251 | info()
252 | }, onError: function (x) {
253 | error(x);
254 | error("joinChatRoom");
255 | }
256 | });
257 | return true;
258 | }).delay(2000).then(function () {
259 | log("退出聊天室");
260 | instance.quitChatRoom(_default.chatroomId, {
261 | onSuccess: function () {
262 | info();
263 | }, onError: function (x) {
264 | error(x);
265 | error("quitChatRoom");
266 | }
267 | });
268 | return true;
269 | }).delay(2000).then(function () {
270 | log("发送通知类型消息");
271 | instance.sendNotification(RongIMClient.ConversationType.PRIVATE, _default.targetId, RongIMClient.InformationNotificationMessage.obtain(_default.content), {
272 | onSuccess: function () {
273 | info()
274 | }, onError: function (x) {
275 | error(x);
276 | error("sendNotification")
277 | }
278 | });
279 | return true;
280 | }).then(function () {
281 | log("发送状态类型消息");
282 | return true;
283 | }).delay(2000).then(function () {
284 | log("创建讨论组");
285 | instance.createDiscussion("单元测试", ["2180"], {
286 | onSuccess: function (id) {
287 | _default.discussId = id;
288 | info();
289 | }, onError: function (x) {
290 | error(x);
291 | error("createDiscussion")
292 | }
293 | });
294 | return true;
295 | }).delay(2000).then(function () {
296 | log("得到指定讨论组信息");
297 | instance.getDiscussion(_default.discussId, {
298 | onSuccess: function (x) {
299 | console.warn("讨论组Id", x.getId());
300 | console.warn("讨论组名称", x.getName());
301 | console.warn("讨论组邀请状态", x.isOpen());
302 | console.warn("讨论组人员", x.getMemberIdList());
303 | console.warn("讨论组管理员", x.getCreatorId());
304 | info()
305 | }, onError: function (x) {
306 | error(x);
307 | error("getDiscussion")
308 | }
309 | });
310 | return true;
311 | }).delay(2000).then(function () {
312 | log("设置讨论组名称");
313 | instance.setDiscussionName(_default.discussId, "修改讨论组名称——", {
314 | onSuccess: function () {
315 | info()
316 | }, onError: function (x) {
317 | error(x);
318 | error("setDiscussionName")
319 | }
320 | });
321 | return true;
322 | }).delay(2000).then(function () {
323 | log("设置讨论组邀请状态");
324 | instance.setDiscussionInviteStatus(_default.discussId, RongIMClient.DiscussionInviteStatus.OPENED, {
325 | onSuccess: function () {
326 | info()
327 | }, onError: function (x) {
328 | error(x);
329 | error("setDiscussionInviteStatus")
330 | }
331 | });
332 | return true;
333 | }).delay(2000).then(function () {
334 |
335 | log("指定人员加入讨论组")//2315
336 | instance.addMemberToDiscussion(_default.discussId, ["2315"], {
337 | onSuccess: function () {
338 | info()
339 | }, onError: function (x) {
340 | error(x);
341 | error("addMemberToDiscussion")
342 | }
343 | });
344 | return true;
345 | }).delay(2000).then(function () {
346 | log("将指定人员移出讨论组");
347 | instance.removeMemberFromDiscussion(_default.discussId, "2315", {
348 | onSuccess: function () {
349 | info()
350 | }, onError: function (x) {
351 | error(x);
352 | error("removeMemberFromDiscussion")
353 | }
354 | });
355 | return true;
356 | }).delay(2000).then(function () {
357 | log("退出讨论组");
358 | instance.quitDiscussion(_default.discussId, {
359 | onSuccess: function () {
360 | info();
361 | }, onError: function (x) {
362 | error(x);
363 | error("quitDiscussion")
364 | }
365 | });
366 | return true;
367 | }).delay(2000).then(function () {
368 | //flash bug
369 | log("加入群");
370 | instance.joinGroup(_default.groupId, "群组一", {
371 | onSuccess: function () {
372 | info();
373 | }, onError: function (x) {
374 | error(x);
375 | error("joinGroup")
376 | }
377 | });
378 | return true;
379 | }).delay(2000).then(function () {
380 | log("退出群");
381 | instance.quitGroup(_default.groupId, {
382 | onSuccess: function () {
383 | info();
384 | }, onError: function (x) {
385 | error(x);
386 | error("quitGroup")
387 | }
388 | });
389 | return true;
390 | }).delay(2000).then(function () {
391 | log("同步群");
392 | var group1 = new RongIMClient.Group();
393 | group1.setId("group001");
394 | group1.setName("群组一");
395 | var group2 = new RongIMClient.Group();
396 | group2.setId("group002");
397 | group2.setName("群组二");
398 | var group3 = new RongIMClient.Group();
399 | group3.setId("group003");
400 | group3.setName("群组三");
401 | instance.syncGroup([group1, group3, group2, group2, group3], {
402 | onSuccess: function () {
403 | info();
404 | }, onError: function (x) {
405 | error(x);
406 | error("syncGroup")
407 | }
408 | });
409 | return true;
410 | }).delay(2000).then(function () {
411 | log("得到黑名单信息");
412 | instance.getBlacklist({
413 | onSuccess: function (x) {
414 | info(x);
415 | }, onError: function (x) {
416 | error(x);
417 | error("getBlacklistStatus")
418 | }
419 | });
420 | return true;
421 | }).delay(2000).then(function () {
422 | log("将指定人员加入到黑名单");
423 | instance.addToBlacklist("2315", {
424 | onSuccess: function () {
425 | info();
426 | }, onError: function (x) {
427 | error(x);
428 | error("addToBlacklist")
429 | }
430 | });
431 | return true;
432 | }).delay(2000).then(function () {
433 | log("得到指定人员在黑名单中的状态");
434 | instance.getBlacklistStatus("2315", {
435 | onSuccess: function (x) {
436 | info(x);
437 | }, onError: function (x) {
438 | error(x);
439 | error("getBlacklistStatus")
440 | }
441 | });
442 | return true;
443 | }).delay(2000).then(function () {
444 | log("将指定人员移出黑名单");
445 | instance.removeFromBlacklist("2315", {
446 | onSuccess: function () {
447 | instance.getBlacklist({
448 | onSuccess: function (x) {
449 | x.indexOf("2315") == -1 ? info(x) : error("removeFromBlacklist");
450 | }, onError: function (x) {
451 | }
452 | })
453 | }, onError: function (x) {
454 | error(x);
455 | error("removeFromBlacklist")
456 | }
457 | });
458 | return true;
459 | }).then(function () {
460 | log("得到未读消息状态");
461 | RongIMClient.hasUnreadMessages(RongBrIdge._client.appId, RongBrIdge._client.token, {
462 | onSuccess: function (x) {
463 | info(x);
464 | }, onError: function (x) {
465 | error(x);
466 | error("hasUnreadMessages")
467 | }
468 | });
469 | return true;
470 | }).delay(2000).then(function () {
471 | log("注册自定义消息");
472 | RongIMClient.registerMessageType({messageType: "_MessageType", "objectName": "RC:selfMsg", "fieldName": ["name", "id", "age"]});
473 |
474 | if (RongIMClient._MessageType) {
475 | var val = new RongIMClient._MessageType();
476 | if (val.getObjectName() == "RC:selfMsg" && val.setname && val.setid && val.setage) {
477 | info();
478 | return true;
479 | }
480 | }
481 | error("registerMessageType");
482 | return false;
483 | }).then(function () {
484 | log("断开链接测试");
485 | instance.disconnect();
486 | return true;
487 | }).delay(5000).then(function () {
488 | if (instance.getIO().getInstance().connected != false) {
489 | return error("disconnect");
490 | }
491 | log("重连");
492 | instance.reconnect({
493 | onSuccess: function () {
494 |
495 | }, onError: function () {
496 |
497 | }
498 | });
499 | return true;
500 | }).delay(10000).then(function () {
501 | console.log("~~~~~~~~~~~~测试完毕~~~~~~~~~~");
502 | if (instance.getIO().getInstance().connected != true) {
503 | return error("reconnect");
504 | }
505 | });
506 | pro.resolve("~~~~~~~~~~~~start~~~~~~~~~~~");
507 | };
508 |
509 |
510 | })();
511 |
--------------------------------------------------------------------------------
/web_SDK_文件结构说明.txt:
--------------------------------------------------------------------------------
1 | web SDk
2 | |---------------------------------
3 | |嵌入式客服|
4 | | [modules/Embedded.js]
5 | |---------------------------------
6 | |帮助模块|
7 | | [modules/emoji-0.9.2.js]
8 | | [modules/indexedDB.js]
9 | | [modules/loadImage.js]
10 | | [modules/voice-0.9.1.js]
11 | |---------------------------------
12 | |消息格式化|
13 | | [external/protobuf.js]
14 | | [external/swfobject.js]
15 | | [external/xhrpolling.js]
16 | |---------------------------------
17 | |SDK 源文件|
18 | | [ dist/RongIMClient.js]
19 | |---------------------------------
20 | |flash 源文件|
21 | | [external/WebSocketMain.zip]
22 | |----------------------------------
23 | |测试用例|
24 | | [test/Junit.js]
25 | | [test/SDk_invoker.html]
26 | |----------------------------------
27 | |sdk代码分块|
28 | | [src]
29 | |----------------------------------
30 |
31 | 联系人:张亚涛
32 | email:xiaodezhang@foxmail.com
33 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | module.exports = {
3 | devtool: '#cheap-source-map',
4 | entry: "./src/IMClient/entry.js",
5 | output: {
6 | path: path.join(__dirname, '/dest'),
7 | filename: 'RongIMClient.js',
8 | sourceMapFilename: '[file].map',
9 | libraryTarget: 'umd',
10 | library: 'RongIMClient',
11 | pathinfo: true
12 | },
13 | resolve: {
14 | extensions: ['', '.js', '.json', '.coffee'],
15 | root: [process.cwd() + '/src', process.cwd() + '/node_modules'] //本文件中的require从哪里找
16 | }
17 | };
--------------------------------------------------------------------------------