O serveOtherPage2(Req req) null { new Matches m; S uri = dropTrailingSlashIfNemptyAfterwards(req.uri); if (eq(uri, "/latestPost")) { UserPost post = highestConceptByField UserPost("created"); if (post == null) ret serve404("No posts in database"); ret servePost(post); } if (eq(uri, "/latestModifiedPost")) { UserPost post = highestConceptByField UserPost("_modified"); if (post == null) ret serve404("No posts in database"); ret servePost(post); } if (eq(uri, "/rootPosts")) { Cl posts = sortedByConceptIDDesc(filter(list(UserPost), post -> empty(post.postRefs))); framer().navBeforeTitle = true; framer().title = "Root Posts"; framer().add(ul(lmap postToHTMLWithDate(posts))); ret framer().render(); } if (eq(uri, "/allPosts")) { Cl posts = sortedByConceptIDDesc(list(UserPost)); framer().navBeforeTitle = true; framer().title = "All Posts"; framer().add(ul(lmap postToHTMLWithDate(posts))); ret framer().render(); } if (eq(uri, "/latestPosts")) { Cl posts = takeFirst(50, sortedByConceptIDDesc(list(UserPost))); framer().navBeforeTitle = true; framer().title = "Latest Posts & Replies"; framer().add(ul(lmap postToHTMLWithDate(posts))); ret framer().render(); } if (eq(uri, "/mainPosts")) { Cl posts = takeFirst(50, sortedByConceptID(conceptsWhereCI UserPost(type := "Main"))); framer().navBeforeTitle = true; framer().title = "Main Posts"; framer().add(ul(lmap postToHTMLWithDate(posts))); ret framer().render(); } if (swic(uri, "/html/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); ret serveHTMLPost(id); } if (swic(uri, "/css/", m) && isInteger(m.rest())) { long id = parseLong(m.rest()); UserPost post = getConcept UserPost(id); if (post == null) ret serve404("Post not found"); ret serveWithContentType(post.text, "text/css"); } if (eq(uri, "/search")) { framer().navBeforeTitle = true; S q = trim(req.params.get("q")); framer().title = joinNemptiesWithColon("Search", q); framer().add(hcomment("cookie: " + req.webRequest.cookie())); framer().add(hform(hinputfield(+q, autofocus := true) + " " + hsubmit("Search"))); framer().add(p(small("Search help: If you search for multiple words, they can appear in any order in the text. An underscore matches any character. Plus means space. Post titles, texts and types are searched."))); if (nempty(q)) { ScoredSearcher searcher = new(q); for (UserPost post) searcher.add(post, searcher.score(post.title)*3 + searcher.score(post.text)*2 + searcher.score(post.type) + searcher.score(joinWithSpace(post.postRefTags))*0.5); L posts = searcher!; framer().add(p(b(addPlusToCount(searcher.maxResults, l(posts), nPosts(posts)) + " found for " + htmlEncode2(q)))); framer().add(ul(lmap postToHTMLWithDate(posts))); } ret framer().render(); } // serve replies for JSTree AJAX call if (eq(uri, "/jstree/replies")) { UserPost post = getConcept UserPost(parseLong(req.params.get("post"))); if (post == null) ret serveJSON(ll()); Cl refs = referencingPosts(post); /*[ { "id" : "demo_root_1", "text" : "Root 1", "children" : true, "type" : "root" }, { "id" : "demo_root_2", "text" : "Root 2", "type" : "root" } ]*/ ret serveJSON(map(refs, p -> litorderedmap( id := p.id, text := postToHTMLWithDate(post), children := nempty(referencingPosts(p)) ? true : null, type := "root" // ? ))); } if (startsWith(uri, "/touchPost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept UserPost(id); if (post == null) ret serve404("Post not found"); touchConcept(post); ret hscript([[setTimeout('history.go(-1)', 1000);]]) + "Post " + post.id + " touched"; } if (startsWith(uri, "/hidePost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept UserPost(id); if (post == null) ret serve404("Post not found"); cset(post, hidden := true); ret hrefresh(postLink(post)); } if (startsWith(uri, "/unhidePost/", m)) { long id = parseLong(m.rest()); UserPost post = getConcept UserPost(id); if (post == null) ret serve404("Post not found"); cset(post, hidden := false); ret hrefresh(postLink(post)); } if (startsWith(uri, "/mirrorConversation/", m)) { if (!req.masterAuthed) ret serveAuthForm(rawLink(uri)); long id = parseLong(m.rest()); Conversation conv = getConcept Conversation(id); if (conv == null) ret "Conversation not found"; conv.updateMirrorPost(); ret "Mirror post updated (" + htmlEncode2(str(conv.mirrorPost!)) + ")"; } if (startsWith(uri, "/bot/")) { S json = req.params.get("json"); new Map data; if (nempty(json)) data = jsonDecodeMap(json); data.putAll(withoutKey("json", req.params)); S userName = cast data.get("_user"); if (userName == null) ret serveJSON(error := "Need _user"); S botToken = cast data.get("_botToken"); if (botToken == null) ret serveJSON(error := "Need _botToken"); User user = conceptWhereIC User(name := userName); if (user == null) ret serveJSON(error := "User not found"); if (!eq(botToken, getVar(user.botToken))) ret serveJSON(error := "Wrong bot token"); req.webRequest.noSpam(); S function = dropPrefix("/bot/", uri); if (eq(function, "authTest")) ret serveJSON(status := "You are authorized as " + user.name); if (eq(function, "postCount")) ret serveJSON(result := countConcepts(UserPost)); if (eq(function, "listPosts")) { LS fields = unnull(stringToStringListOpt tok_identifiersInOrder(data.get("fields"))); if (!fields.contains("id")) fields.add(0, "id"); long changedAfter = toLong(data.get("changedAfter")); long repliesTo = toLong(data.get("repliesTo")); Cl posts; if (repliesTo != 0) { posts = referencingPosts(getConcept UserPost(repliesTo)); if (changedAfter != 0) posts = objectsWhereFieldGreaterThan(posts, _modified := changedAfter); } else { posts = changedAfter == 0 ? list(UserPost) : conceptsWithFieldGreaterThan_sorted(UserPost, _modified := changedAfter); } ret serveJSON_breakAtLevels(2, result := map(posts, post -> mapToValues(fields, field -> getPostFieldForBot(post, field)) )); } if (eq(function, "createPost")) { S text = cast data.get("text"); S type = cast data.get("type"); S title = cast data.get("title"); S botInfo = or2((S) data.get("botInfo"), "Made by bot"); LS postRefTags = unnull(lines((S) data.get("refTags"))); new L postRefs; O _refs = data.get("refs"); if (_refs cast S) for (S s : tok_integersInOrder(_refs)) { UserPost ref = getConcept UserPost(parseLong(s)); if (ref == null) ret serveJSON(error := "Post " + s + " not found"); postRefs.add(ref); } if (empty(text) && empty(title)) ret serveJSON(error := "Need either a text or a title"); bool isPublic = eqOneOf(data.get("isPublic"), null, true, "1", "t", "true"); Pair post = uniq2 UserPost(creator := user, +text, +type, +title, +isPublic, +botInfo, +postRefs, +postRefTags); if (!post.b) post.a.bump(); // bump if exact same post exists ret serveJSON(status := post.b ? "Post created" : "Post existed already, bumped", postID := post.a.id); } if (eq(function, "deletePosts")) { L ids = allToLong(tok_integersInOrder((S) data.get("ids"))); new LS results; new LS errors; fOr (long id : ids) { UserPost post = getConceptOpt UserPost(id); if (post == null) errors.add("Post " + id + " not found"); else { if (!user.isMaster && neq(post.creator!, user)) errors.add("Can't delete post " + id + " from other user"); else { deletePost(post); results.add("Post " + id + " deleted"); } } } ret serveJSON(litorderedmap(+results, +errors)); } ret serveJSON(error := "You are logged in correctly but function is unknown: " + function); } if (eq(uri, "/team")) ret serveHTMLPost(69461); }