diff options
Diffstat (limited to 'juick-www/src/main/java')
8 files changed, 725 insertions, 999 deletions
diff --git a/juick-www/src/main/java/com/juick/www/controllers/Home.java b/juick-www/src/main/java/com/juick/www/controllers/Home.java deleted file mode 100644 index a8a9f1bf..00000000 --- a/juick-www/src/main/java/com/juick/www/controllers/Home.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2008-2017, Juick - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package com.juick.www.controllers; - -import com.juick.server.util.HttpNotFoundException; -import com.juick.server.util.UserUtils; -import com.juick.server.util.WebUtils; -import com.juick.service.MessagesService; -import com.juick.service.TagService; -import com.juick.service.UserService; -import com.juick.www.Utils; -import org.apache.commons.codec.CharEncoding; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.CookieValue; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import org.springframework.web.util.UriComponents; -import ru.sape.Sape; - -import javax.inject.Inject; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.List; -import java.util.stream.Collectors; - -/** - * - * @author Ugnich Anton - */ -@Controller -public class Home { - @Inject - private UserService userService; - @Inject - private MessagesService messagesService; - @Inject - private TagService tagService; - @Inject - private Sape sape; - - @GetMapping("/{anything}/**") - protected String parseAnyThing(@PathVariable String anything, - @RequestParam(required = false, defaultValue = "0") int before) throws IOException { - if (before == 0) { - boolean isPostNumber = WebUtils.isPostNumber(anything); - int messageId = isPostNumber ? - NumberUtils.toInt(anything) : 0; - - if (isPostNumber && anything.equals(Integer.toString(messageId))) { - if (messageId > 0) { - com.juick.User author = messagesService.getMessageAuthor(messageId); - - if (author != null) { - return "redirect:/" + author.getName() + "/" + anything; - } - } - } - com.juick.User user = userService.getUserByName(anything); - if (user.getUid() > 0) { - return "redirect:/" + user.getName() + "/"; - } - throw new HttpNotFoundException(); - } - com.juick.User user = userService.getUserByName(anything); - if (user.getUid() > 0) { - return "redirect:/" + user.getName() + "/?before=" + before; - } else { - throw new HttpNotFoundException(); - } - } - - @GetMapping("/") - protected String doGet( - @RequestParam(required = false) String tag, - @RequestParam(name = "show", required = false) String paramShow, - @RequestParam(name = "search", required = false) String paramSearch, - @RequestParam(name = "before", required = false, defaultValue = "0") Integer paramBefore, - @CookieValue(name = "sape_cookie", required = false, defaultValue = StringUtils.EMPTY) String sapeCookie, - ModelMap model) throws IOException { - if (tag != null) { - return "redirect:/tag/" + URLEncoder.encode(tag, CharEncoding.UTF_8); - } - com.juick.User visitor = UserUtils.getCurrentUser(); - - if (paramSearch != null && paramSearch.length() > 64) { - paramSearch = null; - } - - String title; - List<Integer> mids; - - if (paramSearch != null) { - title = "Поиск: " + StringEscapeUtils.escapeHtml4(paramSearch); - mids = messagesService.getSearch(Utils.encodeSphinx(paramSearch), paramBefore); - } else if (paramShow == null) { - if (visitor.getUid() > 0) { - title = "Популярные"; - mids = messagesService.getPopular(visitor.getUid(), paramBefore); - } else { - title = "Микроблоги Juick: популярные записи"; - mids = messagesService.getPopular(0, paramBefore); - } - - } else if (paramShow.equals("top")) { - return "redirect:/"; - } else if (paramShow.equals("my") && !visitor.isAnonymous()) { - title = "Моя лента"; - mids = messagesService.getMyFeed(visitor.getUid(), paramBefore, true); - } else if (paramShow.equals("private") && !visitor.isAnonymous()) { - title = "Приватные"; - mids = messagesService.getPrivate(visitor.getUid(), paramBefore); - } else if (paramShow.equals("discuss") && !visitor.isAnonymous()) { - title = "Обсуждения"; - mids = messagesService.getDiscussions(visitor.getUid(), paramBefore); - } else if (paramShow.equals("recommended") && !visitor.isAnonymous()) { - title = "Рекомендации"; - mids = messagesService.getRecommended(visitor.getUid(), paramBefore); - } else if (paramShow.equals("photos")) { - title = "Фотографии"; - mids = messagesService.getPhotos(visitor.getUid(), paramBefore); - } else if (paramShow.equals("all")) { - title = "Все сообщения"; - mids = messagesService.getAll(visitor.getUid(), paramBefore); - } else { - throw new HttpNotFoundException(); - } - - String head = StringUtils.EMPTY; - if (paramBefore > 0 || paramShow != null) { - head = "<meta name=\"robots\" content=\"noindex\"/>"; - } - model.addAttribute("title", title); - model.addAttribute("headers", head); - model.addAttribute("visitor", visitor); - model.addAttribute("noindex", !(paramShow == null && paramBefore == 0)); - List<com.juick.Message> msgs = messagesService.getMessages(mids); - - if (visitor.getUid() != 0) { - List<Integer> blUIDs = userService.checkBL(visitor.getUid(), - msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList())); - msgs.forEach(m -> m.ReadOnly |= blUIDs.contains(m.getUser().getUid())); - } - model.addAttribute("msgs", msgs); - model.addAttribute("tags", tagService.getPopularTags()); - model.addAttribute("headers", head); - model.addAttribute("showAdv", - paramShow == null && paramBefore == 0 && paramSearch == null && visitor.getUid() == 0); - if (mids.size() >= 20) { - String nextpage = "?before=" + mids.get(mids.size() - 1); - if (paramShow != null) { - nextpage += "&show=" + paramShow; - } - if (paramSearch != null) { - nextpage += "&search=" + URLEncoder.encode(paramSearch, CharEncoding.UTF_8); - } - model.addAttribute("nextpage", nextpage); - } - UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); - String queryString = builder.getQuery(); - String requestURI = builder.toUri().getPath(); - if (sape != null && visitor.getUid() == 0 && queryString == null) { - String links = sape.getPageLinks(requestURI, sapeCookie).render(); - model.addAttribute("links", links); - } - model.addAttribute("isModerator", visitor.getUid() == 3694); - return "views/index"; - } -} diff --git a/juick-www/src/main/java/com/juick/www/controllers/Messages.java b/juick-www/src/main/java/com/juick/www/controllers/Messages.java new file mode 100644 index 00000000..ce678902 --- /dev/null +++ b/juick-www/src/main/java/com/juick/www/controllers/Messages.java @@ -0,0 +1,620 @@ +/* + * Copyright (C) 2008-2017, Juick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package com.juick.www.controllers; + +import com.juick.Tag; +import com.juick.formatters.PlainTextFormatter; +import com.juick.server.util.HttpForbiddenException; +import com.juick.server.util.HttpNotFoundException; +import com.juick.server.util.UserUtils; +import com.juick.server.util.WebUtils; +import com.juick.service.*; +import com.juick.www.Utils; +import org.apache.commons.codec.CharEncoding; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import org.springframework.web.util.UriComponents; +import ru.sape.Sape; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BooleanSupplier; +import java.util.stream.Collectors; + +/** + * + * @author Ugnich Anton + */ +@Controller +public class Messages { + @Inject + private UserService userService; + @Inject + private TagService tagService; + @Inject + private MessagesService messagesService; + @Inject + private Sape sape; + @Inject + private PMQueriesService pmQueriesService; + @Inject + private CrosspostService crosspostService; + + void fillUserModel(ModelMap model, com.juick.User user, com.juick.User visitor) { + model.addAttribute("user", user); + model.addAttribute("isSubscribed", userService.isSubscribed(visitor.getUid(), user.getUid())); + model.addAttribute("isInBL", userService.isInBL(visitor.getUid(), user.getUid())); + model.addAttribute("isInBLAny", userService.isInBLAny(user.getUid(), visitor.getUid())); + model.addAttribute("statsIRead", userService.getStatsIRead(user.getUid())); + model.addAttribute("statsMyReaders", userService.getStatsMyReaders(user.getUid())); + model.addAttribute("statsMyBL", userService.getUserBLUsers(user.getUid()).size()); + model.addAttribute("statsMessages", userService.getStatsMessages(user.getUid())); + model.addAttribute("statsReplies", userService.getStatsReplies(user.getUid())); + model.addAttribute("iread", userService.getUserReadLeastPopular(user.getUid(), 8)); + model.addAttribute("tagStats", tagService.getUserTagStats(user.getUid()) + .stream().sorted((e1, e2) -> Integer.compare(e2.getUsageCount(), e1.getUsageCount())).limit(20).map(t -> t.getTag().getName()).collect(Collectors.toList())); + } + + @GetMapping("/{anything}/**") + protected String parseAnyThing(@PathVariable String anything, + @RequestParam(required = false, defaultValue = "0") int before) throws IOException { + if (before == 0) { + boolean isPostNumber = WebUtils.isPostNumber(anything); + int messageId = isPostNumber ? + NumberUtils.toInt(anything) : 0; + + if (isPostNumber && anything.equals(Integer.toString(messageId))) { + if (messageId > 0) { + com.juick.User author = messagesService.getMessageAuthor(messageId); + + if (author != null) { + return "redirect:/" + author.getName() + "/" + anything; + } + } + } + com.juick.User user = userService.getUserByName(anything); + if (user.getUid() > 0) { + return "redirect:/" + user.getName() + "/"; + } + throw new HttpNotFoundException(); + } + com.juick.User user = userService.getUserByName(anything); + if (user.getUid() > 0) { + return "redirect:/" + user.getName() + "/?before=" + before; + } else { + throw new HttpNotFoundException(); + } + } + + @GetMapping("/") + protected String doGet( + @RequestParam(required = false) String tag, + @RequestParam(name = "show", required = false) String paramShow, + @RequestParam(name = "search", required = false) String paramSearch, + @RequestParam(name = "before", required = false, defaultValue = "0") Integer paramBefore, + @CookieValue(name = "sape_cookie", required = false, defaultValue = StringUtils.EMPTY) String sapeCookie, + ModelMap model) throws IOException { + if (tag != null) { + return "redirect:/tag/" + URLEncoder.encode(tag, CharEncoding.UTF_8); + } + com.juick.User visitor = UserUtils.getCurrentUser(); + + if (paramSearch != null && paramSearch.length() > 64) { + paramSearch = null; + } + + String title; + List<Integer> mids; + + if (paramSearch != null) { + title = "Поиск: " + StringEscapeUtils.escapeHtml4(paramSearch); + mids = messagesService.getSearch(Utils.encodeSphinx(paramSearch), paramBefore); + } else if (paramShow == null) { + if (visitor.getUid() > 0) { + title = "Популярные"; + mids = messagesService.getPopular(visitor.getUid(), paramBefore); + } else { + title = "Микроблоги Juick: популярные записи"; + mids = messagesService.getPopular(0, paramBefore); + } + + } else if (paramShow.equals("top")) { + return "redirect:/"; + } else if (paramShow.equals("my") && !visitor.isAnonymous()) { + title = "Моя лента"; + mids = messagesService.getMyFeed(visitor.getUid(), paramBefore, true); + } else if (paramShow.equals("private") && !visitor.isAnonymous()) { + title = "Приватные"; + mids = messagesService.getPrivate(visitor.getUid(), paramBefore); + } else if (paramShow.equals("discuss") && !visitor.isAnonymous()) { + title = "Обсуждения"; + mids = messagesService.getDiscussions(visitor.getUid(), paramBefore); + } else if (paramShow.equals("recommended") && !visitor.isAnonymous()) { + title = "Рекомендации"; + mids = messagesService.getRecommended(visitor.getUid(), paramBefore); + } else if (paramShow.equals("photos")) { + title = "Фотографии"; + mids = messagesService.getPhotos(visitor.getUid(), paramBefore); + } else if (paramShow.equals("all")) { + title = "Все сообщения"; + mids = messagesService.getAll(visitor.getUid(), paramBefore); + } else { + throw new HttpNotFoundException(); + } + + String head = StringUtils.EMPTY; + if (paramBefore > 0 || paramShow != null) { + head = "<meta name=\"robots\" content=\"noindex\"/>"; + } + model.addAttribute("title", title); + model.addAttribute("headers", head); + model.addAttribute("visitor", visitor); + model.addAttribute("noindex", !(paramShow == null && paramBefore == 0)); + List<com.juick.Message> msgs = messagesService.getMessages(mids); + + if (visitor.getUid() != 0) { + fillUserModel(model, visitor, visitor); + List<Integer> blUIDs = userService.checkBL(visitor.getUid(), + msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList())); + msgs.forEach(m -> m.ReadOnly |= blUIDs.contains(m.getUser().getUid())); + } + model.addAttribute("msgs", msgs); + model.addAttribute("tags", tagService.getPopularTags()); + model.addAttribute("headers", head); + model.addAttribute("showAdv", + paramShow == null && paramBefore == 0 && paramSearch == null && visitor.getUid() == 0); + if (mids.size() >= 20) { + String nextpage = "?before=" + mids.get(mids.size() - 1); + if (paramShow != null) { + nextpage += "&show=" + paramShow; + } + if (paramSearch != null) { + nextpage += "&search=" + URLEncoder.encode(paramSearch, CharEncoding.UTF_8); + } + model.addAttribute("nextpage", nextpage); + } + UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); + String queryString = builder.getQuery(); + String requestURI = builder.toUri().getPath(); + if (sape != null && visitor.getUid() == 0 && queryString == null) { + String links = sape.getPageLinks(requestURI, sapeCookie).render(); + model.addAttribute("links", links); + } + model.addAttribute("isModerator", visitor.getUid() == 3694); + return "views/index"; + } + + @GetMapping("/{uname}/") + protected String doGetBlog( + @RequestParam(required = false, name = "show") String paramShow, + @RequestParam(required = false, name = "tag") String paramTagStr, + @RequestParam(required = false, name = "search") String paramSearch, + @PathVariable String uname, + @RequestParam(required = false, defaultValue = "0") Integer before, + @CookieValue(name = "sape_cookie", required = false, defaultValue = StringUtils.EMPTY) String sapeCookie, + ModelMap model) throws IOException { + com.juick.User user = userService.getUserByName(uname); + com.juick.User visitor = UserUtils.getCurrentUser(); + if (user.isBanned()) { + throw new HttpNotFoundException(); + } + + List<Integer> mids; + + com.juick.Tag paramTag = null; + if (paramTagStr != null) { + if (paramTagStr.length() < 64) { + paramTag = tagService.getTag(paramTagStr, false); + } + if (paramTag == null) { + throw new HttpNotFoundException(); + } else if (!paramTag.getName().equals(paramTagStr)) { + String url = user.getName() + "/?tag=" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8); + return "redirect:/" + url; + } + } + if (paramSearch != null && paramSearch.length() > 64) { + paramSearch = null; + } + + int privacy = 0; + if (visitor.getUid() > 0) { + if (user.getUid() == visitor.getUid() || visitor.getUid() == 1) { + privacy = -3; + } else if (userService.isInWL(user.getUid(), visitor.getUid())) { + privacy = -2; + } + } + + String title; + if (paramShow == null) { + if (paramTag != null) { + title = "Блог " + user.getName() + ": *" + StringEscapeUtils.escapeHtml4(paramTag.getName()); + mids = messagesService.getUserTag(user.getUid(), paramTag.TID, privacy, before); + } else if (paramSearch != null) { + title = "Блог " + user.getName() + ": " + StringEscapeUtils.escapeHtml4(paramSearch); + mids = messagesService.getUserSearch(user.getUid(), Utils.encodeSphinx(paramSearch), privacy, before); + } else { + title = "Блог " + user.getName(); + mids = messagesService.getUserBlog(user.getUid(), privacy, before); + } + } else if (paramShow.equals("recomm")) { + title = "Рекомендации " + user.getName(); + mids = messagesService.getUserRecommendations(user.getUid(), before); + } else if (paramShow.equals("photos")) { + title = "Фотографии " + user.getName(); + mids = messagesService.getUserPhotos(user.getUid(), privacy, before); + } else { + throw new HttpNotFoundException(); + } + + String head = "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"@" + + user.getName() + "\" href=\"//rss.juick.com/" + user.getName() + "/blog\"/>"; + if (paramTag != null && tagService.getTagNoIndex(paramTag.TID)) { + head += "<meta name=\"robots\" content=\"noindex,nofollow\"/>"; + } else if (before > 0 || paramShow != null) { + head += "<meta name=\"robots\" content=\"noindex\"/>"; + } + model.addAttribute("pageUrl", "http://juick.com/" + user.getName()); + model.addAttribute("title", title); + model.addAttribute("headers", head); + model.addAttribute("visitor", visitor); + model.addAttribute("noindex", paramShow == null && before == 0); + fillUserModel(model, user, visitor); + model.addAttribute("paramTag", paramTag); + List<com.juick.Message> msgs = messagesService.getMessages(mids); + + if (visitor.getUid() != 0) { + List<Integer> blUIDs = userService.checkBL(visitor.getUid(), + msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList())); + msgs.forEach(m -> m.ReadOnly |= blUIDs.contains(m.getUser().getUid())); + } + model.addAttribute("msgs", msgs); + model.addAttribute("headers", head); + model.addAttribute("showAdv", + paramShow == null && before == 0 && paramSearch == null && visitor.getUid() == 0); + if (mids.size() >= 20) { + String nextpage = "?before=" + mids.get(mids.size() - 1); + if (paramShow != null) { + nextpage += "&show=" + paramShow; + } + if (paramSearch != null) { + nextpage += "&search=" + URLEncoder.encode(paramSearch, CharEncoding.UTF_8); + } + if (paramTag != null) { + nextpage += "&tag=" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8); + } + model.addAttribute("nextpage", nextpage); + } + UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); + String queryString = builder.getQuery(); + String requestURI = builder.toUri().getPath(); + if (sape != null && visitor.getUid() == 0 && queryString == null) { + String links = sape.getPageLinks(requestURI, sapeCookie).render(); + model.addAttribute("links", links); + } + model.addAttribute("isModerator", visitor.getUid() == 3694); + return "views/blog"; + } + + @GetMapping("/{uname}/tags") + protected String doGetTags(@PathVariable String uname, ModelMap model) throws IOException { + com.juick.User user = userService.getUserByName(uname); + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.isBanned()) { + throw new HttpNotFoundException(); + } + + model.addAttribute("title", "Теги " + user.getName()); + model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex,nofollow\"/>"); + model.addAttribute("visitor", visitor); + fillUserModel(model, user, visitor); + model.addAttribute("tags", tagService.getUserTagStats(user.getUid()).stream() + .sorted((e1, e2) -> Integer.compare(e2.getUsageCount(), e1.getUsageCount())).map(t -> t.getTag().getName()).collect(Collectors.toList())); + + return "views/blog_tags"; + } + + @GetMapping("/{uname}/friends") + protected String doGetFriends(@PathVariable String uname, ModelMap model) throws IOException { + com.juick.User user = userService.getUserByName(uname); + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.isBanned()) { + throw new HttpNotFoundException(); + } + model.addAttribute("title", "Подписки " + user.getName()); + model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex\"/>"); + model.addAttribute("visitor", visitor); + fillUserModel(model, user, visitor); + model.addAttribute("users", userService.getUserFriends(user.getUid())); + + return "views/users"; + } + + @GetMapping("/{uname}/readers") + protected String doGetReaders(@PathVariable String uname, ModelMap model) throws IOException { + com.juick.User user = userService.getUserByName(uname); + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.isBanned()) { + throw new HttpForbiddenException(); + } + model.addAttribute("title", "Читатели " + user.getName()); + model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex\"/>"); + model.addAttribute("visitor", visitor); + fillUserModel(model, user, visitor); + model.addAttribute("users", userService.getUserReaders(user.getUid())); + + return "views/users"; + } + + @GetMapping("/{uname}/bl") + protected String doGetBL(@PathVariable String uname, ModelMap model) throws IOException { + com.juick.User user = userService.getUserByName(uname); + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.isBanned() || visitor.getUid() != user.getUid()) { + throw new HttpForbiddenException(); + } + model.addAttribute("title", "Черный список " + user.getName()); + model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex\"/>"); + model.addAttribute("visitor", visitor); + fillUserModel(model, user, visitor); + model.addAttribute("users", userService.getUserBLUsers(user.getUid())); + + return "views/users"; + } + @GetMapping("/tag/{tagName}") + protected String tagAction(HttpServletRequest request, + @PathVariable String tagName, + @RequestParam(required = false, defaultValue = "0") int before, + ModelMap model) throws IOException { + com.juick.User visitor = UserUtils.getCurrentUser(); + + String paramTagStr = StringEscapeUtils.unescapeHtml4(tagName); + com.juick.Tag paramTag = tagService.getTag(paramTagStr, false); + if (paramTag == null) { + throw new HttpNotFoundException(); + } else if (paramTag.SynonymID > 0 && paramTag.TID != paramTag.SynonymID) { + com.juick.Tag synTag = tagService.getTag(paramTag.SynonymID); + String url = "/tag/" + URLEncoder.encode(StringEscapeUtils.escapeHtml4(synTag.getName()), CharEncoding.UTF_8); + if (request.getQueryString() != null) { + url += "?" + request.getQueryString(); + } + return "redirect:" + url; + } else if (!paramTag.getName().equals(paramTagStr)) { + String url = "/tag/" + URLEncoder.encode(StringEscapeUtils.escapeHtml4(paramTag.getName()), CharEncoding.UTF_8); + if (request.getQueryString() != null) { + url += "?" + request.getQueryString(); + } + return "redirect:" + url; + } + + int visitor_uid = visitor.getUid(); + + String title = "*" + StringEscapeUtils.escapeHtml4(paramTag.getName()); + model.addAttribute("title", title); + List<Integer> mids = messagesService.getTag(paramTag.TID, visitor_uid, before, (visitor_uid == 0) ? 40 : 20); + + String head = StringUtils.EMPTY; + if (tagService.getTagNoIndex(paramTag.TID)) { + head = "<meta name=\"robots\" content=\"noindex,nofollow\"/>"; + } else if (before > 0 || mids.size() < 5) { + head = "<meta name=\"robots\" content=\"noindex\"/>"; + } + model.addAttribute("headers", head); + model.addAttribute("visitor", visitor); + + List<com.juick.Message> msgs = messagesService.getMessages(mids); + + if (visitor.getUid() != 0) { + List<Integer> blUIDs = userService.checkBL(visitor.getUid(), + msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList())); + msgs.forEach(m -> m.ReadOnly |= blUIDs.contains(m.getUser().getUid())); + fillUserModel(model, visitor, visitor); + } + model.addAttribute("msgs", msgs); + model.addAttribute("tags", tagService.getPopularTags()); + model.addAttribute("headers", head); + model.addAttribute("noindex", before > 0); + model.addAttribute("showAdv",before == 0 && visitor.getUid() == 0); + model.addAttribute("isModerator", visitor.getUid() == 3694); + if (mids.size() >= 20) { + String nextpage = "/tag/" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8) + "?before=" + mids.get(mids.size() - 1); + model.addAttribute("nextpage", nextpage); + } + return "views/index"; + } + @GetMapping("/pm/inbox") + protected String doGetInbox(ModelMap model) { + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.getUid() == 0) { + return "redirect:/login"; + } + String title = "PM: Inbox"; + List<com.juick.Message> msgs = pmQueriesService.getLastPMInbox(visitor.getUid()); + fillUserModel(model, visitor, visitor); + model.addAttribute("title", title); + model.addAttribute("visitor", visitor); + model.addAttribute("msgs", msgs); + model.addAttribute("tags", tagService.getPopularTags()); + return "views/pm_inbox"; + } + + @GetMapping("/pm/sent") + protected String doGetSent(@RequestParam(required = false) String uname, + ModelMap model) { + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.getUid() == 0) { + return "redirect:/login"; + } + String title = "PM: Sent"; + List<com.juick.Message> msgs = pmQueriesService.getLastPMSent(visitor.getUid()); + + if (WebUtils.isNotUserName(uname)) { + uname = StringUtils.EMPTY; + } + fillUserModel(model, visitor, visitor); + model.addAttribute("title", title); + model.addAttribute("visitor", visitor); + model.addAttribute("msgs", msgs); + model.addAttribute("tags", tagService.getPopularTags()); + model.addAttribute("uname", uname); + return "views/pm_sent"; + } + @GetMapping("/{uname}/{mid}") + protected String threadAction(ModelMap model, + @PathVariable String uname, + @PathVariable int mid, + @RequestParam(required = false, value = "view") String paramView) throws IOException { + com.juick.User visitor = UserUtils.getCurrentUser(); + + if (!messagesService.canViewThread(mid, visitor.getUid())) { + throw new HttpForbiddenException(); + } + + com.juick.Message msg = messagesService.getMessage(mid); + + if (msg == null || msg.getUser().isBanned()) { + throw new HttpNotFoundException(); + } + + com.juick.User user = userService.getUserByName(uname); + if (user.getUid() == 0 || !msg.getUser().equals(user)) { + return String.format("redirect:/%s/%d", msg.getUser().getName(), mid); + } + msg.VisitorCanComment = visitor.getUid() > 0; + if (visitor.getUid() > 0) { + fillUserModel(model, user, visitor); + boolean isMsgAuthor = visitor.getUid() == msg.getUser().getUid(); + boolean isInBL = userService.isInBL(msg.getUser().getUid(), visitor.getUid()); + msg.VisitorCanComment = isMsgAuthor || !(msg.ReadOnly || isInBL); + } + model.addAttribute("msg", msg); + + boolean listview = false; + if (paramView != null) { + if (paramView.equals("list")) { + listview = true; + if (visitor.getUid() > 0) { + userService.setUserOptionInt(visitor.getUid(), "repliesview", 1); + } + } else if (paramView.equals("tree") && visitor.getUid() > 0) { + userService.setUserOptionInt(visitor.getUid(), "repliesview", 0); + } + } else if (visitor.getUid() > 0 && userService.getUserOptionInt(visitor.getUid(), "repliesview", 0) == 1) { + listview = true; + } + model.addAttribute("listview", listview); + String title = msg.getUser().getName() + ": " + msg.getTagsString(); + + model.addAttribute("title", title); + model.addAttribute("visitor", visitor); + String headers = "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"@" + msg.getUser().getName() + "\" href=\"//rss.juick.com/" + msg.getUser().getName() + "/blog\"/>"; + String pageUrl = "https://juick.com/" + msg.getUser().getName() + "/" + msg.getMid(); + if (paramView != null) { + headers += "<link rel=\"canonical\" href=\"" + pageUrl + "\"/>"; + } + if (msg.Hidden) { + headers += "<meta name=\"robots\" content=\"noindex\"/>"; + } + String cardType = StringUtils.isNotEmpty(msg.getAttachmentType()) ? "summary_large_image" : "summary"; + String msgImage = StringUtils.isNotEmpty(msg.getAttachmentType()) ? msg.getAttachment().getMedium().getUrl() + : "https://i.juick.com/a/" + msg.getUser().getUid() + ".png"; + model.addAttribute("ogtype", "article"); + String cardDescription = StringEscapeUtils.escapeHtml4(PlainTextFormatter.formatTwitterCard(msg)); + headers += "<meta name=\"twitter:card\" content=\"" + cardType + "\" />\n" + + "<meta name=\"twitter:site\" content=\"@juick\" />\n" + + "<meta property=\"og:url\" content=\"" + pageUrl + "\" />\n" + + "<meta property=\"og:title\" content=\"" + msg.getUser().getName() + " at Juick\" />\n" + + "<meta property=\"og:description\" content=\"" + cardDescription + "\" />\n" + + "<meta name=\"Description\" content=\"" + cardDescription + "\" />\n" + + "<meta property=\"og:image\" content=\"" + msgImage + "\" />"; + String twitterName = crosspostService.getTwitterName(msg.getUser().getUid()); + if (StringUtils.isNotEmpty(twitterName)) { + headers += "<meta name=\"twitter:creator\" content=\"@" + twitterName + "\" />\n"; + } + if (msg.getTags().size() > 0) { + headers += "<meta name=\"Keywords\" content=\"" + msg.getTags().stream().map(Tag::getName) + .collect(Collectors.joining(", ")) + "\" />\n"; + } + model.addAttribute("headers", headers); + model.addAttribute("isModerator", visitor.getUid() == 3694); + model.addAttribute("visitorSubscribed", messagesService.isSubscribed(visitor.getUid(), msg.getMid())); + model.addAttribute("visitorInBL", userService.isInBL(msg.getUser().getUid(), visitor.getUid())); + model.addAttribute("recomm", messagesService.getMessageRecommendations(msg.getMid())); + List<com.juick.Message> replies = messagesService.getReplies(msg.getMid()); + + List<Integer> blUIDs = new ArrayList<>(); + for (int i = 0; i < replies.size(); i++) { + com.juick.Message reply = replies.get(i); + if (reply.getUser().getUid() != msg.getUser().getUid() + && !blUIDs.contains(reply.getUser().getUid())) { + blUIDs.add(reply.getUser().getUid()); + } + if (reply.getReplyto() > 0) { + boolean added = false; + for (int n = 0; n < replies.size(); n++) { + if (replies.get(n).getRid() == reply.getReplyto()) { + replies.get(n).childs.add(reply); + added = true; + break; + } + } + if (!added) { + reply.setReplyto(0); + } + } + + reply.VisitorCanComment = visitor.getUid() > 0; + if (visitor.getUid() > 0) { + boolean isMsgAuthor = visitor.getUid() == msg.getUser().getUid(); + boolean isReplyAuthor = visitor.getUid() == reply.getUser().getUid(); + BooleanSupplier isInBL2 = () -> userService.checkBL(visitor.getUid(), blUIDs).contains(reply.getUser().getUid()); + reply.VisitorCanComment = isMsgAuthor || (!msg.ReadOnly && (isReplyAuthor || !isInBL2.getAsBoolean())); + } + } + + boolean foldable = false; + if (replies.size() > 10) { + for (int i = 0; i < replies.size() - 1; i++) { + if (replies.get(i).getChildsCount() > 1) { + foldable = true; + break; + } + } + } + model.addAttribute("replies", replies); + model.addAttribute("foldable", foldable); + return "views/thread"; + } + + // when message id is not fit to int + @ExceptionHandler(NumberFormatException.class) + public ResponseEntity<String> notFoundAction() { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } +} diff --git a/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java b/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java index b0a2b4af..a87c7136 100644 --- a/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java +++ b/juick-www/src/main/java/com/juick/www/controllers/NewMessage.java @@ -62,6 +62,8 @@ public class NewMessage { @Inject private CrosspostService crosspostService; @Inject + private PMQueriesService pmQueriesService; + @Inject private WebApp webApp; private static final Logger logger = LoggerFactory.getLogger(NewMessage.class); @@ -332,4 +334,107 @@ public class NewMessage { throw new HttpBadRequestException(); } } + @PostMapping("/pm/send") + public String doPostPM(@RequestParam(name = "uname", required = false) String unameParam, + @RequestParam String body) throws IOException { + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.getUid() == 0 || visitor.isBanned()) { + throw new HttpForbiddenException(); + } + String uname = unameParam; + if (uname.startsWith("@")) { + uname = uname.substring(1); + } + int uid = 0; + if (WebUtils.isUserName(uname)) { + uid = userService.getUIDbyName(uname); + } + + if (uid == 0 || body.length() > 10240) { + throw new HttpBadRequestException(); + } + + if (userService.isInBLAny(uid, visitor.getUid())) { + throw new HttpForbiddenException(); + } + + if (pmQueriesService.createPM(visitor.getUid(), uid, body)) { + if (webApp.getXmpp() != null) { + Message msg = new Message(); + msg.setFrom(Jid.of("juick@juick.com")); + msg.setTo(Jid.of(String.format("%d@push.juick.com", uid))); + com.juick.Message jmsg = new com.juick.Message(); + jmsg.setUser(visitor); + jmsg.setText(body); + msg.addExtension(jmsg); + webApp.getXmpp().send(msg); + + msg.setTo(Jid.of(String.format("%d@ws.juick.com", uid))); + webApp.getXmpp().send(msg); + + List<String> jids = userService.getJIDsbyUID(uid); + for (String jid : jids) { + Message mm = new Message(); + mm.setTo(Jid.of(jid)); + mm.setType(Message.Type.CHAT); + if (pmQueriesService.havePMinRoster(visitor.getUid(), jid)) { + mm.setFrom(Jid.of(jmsg.getUser().getName(), "juick.com", "Juick")); + mm.setBody(body); + } else { + mm.setFrom(Jid.of("juick", "juick.com", "Juick")); + mm.setBody("Private message from @" + jmsg.getUser().getName() + ":\n" + body); + } + webApp.getXmpp().send(mm); + } + } else { + logger.warn("XMPP unavailable"); + } + return "redirect:/pm/sent"; + } else { + throw new HttpBadRequestException(); + } + } + @PostMapping("/post2") + public String doPostMessage(@RequestParam(name = "body") String bodyParam, + @RequestParam(required = false) String img, + @RequestParam(required = false) String referer, + @RequestParam(required = false) MultipartFile attach) throws IOException { + + com.juick.User visitor = UserUtils.getCurrentUser(); + if (visitor.getUid() == 0 || visitor.isBanned()) { + throw new HttpForbiddenException(); + } + String body = bodyParam.replace("\r", StringUtils.EMPTY); + + String attachmentFName = HttpUtils.receiveMultiPartFile(attach, webApp.getTmpDir()); + + if (StringUtils.isBlank(attachmentFName) && img != null && img.length() > 10) { + try { + URL imgUrl = new URL(img); + attachmentFName = HttpUtils.downloadImage(imgUrl, webApp.getTmpDir()); + } catch (Exception e) { + logger.error("DOWNLOAD ERROR", e); + throw new HttpBadRequestException(); + } + } + Message msg = new Message(); + msg.setType(Message.Type.CHAT); + msg.setFrom(Jid.of(String.valueOf(visitor.getUid()), "uid.juick.com", "perl")); + msg.setTo(Jid.of("juick@juick.com/Juick")); + msg.setBody(body); + try { + if (StringUtils.isNotEmpty(attachmentFName)) { + String attachmentUrl = String.format("juick://%s", attachmentFName); + msg.addExtension(new OobX(new URI(attachmentUrl), "!!!!Juick!!")); + } + webApp.getXmpp().sendMessage(msg); + } catch (URISyntaxException e1) { + logger.warn("attachment error", e1); + } + if (StringUtils.isBlank(referer) || referer.substring(0, 21).equals("http://juick.com/post") + || referer.substring(0, 22).equals("https://juick.com/post")) { + return "redirect:/?show=my"; + } + return "redirect:" + referer; + } } diff --git a/juick-www/src/main/java/com/juick/www/controllers/PM.java b/juick-www/src/main/java/com/juick/www/controllers/PM.java deleted file mode 100644 index fda3501b..00000000 --- a/juick-www/src/main/java/com/juick/www/controllers/PM.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2008-2017, Juick - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package com.juick.www.controllers; - -import com.juick.server.util.HttpBadRequestException; -import com.juick.server.util.HttpForbiddenException; -import com.juick.server.util.UserUtils; -import com.juick.server.util.WebUtils; -import com.juick.service.PMQueriesService; -import com.juick.service.TagService; -import com.juick.service.UserService; -import com.juick.www.WebApp; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import rocks.xmpp.addr.Jid; -import rocks.xmpp.core.stanza.model.Message; - -import javax.inject.Inject; -import java.io.IOException; -import java.util.List; - -/** - * - * @author Ugnich Anton - */ -@Controller -public class PM { - private static final Logger logger = LoggerFactory.getLogger(PM.class); - - @Inject - private PMQueriesService pmQueriesService; - @Inject - private TagService tagService; - @Inject - private UserService userService; - @Inject - private WebApp webApp; - - @GetMapping("/pm/inbox") - protected String doGetInbox(ModelMap model) { - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.getUid() == 0) { - return "redirect:/login"; - } - String title = "PM: Inbox"; - List<com.juick.Message> msgs = pmQueriesService.getLastPMInbox(visitor.getUid()); - model.addAttribute("title", title); - model.addAttribute("visitor", visitor); - model.addAttribute("msgs", msgs); - model.addAttribute("tags", tagService.getPopularTags()); - return "views/pm_inbox"; - } - - @GetMapping("/pm/sent") - protected String doGetSent(@RequestParam(required = false) String uname, - ModelMap model) { - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.getUid() == 0) { - return "redirect:/login"; - } - String title = "PM: Sent"; - List<com.juick.Message> msgs = pmQueriesService.getLastPMSent(visitor.getUid()); - - if (WebUtils.isNotUserName(uname)) { - uname = StringUtils.EMPTY; - } - - model.addAttribute("title", title); - model.addAttribute("visitor", visitor); - model.addAttribute("msgs", msgs); - model.addAttribute("tags", tagService.getPopularTags()); - model.addAttribute("uname", uname); - return "views/pm_sent"; - } - - @PostMapping("/pm/send") - public String doPostPM(@RequestParam(name = "uname", required = false) String unameParam, - @RequestParam String body) throws IOException { - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.getUid() == 0 || visitor.isBanned()) { - throw new HttpForbiddenException(); - } - String uname = unameParam; - if (uname.startsWith("@")) { - uname = uname.substring(1); - } - int uid = 0; - if (WebUtils.isUserName(uname)) { - uid = userService.getUIDbyName(uname); - } - - if (uid == 0 || body.length() > 10240) { - throw new HttpBadRequestException(); - } - - if (userService.isInBLAny(uid, visitor.getUid())) { - throw new HttpForbiddenException(); - } - - if (pmQueriesService.createPM(visitor.getUid(), uid, body)) { - if (webApp.getXmpp() != null) { - Message msg = new Message(); - msg.setFrom(Jid.of("juick@juick.com")); - msg.setTo(Jid.of(String.format("%d@push.juick.com", uid))); - com.juick.Message jmsg = new com.juick.Message(); - jmsg.setUser(visitor); - jmsg.setText(body); - msg.addExtension(jmsg); - webApp.getXmpp().send(msg); - - msg.setTo(Jid.of(String.format("%d@ws.juick.com", uid))); - webApp.getXmpp().send(msg); - - List<String> jids = userService.getJIDsbyUID(uid); - for (String jid : jids) { - Message mm = new Message(); - mm.setTo(Jid.of(jid)); - mm.setType(Message.Type.CHAT); - if (pmQueriesService.havePMinRoster(visitor.getUid(), jid)) { - mm.setFrom(Jid.of(jmsg.getUser().getName(), "juick.com", "Juick")); - mm.setBody(body); - } else { - mm.setFrom(Jid.of("juick", "juick.com", "Juick")); - mm.setBody("Private message from @" + jmsg.getUser().getName() + ":\n" + body); - } - webApp.getXmpp().send(mm); - } - } else { - logger.warn("XMPP unavailable"); - } - return "redirect:/pm/sent"; - } else { - throw new HttpBadRequestException(); - } - } -} diff --git a/juick-www/src/main/java/com/juick/www/controllers/Tags.java b/juick-www/src/main/java/com/juick/www/controllers/Tags.java deleted file mode 100644 index 6a22216f..00000000 --- a/juick-www/src/main/java/com/juick/www/controllers/Tags.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2008-2017, Juick - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package com.juick.www.controllers; - -import com.juick.server.util.HttpNotFoundException; -import com.juick.server.util.UserUtils; -import com.juick.service.MessagesService; -import com.juick.service.TagService; -import com.juick.service.UserService; -import org.apache.commons.codec.CharEncoding; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author Ugnich Anton - */ -@Controller -public class Tags { - @Inject - private MessagesService messagesService; - @Inject - private TagService tagService; - @Inject - private UserService userService; - - @GetMapping("/tag/{tagName}") - protected String tagAction(HttpServletRequest request, - @PathVariable String tagName, - @RequestParam(required = false, defaultValue = "0") int before, - ModelMap model) throws IOException { - com.juick.User visitor = UserUtils.getCurrentUser(); - - String paramTagStr = StringEscapeUtils.unescapeHtml4(tagName); - com.juick.Tag paramTag = tagService.getTag(paramTagStr, false); - if (paramTag == null) { - throw new HttpNotFoundException(); - } else if (paramTag.SynonymID > 0 && paramTag.TID != paramTag.SynonymID) { - com.juick.Tag synTag = tagService.getTag(paramTag.SynonymID); - String url = "/tag/" + URLEncoder.encode(StringEscapeUtils.escapeHtml4(synTag.getName()), CharEncoding.UTF_8); - if (request.getQueryString() != null) { - url += "?" + request.getQueryString(); - } - return "redirect:" + url; - } else if (!paramTag.getName().equals(paramTagStr)) { - String url = "/tag/" + URLEncoder.encode(StringEscapeUtils.escapeHtml4(paramTag.getName()), CharEncoding.UTF_8); - if (request.getQueryString() != null) { - url += "?" + request.getQueryString(); - } - return "redirect:" + url; - } - - int visitor_uid = visitor.getUid(); - - String title = "*" + StringEscapeUtils.escapeHtml4(paramTag.getName()); - model.addAttribute("title", title); - List<Integer> mids = messagesService.getTag(paramTag.TID, visitor_uid, before, (visitor_uid == 0) ? 40 : 20); - - String head = StringUtils.EMPTY; - if (tagService.getTagNoIndex(paramTag.TID)) { - head = "<meta name=\"robots\" content=\"noindex,nofollow\"/>"; - } else if (before > 0 || mids.size() < 5) { - head = "<meta name=\"robots\" content=\"noindex\"/>"; - } - model.addAttribute("headers", head); - model.addAttribute("visitor", visitor); - - List<com.juick.Message> msgs = messagesService.getMessages(mids); - - if (visitor.getUid() != 0) { - List<Integer> blUIDs = userService.checkBL(visitor.getUid(), - msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList())); - msgs.forEach(m -> m.ReadOnly |= blUIDs.contains(m.getUser().getUid())); - } - model.addAttribute("msgs", msgs); - model.addAttribute("tags", tagService.getPopularTags()); - model.addAttribute("headers", head); - model.addAttribute("noindex", before > 0); - model.addAttribute("showAdv",before == 0 && visitor.getUid() == 0); - model.addAttribute("isModerator", visitor.getUid() == 3694); - if (mids.size() >= 20) { - String nextpage = "/tag/" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8) + "?before=" + mids.get(mids.size() - 1); - model.addAttribute("nextpage", nextpage); - } - return "views/index"; - } -} diff --git a/juick-www/src/main/java/com/juick/www/controllers/User.java b/juick-www/src/main/java/com/juick/www/controllers/User.java deleted file mode 100644 index d42d3ed3..00000000 --- a/juick-www/src/main/java/com/juick/www/controllers/User.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2008-2017, Juick - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package com.juick.www.controllers; - -import com.juick.server.util.HttpForbiddenException; -import com.juick.server.util.HttpNotFoundException; -import com.juick.server.util.UserUtils; -import com.juick.service.MessagesService; -import com.juick.service.TagService; -import com.juick.service.UserService; -import com.juick.www.Utils; -import org.apache.commons.codec.CharEncoding; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.CookieValue; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import org.springframework.web.util.UriComponents; -import ru.sape.Sape; - -import javax.inject.Inject; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.List; -import java.util.stream.Collectors; - -/** - * - * @author Ugnich Anton - */ -@Controller -public class User { - @Inject - private UserService userService; - @Inject - private TagService tagService; - @Inject - private MessagesService messagesService; - @Inject - private Sape sape; - - void fillUserModel(ModelMap model, com.juick.User user, com.juick.User visitor) { - model.addAttribute("isSubscribed", userService.isSubscribed(visitor.getUid(), user.getUid())); - model.addAttribute("isInBL", userService.isInBL(visitor.getUid(), user.getUid())); - model.addAttribute("isInBLAny", userService.isInBLAny(user.getUid(), visitor.getUid())); - model.addAttribute("statsIRead", userService.getStatsIRead(user.getUid())); - model.addAttribute("statsMyReaders", userService.getStatsMyReaders(user.getUid())); - model.addAttribute("statsMyBL", userService.getUserBLUsers(user.getUid()).size()); - model.addAttribute("statsMessages", userService.getStatsMessages(user.getUid())); - model.addAttribute("statsReplies", userService.getStatsReplies(user.getUid())); - model.addAttribute("iread", userService.getUserReadLeastPopular(user.getUid(), 8)); - model.addAttribute("tagStats", tagService.getUserTagStats(user.getUid()) - .stream().sorted((e1, e2) -> Integer.compare(e2.getUsageCount(), e1.getUsageCount())).limit(20).map(t -> t.getTag().getName()).collect(Collectors.toList())); - } - - @GetMapping("/{uname}/") - protected String doGetBlog( - @RequestParam(required = false, name = "show") String paramShow, - @RequestParam(required = false, name = "tag") String paramTagStr, - @RequestParam(required = false, name = "search") String paramSearch, - @PathVariable String uname, - @RequestParam(required = false, defaultValue = "0") Integer before, - @CookieValue(name = "sape_cookie", required = false, defaultValue = StringUtils.EMPTY) String sapeCookie, - ModelMap model) throws IOException { - com.juick.User user = userService.getUserByName(uname); - com.juick.User visitor = UserUtils.getCurrentUser(); - if (user.isBanned()) { - throw new HttpNotFoundException(); - } - - List<Integer> mids; - - com.juick.Tag paramTag = null; - if (paramTagStr != null) { - if (paramTagStr.length() < 64) { - paramTag = tagService.getTag(paramTagStr, false); - } - if (paramTag == null) { - throw new HttpNotFoundException(); - } else if (!paramTag.getName().equals(paramTagStr)) { - String url = user.getName() + "/?tag=" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8); - return "redirect:/" + url; - } - } - if (paramSearch != null && paramSearch.length() > 64) { - paramSearch = null; - } - - int privacy = 0; - if (visitor.getUid() > 0) { - if (user.getUid() == visitor.getUid() || visitor.getUid() == 1) { - privacy = -3; - } else if (userService.isInWL(user.getUid(), visitor.getUid())) { - privacy = -2; - } - } - - String title; - if (paramShow == null) { - if (paramTag != null) { - title = "Блог " + user.getName() + ": *" + StringEscapeUtils.escapeHtml4(paramTag.getName()); - mids = messagesService.getUserTag(user.getUid(), paramTag.TID, privacy, before); - } else if (paramSearch != null) { - title = "Блог " + user.getName() + ": " + StringEscapeUtils.escapeHtml4(paramSearch); - mids = messagesService.getUserSearch(user.getUid(), Utils.encodeSphinx(paramSearch), privacy, before); - } else { - title = "Блог " + user.getName(); - mids = messagesService.getUserBlog(user.getUid(), privacy, before); - } - } else if (paramShow.equals("recomm")) { - title = "Рекомендации " + user.getName(); - mids = messagesService.getUserRecommendations(user.getUid(), before); - } else if (paramShow.equals("photos")) { - title = "Фотографии " + user.getName(); - mids = messagesService.getUserPhotos(user.getUid(), privacy, before); - } else { - throw new HttpNotFoundException(); - } - - String head = "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"@" + - user.getName() + "\" href=\"//rss.juick.com/" + user.getName() + "/blog\"/>"; - if (paramTag != null && tagService.getTagNoIndex(paramTag.TID)) { - head += "<meta name=\"robots\" content=\"noindex,nofollow\"/>"; - } else if (before > 0 || paramShow != null) { - head += "<meta name=\"robots\" content=\"noindex\"/>"; - } - model.addAttribute("pageUrl", "http://juick.com/" + user.getName()); - model.addAttribute("title", title); - model.addAttribute("headers", head); - model.addAttribute("visitor", visitor); - model.addAttribute("user", user); - model.addAttribute("noindex", paramShow == null && before == 0); - fillUserModel(model, user, visitor); - model.addAttribute("paramTag", paramTag); - List<com.juick.Message> msgs = messagesService.getMessages(mids); - - if (visitor.getUid() != 0) { - List<Integer> blUIDs = userService.checkBL(visitor.getUid(), - msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList())); - msgs.forEach(m -> m.ReadOnly |= blUIDs.contains(m.getUser().getUid())); - } - model.addAttribute("msgs", msgs); - model.addAttribute("headers", head); - model.addAttribute("showAdv", - paramShow == null && before == 0 && paramSearch == null && visitor.getUid() == 0); - if (mids.size() >= 20) { - String nextpage = "?before=" + mids.get(mids.size() - 1); - if (paramShow != null) { - nextpage += "&show=" + paramShow; - } - if (paramSearch != null) { - nextpage += "&search=" + URLEncoder.encode(paramSearch, CharEncoding.UTF_8); - } - if (paramTag != null) { - nextpage += "&tag=" + URLEncoder.encode(paramTag.getName(), CharEncoding.UTF_8); - } - model.addAttribute("nextpage", nextpage); - } - UriComponents builder = ServletUriComponentsBuilder.fromCurrentRequestUri().build(); - String queryString = builder.getQuery(); - String requestURI = builder.toUri().getPath(); - if (sape != null && visitor.getUid() == 0 && queryString == null) { - String links = sape.getPageLinks(requestURI, sapeCookie).render(); - model.addAttribute("links", links); - } - model.addAttribute("isModerator", visitor.getUid() == 3694); - return "views/blog"; - } - - @GetMapping("/{uname}/tags") - protected String doGetTags(@PathVariable String uname, ModelMap model) throws IOException { - com.juick.User user = userService.getUserByName(uname); - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.isBanned()) { - throw new HttpNotFoundException(); - } - - model.addAttribute("title", "Теги " + user.getName()); - model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex,nofollow\"/>"); - model.addAttribute("visitor", visitor); - model.addAttribute("user", user); - fillUserModel(model, user, visitor); - model.addAttribute("tags", tagService.getUserTagStats(user.getUid()).stream() - .sorted((e1, e2) -> Integer.compare(e2.getUsageCount(), e1.getUsageCount())).map(t -> t.getTag().getName()).collect(Collectors.toList())); - - return "views/blog_tags"; - } - - @GetMapping("/{uname}/friends") - protected String doGetFriends(@PathVariable String uname, ModelMap model) throws IOException { - com.juick.User user = userService.getUserByName(uname); - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.isBanned()) { - throw new HttpNotFoundException(); - } - model.addAttribute("title", "Подписки " + user.getName()); - model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex\"/>"); - model.addAttribute("visitor", visitor); - model.addAttribute("user", user); - fillUserModel(model, user, visitor); - model.addAttribute("users", userService.getUserFriends(user.getUid())); - - return "views/users"; - } - - @GetMapping("/{uname}/readers") - protected String doGetReaders(@PathVariable String uname, ModelMap model) throws IOException { - com.juick.User user = userService.getUserByName(uname); - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.isBanned()) { - throw new HttpForbiddenException(); - } - model.addAttribute("title", "Читатели " + user.getName()); - model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex\"/>"); - model.addAttribute("visitor", visitor); - model.addAttribute("user", user); - fillUserModel(model, user, visitor); - model.addAttribute("users", userService.getUserReaders(user.getUid())); - - return "views/users"; - } - - @GetMapping("/{uname}/bl") - protected String doGetBL(@PathVariable String uname, ModelMap model) throws IOException { - com.juick.User user = userService.getUserByName(uname); - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.isBanned() || visitor.getUid() != user.getUid()) { - throw new HttpForbiddenException(); - } - model.addAttribute("title", "Черный список " + user.getName()); - model.addAttribute("headers", "<meta name=\"robots\" content=\"noindex\"/>"); - model.addAttribute("visitor", visitor); - model.addAttribute("user", user); - fillUserModel(model, user, visitor); - model.addAttribute("users", userService.getUserBLUsers(user.getUid())); - - return "views/users"; - } -} diff --git a/juick-www/src/main/java/com/juick/www/controllers/UserThread.java b/juick-www/src/main/java/com/juick/www/controllers/UserThread.java deleted file mode 100644 index 88217b9d..00000000 --- a/juick-www/src/main/java/com/juick/www/controllers/UserThread.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2008-2017, Juick - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package com.juick.www.controllers; - -import com.juick.Tag; -import com.juick.formatters.PlainTextFormatter; -import com.juick.server.util.HttpForbiddenException; -import com.juick.server.util.HttpNotFoundException; -import com.juick.server.util.UserUtils; -import com.juick.service.CrosspostService; -import com.juick.service.MessagesService; -import com.juick.service.UserService; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.inject.Inject; -import java.io.IOException; -import java.util.ArrayList; -import java.util.function.BooleanSupplier; -import java.util.List; -import java.util.stream.Collectors; - -/** - * - * @author Ugnich Anton - */ -@Controller -public class UserThread { - - @Inject - private MessagesService messagesService; - @Inject - private UserService userService; - @Inject - private CrosspostService crosspostService; - - @GetMapping("/{uname}/{mid}") - protected String threadAction(ModelMap model, - @PathVariable String uname, - @PathVariable int mid, - @RequestParam(required = false, value = "view") String paramView) throws IOException { - com.juick.User visitor = UserUtils.getCurrentUser(); - - if (!messagesService.canViewThread(mid, visitor.getUid())) { - throw new HttpForbiddenException(); - } - - com.juick.Message msg = messagesService.getMessage(mid); - - if (msg == null || msg.getUser().isBanned()) { - throw new HttpNotFoundException(); - } - - com.juick.User user = userService.getUserByName(uname); - if (user.getUid() == 0 || !msg.getUser().equals(user)) { - return String.format("redirect:/%s/%d", msg.getUser().getName(), mid); - } - msg.VisitorCanComment = visitor.getUid() > 0; - if (visitor.getUid() > 0) { - boolean isMsgAuthor = visitor.getUid() == msg.getUser().getUid(); - boolean isInBL = userService.isInBL(msg.getUser().getUid(), visitor.getUid()); - msg.VisitorCanComment = isMsgAuthor || !(msg.ReadOnly || isInBL); - } - model.addAttribute("msg", msg); - - boolean listview = false; - if (paramView != null) { - if (paramView.equals("list")) { - listview = true; - if (visitor.getUid() > 0) { - userService.setUserOptionInt(visitor.getUid(), "repliesview", 1); - } - } else if (paramView.equals("tree") && visitor.getUid() > 0) { - userService.setUserOptionInt(visitor.getUid(), "repliesview", 0); - } - } else if (visitor.getUid() > 0 && userService.getUserOptionInt(visitor.getUid(), "repliesview", 0) == 1) { - listview = true; - } - model.addAttribute("listview", listview); - String title = msg.getUser().getName() + ": " + msg.getTagsString(); - - model.addAttribute("title", title); - model.addAttribute("visitor", visitor); - String headers = "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"@" + msg.getUser().getName() + "\" href=\"//rss.juick.com/" + msg.getUser().getName() + "/blog\"/>"; - String pageUrl = "https://juick.com/" + msg.getUser().getName() + "/" + msg.getMid(); - if (paramView != null) { - headers += "<link rel=\"canonical\" href=\"" + pageUrl + "\"/>"; - } - if (msg.Hidden) { - headers += "<meta name=\"robots\" content=\"noindex\"/>"; - } - String cardType = StringUtils.isNotEmpty(msg.getAttachmentType()) ? "summary_large_image" : "summary"; - String msgImage = StringUtils.isNotEmpty(msg.getAttachmentType()) ? msg.getAttachment().getMedium().getUrl() - : "https://i.juick.com/a/" + msg.getUser().getUid() + ".png"; - model.addAttribute("ogtype", "article"); - String cardDescription = StringEscapeUtils.escapeHtml4(PlainTextFormatter.formatTwitterCard(msg)); - headers += "<meta name=\"twitter:card\" content=\"" + cardType + "\" />\n" + - "<meta name=\"twitter:site\" content=\"@juick\" />\n" + - "<meta property=\"og:url\" content=\"" + pageUrl + "\" />\n" + - "<meta property=\"og:title\" content=\"" + msg.getUser().getName() + " at Juick\" />\n" + - "<meta property=\"og:description\" content=\"" + cardDescription + "\" />\n" + - "<meta name=\"Description\" content=\"" + cardDescription + "\" />\n" + - "<meta property=\"og:image\" content=\"" + msgImage + "\" />"; - String twitterName = crosspostService.getTwitterName(msg.getUser().getUid()); - if (StringUtils.isNotEmpty(twitterName)) { - headers += "<meta name=\"twitter:creator\" content=\"@" + twitterName + "\" />\n"; - } - if (msg.getTags().size() > 0) { - headers += "<meta name=\"Keywords\" content=\"" + msg.getTags().stream().map(Tag::getName) - .collect(Collectors.joining(", ")) + "\" />\n"; - } - model.addAttribute("headers", headers); - model.addAttribute("contentStyle", "margin-left: 0; width: 100%"); - model.addAttribute("isModerator", visitor.getUid() == 3694); - model.addAttribute("visitorSubscribed", messagesService.isSubscribed(visitor.getUid(), msg.getMid())); - model.addAttribute("visitorInBL", userService.isInBL(msg.getUser().getUid(), visitor.getUid())); - model.addAttribute("recomm", messagesService.getMessageRecommendations(msg.getMid())); - List<com.juick.Message> replies = messagesService.getReplies(msg.getMid()); - - List<Integer> blUIDs = new ArrayList<>(); - for (int i = 0; i < replies.size(); i++) { - com.juick.Message reply = replies.get(i); - if (reply.getUser().getUid() != msg.getUser().getUid() - && !blUIDs.contains(reply.getUser().getUid())) { - blUIDs.add(reply.getUser().getUid()); - } - if (reply.getReplyto() > 0) { - boolean added = false; - for (int n = 0; n < replies.size(); n++) { - if (replies.get(n).getRid() == reply.getReplyto()) { - replies.get(n).childs.add(reply); - added = true; - break; - } - } - if (!added) { - reply.setReplyto(0); - } - } - - reply.VisitorCanComment = visitor.getUid() > 0; - if (visitor.getUid() > 0) { - boolean isMsgAuthor = visitor.getUid() == msg.getUser().getUid(); - boolean isReplyAuthor = visitor.getUid() == reply.getUser().getUid(); - BooleanSupplier isInBL2 = () -> userService.checkBL(visitor.getUid(), blUIDs).contains(reply.getUser().getUid()); - reply.VisitorCanComment = isMsgAuthor || (!msg.ReadOnly && (isReplyAuthor || !isInBL2.getAsBoolean())); - } - } - - boolean foldable = false; - if (replies.size() > 10) { - for (int i = 0; i < replies.size() - 1; i++) { - if (replies.get(i).getChildsCount() > 1) { - foldable = true; - break; - } - } - } - model.addAttribute("replies", replies); - model.addAttribute("foldable", foldable); - return "views/thread"; - } - - // when message id is not fit to int - @ExceptionHandler(NumberFormatException.class) - public ResponseEntity<String> notFoundAction() { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } -} diff --git a/juick-www/src/main/java/com/juick/www/controllers/XMPPPost.java b/juick-www/src/main/java/com/juick/www/controllers/XMPPPost.java deleted file mode 100644 index 51b9d964..00000000 --- a/juick-www/src/main/java/com/juick/www/controllers/XMPPPost.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2008-2017, Juick - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.www.controllers; - -import com.juick.server.util.HttpBadRequestException; -import com.juick.server.util.HttpForbiddenException; -import com.juick.server.util.HttpUtils; -import com.juick.server.util.UserUtils; -import com.juick.www.WebApp; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.multipart.MultipartFile; -import rocks.xmpp.addr.Jid; -import rocks.xmpp.core.stanza.model.Message; -import rocks.xmpp.extensions.oob.model.x.OobX; - -import javax.inject.Inject; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; - -/** - * Created by vitalyster on 08.12.2016. - */ -@Controller -public class XMPPPost { - private final static Logger logger = LoggerFactory.getLogger(XMPPPost.class); - - @Inject - private WebApp webApp; - - @PostMapping("/post2") - public String doPostMessage(@RequestParam(name = "body") String bodyParam, - @RequestParam(required = false) String img, - @RequestParam(required = false) String referer, - @RequestParam(required = false) MultipartFile attach) throws IOException { - - com.juick.User visitor = UserUtils.getCurrentUser(); - if (visitor.getUid() == 0 || visitor.isBanned()) { - throw new HttpForbiddenException(); - } - String body = bodyParam.replace("\r", StringUtils.EMPTY); - - String attachmentFName = HttpUtils.receiveMultiPartFile(attach, webApp.getTmpDir()); - - if (StringUtils.isBlank(attachmentFName) && img != null && img.length() > 10) { - try { - URL imgUrl = new URL(img); - attachmentFName = HttpUtils.downloadImage(imgUrl, webApp.getTmpDir()); - } catch (Exception e) { - logger.error("DOWNLOAD ERROR", e); - throw new HttpBadRequestException(); - } - } - Message msg = new Message(); - msg.setType(Message.Type.CHAT); - msg.setFrom(Jid.of(String.valueOf(visitor.getUid()), "uid.juick.com", "perl")); - msg.setTo(Jid.of("juick@juick.com/Juick")); - msg.setBody(body); - try { - if (StringUtils.isNotEmpty(attachmentFName)) { - String attachmentUrl = String.format("juick://%s", attachmentFName); - msg.addExtension(new OobX(new URI(attachmentUrl), "!!!!Juick!!")); - } - webApp.getXmpp().sendMessage(msg); - } catch (URISyntaxException e1) { - logger.warn("attachment error", e1); - } - if (StringUtils.isBlank(referer) || referer.substring(0, 21).equals("http://juick.com/post") - || referer.substring(0, 22).equals("https://juick.com/post")) { - return "redirect:/?show=my"; - } - return "redirect:" + referer; - } -} |