!7 // TODO: use DynEleu // for sub-bots please include function serveRedirect. please include function serve403. please include function serve404. please include function serve500. please include function serveFile. please include function serveFileWithName. please include function serveFile_maxCache. please include function serveByteArray. please include function serveByteArray_maxCache. sclass WebRequest { NanoHTTPD.IHTTPSession httpSession; S uri, subURI; SS params; S cookie; Session session; *(NanoHTTPD.IHTTPSession *httpSession, S *uri, SS *params) {} S uri() { ret uri; } SS params() { ret params; } S clientIP() { ret unnull(getClientIPFromHeaders(httpSession.getHeaders())); } S cookie() { ret cookie; } S domain() { ret mapGet(httpSession.getHeaders(), "host"); } User loggedInUser() { ret session == null ? null : session.user(); } S googleClientID() { S domain = lower(domain()); File jsonFile = googleClientSecretFileForDomain(domain); if (!fileExists(jsonFile)) null; Map map = decodeJSONMap(loadTextFile(jsonFile)); map = (Map) map.get("web"); ret (S) map.get("client_id"); } } concept User > ConceptWithGlobalID { long lastSeen; } concept CookieUser > User { S cookie; toString { ret "[cookieUser " + md5(cookie) + "]"; } } concept GoogleUser > User { long googleLogInDate; S googleEmail, googleFirstName, googleLastName; bool googleEmailVerified; toString { ret googleFirstName + " " + googleLastName; } } concept Session { S cookie; User user; User user() { if (user == null) cset(this, user := uniq CookieUser(+cookie)); ret user; } } cmodule Eleu3 > DynPrintLogAndEnabled { //!include #1027628 // HTTP+HTTPS servers !include #1029492 // HTTP+HTTPS servers with WebSockets switchable bool alwaysWikify; start { dbIndexing(Session, 'cookie, CookieUser, 'cookie, GoogleUser, 'googleEmail); dm_restartOnFieldChange enabled(); if (!enabled) ret; set redirectHttpToHttps; start_webServers(serverSocketFactory_botCompanyEtc()); } WebSocket newWebSocket(NanoHTTPD.IHTTPSession handshake) enter { S domain = mapGet(handshake.getHeaders(), "host"); print("Making WebSocket. domain: " + domain); WebSocket ws = new(handshake); S module = moduleForDomain(domain); if (nempty(module)) pcall { dm_callOpt(module, 'handleWebSocket, ws); } else ws.close(); // Hopefully just a reload ret ws; } O webServe(S uri, SS params) { Pair spamCheck = spamBlocker.checkRequest(uri, serveHttp_clientIP()); if (spamCheck.b) { sleepSeconds(60.0); ret print("go away"); } printVars("webServe", +uri); // Serve Let's encrypt challenges if (startsWith(uri, "/.well-known/")) ret loadTextFile(userDir("validation.txt")); // make WebRequest WebRequest req = new(NanoHTTPD.currentSession!, uri, params); req.cookie = nu ServeHttp_CookieHandler(verbose := true).handle(); // Get session req.session = nempty(req.cookie) ? uniq Session(cookie := req.cookie) : null; print(session := req.session); // Serve Google verification if (eqic(uri, "/google-verify")) ret serveGoogleVerify(req); // Serve Rewrite DB S uri2 = appendSlash(uri); new Matches m; if (startsWith(uri2, "/db/", m)) { S mod = null; while licensed { mod = dm_findModuleWithParams("#1028965/RewriteDBWebBot", enabled := true); if (mod == null && dm_moduleIsReloading(dm_findModule("#1028965/RewriteDBWebBot")) || dm_moduleIsStarting(mod)) { printWithTime("Module is starting, waiting"); sleep(100); } else break; } if (mod != null) { req.subURI = "/" + m.rest(); ret eleu_callModuleHTMLMethod(mod, req); } ret "DB not loaded"; } S module = moduleForDomain(req.domain()); if (nempty(module)) ret eleu_callModuleHTMLMethod(module, req); ret "I'm probably reloading a module, please check back in a few seconds"; } S moduleForDomain(S domain) { // WIKIFY /*if (domainIsUnder(domain, "test.wikify.live")) try answer dm_findModuleWithParams("#1029430/WikifyLive", enabled := true);*/ if (alwaysWikify || domainIsUnder(domain, "wikify.live") || swic(dropPrefixIC("www.", domain), "wikify.")) try answer dm_findModuleWithParams("#1029430/WikifyLive", enabled := true); if (domainIsUnder(domain, "avor.botcompany.de")) try answer dm_findModule("#1029802/AvorDemonstrator"); if (domainIsUnder(domain, "actualbackground.website")) try answer dm_findModule("#1029697/ScribbleDemo"); if (domainIsUnder(domain, "ir.masterbot.online")) try answer dm_findModule("#1029824/ImageRecogDemoBot"); if (domainIsUnder(domain, "masterbot.online")) try answer dm_findModule("#1029807/WebCamDemo"); // bibo.digital if (domainIsUnder(domain, "bibo.digital")) try answer dm_findModule("#1029671/Bibo"); // CRUDDIE as default try answer dm_findModuleWithParams("#1028961/Cruddie", enabled := true); null; } O serveGoogleVerify(WebRequest req) { Payload payload = googleVerifyUserToken2(req.googleClientID(), req.params.get("token")); S email = payload == null ? null : payload.getEmail(); if (empty(email)) ret print("google-verify", "No"); // create/update an object for the user GoogleUser user = uniqCI_sync GoogleUser(googleEmail := email); cset(user, googleEmailVerified := payload.getEmailVerified(), googleFirstName := strOrNull(payload.get("given_name")), googleLastName := strOrNull(payload.get("family_name")), googleLogInDate := now()); // link user to session cset(req.session, +user); ret print("google-verify", payload.getEmail() + " " + (payload.getEmailVerified() ? "(verified)" : "(not verified)")); } }