From d233943fc29508dc37714852b11b96b0b46b55d9 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 24 Nov 2016 21:38:52 +0300 Subject: juick-api: now on spring-webmvc --- .../java/com/juick/api/controllers/Messages.java | 248 +++++++++++++++++ .../com/juick/api/controllers/Notifications.java | 138 ++++++++++ .../java/com/juick/api/controllers/Others.java | 70 +++++ .../main/java/com/juick/api/controllers/PM.java | 130 +++++++++ .../main/java/com/juick/api/controllers/Post.java | 304 +++++++++++++++++++++ .../com/juick/api/controllers/SkypeEndpoint.java | 30 ++ .../com/juick/api/controllers/Subscriptions.java | 69 +++++ .../com/juick/api/controllers/TelegramWebhook.java | 77 ++++++ .../main/java/com/juick/api/controllers/Users.java | 159 +++++++++++ 9 files changed, 1225 insertions(+) create mode 100644 juick-api/src/main/java/com/juick/api/controllers/Messages.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/Notifications.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/Others.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/PM.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/Post.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/SkypeEndpoint.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/TelegramWebhook.java create mode 100644 juick-api/src/main/java/com/juick/api/controllers/Users.java (limited to 'juick-api/src/main/java/com/juick/api/controllers') diff --git a/juick-api/src/main/java/com/juick/api/controllers/Messages.java b/juick-api/src/main/java/com/juick/api/controllers/Messages.java new file mode 100644 index 00000000..a6bd3f6d --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/Messages.java @@ -0,0 +1,248 @@ +package com.juick.api.controllers; + +import com.juick.Tag; +import com.juick.User; +import com.juick.api.ApiServer; +import com.juick.api.util.HttpBadRequestException; +import com.juick.api.util.HttpForbiddenException; +import com.juick.api.util.HttpNotFoundException; +import com.juick.server.helpers.Status; +import com.juick.service.MessagesService; +import com.juick.service.TagService; +import com.juick.service.UserService; +import org.apache.commons.lang3.math.NumberUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.stanza.model.Message; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * @author ugnich + */ +@Controller +@ResponseBody +public class Messages { + private static final Logger logger = LoggerFactory.getLogger(Messages.class); + + @Inject + private MessagesService messagesService; + @Inject + private UserService userService; + @Inject + private TagService tagService; + @Inject + ApiServer apiServer; + + // TODO: serialize image urls + + @RequestMapping(value = "/home", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGetHome(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + int before_mid = NumberUtils.toInt(request.getParameter("before_mid"), 0); + List mids = messagesService.getMyFeed(vuid, before_mid); + return messagesService.getMessages(mids); + } + + @RequestMapping(value = "/messages", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGet(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + int before_mid = NumberUtils.toInt(request.getParameter("before_mid"), 0); + String uname = request.getParameter("uname"); + String popular = request.getParameter("popular"); + String media = request.getParameter("media"); + String tag = request.getParameter("tag"); + List mids; + if (!StringUtils.isEmpty(uname)) { + User user = userService.getUserByName(uname); + if (user != null) { + if (!StringUtils.isEmpty(media)) { + mids = messagesService.getUserPhotos(user.getUid(), 0, before_mid); + } else if (!StringUtils.isEmpty(tag)) { + Tag tagObject = tagService.getTag(tag, false); + if (tagObject != null) { + mids = messagesService.getUserTag(user.getUid(), tagObject.TID, 0, before_mid); + } else { + throw new HttpNotFoundException(); + } + } else { + mids = messagesService.getUserBlog(user.getUid(), 0, before_mid); + } + } else { + throw new HttpNotFoundException(); + } + } else { + if (!StringUtils.isEmpty(popular)) { + mids = messagesService.getPopular(vuid, before_mid); + } else if (!StringUtils.isEmpty(media)) { + mids = messagesService.getPhotos(vuid, before_mid); + } else if (!StringUtils.isEmpty(tag)) { + Tag tagObject = tagService.getTag(tag, false); + if (tagObject != null) { + mids = messagesService.getTag(tagObject.TID, vuid, before_mid, 20); + } else { + throw new HttpNotFoundException(); + } + } else { + mids = messagesService.getAll(vuid, before_mid); + } + } + return messagesService.getMessages(mids); + } + + @RequestMapping(value = "/thread", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doThreadGet(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + int mid = NumberUtils.toInt(request.getParameter("mid"), 0); + com.juick.Message msg = messagesService.getMessage(mid); + if (msg != null) { + if (!messagesService.canViewThread(mid, vuid)) { + throw new HttpForbiddenException(); + } else { + List replies = messagesService.getReplies(mid); + replies.add(0, msg); + return replies; + } + } + throw new HttpNotFoundException(); + } + + @RequestMapping(value = "/messages/recommended", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGetRecommended(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + int before_mid = NumberUtils.toInt(request.getParameter("before_mid"), 0); + + List mids = messagesService.getUserRecommendations(vuid, before_mid); + if (mids != null && !mids.isEmpty()) { + List msgs = messagesService.getMessages(mids); + if (msgs != null && !msgs.isEmpty()) { + return msgs; + } else { + throw new HttpForbiddenException(); + } + } + throw new HttpNotFoundException(); + } + + @RequestMapping(value = "/messages/set_privacy", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @ResponseBody + public Status doSetPrivacy(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + int mid = NumberUtils.toInt(request.getParameter("mid"), 0); + com.juick.User user = messagesService.getMessageAuthor(mid); + if (user != null && user.getUid() == vuid && messagesService.setMessagePrivacy(mid)) { + return new Status("ok"); + } else { + throw new HttpBadRequestException(); + } + } + + @RequestMapping(value = "/messages/set_popular", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public Status doSetPopular(HttpServletRequest request) { + int mid = NumberUtils.toInt(request.getParameter("mid"), 0); + int popular = NumberUtils.toInt(request.getParameter("popular"), 0); + + if (mid > 0) { + boolean ret = messagesService.setMessagePopular(mid, popular); + + if (ret && popular == 2) { + try { + com.juick.Message m = messagesService.getMessage(mid); + if (m != null) { + Message msg = new Message(); + msg.setFrom(Jid.of("juick@juick.com")); + msg.setTo(Jid.of("crosspost.juick.com")); + m.setUser(userService.getUserByUID(11574).get()); + msg.addExtension(m); + + msg.setTo(Jid.of("twitter@crosspost.juick.com")); + apiServer.getXmpp().send(msg); + msg.setTo(Jid.of("fb@crosspost.juick.com")); + apiServer.getXmpp().send(msg); + msg.setTo(Jid.of("vk@crosspost.juick.com")); + apiServer.getXmpp().send(msg); + } else { + throw new Exception("Message not found"); + } + } catch (Exception e) { + logger.error("SETPOPULAR ERROR", e); + } + } + return new Status("ok"); + } + throw new HttpBadRequestException(); + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/Notifications.java b/juick-api/src/main/java/com/juick/api/controllers/Notifications.java new file mode 100644 index 00000000..0d0d0965 --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/Notifications.java @@ -0,0 +1,138 @@ +package com.juick.api.controllers; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.juick.Message; +import com.juick.User; +import com.juick.api.util.HttpBadRequestException; +import com.juick.api.util.HttpForbiddenException; +import com.juick.server.helpers.Status; +import com.juick.server.helpers.TokensList; +import com.juick.service.MessagesService; +import com.juick.service.PushQueriesService; +import com.juick.service.SubscriptionService; +import com.juick.service.UserService; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Created by vitalyster on 24.10.2016. + */ +@Controller +@ResponseBody +public class Notifications { + + @Inject + PushQueriesService pushQueriesService; + @Inject + UserService userService; + @Inject + MessagesService messagesService; + @Inject + SubscriptionService subscriptionService; + + @RequestMapping(value = "/notifications", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGet(HttpServletRequest request) { + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + User visitor = userService.getUserByUID(vuid).orElse(new User()); + if ((visitor.getUid() == 0) || !(visitor.getName().equals("juick"))) { + throw new HttpForbiddenException(); + } + String type = request.getParameter("type"); + int uid = NumberUtils.toInt(request.getParameter("uid"), 0); + int mid = NumberUtils.toInt(request.getParameter("mid"), 0); + if (uid > 0) { + switch (type) { + case "gcm": + return pushQueriesService.getAndroidRegID(uid); + case "apns": + return pushQueriesService.getAPNSToken(uid); + case "mpns": + return pushQueriesService.getWinPhoneURL(uid); + default: + throw new HttpBadRequestException(); + } + + } else { + if (mid > 0) { + Message msg = messagesService.getMessage(mid); + if (msg != null) { + List users; + if (msg.getRid() > 0) { + users = subscriptionService.getUsersSubscribedToComments(mid, msg.getUser().getUid()); + } else { + users = subscriptionService.getSubscribedUsers(msg.getUser().getUid(), mid); + } + + List uids = users.stream().map(User::getUid).collect(Collectors.toList()); + + switch (type) { + case "gcm": + return pushQueriesService.getAndroidTokens(uids); + case "apns": + return pushQueriesService.getAPNSTokens(uids); + case "mpns": + return pushQueriesService.getWindowsTokens(uids); + default: + throw new HttpBadRequestException(); + } + } + } + } + throw new HttpBadRequestException(); + } + + @RequestMapping(value = "/notifications", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public Status doDelete(HttpServletRequest request, @RequestBody String requestBody) throws IOException { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + User visitor = userService.getUserByUID(vuid).orElse(new User()); + if ((visitor.getUid() == 0) || !(visitor.getName().equals("juick"))) { + throw new HttpForbiddenException(); + } + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); + TokensList list = mapper.readValue(requestBody, TokensList.class); + list.getTokens().forEach(t -> pushQueriesService.deleteAPNSToken(t)); + return new Status("ok"); + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/Others.java b/juick-api/src/main/java/com/juick/api/controllers/Others.java new file mode 100644 index 00000000..ad620444 --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/Others.java @@ -0,0 +1,70 @@ +package com.juick.api.controllers; + +import com.juick.User; +import com.juick.api.util.HttpForbiddenException; +import com.juick.api.util.HttpNotFoundException; +import com.juick.server.helpers.PrivateChats; +import com.juick.service.PMQueriesService; +import com.juick.service.UserService; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * + * @author ugnich + */ +@Controller +@ResponseBody +public class Others { + + @Inject + PMQueriesService pmQueriesService; + @Inject + UserService userService; + + @RequestMapping(value = "groups_pms", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public PrivateChats doGetGroupsPMs(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + int cnt = 5; + try { + String cntStr = request.getParameter("cnt"); + cnt = Integer.parseInt(cntStr); + if (cnt < 3) { + cnt = 3; + } + if (cnt > 10) { + cnt = 10; + } + } catch (Exception e) { + } + + List lastconv = pmQueriesService.getPMLastConversationsUsers(vuid, cnt); + if (lastconv != null && !lastconv.isEmpty()) { + PrivateChats pms = new PrivateChats(); + pms.setUsers(lastconv); + return pms; + } + throw new HttpNotFoundException(); + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/PM.java b/juick-api/src/main/java/com/juick/api/controllers/PM.java new file mode 100644 index 00000000..3d9893b1 --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/PM.java @@ -0,0 +1,130 @@ +package com.juick.api.controllers; + +import com.juick.api.ApiServer; +import com.juick.api.util.HttpBadRequestException; +import com.juick.api.util.HttpForbiddenException; +import com.juick.service.PMQueriesService; +import com.juick.service.UserService; +import com.juick.util.UserUtils; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.stanza.model.Message; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * + * @author ugnich + */ +@Controller +@ResponseBody +public class PM { + + @Inject + UserService userService; + @Inject + PMQueriesService pmQueriesService; + @Inject + ApiServer apiServer; + + @RequestMapping(value = "/pm", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGetPM(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + String uname = request.getParameter("uname"); + int uid = 0; + if (uname != null && uname.matches("^[a-zA-Z0-9\\-]{2,16}$")) { + uid = userService.getUIDbyName(uname); + } + + if (uid == 0) { + throw new HttpBadRequestException(); + } + + return pmQueriesService.getPMMessages(vuid, uid); + } + + @RequestMapping(value = "/pm", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public com.juick.Message doPostPM(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + String uname = request.getParameter("uname"); + int uid = 0; + if (UserUtils.checkUserNameValid(uname)) { + uid = userService.getUIDbyName(uname); + } + + String body = request.getParameter("body"); + if (uid == 0 || body == null || body.length() < 1 || body.length() > 10240) { + throw new HttpBadRequestException(); + } + + if (userService.isInBLAny(uid, vuid)) { + throw new HttpForbiddenException(); + } + + if (pmQueriesService.createPM(vuid, uid, body)) { + 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(userService.getUserByUID(vuid).get()); + jmsg.setText(body); + msg.addExtension(jmsg); + apiServer.getXmpp().send(msg); + + msg.setTo(Jid.of(String.format("%d@ws.juick.com", uid))); + apiServer.getXmpp().send(msg); + + List 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(vuid, 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); + } + apiServer.getXmpp().send(mm); + } + return jmsg; + + } + throw new HttpBadRequestException(); + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/Post.java b/juick-api/src/main/java/com/juick/api/controllers/Post.java new file mode 100644 index 00000000..fb1914e9 --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/Post.java @@ -0,0 +1,304 @@ +package com.juick.api.controllers; + +import com.juick.Tag; +import com.juick.api.ApiServer; +import com.juick.api.util.HttpBadRequestException; +import com.juick.api.util.HttpForbiddenException; +import com.juick.api.util.HttpNotFoundException; +import com.juick.api.util.HttpUtils; +import com.juick.service.MessagesService; +import com.juick.service.SubscriptionService; +import com.juick.service.TagService; +import com.juick.service.UserService; +import net.coobird.thumbnailator.Thumbnails; +import org.apache.commons.lang3.math.NumberUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import rocks.xmpp.addr.Jid; +import rocks.xmpp.core.session.XmppSession; +import rocks.xmpp.core.stanza.model.Message; +import rocks.xmpp.extensions.nick.model.Nickname; +import rocks.xmpp.extensions.oob.model.x.OobX; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by vt on 24/11/2016. + */ +@Controller +@ResponseBody +public class Post { + private static Logger logger = LoggerFactory.getLogger(ApiServer.class); + + @Inject + UserService userService; + @Inject + ApiServer apiServer; + @Inject + TagService tagService; + @Inject + MessagesService messagesService; + @Inject + SubscriptionService subscriptionService; + + @RequestMapping(value = "/post", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + protected com.juick.Message doPost(HttpServletRequest request) throws IOException { + String uri = request.getRequestURI(); + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + switch (uri) { + case "/post": + int mid = NumberUtils.toInt(request.getParameter("mid"), 0); + if (mid == 0) { + return doPostMessage(request, apiServer.getXmpp(), vuid); + } else { + return doPostComment(request, apiServer.getXmpp(), vuid); + } + default: + throw new HttpBadRequestException(); + } + } + + public com.juick.Message doPostMessage(HttpServletRequest request, XmppSession xmpp, int vuid) throws IOException { + String body = request.getParameter("body"); + if (body == null || body.length() < 1 || body.length() > 4096) { + throw new HttpBadRequestException(); + } + body = body.replace("\r", ""); + + String tagsStr = request.getParameter("tags"); + List tags = new ArrayList<>(); + String tagsArr[] = new String[1]; + if (tagsStr != null && !tagsStr.isEmpty()) { + tagsArr = tagsStr.split("[ \\,]"); + for (int i = 0; i < tagsArr.length; i++) { + if (tagsArr[i].startsWith("*")) { + tagsArr[i] = tagsArr[i].substring(1); + } + if (tagsArr[i].length() > 64) { + tagsArr[i] = tagsArr[i].substring(0, 64); + } + } + tags = tagService.getTags(tagsArr, true); + while (tags.size() > 5) { + tags.remove(5); + } + } + + String attachmentFName = null; + try { + attachmentFName = HttpUtils.receiveMultiPartFile(request, "attach"); + } catch (Exception e) { + logger.error("MULTIPART ERROR", e); + throw new HttpBadRequestException(); + } + + String paramImg = request.getParameter("img"); + if (attachmentFName == null && paramImg != null && paramImg.length() > 10) { + try { + URL imgUrl = new URL(paramImg); + attachmentFName = HttpUtils.downloadImage(imgUrl); + } catch (Exception e) { + logger.error("DOWNLOAD ERROR", e); + throw new HttpBadRequestException(); + } + } + + String attachmentType = attachmentFName != null ? attachmentFName.substring(attachmentFName.length() - 3) : null; + int mid = messagesService.createMessage(vuid, body, attachmentType, tags); + subscriptionService.subscribeMessage(mid, vuid); + com.juick.Message jmsg = messagesService.getMessage(mid); + if (xmpp != null) { + Message xmsg = new Message(); + xmsg.setFrom(Jid.of("juick@juick.com")); + xmsg.setType(Message.Type.CHAT); + xmsg.setThread("juick-" + mid); + + xmsg.addExtension(jmsg); + xmsg.addExtension(new Nickname("@" + jmsg.getUser().getName())); + + if (attachmentFName != null) { + String fname = mid + "." + attachmentType; + String attachmentURL = "http://i.juick.com/photos-1024/" + fname; + + Path origName = Paths.get(apiServer.imgDir, "p", fname); + Files.move(Paths.get(apiServer.tmpDir, attachmentFName), origName); + Thumbnails.of(origName.toFile()).size(1024, 1024).outputQuality(0.9) + .toFile(Paths.get(apiServer.imgDir, "photos-1024", fname).toFile()); + Thumbnails.of(origName.toFile()).size(512, 512).outputQuality(0.9) + .toFile(Paths.get(apiServer.imgDir, "photos-512", fname).toFile()); + Thumbnails.of(origName.toFile()).size(160, 120).outputQuality(0.9) + .toFile(Paths.get(apiServer.imgDir, "ps", fname).toFile()); + + body = attachmentURL + "\n" + body; + try { + OobX xoob = new OobX(new URI(attachmentURL)); + xmsg.addExtension(xoob); + } catch (URISyntaxException e) { + logger.error("invalid uri: " + attachmentURL, e); + } + } + + String tagsStr2 = ""; + for (String tag : tagsArr) { + tagsStr2 += " *" + tag; + } + xmsg.setBody("@" + jmsg.getUser().getName() + ":" + tagsStr2 + "\n" + body + "\n\n#" + mid + " http://juick.com/" + mid); + + xmsg.setTo(Jid.of("juick@s2s.juick.com")); + xmpp.send(xmsg); + + xmsg.setTo(Jid.of("juick@ws.juick.com")); + xmpp.send(xmsg); + + xmsg.setTo(Jid.of("juick@push.juick.com")); + xmpp.send(xmsg); + + xmsg.setTo(Jid.of("twitter@crosspost.juick.com")); + xmpp.send(xmsg); + xmsg.setTo(Jid.of("fb@crosspost.juick.com")); + xmpp.send(xmsg); + + xmsg.setTo(Jid.of("jubo@nologin.ru")); + xmpp.send(xmsg); + } else { + logger.error("XMPP unavailable"); + } + return jmsg; + } + + public com.juick.Message doPostComment(HttpServletRequest request, XmppSession xmpp, int vuid) + throws IOException { + int mid = NumberUtils.toInt(request.getParameter("mid"), 0); + if (mid == 0) { + throw new HttpBadRequestException(); + } + com.juick.Message msg = messagesService.getMessage(mid); + if (msg == null) { + throw new HttpNotFoundException(); + } + + int rid = NumberUtils.toInt(request.getParameter("rid"), 0); + com.juick.Message reply = null; + if (rid > 0) { + reply = messagesService.getReply(mid, rid); + if (reply == null) { + throw new HttpNotFoundException(); + } + } + + String body = request.getParameter("body"); + if (body == null || body.length() < 1 || body.length() > 4096) { + throw new HttpBadRequestException(); + } + body = body.replace("\r", ""); + + if ((msg.ReadOnly && msg.getUser().getUid() != vuid) || userService.isInBLAny(msg.getUser().getUid(), vuid) + || (reply != null && userService.isInBLAny(reply.getUser().getUid(), vuid))) { + throw new HttpForbiddenException(); + } + + String attachmentFName = null; + try { + attachmentFName = HttpUtils.receiveMultiPartFile(request, "attach"); + } catch (Exception e) { + logger.error("MULTIPART ERROR", e); + throw new HttpBadRequestException(); + } + + String paramImg = request.getParameter("img"); + if (attachmentFName == null && paramImg != null && paramImg.length() > 10) { + try { + attachmentFName = HttpUtils.downloadImage(new URL(paramImg)); + } catch (Exception e) { + logger.error("DOWNLOAD ERROR", e); + throw new HttpBadRequestException(); + } + } + + String attachmentType = attachmentFName != null ? attachmentFName.substring(attachmentFName.length() - 3) : null; + int ridnew = messagesService.createReply(mid, rid, vuid, body, attachmentType); + subscriptionService.subscribeMessage(mid, vuid); + + com.juick.Message jmsg = messagesService.getReply(mid, ridnew); + + if (xmpp != null) { + Message xmsg = new Message(); + xmsg.setFrom(Jid.of("juick@juick.com")); + xmsg.setType(Message.Type.CHAT); + xmsg.setThread("juick-" + mid); + xmsg.addExtension(jmsg); + + String quote = reply != null ? reply.getText() : msg.getText(); + if (quote.length() >= 50) { + quote = quote.substring(0, 47) + "..."; + } + + xmsg.addExtension(new Nickname("@" + jmsg.getUser().getName())); + + if (attachmentFName != null) { + String fname = mid + "-" + ridnew + "." + attachmentType; + String attachmentURL = "http://i.juick.com/photos-1024/" + fname; + + Path origName = Paths.get(apiServer.imgDir, "p", fname); + Files.move(Paths.get(apiServer.tmpDir, attachmentFName), origName); + Thumbnails.of(origName.toFile()).size(1024, 1024).outputQuality(0.9) + .toFile(Paths.get(apiServer.imgDir, "photos-1024", fname).toFile()); + Thumbnails.of(origName.toFile()).size(512, 512).outputQuality(0.9) + .toFile(Paths.get(apiServer.imgDir, "photos-512", fname).toFile()); + Thumbnails.of(origName.toFile()).size(160, 120).outputQuality(0.9) + .toFile(Paths.get(apiServer.imgDir, "ps", fname).toFile()); + + body = attachmentURL + "\n" + body; + try { + xmsg.addExtension(new OobX(new URI(attachmentURL))); + } catch (URISyntaxException e) { + logger.error("invalid uri: " + attachmentURL, e); + } + } + + xmsg.setBody("Reply by @" + jmsg.getUser().getName() + ":\n>" + quote + "\n" + body + "\n\n#" + + mid + "/" + ridnew + " http://juick.com/" + mid + "#" + ridnew); + + xmsg.setTo(Jid.of("juick@s2s.juick.com")); + xmpp.send(xmsg); + + xmsg.setTo(Jid.of("juick@ws.juick.com")); + xmpp.send(xmsg); + + xmsg.setTo(Jid.of("juick@push.juick.com")); + xmpp.send(xmsg); + } else { + logger.error("XMPP unavailable"); + } + return jmsg; + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/SkypeEndpoint.java b/juick-api/src/main/java/com/juick/api/controllers/SkypeEndpoint.java new file mode 100644 index 00000000..2a5c6c1e --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/SkypeEndpoint.java @@ -0,0 +1,30 @@ +package com.juick.api.controllers; + +import org.msbotframework4j.builder.bot.AbstractBot; +import org.msbotframework4j.core.model.Message; +import org.msbotframework4j.logging.BotLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.io.IOException; + +/** + * Created by vitalyster on 18.07.2016. + */ +@Controller +public class SkypeEndpoint extends AbstractBot { + private static final Logger logger = LoggerFactory.getLogger(SkypeEndpoint.class); + @Override + protected Message onMessage(Message request, BotLogger logger) { + return null; + } + + @RequestMapping(value = "/skypebotendpoint", method = RequestMethod.POST) + public void doPost(@RequestBody String body) throws IOException { + logger.info(body); + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java b/juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java new file mode 100644 index 00000000..5426f853 --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java @@ -0,0 +1,69 @@ +package com.juick.api.controllers; + +import com.juick.Message; +import com.juick.User; +import com.juick.api.util.HttpBadRequestException; +import com.juick.api.util.HttpForbiddenException; +import com.juick.service.MessagesService; +import com.juick.service.SubscriptionService; +import com.juick.service.UserService; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.List; + +/** + * Created by vitalyster on 24.10.2016. + */ +@Controller +@ResponseBody +public class Subscriptions { + @Inject + UserService userService; + @Inject + SubscriptionService subscriptionService; + @Inject + MessagesService messagesService; + + @RequestMapping(value = "/subscriptions", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGet(HttpServletRequest request) throws IOException { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + User visitor = userService.getUserByUID(vuid).orElse(new User()); + if ((visitor.getUid() == 0) && !(visitor.getName().equals("juick"))) { + throw new HttpForbiddenException(); + } + int uid = NumberUtils.toInt(request.getParameter("uid"), 0); + int mid = NumberUtils.toInt(request.getParameter("mid"), 0); + if (uid > 0) { + return subscriptionService.getSubscribedUsers(uid, mid); + } else { + // thread + Message msg = messagesService.getMessage(mid); + if (msg != null) { + return subscriptionService.getUsersSubscribedToComments(mid, msg.getUser().getUid()); + } + } + throw new HttpBadRequestException(); + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/TelegramWebhook.java b/juick-api/src/main/java/com/juick/api/controllers/TelegramWebhook.java new file mode 100644 index 00000000..8b491167 --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/TelegramWebhook.java @@ -0,0 +1,77 @@ +package com.juick.api.controllers; + +import com.juick.User; +import com.juick.api.TGBot; +import com.juick.service.TelegramService; +import com.juick.service.UserService; +import com.pengrad.telegrambot.BotUtils; +import com.pengrad.telegrambot.model.Message; +import com.pengrad.telegrambot.model.Update; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.inject.Inject; +import java.util.List; + +/** + * Created by vt on 24/11/2016. + */ +@Controller +public class TelegramWebhook { + private static Logger logger = LoggerFactory.getLogger(TelegramWebhook.class); + @Inject + UserService usersService; + @Inject + TelegramService telegramService; + @Inject + TGBot tgBot; + + + @RequestMapping(value = "/tlgmbtwbhk", method = RequestMethod.POST) + public void processUpdate(@RequestBody String updateData) { + Update update = BotUtils.parseUpdate(updateData); + Message message = update.message(); + if (update.message() == null) { + message = update.editedMessage(); + if (message == null) { + logger.error("error parsing telegram update: " + update.toString()); + return; + } + } + logger.info(String.format("got telegram msg %s", message.toString())); + User user_from = usersService.getUserByUID(telegramService.getUser(message.chat().id())).orElse(new User()); + logger.info(String.format("Found juick user %d", user_from.getUid())); + + List chats = telegramService.getChats(); + String username = message.from().username(); + if (username == null) { + username = message.from().firstName(); + } + if (!chats.contains(message.chat().id())) { + telegramService.addChat(message.chat().id()); + logger.info("added chat with " + username); + telegramService.createTelegramUser(message.from().id(), username); + tgBot.telegramSignupNotify(message.from().id().longValue(), usersService.getSignUpHashByTelegramID(message.from().id().longValue(), username)); + } else { + if (user_from.getUid() == 0) { + tgBot.telegramSignupNotify(message.from().id().longValue(), usersService.getSignUpHashByTelegramID(message.from().id().longValue(), username)); + } else { + String text = message.text(); + if (text != null) { + if (text.equalsIgnoreCase("/login")) { + String msg = String.format("Hi, %s!\nTap to log in", user_from.getName()); + String msgUrl = "http://juick.com/login?" + usersService.getHashByUID(user_from.getUid()); + tgBot.telegramNotify(message.from().id().longValue(), msg, msgUrl); + } /* else { + ProtocolReply reply = protocol.getReply(user_from, text); + telegramNotify(message.from().id().longValue(), reply.getDescription(), null); + }*/ + } + } + } + } +} diff --git a/juick-api/src/main/java/com/juick/api/controllers/Users.java b/juick-api/src/main/java/com/juick/api/controllers/Users.java new file mode 100644 index 00000000..8b1bc6cd --- /dev/null +++ b/juick-api/src/main/java/com/juick/api/controllers/Users.java @@ -0,0 +1,159 @@ +package com.juick.api.controllers; + +import com.juick.User; +import com.juick.api.util.HttpForbiddenException; +import com.juick.api.util.HttpNotFoundException; +import com.juick.service.UserService; +import com.juick.util.UserUtils; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +/** + * + * @author ugnich + */ +@Controller +@ResponseBody +public class Users { + + @Inject + UserService userService; + + @RequestMapping(value = "/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGetUsers(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + List users = new ArrayList<>(); + + String punames[] = request.getParameterValues("uname"); + if (punames != null) { + ArrayList unames = new ArrayList<>(Arrays.asList(punames)); + Iterator i = unames.iterator(); + while (i.hasNext()) { + if (!i.next().matches("^[a-zA-Z0-9\\-]{2,16}$")) { + i.remove(); + } + } + if (!unames.isEmpty() && unames.size() < 20) { + users.addAll(userService.getUsersByName(unames)); + } + } + + String pjids[] = request.getParameterValues("jid"); + if (pjids != null) { + List jids = new ArrayList<>(Arrays.asList(pjids)); + Iterator ii = jids.iterator(); + while (ii.hasNext()) { + if (!ii.next().matches("^[a-zA-Z0-9\\-\\_\\@\\.]{6,64}$")) { + ii.remove(); + } + } + if (!jids.isEmpty() && jids.size() < 20) { + users.addAll(userService.getUsersByJID(jids)); + } + } + + if (!users.isEmpty()) { + return users; + } + throw new HttpNotFoundException(); + } + + @RequestMapping(value = "/users/read", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGetUserRead(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + int uid = 0; + String uname = request.getParameter("uname"); + if (uname == null) { + uid = vuid; + } else { + if (UserUtils.checkUserNameValid(uname)) { + com.juick.User u = userService.getUserByName(uname); + if (u != null && u.getUid() > 0) { + uid = u.getUid(); + } + } + } + + if (uid > 0) { + List uids = userService.getUserRead(uid); + if (uids.size() > 0) { + List users = userService.getUsersByID(uids); + if (users.size() > 0) { + return users; + } + } + } + throw new HttpNotFoundException(); + } + + @RequestMapping(value = "/users/readers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public List doGetUserReaders(HttpServletRequest request) { + // TODO: use spring-security + String auth = request.getHeader("Authorization"); + int vuid = userService.getUIDByHttpAuth(auth); + if (vuid == -1) { + throw new HttpForbiddenException(); + } + if (vuid == 0) { + String hash = request.getParameter("hash"); + if (hash != null && hash.length() == 16) { + vuid = userService.getUIDbyHash(hash); + } + } + if (vuid == 0) { + throw new HttpForbiddenException(); + } + int uid = 0; + String uname = request.getParameter("uname"); + if (uname == null) { + uid = vuid; + } else { + if (UserUtils.checkUserNameValid(uname)) { + com.juick.User u = userService.getUserByName(uname); + if (u != null && u.getUid() > 0) { + uid = u.getUid(); + } + } + } + + if (uid > 0) { + return userService.getUserReaders(uid); + } + throw new HttpNotFoundException(); + } +} -- cgit v1.2.3