Uses 911K of libraries. Click here for Pure Java version (19600L/114K).
1 | !7 |
2 | |
3 | concept StandardScript { |
4 | S scriptID; |
5 | } |
6 | |
7 | cmodule Cruddie > DynPrintLogAndEnabled { |
8 | !include #1027628 // HTTP+HTTPS servers |
9 | |
10 | transient S salt; |
11 | transient WebChatBot chatBot; |
12 | transient CRUD<StandardScript> standardScriptsCRUD; |
13 | transient CRUD<Conversation> conversationsCRUD; |
14 | |
15 | S myLink() { ret "https://cruddie.site/"; } |
16 | S botLink() { ret "bot"; /*ret appendWithSlash(myLink(), "bot");*/ } |
17 | |
18 | switchable S frontendModuleLibID = "#1027675/ChatBotFrontend"; |
19 | switchable S backendModuleLibID = "#1027591/DynamicClassesMultiCRUD"; |
20 | transient S cmdsSnippetID = #1027616; |
21 | |
22 | start { |
23 | standardScriptsCRUD = new CRUD(StandardScript); |
24 | conversationsCRUD = new CRUD(Conversation); |
25 | thread { |
26 | File saltFile = secretProgramFile("salt.txt"); |
27 | S salt = trimLoadTextFile(saltFile); |
28 | if (empty(salt)) { |
29 | saveTextFile(saltFile, salt = randomID()); |
30 | print("Made salt"); |
31 | } |
32 | dm_restartOnFieldChange enabled(); |
33 | if (!enabled) ret; |
34 | chatBot = new WebChatBot; |
35 | chatBot.preprocess = s -> { |
36 | S s2 = googleDecensor(s); |
37 | print("Preprocessing: " + s + " => " + s2); |
38 | ret s2; |
39 | }; |
40 | chatBot.templateID = #1027690; |
41 | chatBot.baseLink = botLink(); |
42 | chatBot.thoughtBot = new ThoughtBot; |
43 | |
44 | chatBot.jsOnMsgHTML = "window.processNewStuff(src);"; |
45 | |
46 | chatBot.onBotShown = [[ { |
47 | var input = $("#status_message")[0]; |
48 | console.log("input: " + input); |
49 | if (input) |
50 | new Awesomplete(input, { |
51 | minChars: 1, |
52 | list: [ |
53 | "I call you Fido", |
54 | "What is your name?", |
55 | 'add script "#1027704/SomeCruddieScripts/RepeatAfterMe"', |
56 | 'add script "#1027704/SomeCruddieScripts/GoPublic"', |
57 | 'clear scripts' |
58 | ] |
59 | }); |
60 | } ]]; |
61 | |
62 | chatBot.afterHeading = "` + ('webkitSpeechRecognition' in window ? ` " + tag("button", "...", onclick := "startOrStop(); if (bigOn) startVAD(); else stopVAD();", type := 'button, class := 'speechOnBtn, disabled := 'disabled, display := 'inline) |
63 | /*+ hjs([[console.log("Updating"); window.srUpdate();]])*/ + "` : ``) + `" |
64 | + hdiv(hsnippetimg(#1102908, width := 24, height := 24, title := "Someone is speaking (either me or you)"), style := "display: inline; visibility: hidden; margin-left: 10px", class := "vadStatus") |
65 | + hdiv(hsnippetimg(#1102909, width := 24, height := 24, title := "Listening"), style := "display: inline; visibility: hidden; margin-left: 10px", class := "listenStatus") |
66 | + hdiv(small("Note: All conversations are public rn " + targetBlank("https://www.youtube.com/watch?v=StxQerL0D-o", "(why)"))); |
67 | |
68 | chatBot.moreStuff = "window.srUpdate();"; |
69 | |
70 | chatBot.start(); |
71 | |
72 | set redirectHttpToHttps; |
73 | start_webServers(javaxSecretDir("cruddie.site/keystore.p12"), "botcompany"); |
74 | } |
75 | } |
76 | |
77 | O webServe(S uri, SS params) { |
78 | printVars("webServe", +uri); |
79 | //S cookie = serveHttp_cookieHandling(); |
80 | new Matches m; |
81 | S uri2 = appendSlash(uri); |
82 | if (startsWith(uri2, "/bot/", m)) |
83 | ret chatBot.html("/" + m.rest(), params); |
84 | if (eq(uri, "/awesomplete.css")) ret serveWithContentType(loadSnippet(#2000595), "text/css"); |
85 | if (eq(uri, "/awesomplete.js")) ret serveText(loadSnippet(#2000594)); |
86 | |
87 | S jsOnSpeech = "if (transcript != 'stop listening') window.submitAMsg(transcript);"; |
88 | |
89 | S sayBotMsgsScript = [[ |
90 | window.processNewStuff = function(src) { |
91 | ]] + (eq(params.get('quiet), "1") ? "" : [[ |
92 | if ($("#speechResults") == null) return; // no speech |
93 | // we assume that webkit speech synthesis is present |
94 | // when there is webkit speech recognition |
95 | if (!bigOn) return; // not enabled |
96 | console.log("Got speech"); |
97 | var match = src.match(/\d+/); |
98 | if (match == null) return; |
99 | if (src.match(/NEW DIALOG -->/)) return; |
100 | console.log("Got incremental"); |
101 | var re = /bot-utterance">(.*?)</g; |
102 | var match = re.exec(src); |
103 | var lastUtterance = null; |
104 | while (match != null) { |
105 | lastUtterance = match[1]; |
106 | match = re.exec(src); |
107 | } |
108 | // TODO: properly drop HTML tags/HTML-decode |
109 | if (lastUtterance) |
110 | say(lastUtterance); |
111 | ]]) + [[ |
112 | }; |
113 | ]]; |
114 | |
115 | S speechUI = ""; |
116 | /*hdiv( |
117 | "< Talk to me >", |
118 | id := 'speechResults, |
119 | style := "margin: 10px");*/ |
120 | |
121 | ret hhtml(hmobilefix() + hhead( |
122 | htitle("CRUDDIE - I manage your anything") |
123 | + hLoadJQuery2() |
124 | + hJsMakeCookie() |
125 | + [[<link rel="stylesheet" href="awesomplete.css" /><script src="awesomplete.js"></script>]] // took out async |
126 | ) |
127 | + hbody(hOnBottom( |
128 | p(hsnippetimage(#1102905)) |
129 | + p("Chat bot is doing basic stuff. Documentation coming up.") |
130 | + stats() |
131 | + hjavascript([[ |
132 | var srPause; |
133 | |
134 | function say(text) { |
135 | console.log("Saying: " + text); |
136 | var u = new SpeechSynthesisUtterance(text); |
137 | u.onstart = function() { console.log("speech start"); srPause = true; srUpdate(); }; |
138 | u.onend = function() { srPause = false; srUpdate(); }; |
139 | window.speechSynthesis.speak(u); |
140 | } |
141 | ]] + sayBotMsgsScript) |
142 | + hSpeechRecognition(jsOnSpeech, true, "en-US", false, |
143 | noWebKit := p("Use Chrome if you want speech recognition"), |
144 | +speechUI) |
145 | + hjs((S) chatBot.html("/", litmap(), returnJS := true)) |
146 | + hVAD( |
147 | [[console.log("voice start"); $(".vadStatus").css("visibility", "visible");]], |
148 | [[console.log("voice stop"); $(".vadStatus").css("visibility", "hidden");]], |
149 | false) |
150 | )/*, onLoad := "startAwesomplete()"*/)); |
151 | } |
152 | |
153 | S cookieToCaseID(S cookie) { |
154 | ret md5(cookie + salt); |
155 | } |
156 | |
157 | class Request { |
158 | S cookie, caseID; |
159 | S frontend, backend; // module IDs |
160 | |
161 | *(S *cookie) { |
162 | caseID = cookieToCaseID(cookie); |
163 | frontend = dm_makeModuleWithParams_systemQ(frontendModuleLibID, +caseID); |
164 | backend = dm_makeModuleWithParams_systemQ(backendModuleLibID, +caseID); |
165 | dm_call(frontend, 'connectToBackend, backend); |
166 | dm_call(frontend, 'importCmdsFromSnippetIfEmpty, cmdsSnippetID); |
167 | dm_call(frontend, 'addScripts, collect scriptID(list StandardScript())); |
168 | Conversation conv = uniq Conversation(+cookie); |
169 | forwardSwappableFunctionToObject(dm_mod(frontend), |
170 | 'chatLog_userMessagesOnly, func -> LS { |
171 | map(m -> m.text, filter(conv.allMsgs(), m -> m.fromUser)) |
172 | }, 'get); |
173 | printVars(+caseID, +backend); |
174 | } |
175 | } |
176 | |
177 | class ThoughtBot { |
178 | new ThreadLocal<Request> request; |
179 | |
180 | void setSession(S cookie, SS params) { |
181 | //session.set(uniq_sync(Session, +cookie)); |
182 | request.set(new Request(cookie)); |
183 | } |
184 | |
185 | S initialMessage() { |
186 | //ret "Hello from module " + request->backend; |
187 | ret (S) dm_call(request->backend, 'answer, "stats"); |
188 | } |
189 | |
190 | S answer(S s) { |
191 | ret (S) dm_call(request->frontend, 'answer, s); |
192 | } |
193 | } |
194 | |
195 | S stats() { |
196 | ret p(joinWithBR( |
197 | "Server temperature is " + dm_cpuTemperature(), |
198 | n2(numberOfCruddies(), "cruddie") + ", " + n2(vmBus_countResponses chatBotFrontend()) + " loaded", |
199 | )); |
200 | } |
201 | |
202 | int numberOfCruddies() { |
203 | ret countDirsInDir(getProgramDir(beforeSlash(frontendModuleLibID))); |
204 | } |
205 | |
206 | visual |
207 | jtabs("Main", super, |
208 | "Standard Scripts", standardScriptsCRUD.visualize(), |
209 | "Conversations", conversationsCRUD.visualize()); |
210 | } |
Began life as a copy of #1027610
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1027734 |
Snippet name: | Cruddie [backup before changing cookie handling] |
Eternal ID of this version: | #1027734/1 |
Text MD5: | 6ab1a5a2047bed8727c6d029be3782cb |
Transpilation MD5: | 2e9c5ce050655a6be6cb27eeac07a833 |
Author: | stefan |
Category: | |
Type: | JavaX source code (Dynamic Module) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-04-09 12:26:06 |
Source code size: | 7769 bytes / 210 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 202 / 262 |
Referenced in: | [show references] |