/*
* Copyright (C) 2008-2019, 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 .
*/
package com.juick.server.api;
import com.juick.Message;
import com.juick.Status;
import com.juick.ExternalToken;
import com.juick.User;
import com.juick.model.AnonymousUser;
import com.juick.server.util.HttpBadRequestException;
import com.juick.server.util.UserUtils;
import com.juick.service.MessagesService;
import com.juick.service.PushQueriesService;
import com.juick.service.SubscriptionService;
import com.juick.service.TelegramService;
import com.juick.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
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;
@Inject
private TelegramService telegramService;
private User collectTokens(Integer uid) {
User user = userService.getUserByUID(uid).orElse(AnonymousUser.INSTANCE);
user.setUnreadCount(messagesService.getUnread(user).size());
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)));
List xmppJids = userService.getJIDsbyUID(uid).stream()
.map(jid -> new ExternalToken(null, "xmpp", jid, null))
.collect(Collectors.toList());
user.getTokens().addAll(xmppJids);
List tgIds = telegramService.getTelegramIdentifiers(Collections.singletonList(user)).stream()
.map(tgId -> new ExternalToken(null, "durov", String.valueOf(tgId), null))
.collect(Collectors.toList());
user.getTokens().addAll(tgIds);
return user;
}
@ApiIgnore
@RequestMapping(value = "/api/notifications", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity> 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.getName().equals("juick"))) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
}
if (uid > 0 && mid == 0) {
// PM
return ResponseEntity.ok(Collections.singletonList(collectTokens(uid)));
} else {
if (mid > 0) {
// reply
Message msg = messagesService.getMessage(mid).orElseThrow(IllegalStateException::new);
List users;
if (rid > 0) {
Message op = messagesService.getMessage(mid).orElseThrow(IllegalStateException::new);
Message reply = messagesService.getReply(mid, rid);
users = subscriptionService.getUsersSubscribedToComments(op, reply);
} else {
users = subscriptionService.getSubscribedUsers(msg.getUser().getUid(), msg);
}
return ResponseEntity.ok(users.stream().map(User::getUid)
.map(this::collectTokens).collect(Collectors.toList()));
} else {
// read
return ResponseEntity.ok(Collections.singletonList(collectTokens(uid)));
}
}
}
@ApiIgnore
@RequestMapping(value = "/api/notifications", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity doDelete(
@RequestBody List list) {
User visitor = UserUtils.getCurrentUser();
if (!visitor.getName().equals("juick")) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
}
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 ResponseEntity.ok(Status.OK);
}
@ApiIgnore
@RequestMapping(value = "/api/notifications/delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity doDeleteTokens(
@RequestBody List list) {
User visitor = UserUtils.getCurrentUser();
if (!visitor.getName().equals("juick")) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
}
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 ResponseEntity.ok(Status.OK);
}
@ApiIgnore
@RequestMapping(value = "/api/notifications", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Status doPut(
@RequestBody List list) throws IOException {
User visitor = UserUtils.getCurrentUser();
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 = "/api/android/register", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Status doAndroidRegister(
@RequestParam(name = "regid") String regId) {
User visitor = UserUtils.getCurrentUser();
pushQueriesService.addGCMToken(visitor.getUid(), regId);
return Status.OK;
}
@Deprecated
@RequestMapping(value = "/api/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;
}
}