aboutsummaryrefslogtreecommitdiff
path: root/juick-server/src/main/java/com/juick/api/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'juick-server/src/main/java/com/juick/api/controllers')
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/ApiController.java54
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/Messages.java181
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/MessengerWebhook.java62
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/Notifications.java190
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/Others.java66
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/PM.java127
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/Post.java281
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/Service.java74
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/SkypeEndpoint.java47
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/Tags.java54
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/TelegramWebhook.java48
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/Users.java125
-rw-r--r--juick-server/src/main/java/com/juick/api/controllers/util/JsonpAdvice.java31
13 files changed, 1340 insertions, 0 deletions
diff --git a/juick-server/src/main/java/com/juick/api/controllers/ApiController.java b/juick-server/src/main/java/com/juick/api/controllers/ApiController.java
new file mode 100644
index 00000000..0929d1ea
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/ApiController.java
@@ -0,0 +1,54 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.Status;
+import com.juick.api.WebsocketManager;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.inject.Inject;
+import java.net.URI;
+
+/**
+ * Created by vitalyster on 25.07.2016.
+ */
+@ApiIgnore
+@RestController
+public class ApiController {
+ @Inject
+ private WebsocketManager wsHandler;
+
+ @RequestMapping(value = "/", method = RequestMethod.GET, headers = "Connection!=Upgrade")
+ public ResponseEntity<Void> description() {
+ URI redirectUri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/swagger-ui.html").build().toUri();
+ return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).location(redirectUri).build();
+ }
+
+ @RequestMapping(value = "/api/status", method = RequestMethod.GET,
+ produces = MediaType.APPLICATION_JSON_UTF8_VALUE, headers = "Connection!=Upgrade")
+ public Status status() {
+ return Status.getStatus(String.valueOf(wsHandler.getClients().size()));
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/Messages.java b/juick-server/src/main/java/com/juick/api/controllers/Messages.java
new file mode 100644
index 00000000..e16e46d5
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/Messages.java
@@ -0,0 +1,181 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.Status;
+import com.juick.Tag;
+import com.juick.User;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.server.util.UserUtils;
+import com.juick.service.MessagesService;
+import com.juick.service.TagService;
+import com.juick.service.UserService;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.inject.Inject;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author ugnich
+ */
+@RestController
+@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+public class Messages {
+
+ private static final ResponseEntity<List<com.juick.Message>> NOT_FOUND = ResponseEntity
+ .status(HttpStatus.NOT_FOUND)
+ .body(Collections.emptyList());
+
+ private static final ResponseEntity<List<com.juick.Message>> FORBIDDEN = ResponseEntity
+ .status(HttpStatus.FORBIDDEN)
+ .body(Collections.emptyList());
+
+ @Inject
+ private MessagesService messagesService;
+ @Inject
+ private UserService userService;
+ @Inject
+ private TagService tagService;
+
+ // TODO: serialize image urls
+
+ @RequestMapping("/home")
+ public ResponseEntity<List<com.juick.Message>> getHome(
+ @RequestParam(defaultValue = "0") int before_mid) {
+ User visitor = UserUtils.getCurrentUser();
+ if (!visitor.isAnonymous()) {
+ int vuid = visitor.getUid();
+ List<Integer> mids = messagesService.getMyFeed(vuid, before_mid, true);
+
+ if (!mids.isEmpty())
+ return ResponseEntity.ok(messagesService.getMessages(mids));
+
+ return NOT_FOUND;
+ }
+ return FORBIDDEN;
+ }
+
+ @RequestMapping("/messages")
+ public ResponseEntity<List<com.juick.Message>> getMessages(
+ @RequestParam(required = false) String uname,
+ @RequestParam(name = "before_mid", defaultValue = "0") Integer before,
+ @RequestParam(required = false, defaultValue = "0") Integer daysback,
+ @RequestParam(required = false) String withrecommended,
+ @RequestParam(required = false) String popular,
+ @RequestParam(required = false) String media,
+ @RequestParam(required = false) String tag) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+
+ List<Integer> mids;
+ if (!StringUtils.isEmpty(uname)) {
+ User user = userService.getUserByName(uname);
+ if (user != null) {
+ if (!StringUtils.isEmpty(media)) {
+ mids = messagesService.getUserPhotos(user.getUid(), 0, before);
+ } else if (!StringUtils.isEmpty(tag)) {
+ Tag tagObject = tagService.getTag(tag, false);
+ if (tagObject != null) {
+ mids = messagesService.getUserTag(user.getUid(), tagObject.TID, 0, before);
+ } else {
+ return NOT_FOUND;
+ }
+ } else if (!StringUtils.isEmpty(withrecommended)) {
+ mids = messagesService.getUserBlogWithRecommendations(user.getUid(), 0, before);
+ } else if (daysback > 0) {
+ mids = messagesService.getUserBlogAtDay(user.getUid(), 0, daysback);
+ } else {
+ mids = messagesService.getUserBlog(user.getUid(), 0, before);
+ }
+ } else {
+ return NOT_FOUND;
+ }
+ } else {
+ if (!StringUtils.isEmpty(popular)) {
+ mids = messagesService.getPopular(vuid, before);
+ } else if (!StringUtils.isEmpty(media)) {
+ mids = messagesService.getPhotos(vuid, before);
+ } else if (!StringUtils.isEmpty(tag)) {
+ Tag tagObject = tagService.getTag(tag, false);
+ if (tagObject != null) {
+ mids = messagesService.getTag(tagObject.TID, vuid, before, 20);
+ } else {
+ return NOT_FOUND;
+ }
+ } else {
+ mids = messagesService.getAll(vuid, before);
+ }
+ }
+ return ResponseEntity.ok(messagesService.getMessages(mids));
+ }
+
+ @GetMapping("/messages/notifications")
+ public ResponseEntity<List<com.juick.Message>> getNotifications(
+ @RequestParam(required = false) Long before
+ ) {
+ User visitor = UserUtils.getCurrentUser();
+ LocalDateTime beforeTime = before != null ?
+ LocalDateTime.ofInstant(Instant.ofEpochMilli(before), ZoneId.systemDefault())
+ : null;
+ return ResponseEntity.ok(messagesService.getNotifications(visitor, beforeTime));
+ }
+ @RequestMapping("/thread")
+ public ResponseEntity<List<com.juick.Message>> getThread(
+ @RequestParam(defaultValue = "0") int mid) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ com.juick.Message msg = messagesService.getMessage(mid);
+ if (msg != null) {
+ if (!messagesService.canViewThread(mid, vuid)) {
+ return FORBIDDEN;
+ } else {
+ List<com.juick.Message> replies = messagesService.getReplies(mid);
+ replies.add(0, msg);
+ return ResponseEntity.ok(replies);
+ }
+ }
+ return NOT_FOUND;
+ }
+
+ @ApiIgnore
+ @RequestMapping("/messages/set_privacy")
+ @ResponseBody
+ public ResponseEntity<Status> doSetPrivacy(
+ @RequestParam(defaultValue = "0") int mid) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ if (vuid == 0) {
+ throw new HttpForbiddenException();
+ }
+ com.juick.User user = messagesService.getMessageAuthor(mid);
+ if (user != null && user.getUid() == vuid && messagesService.setMessagePrivacy(mid)) {
+ return ResponseEntity.ok(Status.OK);
+ }
+ throw new HttpForbiddenException();
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/MessengerWebhook.java b/juick-server/src/main/java/com/juick/api/controllers/MessengerWebhook.java
new file mode 100644
index 00000000..835165ba
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/MessengerWebhook.java
@@ -0,0 +1,62 @@
+/*
+ * 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.api.controllers;
+
+import com.github.messenger4j.exception.MessengerVerificationException;
+import com.juick.api.MessengerManager;
+import com.juick.server.util.HttpForbiddenException;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Created by vitalyster on 27.03.2017.
+ */
+@ApiIgnore
+@RestController
+public class MessengerWebhook {
+ private static Logger logger = LoggerFactory.getLogger(MessengerWebhook.class);
+
+ @Inject
+ private MessengerManager messengerManager;
+
+ @RequestMapping(value = "/fbwbhk", method = RequestMethod.GET)
+ public ResponseEntity<Integer> verifyHook(@RequestParam(name = "hub.mode") String hubMode,
+ @RequestParam(name = "hub.challenge") Integer hubChallenge,
+ @RequestParam(name = "hub.verify_token") String verifyToken) {
+ if (hubMode.equals("subscribe") && verifyToken.equals(messengerManager.getFacebookVerifyToken())) {
+ return new ResponseEntity<>(hubChallenge, HttpStatus.OK);
+ }
+ throw new HttpForbiddenException();
+ }
+ @RequestMapping(value = "/fbwbhk", method = RequestMethod.POST)
+ @ResponseStatus(value = HttpStatus.OK)
+ public void processUpdate(@RequestHeader(name = "X-Hub-Signature", required = false) String signature, InputStream body) throws IOException, MessengerVerificationException {
+ String data = IOUtils.toString(body, StandardCharsets.UTF_8);
+ messengerManager.processUpdate(signature, data);
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/Notifications.java b/juick-server/src/main/java/com/juick/api/controllers/Notifications.java
new file mode 100644
index 00000000..e4474e6e
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/Notifications.java
@@ -0,0 +1,190 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.Message;
+import com.juick.Status;
+import com.juick.ExternalToken;
+import com.juick.User;
+import com.juick.server.helpers.AnonymousUser;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.service.MessagesService;
+import com.juick.service.PushQueriesService;
+import com.juick.service.SubscriptionService;
+import com.juick.server.util.UserUtils;
+import com.juick.service.UserService;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Created by vitalyster on 24.10.2016.
+ */
+@RestController
+public class Notifications {
+
+ @Inject
+ private PushQueriesService pushQueriesService;
+ @Inject
+ private MessagesService messagesService;
+ @Inject
+ private SubscriptionService subscriptionService;
+ @Inject
+ private UserService userService;
+
+
+ private User collectTokens(Integer uid) {
+ User user = userService.getUserByUID(uid).orElse(AnonymousUser.INSTANCE);
+ pushQueriesService.getGCMRegID(uid).forEach(t -> user.getTokens().add(new ExternalToken(null, "gcm", t, null)));
+ pushQueriesService.getAPNSToken(uid).forEach(t -> user.getTokens().add(new ExternalToken(null, "apns", t, null)));
+ pushQueriesService.getMPNSURL(uid).forEach(t -> user.getTokens().add(new ExternalToken(null, "mpns", t, null)));
+ return user;
+ }
+
+ @ApiIgnore
+ @RequestMapping(value = "/notifications", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public ResponseEntity<List<User>> doGet(
+ @RequestParam(required = false, defaultValue = "0") int uid,
+ @RequestParam(required = false, defaultValue = "0") int mid,
+ @RequestParam(required = false, defaultValue = "0") int rid) {
+ User visitor = UserUtils.getCurrentUser();
+ if ((visitor.getUid() == 0) || !(visitor.getName().equals("juick"))) {
+ throw new HttpForbiddenException();
+ }
+ if (uid > 0 && mid == 0) {
+ // PM
+ return ResponseEntity.ok(Collections.singletonList(collectTokens(uid)));
+ } else {
+ if (mid > 0) {
+ Message msg = messagesService.getMessage(mid);
+ if (msg != null) {
+ List<User> users;
+ if (rid > 0) {
+ Message reply = messagesService.getReply(mid, rid);
+ users = subscriptionService.getUsersSubscribedToComments(mid, reply.getUser().getUid());
+ } else {
+ users = subscriptionService.getSubscribedUsers(msg.getUser().getUid(), mid);
+ }
+
+ return ResponseEntity.ok(users.stream().map(User::getUid)
+ .map(this::collectTokens).collect(Collectors.toList()));
+ }
+ }
+ }
+ throw new HttpBadRequestException();
+ }
+
+ @ApiIgnore
+ @RequestMapping(value = "/notifications", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public Status doDelete(
+ @RequestBody List<ExternalToken> list) throws IOException {
+ User visitor = UserUtils.getCurrentUser();
+ // FIXME: it is possible to delete other user's tokens
+ if ((visitor.getUid() == 0) || !(visitor.getName().equals("juick"))) {
+ throw new HttpForbiddenException();
+ }
+ list.forEach(t -> {
+ switch (t.getType()) {
+ case "gcm":
+ pushQueriesService.deleteGCMToken(t.getToken());
+ break;
+ case "apns":
+ pushQueriesService.deleteAPNSToken(t.getToken());
+ break;
+ case "mpns":
+ pushQueriesService.deleteMPNSToken(t.getToken());
+ break;
+ default:
+ throw new HttpBadRequestException();
+ }
+ });
+
+ return Status.OK;
+ }
+
+ @ApiIgnore
+ @RequestMapping(value = "/notifications", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public Status doPut(
+ @RequestBody List<ExternalToken> list) throws IOException {
+ User visitor = UserUtils.getCurrentUser();
+ if (visitor.getUid() == 0) {
+ throw new HttpForbiddenException();
+ }
+ list.forEach(t -> {
+ switch (t.getType()) {
+ case "gcm":
+ pushQueriesService.addGCMToken(visitor.getUid(), t.getToken());
+ break;
+ case "apns":
+ pushQueriesService.addAPNSToken(visitor.getUid(), t.getToken());
+ break;
+ case "mpns":
+ pushQueriesService.addMPNSToken(visitor.getUid(), t.getToken());
+ break;
+ default:
+ throw new HttpBadRequestException();
+ }
+ });
+ return Status.OK;
+ }
+
+ @Deprecated
+ @RequestMapping(value = "/android/register", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public Status doAndroidRegister(
+ @RequestParam(name = "regid") String regId) {
+ User visitor = UserUtils.getCurrentUser();
+ if (visitor.getUid() == 0) {
+ throw new HttpForbiddenException();
+ }
+ pushQueriesService.addGCMToken(visitor.getUid(), regId);
+ return Status.OK;
+ }
+
+ @Deprecated
+ @RequestMapping(value = "/android/unregister", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public Status doAndroidUnRegister(@RequestParam(name = "regid") String regId) {
+ pushQueriesService.deleteGCMToken(regId);
+ return Status.OK;
+ }
+
+ @Deprecated
+ @RequestMapping(value = "/winphone/register", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public Status doWinphoneRegister(
+ Principal principal,
+ @RequestParam(name = "url") String regId) {
+ User visitor = UserUtils.getCurrentUser();
+ pushQueriesService.addMPNSToken(visitor.getUid(), regId);
+ return Status.OK;
+ }
+
+ @Deprecated
+ @RequestMapping(value = "/winphone/unregister", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public Status doWinphoneUnRegister(@RequestParam(name = "url") String regId) {
+ pushQueriesService.deleteMPNSToken(regId);
+ return Status.OK;
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/Others.java b/juick-server/src/main/java/com/juick/api/controllers/Others.java
new file mode 100644
index 00000000..4245de81
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/Others.java
@@ -0,0 +1,66 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.User;
+import com.juick.server.helpers.PrivateChats;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.server.util.HttpNotFoundException;
+import com.juick.server.util.UserUtils;
+import com.juick.service.PMQueriesService;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.inject.Inject;
+import java.util.List;
+
+/**
+ * @author ugnich
+ */
+@RestController
+public class Others {
+ @Inject
+ private PMQueriesService pmQueriesService;
+
+ @RequestMapping(value = "groups_pms", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public PrivateChats doGetGroupsPMs(
+ @RequestParam(defaultValue = "5") int cnt) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ if (vuid == 0) {
+ throw new HttpForbiddenException();
+ }
+ if (cnt < 3) {
+ cnt = 3;
+ }
+ if (cnt > 10) {
+ cnt = 10;
+ }
+
+ List<User> 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-server/src/main/java/com/juick/api/controllers/PM.java b/juick-server/src/main/java/com/juick/api/controllers/PM.java
new file mode 100644
index 00000000..87858e8c
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/PM.java
@@ -0,0 +1,127 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.User;
+import com.juick.api.ApiServer;
+import com.juick.server.helpers.AnonymousUser;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.service.PMQueriesService;
+import com.juick.service.UserService;
+import com.juick.server.util.UserUtils;
+import com.juick.server.util.WebUtils;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import rocks.xmpp.addr.Jid;
+import rocks.xmpp.core.stanza.model.Message;
+
+import javax.inject.Inject;
+import java.util.List;
+
+/**
+ * @author ugnich
+ */
+@RestController
+public class PM {
+ @Inject
+ private UserService userService;
+ @Inject
+ private PMQueriesService pmQueriesService;
+ @Inject
+ private ApiServer apiServer;
+
+ @RequestMapping(value = "/pm", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public List<com.juick.Message> doGetPM(
+ @RequestParam(required = false) String uname) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ if (vuid == 0) {
+ throw new HttpForbiddenException();
+ }
+ 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(
+ @RequestParam String uname,
+ @RequestParam String body) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ if (vuid == 0) {
+ throw new HttpForbiddenException();
+ }
+ User userTo = AnonymousUser.INSTANCE;
+ if (WebUtils.isUserName(uname)) {
+ userTo = userService.getUserByName(uname);
+ }
+
+ if (userTo.getUid() == 0 || body == null || body.length() < 1 || body.length() > 10240) {
+ throw new HttpBadRequestException();
+ }
+
+ if (userService.isInBLAny(userTo.getUid(), vuid)) {
+ throw new HttpForbiddenException();
+ }
+
+ if (pmQueriesService.createPM(vuid, userTo.getUid(), body)) {
+ Message msg = new Message();
+ msg.setFrom(Jid.of("juick@juick.com"));
+ msg.setTo(Jid.of(String.format("%d@push.juick.com", userTo.getUid())));
+ com.juick.Message jmsg = new com.juick.Message();
+ jmsg.setUser(visitor);
+ jmsg.setText(body);
+ jmsg.setTo(userTo);
+ msg.addExtension(jmsg);
+ apiServer.sendMessage(msg);
+
+ msg.setTo(Jid.of(String.format("%d@ws.juick.com", userTo.getUid())));
+ apiServer.sendMessage(msg);
+
+ List<String> jids = userService.getJIDsbyUID(userTo.getUid());
+ 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.sendMessage(mm);
+ }
+ return jmsg;
+
+ }
+ throw new HttpBadRequestException();
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/Post.java b/juick-server/src/main/java/com/juick/api/controllers/Post.java
new file mode 100644
index 00000000..a89786b1
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/Post.java
@@ -0,0 +1,281 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.User;
+import com.juick.api.ApiServer;
+import com.juick.api.EmailManager;
+import com.juick.server.util.*;
+import com.juick.service.MessagesService;
+import com.juick.service.SubscriptionService;
+import com.juick.service.UserService;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.mail.util.MimeMessageParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import rocks.xmpp.addr.Jid;
+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.mail.Session;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.UUID;
+
+/**
+ * Created by vt on 24/11/2016.
+ */
+@RestController
+public class Post {
+ private static Logger logger = LoggerFactory.getLogger(ApiServer.class);
+
+ @Inject
+ private UserService userService;
+ @Inject
+ private ApiServer apiServer;
+ @Inject
+ private MessagesService messagesService;
+ @Inject
+ private SubscriptionService subscriptionService;
+ @Value("${upload_tmp_dir:/var/www/juick.com/i/tmp/}")
+ private String tmpDir;
+ @Value("${img_path:/var/www/juick.com/i/}")
+ private String imgDir;
+
+ @RequestMapping(value = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ @ResponseStatus(value = HttpStatus.OK)
+ public void doPostMessage(
+ @RequestParam String body,
+ @RequestParam(required = false) String img,
+ @RequestParam(required = false) MultipartFile attach) throws IOException {
+ User visitor = UserUtils.getCurrentUser();
+
+ if (visitor.isAnonymous())
+ throw new HttpForbiddenException();
+
+ if (body == null || body.length() < 1 || body.length() > 4096) {
+ throw new HttpBadRequestException();
+ }
+ body = body.replace("\r", StringUtils.EMPTY);
+
+ String attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir);
+
+ if (StringUtils.isBlank(attachmentFName) && img != null && img.length() > 10) {
+ try {
+ URL imgUrl = new URL(img);
+ attachmentFName = HttpUtils.downloadImage(imgUrl, tmpDir);
+ } catch (Exception e) {
+ logger.error("DOWNLOAD ERROR", e);
+ throw new HttpBadRequestException();
+ }
+ }
+ apiServer.processMessage(visitor, body, attachmentFName);
+ }
+
+ @RequestMapping(value = "/comment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public com.juick.Message doPostComment(
+ @RequestParam(defaultValue = "0") int mid,
+ @RequestParam(defaultValue = "0") int rid,
+ @RequestParam String body,
+ @RequestParam(required = false) String img,
+ @RequestParam(required = false) MultipartFile attach)
+ throws IOException {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ if (vuid == 0) {
+ throw new HttpForbiddenException();
+ }
+ if (mid == 0) {
+ throw new HttpBadRequestException();
+ }
+ com.juick.Message msg = messagesService.getMessage(mid);
+ if (msg == null) {
+ throw new HttpNotFoundException();
+ }
+
+ com.juick.Message reply = null;
+ if (rid > 0) {
+ reply = messagesService.getReply(mid, rid);
+ if (reply == null) {
+ throw new HttpNotFoundException();
+ }
+ }
+
+ if (body == null || body.length() < 1 || body.length() > 4096) {
+ throw new HttpBadRequestException();
+ }
+ body = body.replace("\r", StringUtils.EMPTY);
+
+ 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 = HttpUtils.receiveMultiPartFile(attach, tmpDir);
+
+ if (StringUtils.isBlank(attachmentFName) && img != null && img.length() > 10) {
+ try {
+ attachmentFName = HttpUtils.downloadImage(new URL(img), tmpDir);
+ } catch (Exception e) {
+ logger.error("DOWNLOAD ERROR", e);
+ throw new HttpBadRequestException();
+ }
+ }
+
+ String attachmentType = StringUtils.isNotEmpty(attachmentFName) ? 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);
+
+ 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 ? StringUtils.defaultString(reply.getText()) : StringUtils.defaultString(msg.getText());
+ if (quote.length() >= 50) {
+ quote = quote.substring(0, 47) + "...";
+ }
+
+ xmsg.addExtension(new Nickname("@" + jmsg.getUser().getName()));
+
+ if (StringUtils.isNotEmpty(attachmentFName)) {
+ String fname = mid + "-" + ridnew + "." + attachmentType;
+ String attachmentURL = "http://i.juick.com/photos-1024/" + fname;
+
+ ImageUtils.saveImageWithPreviews(attachmentFName, fname, tmpDir, imgDir);
+
+ body = attachmentURL + "\n" + body;
+ try {
+ xmsg.addExtension(new OobX(new URI(attachmentURL)));
+ } catch (URISyntaxException e) {
+ logger.error("invalid uri: {}, exception {}", 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"));
+ apiServer.sendMessage(xmsg);
+
+ xmsg.setTo(Jid.of("juick@ws.juick.com"));
+ apiServer.sendMessage(xmsg);
+
+ xmsg.setTo(Jid.of("juick@push.juick.com"));
+ apiServer.sendMessage(xmsg);
+ return jmsg;
+ }
+
+ Session session = Session.getDefaultInstance(new Properties());
+
+ @PostMapping("/mail")
+ @ResponseStatus(value = HttpStatus.OK)
+ public void processMail(InputStream data) throws Exception {
+ MimeMessage msg = new MimeMessage(session, data);
+ String from = msg.getFrom().length > 1 ? ((InternetAddress) msg.getSender()).getAddress()
+ : ((InternetAddress) msg.getFrom()[0]).getAddress();
+ logger.info("got msg from {}", from);
+
+ User visitor = userService.getUserByEmail(from);
+ if (!visitor.isAnonymous()) {
+ MimeMessageParser parser = new MimeMessageParser(msg);
+ parser.parse();
+ final String[] body = {parser.getPlainContent()};
+ if (body[0] == null) {
+ parser.getAttachmentList().stream()
+ .filter(a -> a.getContentType().equals("text/plain")).findFirst()
+ .ifPresent(a -> {
+ try {
+ body[0] = IOUtils.toString(a.getInputStream(), StandardCharsets.UTF_8);
+ logger.info("got text: {}", body[0]);
+ } catch (IOException e) {
+ logger.info("attachment error: {}", e);
+ }
+ });
+ }
+ final String[] attachmentFName = new String[1];
+ parser.getAttachmentList().stream().filter(a ->
+ a.getContentType().equals("image/jpeg") || a.getContentType().equals("image/png"))
+ .findFirst().ifPresent(a -> {
+ logger.info("got attachment: {}", a.getContentType());
+ String attachmentType;
+ if (a.getContentType().equals("image/jpeg")) {
+ attachmentType = "jpg";
+ } else {
+ attachmentType = "png";
+ }
+ attachmentFName[0] = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType;
+ try {
+ logger.info("got inputstream: {}", a.getInputStream());
+ FileOutputStream fos = new FileOutputStream(Paths.get(tmpDir, attachmentFName[0]).toString());
+ IOUtils.copy(a.getInputStream(), fos);
+ fos.close();
+ } catch (IOException e) {
+ logger.info("attachment error: {}", e);
+ }
+ });
+ String[] inReplyToHeaders = msg.getHeader("In-Reply-To");
+ if (inReplyToHeaders != null && inReplyToHeaders.length > 0) {
+ Scanner inReplyToScanner = new Scanner(inReplyToHeaders[0].trim()).useDelimiter(EmailManager.MSGID_PATTERN);
+ int mid = Integer.parseInt(inReplyToScanner.next());
+ int rid = Integer.parseInt(inReplyToScanner.next());
+ logger.info("Message is reply to #{}/{}", mid, rid);
+ body[0] = rid > 0 ? String.format("#%d/%d %s", mid, rid, body[0])
+ : String.format("#%d %s", mid, body[0]);
+ }
+ rocks.xmpp.core.stanza.model.Message xmsg = new rocks.xmpp.core.stanza.model.Message();
+ xmsg.setType(rocks.xmpp.core.stanza.model.Message.Type.CHAT);
+ xmsg.setFrom(Jid.of(String.valueOf(visitor.getUid()), "uid.juick.com", "mail"));
+ xmsg.setTo(Jid.of("juick@juick.com/Juick"));
+ xmsg.setBody(body[0]);
+ try {
+ if (StringUtils.isNotEmpty(attachmentFName[0])) {
+ String attachmentUrl = String.format("juick://%s", attachmentFName[0]);
+ xmsg.addExtension(new OobX(new URI(attachmentUrl), "!!!!Juick!!"));
+ }
+ apiServer.sendMessage(xmsg);
+ } catch (URISyntaxException e1) {
+ logger.warn("attachment error", e1);
+ }
+ } else {
+ logger.info("not registered: {}", from);
+ }
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/Service.java b/juick-server/src/main/java/com/juick/api/controllers/Service.java
new file mode 100644
index 00000000..9e7f3333
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/Service.java
@@ -0,0 +1,74 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.Message;
+import com.juick.User;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.server.util.UserUtils;
+import com.juick.service.CrosspostService;
+import com.juick.service.MessagesService;
+import com.juick.service.SubscriptionService;
+import com.juick.service.UserService;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * TODO: configure spring-security to allow only admin role
+ */
+@ApiIgnore
+@RestController
+public class Service {
+ @Inject
+ private SubscriptionService subscriptionService;
+ @Inject
+ private MessagesService messagesService;
+ @Inject
+ private CrosspostService crosspostService;
+ @Inject
+ private UserService userService;
+
+ @RequestMapping(value = "/subscriptions", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public List<User> doGet(
+ @RequestParam(defaultValue = "0") int mid,
+ @RequestParam(defaultValue = "0") int uid) throws IOException {
+ User visitor = UserUtils.getCurrentUser();
+ if ((visitor.getUid() == 0) && !(visitor.getName().equals("juick"))) {
+ throw new HttpForbiddenException();
+ }
+ 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-server/src/main/java/com/juick/api/controllers/SkypeEndpoint.java b/juick-server/src/main/java/com/juick/api/controllers/SkypeEndpoint.java
new file mode 100644
index 00000000..91a617b4
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/SkypeEndpoint.java
@@ -0,0 +1,47 @@
+/*
+ * 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.api.controllers;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Created by vitalyster on 18.07.2016.
+ */
+@ApiIgnore
+@RestController
+public class SkypeEndpoint {
+ private static final Logger logger = LoggerFactory.getLogger(SkypeEndpoint.class);
+ @RequestMapping(value = "/skypebotendpoint", method = RequestMethod.POST)
+ @ResponseStatus(value = HttpStatus.OK)
+ public void doPost(InputStream body) throws IOException {
+ String data = IOUtils.toString(body, StandardCharsets.UTF_8);
+ logger.info("got data: {}", data);
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/Tags.java b/juick-server/src/main/java/com/juick/api/controllers/Tags.java
new file mode 100644
index 00000000..85bb1ba4
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/Tags.java
@@ -0,0 +1,54 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.User;
+import com.juick.server.helpers.TagStats;
+import com.juick.server.util.UserUtils;
+import com.juick.service.TagService;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.inject.Inject;
+import java.util.List;
+
+/**
+ * Created by vitalyster on 29.11.2016.
+ */
+@RestController
+public class Tags {
+ @Inject
+ private TagService tagService;
+
+ @RequestMapping(value = "/tags", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public List<TagStats> tags(
+ @RequestParam(required = false, defaultValue = "0") int user_id
+ ) {
+ User visitor = UserUtils.getCurrentUser();
+ if (user_id == 0) {
+ user_id = visitor.getUid();
+ }
+ if (user_id > 0) {
+ return tagService.getUserTagStats(user_id);
+ }
+ return tagService.getTagStats();
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/TelegramWebhook.java b/juick-server/src/main/java/com/juick/api/controllers/TelegramWebhook.java
new file mode 100644
index 00000000..31e7b4ea
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/TelegramWebhook.java
@@ -0,0 +1,48 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.api.TelegramBotManager;
+import org.apache.commons.io.IOUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.inject.Inject;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Created by vt on 24/11/2016.
+ */
+@ApiIgnore
+@RestController
+public class TelegramWebhook {
+ @Inject
+ private TelegramBotManager telegramBotManager;
+
+ @RequestMapping(value = "/tlgmbtwbhk", method = RequestMethod.POST)
+ @ResponseStatus(value = HttpStatus.OK)
+ public void processUpdate(InputStream body) throws Exception {
+ String data = IOUtils.toString(body, StandardCharsets.UTF_8);
+ telegramBotManager.processUpdate(data);
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/Users.java b/juick-server/src/main/java/com/juick/api/controllers/Users.java
new file mode 100644
index 00000000..b221d9fe
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/Users.java
@@ -0,0 +1,125 @@
+/*
+ * 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.api.controllers;
+
+import com.juick.User;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.server.util.HttpNotFoundException;
+import com.juick.service.UserService;
+import com.juick.server.util.UserUtils;
+import com.juick.server.util.WebUtils;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author ugnich
+ */
+@RestController
+public class Users {
+ @Inject
+ private UserService userService;
+
+ @RequestMapping(value = "/auth", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public String getAuthToken() {
+ return userService.getHashByUID(UserUtils.getCurrentUser().getUid());
+ }
+
+ @RequestMapping(value = "/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public List<User> doGetUsers(
+ @RequestParam(value = "uname", required = false) List<String> unames) {
+ List<com.juick.User> users = new ArrayList<>();
+
+ if (unames != null) {
+ unames.removeIf(WebUtils::isNotUserName);
+
+ if (!unames.isEmpty() && unames.size() < 20)
+ users.addAll(userService.getUsersByName(unames));
+ }
+
+ if (!users.isEmpty())
+ return users;
+ if (!UserUtils.getCurrentUser().isAnonymous()) {
+ return Collections.singletonList(UserUtils.getCurrentUser());
+ }
+
+ throw new HttpNotFoundException();
+ }
+
+ @RequestMapping(value = "/users/read", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public List<User> doGetUserRead(
+ @RequestParam String uname) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ if (vuid == 0) {
+ throw new HttpForbiddenException();
+ }
+ int uid = 0;
+ if (uname == null) {
+ uid = vuid;
+ } else {
+ if (WebUtils.isUserName(uname)) {
+ com.juick.User u = userService.getUserByName(uname);
+ if (u != null && u.getUid() > 0) {
+ uid = u.getUid();
+ }
+ }
+ }
+
+ if (uid > 0) {
+ List<Integer> uids = userService.getUserRead(uid);
+ if (uids.size() > 0) {
+ List<com.juick.User> 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<User> doGetUserReaders(
+ @RequestParam String uname) {
+ User visitor = UserUtils.getCurrentUser();
+ int vuid = visitor.getUid();
+ if (vuid == 0) {
+ throw new HttpForbiddenException();
+ }
+ int uid = 0;
+ if (uname == null) {
+ uid = vuid;
+ } else {
+ if (WebUtils.isUserName(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();
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/api/controllers/util/JsonpAdvice.java b/juick-server/src/main/java/com/juick/api/controllers/util/JsonpAdvice.java
new file mode 100644
index 00000000..90a01da0
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/api/controllers/util/JsonpAdvice.java
@@ -0,0 +1,31 @@
+/*
+ * 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.api.controllers.util;
+
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
+
+/**
+ * Created by vitalyster on 25.11.2016.
+ */
+@ControllerAdvice
+public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
+ public JsonpAdvice() {
+ super("callback");
+ }
+}