1 | // Minimal template - we assume JQuery is loaded |
2 | // and script is included only once |
3 | |
4 | /*jshint esversion: 6 */ |
5 | |
6 | console.log("starting sahil-style chat bot template"); |
7 | |
8 | // polyfill for URLSearchParams |
9 | |
10 | (function (w) { |
11 | w.URLSearchParams = w.URLSearchParams || function (searchString) { |
12 | var self = this; |
13 | self.searchString = searchString; |
14 | self.get = function (name) { |
15 | var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(self.searchString); |
16 | if (results == null) { |
17 | return null; |
18 | } |
19 | else { |
20 | return decodeURI(results[1]) || 0; |
21 | } |
22 | }; |
23 | }; |
24 | })(window); |
25 | |
26 | // helper for inserting emojis |
27 | |
28 | $.fn.insertIntoTextArea = function(textToInsert) { |
29 | return this.each(function () { |
30 | var txt = $(this); |
31 | var cursorPosStart = txt.prop('selectionStart'); |
32 | var cursorPosEnd = txt.prop('selectionEnd'); |
33 | var v = txt.val(); |
34 | var textBefore = v.substring(0, cursorPosStart); |
35 | var textAfter = v.substring(cursorPosEnd, v.length); |
36 | txt.val(textBefore + textToInsert + textAfter); |
37 | txt.prop('selectionStart', cursorPosStart + textToInsert.length); |
38 | txt.prop('selectionEnd', cursorPosStart + textToInsert.length); |
39 | txt.focus(); |
40 | }); |
41 | }; |
42 | |
43 | // more helpers |
44 | |
45 | function dynamicallyLoadScript(url, onload, asModule) { |
46 | var script = document.createElement("script"); |
47 | script.src = url; |
48 | script.onload = onload; |
49 | if (asModule) script.type = "module"; |
50 | document.head.appendChild(script); |
51 | } |
52 | |
53 | function dynamicallyLoadModule(code) { |
54 | var script = document.createElement("script"); |
55 | script.type = "module"; |
56 | script.appendChild(document.createTextNode(code)); |
57 | document.head.appendChild(script); |
58 | } |
59 | |
60 | function loadStyleSheet(url, onLoad) { |
61 | var link = document.createElement('link'); |
62 | link.setAttribute("rel", "stylesheet"); |
63 | link.setAttribute("type", "text/css"); |
64 | link.onload = onLoad; |
65 | link.setAttribute("href", url); |
66 | document.head.appendChild(link); |
67 | } |
68 | |
69 | class ChatBot { |
70 | constructor() { |
71 | this.n = $n; |
72 | this.interval = 1000; |
73 | this.nInitial = this.n; |
74 | this.started = false; |
75 | this.cookie = localStorage.getItem('chatbot-cookie'); |
76 | this.notificationsOn = true; |
77 | this.pollURL = "$incrementalURL"; |
78 | |
79 | this.sendTyping_sent = 0; |
80 | this.sendTyping_interval = 5000; |
81 | this.typingCounter = 0; |
82 | this.showTyping_interval = 3000; |
83 | |
84 | this.allowEmptyMsg = false; |
85 | |
86 | this.urlParams = new URLSearchParams(window.location.search); |
87 | this.botConfig = this.urlParams.get('_botConfig'); |
88 | this.started = false; |
89 | this.justStarted = true; |
90 | |
91 | // allow cookie override in URL |
92 | var cookie2 = this.urlParams.get('cookie'); |
93 | if (this.urlParams.get("_newBotCookie") == "1") { |
94 | this.cookie = "conv-" + Math.random().toString(36).substr(2, 9); |
95 | console.log("New cookie made >> " + this.cookie); |
96 | } |
97 | |
98 | if (cookie2) { |
99 | this.cookie = cookie2; |
100 | console.log("Cookie override >> " + cookie2); |
101 | } |
102 | |
103 | console.log("cookie 1: " + this.cookie); |
104 | if (!this.cookie) { |
105 | this.cookie = Math.random().toString(36).substr(2, 9); |
106 | localStorage.setItem('chatbot-cookie', this.cookie); |
107 | console.log("cookie 2: " + this.cookie); |
108 | } |
109 | |
110 | /* |
111 | // intTelInput.min.css |
112 | loadStyleSheet("https://botcompany.de/serve/1029819?ct=text/css"); |
113 | |
114 | // intlTelInput.min.js |
115 | dynamicallyLoadScript("https://botcompany.de/serve/1029820?ct=text/javascript", function() { |
116 | window.telInput = document.querySelector("#chat_telephone"); |
117 | console.log("telInput: " + telInput); |
118 | window.telHandler = window.intlTelInput(window.telInput, { |
119 | utilsScript: "https://botcompany.de/serve/1029822?ct=text/javascript", |
120 | preferredCountries: ["in", "gb"], |
121 | separateDialCode: true, |
122 | initialCountry: "$country" |
123 | }); |
124 | }); |
125 | |
126 | dynamicallyLoadScript("https://gazelle.rocks/emoji-picker/index.js", function() { |
127 | console.log("emoji picker loaded"); |
128 | |
129 | dynamicallyLoadModule(` |
130 | import { EmojiButton } from "https://gazelle.rocks/emoji-picker/index.js"; |
131 | |
132 | const picker = new EmojiButton(); |
133 | const trigger = document.querySelector('#bot-emoji-trigger'); |
134 | |
135 | picker.on('emoji', selection => { |
136 | console.log(selection.emoji); |
137 | $("#chat_message").insertIntoTextArea(selection.emoji); |
138 | setTimeout(function() { |
139 | $("#chat_message").focus(); |
140 | }, 250); |
141 | }); |
142 | |
143 | trigger.addEventListener('click', () => picker.togglePicker(trigger)); |
144 | `); |
145 | }, true); |
146 | */ |
147 | } |
148 | |
149 | standardParams() { |
150 | return "&cookie=" + this.cookie + "&rand=" + Math.random() + (!this.botConfig ? "" : "&_botConfig=" + encodeURIComponent(this.botConfig)); |
151 | } |
152 | |
153 | start() { |
154 | if (this.started) return; |
155 | this.started = true; |
156 | this.poll(); |
157 | } |
158 | |
159 | poll() { |
160 | if (!this.pollURL) return; |
161 | |
162 | var url = this.pollURL + this.n + this.standardParams(); |
163 | |
164 | // mandatory memory wipe on opening chat bot |
165 | if (this.language) url += "&language_default=" + this.language; |
166 | if (this.justStarted) { |
167 | url += "&message=!new+dialog"; |
168 | this.justStarted = false; |
169 | } |
170 | |
171 | var self = this; |
172 | var again = function() { self.poll(); }; |
173 | |
174 | console.log("Loading " + url); |
175 | $.get(url, function(src) { |
176 | console.log("Loaded " + src.length + " chars"); |
177 | var match = src.match(/\d+/); |
178 | if (match != null) { |
179 | var newN = parseInt(match[0]); |
180 | if (src.match(/NEW DIALOG -->/)) { |
181 | $(".chat-box .chat-live-content").html(src); |
182 | } else { |
183 | // hide old buttons and special input fields |
184 | $(".chat_buttons, .chat-button-span, .chatbot-choice-button").hide(); |
185 | $("#chat_telephone, .iti").hide(); |
186 | $("#chat_message").show(); |
187 | // now append new stuff |
188 | $(".chat-box .chat-live-content").append(src); |
189 | } |
190 | //var oldN = self.n; |
191 | self.n = newN; |
192 | console.log("newN=" + newN); |
193 | $(".chat-box").scrollTop(1000000); |
194 | console.log("Appended " + src.length); |
195 | console.log(src); |
196 | } else |
197 | console.log("self.n=" + self.n + " (initial=" + self.nInitial + ")"); |
198 | var interval = self.interval; |
199 | console.log("Rescheduling (" + interval + ")"); |
200 | //var interval = src == '' ? self.interval*10 : self.interval; // slowdown when bug |
201 | setTimeout(again, interval); |
202 | console.log("Rescheduled"); |
203 | }, 'text') |
204 | .fail(function() { |
205 | console.log("Rescheduling after fail"); |
206 | setTimeout(again, self.interval); |
207 | }); |
208 | } |
209 | |
210 | // also focuses input field |
211 | setInput(text, placeholder) { |
212 | if (placeholder == '') placeholder = "Type a message..."; |
213 | $('#chat_message') |
214 | .attr('placeholder', placeholder); |
215 | if (text) |
216 | $('#chat_message').val(text).select().focus(); |
217 | } |
218 | |
219 | submitAMsg(msg) { |
220 | if (!this.allowEmptyMsg && msg == "") return; |
221 | $("#chat_message").val(msg); |
222 | this.submitMsg(); |
223 | } |
224 | |
225 | submitMsg() { |
226 | var msg = $("#chat_message").val(); |
227 | |
228 | if ($("#chat_telephone").is(":visible") && !/^!/.test(msg)) |
229 | msg = window.telHandler.getNumber(); |
230 | |
231 | var url = '$msgURL' + encodeURIComponent(msg) + this.standardParams(); |
232 | if (this.language) url += "&language_default=" + this.language; |
233 | console.log('Submitting ' + url); |
234 | $.get(url); |
235 | $("#chat_message").val(''); |
236 | } |
237 | |
238 | playChatNotification() { |
239 | if (window.chatNotificationWav == null) { |
240 | console.log("Loading notification wav"); |
241 | window.chatNotificationWav = new Audio("$notificationSound"); |
242 | if ("$workerMode" != "true") |
243 | window.chatNotificationWav.volume = 0.5; |
244 | } |
245 | console.log("Playing notification mp3"); |
246 | window.chatNotificationWav.play(); |
247 | } |
248 | |
249 | /*var originalTitle; |
250 | |
251 | window.setTitleStatus = function(status) { |
252 | if (originalTitle == null) |
253 | originalTitle = document.title; |
254 | if (!document.hasFocus() || document.activeElement !== document.getElementById('chat_message')) { |
255 | if (status) status = status + " "; |
256 | } else status = ""; |
257 | document.title = status + originalTitle; |
258 | }; |
259 | |
260 | resetTitle() { |
261 | window.setTitleStatus(""); |
262 | } |
263 | |
264 | window.onfocus = resetTitle; |
265 | $('#chat_message').on("focus", resetTitle);*/ |
266 | |
267 | sendTyping() { |
268 | var time = Date.now(); |
269 | if (time > this.sendTyping_sent+this.sendTyping_interval) { |
270 | this.sendTyping_sent = time; |
271 | var url = "$typingURL" + this.standardParams(); |
272 | console.log("Loading " + url); |
273 | $.get(url); |
274 | } |
275 | } |
276 | |
277 | notiToggle() { |
278 | this.submitAMsg('!toggle notifications'); |
279 | var text = $("#chatBot_notiToggleText"); |
280 | text.text("Turn " + (/Turn on/.test(text.text()) ? "off" : "on") + " notifications"); |
281 | } |
282 | |
283 | showTyping(botImg) { |
284 | var self = this; |
285 | console.log("showTyping " + self.typingCounter); |
286 | self.typingCounter++; |
287 | |
288 | // set avatar image for typing wave |
289 | if (botImg) { |
290 | // old version: $('#otherSideTyping img').attr('src', botImg); |
291 | $('#otherSideTyping div.bg-img').css("background-image", "url('" + botImg + "')"); |
292 | } |
293 | |
294 | if (self.typingCounter == 1) |
295 | $('#otherSideTyping').css('display', 'block'); |
296 | setTimeout(function() { |
297 | console.log("showTyping end " + self.typingCounter); |
298 | if (--self.typingCounter <= 0) |
299 | $('#otherSideTyping').css('display', 'none'); |
300 | }, self.showTyping_interval); |
301 | } |
302 | |
303 | chat_keyDown(event) { |
304 | if (event.keyCode == 13) { this.submitMsg(); return false; } |
305 | else if (event.keyCode >= 32 && event.keyCode < 128) this.sendTyping(); |
306 | } |
307 | } // end of class ChatBot |
308 | |
309 | var chatBot = new ChatBot(); |
310 | |
311 | function chatBot_setInput(text, placeholder) { |
312 | chatBot.setInput(text, placeholder); |
313 | } |
314 | |
315 | function submitAMsg(msg) { |
316 | chatBot.submitAMsg(msg); |
317 | } |
318 | |
319 | function submitMsg() { |
320 | chatBot.submitMsg(); |
321 | } |
322 | |
323 | function showTyping(botImg) { chatBot.showTyping(botImg); } |
324 | |
325 | function playChatNotification() { chatBot.playChatNotification(); } |
326 | |
327 | // change window title when bot says something |
328 | |
329 | var originalTitle; |
330 | |
331 | function setTitleStatus(status) { |
332 | if (originalTitle == null) |
333 | originalTitle = document.title; |
334 | if (!document.hasFocus() || document.activeElement !== document.getElementById('chat_message')) { |
335 | if (status) status = status + " "; |
336 | } else status = ""; |
337 | document.title = status + originalTitle; |
338 | } |
339 | |
340 | function resetTitle() { |
341 | setTitleStatus(""); |
342 | } |
Began life as a copy of #1030430
Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt
No comments. add comment
Snippet ID: | #1030498 |
Snippet name: | Pays5 Sahil-Style Bot Template As JavaScript [dev.] |
Eternal ID of this version: | #1030498/29 |
Text MD5: | 0dbd9778bc710bf6e6368eda2520534c |
Author: | stefan |
Category: | javax / web chat bots |
Type: | Document |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-01-13 23:01:13 |
Source code size: | 10682 bytes / 342 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 259 / 331 |
Version history: | 28 change(s) |
Referenced in: | [show references] |