File size: 3,825 Bytes
e7c953d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
'use strict';

var EngineIOClient = require('engine.io-client');

var DubAPIRequestError = require('./errors/requestError.js');

var utils = require('./utils.js');

var endpoints = require('./data/endpoints.js');

function SocketHandler(dubAPI) {
    this._ = {};
    this._.dubAPI = dubAPI;
    this._.socket = undefined;
    this._.channels = {};
    this._.reconnect = true;

    this.connectBind = utils.bind(this.connect, this);

    this.onOpenBind = utils.bind(this.onOpen, this);
    this.onMessageBind = utils.bind(this.onMessage, this);
    this.onErrorBind = utils.bind(this.onError, this);
    this.onCloseBind = utils.bind(this.onClose, this);
}

SocketHandler.prototype.connect = function() {
    if (this._.socket) return;

    this._.reconnect = true;

    var that = this;

    this._.dubAPI._.reqHandler.queue({method: 'GET', url: endpoints.authToken}, function(code, body) {
        if (code !== 200) {
            that._.dubAPI.emit('error', new DubAPIRequestError(code, that._.dubAPI._.reqHandler.endpoint(endpoints.authToken)));
            setTimeout(that.connectBind, 5000);
            return;
        }

        that._.socket = new EngineIOClient({
            hostname: 'ws.queup.net',
            secure: true,
            path: '/ws',
            query: {access_token: body.data.token}, //eslint-disable-line camelcase
            transports: ['websocket']
        });

        that._.socket.on('open', that.onOpenBind);
        that._.socket.on('message', that.onMessageBind);
        that._.socket.on('error', that.onErrorBind);
        that._.socket.on('close', that.onCloseBind);
    });
};

SocketHandler.prototype.onOpen = function() {
    var channels = Object.keys(this._.channels);

    for (var i = 0; i < channels.length; i++) {
        this._.socket.send(JSON.stringify({action: 10, channel: channels[i]}));

        if (/^room:/.test(channels[i])) {
            this._.socket.send(JSON.stringify({action: 14, channel: channels[i], presence: {action: 0, data: {}}}));
        }
    }

    this._.dubAPI.emit('socket:open');
};

SocketHandler.prototype.onMessage = function(data) {
    try {
        data = JSON.parse(data);
    } catch (err) {
        this._.dubAPI.emit('error', err);
        return;
    }

    this._.dubAPI.emit('socket:message', data);

    if (data.action === 15 && this._.channels[data.channel]) {
        try {
            data.message.data = JSON.parse(data.message.data);
        } catch (err) {
            this._.dubAPI.emit('error', err);
            return;
        }

        this._.channels[data.channel](data.message.data);
    }
};

SocketHandler.prototype.onError = function(err) {
    this._.dubAPI.emit('error', err);
};

SocketHandler.prototype.onClose = function() {
    this._.socket = undefined;

    if (this._.reconnect) setTimeout(this.connectBind, 5000);

    this._.dubAPI.emit('socket:close');
};

SocketHandler.prototype.attachChannel = function(channel, callback) {
    if (this._.socket && !this._.channels[channel]) {
        this._.socket.send(JSON.stringify({action: 10, channel: channel}));

        if (/^room:/.test(channel)) {
            this._.socket.send(JSON.stringify({action: 14, channel: channel, presence: {action: 0, data: {}}}));
        }
    }

    this._.channels[channel] = callback;
};

SocketHandler.prototype.detachChannel = function(channel) {
    if (this._.socket && this._.channels[channel]) this._.socket.send(JSON.stringify({action: 12, channel: channel}));

    delete this._.channels[channel];
};

SocketHandler.prototype.disconnect = function() {
    if (!this._.socket) return;

    this._.reconnect = false;
    this._.socket.close();
};

module.exports = SocketHandler;