1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | var debug = require('debug')('antisocial-friends-feeds');
|
10 | var url = require('url');
|
11 | var IOClient = require('socket.io-client');
|
12 | var cryptography = require('antisocial-encryption');
|
13 | var moment = require('moment');
|
14 |
|
15 | module.exports.connect = function activityFeedSubscribeConnect(antisocialApp, currentUser, friend) {
|
16 | var config = antisocialApp.config;
|
17 | var db = antisocialApp.db;
|
18 | var authUserMiddleware = antisocialApp.authUserMiddleware;
|
19 |
|
20 | if (!antisocialApp.openActivityListeners) {
|
21 | antisocialApp.openActivityListeners = {};
|
22 | }
|
23 |
|
24 | var key = currentUser.username + '<-' + friend.remoteEndPoint;
|
25 |
|
26 | if (antisocialApp.openActivityListeners[key]) {
|
27 | debug('activityFeedSubscribeConnect abort already connected %s', key);
|
28 | return;
|
29 | }
|
30 |
|
31 | var remoteEndPoint = url.parse(friend.remoteEndPoint);
|
32 | var endpoint = remoteEndPoint.protocol === 'https:' ? 'wss' : 'ws';
|
33 | endpoint += '://' + remoteEndPoint.host;
|
34 |
|
35 | debug('attempting to subscribe to ' + endpoint + '/antisocial-activity');
|
36 |
|
37 |
|
38 | var socket = IOClient(endpoint, {
|
39 | 'path': '/antisocial-activity',
|
40 | 'reconnection': false
|
41 | });
|
42 |
|
43 | socket.on('reconnecting', function (attempt) {
|
44 | debug('attempting reconnect %s %s', endpoint, attempt);
|
45 | });
|
46 |
|
47 | socket.on('reconnect_error', function () {
|
48 | debug('reconnect attempt failed %s', endpoint);
|
49 | });
|
50 |
|
51 | socket.on('reconnect_failed', function () {
|
52 | debug('reconnect failed %s', endpoint);
|
53 | });
|
54 |
|
55 |
|
56 | socket.on('connect', function () {
|
57 | debug('client connected');
|
58 |
|
59 | socket.on('unauthorized', function (err) {
|
60 | debug('client unauthorized', err.message);
|
61 | });
|
62 |
|
63 | socket.on('error', function () {
|
64 | debug('client error');
|
65 | });
|
66 |
|
67 | socket.on('authenticated', function () {
|
68 | debug('client authenticated');
|
69 |
|
70 | socket.antisocial = {
|
71 | 'key': key,
|
72 | 'friend': friend,
|
73 | 'user': currentUser,
|
74 | 'setDataHandler': function setDataHandler(handler) {
|
75 | socket.antisocial.dataHandler = handler;
|
76 | }
|
77 | };
|
78 |
|
79 | antisocialApp.openActivityListeners[socket.antisocial.key] = socket;
|
80 |
|
81 | antisocialApp.emit('open-activity-connection', {
|
82 | 'info': socket.antisocial,
|
83 | 'socket': socket
|
84 | });
|
85 |
|
86 | socket.on('highwater', function (highwater) {
|
87 | debug('got highwater from %s %j', socket.antisocial.friend.id, highwater);
|
88 | antisocialApp.emit('activity-backfill', {
|
89 | 'info': socket.antisocial,
|
90 | 'socket': socket,
|
91 | 'highwater': highwater
|
92 | });
|
93 | });
|
94 |
|
95 | socket.on('data', function (data) {
|
96 | var decrypted = cryptography.decrypt(socket.antisocial.friend.remotePublicKey, socket.antisocial.friend.keys.private, data);
|
97 | if (!decrypted.valid) {
|
98 | console.log('WatchNewsFeedItem decryption signature validation error:', decrypted.invalidReason);
|
99 | return;
|
100 | }
|
101 |
|
102 | try {
|
103 | data = JSON.parse(decrypted.data);
|
104 | }
|
105 | catch (e) {
|
106 | data = decrypted.data;
|
107 | }
|
108 |
|
109 | if (socket.antisocial.dataHandler) {
|
110 | socket.antisocial.dataHandler(data);
|
111 | }
|
112 | });
|
113 |
|
114 | socket.on('disconnect', function (reason) {
|
115 | antisocialApp.emit('close-activity-connection', {
|
116 | 'info': socket.antisocial,
|
117 | 'reason': reason
|
118 | });
|
119 |
|
120 | db.updateInstance('friends', socket.antisocial.friend.id, {
|
121 | 'online': false
|
122 | });
|
123 |
|
124 | delete antisocialApp.openActivityListeners[socket.antisocial.key];
|
125 | });
|
126 |
|
127 | socket.emit('highwater', socket.antisocial.friend.highWater ? socket.antisocial.friend.highWater : moment().subtract(7, 'd').toISOString());
|
128 |
|
129 | db.updateInstance('friends', socket.antisocial.friend.id, {
|
130 | 'online': true
|
131 | });
|
132 | });
|
133 |
|
134 |
|
135 | debug('authenticating');
|
136 | socket.emit('authentication', {
|
137 | 'username': friend.remoteUsername,
|
138 | 'friendAccessToken': friend.remoteAccessToken
|
139 | });
|
140 | });
|
141 | };
|
142 |
|
143 | module.exports.disconnect = function activityFeedSubscribeDisconnect(antisocialApp, config, dbAdaptor, currentUser, friend) {
|
144 | for (var key in antisocialApp.openActivityListeners) {
|
145 | var socket = antisocialApp.openActivityListeners[key];
|
146 | if (socket.data.friend.id.toString() === friend.id.toString()) {
|
147 | debug('disconnect %s', socket.data.connectionKey);
|
148 | socket.disconnect(true);
|
149 | delete antisocialApp.openActivityListeners[key];
|
150 | }
|
151 | }
|
152 | };
|