|
@@ -0,0 +1,367 @@
|
|
|
+/**
|
|
|
+ * WTWS
|
|
|
+ * @param config {username, url, token, channel, logCallback}
|
|
|
+ * @constructor
|
|
|
+ */
|
|
|
+const WTWS = function (config) {
|
|
|
+ this.__instance = null;
|
|
|
+ this.__connected = false;
|
|
|
+ this.__callbackid = {};
|
|
|
+ this.__openNum = 0;
|
|
|
+ this.__autoNum = 0;
|
|
|
+
|
|
|
+ this.__autoLine = function (timeout) {
|
|
|
+ var tempNum = this.__autoNum;
|
|
|
+ var thas = this;
|
|
|
+ setTimeout(function () {
|
|
|
+ if (tempNum === thas.__autoNum) {
|
|
|
+ thas.__autoNum++
|
|
|
+ if (!thas.__config.token) {
|
|
|
+ thas.__log("[WS] No token");
|
|
|
+ thas.__autoLine(timeout + 5);
|
|
|
+ } else {
|
|
|
+ thas.sendTo('refresh', function (res) {
|
|
|
+ thas.__log("[WS] Connection " + (res.status ? 'success' : 'error'));
|
|
|
+ thas.__autoLine(timeout + 5);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, Math.min(timeout, 30) * 1000);
|
|
|
+ }
|
|
|
+ this.__log = function (text, event) {
|
|
|
+ typeof this.__config.logCallback === "function" && this.__config.logCallback(text, event);
|
|
|
+ }
|
|
|
+ this.__lExists = function (string, find, lower) {
|
|
|
+ string += "";
|
|
|
+ find += "";
|
|
|
+ if (lower !== true) {
|
|
|
+ string = string.toLowerCase();
|
|
|
+ find = find.toLowerCase();
|
|
|
+ }
|
|
|
+ return (string.substring(0, find.length) === find);
|
|
|
+ }
|
|
|
+ this.__rNum = function (str, fixed) {
|
|
|
+ var _s = Number(str);
|
|
|
+ if (_s + "" === "NaN") {
|
|
|
+ _s = 0;
|
|
|
+ }
|
|
|
+ if (/^[0-9]*[1-9][0-9]*$/.test(fixed)) {
|
|
|
+ _s = _s.toFixed(fixed);
|
|
|
+ var rs = _s.indexOf('.');
|
|
|
+ if (rs < 0) {
|
|
|
+ _s += ".";
|
|
|
+ for (var i = 0; i < fixed; i++) {
|
|
|
+ _s += "0";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return _s;
|
|
|
+ }
|
|
|
+ this.__jParse = function (str, defaultVal) {
|
|
|
+ if (str === null) {
|
|
|
+ return defaultVal ? defaultVal : {};
|
|
|
+ }
|
|
|
+ if (typeof str === "object") {
|
|
|
+ return str;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ return JSON.parse(str);
|
|
|
+ } catch (e) {
|
|
|
+ return defaultVal ? defaultVal : {};
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.__randString = function (len) {
|
|
|
+ len = len || 32;
|
|
|
+ var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678oOLl9gqVvUuI1';
|
|
|
+ var maxPos = $chars.length;
|
|
|
+ var pwd = '';
|
|
|
+ for (var i = 0; i < len; i++) {
|
|
|
+ pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
|
|
|
+ }
|
|
|
+ return pwd;
|
|
|
+ }
|
|
|
+ this.__urlParams = function(url, params) {
|
|
|
+ if (typeof params === "object" && params !== null) {
|
|
|
+ url+= "";
|
|
|
+ url+= url.indexOf("?") === -1 ? '?' : '';
|
|
|
+ for (var key in params) {
|
|
|
+ if (!params.hasOwnProperty(key)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ url+= '&' + key + '=' + params[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return url.replace("?&", "?");
|
|
|
+ }
|
|
|
+ this.__isArr = function (obj){
|
|
|
+ return Object.prototype.toString.call(obj)=='[object Array]';
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置参数
|
|
|
+ * @param config
|
|
|
+ */
|
|
|
+ this.config = function (config) {
|
|
|
+ if (typeof config !== "object" || config === null) {
|
|
|
+ config = {};
|
|
|
+ }
|
|
|
+ config.username = config.username || '';
|
|
|
+ config.url = config.url || '';
|
|
|
+ config.token = config.token || '';
|
|
|
+ config.channel = config.channel || '';
|
|
|
+ config.logCallback = config.logCallback || null;
|
|
|
+ this.__config = config;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接
|
|
|
+ * @param force
|
|
|
+ */
|
|
|
+ this.connection = function (force) {
|
|
|
+ if (!this.__lExists(this.__config.url, "ws://") && !this.__lExists(this.__config.url, "wss://")) {
|
|
|
+ this.__log("[WS] No connection address");
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.__config.token) {
|
|
|
+ this.__log("[WS] No connected token");
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.__instance !== null && force !== true) {
|
|
|
+ this.__log("[WS] Connection exists");
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ var thas = this;
|
|
|
+
|
|
|
+ // 初始化客户端套接字并建立连接
|
|
|
+ this.__instance = new WebSocket(this.__urlParams(this.__config.url, {
|
|
|
+ token: this.__config.token,
|
|
|
+ channel: this.__config.channel
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 连接建立时触发
|
|
|
+ this.__instance.onopen = function (event) {
|
|
|
+ thas.__log("[WS] Connection opened", event);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 接收到服务端推送时执行
|
|
|
+ this.__instance.onmessage = function (event) {
|
|
|
+ var msgDetail = thas.__jParse(event.data);
|
|
|
+ if (msgDetail.messageType === 'open') {
|
|
|
+ thas.__log("[WS] Connection connected");
|
|
|
+ msgDetail.openNum = thas.__openNum;
|
|
|
+ msgDetail.config = thas.__config;
|
|
|
+ thas.__openNum++;
|
|
|
+ thas.__connected = true;
|
|
|
+ thas.__autoLine(30);
|
|
|
+ } else if (msgDetail.messageType === 'back') {
|
|
|
+ typeof thas.__callbackid[msgDetail.messageId] === "function" && thas.__callbackid[msgDetail.messageId](msgDetail.body);
|
|
|
+ delete thas.__callbackid[msgDetail.messageId];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (thas.__rNum(msgDetail.contentId) > 0) {
|
|
|
+ thas.sendTo('roger', msgDetail.contentId);
|
|
|
+ }
|
|
|
+ thas.triggerMsgListener(msgDetail);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 连接关闭时触发
|
|
|
+ this.__instance.onclose = function (event) {
|
|
|
+ thas.__log("[WS] Connection closed", event);
|
|
|
+ thas.__connected = false;
|
|
|
+ thas.__instance = null;
|
|
|
+ thas.__autoLine(5);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 连接出错
|
|
|
+ this.__instance.onerror = function (event) {
|
|
|
+ thas.__log("[WS] Connection error", event);
|
|
|
+ thas.__connected = false;
|
|
|
+ thas.__instance = null;
|
|
|
+ thas.__autoLine(5);
|
|
|
+ }
|
|
|
+
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加消息监听
|
|
|
+ * @param listenerName
|
|
|
+ * @param listenerType
|
|
|
+ * @param callback
|
|
|
+ */
|
|
|
+ this.setOnMsgListener = function (listenerName, listenerType, callback) {
|
|
|
+ if (typeof listenerName != "string") {
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ if (typeof listenerType === "function") {
|
|
|
+ callback = listenerType;
|
|
|
+ listenerType = [];
|
|
|
+ }
|
|
|
+ if (!this.__isArr(listenerType)) {
|
|
|
+ listenerType = [listenerType];
|
|
|
+ }
|
|
|
+ if (typeof callback === "function") {
|
|
|
+ this.__msgListenerObject[listenerName] = {
|
|
|
+ callback: callback,
|
|
|
+ listenerType: listenerType,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ this.triggerMsgListener = function (msgDetail) {
|
|
|
+ var key, item;
|
|
|
+ for (key in this.__msgListenerObject) {
|
|
|
+ if (!this.__msgListenerObject.hasOwnProperty(key)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ item = this.__msgListenerObject[key];
|
|
|
+ if (item.listenerType.length > 0 && item.listenerType.indexOf(msgDetail.messageType) === -1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (typeof item.callback === "function") {
|
|
|
+ item.callback(msgDetail);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.__msgListenerObject = {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加特殊监听
|
|
|
+ * @param listenerName
|
|
|
+ * @param callback
|
|
|
+ */
|
|
|
+ this.setOnSpecialListener = function (listenerName, callback) {
|
|
|
+ if (typeof listenerName != "string") {
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ if (typeof callback === "function") {
|
|
|
+ this.__specialListenerObject[listenerName] = {
|
|
|
+ callback: callback,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ this.triggerSpecialListener = function (simpleMsg) {
|
|
|
+ var key, item;
|
|
|
+ for (key in this.__specialListenerObject) {
|
|
|
+ if (!this.__specialListenerObject.hasOwnProperty(key)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ item = this.__specialListenerObject[key];
|
|
|
+ if (typeof item.callback === "function") {
|
|
|
+ item.callback(simpleMsg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.__specialListenerObject = {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送消息
|
|
|
+ * @param messageType 会话类型
|
|
|
+ * - refresh: 刷新
|
|
|
+ * - unread: 未读信息总数量
|
|
|
+ * - read: 已读会员信息
|
|
|
+ * - roger: 收到信息回执
|
|
|
+ * - user: 指定target
|
|
|
+ * - team: 团队会员
|
|
|
+ * @param target 发送目标
|
|
|
+ * @param body 发送内容(对象或数组)
|
|
|
+ * @param callback 发送回调
|
|
|
+ * @param againNum
|
|
|
+ */
|
|
|
+ this.sendTo = function (messageType, target, body, callback, againNum = 0) {
|
|
|
+ if (typeof target === "object" && typeof body === "undefined") {
|
|
|
+ body = target;
|
|
|
+ target = null;
|
|
|
+ }
|
|
|
+ if (typeof target === "function") {
|
|
|
+ body = target;
|
|
|
+ target = null;
|
|
|
+ }
|
|
|
+ if (typeof body === "function") {
|
|
|
+ callback = body;
|
|
|
+ body = null;
|
|
|
+ }
|
|
|
+ if (body === null || typeof body !== "object") {
|
|
|
+ body = {};
|
|
|
+ }
|
|
|
+ //
|
|
|
+ var thas = this;
|
|
|
+ if (this.__instance === null || this.__connected === false) {
|
|
|
+ if (againNum < 10 && messageType != 'team') {
|
|
|
+ setTimeout(function () {
|
|
|
+ thas.sendTo(messageType, target, body, callback, thas.__rNum(againNum) + 1)
|
|
|
+ }, 600);
|
|
|
+ if (againNum === 0) {
|
|
|
+ this.connection();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (this.__instance === null) {
|
|
|
+ this.__log("[WS] Service not connected");
|
|
|
+ typeof callback === "function" && callback({status: 0, message: '服务未连接'});
|
|
|
+ } else {
|
|
|
+ this.__log("[WS] Failed connection");
|
|
|
+ typeof callback === "function" && callback({status: 0, message: '未连接成功'});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ if (['refresh', 'unread', 'read', 'roger', 'user', 'team'].indexOf(messageType) === -1) {
|
|
|
+ this.__log("[WS] Wrong message messageType: " + messageType);
|
|
|
+ typeof callback === "function" && callback({status: 0, message: '错误的消息类型: ' + messageType});
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ //
|
|
|
+ var contentId = 0;
|
|
|
+ if (messageType === 'roger') {
|
|
|
+ contentId = target;
|
|
|
+ target = null;
|
|
|
+ }
|
|
|
+ var messageId = '';
|
|
|
+ if (typeof callback === "string" && callback === 'special') {
|
|
|
+ callback = function (res) {
|
|
|
+ res.status === 1 && thas.triggerSpecialListener({
|
|
|
+ target: target,
|
|
|
+ body: body,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (typeof callback === "function") {
|
|
|
+ messageId = this.__randString(16);
|
|
|
+ this.__callbackid[messageId] = callback;
|
|
|
+ }
|
|
|
+ this.__instance.send(JSON.stringify({
|
|
|
+ messageType: messageType,
|
|
|
+ messageId: messageId,
|
|
|
+ contentId: contentId,
|
|
|
+ channel: this.__config.channel,
|
|
|
+ username: this.__config.username,
|
|
|
+ target: target,
|
|
|
+ body: body,
|
|
|
+ time: Math.round(new Date().getTime() / 1000),
|
|
|
+ }));
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭连接
|
|
|
+ */
|
|
|
+ this.close = function () {
|
|
|
+ if (this.__instance === null) {
|
|
|
+ this.__log("[WS] Service not connected");
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ if (this.__connected === false) {
|
|
|
+ this.__log("[WS] Failed connection");
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ this.__instance.close();
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.config(config);
|
|
|
+}
|