This repository was archived by the owner on Mar 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSocketEventsPlugin.js
More file actions
125 lines (105 loc) · 3.27 KB
/
Copy pathSocketEventsPlugin.js
File metadata and controls
125 lines (105 loc) · 3.27 KB
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
import { defer, pick } from 'underscore';
import { before } from 'meld';
import Events from 'plug/core/Events';
import chatFacade from 'plug/facades/chatFacade';
import currentRoom from 'plug/models/currentRoom';
import currentUser from 'plug/models/currentUser';
import Plugin from '../Plugin';
const CHAT_INTERCEPT_STRING = `ExtPlugSocketIntercept${Math.random()}`;
// gives the user all permissions client-side temporarily, to make sure that
// a chat message will actually be passed to the socket.
function sudo(cb) {
const originalUser = currentUser.toJSON();
currentUser.set({
id: 1,
guest: false,
level: 50,
role: 5,
gRole: 5,
}, { silent: true });
const originalRoom = pick(currentRoom.toJSON(), 'joined', 'minChatLevel');
currentRoom.set({
joined: true,
minChatLevel: 0,
}, { silent: true });
// this forces the chat slowmode cooldown timer to always return 0, thus
// working around slowmode
const originalMax = Math.max;
Math.max = () => 0;
cb();
Math.max = originalMax;
currentRoom.set(originalRoom, { silent: true });
currentUser.set(originalUser, { silent: true });
}
function getSocket() {
// If RCS is loaded and already has a reference to the WebSocket, just use
// that.
if (window.rcs && window.rcs.plugSock &&
window.rcs.plugSock.sock instanceof WebSocket) {
return window.rcs.plugSock.sock;
}
const send = WebSocket.prototype.send;
let socket;
WebSocket.prototype.send = function sendIntercept(data) {
if (this.url.indexOf('plug.dj') !== -1 && data.indexOf(CHAT_INTERCEPT_STRING) !== -1) {
socket = this;
WebSocket.prototype.send = send;
} else {
send.call(this, data);
}
};
sudo(() => {
chatFacade.sendChat(CHAT_INTERCEPT_STRING);
});
// restore even if it didn't work
WebSocket.prototype.send = send;
return socket;
}
const SocketEventsPlugin = Plugin.extend({
enable() {
const plugin = this;
this.socket = getSocket();
if (this.socket) {
this.onConnect();
}
// make sure we still get an instance if the server reconnects, or
// if ExtPlug loads before plug.dj connects, by overriding the WebSocket
// constructor
const WS = WebSocket;
window.WebSocket = function WebSocketIntercept(arg) {
plugin.debug('instance', arg);
const ws = new WS(arg);
// wait for plug.dj to add handlers
defer(() => {
// find the socket object again, this new connection might be
// instantiated by a plugin or another extension, and that should not
// be intercepted
plugin.socket = getSocket();
plugin.onConnect();
});
return ws;
};
WebSocket.prototype = WS.prototype;
this.WS = WS;
},
disable() {
if (this.WS) window.WebSocket = this.WS;
if (this.advice) this.advice.remove();
this.WS = null;
this.advice = null;
this.socket = null;
},
onConnect() {
if (this.advice) this.advice.remove();
this.debug('patching', this.socket);
this.advice = before(this.socket, 'onmessage', (e) => {
if (e.data !== 'h') {
this.debug('receive', e.data);
JSON.parse(e.data).forEach((message) => {
Events.trigger(`socket:${message.a}`, message.p);
});
}
});
},
});
export default SocketEventsPlugin;