Download Jar. Uses 17395K of libraries. Click here for Pure Java version (44978L/280K).
1 | !7 |
2 | |
3 | set flag hotwire_here. // to honor classesToShare |
4 | |
5 | sbool greetCookies, theoryOn; |
6 | |
7 | sbool cloned; |
8 | static long clonedSince, cloningSince; |
9 | sS postStartUpMessageToChat; |
10 | static new L thoughtBots; |
11 | static long started, indexMakingTime, bootTime; |
12 | static Class theoryModule; |
13 | static Lock theoryLock = lock(); |
14 | static S selectedWord; |
15 | static int inputNr = 1; |
16 | static int myPort = 4678; |
17 | static int ultimateAnswerLimit = 500000; |
18 | static double speculationTimeoutForHttp = 5.0; // 5 seconds |
19 | static double speculationTimeoutForNewChatLine = 30.0; |
20 | static int autoComplete_timeOut = 1000; // 1 second |
21 | static Set<S> speculationQueue = synchroHashSet(); |
22 | static double spammerSleep = 10.0; |
23 | static Set<S> blockedIPs = synchroHashSet(); |
24 | |
25 | sS classesToShare = smartBot_sharedClasses(); |
26 | |
27 | static Lock aiLock = lock(); |
28 | static new ThreadLocal<Bool> httpAuthed; |
29 | static Map<S, L<S>> lastUserLines = syncCIMap(); |
30 | static new ThreadLocal<L> afterAnswering; |
31 | static new ThreadLocal<Bool> answering; |
32 | static L<GlobalID> latestWebs = synchroList(LatestList(1000)); |
33 | |
34 | static TimedCache<Int> cachedNumberOfThreads = TimedCache(f numberOfAllThreads, 10.0); |
35 | |
36 | static L<S> tripleAnswerFunctions = ll( |
37 | f ai_tripleAnswer_regexpMatches |
38 | ); |
39 | |
40 | set flag allpublic. |
41 | |
42 | // save space |
43 | sclass E {} |
44 | set flag noCLParse. |
45 | |
46 | p { |
47 | set profilePoint_print; |
48 | print("yo"); |
49 | started = sysNow(); |
50 | try { setGCFrequency(10*60.0); // 10 minutes |
51 | } catch { updateJavaXAndRestart(); } |
52 | |
53 | doEvery(10*60*1000, r { blockedIPs.clear() }); |
54 | |
55 | ai_useThoughtSpaces(true); |
56 | cachedNodeIndex_autoMake = false; |
57 | releaseDBLockOnTimeoutEval(); |
58 | ai_prepLoadFunctions(); |
59 | |
60 | //set postToStefansChat_printStackTrace; |
61 | db(); |
62 | load('selectedWord); |
63 | load('inputNr); |
64 | //autoRestart(5); |
65 | //typicalDownload(); |
66 | |
67 | O webSocketFactory = f makeWebSocket; |
68 | if (canOccupyPort80()) |
69 | serveHttpWithWebsockets_multiplePorts(webSocketFactory, myPort, 80); |
70 | else |
71 | serveHttpWithWebsockets(myPort, webSocketFactory); |
72 | pcall { serveHttps_botCompany(); } |
73 | |
74 | bot("Smart Bot.", func(S s) -> S { |
75 | S x = "Input line " + (inputNr++); |
76 | print(x); |
77 | save("inputNr"); |
78 | ai_postTriple(x, "is", quote(s)); |
79 | //ai_speculate(x); |
80 | |
81 | stefansChat_onLine_fullParams.set(litmap(auth := true)); |
82 | try { |
83 | ret actualAnswer(s); |
84 | } finally { |
85 | stefansChat_onLine_fullParams.set(null); |
86 | } |
87 | }); |
88 | |
89 | loadPage_forcedTimeout = 70000; |
90 | thoughtBots.add(mc()); |
91 | |
92 | indexMakingTime = sysNow(); |
93 | |
94 | ai_fillTripleIndex(); |
95 | //tripleIndex().addWeb(web_setGlobalID("abcdefghijklmnop", webFromTriple("It's", "a", "test"))); |
96 | |
97 | indexMakingTime = sysNow()-indexMakingTime; |
98 | |
99 | // TODO ai_onNewIndexedText_do(func(S s) { speculationQueue.add(s) }); |
100 | |
101 | //thoughtBots.add(memoryBot = runSubBot(#1001951)); |
102 | |
103 | handleStefansChat(); |
104 | handleSmartBotsChat(); |
105 | |
106 | //stefansChat_post("Smart Bot Upgraded! Boot took: " + formatDouble(fromMS(sysNow()-started), 1) + " s"); |
107 | |
108 | if (greetCookies) runInNewThread(#1010793); // Post on UAIP |
109 | |
110 | ai_onNewWeb(f ai_spec_moveToMiddle); |
111 | ai_onNewWeb(f addToLatestWebs); |
112 | ai_extendKnownVerbs(); |
113 | |
114 | // Do the slow stuff |
115 | |
116 | addVirtualNodeIndex(hugeEnglishDictionary_virtualNodeIndex()); |
117 | loadTheory(); |
118 | |
119 | thread "Speculator" { speculatorLoop(); } |
120 | |
121 | doneLoading(); |
122 | bootTime = sysNow()-started; |
123 | if (cloned) |
124 | postToChatNamed(postStartUpMessageToChat, infoBoxAndReturn( |
125 | "Smart Bot cloned in " + formatSeconds(bootTime, 1) + "s (" |
126 | + formatSeconds(sysNow()-clonedSince, 1) + "s full)")); |
127 | else |
128 | infoBox("Smart Bot booted in " + formatSeconds(bootTime, 1) + "s"); |
129 | } |
130 | |
131 | sS actualAnswer(S s) { |
132 | ret scanMultipleBots(thoughtBots, s); |
133 | } |
134 | |
135 | svoid loadTheory { |
136 | lock theoryLock; |
137 | cleanUp(theoryModule); |
138 | theoryModule = null; |
139 | if (!theoryOn) ret; |
140 | theoryModule = run(#1010963); |
141 | setOpt(theoryModule, 'onUpdate, r { call(theoryModule, 'react) }); |
142 | call(theoryModule, 'react); |
143 | print("Theory module loaded."); |
144 | } |
145 | |
146 | static int lineCount; |
147 | |
148 | sbool authed() { |
149 | ret isTrue(mapGet(stefansChat_onLine_fullParams!, 'auth)) |
150 | || webAuthed(); |
151 | } |
152 | |
153 | sbool byBot() { |
154 | ret isTrue(mapGet(stefansChat_onLine_fullParams!, 'botMark)); |
155 | } |
156 | |
157 | answer ctex { |
158 | if (byBot()) null; |
159 | /*temp tempSetThreadLocal(answering, true); |
160 | try {*/ |
161 | selectWord(quote(s)); |
162 | S a = answer_2(s); |
163 | //callAll(getAndClearThreadLocal(afterAnswering)); |
164 | try answer a; |
165 | /*} on fail { |
166 | clearThreadLocal(afterAnswering); |
167 | }*/ |
168 | } |
169 | |
170 | sS answer_2(S s) { |
171 | // repeat while ConcurrentModificationException |
172 | // (should not occur anymore anyway) |
173 | while licensed { |
174 | try { |
175 | ret trim(answer_go(s)); |
176 | } catch print e { |
177 | S a = exceptionToStringShort(e); |
178 | if (eq(a, "ConcurrentModificationException")) { |
179 | sleep(50); |
180 | continue; |
181 | } |
182 | ret a; |
183 | } |
184 | } |
185 | null; |
186 | } |
187 | |
188 | |
189 | sS answer_go(S s) { |
190 | ++lineCount; |
191 | bool authed = authed(); |
192 | lock dbLock(); |
193 | |
194 | S std = ai_standardAnswer(s); |
195 | if (std == null) std = ai_standardAnswer_dollarVars(s); // TODO: might get slow eventually |
196 | |
197 | if (!startsWith(s, "!")) |
198 | s = ai_dropDroppableStuff(s); |
199 | |
200 | int safety = 0; |
201 | replaceloop: while (safety++ < 10) { |
202 | s = trim(s); |
203 | |
204 | try answer answer_inner(s, lineCount); |
205 | |
206 | for (WebNode node : indexedNodes(s)) { |
207 | S x = web_operandText(node, "replace with"); |
208 | if (x != null && neq(s, x)) { |
209 | print("Replacing with " + x); |
210 | s = x; |
211 | continue replaceloop; |
212 | } |
213 | } |
214 | |
215 | break; |
216 | } |
217 | |
218 | //if (ai_isQuestion_1(s)) ret "No idea"; |
219 | ret std; |
220 | } |
221 | |
222 | sS chatName() { |
223 | ret or2((S) mapGet(stefansChat_onLine_fullParams!, 'chatName), "Unknown Chat"); |
224 | } |
225 | |
226 | sS chatLineSymbol() { |
227 | ret (S) mapGet(stefansChat_onLine_fullParams!, "Chat line symbol"); |
228 | } |
229 | |
230 | sS answer_inner(S s, int lineCount) { |
231 | S chatName = chatName(); |
232 | |
233 | final new Matches m; |
234 | |
235 | if (eqic(s, "!eval ps")) |
236 | ret backtick("ps"); |
237 | if (swic_trim(s, "!eval ps ", m)) |
238 | ret backtick("ps " + noUnixTricks(m.rest())); |
239 | |
240 | if (authed()) { |
241 | /*if (lineCount >= stefansChat_onLine_lookback)*/ { |
242 | if (eqic(s, "!restart")) { restart(); ret "Yo"; } |
243 | if (eqic(s, "!kill")) { cleanKillIn1Second(); ret "Yo"; } |
244 | if (eqic(s, "!soft-restart 1")) { |
245 | softRestart_level1(); |
246 | ret "Hold on..."; |
247 | } |
248 | |
249 | if (eqicOneOf(s, "!soft-restart", "!auto-restart")) { |
250 | softRestart_level2(); |
251 | ret "Hold on..."; |
252 | } |
253 | |
254 | if (eqic(s, "!theory")) ret "OK" with loadTheory(); |
255 | if (swic_trim(s, "!theory ", m)) |
256 | ret callAnswerFunction(theoryModule, m.rest()); |
257 | if (eqic(s, "!peep")) { |
258 | runAndCleanUp(#1010980); |
259 | ret "OK, got " + fileLength(ai_chatAnalysis_peepHoleFile()) + " bytes"; |
260 | } |
261 | |
262 | if (swic_trim(s, "!subst-web ", m)) { |
263 | L<S> tok = javaTokC(m.rest()); |
264 | if (l(tok) == 2) |
265 | ret ai_subst_web_charBasedReplace(first(tok), selectWord(unquote(last(tok)))); |
266 | else |
267 | ret ai_subst_web(m.rest()); |
268 | } |
269 | |
270 | if (eqic(s, "!idle-patterns")) { |
271 | time2 { |
272 | Either<Int, Thread> e = (Either) evalWithTimeout(60.0, f ai_idle_matchPatterns); |
273 | } |
274 | ret e.isA() ? "Made " + nWebs(e.a()) + " in " + toSeconds(lastTiming(), 1) + "s" : "Timeout"; |
275 | } |
276 | |
277 | if (swic_trim(s, "!experiment ", m)) { |
278 | S code = m.rest(); |
279 | if (!isSnippetID(code)) |
280 | code = psI(#1013002) + " " + bashQuote(code); |
281 | File outFile = directNohupJavax(code); |
282 | ret "OK, " + f2s(outFile); |
283 | } |
284 | |
285 | if (swic_trim(s, "!experiment ", m)) { |
286 | File outFile = directNohupJavax(m.rest()); |
287 | ret "OK, " + f2s(outFile); |
288 | } |
289 | |
290 | if (eqic(s, "!rotate")) { |
291 | rotateSoftwareMadeWebs(); |
292 | ret "OK"; |
293 | } |
294 | |
295 | if (swic_trim(s, "!speculate-all ", m)) { |
296 | time2 { |
297 | Either<Int, Thread> e = (Either) evalWithTimeout(10.0, r { ai_speculate_all(m.rest()) }); |
298 | } |
299 | int n = 0; |
300 | |
301 | pcall { n = e.isA() ? e.a() : websMadeInThread(e.b()); } |
302 | |
303 | ret "Made " + nWebs(n) + " in " + toSeconds(lastTiming(), 1) + "s"; |
304 | } |
305 | |
306 | if (eqic(s, "!quick-transpile yourself")) ret transpileMyself('quick); |
307 | |
308 | if (eqic(s, "!medium-transpile yourself")) ret transpileMyself('medium); |
309 | } |
310 | |
311 | if "unlearn * *" |
312 | ret "OK, was: " + uniq(MatchLearner, pattern := $1).examples.put($2, 'rejected); |
313 | |
314 | if (swic_trim(s, "!sf ", m)) |
315 | ret sfu(callAndMake_orDirect(m.rest())); |
316 | |
317 | if (swic_trim(s, "!specf ", m)) { |
318 | S sf = m.rest(); |
319 | print("specf " + sf); |
320 | Class c = loadFunctionsWithInclude(ll(sf), #1011841); |
321 | try { |
322 | callOpt(c, 'ai_spec_init); |
323 | ret sfu(call(c, sf)); |
324 | } finally { |
325 | cleanUp(c); |
326 | } |
327 | } |
328 | |
329 | if (swicOneOf_trim(s, m, "!eval ", "!j ")) |
330 | ret smartBotEval(m.rest()); |
331 | |
332 | if (swic_trim(s, "!fresh ", m)) { |
333 | dynClear(); |
334 | ret smartBotEval(m.rest()); |
335 | } |
336 | |
337 | if (eqicOneOf(s, "!fresh", "!dyn-clear")) { |
338 | dynClear(); |
339 | ret "OK, refreshed"; |
340 | } |
341 | |
342 | if (swic_trim(s, "!spec ", m)) { |
343 | Pair<S> p = splitAtFirstSpace(m.rest()); |
344 | S f = startsWith(p.a, "ai_") ? p.a : "ai_spec_" + p.a; |
345 | ret smartBotEval("ai_callSpeculationFunction(f " + f + ", " + p.b + ");"); |
346 | } |
347 | |
348 | if (swic_trim(s, "!spec-all ", m)) { |
349 | S f = m.rest(); |
350 | f = startsWith(f, "ai_") ? f : "ai_spec_" + f; |
351 | fS _f = f; |
352 | ret smartBotEval("ai_callSpeculationFunctionOnAllTerms(f " + f + ");"); |
353 | } |
354 | |
355 | if (swic_trim(s, "!run ", m)) { |
356 | runAndCleanUp(m.rest()); |
357 | ret "OK"; |
358 | } |
359 | |
360 | if (swic_trim(s, "!match ", m)) { |
361 | L<S> tok = javaTokC(m.rest()); |
362 | if (l(tok) != 2) ret "need 2 parameters"; |
363 | S pat = get(tok, 0), input = unquote(get(tok, 1)); |
364 | Matches mm = ai_matchPattern(pat, input); |
365 | ret mm == null ? "No match" : sfu(toList(mm.m)); |
366 | } |
367 | |
368 | if (eqic(s, "!compact")) { |
369 | thread "Compacting" { |
370 | startedLoading(); |
371 | try { |
372 | time { |
373 | ai_compactLiveDB(true); |
374 | } |
375 | postToSmartBotsChat("Tripelized in " + toSeconds(lastTiming()) + " s"); |
376 | } finally { |
377 | doneLoading(); |
378 | } |
379 | } |
380 | ret "OK, compacting"; |
381 | } |
382 | |
383 | if (eqic(s, "!sort-lists")) { |
384 | time { |
385 | tripleIndex().sortAllLists(); |
386 | } |
387 | ret "OK [" + lastTiming() + " ms]"; |
388 | } |
389 | |
390 | if (swic_trim(s, "!var ", m)) |
391 | ret sfu(get(mc(), m.rest()); |
392 | |
393 | if (eqic(s, "!mtm")) { |
394 | ai_spec_moveToMiddle_all(); |
395 | ret "OK"; |
396 | } |
397 | |
398 | if (eqic(s, "!gc")) |
399 | ret ai_gc_scan("The most important word"); |
400 | |
401 | if (eqic(s, "!num-invalid")) |
402 | ret lstr(ai_allInvalidWebs()); |
403 | |
404 | if (swic_trim(s, "!load-subspace ", m)) { |
405 | AI_SubSpace ss = ai_swapInSubSpace($1); |
406 | ret "OK, size=" + l(ss); |
407 | } |
408 | |
409 | if (eqic(s, "!assume")) { |
410 | assumeSmartBotURL(); |
411 | ret "OK"; |
412 | } |
413 | |
414 | if "done making that" |
415 | ret ai_doneMakingThat(chatName); |
416 | |
417 | S c = "are making in " + chatName; |
418 | |
419 | if (flexMatchIC("let's make a *", s, m) || flexMatchIC("let's make an *", s, m)) { |
420 | S id = ai_text_verified("We", c, "$X"); |
421 | if (id != null) |
422 | ret "We're still making " + id; |
423 | S aThing = a(m.rest()); |
424 | id = selectWord(aGlobalID()); |
425 | post("We", c, id); |
426 | post(id, "is", aThing); |
427 | |
428 | S answer = "OK, ID for new " + m.rest() + ": " + id + "."; |
429 | |
430 | pcall { |
431 | answer = appendWithSpaceIfNempty(answer, ai_makePartQuestion(chatName, id)); |
432 | } |
433 | |
434 | ret answer; |
435 | } |
436 | |
437 | WebNode openQuestion = first(ai_search_dollarX_verified("Open question in " + chatName, "is", "$X")); |
438 | if (openQuestion != null) { |
439 | post(web_text(openQuestion), "is", s); |
440 | ai_invalidateWeb(openQuestion); |
441 | S answer = "OK, stored: " + web_text(openQuestion) + " is " + quoteUnlessWordsAndSpaces(s) + "."; |
442 | S id = ai_text("We", c, "$X"); // What we're making |
443 | S q = ai_makePartQuestion(chatName, id); |
444 | if (q == null) { |
445 | ai_doneMakingThat(chatName); |
446 | q = "I think we're done here. Made " + id + ", " |
447 | + ai_renderThingDescriptionWithParts(id); |
448 | } |
449 | answer = appendWithSpaceIfNempty(answer, q); |
450 | ret answer; |
451 | } |
452 | |
453 | for (S sf : ai_texts_verified("$X", "is a good function to call when user says", quote(s))) { |
454 | sf = unquote(sf); |
455 | if (endsWith(sf, "()", m)) |
456 | if (isIdentifier(m.rest())) |
457 | ret sfu(makeAndCall(m.rest())); |
458 | } |
459 | |
460 | // end of priviledged commands |
461 | } |
462 | |
463 | if (ai_isQuestion_1(s) && !byBot()) { |
464 | selectWord(s); |
465 | ai_postTriple(s, "should be", "answered in the chat"); |
466 | } |
467 | |
468 | if "Are you online?" ret "Yes"; |
469 | if (eqicOneOf(s, "!question", "!gac")) |
470 | ret random_gac36k(); |
471 | |
472 | if (swic_trim(s, "!word ", m)) { |
473 | selectWord(m.rest()); |
474 | ret "OK " + unicode_rightPointingTriangle() + unicode_rightPointingTriangle(); |
475 | } |
476 | |
477 | if (swic_trim(s, "!image ", m)) { |
478 | S x = m.rest(); |
479 | print("Googling " + x); |
480 | BufferedImage img = quickVisualize(x); |
481 | ret "[IMAGE] " + uploadJPEGToImageServer(img, x); |
482 | } |
483 | |
484 | if "memory stats|full memory stats" |
485 | ret nWeb(ai_allWebsCount()) + ". " + diskSpaceEtcBot_answer(s) + ". " + diskSpaceInfo(); |
486 | |
487 | try answer diskSpaceEtcBot_answer(s); |
488 | |
489 | if (swic_trim(s, "!search ", m)) { |
490 | selectWord("[search] " + m.rest()); |
491 | ret "OK " + unicode_rightPointingTriangle() + unicode_rightPointingTriangle(); |
492 | } |
493 | |
494 | if (swic_trim(s, "!solve ", m)) { |
495 | S a; |
496 | time "Solve in subspace" { |
497 | a = ai_solveQuestionInSubSpace(m.rest()); |
498 | } |
499 | ret "[" + lastTiming() + " ms] " + (a != null ? a : "I don't know"); |
500 | } |
501 | |
502 | if (eqic(s, "!loaded-subspaces")) |
503 | ret sfu(ai_subSpaceNames()); |
504 | |
505 | if (eqic(s, "!subspaces")) |
506 | ret sfu(ai_subSpaceNamesOnDisk()); |
507 | |
508 | if (eqic(s, "!index-time")) ret toS(indexMakingTime, 1) + " s"; |
509 | if (eqic(s, "!boot-time")) |
510 | ret toS(bootTime, 1) + " s (" + toS(bootTime+started-vmStarted(), 1) + "s full)"; |
511 | |
512 | if (swic_trim(s, "!bench-search", m)) { |
513 | T3<S> t = ai_parseArrowTriple(m.rest()); |
514 | time2 { |
515 | int n = l(ai_search_dollarX(t)); |
516 | } |
517 | ret n(n, "result") + ", " + lastTiming() + " ms"; |
518 | } |
519 | |
520 | if (swic_trim(s, "!vary ", m)) |
521 | ret ifEq(ai_nlVary(m.rest()), m.rest(), "Sorry, no variation found"); |
522 | |
523 | if (swic_trim(s, "!google ", m)) |
524 | ret join(" - ", swapPair(first(quickGoogle($1)))); |
525 | |
526 | if (swic_trim(s, "!google-texts", m)) |
527 | ret lines(uniquify(map tripleC(quickGoogle2($1)))); |
528 | |
529 | if (swic_trim(s, "!google-define", m)) |
530 | ret lines(uniquify(map(func(T3<S> t) { t.b + " ~ " + t.c }, |
531 | quickGoogle2($1)))); |
532 | |
533 | if (swic_trim(s, "!google-complete ", m)) |
534 | ret lines(googleAutoComplete($1)); |
535 | |
536 | if (swic_trim(s, "!antonyms ", m)) |
537 | ret join(", ", antonymsFromSynonymDotCom($1)); |
538 | |
539 | if (swic_trim(s, "!has-triple ", m)) { |
540 | Triple<S> t = ai_parseArrowTriple(m.rest()); |
541 | ret yn(ai_cache_hasTriple(t)); |
542 | } |
543 | |
544 | if (swic_trim(s, "!triple ", m) || swic_trim(s, "!triples ", m)) { |
545 | L<S> elements = trimAll(splitAt(m.rest(), "->")); |
546 | if (l(elements) != 3) ret "3 parts please"; |
547 | ret "[IMAGE] " + "http://ai1.space/1007546?triples=" + urlencode(lines(elements)); |
548 | } |
549 | |
550 | if (swic_trim(s, "!answer ", m)) { |
551 | time2 { |
552 | S a = ai_specReturn_answerToExternalQuestion(10.0, m.rest()); |
553 | } |
554 | ret "[" + lastTiming() + " ms] " + (a != null ? a : "I don't know"); |
555 | } |
556 | |
557 | |
558 | if (swic_trim(s, "!web ", m)) { |
559 | S id = $1; |
560 | Web web = indexedWebWithGlobalID(id); |
561 | if (web == null) ret "Not found"; |
562 | ret "[IMAGE] " + smartBotURL() + "/diagram?id=" + id; |
563 | } |
564 | |
565 | if (swic_trim(s, "!parse ", m)) |
566 | ret ai_renderTriple(ai_tripelize(m.rest())); |
567 | |
568 | if (eqic(s, "!worst-case")) |
569 | ret sfu(getOptMC('ai_hasTriple_vary_worstCase)); |
570 | |
571 | if (eqic(s, "!uptime")) |
572 | ret n(secondsSinceSysTime(started), "second"); |
573 | |
574 | if (eqic(s, "!typical-set")) |
575 | ret sfu(diagramServer_typicalSet()); |
576 | |
577 | if (eqic(s, "!num-unverified")) |
578 | ret lstr(ai_unverifiedWebs()); |
579 | |
580 | if (eqic(s, "!num-true")) |
581 | ret lstr(ai_trueWebs()); |
582 | |
583 | if (eqic(s, "!version")) |
584 | ret autoRestart_localMD5(); |
585 | |
586 | if (swic_trim(s, "!blob ", m)) { |
587 | S a = postNodeFromInput(m.rest(), s); |
588 | selectWord(m.rest()); |
589 | ret a; |
590 | } |
591 | |
592 | if (swic_trim(s, "!store ", m)) |
593 | ret postTripleFromInput(ai_tripelize(m.rest()), s); |
594 | |
595 | if (swic_trim(s, "!store-triple ", m)) |
596 | ret postTripleFromInput(ai_parseArrowTriple(m.rest()), s); |
597 | |
598 | if (swic(s, "!nodes ", m)) { |
599 | if (dropSuffixTrim("...", m.rest(), m)) |
600 | ret lstr(indexedNodesStartingWith(m.rest())); |
601 | ret lstr(indexedNodes(m.rest())); |
602 | } |
603 | |
604 | if (eqic(s, "!webs")) |
605 | ret lstr(allIndexedWebs()); |
606 | |
607 | if (swic(s, "!webs ", m)) |
608 | ret joinWithSpace(collect(indexedWebs($1), 'globalID)); |
609 | |
610 | if (swic(s, "!splitAtBaseFormVerb ", m)) |
611 | ret sfu(splitAtBaseFormVerb($1)); |
612 | |
613 | if (swic(s, "!maxRunlengthOfRepeatingChars ", m)) |
614 | ret str(maxRunlengthOfRepeatingChars($1)); |
615 | |
616 | if (swic(s, "!collapseWord ", m)) |
617 | ret collapseWord($1); |
618 | |
619 | if (swic(s, "!gac ", m)) |
620 | ret or2(first(scoredSearch(m.get(0), keys(gac36k()))), "-"); |
621 | |
622 | if (eqic(s, "!vms")) |
623 | ret computerVMs_text(); |
624 | |
625 | if (eqic(s, "!id")) ret aGlobalID(); |
626 | |
627 | if (swic_trim(s, "!count-triple ", m)) { |
628 | T3<S> t = ai_parseArrowTriple(m.rest()); |
629 | print("Searching: " + sfu(t)); |
630 | Pair<Int> p = ai_countBoth_dollarX(t); |
631 | ret eq(p.a, p.b) ? str(p.a) |
632 | : p.a + " (+" + (p.b-p.a) + " unverified)"; |
633 | } |
634 | |
635 | pcall { try answer ai_sfCommands(s); } |
636 | |
637 | if (swic_trim(s, "!macmillan ", m)) try { |
638 | Pair<S, L<S>> p = macmillanDefinitions3(m.rest()); |
639 | ret toUpper(p.a) + "\n" + lines(prependAll("-", p.b)); |
640 | } catch e { |
641 | printShortException(e); |
642 | ret "Macmillan is quiet today."; |
643 | } |
644 | |
645 | try answer ai_answerFromCache(s); |
646 | |
647 | S _s = s; |
648 | s = ai_dropLeadingAdditions(s); |
649 | |
650 | if (neq(_s, s)) |
651 | try answer ai_answerFromCache(s); |
652 | |
653 | if "cache size" |
654 | ret n2(indexedTerms(), "different term") |
655 | //+ ", " + n(web_countNodes(allWebs_cached()), "node") |
656 | //+ ", " + n(allWebs_cached(), "web"); |
657 | + ", " + nWeb(tripleIndex().numWebs()); |
658 | |
659 | if "give me subtypes of ..." |
660 | ret ai_renderList(ai_subtypesOf(m.rest())); |
661 | |
662 | if "give me a third person verb" |
663 | ret random(thirdPersonVerbs()); |
664 | |
665 | if (learnedFlexMatch("give me some *", s, m)) { |
666 | S query = singular($1); |
667 | ret ai_renderNodesList(concatLists( |
668 | ai_index_search_dollarX("$X", "is a", query), |
669 | ai_index_search_dollarX("$X", "is", a(query)))); |
670 | } |
671 | |
672 | if "authed?" |
673 | ret authed() ? "You are authed." : "You are not authed."; |
674 | |
675 | if "what is the singular of *" |
676 | ret or2(getSingularFromWordHippo($1), singular($1)); |
677 | |
678 | if (learnedFlexMatch("what is the relation between * and *", s, m)) { |
679 | L<S> l = ai_getRelation($1, $2); |
680 | //ret ai_renderList(l); |
681 | if (nempty(l)) ret $1 + " " + first(l) + " " + $2; |
682 | } |
683 | |
684 | if (containsAll(asCISet(javaTokC(s)), "list", "long")) |
685 | pcall { try answer callAnswerMethod(hotwireOnce(#1013113), s); } |
686 | |
687 | if "what unix day is it" |
688 | ret str(unixDay()); |
689 | |
690 | if "show me the ..." |
691 | ret "What " + $1 + "?"; |
692 | |
693 | if (learnedFlexMatch("What do * have?", s, m)) |
694 | ret ai_renderNodesList(ai_index_search_dollarX($1, "have", "$X")); |
695 | |
696 | if (learnedFlexMatch("What does * do?", s, m)) |
697 | ret ai_renderList(map(f web_nodePairToText, webs_search_dollarXY(webFromTriples($1, "$X", "$Y"), indexedWebs($1)))); |
698 | |
699 | if (learnedFlexMatch_multi(s, m, "What is *", "Who is *", "Was ist *", "Wer ist *")) |
700 | try answer ai_renderList(ai_whatIs($1), ""); |
701 | |
702 | S sf = web_text(first(ai_search_dollarX_verified("$X", "implements", quote(s)))); |
703 | if (startsWith(sf, "sf ", m)) |
704 | ret str(makeAndCall($1)); |
705 | |
706 | if (learnedFlexMatch("* how many visitors *", s) || match("how many visitors", s)) |
707 | ret str(ai1_cookiesToday_int()); |
708 | |
709 | // Once more with generated webs (replacing $ vars) |
710 | |
711 | if (learnedFlexMatch("What is *", s, m)) { |
712 | L<Web> extendedWebs = indexedWebsAfterVariableSubstitution($1); |
713 | print("Have " + n(extendedWebs, "extended web") + " for " + quote($1)); |
714 | try answer ai_renderNodesList(webs_search_dollarX(webFromTriples($1, "is", "$X"), extendedWebs), null); |
715 | } |
716 | |
717 | try answer ai_tryIfAndInput(s); |
718 | try answer ai_autoApplyRules(s); |
719 | |
720 | if (!ai_isQuestion_1(s) |
721 | && learnedFlexMatch_multi(s, m, "* is *", "* ist *")) |
722 | try answer postTripleFromInput(triple(m.get(0), "is", m.get(1)), s); |
723 | |
724 | try answer ai_standardAnswer(s); |
725 | try answer ai_standardAnswer_dollarVars(s); // TODO: might get slow eventually |
726 | try answer ai_standardAnswerEval(s); |
727 | |
728 | pcall { |
729 | final T3<S> t = ai_tripelize(s); |
730 | if (t != null) { |
731 | try answer evalWithTimeoutOrNull(20.0, func -> S { |
732 | for (O f : tripleAnswerFunctions) |
733 | try answer (S) pcallF(f, t); |
734 | null; |
735 | }); |
736 | try answer ai_standardAnswerSF_triple_dollarVars(t); |
737 | } |
738 | } |
739 | |
740 | // 10 second timeout |
741 | S a = ai_specReturn_answerToExternalQuestion(10.0, s); |
742 | if (nempty(a) && !swicOneOf(a, "[", "What is ")) ret a; |
743 | |
744 | null; |
745 | } |
746 | |
747 | svoid loadBots(S... botIDs) { |
748 | for (S id : botIDs) pcall { |
749 | thoughtBots.add(runSubBot(id)); |
750 | } |
751 | } |
752 | |
753 | static O html(S uri, SS params) { |
754 | profilePoint('html_1); |
755 | S ip = clientIP(); |
756 | bool bad = eq(uri, "/simulate-bad-client"); |
757 | Pair<Int, Bool> pair = simpleSpamClientDetect2(ip, uri); |
758 | if (pair.b) { |
759 | if (eq(ip, pcall_myFirewallIP())) |
760 | print("Not blocking myself."); |
761 | else { |
762 | print("Blocking IP " + ip); |
763 | blockedIPs.add(ip); |
764 | } |
765 | } |
766 | |
767 | if (blockedIPs.contains(ip)) { |
768 | bad = true; |
769 | post_verified(print(t3("an HTTP request from a blocked IP", "came in at", dateWithTimeGMT()))); |
770 | } |
771 | |
772 | if (bad) { |
773 | NanoHTTPD.IHTTPSession httpSession = NanoHTTPD.currentSession!; |
774 | if (httpSession == null) { |
775 | print("No HTML session?"); |
776 | sleepSeconds(spammerSleep); |
777 | ret "go away"; |
778 | } |
779 | httpSession.badClient(true); |
780 | null; |
781 | } |
782 | |
783 | print(gmtWithSeconds() + ": Serving HTTP " + quote(uri) + " to " + ip + " (anti-spam count: " + pair.a + "/" + simpleSpamClientDetect2_spamMax + ")"); |
784 | profilePoint('html_2); |
785 | |
786 | S requestID = aGlobalID(); |
787 | S symbol = "HTTP request " + requestID; |
788 | if (http_isBot()) symbol = "Bot " + symbol; |
789 | //S domain = serveHttp_domainName(); |
790 | { |
791 | temp temp_ai_startBuffering(); |
792 | post_verified(symbol, "came in at", dateWithTimeGMT()); |
793 | post_verified(symbol, "was for path", uri); |
794 | post_verified(symbol, "had user agent", serveHttp_userAgent()); |
795 | post_verified(symbol, "came from IP", ip); |
796 | } |
797 | profilePoint('html_3); |
798 | |
799 | //set serveHttp_cookieHandling_verbose; |
800 | S cookie = serveHttp_cookieHandling(); |
801 | S loginUrl = "/"; |
802 | S pw = params.get("pw"); |
803 | Pair<S, Bool> p = standaloneWebAuth(loginUrl, cookie, pw); |
804 | print("ip=" + ip + ", cookie=" + l(cookie) + ", authed: " + p.b); |
805 | if (nempty(p.a)) ret p.a; |
806 | if (eq(uri, "/login")) ret standaloneWebAuth_showForm(loginUrl, cookie); |
807 | |
808 | httpAuthed.set(p.b); |
809 | try { |
810 | long time = sysNow(); |
811 | O html = html_2(uri, params); |
812 | done2(time, "Making HTML " + uri); |
813 | ret html; |
814 | } finally { |
815 | httpAuthed.set(false); |
816 | } |
817 | } |
818 | |
819 | static O html_2(S s, SS params) { |
820 | new Matches m; |
821 | |
822 | S domain = serveHttp_domainName(); |
823 | |
824 | if (ewic(domain, ".supersrv.de")) ret "Super server!"; |
825 | |
826 | if (eqic(s, "/favicon.ico")) |
827 | ret serveFile(loadLibrary(#1013028), "image/x-icon"); |
828 | |
829 | if (nempty(params.get("_pretendAuthed")) || authed()) |
830 | html_pretendAuthed.set(true); |
831 | |
832 | if (eqic(s, "/number-of-threads")) ret str(cachedNumberOfThreads!); |
833 | |
834 | if (eqic(s, "/realurl")) |
835 | ret hrefresh(smartBotDirectURL()); |
836 | |
837 | if (swic(domain, "pixelboys.") || eqic(domain, "www.botcompany.de")) |
838 | ret hrefresh("https://www.botcompany.de:8443/1016323/raw"); |
839 | |
840 | S input = params.get("input"); |
841 | if (nempty(input)) { |
842 | if (webAuthed()) |
843 | ret htmlencode(callAnswerMethodVerbose(input)); |
844 | else |
845 | ret "Can't send input (not authed)"; |
846 | } |
847 | |
848 | if (swic(s, "/matrix/", m)) { |
849 | s = "/dyn/" + psI(#1013031); |
850 | if (nempty(m.rest())) |
851 | params.put("topic", urldecode(m.rest())); |
852 | } |
853 | |
854 | if (eqicOptSlash(s, "/rules")) |
855 | s = "/dyn/1013529/ai_rulesTable"; |
856 | |
857 | if (eqicOptSlash(s, "/livecount")) |
858 | s = "/dyn/1013377"; |
859 | |
860 | if (eqic(s, "/dyn/fresh")) { |
861 | if (!webAuthed()) ret "No"; |
862 | dynClear(); |
863 | ret "OK"; |
864 | } |
865 | |
866 | if (swic(s, "/dyn/", m)) { |
867 | if (loading()) ret "LOADING, please try again"; |
868 | S u = m.rest(); |
869 | int i = smartIndexOf(u, '/'); |
870 | S id = fsI(takeFirst(u, i)); |
871 | if (!has_verified(id, "is", "a safe web module")) ret "Unsafe"; |
872 | O mod = hotwireCached(id); |
873 | ret callHtmlMethod2(mod, or2(substring(u, i), "/"), params); |
874 | } |
875 | |
876 | if (swic(s, "/sf/", m)) |
877 | ret htmlencode2(struct(callSafeSF(m.rest()))); |
878 | |
879 | if "random-web" |
880 | s = str(randomIndexedTriple().globalID()); |
881 | |
882 | try { |
883 | if "threads" { |
884 | time2 { |
885 | S text = renderRunnableThreadsWithStackTraces(); |
886 | } |
887 | ret hpre(text + "\n\n" + lastTiming() + " ms"); |
888 | } |
889 | |
890 | if (eqic(s, "/livecheck")) ret "Smart Bot"; |
891 | |
892 | if (eqic(s, "/load")) ret formatDouble(systemLoad(), 2); |
893 | |
894 | if (eqic(s, "/1-sec-profile")) ret html_profile(1); |
895 | if (eqic(s, "/10-sec-profile")) ret html_profile(10); |
896 | |
897 | if (eqic(s, "/deadlocks")) ret htmlencode(solveDeadlocks()); |
898 | |
899 | if (eqic(s, "/source-stats")) |
900 | ret h1_title("Source Stats") + multiSetToUL(ai_sourceStats()); |
901 | |
902 | if "thoughts" |
903 | ret serveHTML(html_thoughts()); |
904 | |
905 | if "diagram" { |
906 | S id = params.get("id"); |
907 | Web web = indexedWebWithGlobalID(id); |
908 | ret serveJPEG(webToCAL(web).makeImage(600, 400)); |
909 | } |
910 | |
911 | if "log" |
912 | ret serveText_direct(printLog()); |
913 | |
914 | if "learners" |
915 | ret serveText_direct(renderConcepts(list(MatchLearner))); |
916 | |
917 | if "unreached" |
918 | ret h3_title("Unreached") |
919 | + ul(map html_encyclopediaTopic(ai_gc_unreachedWords())); |
920 | |
921 | // Serve Web With Global ID |
922 | |
923 | s = dropPrefix("/", s); |
924 | if (possibleGlobalID(s)) { |
925 | L<Web> webs = ai_getWebs(s); |
926 | if (nempty(webs)) { |
927 | for (Web web : webs) ai_speculateOnWeb(web); |
928 | |
929 | Web web = first(webs); |
930 | ret h2_title("Web " + s + (ai_isInvalidWeb(web) ? " [INVALID]" : "")) + loadjquery() |
931 | + pre(htmlencode(renderWeb_multiLine(web))) |
932 | + p(himg(ai_webImage_link(s), title := "Web " + s)) |
933 | + (l(webs) > 1 ? p("Warning: Multiple webs") : "") |
934 | + ai_html_wordThoughts("Web " + web.globalID); |
935 | } |
936 | |
937 | /*if (theoryOn && theoryModule == null) ret serveHTML("Loading theory module"); |
938 | Map<S, O> map = (Map) getOpt(theoryModule, 'theoryForLineMap); |
939 | if (map.containsKey(toLower(s))) |
940 | ret serveHTML("A line in the chat.");*/ |
941 | ret serveHTML("Unknown: " + s); |
942 | } |
943 | |
944 | if (swic(s, "json/", m)) { |
945 | s = m.rest(); |
946 | if (swic(s, "relations/", m)) { |
947 | new L out; |
948 | Map map = litorderedmap(); |
949 | if (loading()) map.put("loading", true); |
950 | int max = 1000; |
951 | for (WebRelation r : indexedRelations(m.rest())) |
952 | if (l(out) >= max) { |
953 | map.put("more", true); |
954 | break; |
955 | } else { |
956 | L<S> l = tripleToList(web_relationToTriple(r)); |
957 | l.add(r.web.globalID()); |
958 | l.add(r.web.source); |
959 | if (r.web.verified()) l.add("v"); |
960 | out.add(l); |
961 | } |
962 | map.put("data", out); |
963 | ret serveText(jsonEncode(map)); |
964 | } |
965 | ret "unknown"; |
966 | } |
967 | |
968 | if (swic(s, "e/", m)) { // serve encyclopedia topic |
969 | S topic = urldecode(m.rest()); |
970 | ret html_topic(topic, eq("1", params.get("random"))); |
971 | } |
972 | |
973 | if (swic(s, "autocomplete/", m)) { |
974 | int max = min(100, parseInt(or2(params.get("n"), "10"))); |
975 | L<S> completed = ai_autoComplete(urldecode(m.rest()), max, autoComplete_timeOut); |
976 | new L<Map> out; |
977 | for (S c : completed) { |
978 | new HashMap map; |
979 | if (startsWith(s, c)) |
980 | map.put(follow := substring(c, l(s))); |
981 | else |
982 | map.put(whole := c); |
983 | out.add(map); |
984 | } |
985 | ret serveText(jsonEncode_breakAtLevel1(out)); |
986 | } |
987 | |
988 | if (eqic(s, "alphabetical")) |
989 | ret html_alphabetical(params); |
990 | |
991 | if (eqic(s, "latest-webs")) { |
992 | int n = toInt(params.get('n)); |
993 | if (n == 0) n = 100; |
994 | ret html_latestWebs(min(1000, max(n, 10))); |
995 | } |
996 | |
997 | if (eqic(s, "the-big-number")) |
998 | ret formatWithThousandsSeparator(ai_allWebsCount()); |
999 | |
1000 | if (eqic(s, "random")) |
1001 | ret hrefresh(smartBot_encyclopediaLink(ai_randomString()) + "?random=1"); |
1002 | |
1003 | if (eqic(s, "classes")) ret html_classes(); |
1004 | if (eqic(s, "standard-relations")) ret html_standardRelations(); |
1005 | if (eqic(s, "active")) ret html_active(); |
1006 | |
1007 | if (eqic(s, "all-web-ids")) { |
1008 | L<S> l = allToString(allWebIDs_cloned()); |
1009 | ret serveText( |
1010 | l(l) + " ids follow.\n" + lines(l) |
1011 | + l(l) + " ids written."); |
1012 | } |
1013 | |
1014 | if (eqic(s, "internal-files")) |
1015 | ret serveText(lines(map(func(File f) -> S { |
1016 | quote(f.getName()) + " " + fileSize(f) + " " + fileModificationTime(f) |
1017 | }, listFiles(programDir())))); |
1018 | |
1019 | if (swic(s, "internal-files/", m)) { |
1020 | S name = urldecode(m.rest()); |
1021 | if (!isProperFileName(name)) ret serve404("No"); |
1022 | File f = getProgramFile(name); |
1023 | ret f.isFile() ? serveFile(f) : serve404(); |
1024 | } |
1025 | |
1026 | if (eqic(s, "submit-triple")) { |
1027 | S a = params.get("a"), b = params.get("b"), c = params.get("c"); |
1028 | if (empty(a) || empty(b) || empty(c)) ret "Empty field(s)"; |
1029 | ret htmlencode(postTripleFromInput(t3(a, b, c), null)); |
1030 | } |
1031 | |
1032 | if (swic_trim(s, "texts/", m)) { |
1033 | ret serveText((loading() ? "[LOADING]\n" : "\n") + lines(map quoteBorderless2(ai_texts(ai_parseSlashTriple(urldecode(m.rest())))))); |
1034 | } |
1035 | |
1036 | T3<S> texts_big_t = null; |
1037 | |
1038 | if (swic_trim(s, "texts-big/", m)) |
1039 | texts_big_t = ai_parseSlashTriple(urldecode(m.rest())); |
1040 | |
1041 | if (eqic(s, "texts-big")) { |
1042 | texts_big_t = t3( |
1043 | params.get("a"), params.get("b"), params.get("c")); |
1044 | } |
1045 | |
1046 | if (swic_trim(s, "rev/", m)) |
1047 | texts_big_t = triple("$X", "is", urldecode(m.rest())); |
1048 | |
1049 | if (texts_big_t != null) { |
1050 | final bool strip = eq("1", params.get('strip)); |
1051 | fS style = or2(params.get("style"), "font-size: 20px"); |
1052 | T3<S> t = texts_big_t; |
1053 | //L<S> texts = ai_texts(t = ai_parseSlashTriple(urldecode(m.rest()))); |
1054 | L<TripleRef<S>> refs = ai_tripleRefs(t); |
1055 | ret htitle_htmlencode(ai_renderTriple(t)) |
1056 | + (loading() ? "[LOADING]\n" : "\n") + |
1057 | //joinMap(texts, func(S s) -> S { pre(htmlencode_noQuote(s), +style, title := ) }); |
1058 | joinMap(refs, func(TripleRef<S> r) -> S { |
1059 | TripleWeb w = cast r.triple; |
1060 | S title = "Web " + w.globalID(); |
1061 | S source = w.source(); |
1062 | if (nempty(source)) title += ", source: " + source; |
1063 | S text = r!; |
1064 | if (strip) text = unquoteMultiline(text); |
1065 | ret pre(htmlencode_noQuote(text), +style, +title); |
1066 | }); |
1067 | } |
1068 | |
1069 | // Search Results |
1070 | |
1071 | S q = params.get("q"); |
1072 | if (nempty(q)) |
1073 | ret html_searchResults(q, params.get("mode")); |
1074 | |
1075 | if (eqic(s, "popular")) |
1076 | ret html_popular(params); |
1077 | |
1078 | // Default for unknown URL |
1079 | |
1080 | S topic = nempty(s) ? s : params.get("topic"); |
1081 | if (nempty(topic)) |
1082 | ret html_topic(urldecode(topic), false); |
1083 | |
1084 | // Home page |
1085 | |
1086 | ret html_home(); |
1087 | } finally { |
1088 | html_pretendAuthed.set(null); |
1089 | } |
1090 | } |
1091 | |
1092 | static NanoHTTPD.Response html_topic(S topic, bool random) { |
1093 | long time; |
1094 | bool timeout = false; |
1095 | print("User agent: " + serveHttp_userAgent()); |
1096 | if (http_isBot()) { |
1097 | time = -1; |
1098 | print("Bot request"); |
1099 | } else { |
1100 | time2 { |
1101 | timeout = ai_speculateDeepWithActiveAndTimeout(topic, speculationTimeoutForHttp); |
1102 | } |
1103 | time = lastTiming(); |
1104 | } |
1105 | L<S> words = ll(topic); |
1106 | //if (ai_getWeb(topic) != null) words.add("Web " + topic); |
1107 | ret serveHTMLNoCache( |
1108 | htitle(topic + " | Smart Bot") |
1109 | + h1(html_smallSmartBotLogo() + " " + htmlencode_noQuote("Topic: " + topic)) |
1110 | + loadjquery() |
1111 | + (random ? ahref("/random", "Another random term") + " | " : "") |
1112 | + "Search: " + html_searchField(topic) + "<br><br>" |
1113 | + ai_html_wordThoughts(words) |
1114 | + ai_html_enterTripleForm(first(words)) |
1115 | + p( |
1116 | (time < 0 ? "" : "Speculated for " + time + " ms" + (timeout ? " (TIMED OUT)" : "") + " ") + |
1117 | ahref(smartBot_directTopicLink(topic), "[Direct link]")) |
1118 | ); |
1119 | } |
1120 | |
1121 | sS html_home() { |
1122 | temp tempProfileBlock('html_home); |
1123 | ret tag('link, "", rel := "search", |
1124 | type := "application/opensearchdescription+xml", |
1125 | title := "Smart Bot", |
1126 | href := "http://tinybrain.de:8080/getraw.php?id=1013357") |
1127 | + hcenter3( |
1128 | hsnippetimg(#1101146, width := 64, height := 64) //#1011942) |
1129 | + h1_title("Smart Bot") |
1130 | + p("by " + ahref("http://BotCompany.de/", "BotCompany.de") |
1131 | + (webAuthed() ? " Authed." : "")) |
1132 | + ahref("/popular", "Most occurring") + " | " |
1133 | + ahref("/alphabetical", "Alphabetical") + " | " |
1134 | + ahref("/latest-webs", "Latest") + " | " |
1135 | + ahref("/random", "Random term") + " | " |
1136 | + html_searchField() + "<br><br>" |
1137 | + h3("Triple Search") |
1138 | + form( |
1139 | htextfield("a") + " -> " + htextfield("b") + " -> " + htextfield("c", "$X") |
1140 | + " " + hsubmit("Search triples"), |
1141 | action := "texts-big")); |
1142 | } |
1143 | |
1144 | sS html_popular(SS params) { |
1145 | time "Popularity search" { |
1146 | //L<S> keys = multiMapKeysByPopularity(ai_mainIndex()); |
1147 | L<S> keys = multiSetByPopularity(tripleIndex().wordIndex); |
1148 | } |
1149 | |
1150 | int step = 100, n = toInt(params.get("n")); |
1151 | int count = l(keys); |
1152 | L<S> l = subList(keys, n, n+step); |
1153 | |
1154 | ret hcenter3(hsnippetimg(#1011942)) |
1155 | + h1_title("Smart Bot's Encyclopedia (" + n_fancy(keys, "entry") + ")") |
1156 | + "Most occurring | " |
1157 | + ahref("/alphabetical", "Alphabetical") + " | " |
1158 | + ahref("/latest-webs", "Latest") + " | " |
1159 | + html_searchField() + "<br><br>" |
1160 | + pageNav2("/", count, n, step, 'n) |
1161 | + ul(map(func(S s) -> S { |
1162 | ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) |
1163 | + " [" + ai_approximateIndexedNodesCount(s) + "]" |
1164 | }, l)); |
1165 | } |
1166 | |
1167 | sS html_searchField() { ret html_searchField(""); } |
1168 | sS html_searchField(S q) { ret html_searchField(q, ""); } |
1169 | |
1170 | sS html_searchField(S q, S mode) { |
1171 | ret hform( |
1172 | htextinput("q", value := q, autofocus := 'autofocus) + |
1173 | " Mode: " + |
1174 | hselect_list(ll("starts with", "multiple words", "ends with", "contains"), mode, name := "mode") + |
1175 | " " + |
1176 | hsubmit("Search"), |
1177 | style := "display: inline", action := smartBotOfficialURL()); |
1178 | } |
1179 | |
1180 | static O html_profile(int seconds) { |
1181 | if (poorMansProfiling_isOn()) ret "Already on"; |
1182 | poorMansProfiling(100); |
1183 | sleepSeconds(seconds); |
1184 | ret serveText(poorMansProfiling_stopAndRenderResults()); |
1185 | } |
1186 | |
1187 | static S html_searchResults(S q, S mode) { |
1188 | int max = 1000; |
1189 | time2 { |
1190 | L<S> l; |
1191 | if (eqic(mode, "multiple words")) |
1192 | l = indexedTerms_scoredSearch(q, max+1); |
1193 | else if (eqic(mode, "ends with")) |
1194 | l = asList(termsEndingWith(q)); |
1195 | else if (eqic(mode, "contains")) |
1196 | l = asList(indexedTermsContaining(q)); |
1197 | else |
1198 | l = asList(fullIndexedTermsStartingWith(q)); |
1199 | if (possibleGlobalID(q) && !eq(first(l), q)) |
1200 | l.add(0, q); |
1201 | } |
1202 | long time = lastTiming(); |
1203 | bool more = l(l) > max; |
1204 | l = takeFirst(max, l); |
1205 | sortInPlaceAlternativeCI(l); |
1206 | |
1207 | S directHit = ""; |
1208 | S trimmed = trim(q); |
1209 | S direct = ai_findIndexedTerm(trimmed); |
1210 | if (direct != null) |
1211 | directHit = p(unicode_blackRightArrow() + " " + b(html_encyclopediaTopic(direct))); |
1212 | else |
1213 | directHit = p("No direct hit. Create entry: " + b(html_encyclopediaTopic(trimmed))); |
1214 | |
1215 | ret h1_title("Smart Bot Search: " + htmlencode(q) + " (" + n_fancy(l, "result") + (loading() ? ", LOADING" : "") + ")") |
1216 | + "Search again: " + html_searchField(q, mode) + "<br><br>" |
1217 | + directHit |
1218 | + p(l(l) > max ? max + "+ search results" : n(l, "search result") + " [" + time + " ms]") |
1219 | + ul(map html_encyclopediaTopic(l)); |
1220 | } |
1221 | |
1222 | static S html_alphabetical(SS params) { |
1223 | int step = 100, n = toInt(params.get("n")); |
1224 | Collection<S> all = indexedTerms(); |
1225 | int count = l(all); |
1226 | L<S> l = subListOfCollection(all, n, n+step); |
1227 | |
1228 | ret h1_title("Smart Bot's Encyclopedia (Alphabetical) :)") |
1229 | + ahref("/popular", "Most occurring") + " | " |
1230 | + "Alphabetical" + " | " |
1231 | + ahref("/latest-webs", "Latest") + " | " |
1232 | + html_searchField() + "<br><br>" |
1233 | + pageNav2("/alphabetical", count, n, step, 'n) |
1234 | + ul(map(func(S s) -> S { |
1235 | ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) |
1236 | }, l)); |
1237 | } |
1238 | |
1239 | sS html_classes() { |
1240 | L<S> l = sortedIC(ai_texts_verified("$X", "is", "a standard class")); |
1241 | |
1242 | ret h1_title("Smart Bot Classes") |
1243 | + ul(map(func(S s) -> S { |
1244 | ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) |
1245 | + " [" + ai_approximateIndexedNodesCount(s) + "]" |
1246 | }, l)); |
1247 | } |
1248 | |
1249 | sS html_standardRelations() { |
1250 | L<S> l = sortedIC(unquoteAll(ai_texts_verified("$X", "is", "a standard relation"))); |
1251 | |
1252 | ret h1_title("Smart Bot Standard Relations") |
1253 | + ul(map(func(S s) -> S { |
1254 | ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) |
1255 | + " [" + ai_approximateIndexedNodesCount(s) + "]" |
1256 | }, l)); |
1257 | } |
1258 | |
1259 | sS html_active() { |
1260 | L<S> l = sortedIC(unquoteAll(ai_texts_verified("$X", "is", "an active topic"))); |
1261 | L<S> lRules = sortedIC(unquoteAll(ai_texts_verified("$X", "is", "an active rule"))); |
1262 | |
1263 | ret h1_title("Smart Bot's Active Topics") |
1264 | + ul(map(func(S s) -> S { |
1265 | ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) |
1266 | + " [" + ai_approximateIndexedNodesCount(s) + "]" |
1267 | }, l)) |
1268 | + h2("Active Rules") |
1269 | + ul(map(func(S s) -> S { |
1270 | ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) |
1271 | + " [" + ai_approximateIndexedNodesCount(s) + "]" |
1272 | }, lRules)) |
1273 | ; |
1274 | } |
1275 | |
1276 | static S html_latestWebs(int n) { |
1277 | L<GlobalID> l = takeLast(n, cloneList(latestWebs)); |
1278 | S bn = formatWithThousands(ai_theBigNumber()); |
1279 | ret htitle("Latest Webs (" + bn + ") | Smart Bot") |
1280 | + h1(html_smallSmartBotLogo() + " - Latest Webs from " + bn) |
1281 | + ul(mapReversed(func(GlobalID id) -> S { |
1282 | TripleWeb w = ai_getTriple(id); |
1283 | if (w == null) ret "[not found] Web " + id; |
1284 | ret ai_html_linkedWeb(id) |
1285 | + htmlencode( |
1286 | " [" + renderGMTDate(w.created()) + "] " |
1287 | + w.source() + ": ") |
1288 | + ai_html_renderTriple(w); |
1289 | }, l)); |
1290 | } |
1291 | |
1292 | sS html_thoughts() { |
1293 | S html = /*hrefresh(5) +*/ hGoogleFontOswald() + loadjquery(); |
1294 | S status = ""; |
1295 | |
1296 | /*Pair<Int> p = evalWithTimeout_numberOfCalculations(); |
1297 | if (p.a > 0) status = p(n(p.a, "calculation") |
1298 | + (p.b == 0 ? "" : ", " + p.b + " timed out"));*/ |
1299 | |
1300 | Pair<Set<Thread>> p = evalWithTimeout_calculations(); |
1301 | if (nempty(p.a) || nempty(p.b)) |
1302 | status = ul( |
1303 | nempty(p.a) ? "In time calculations" + ul_htmlEncode(map threadName(p.a)) : null, |
1304 | nempty(p.b) ? "Timed out calculations" + ul_htmlEncode(map threadName(p.b)) : null |
1305 | ); |
1306 | |
1307 | ai_html_wordThoughts_nodesMax.set(100); |
1308 | try { |
1309 | ret html + wordThoughts() + status; |
1310 | } finally { |
1311 | ai_html_wordThoughts_nodesMax.set(null); |
1312 | } |
1313 | |
1314 | /* |
1315 | if (theoryModule == null) |
1316 | ret html + "Loading theory module..."; |
1317 | S thoughts = (S) call(theoryModule, 'html_thoughts); |
1318 | if (nempty(selectedWord)) |
1319 | ret html + tag('table, tr(td_top(thoughts, style := "background: #CCC") + td_top(wordThoughts(), style := "padding-left: 20px"))); |
1320 | ret html + thoughts; |
1321 | */ |
1322 | } |
1323 | |
1324 | sS wordThoughts() { |
1325 | try { |
1326 | if (empty(selectedWord)) ret ""; |
1327 | S html = ai_html_wordThoughts(selectedWord); |
1328 | html = html_addLinkToSpan(html, 'title, encyclopediaLink(selectedWord)); |
1329 | ret html_addTargetBlank(html); |
1330 | } catch e { |
1331 | printStackTrace(e); |
1332 | ret "Erreur"; |
1333 | } |
1334 | } |
1335 | |
1336 | sS postTripleFromInput(T3<S> triple, S input) { |
1337 | if (triple == null) null; |
1338 | if (swic(input, "OK, stored")) null; |
1339 | if (!ai_tripleAllowedToPost(triple)) null; |
1340 | |
1341 | new Matches m; |
1342 | if (!(swic(triple.a, "Web ", m) && possibleGlobalID(m.rest()))) selectWord(triple.a); |
1343 | |
1344 | if (ai_cache_hasTriple(triple)) |
1345 | ret "I know"; |
1346 | else { |
1347 | Web web = webFromTriple(triple); |
1348 | web.unverified = !authed(); |
1349 | postSoftwareMadeWeb(web, +input); |
1350 | |
1351 | if (eqic(triple.b, "is") && eqic(triple.c, "invalid")) |
1352 | ai_invalidateWeb(triple.a); |
1353 | if (eqic(triple.b, "is") && eqic(triple.c, "wrong")) |
1354 | ai_wrongWeb(triple.a); |
1355 | |
1356 | ai_postTriple("Web " + web.globalID, "stored because of", chatLineSymbol()); |
1357 | |
1358 | ret "OK, stored" + (web.unverified ? " (unverified)" : "") + ": " + ai_renderTriple(triple); |
1359 | } |
1360 | } |
1361 | |
1362 | sS postNodeFromInput(S node, S input) { |
1363 | if (!ai_nodeNameAllowedToPost(node)) null; |
1364 | if (hasIndexedNode(node)) |
1365 | ret "I know"; |
1366 | else { |
1367 | Web web = oneNodeWeb(node); |
1368 | web.unverified = !authed(); |
1369 | postSoftwareMadeWeb(web, +input); |
1370 | ret "OK, stored" + (web.unverified ? " (unverified)" : "") + ": " + node; |
1371 | } |
1372 | } |
1373 | |
1374 | // might want to get rid of this; do it in speculation |
1375 | svoid processSelectedWord { |
1376 | fS word = selectedWord; |
1377 | if (empty(word)) ret; |
1378 | ai_withMaker('processSelectedWord, r { |
1379 | //ai_speculate(word); |
1380 | pcall { |
1381 | ai_greetingRule1(word); |
1382 | //ai_greetingRule2(word); |
1383 | if (ai_hasTriple(word, "should be", "answered by me") |
1384 | && ai_postTriple(word, "was", "answered by me") != null) { |
1385 | S text = firstQuoted(web_texts(ai_search_dollarX(word, "is", "$X"))); |
1386 | postToStefansChat((nempty(text) ? text + " << " : "") + "Greetings back to you!"); |
1387 | } |
1388 | } |
1389 | }); |
1390 | } |
1391 | |
1392 | svoid makeChatLinesUnrecent { |
1393 | new Matches m; |
1394 | for (WebNode node : ai_search_dollarX("$X", "is", "recent")) |
1395 | if (web_match("Chat line *", node, m)) pcall { |
1396 | int n = parseInt($1); |
1397 | if (n <= stefansChat_n_value-100) { |
1398 | //print("Unrecenting " + n); |
1399 | ai_invalidateWeb(node.web); |
1400 | } |
1401 | } else if (web_match("Smart Bot's Chat line *", node, m)) pcall { |
1402 | int n = parseInt($1); |
1403 | if (n <= smartBotsChat_n_value-100) { |
1404 | //print("Unrecenting " + n); |
1405 | ai_invalidateWeb(node.web); |
1406 | } |
1407 | } |
1408 | } |
1409 | |
1410 | svoid onHistoryRead { |
1411 | lock dbLock(); |
1412 | print("History read."); |
1413 | processSelectedWord(); |
1414 | pcall { makeChatLinesUnrecent(); } |
1415 | } |
1416 | |
1417 | sS selectWord(S word) { |
1418 | if (nempty(word)) { |
1419 | selectedWord = word; |
1420 | save('selectedWord); |
1421 | processSelectedWord(); |
1422 | } |
1423 | ret word; |
1424 | } |
1425 | |
1426 | sS transpileMyself(S mode) { |
1427 | postToStefansChat("Transpiling..."); |
1428 | Pair<Bool, S> p = transpileOnServer(programID(), 'medium); |
1429 | ret p.a ? "OK" : "Not OK"; |
1430 | } |
1431 | |
1432 | svoid speculatorLoop { |
1433 | repeat with sleep 5 { |
1434 | ai_speculateDeepAndActive(selectedWord); |
1435 | for (L<S> words : cloneValues(lastUserLines)) |
1436 | for (S word : words) |
1437 | ai_speculateDeepAndActive(word); |
1438 | |
1439 | S s; |
1440 | while ((s = first_sync(speculationQueue)) != null) { |
1441 | speculationQueue.remove(s); |
1442 | long time = sysNow(); |
1443 | ai_speculateWithActive(s); |
1444 | done2_always(time, "Speculation Queue > " + s); |
1445 | } |
1446 | } |
1447 | } |
1448 | |
1449 | public static ISpec ispec = ai_defaultISpec(); |
1450 | |
1451 | // share ISpec interface with sub-modules |
1452 | static JavaXClassLoader hotwire_makeClassLoader(L<File> files) { |
1453 | ClassLoader cl = myClassLoader(); |
1454 | |
1455 | // Avoid class loader chaining, always reference base class loader |
1456 | if (cloned && cloningSince != 0) { |
1457 | ClassLoader parent = cast getOpt(cl, 'virtualParent); |
1458 | print("Cloned class loader. " + parent); |
1459 | if (parent != null) cl = parent; |
1460 | } |
1461 | |
1462 | ret new JavaXClassLoaderWithParent2(null, files, cl, parseClassesToShareList(classesToShare)); |
1463 | } |
1464 | |
1465 | static Lock aiLock() { |
1466 | ret aiLock; |
1467 | } |
1468 | |
1469 | static bool webAuthed() { |
1470 | ret isTrue(httpAuthed!); |
1471 | } |
1472 | |
1473 | svoid handleStefansChat { |
1474 | stefansChat_n_onChange(r { |
1475 | clearTransientWebs(); |
1476 | addTransientWeb(webFromTriple("Latest chat line", "is", "Chat line " + stefansChat_n_value)); |
1477 | }); |
1478 | |
1479 | stefansChat_onLine_lookback = 1; // 2 does double restarts etc. |
1480 | stefansChat_onLine_onHistoryRead.set(f onHistoryRead); |
1481 | stefansChat_onLine_safe(voidfunc(fS text) ctex { |
1482 | pcall { |
1483 | int nr = toInt(mapGet(stefansChat_onLine_fullParams!, "nr")); |
1484 | print("> [" + nr + "] " + text); |
1485 | if (nr != 0) { |
1486 | S x = "Chat line " + nr; |
1487 | stefansChat_onLine_fullParams->put('chatName, "Stefan's Chat"); |
1488 | stefansChat_onLine_fullParams->put("Chat line symbol", x); |
1489 | post(x, "is", "a chat line"); |
1490 | post(x, "is", "recent"); |
1491 | postChatLineInfo(x, text); |
1492 | stefansChat_n_notify(nr); |
1493 | ai_speculateWithActiveAndTimeout(x, speculationTimeoutForNewChatLine); |
1494 | if (!byBot()) |
1495 | lastUserLines.put("Stefan's Chat", ll(text, quote(text), x)); |
1496 | } |
1497 | } |
1498 | |
1499 | temp tempSetThreadLocal(answering, true); |
1500 | try { |
1501 | S a = actualAnswer(text); |
1502 | a = shortenAnswerForChatAndUploadFull(text, a); |
1503 | postToStefansChat(a); |
1504 | callAll(getAndClearThreadLocal(afterAnswering)); |
1505 | } on fail { |
1506 | clearThreadLocal(afterAnswering); |
1507 | } |
1508 | }); |
1509 | } |
1510 | |
1511 | svoid handleSmartBotsChat { |
1512 | smartBotsChat_onLine_lookback = 1; |
1513 | smartBotsChat_onLine_onHistoryRead.set(f onHistoryRead); |
1514 | smartBotsChat_onLine_safe(voidfunc(fS text) ctex { |
1515 | pcall { |
1516 | int nr = toInt(mapGet(stefansChat_onLine_fullParams!, "nr")); |
1517 | print("> [" + nr + "] " + text); |
1518 | if (nr != 0) { |
1519 | S x = "Smart Bot's Chat line " + nr; |
1520 | stefansChat_onLine_fullParams->put('chatName, "Smart Bot's Chat"); |
1521 | stefansChat_onLine_fullParams->put("Chat line symbol", x); |
1522 | post(x, "is", "a Smart Bot's chat line"); |
1523 | post(x, "is", "recent"); |
1524 | postChatLineInfo(x, text); |
1525 | smartBotsChat_n_notify(nr); |
1526 | ai_speculateWithActiveAndTimeout(x, speculationTimeoutForNewChatLine); |
1527 | if (!byBot()) |
1528 | lastUserLines.put("Smart Bot's Chat", ll(text, quote(text), x)); |
1529 | } |
1530 | } |
1531 | |
1532 | temp tempSetThreadLocal(answering, true); |
1533 | try { |
1534 | S a = actualAnswer(text); |
1535 | a = shortenAnswerForChatAndUploadFull(text, a); |
1536 | postToSmartBotsChat(a); |
1537 | callAll(getAndClearThreadLocal(afterAnswering)); |
1538 | } on fail { |
1539 | clearThreadLocal(afterAnswering); |
1540 | } |
1541 | }); |
1542 | } |
1543 | |
1544 | sS handleArchiveMsg(S msgSymbol) { |
1545 | S text = firstQuoted(ai_texts(msgSymbol, "is", "$X")); |
1546 | if (text == null) ret "No text found for " + msgSymbol; |
1547 | text = unquote(text); |
1548 | SS oldParams = setThreadLocal(stefansChat_onLine_fullParams, lithashmap("Chat line symbol", msgSymbol)); |
1549 | try { |
1550 | ret actualAnswer(text); |
1551 | } finally { |
1552 | stefansChat_onLine_fullParams.set(oldParams); |
1553 | } |
1554 | } |
1555 | |
1556 | sS shortenAnswerForChatAndUploadFull(S text, S a) { |
1557 | a = shorten(a, ultimateAnswerLimit); |
1558 | if (l(a) > stefansChat_messageLimit()) { |
1559 | S title = "Smart Bot's answer to: " + text; |
1560 | S id = ntUpload("smart-bot-for-user", title, unSlackSnippet(a)); |
1561 | a = snippetURL(id) + " | " + a; |
1562 | } |
1563 | ret a; |
1564 | } |
1565 | |
1566 | static bool ai_enabled() { |
1567 | true; |
1568 | } |
1569 | |
1570 | sbool http_isBot() { |
1571 | ret userAgentIsBot(serveHttp_userAgent()); |
1572 | } |
1573 | |
1574 | // UNUSED |
1575 | svoid softRestart_level1 { |
1576 | startedLoading(); |
1577 | cloningSince = sysNow(); |
1578 | classesToShare = "T3, TripleWeb, Symbol, GlobalID, MultiSet"; |
1579 | Class c = hotwire(programID()); |
1580 | set(c, ai_fillTripleIndex_useThese := asList(ai_allTriples())); |
1581 | |
1582 | softRestart_phase2(c); |
1583 | } |
1584 | |
1585 | svoid softRestart_phase2(final Class c) { |
1586 | print("Cloning phase 2"); |
1587 | set(c, cloned := true); |
1588 | set(c, clonedSince := cloningSince); |
1589 | set(c, postStartUpMessageToChat := chatName()); |
1590 | addAll((L) getOpt(c, 'latestWebs), latestWebs); |
1591 | |
1592 | removeFirstInjection(); |
1593 | |
1594 | afterAnswering(r { |
1595 | // Create raw thread without any registering/pinging etc. |
1596 | //new Thread("Soft-Restarting") { |
1597 | // public void run() ctex { |
1598 | //Thread.sleep(2000); |
1599 | |
1600 | print("Cloning, new thread"); |
1601 | // copy JavaX translator over |
1602 | copyFields(mc(), c, 'transpileRaw_trans); |
1603 | transpileRaw_trans = null; |
1604 | |
1605 | cleanUp(mc()); // This should end all the threads & the HTTP server |
1606 | System.out.println("Cloning: Cleaned up"); |
1607 | clearAllVariables(); |
1608 | System.out.println("Cloning: Running main"); |
1609 | runMain(c); |
1610 | System.out.println("Cloning: Done!"); |
1611 | // } |
1612 | //}.start(); |
1613 | }); |
1614 | } |
1615 | |
1616 | // also reuse the index |
1617 | svoid softRestart_level2 { |
1618 | startedLoading(); |
1619 | cloningSince = sysNow(); |
1620 | classesToShare = smartBot_sharedClassesForRestart(); |
1621 | Class c = hotwire(programID()); |
1622 | //set(c, ai_fillTripleIndex_useThese := asList(ai_allTriples())); |
1623 | set(c, ai_fillTripleIndex_useTripleIndex := tripleIndex()); |
1624 | |
1625 | softRestart_phase2(c); |
1626 | } |
1627 | |
1628 | svoid afterAnswering(O runnable) { |
1629 | if (isTrue(answering!)) |
1630 | afterAnswering.set(addToOrCreateList(afterAnswering!, runnable)); |
1631 | else |
1632 | callF(runnable); |
1633 | } |
1634 | |
1635 | svoid addToLatestWebs(Web web) { |
1636 | latestWebs.add(web.globalIDObj()); |
1637 | } |
1638 | |
1639 | svoid dynClear { |
1640 | veryQuickJava_refresh(); |
1641 | hotwireCached_clear(); |
1642 | clearAllCaches(); |
1643 | } |
1644 | |
1645 | svoid postChatLineInfo(S x, S text) { |
1646 | post(x, "has text", quote(text)); |
1647 | post(x, "was", byBot() ? "sent by bot" : "sent by human"); |
1648 | post(x, "was sent by IP", (S) lookupPossiblyIgnoreCase(stefansChat_onLine_fullParams!, "ip")); |
1649 | } |
1650 | |
1651 | static WebSocket makeWebSocket(NanoHTTPD.IHTTPSession handshake) { |
1652 | print("New WebSocket."); |
1653 | ret new WebSocket(handshake) { |
1654 | AutoCloseable streamer; |
1655 | |
1656 | @Override |
1657 | protected void onMessage(WebSocketFrame messageFrame) { |
1658 | S s = messageFrame.getTextPayload(); |
1659 | print("WebSocket msg: " + s); |
1660 | if (streamer == null && eq(s, "stream-big-number")) { |
1661 | streamer = timerAsAutocloseable(doEveryStartingNow(100, new Runnable { |
1662 | S lastS = null; |
1663 | public void run() ctex { |
1664 | S s = formatWithThousands(ai_theBigNumber()); |
1665 | if (neq(s, lastS)) { |
1666 | lastS = s; |
1667 | //print("Sending: " + s); |
1668 | send(s); |
1669 | } |
1670 | } |
1671 | })); |
1672 | println("Streaming!"); |
1673 | } |
1674 | } |
1675 | |
1676 | protected void onClose(WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) { |
1677 | print("WebSocket close"); |
1678 | _close(streamer); |
1679 | streamer = null; |
1680 | } |
1681 | }; |
1682 | }; |
1683 | |
1684 | sS diskSpaceInfo() { |
1685 | ret toM(fileSize(programFile("triples.gz"))) + " MB (triples.gz) + " + toM(fileSize(programFile("webs-made.txt"))) + " MB (webs-made.txt). " |
1686 | + toM(userDir().getUsableSpace()) + " MB free disk space"; |
1687 | } |
1688 | |
1689 | please include function ai_possibleRuleNames. |
Began life as a copy of #1009195
download show line numbers debug dex old transpilations
Travelled to 20 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, jmyaexzvplwz, jtubtzbbkimh, lpdgvwnxivlt, mjouhigkdmyk, mqqgnosmbjvj, onxytkatvevr, ppjhyzlbdabe, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, ydilcnlqtmvn
No comments. add comment
Snippet ID: | #1010745 |
Snippet name: | Smart Bot (LIVE) |
Eternal ID of this version: | #1010745/939 |
Text MD5: | cd0a6a4aaf387d0b2c5dd9090c9e2157 |
Transpilation MD5: | 73477117d0a453acc4c02eb07f33d8a4 |
Author: | stefan |
Category: | javax / chat |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2018-06-15 02:59:13 |
Source code size: | 51838 bytes / 1689 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 3262 / 1150815 |
Version history: | 938 change(s) |
Referenced in: | [show references] |