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

395
LINES

< > BotCompany Repo | #1030819 // BEA Live Input [dev.]

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

Uses 12447K of libraries. Click here for Pure Java version (18775L/98K).

1  
!7
2  
3  
concept Screen {
4  
  S screenID;
5  
  long lastSeen = now();
6  
  
7  
  S query;
8  
  
9  
  transient S status;
10  
11  
  // the ongoing search (if any)
12  
  transient LC_ParallelSearch search;
13  
  
14  
  transient Lock lock = lock();
15  
16  
  toString { ret "Screen " + screenID; }
17  
}
18  
19  
cmodule2 BEALiveInput > DynPrintLogAndEnabled {
20  
  switchable int statusUpdateInterval = 100;
21  
22  
  transient Map<virtual WebSocket, Screen> webSockets = syncWeakHashMap();
23  
24  
  transient Set<virtual WebSocket> liveSearches = weakHashSet();
25  
  
26  
  start {
27  
    dbIndexing(Screen, 'screenID);
28  
    dm_doEvery(statusUpdateInterval, r updateStati);
29  
  }
30  
31  
  set flag NoNanoHTTPD. 
32  
  O html(IWebRequest request) { try {
33  
    //try object redirectToHTTPS(request);
34  
    
35  
    S uri = request.uri();
36  
    SS params = request.params();
37  
    print(+params);
38  
    
39  
    S cookie = request.cookie();
40  
    print("cookie", cookie);
41  
    
42  
    new Matches m;
43  
    
44  
    if (eqic(uri, "/about"))
45  
      ret serveText(unindent_mls([[
46  
        What is the BEA Live Input?
47  
  
48  
        Bla bla bla. Also, bla.
49  
      ]]));
50  
    
51  
    if (eqic(uri, "/websockettest")) {
52  
      ret htitle("Web Socket Test")
53  
        + hreconnectingWebSockets()
54  
        + hloadjquery()
55  
        + hdiv("bla<br>", id := "dynamic", style := "font-size: 40px")
56  
        + hjavascript([[
57  
          var ws = new ReconnectingWebSocket("wss://wikify.live/test");
58  
          ws.onopen = function(event) {
59  
            ws.send("here i am");
60  
            $("#dynamic").append("Streaming...<br>");
61  
          };
62  
          ws.onmessage = function(event) {
63  
            $("#dynamic").html(event.data);
64  
            document.title = event.data;
65  
          };
66  
        ]]);
67  
    }
68  
69  
    // home page
70  
    S query = "";
71  
    if (swic(uri, "/search/", m))
72  
      query = takeFirst(1000, urldecode(m.rest()));
73  
    else // now we actually accept wikify.live/{any search term}
74  
      query = urldecode(dropSlashPrefix(uri));
75  
76  
    ret hhtml(hmobilefix() + hhead(
77  
        htitle("BEA Live Input [dev.]")
78  
      + hsansserif()
79  
      + hstyle([[
80  
        .queryContainer {
81  
          height: 100%;
82  
          width: 100%;
83  
84  
          display: flex;
85  
          flex-flow: column;
86  
        }
87  
        
88  
        input.query {
89  
          font-size: 40px;
90  
          padding: 20px;
91  
          width: 400px;
92  
          height: 2em;
93  
94  
          position: relative;
95  
          left: 50%;
96  
          transform: translate(-50%, 0);
97  
          flex: .01 1 auto;
98  
        }
99  
100  
        .filler {
101  
          flex: .5 1 auto;
102  
        }
103  
104  
        .filler.ontop {
105  
          flex: .01 1 auto;
106  
        }
107  
        
108  
        input.query.ontop {
109  
          transform: translate(-50%, 0);
110  
          margin-top: 20px;
111  
          font-size: 20px;
112  
        }
113  
        
114  
        .searching {
115  
          display: none;
116  
        }
117  
        
118  
        .searching.show {
119  
          display: block;
120  
          position: relative;
121  
          left: 50%;
122  
          margin-left: -45px;
123  
        }
124  
125  
        .results {
126  
          font-family: monospace;
127  
          white-space: pre; /* no word-wrapping */
128  
          overflow: auto; /* scrollbars */
129  
          margin-top: 20px;
130  
          border: 2px solid black;
131  
          padding: 0px;
132  
          display: block;
133  
          flex: .01 1 auto;
134  
          opacity: 0%;
135  
          width: 1px;
136  
          margin-left: auto;
137  
          margin-right: auto;
138  
        }
139  
140  
        .results.ontop {
141  
          padding: 20px;
142  
          flex: 1 0 0;  
143  
          opacity: 100%;
144  
          width: calc(100% - 50px);
145  
          left: 0;
146  
          transform: none;
147  
        }
148  
        
149  
        .about {
150  
          margin-bottom: 10px;
151  
          font-size: 12px;
152  
          text-align: center;
153  
          margin-left: auto;
154  
          margin-right: auto;
155  
        }
156  
        
157  
        .status {
158  
          display: none;
159  
          margin-top: 10px;
160  
          font-size: 12px;
161  
        }
162  
        
163  
        .status.ontop {
164  
          display: block;
165  
          margin-left: auto;
166  
          margin-right: auto;
167  
        }
168  
        
169  
        .query, .results, .filler {
170  
          transition: all 1s;
171  
        }
172  
      ]])
173  
      + hLoadJQuery2()
174  
      + hreconnectingWebSockets())
175  
      + hbody(hdiv(
176  
            hdiv("", class := "filler")
177  
          + hdiv("AI bla bla<br>"
178  
          + "By " + ahref("https://BotCompany.de", "BotCompany") + "."
179  
          + targetBlank("/about", "More info."), class := "about")
180  
          + hinput("", value := query, autofocus := true, class := "query", placeholder := "TYPE ANYTHING")
181  
          + hdiv("", class := "status")
182  
          + hdiv(
183  
              hdiv("", class := "actualResults")
184  
            + hdiv(himgsnippet(#1102949, title := "Searching..."), class := "searching"),
185  
              class := "results")
186  
          + hdiv("", class := "filler"),
187  
          class := "queryContainer")
188  
      + hjs_urlencode()
189  
      + hjs([[
190  
        function queryUpdate() {
191  
          var sel = $("input.query, .queryContainer, .results, .filler, .status");
192  
          var q = $("input.query").val();
193  
          if (q == "") {
194  
            $(".actualResults").html("");
195  
            sel.removeClass("ontop");
196  
          } else {
197  
            sel.addClass("ontop");
198  
          }
199  
          if (history.replaceState)
200  
            history.replaceState(null, "Wikify.LIVE", q == "" ? "/" : "/search/" + urlencode(q));
201  
          sendQuery();
202  
        }
203  
      
204  
        $("input.query").on('change keydown paste input', queryUpdate);
205  
        var screenID = Math.random().toString(36).substr(2, 9);
206  
        var wsURL = "wss://wikify.live/search?screen=" + urlencode(screenID);
207  
        console.log("WS: " + wsURL);
208  
        var ws = new ReconnectingWebSocket(wsURL);
209  
        var wsReady = false;
210  
        var querySent = "";
211  
        var maxQueryLength = 1000;
212  
213  
        function wsSend(text) {
214  
          if (wsReady) {
215  
            console.log("wsSend: " + text);
216  
            ws.send(text);
217  
          } else
218  
            console.log("wsNotReady: " + text);
219  
        }
220  
221  
        function sendQuery() {
222  
          var q = $("input.query").val().substring(0, maxQueryLength);
223  
          if (querySent != q) {
224  
            querySent = q;
225  
            wsSend(JSON.stringify({ q: q }));
226  
          }
227  
        }
228  
        
229  
        ws.onopen = function(event) {
230  
          wsReady = true;
231  
          ws.onmessage = function(event) {
232  
            var text = event.data;
233  
            console.log("Got text: " + text);
234  
            var data = JSON.parse(text);
235  
            if ('clearResults' in data)
236  
              $(".actualResults").html("");
237  
            if ('searching' in data)
238  
              $(".searching").addClass("show");
239  
            if ('result' in data)
240  
              $(".actualResults").append(data.result + "<br>");
241  
            if ('searchCancelled' in data)
242  
              $(".searching").removeClass("show");
243  
            if ('searchDone' in data) {
244  
              $(".actualResults").append("<br>[SEARCH DONE]<br>");
245  
              $(".searching").removeClass("show");
246  
            }
247  
            if ('status' in data)
248  
              $(".status").html(data.status);
249  
          };
250  
          queryUpdate();
251  
        };
252  
      ]])
253  
      ));
254  
  } catch e { printStackTrace(e); throw rethrow(e); }
255  
  }
256  
  
257  
  class Request {
258  
    S cookie;  
259  
  }
260  
261  
  void cleanMeUp_webSockets {
262  
    for (virtual WebSocket ws : cloneAndClearKeys(webSockets)) {
263  
      print("Closing WebSocket");
264  
      close((AutoCloseable) ws);
265  
    }
266  
  }
267  
268  
  void cleanMeUp_searches {
269  
    for (virtual WebSocket ws : cloneAndClearList(liveSearches))
270  
      cancelSearch_noLock(webSockets.get(ws));
271  
  }
272  
  
273  
  // API for Eleu
274  
  
275  
  void setEleu(O eleu) {
276  
    setOptMC(mainBot := eleu);
277  
  }
278  
  
279  
  void handleWebSocket(virtual WebSocket ws) {
280  
    print("Got new websocket!");
281  
    set(ws, onClose := r { webSockets.remove(ws) });
282  
    
283  
    set(ws, onOpen := rEnter {  
284  
      S uri = cast rcall getUri(ws);
285  
      
286  
      print("WebSocket opened! uri: " + uri);
287  
      
288  
      SS params = cast rcall getParms(ws);
289  
      S screenID = takeFirst(params.get("screen"), 100);
290  
      Screen screen = uniq Screen(+screenID);
291  
      screen.status = null;
292  
      webSockets.put(ws, screen);
293  
      cset(screen, lastSeen := now());
294  
      
295  
      print("Screen ID: " + screenID);
296  
        
297  
      setFieldToIVF1Proxy(ws, onMessage := msg -> {
298  
        temp enter();
299  
        pcall {
300  
          S text = cast rcall getTextPayload(msg);
301  
          print("Got msg: " + text);
302  
303  
          Map json = jsonDecodeMap(text);
304  
          S q = upper((S) json.get("q"));
305  
          if (q != null && neq(screen.query, q)) {
306  
            temp tempLock("start search", screen.lock);
307  
            
308  
            cancelSearch_noLock(screen);
309  
            cset(screen, query := q);
310  
            if (nempty(q))
311  
              startSearch_noLock(ws, screen, q);
312  
          }
313  
        }
314  
      });
315  
316  
      if (eq(uri, "/test")) thread {
317  
        repeat 100 {
318  
          call(ws, 'send, "It is " + localTimeWithMilliseconds());
319  
          sleep(100);
320  
        }
321  
      }
322  
323  
      if (eq(uri, "/search")) {
324  
      }
325  
    });
326  
  }
327  
328  
  void cancelSearch_noLock(Screen screen) {
329  
    if (screen == null) ret;
330  
    close(screen.search);
331  
    screen.search = null;
332  
  }
333  
334  
  void startSearch_noLock(virtual WebSocket ws, Screen screen, S query) {
335  
    cset(screen, +query);
336  
    call(ws, "send", jsonEncode(litorderedmap("clearResults", true)));
337  
      
338  
    if (empty(query)) ret;
339  
    
340  
    call(ws, "send", jsonEncode(litorderedmap("searching", true)));
341  
342  
    print("Starting search for " + quote(query) + " for " + screen);
343  
    /*LC_ParallelSearch search = new(searchers, query);
344  
    screen.search = search;
345  
    liveSearches.add(ws);
346  
    search.enter = lambda0 enter;
347  
    search.maxResults = defaultResults;
348  
    search.onResult = (iSearcher, iFile, position) -> {
349  
      temp tempLock("onResult", screen.lock);
350  
      if (screen.search != search) ret;
351  
      try {
352  
        //print("Sending result");
353  
        S status = search.status_html();
354  
        call(ws, "send", jsonEncode(litorderedmap(
355  
          result := renderResult(iSearcher, iFile, position, query, screen.search.startTime),
356  
          +status)));
357  
        //print("Sent result");
358  
      } catch print e {
359  
        cancelSearch_noLock(screen);
360  
      }
361  
    };
362  
    search.onSearchDone = r {
363  
      liveSearches.remove(ws);
364  
      print("Search done. " + screen.search + " / " + search);
365  
      temp tempLock("onSearchDone", screen.lock);
366  
      if (screen.search != search) ret;
367  
      updateStatus(ws, screen);
368  
      print("Cancelling search");
369  
      cancelSearch_noLock(screen);
370  
      print("Sending searchDone");
371  
      call(ws, "send", jsonEncode(litorderedmap(
372  
        search.completed() ? "searchDone" : "searchCancelled", true)));
373  
      print("Sent searchDone");
374  
    };
375  
    search.start();*/
376  
  }
377  
378  
  void updateStati enter {
379  
    for (virtual WebSocket ws : cloneList(liveSearches)) pcall {
380  
      Screen screen = webSockets.get(ws);
381  
      updateStatus(ws, screen);
382  
    }
383  
  }
384  
  
385  
  void updateStatus(virtual WebSocket ws, Screen screen) {
386  
    if (screen == null) ret;
387  
    /*LC_ParallelSearch search = screen.search;
388  
    if (search == null) ret;
389  
    S status = search.status_html();
390  
    if (neq(status, screen.status)) {
391  
      screen.status = status;
392  
      call(ws, "send", jsonEncode(litorderedmap(status := screen.status)));
393  
    }*/
394  
  }
395  
}

Author comment

Began life as a copy of #1029430

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt

No comments. add comment

Snippet ID: #1030819
Snippet name: BEA Live Input [dev.]
Eternal ID of this version: #1030819/10
Text MD5: a2d03d42941d69da4bb682023afdd7d3
Transpilation MD5: e0e9be9e77162150c598de135b54f6b7
Author: stefan
Category: javax
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-07-14 18:44:26
Source code size: 11481 bytes / 395 lines
Pitched / IR pitched: No / No
Views / Downloads: 203 / 65182
Version history: 9 change(s)
Referenced in: [show references]