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

303
LINES

< > BotCompany Repo | #1028679 // Cruddie Spike [with VAT magic for Chrome]

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

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

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

Author comment

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: #1028679
Snippet name: Cruddie Spike [with VAT magic for Chrome]
Eternal ID of this version: #1028679/34
Text MD5: cb8a154981fa170c61f92d47c303fd31
Transpilation MD5: 496e02387fc9fb96cea7efe313751ed7
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-05 15:14:31
Source code size: 10979 bytes / 303 lines
Pitched / IR pitched: No / No
Views / Downloads: 285 / 8464
Version history: 33 change(s)
Referenced in: [show references]