Uses 911K of libraries. Click here for Pure Java version (13346L/80K).
1 | !7 |
2 | |
3 | cmodule GazelleWebServer > DynPrintLogAndEnabled { |
4 | transient MyHTTPD server; |
5 | new Set<S> authedCookies; |
6 | |
7 | void start() ctex { |
8 | super.start(); |
9 | if (!enabled) ret; |
10 | |
11 | dm_useLocalMechListCopies(); |
12 | |
13 | server = new MyHTTPD(80); |
14 | server.serveFunction = func(S uri, SS parms) { |
15 | serve(uri, parms) |
16 | }; |
17 | server.start(); |
18 | print("HTTP server started on port " + server.getPort()); |
19 | } |
20 | |
21 | void cleanMeUp { |
22 | server.stop(); |
23 | server = null; |
24 | } |
25 | |
26 | O serve(S uri, SS params) { |
27 | new Matches m; |
28 | |
29 | S cookie = serveHttp_cookieHandling(); |
30 | bool authed = nempty(cookie) && syncContains(authedCookies, cookie); |
31 | print("Cookie: " + cookie + ", authed: " + authed); |
32 | S master = trim(loadTextFile(javaxSecretDir("gazelle-master-pw"))); |
33 | S attempt = params.get('_pass); |
34 | if (nempty(attempt) && nempty(cookie) && nempty(master)) { |
35 | if (eq(attempt, master)) { |
36 | print("Login SUCCEEDED"); |
37 | syncAdd(authedCookies, cookie); |
38 | change(); |
39 | authed = true; |
40 | } else |
41 | print("Login FAILED"); |
42 | } |
43 | |
44 | if (eq(uri, "/favicon.ico")) |
45 | ret serveFile(loadLibrary(#1400189), faviconMimeType()); |
46 | |
47 | if (eq(uri, "/login")) |
48 | ret nempty(master) ? hpostform(hpasswordfield('_pass)) : "No master PW"; |
49 | |
50 | O[] bodyParams = litobjectarray(style := "font-family: Roboto Mono; " + (authed ? "background-color: #FFFF88" : "")); |
51 | |
52 | if (swic(uri, "/texts/", m)) { |
53 | S textID = m.rest(); |
54 | if (!possibleMD5(textID)) ret serve404(); |
55 | ret serveTextFileAsUTF8(javaxDataDir("Gazelle Texts/" + textID)); |
56 | } |
57 | |
58 | if (swic(uri, "/rule/", m)) { |
59 | S ruleID = assertGlobalID(m.rest()); |
60 | PairS textAndComment = unnull(dm_textAndCommentForRule(ruleID)); |
61 | L feedback = dm_gazelle_feedbackForRule(ruleID); |
62 | L applications = dm_gazelle_applicationsForRule(ruleID); |
63 | Map<S, O> feedbackByContext = indexByFieldNotNull context(feedback); |
64 | S title = "Rule " + ruleID; |
65 | bool showStruct = eq("1", params.get('struct)); |
66 | L list = cloneList(feedback); |
67 | for (O o : applications) |
68 | if (!containsKey(feedbackByContext, getString context(o))) |
69 | list.add(o); |
70 | |
71 | // add comments |
72 | |
73 | for (S applicationID, S text : subMapStartingWith_dropPrefix(params, "comment_")) { |
74 | continue if empty(text = trim(text)); |
75 | if (!authed) text = "[anon] " + text; |
76 | O app = findByField(list, globalID := applicationID); |
77 | print("Processing comment for " + applicationID + " - " + app); |
78 | if (app == null) continue; |
79 | Set<S> comments = asSet(tlft(getString comments(app))); |
80 | if (!contains(comments, text)) |
81 | call(app, '_setField, comments := appendWithNewLine(getString comments(app), text)); |
82 | } |
83 | |
84 | // Serve Rule & Applications & Feedback |
85 | |
86 | ret hhtml_head_title_body(title + " | Gazelle", |
87 | hprelude() + |
88 | heading(htmlEncode2(title)) |
89 | + h3("Rule") |
90 | + hblock(textAndComment.a) |
91 | + (nempty(textAndComment.b) ? h3("Comments") + hblock(textAndComment.b) : "") |
92 | + h3("Feedback") |
93 | + htmlTable2(map(list, func(O o) -> Map { |
94 | litorderedmap( |
95 | "Judgement" := getString judgement(o), |
96 | "Rewritten Rule" := getString_htmlEncode modifiedRule(o), |
97 | "Generated Output" := getString_htmlEncode outText(o), |
98 | "Mapping" := dropPrefix("cimap", getString_htmlEncode varMap(o)), |
99 | "Context" := getString_htmlEncode context(o), |
100 | "Comments" := hform( |
101 | appendIfNempty(nlToBr(rtrim(getString_htmlEncode comments(o))), "<br>") |
102 | + htextfield("comment_" + getString globalID(o))), |
103 | "Struct" := showStruct ? getString matchedRuleStruct(o) : null) |
104 | }), tdParams := litobjectarray(align := 'center, valign := 'top), htmlEncode := false), bodyParams); |
105 | } |
106 | |
107 | if (eq(uri, "/commands")) |
108 | ret hhtml_head_title_body("Commands | Gazelle", |
109 | hprelude() + |
110 | linesLL(heading("Commands"), |
111 | h3("!eval"), |
112 | |
113 | p([[You can evaluate Java code directly through Discord. |
114 | Unless you are specifically authorized, only a ]] + ahref(rawSelfLink("safeIdentifiers"), "safe subset |
115 | of identifiers") + " is allowed."), |
116 | |
117 | p("Example: " + tt("!eval 1+2")), |
118 | p("In rare cases " + tt("!eval") + " may fail and you need to type " + tt("!real-eval") + " instead (which invokes an actual Java compiler).")), bodyParams); |
119 | |
120 | if (eq(uri, "/safeIdentifiers")) |
121 | ret hhtml_head_title_body("Safe Java Identifiers | Gazelle", |
122 | hprelude() + |
123 | linesLL( |
124 | heading("Safe Java(X) identifiers for !eval"), |
125 | hpre(lines(sortedIC(codeAnalysis_allSafeIdentifiers())))), bodyParams); |
126 | |
127 | if (!eq(uri, "/")) |
128 | ret serve404(); |
129 | |
130 | //final Map<S, Int> feedbackStats = dm_gazelle_feedbackStats(); |
131 | final Map<S, Int> feedbackStats2 = dm_gazelle_feedbackStatsByJudgement(); |
132 | final Map<S, Int> feedbackStats3 = dm_gazelle_feedbackStatsForNonJudged(); |
133 | |
134 | // Home Page |
135 | |
136 | L<T3<S>> rules = dm_allRulesFromRulesModuleWithCommentsAndIDs(); |
137 | // dm_gazelle_allRulesWithComment("discord"); |
138 | |
139 | ret hhtml_head_title_body("Gazelle - Next-Gen Chat Bot", |
140 | hprelude() + |
141 | hopeningTag link(rel :="icon", href := "/favicon.ico?v=2") + |
142 | hcenter( |
143 | p(b("GAZELLE 2019", style := "font-size: 5em")) + |
144 | p(hsnippetimg(#1101500, height := 150, title := "Gazelle")) + |
145 | p(span("<b>Hello! I am a next-generation chat bot in training.</b>", style := "font-size: 1.4em") + "<br>" |
146 | + span(targetBlank("https://BotCompany.de", "Maker.") + " " |
147 | + targetBlank("https://slides.com/stefanreich/how-about-thinking-machines/", "Slides.") + " " |
148 | + targetBlank("https://discordapp.com/invite/SEAjPqk", b("Join my Discord server!")), style := "font-size: 1.2em")) |
149 | + p(ahref(rawSelfLink("commands"), "Commands.")) |
150 | |
151 | + h3("Rules (" + l(rules) + ")") |
152 | + htmlTable2(mapReversed(rules, |
153 | func(T3<S> t) -> SS { |
154 | S ruleID = t.c; |
155 | ret litorderedmap( |
156 | "Rule ID" := htmlEncode2(ruleID), |
157 | "Rule Text" := htmlEncode_nlToBr(t.a), |
158 | "Comments" := nlToBr( |
159 | mapEachLine(/*withoutLine("discord",*/ t.b/*)*/, func(S s) -> S { |
160 | new Matches m; |
161 | if "use helper table mech list *" |
162 | ret "use helper table mech list " + |
163 | ahref(neatMechListURL($1), m.get(0)); |
164 | ret s; |
165 | })), |
166 | "Feedback" := ahref(rawSelfLink("rule/" + ruleID), |
167 | toInt(feedbackStats2.get(ruleID + "/good")) |
168 | + " / " + |
169 | toInt(feedbackStats3.get(ruleID)) |
170 | + " / " + |
171 | toInt(feedbackStats2.get(ruleID + "/bad")))); |
172 | }), |
173 | htmlEncode := false, |
174 | paramsByColName := litmap("Feedback" := litobjectarray(align := 'center)), |
175 | tdParams := litobjectarray(valign := 'top) |
176 | )), bodyParams); |
177 | } |
178 | } |
179 | |
180 | sS rawSelfLink(S uri) { ret addSlashPrefix(uri); } |
181 | |
182 | sS heading(O contents) { |
183 | ret h2(ahref(rawSelfLink(""), "Gazelle") + " | " + contents; |
184 | } |
185 | |
186 | sS hprelude() { |
187 | ret [[<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">]] + |
188 | hmobilefix(); |
189 | } |
190 | |
191 | sS hblock(S s) { |
192 | ret htmlEncode_nlToBr(s); |
193 | } |
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: | #1021844 |
Snippet name: | Gazelle Web Server v1 [backup] |
Eternal ID of this version: | #1021844/1 |
Text MD5: | 7cce4d6fac56d4ecbfd4c64f2b9b2c5d |
Transpilation MD5: | 8ac887e715fc02696c5c7e83ae3c78da |
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-02 13:18:45 |
Source code size: | 7657 bytes / 193 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 296 / 355 |
Referenced in: | [show references] |