-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathBotControls.user.js
130 lines (105 loc) · 4.62 KB
/
BotControls.user.js
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
130
// ==UserScript==
// @name Bot Controls
// @namespace https://github.com/SOBotics
// @description Simplifies the process of sending feedback to most SOBotics bots
// @author double-beep
// @match https://chat.stackoverflow.com/rooms/111347/*
// @match https://chat.stackoverflow.com/rooms/167908/*
// @version 1.0.0
// @downloadURL https://github.com/SOBotics/Userscripts/raw/master/BotControls.user.js
// @updateURL https://github.com/SOBotics/Userscripts/raw/master/BotControls.user.js
// @run-at document-end
// @grant none
// ==/UserScript==
/* globals CHAT */
(function () {
'use strict';
function intercept(callback) {
const open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener('load', () => {
if (!/messages\/\d+\/history/.test(this.responseURL)) return;
callback();
}, false);
open.apply(this, arguments);
};
}
class Control {
constructor(botId, phrase, feedbacks) {
this.botId = botId;
this.phrase = phrase;
this.feedbacks = feedbacks;
this.roomId = CHAT.CURRENT_ROOM_ID;
this.chatFkey = window.fkey().fkey;
}
generateReply(toReplyId, text) {
return `:${toReplyId} ${text}`;
}
async sendMessageToChat(messageText) {
const params = new FormData();
params.append('text', messageText);
params.append('fkey', this.chatFkey);
await fetch(`/chats/${this.roomId}/messages/new`, {
method: 'POST',
body: params
});
}
decorateChatMessage(element) {
const messageId = element.closest('.message')?.id.split('-')[1];
const container = document.createElement('span');
container.classList.add(`controls-${this.botId}`, 'controls-container');
container.append(' [ ');
this.feedbacks.forEach((feedback, index) => {
const anchor = document.createElement('a');
anchor.classList.add(`${feedback}-${this.botId}`);
anchor.href = '#';
anchor.textContent = feedback;
anchor.addEventListener('click', event => {
event.preventDefault();
const message = this.generateReply(messageId, feedback);
this.sendMessageToChat(message);
});
container.append(anchor);
if (index !== this.feedbacks.length - 1) container.append(' | ');
});
container.append(' ] ');
element.prepend(container);
}
decorateNotDecoratedMessages() {
document.querySelectorAll(`.user-${this.botId}.monologue .message .content`)
.forEach(el => {
if (!el.innerHTML.match(this.phrase) || el.querySelector('.controls-container')) return;
this.decorateChatMessage(el);
});
}
runOnNewMessage({ room_id, event_type, user_id, content, message_id }) {
if (room_id !== this.roomId // event happened in the current room
|| (event_type !== 1 && event_type !== 2) // new message posted/existing message edited
|| user_id !== this.botId // the author of the message is the bot in question
|| !content?.includes(this.phrase) // the new/edited message is a report
) return;
setTimeout(() => {
this.decorateChatMessage(document.querySelector(`#message-${message_id} .content`));
}, 0); // hacky setTimeout; element is not found otherwise
}
init() {
this.decorateNotDecoratedMessages();
CHAT.addEventHandlerHook(event => this.runOnNewMessage(event));
intercept(this.decorateNotDecoratedMessages.bind(this));
}
}
const ready = CHAT.Hub.roomReady.fire;
CHAT.Hub.roomReady.fire = function() {
ready.apply(this, arguments);
const natty = new Control(6817005, 'Link to Post', ['tp', 'fp', 'ne']);
const queen = new Control(6294609, 'SCORE', ['tp', 'fp', 'nc', 'sk']);
const generic = new Control(7481043, 'has been edited', ['untrack']);
const belisarius = new Control(13903854, 'All revisions', ['tp', 'fp']);
const guttenberg = new Control(7418352, 'is possible', ['k', 'f']);
natty.init();
queen.init();
generic.init();
belisarius.init();
guttenberg.init();
};
})();