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

450
LINES

< > BotCompany Repo | #1013927 // mech[anics].botcompany.de

JavaX module (desktop) [tags: butter use-pretranspiled] - homepage

Download Jar. Libraryless. Click here for Pure Java version (29897L/191K).

1  
!7
2  
3  
set flag OurSyncCollections.
4  
5  
!include #1015743 // concept AIList
6  
7  
static ConceptFieldIndexCI<AIList> nameIndex;
8  
static volatile long totalChars = -1;
9  
10  
concept Session {
11  
  S cookie;
12  
  S mech_filter;
13  
}
14  
15  
p {
16  
  dbSaveEvery(60);
17  
  dbIndexing(AIList, 'name);
18  
  nameIndex = indexConceptFieldCI(AIList, 'name);
19  
  thread { mech_guessLanguage(""); } // preload
20  
  calcOnConceptChanges(10000, r calcTotalSize, true);
21  
  addConceptIndex(new IConceptIndex {
22  
    public void update(Concept c) {
23  
      pcall { if (c cast AIList) sendToUpdatesBot('mechListChange, c.name); }
24  
    }
25  
    public void remove(Concept c) {
26  
      pcall { if (c cast AIList) sendToUpdatesBot('removeMechList, c.name); }
27  
    }
28  
  });
29  
  updateListNamesList();
30  
}
31  
32  
set flag NoNanoHTTPD. html {
33  
  temp countDispatch('html);
34  
  O response;
35  
  new Matches m;
36  
  
37  
  S cookie = cookieFromUser();
38  
  S filter = params.get('mech_filter);
39  
  print("cookie=" + cookie + ", filter=" + filter + ", dialogID=" + getDialogID());
40  
  Session session = empty(cookie) ? null : uniq(Session, +cookie);
41  
  if (session != null && filter != null) {
42  
    cset(session, mech_filter := filter);
43  
    ret hrefresh(rawSelfLink());
44  
  }
45  
46  
  bool authed = webAuthed(params);
47  
  
48  
  if (eq(uri, "/list-count")) ret serveText(countConcepts(AIList));
49  
  if ((response = serveListText(uri, params, authed)) != null) ret response;
50  
  
51  
  // Append API
52  
  if (swic(uri, "/bot-list-append/", m)) {
53  
    params.put(name := urldecode(m.rest());
54  
    uri = "/bot-list-append";
55  
  }
56  
57  
  if (eq(uri, "/bot-list-append")) {
58  
    S mode = params.get('mode);
59  
    lock dbLock();
60  
    S name = params.get("name"), text = params.get("text");
61  
    if (!authed)
62  
      name = "Unauthorized Appends | " + name;
63  
    AIList l = getList(name);
64  
    //if (!authed) cset(l, status := "PUBLIC READ");
65  
    
66  
    if (eq(mode, "uniqCI")) {
67  
      text = lines(listMinusSet(tlft(text), asCISet(tlft(l.text))));
68  
      if (empty(text)) ret "No change";
69  
    }
70  
        
71  
    if (eq(mode, "uniq")) {
72  
      text = lines(listMinusSet(tlft(text), tlft(l.text)));
73  
      if (empty(text)) ret "No change";
74  
    }
75  
    
76  
    listAppendWithLog(l, text);
77  
    ret "Changed";
78  
  }
79  
80  
  if (!authed && eq(uri, "/list-names"))
81  
    ret serveText(jsonEncode(sortedIC(collect(publicReadLists(), 'name))));
82  
    
83  
  if (!authed && eq(uri, "/list-md5s"))
84  
    ret serveText(jsonEncode(map(publicReadLists(), func(AIList l) -> LS { ll(l.name, md5OfList(l)) })));
85  
    
86  
  if (!authed && eq(uri, "/list-md5s-and-statuses"))
87  
    ret serveText(jsonEncode(map(publicReadLists(), func(AIList l) -> LS { ll(l.name, md5OfList(l), l.status, str(lineCountOfList(l))) })));
88  
    
89  
  if (eq(uri, "/authed")) ret yesno(authed);
90  
  
91  
  // Show list (unauthed)
92  
  if (!authed && startsWith(uri, "/list/", m)) {
93  
    AIList l = getList_noCreate(urldecode(m.get(0)));
94  
    if (l == null || !l.isPublicRead()) ret serve404("List not found");
95  
    ret htitle_h2(htmlencode(l.name)) + hpre_htmlencode(l.text);
96  
  }
97  
  
98  
  bool alphabetical = eq(uri, "/alphabetical");
99  
  if (!authed && (eq(uri, "/") || alphabetical)) {
100  
    L<AIList> list = alphabetical
101  
    ? sortedByFieldIC('name, publicReadLists())
102  
    : sortedByFieldDesc('modified, publicReadLists());
103  
104  
    ret h3_title("Bot Data")
105  
    + hBoolSelector(alphabetical, "/", "By date", "/alphabetical", "Alphabetical")
106  
    + listLists(list);
107  
  }
108  
  
109  
  // Search results
110  
  S q = params.get('q);
111  
  if (nempty(q)) {
112  
    L<AIList> found = scoredSearch_AIList(q, listsForAuth(authed));
113  
    
114  
    if (eq(uri, "/json-search"))
115  
      ret serveText(jsonEncode(collect name(found)));
116  
      
117  
    ret hmobilefix()
118  
      + htitle_h3("mech.botcompany.de: Search results for " + htmlencode(singleQuote(q)))
119  
      + listLists(found);
120  
  }
121  
122  
  if (!authed) ret redirectToWebAuth();
123  
  
124  
  // AUTHED FROM HERE ON
125  
  
126  
  try object html_serveDispatches(uri);
127  
128  
  if (swic(uri, "/list-id/", m)) {
129  
    AIList l = getList_noCreate(urldecode(m.rest()));
130  
    ret l == null ? "List not found" : str(l.id);
131  
  }
132  
133  
  if (eq(uri, "/fix-unauth")) {
134  
    for (AIList l) if (swic(l.name, "Unauthorized Appends |"))
135  
      cset(l, status := "");
136  
    ret "OK";
137  
  }
138  
  
139  
  // API
140  
  if (eq(uri, "/download"))
141  
    ret subBot_serveFileWithName("mechlists-" + ymd_minus_hms() + ".gz", conceptsFile()); // TODO: concurrent writes?
142  
  
143  
  if (eq(uri, "/list-names"))
144  
    ret serveText(jsonEncode(sortedIC(collect(list(AIList), 'name))));
145  
146  
  if (eq(uri, "/list-md5s"))
147  
    ret serveText(jsonEncode(map(list(AIList), func(AIList l) -> LS { ll(l.name, md5OfList(l)) })));
148  
    
149  
  if (eq(uri, "/list-md5s-and-statuses"))
150  
    ret serveText(jsonEncode(map(list(AIList), func(AIList l) -> LS { ll(l.name, md5OfList(l), l.status, str(lineCountOfList(l))) })));
151  
    
152  
  if (eq(uri, "/bot-edited-lists"))
153  
    ret serveText(jsonEncode(sortedIC(collect(conceptsWhere(AIList, botFlag := true), 'name))));
154  
155  
  // Create API
156  
  if (eq(uri, "/bot-list-create")) {
157  
    lock dbLock();
158  
    S name = params.get("name");
159  
    getList(name);
160  
    ret "OK";
161  
  }
162  
163  
  // Edit API
164  
  if (eq(uri, "/bot-list-edit")) {
165  
    lock dbLock();
166  
    S name = params.get("name"), text = params.get("text");
167  
    AIList l = getList(name);
168  
    if (eq(l.text, text)) ret "No change";
169  
    listReplaceWithLog(l, text);
170  
    ret "Changed";
171  
  }
172  
173  
  // Show list (authed)
174  
  if (startsWith(uri, "/list/", m)) {
175  
    S name = urldecode(m.get(0));
176  
    AIList l = eq("1", params.get("create")) ? getList(name) : getList_noCreate(name);
177  
    if (l == null)
178  
      ret "List not found"
179  
        + (!authed ? "" : hpostform(hhidden(create := 1) + hsubmit("Create")));
180  
    
181  
    bool delete = eq(params.get("delete"), "1");
182  
    
183  
    // Rename list
184  
    S renameTo = params.get('renameTo);
185  
    if (nempty(renameTo) && !delete) {
186  
      if (neqic(l.name, renameTo) && getList_noCreate(renameTo) != null)
187  
        ret "Can't rename - list " + quote(renameTo) + " already exists";
188  
      S oldName = l.name;
189  
      cset(l, name := renameTo);
190  
      updateListNamesList();
191  
      ret nav() + "List " + quote(oldName) + " renamed to " + quote(renameTo);
192  
    }
193  
    
194  
    if (delete) {
195  
      logStructure("versions.log", litmap(id := l.id, status := "delete me", date := now()));
196  
      deleteConcept(l);
197  
      updateListNamesList();
198  
      ret nav() + "List deleted";
199  
    }
200  
201  
    // Update text
202  
    S text = params.get("human");
203  
    S status = params.get("status");
204  
    if (text != null) {
205  
      lock dbLock();
206  
      //printStruct(ll(+text, +status));
207  
      if (neqAny(text, l.text, status, unnull(l.status))) {
208  
        logStructure("versions.log", litmap(id := l.id, +text, +status, date := now()));
209  
        if (status != null) cset(l, +status);
210  
        cset(l, +text, textMD5 := md5(text), lines := -1, botFlag := false, modified := now());
211  
        listTextChanged(l);
212  
        //printStruct("l.text=" + sfu(text));
213  
      }
214  
      ret hrefresh(0, rawLink(uri) + "?random=" + randomID());
215  
    }
216  
    
217  
    S textArea = htextarea(l.text, name := 'human, cols := 80, rows := 30);
218  
    
219  
    L<S> tok = javaTok(l.status);
220  
    jreplace(tok, "bb", "iframe 1018300");
221  
    int idx = jfind(tok, "iframe <int>");
222  
    if (idx > 0) {
223  
      S analyzer = tok.get(idx+2);
224  
      S subUri = joinSubList(tok, idx+4, smartIndexOf(tok, idx, ",")-1);
225  
      textArea = htableRaw2_singleRow(ll(textArea, iframe(relativeRawBotLink(analyzer, subUri + "?list=" + urlencode(l.name)), width := "500", height := "500")),
226  
        null, null, ll(valign := 'top));
227  
    }
228  
    
229  
    // Serve list text (editable)
230  
    
231  
    ret nav() + htitle(l.name)
232  
      + h2(ahref(neatMechListURL(l.name), htmlencode2(l.name)) + " [" + nLines(countLines(l.text)) + "]")
233  
      + hpostform(
234  
        "Status: " + htextinput('status, value := l.status)
235  
      + h3("Contents (" + (l.botFlag ? "bot" : "human") + "-edited)")
236  
      + p(hsubmit("Save"))
237  
      + textArea
238  
      + p(hsubmit("Save"))
239  
      )
240  
      + hpostform(
241  
        "New name: " + htextinput('renameTo, value := l.name)
242  
        + " "
243  
        + hsubmit("Rename list") + " or " + hbutton("Delete list", name := "delete", type := "submit", value := 1, onClick := "return confirm('Really delete?')")
244  
      );
245  
  }
246  
  
247  
  // New list
248  
  S newList = trim(params.get('newList));
249  
  if (nempty(newList)) {
250  
    AIList l = getList(newList);
251  
    ret hrefresh(rawLink("/list/" + urlencode(l.name)));
252  
  }
253  
  
254  
  // Overview
255  
  
256  
  L<AIList> list = alphabetical
257  
    ? sortedByFieldIC('name, list(AIList))
258  
    : sortedByFieldDesc('modified, list(AIList));
259  
    
260  
  fS prefix = session == null ? null : session.mech_filter;
261  
  if (nempty(prefix))
262  
    list = [AIList l : list | swic(l.name, prefix)];
263  
264  
  ret hmobilefix()
265  
    + hcomment("cookie=" + cookie)
266  
    + htitle_h3("mech.botcompany.de [" + n2(l(list), "list")
267  
      + (totalChars >= 0 ? ", " + toK(totalChars) + "K chars" : "")
268  
    + "]")
269  
    + htableRaw_singleRow(ll(
270  
      hform("Search: " + htextinput('q, style := "width: 200px") + " " + hsubmit("Search")),
271  
      hpostform("| New list: " + htextinput('newList, style := "background-color: yellow") + " " + hsubmit("Create list"))))
272  
    + hBoolSelector(alphabetical, "/", "By date", "/alphabetical", "Alphabetical")
273  
    + listLists(list)
274  
    + hpostform("Only show lists starting with: "
275  
      + htextinput('mech_filter, value := prefix)
276  
      + " " + hsubmit("OK"));
277  
}
278  
279  
sS nav() {
280  
  ret hmobilefix() + p(ahref(rawLink(), "&lt;&lt; back"));
281  
}
282  
283  
static AIList getList_noCreate(S name) {
284  
  ret getList(name, false);
285  
}
286  
287  
static AIList getList(S name) {
288  
  ret getList(name, true);
289  
}
290  
291  
static AIList getList(S name, bool create) {
292  
  lock dbLock();
293  
  AIList l = findConcept(AIList, +name);
294  
  if (l == null) l = nameIndex.get(name);
295  
  if (l == null) if (!create) null; else {
296  
    l = cnew(AIList, +name);
297  
    logStructure("versions.log", litmap(id := l.id, +name, date := now(), mode := "List created"));
298  
    updateListNamesList();
299  
  }
300  
  if (l.modified == 0) cset(l, modified := now());
301  
  ret l;
302  
}
303  
304  
sS listLists(L<AIList> list) {
305  
  ret ul(map(list, func(AIList l) -> S {
306  
    int n = lineCountOfList(l);
307  
    new L<S> status;
308  
    bool german = eq('german, mech_guessLanguage_quick(l.name));
309  
    //if (l.mighty) status.add(german ? "GENUTZT" : "USED");
310  
    addIfNempty(status, htmlencode(l.status));
311  
    if (n != 0) status.add(n2(n, german ? "Zeile" : "line", german ? "Zeilen": "lines"));
312  
    ret ahref(rawLink("/list/" + urlencode(l.name)),
313  
        htmlencode(or2(l.name, "[no name]")) + appendBracketed(joinWithComma(status));
314  
  }));
315  
}
316  
317  
static L<AIList> scoredSearch_AIList(S query, Iterable<AIList> data) {
318  
  new Map<AIList, Int> scores;
319  
  L<S> prepared = scoredSearch_prepare(query);
320  
  for (AIList l : data)
321  
    putUnlessZero(scores, l,
322  
        3*scoredSearch_score(l.name, prepared)
323  
      + 2*scoredSearch_score(l.status, prepared)
324  
      +   scoredSearch_score(l.text, prepared));
325  
  ret keysSortedByValuesDesc(scores);
326  
}
327  
328  
svoid calcTotalSize {
329  
  long total = 0;
330  
  for (AIList l)
331  
    total += l(l.text);
332  
  totalChars = total;
333  
}
334  
335  
sS export_getListText(S listName) {
336  
  AIList l = getList_noCreate(listName);
337  
  ret l == null ? "" : l.text;
338  
}
339  
340  
sS export_setListText(S listName, S text) {
341  
  AIList l = getList(listName);
342  
  if (eq(l.text, text)) ret "No change";
343  
  logStructure("versions.log", litmap(id := l.id, +text, date := now(), mode := "bot edit"));
344  
  cset(l, +text, textMD5 := md5(text), lines := -1, botFlag := true, modified := now());
345  
  listTextChanged(l);
346  
  ret "Changed";
347  
}
348  
349  
sO serveListText(S uri, SS params, bool authed) {
350  
  new Matches m;
351  
  if (startsWith(uri, "/list-text/", m)) {
352  
    bool opt = eq("1", params.get("opt"));
353  
    bool withStatus = eq("1", params.get("withStatus"));
354  
    bool create = authed && eq("1", params.get("create"));
355  
    S md5 = params.get("md5");
356  
    int md5Len = parseIntOpt(params.get('l));
357  
    S name = urldecode(m.get(0));
358  
    lock dbLock();
359  
    AIList l = create ? getList(name) : getList_noCreate(name);
360  
    if (!authed && l != null && !l.isPublicRead())
361  
      l = null;
362  
      //ret subBot_serve404("Not logged in");
363  
    cset(l, mighty := true);
364  
    if (l == null)
365  
      if (opt)
366  
        ret serveText(jsonEncode(litmap("Text" := "")));
367  
      else
368  
        ret serveText(jsonEncode(litmap("Error", ll("List not found", name))));
369  
    else {
370  
      Map map = litmap("Name" := l.name, "Status" := withStatus ? l.status : null);
371  
      if (md5 != null) {
372  
        S actualMD5 = md5OfList(l);
373  
        print("md5: " + md5 + " / " + actualMD5);
374  
        if (eq(actualMD5, md5))
375  
          ret serveText(jsonEncode(mapPlus(map, "Same" := true)));
376  
        else if (md5Len != 0 && eq(md5(takeFirst(l.text, md5Len)), md5))
377  
          ret serveText(jsonEncode(mapPlus(map, "Appended" := true, "Text" := substring(l.text, md5Len))));
378  
      }
379  
      ret serveText(jsonEncode(mapPlus(map, "Text" := l.text)));
380  
    }
381  
  }
382  
  null;
383  
}
384  
385  
sS md5OfList(AIList l) {
386  
  lock dbLock();
387  
  if (l.textMD5 == null) l.textMD5 = md5(l.text);
388  
  ret l.textMD5;
389  
}
390  
391  
static int lineCountOfList(AIList l) {
392  
  lock dbLock();
393  
  if (l.lines < 0) l.lines = countLines(l.text);
394  
  ret l.lines;
395  
}
396  
397  
static L<AIList> publicReadLists() {
398  
  ret [AIList l : list(AIList) | l.isPublicRead()];
399  
}
400  
401  
svoid updateListNamesList {
402  
  lock dbLock();
403  
  AIList l = getList("All public-read mech lists");
404  
  TreeSet<S> actual = new TreeSet(collect(publicReadLists(), 'name));
405  
  Set<S> listed = asHashSet(lines(l.text));
406  
  if (nempty(setMinusSet(listed, actual)))
407  
    listReplaceWithLog(l, lines(actual));
408  
  else
409  
    listAppendWithLog(l, lines(setMinusSet(actual, listed)));
410  
}
411  
412  
svoid listAppendWithLog(AIList l, S text) {
413  
  if (emptyAfterTrim(text)) ret;
414  
  logStructure("versions.log", litmap(id := l.id, +text, date := now(), mode := "bot append"));
415  
  cset(l, text := appendNewLineIfNempty(rtrim(l.text)) + text, botFlag := true, modified := now(), textMD5 := null, lines := -1);
416  
  listTextChanged(l);
417  
}
418  
419  
svoid listReplaceWithLog(AIList l, S text) {
420  
  if (eq(text, l.text)) ret;
421  
  logStructure("versions.log", litmap(id := l.id, +text, date := now(), mode := "bot edit"));
422  
  cset(l, +text, textMD5 := md5(text), lines := -1, botFlag := true, modified := now());
423  
  listTextChanged(l);
424  
}
425  
426  
static new ThreadLocal<Bool> listTextChanged_noRecurse;
427  
428  
svoid listTextChanged(AIList l) {
429  
  if (!isTrue(listTextChanged_noRecurse!) && cic(l.status, "auto global ids")) pcall {
430  
    L<S> entries = splitAtEmptyLines(l.text);
431  
    S text = joinWithEmptyLines(map nlLogic_addGlobalID(entries));
432  
    temp tempSetThreadLocal(listTextChanged_noRecurse, true);
433  
    listReplaceWithLog(l, text);
434  
  }
435  
  
436  
  if (!isTrue(listTextChanged_noRecurse!) && cic(l.status, "gazelle ids")) pcall {
437  
    L<S> entries = splitAtEmptyLines(l.text);
438  
    S text = joinWithEmptyLines(map gazelle_addGlobalID(entries));
439  
    temp tempSetThreadLocal(listTextChanged_noRecurse, true);
440  
    listReplaceWithLog(l, text);
441  
  }
442  
}
443  
444  
sS mechList_opt_raw_fresh(S name) {
445  
  ret export_getListText(name);
446  
}
447  
448  
static L<AIList> listsForAuth(bool authed) {
449  
  ret authed ? list(AIList) : publicReadLists();
450  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 17 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, xfbsdwenvhih, xrpafgyirdlv

No comments. add comment

Snippet ID: #1013927
Snippet name: mech[anics].botcompany.de
Eternal ID of this version: #1013927/199
Text MD5: bd2cb8ceb7b253536d0f6cfa85e59605
Transpilation MD5: 99c1928160ca703f2fafe3733d4451d9
Author: stefan
Category: javax / a.i. / web
Type: JavaX module (desktop)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-03-30 18:43:09
Source code size: 15249 bytes / 450 lines
Pitched / IR pitched: No / No
Views / Downloads: 1215 / 6930
Version history: 198 change(s)
Referenced in: [show references]