Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

329
LINES

< > BotCompany Repo | #1027610 // Cruddie standalone [old]

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 911K of libraries. Click here for Pure Java version (20104L/121K).

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  
  switchable int vadUpdateInterval = 100;
16  
  switchable double listenTime = 3.0; // listen for 3 seconds after voice activity
17  
  switchable double listenTimeAfterActualSpeech = 10.0; // listen for 10 seconds after actual speech recognized
18  
  switchable double transcriptTitleShowTime = 5.0; // how long to show recognized text in window title
19  
  switchable bool showVadStatus;
20  
  
21  
  S myLink() { ret "https://cruddie.site/"; }
22  
  S botLink() { ret "bot"; /*ret appendWithSlash(myLink(), "bot");*/ }
23  
  
24  
  switchable S frontendModuleLibID = "#1027675/ChatBotFrontend";
25  
  switchable S backendModuleLibID = "#1027591/DynamicClassesMultiCRUD";
26  
  transient S cmdsSnippetID = #1027616;
27  
28  
  start {
29  
    standardScriptsCRUD = new CRUD(StandardScript);
30  
    conversationsCRUD = new CRUD(Conversation);
31  
    thread enter { pcall {
32  
      File saltFile = secretProgramFile("salt.txt");
33  
      S salt = trimLoadTextFile(saltFile);
34  
      if (empty(salt)) {
35  
        saveTextFile(saltFile, salt = randomID());
36  
        print("Made salt"); 
37  
      }
38  
      dm_restartOnFieldChange enabled();
39  
      if (!enabled) ret;
40  
      chatBot = new WebChatBot;
41  
      chatBot.forceCookie = true;
42  
      chatBot.preprocess = s -> {
43  
        S s2 = googleDecensor(s);
44  
        print("Preprocessing: " + s + " => " + s2);
45  
        ret s2;
46  
      };
47  
      chatBot.templateID = #1027690;
48  
      chatBot.baseLink = botLink();
49  
      chatBot.thoughtBot = new ThoughtBot;
50  
      
51  
      chatBot.jsOnMsgHTML = "window.processNewStuff(src);";
52  
      
53  
      chatBot.onBotShown = [[ {
54  
        var input = $("#status_message")[0];
55  
        console.log("input: " + input);
56  
        if (input)
57  
          new Awesomplete(input, {
58  
            minChars: 1,
59  
            list: [
60  
              "I call you Fido",
61  
              "What is your name?",
62  
              'add script "#1027704/SomeCruddieScripts/RepeatAfterMe"',
63  
              'add script "#1027704/SomeCruddieScripts/GoPublic"',
64  
              'clear scripts'
65  
            ]
66  
          });
67  
      } ]];
68  
      
69  
      chatBot.afterHeading = "` + ('webkitSpeechRecognition' in window ? ` &nbsp; " + tag("button", "...", onclick := lineBreaksToSpaces([[
70  
        startOrStop();
71  
        if (bigOn) { lastHadVoice = Date.now(); startVAD(); startUpdater(); humOn(); }
72  
        else stopVAD();
73  
      ]]), type := 'button, class := 'speechOnBtn, disabled := 'disabled, display := 'inline)
74  
        /*+ hjs([[console.log("Updating"); window.srUpdate();]])*/ + "` : ``) + `"
75  
        + hdiv(hsnippetimg(#1102938, width := 24, height := 24, title := "Streaming audio to cloud"), style := "display: inline; visibility: hidden; margin-left: 10px", class := "listenStatus")
76  
        + (!showVadStatus ? "" : 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"))
77  
        + hdiv(small("Note: All conversations are public rn " + targetBlank("https://www.youtube.com/watch?v=StxQerL0D-o", "(why)")));
78  
        
79  
      chatBot.moreStuff = "window.srUpdate();";
80  
  
81  
      chatBot.start();
82  
      
83  
      set redirectHttpToHttps;
84  
      start_webServers(serverSocketFactory_botCompanyEtc());
85  
    }}
86  
  }
87  
88  
  O webServe(S uri, SS params) {
89  
    Pair<Int, Bool> spamCheck = spamBlocker.checkRequest(uri, serveHttp_clientIP());
90  
    if (spamCheck.b) {
91  
      sleepSeconds(60.0);
92  
      ret print("go away");
93  
    }
94  
    printVars("webServe", +uri);
95  
    //S cookie = serveHttp_cookieHandling();
96  
    
97  
    if (startsWith(uri, "/.well-known/"))
98  
      ret loadTextFile(userDir("validation.txt"));
99  
    
100  
    // new-style cookie isn't really used yet
101  
    S newStyleCookie = nu ServeHttp_CookieHandler(verbose := true).handle();
102  
    
103  
    new Matches m;
104  
    S uri2 = appendSlash(uri);
105  
    if (startsWith(uri2, "/bot/", m))
106  
      ret chatBot.html("/" + m.rest(), params);
107  
    if (eq(uri, "/awesomplete.css")) ret serveWithContentType(loadSnippet(#2000595), "text/css");
108  
    if (eq(uri, "/awesomplete.js")) ret serveText(loadSnippet(#2000594));
109  
    if (endsWith(uri, ".map")) ret "";
110  
    
111  
    if (eq(uri, "/frames"))
112  
      ret serveFrameSet(params);
113  
      
114  
    S jsOnSpeech = [[
115  
      if (transcript == 'stop listening')
116  
        stopVAD();
117  
      else
118  
        window.submitAMsg(transcript);
119  
      lastHeard = transcript;
120  
      lastHeardWhen = Date.now();
121  
    ]];
122  
    
123  
    S sayBotMsgsScript = [[
124  
      window.processNewStuff = function(src) {
125  
      ]] + (eq(params.get('quiet), "1") ? "" : [[
126  
        if ($("#speechResults") == null) return; // no speech
127  
        // we assume that webkit speech synthesis is present
128  
        // when there is webkit speech recognition
129  
        if (!bigOn) return; // not enabled
130  
        console.log("Got speech");
131  
        var match = src.match(/\d+/);
132  
        if (match == null) return;
133  
        if (src.match(/NEW DIALOG -->/)) return;
134  
        console.log("Got incremental");
135  
        var re = /bot-utterance">(.*?)</g;
136  
        var match = re.exec(src);
137  
        var lastUtterance = null;
138  
        while (match != null) {
139  
          lastUtterance = match[1];
140  
          match = re.exec(src);
141  
        }
142  
        // TODO: properly drop HTML tags/HTML-decode
143  
        if (lastUtterance)
144  
          say(lastUtterance);
145  
      ]]) + [[
146  
      };
147  
    ]];
148  
    
149  
    S speechUI = "";
150  
      /*hdiv(
151  
        "&lt; Talk to me &gt;",
152  
        id := 'speechResults,
153  
        style := "margin: 10px");*/
154  
        
155  
    // old-style cookie (client-generated)
156  
    // S botScript = (S) chatBot.html("/", litmap(), returnJS := true);
157  
    
158  
    // new-style cookie (server-generated)
159  
    WebChatBot.Request req = chatBot.new Request("/", litmap());
160  
    req.cookie = newStyleCookie;
161  
    S botScript = cast req.html(returnJS := true);
162  
    
163  
    int humVolume = 5;
164  
      
165  
    ret hhtml(hmobilefix() + hhead(
166  
        htitle("CRUDDIE - I manage your anything")
167  
      + hLoadJQuery2()
168  
      + hjs_humWithFade(humVolume/100.0)
169  
      + hJsMakeCookie()
170  
      + [[<link rel="stylesheet" href="awesomplete.css" /><script src="awesomplete.js"></script>]] // took out async
171  
      )
172  
      + hbody(hOnBottom(
173  
        p(hsnippetimage(#1102905))
174  
      + p("Work in progress")
175  
      + p("Hum volume (sound when listening): " + htextinput("", humVolume, style := "width: 5ch", id := "humVolumeInput", onInput := "updateHumVolume(parseInt(this.value)/100.0)"))
176  
      + stats()
177  
      + hSpeechRecognition(jsOnSpeech, true, "en-US", false,
178  
        noWebKit := p("Use Chrome if you want speech recognition"),
179  
        +speechUI)
180  
      + hjavascript([[
181  
        function say(text) {
182  
          console.log("Saying: " + text);
183  
          var u = new SpeechSynthesisUtterance(text);
184  
          u.lang = 'en-US';
185  
          u.onstart = function() { console.log("speech start"); meSpeaking = true; };
186  
          u.onend = function() { meSpeaking = false; };
187  
          window.speechSynthesis.speak(u);
188  
        }
189  
      ]] + sayBotMsgsScript)
190  
      + hjs(botScript)
191  
      + hVAD(
192  
        [[console.log("voice start"); $(".vadStatus").css("visibility", "visible");]],
193  
        [[console.log("voice stop"); $(".vadStatus").css("visibility", "hidden");]],
194  
        false)
195  
      + hjs_setTitleStatus()
196  
      + hjs(replaceDollarVars([[
197  
        var updater;
198  
        var lastHadVoice = 0;
199  
        var lastHeard, lastHeardWhen = 0;
200  
        var meSpeaking = false;
201  
        
202  
        //audioMeterDebug = true;
203  
        
204  
        function startUpdater() {
205  
          if (updater) return;
206  
          console.log("Starting updater");
207  
          updater = setInterval(vadMagicUpdate, $interval);
208  
          srPause = true;
209  
        }
210  
        
211  
        function stopUpdater() {
212  
          if (!updater) return;
213  
          console.log("Stopping updater");
214  
          clearInterval(updater);
215  
          updater = null;
216  
          window.resetTitle();
217  
        }
218  
        
219  
        function vadMagicUpdate() {
220  
          var now = Date.now();
221  
          var hasVoice = vadHasVoice();
222  
          var clipping = vadHasClipping();
223  
          if (hasVoice) lastHadVoice = now;
224  
          var shouldListen1 = bigOn && (lastHadVoice >= now-$listenTime || lastHeardWhen >= now-$listenTimeAfterActualSpeech);
225  
          var shouldListen = !meSpeaking && shouldListen1;
226  
          var titleStatus = "";
227  
          if (lastHeardWhen >= now-$transcriptTitleShowTime)
228  
            titleStatus = lastHeard + " |";
229  
          else if (shouldListen)
230  
            titleStatus = $listeningSymbol;
231  
          else if (bigOn)
232  
            titleStatus = $ear;
233  
          if (clipping)
234  
            titleStatus = "! " + titleStatus;
235  
          window.setTitleStatus(titleStatus);
236  
          if (srPause != !shouldListen) {
237  
            console.log(shouldListen ? "Listening" : "Not listening");
238  
            srPause = !shouldListen;
239  
            srUpdate();
240  
          }
241  
          if (shouldListen1) humOn(); else humOff();
242  
          if (!bigOn) { stopUpdater(); return; }
243  
        }
244  
        
245  
        // debug mic level
246  
        /*setInterval(function() {
247  
          if (audioMeter)
248  
            console.log("Mic level: " + audioMeter.absLevel);
249  
        }, 1000);*/
250  
      ]],
251  
        interval := vadUpdateInterval,
252  
        listenTime := toMS(listenTime),
253  
        listenTimeAfterActualSpeech := toMS(listenTimeAfterActualSpeech),
254  
        transcriptTitleShowTime := toMS(transcriptTitleShowTime),
255  
        listeningSymbol := jsQuote(/*"[LISTENING]"*/unicode_cloud()),
256  
        ear := jsQuote(unicode_ear())))
257  
      )/*, onLoad := "startAwesomplete()"*/));
258  
  }
259  
  
260  
  S cookieToCaseID(S cookie) {
261  
    ret md5(cookie + salt);
262  
  }
263  
  
264  
  class Request {
265  
    S cookie, caseID;
266  
    S frontend, backend; // module IDs
267  
    
268  
    *(S *cookie) {
269  
      caseID = cookieToCaseID(cookie);
270  
      frontend = dm_makeModuleWithParams_systemQ(frontendModuleLibID, +caseID);
271  
      backend = dm_makeModuleWithParams_systemQ(backendModuleLibID, +caseID);
272  
      dm_call(frontend, 'connectToBackend, backend);
273  
      dm_call(frontend, 'importCmdsFromSnippetIfEmpty, cmdsSnippetID);
274  
      dm_call(frontend, 'addScripts, collect scriptID(list StandardScript()));
275  
      Conversation conv = uniq Conversation(+cookie);
276  
      forwardSwappableFunctionToObject(dm_mod(frontend),
277  
        'chatLog_userMessagesOnly, func -> LS {
278  
          map(m -> m.text, filter(conv.allMsgs(), m -> m.fromUser))
279  
        }, 'get);
280  
      printVars(+caseID, +backend);
281  
    }
282  
  }
283  
  
284  
  class ThoughtBot {
285  
    new ThreadLocal<Request> request;
286  
    
287  
    void setSession(S cookie, SS params) {
288  
      //session.set(uniq_sync(Session, +cookie));
289  
      request.set(new Request(cookie));
290  
    }
291  
    
292  
    S initialMessage() {
293  
      //ret "Hello from module " + request->backend;
294  
      ret (S) dm_call(request->backend, 'answer, "stats");
295  
    }
296  
    
297  
    S answer(S s) {
298  
      ret (S) dm_call(request->frontend, 'answer, s);
299  
    }
300  
  }
301  
  
302  
  S stats() {
303  
    ret p(joinWithBR(
304  
      "Server temperature is " + dm_cpuTemperature(),
305  
      n2(numberOfCruddies(), "cruddie") + ", " + n2(vmBus_countResponses chatBotFrontend()) + " loaded",
306  
    ));
307  
  }
308  
  
309  
  int numberOfCruddies() {
310  
    ret countDirsInDir(getProgramDir(beforeSlash(frontendModuleLibID)));
311  
  }
312  
  
313  
  visualize {
314  
    JComponent c = jtabs("Main", super.visualize(),
315  
      "Standard Scripts", standardScriptsCRUD.visualizeWithCountInTab(),
316  
      "Conversations", conversationsCRUD.visualizeWithCountInTab());
317  
    standardScriptsCRUD.updateTabTitle();
318  
    conversationsCRUD.updateTabTitle();
319  
    ret c;
320  
  }
321  
      
322  
  S serveFrameSet(SS params) {
323  
    ret hhtml(hhead_title("CRUDDIE with frames") +
324  
      tag frameset(
325  
        tag frame("", name := "leftmonitor") +
326  
        tag frame("", src := appendParamsToURL(myLink(), params)) +
327  
        tag frame("", name := "rightmonitor"), cols := "*,550,*"));
328  
  }
329  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 8 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, unoaxrwscvea, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1027610
Snippet name: Cruddie standalone [old]
Eternal ID of this version: #1027610/178
Text MD5: aab0aa4749c01d848b16a1b4b2ea4651
Transpilation MD5: 70782cf6eaf3ef70656f86346fc01912
Author: stefan
Category: javax
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-07-14 18:47:31
Source code size: 12241 bytes / 329 lines
Pitched / IR pitched: No / No
Views / Downloads: 602 / 12549
Version history: 177 change(s)
Referenced in: [show references]