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

409
LINES

< > BotCompany Repo | #1021960 // Gazelle Web Server backup

JavaX source code (Dynamic Module) - run with: Stefan's OS

!7

cmodule GazelleWebServer > DynPrintLogAndEnabled {
  transient MyHTTPD server;
  new Set<S> authedCookies;
  transient new GazelleContextCache contextCache;
  
  transient new ThreadLocal<O[]> bodyParams;
  transient new ThreadLocal<Bool> authed;

  int absoluteMaxResults = 1000, defaultMaxResults = 100;

  void start() ctex {
    super.start();
    if (!enabled) ret;
    
    dm_useLocalMechListCopies();
    
    server = new MyHTTPD(80);
    server.serveFunction = func(S uri, SS parms) {
      serve(uri, parms)
    };
    server.start();
    print("HTTP server started on port " + server.getPort());
  }
  
  void cleanMeUp {
    server.stop();
    server = null;
  }
  
  O serve(S uri, SS params) enter {
    new Matches m;
    
    S cookie = serveHttp_cookieHandling();
    bool authed = nempty(cookie) && syncContains(authedCookies, cookie);
    temp tempSetTL(this.authed, authed);
    print("Cookie: " + cookie + ", authed: " + authed);
    S master = trim(loadTextFile(javaxSecretDir("gazelle-master-pw")));
    S attempt = params.get('_pass);
    if (nempty(attempt) && nempty(cookie) && nempty(master)) {
      if (eq(attempt, master)) {
        print("Login SUCCEEDED");
        syncAdd(authedCookies, cookie);
        change();
        authed = true;
      } else
        print("Login FAILED");
    }
    
    if (eq(uri, "/favicon.ico"))
      ret serveFile(loadLibrary(#1400189), faviconMimeType());
      
    O[] bodyParams = litobjectarray(style := "font-family: Roboto Mono; " + (authed ? "background-color: #FFFF88" : ""));
    temp tempSetTL(this.bodyParams, bodyParams);
    
    if (eq(uri, "/login"))
      ret hhtml_head_title_body("Login" + " | Gazelle",
        hprelude() +
          (nempty(master) ? hpostform(hpasswordfield('_pass)) : "No master PW"), bodyParams);
    
    if (swic(uri, "/texts/", m)) {
      S textID = m.rest();
      if (!possibleMD5(textID)) ret serve404();
      ret serveTextFileAsUTF8(javaxDataDir("Gazelle Texts/" + textID));
    }
    
    if (eq(uri, "/lastOutput")) {
      L<GazelleLine> lines = reversed(takeLast(10, dm_discord_allBotLines()));
      ret hframe("Last Output", hcenter(hheading("Last Output")
        + htmlTable2(
          map(lines, line -> {
            L applications = dm_gazelle_applicationsForMsgID(line.msgID);
            //print("Got " + n2(applications, "application") + " for " + line.msgID + " from " + dm_gazelle_longFeedbackCRUD());
            ret litorderedmap(
              "Date" := spanTitle("Message ID: " + line.msgID, htmlencode2(localDateWithMinutes(line.timestamp))),
              "Gazelle said:" := htmlencode2(line.text),
              "Applied rules" := joinWithSpace(map(f<S, S> ruleLink, collect ruleID(applications)))
            );
          }), htmlEncode := false, tableParams := litparams(cellpadding := 5))
      ));
    }
      
    if (eq(uri, "/lastInput")) {
      L<GazelleLine> lines = reversed(takeLast(30, dm_discord_allLines()));
      ret hframe("Last Input", hcenter(hheading("Last Input")
        + htmlTable2(
          map(lines, line -> {
            //L applications = dm_gazelle_applicationsForMsgID(line.msgID);
            ret litorderedmap(
              "Date" := spanTitle("Message ID: " + line.msgID, htmlencode2(localDateWithMinutes(line.timestamp))),
              "Author" := htmlencode(line.user),
              "Bot?" := htmlencode(line.bot ? "yes" : ""),
              "Line" := htmlencode2(line.text),
              //"Applied rules" := joinWithSpace(map(f<S, S> ruleLink, collect ruleID(applications))),
              "More" := moreForMsgID(line.msgID)
            );
          }), htmlEncode := false, tableParams := litparams(cellpadding := 5))
      ));
    }
    
    if (swic(uri, "/revisit/", m)) {
      long msgID = assertNotZero(parseLong(m.rest()));
      GazelleLine line = dm_discord_lineForMsgID(msgID);
      if (line == null) ret "Message not found: " + msgID;
      long startTime = sysNow();
      L<GazelleTree> tree = dm_gazelle_revisitChatLine(msgID,
        ctx := contextCache!);
      long endTime = sysNow();
      
      //print("Tree to string.");
      S tv = treeViewToString_withoutHijackPrint(gazelle_treeView(tree),
        stringifier := func(TreeView<GazelleTree> t) -> S { gazelleTreeToHTML(t.node()) });
      //print("children=" + l(tree) + ", tv = " + quote(tv));
      ret hframe("Revisiting msg " + msgID,
        hheading("Revisiting message " + msgID + ": " + htmlEncode2(line.text))
        + nlToBr_withIndents(tv)
        + p((endTime-startTime) + " ms"));
    }
    
    Request request = new(authed, params);
      
    if (swic(uri, "/rule/", m)) {
      S ruleID = assertGlobalID(m.rest());
      ret request.serveRule(ruleID, params);
    }
    
    if (eq(uri, "/search"))
      ret search(params);
    
    if (eq(uri, "/wikipedia"))
      ret request.serveWikipedia();
    
    if (eq(uri, "/commands"))
      ret hhtml_head_title_body("Commands | Gazelle",
        hprelude() +
        linesLL(hheading("Commands"),
          h3("!eval"),
        
          p([[You can evaluate Java code directly through Discord.
          Unless you are specifically authorized, only a ]] + ahref(rawSelfLink("safeIdentifiers"), "safe subset of identifiers") + " is allowed."),
          
          p("Example: " + tt("!eval 1+2")),
          p("In rare cases " + tt("!eval") + " may fail and you need to type " + tt("!real-eval") + " instead (which invokes an actual Java compiler).")), bodyParams);

    if (eq(uri, "/safeIdentifiers"))
      ret hhtml_head_title_body("Safe Java Identifiers | Gazelle",
        hprelude() +
        linesLL(
          hheading("Safe Java(X) identifiers for !eval"),
          hpre(lines(sortedIC(codeAnalysis_allSafeIdentifiers())))), bodyParams);
          
    if (!eq(uri, "/"))
      ret serve404();
    
    //final Map<S, Int> feedbackStats = dm_gazelle_feedbackStats();
    final Map<S, Int> feedbackStats2 = dm_gazelle_feedbackStatsByJudgement();
    final Map<S, Int> feedbackStats3 = dm_gazelle_feedbackStatsForNonJudged();
    
    // Home Page / Main List
    
    L<T3<S>> rules = dm_allRulesFromRulesModuleWithCommentsAndIDs();
      // dm_gazelle_allRulesWithComment("discord");
      
    bool showAll = eq("1", params.get('showAll));
      
    L<Map> mapped = mapReversed(rules,
      func(T3<S> t) -> SS {
        S ruleID = t.c;
        ret litorderedmap(
          "Rule ID" := !showAll ? null : htmlEncode2(ruleID),
          "Rule Text" := htmlEncode_nlToBr(t.a),
          "Comments" := !showAll ? null : nlToBr(
            mapEachLine(/*withoutLine("discord",*/ t.b/*)*/, func(S s) -> S {
              new Matches m;
              if "use helper table mech list *"
                ret "use helper table mech list " +
                  ahref(neatMechListURL($1), m.get(0));
              ret s;
            })),
          "# of applications" := strOr(feedbackStats3.get(ruleID), "-"),
          "Feedback" := ahref(rawSelfLink("rule/" + ruleID),
            "+" + toInt(feedbackStats2.get(ruleID + "/good"))
              /*+ " / " +
            toInt(feedbackStats3.get(ruleID))*/
              + " / " + 
            "-" + toInt(feedbackStats2.get(ruleID + "/bad"))));
      });
    
    S sortBy = params.get('sortBy);
    bool desc = eq("1", params.get('desc));
    if (nempty(sortBy))
      if (eq(sortBy, "Feedback"))
        mapped = sortByCalculatedField(mapped, func(Map map) -> Int {
          S s = cast map.get("Feedback");
          ret parseFirstInt(s) - parseSecondInt(s);
        });
      else if (eq(sortBy, "# of applications"))
        mapped = sortByMapKeyAlphaNum(mapped, sortBy);
      else
        mapped = sortByMapKey(mapped, sortBy);
    if (desc) reverseInPlace(mapped);
      
    ret hhtml_head_title_body("Gazelle - Next-Gen Chat Bot",
      hprelude() +
      hopeningTag link(rel :="icon", href := "/favicon.ico?v=2") +
      hcenter(
        p(b("GAZELLE 2019", style := "font-size: 5em")) +
        p(hsnippetimg(#1101500, height := 150, title := "Gazelle")) +
        p(span("<b>Hello! I am a next-generation chat bot in training.</b>", style := "font-size: 1.4em") + "<br>"
          + span(targetBlank("https://BotCompany.de", "Maker.") + " "
          + targetBlank("https://slides.com/stefanreich/how-about-thinking-machines/", "Slides.") + " "
          + targetBlank("https://discordapp.com/invite/SEAjPqk", b("Join my Discord server!")), style := "font-size: 1.2em"))
        + hform(p(ahref(rawSelfLink("commands"), "Commands.")
        + " " + ahref(rawSelfLink("lastOutput"), "Last output.")
        //+ " " + ahref(rawSelfLink("search"), "Search.")
        + " | " + hinputfield('q, style := "width: 120px") + " " + hsubmit("Search")), action := "/search")
        
        + h3("Rules (" + l(rules) + ")")
      + htmlTable2(mapped,
          htmlEncode := false,
          paramsByColName := litmap(
            "Feedback" := litobjectarray(align := 'center),
            "# of applications" := litobjectarray(align := 'center)),
          replaceHeaders := litmap(
            "Rule Text" := "Rule (input + more input => output)",
            "# of applications" := sortLink(params, "# of applications"),
            "Feedback" := sortLink(params, "Feedback")),
          tdParams := litobjectarray(valign := 'top)
          )
          + p(ahref(hqueryWithoutNanoHTTPDStuff(mapPlus(params, showAll := 1)), "Show technical stuff"))
          ), bodyParams);
  }
  
  S hframe(S title, O body) {
    print("Params: " + sfu(bodyParams!));
    ret hhtml_head_title_body(title + " | Gazelle",
      hprelude() +
      body,
      bodyParams!);
  }
  
  S ruleLink(S ruleID) {
    if (!isGlobalID(ruleID)) ret htmlEncode2(ruleID);
    ret ahref("/rule/" + ruleID, ruleID);
  }
  
  S gazelleTreeToHTML(GazelleTree tree) {
    if (tree == null) ret "*";
    ret (tree.isSplitNode ? "[split] " : "")
      + htmlEncode2(tree.line) + appendSquareBracketed(
      joinWithComma(listPlus(
        map htmlEncode2(tree.renderQualityElements()),
        ruleLink(tree.ruleID()))));
  }
  
  S moreForMsgID(long msgID) {
    ret ahref(rawSelfLink("revisit/" + msgID), "revisit", rel := "nofollow");
  }
  
  S search(SS params) {
    S q = trim(params.get('q));
    Set<S> types = singletonCISetIfNempty(params.get('type));
    int maxResults = min(absoluteMaxResults, toIntOr(params.get('max), defaultMaxResults));
    L results = empty(q) ? null : dm_gazelle_fullSearch(q, +types, maxResults := maxResults+1);
    S title = empty(q) ? "Search" : "Search results for: " + q;
    ret hframe(title,
      hheading(htmlEncode2(title)) +
      hform("Terms: " + hinputfield('q, value := q, autofocus := true)
        + " Type: " + hselect_list(ll("", "Rules", "Lines"), params.get('type), name := 'type)
        + " " + hsubmit("Search"), action := "/search") +
      (empty(results) ?
        (empty(q) ? "" : "No results") : p(
          l(results) > maxResults ? maxResults + "+ results" : n2(results, "result"))
          + htmlTable2(map(takeFirst_lazy(maxResults, results), o -> {
        S type = shortClassName(o);
        bool isLine = eq(type, "Line");
        long msgID = isLine ? getLong msgID(o) : 0;
        Map map = litorderedmap("Type" :=
          isLine ? spanTitle("Message ID: " + msgID, type) : type);
        S text = htmlEncode2OrNull(getStringOpt text(o));
        if (isLine)
 {
          map.put("Date" := localDateWithMinutes(getLong created(o)));
          map.put("By" := (S) call(o, 'userName));
        }
        if (text != null) {
          if (eq(type, "Rule"))
            text = ahref("/rule/" + getString globalID(o), text);
          mapPut(map, "Text", text);
        }
        if (isLine)
          map.put("More" := moreForMsgID(msgID));
        ret map;
      }), htmlEncode := false)));
    }

  class Request {
    bool authed;
    SS params;
    
    *(bool *authed, SS *params) {}
  
    S serveRule(S ruleID, SS params) {
      // add rule comment
      S comment = trim(params.get("comment"));
      if (nempty(comment)) {
        if (!authed) comment = "[anon] " + comment;
        dm_gazelle_addRuleComments_verbose(ruleID, ll(comment));
      }
  
      PairS textAndComment = unnull(dm_textAndCommentForRule(ruleID));
      L feedback = dm_gazelle_feedbackForRule(ruleID);
      L applications = dm_gazelle_applicationsForRule(ruleID);
      Map<S, O> feedbackByContext = indexByFieldNotNull context(feedback);
      S title = "Rule " + ruleID;
      bool showStruct = eq("1", params.get('struct));
      L list = cloneList(feedback);
      for (O o : applications)
        if (!containsKey(feedbackByContext, getString context(o)))
          list.add(o);
          
      // add feedback comments
      
      for (S applicationID, S text : subMapStartingWith_dropPrefix(params, "comment_")) {
        continue if empty(text = trim(text));
        if (!authed) text = "[anon] " + text;
        O app = findByField(list, globalID := applicationID);
        print("Processing comment for " + applicationID + " - " + app);
        if (app == null) continue;
        Set<S> comments = asSet(tlft(getString comments(app)));
        if (!contains(comments, text))
          call(app, '_setField, comments := appendWithNewLine(getString comments(app), text));
      }
      
      // Serve Rule & Applications & Feedback
      
      L<Map> mapped = map(list, func(O o) -> Map {
        litorderedmap(
          "Judgement" := getString judgement(o),
          "Rewritten Rule" := getString_htmlEncode modifiedRule(o),
          "Generated Output" := getString_htmlEncode outText(o),
          "Mapping" := dropPrefix("cimap", getString_htmlEncode varMap(o)),
          "Context" := getString_htmlEncode context(o),
          "Comments" := hform(
            appendIfNempty(nlToBr(rtrim(getString_htmlEncode comments(o))), "<br>")
            + htextfield("comment_" + getString globalID(o))),
          "Struct" := showStruct ? getString matchedRuleStruct(o) : null)
      });
      
      S sortBy = params.get('sortBy);
      if (nempty(sortBy))
        mapped = sortByMapKey(mapped, sortBy);
        
      Collection<S> statements = dm_gazelle_statementsForRule(ruleID);
  
      ret hhtml_head_title_body(title + " | Gazelle",
        hprelude() +
        hheading(htmlEncode2(title))
        + h3("Rule")
        + hblock(textAndComment.a)
        + (nempty(textAndComment.b) ? h3("Comments") + hblock(textAndComment.b) : "")
        + "<br><br>" + hform(
            "Add comment: " + htextfield("comment"))
        + h3("Feedback")
        + htmlTable2(mapped, tdParams := litobjectarray(align := 'center, valign := 'top), htmlEncode := false)
        + h3("Analysis 1")
        + hblock(lines(statements))
        + h3("Analysis 2")
        + hblock(sfuLines(objectToMap(
          ai_gazelle_analyzeStatementsForRule(statements))))
        , bodyParams!);
    }
    
    S serveWikipedia() {
      /*hheading("All Simple English Wikipedia Topics")
        + htmlTable2(map(simpleWikipediaTopics_cached(), topic -> litorderedmap("Topic" := topic))));*/
      ret hframe("Wikipedia",
        hheading("Retrieved Simple Wikipedia Pages")
        + htmlTable2(map(simpleWikipedia_allCachedTopics(), topic -> litorderedmap("Topic" := topic))));

    }
    
  } // end of Request

} // end of class

sS rawSelfLink(S uri) { ret addSlashPrefix(uri); }

sS hheading(O contents) {
  ret h2(ahref(rawSelfLink(""), "Gazelle") + " | " + contents);
}

sS hprelude() {
  ret [[<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">]] +
    hmobilefix();
}

sS hblock(S s) {
  ret htmlEncode_nlToBr(s);
}

sS sortLink(SS params, S key) {
  params = cloneMap(params);
  mapPutOrRemove(params, 'desc,
    eq(params.get('sortBy), key) && !eq("1", params.get('desc)) ? "1" : null);
  params.put(sortBy := key);
  ret ahref(hqueryWithoutNanoHTTPDStuff(params), htmlEncode2(key));
}

Author comment

Began life as a copy of #1021679

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, cfunsshuasjs, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1021960
Snippet name: Gazelle Web Server backup
Eternal ID of this version: #1021960/1
Text MD5: 3a22e640d7ec1bf2341e23b5eaf22333
Author: stefan
Category: javax / stefan's os / a.i. / web
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-03-04 10:40:41
Source code size: 16350 bytes / 409 lines
Pitched / IR pitched: No / No
Views / Downloads: 147 / 158
Referenced in: [show references]