aboutsummaryrefslogtreecommitdiff
path: root/juick-notifications/src
diff options
context:
space:
mode:
Diffstat (limited to 'juick-notifications/src')
-rw-r--r--juick-notifications/src/main/java/com/juick/components/APNSManager.java172
-rw-r--r--juick-notifications/src/main/java/com/juick/components/FirebaseManager.java129
-rw-r--r--juick-notifications/src/main/java/com/juick/components/MPNSManager.java168
-rw-r--r--juick-notifications/src/main/java/com/juick/components/NotificationsManager.java216
-rw-r--r--juick-notifications/src/main/java/com/juick/components/PushServer.java15
-rw-r--r--juick-notifications/src/main/java/com/juick/components/configuration/APNSConfiguration.java18
-rw-r--r--juick-notifications/src/main/java/com/juick/components/configuration/GCMConfiguration.java19
-rw-r--r--juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java75
-rw-r--r--juick-notifications/src/main/java/com/juick/components/configuration/MPNSConfiguration.java18
-rw-r--r--juick-notifications/src/main/java/com/juick/components/mpns/MPNSError.java29
-rw-r--r--juick-notifications/src/main/java/com/juick/components/mpns/MPNSToken.java39
-rw-r--r--juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java24
12 files changed, 0 insertions, 922 deletions
diff --git a/juick-notifications/src/main/java/com/juick/components/APNSManager.java b/juick-notifications/src/main/java/com/juick/components/APNSManager.java
deleted file mode 100644
index 4e5fc01a..00000000
--- a/juick-notifications/src/main/java/com/juick/components/APNSManager.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package com.juick.components;
-
-import com.juick.ExternalToken;
-import com.juick.Message;
-import com.juick.User;
-import com.juick.formatters.PlainTextFormatter;
-import com.juick.service.component.*;
-import com.turo.pushy.apns.ApnsClient;
-import com.turo.pushy.apns.ApnsClientBuilder;
-import com.turo.pushy.apns.PushNotificationResponse;
-import com.turo.pushy.apns.auth.ApnsSigningKey;
-import com.turo.pushy.apns.util.ApnsPayloadBuilder;
-import com.turo.pushy.apns.util.SimpleApnsPushNotification;
-import com.turo.pushy.apns.util.concurrent.PushNotificationResponseListener;
-import io.netty.util.concurrent.Future;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import java.io.File;
-import java.io.IOException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
-
-public class APNSManager implements NotificationListener {
- private static Logger logger = LoggerFactory.getLogger(APNSManager.class);
-
- private ApnsClient apns;
- @Value("${ios_p8_key:}")
- private String p8key;
- @Value("${ios_app_id:}")
- private String topic;
- @Value("${ios_team_id:}")
- private String teamId;
- @Value("${ios_key_id:}")
- private String keyId;
- @Value("${ios_sandbox_user_id:}")
- private Integer sandboxUserId;
- @Inject
- private NotificationsManager notificationsManager;
-
- @PostConstruct
- public void initialize() throws NoSuchAlgorithmException, InvalidKeyException, IOException {
- apns = new ApnsClientBuilder()
- .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST)
- .setSigningKey(ApnsSigningKey.loadFromPkcs8File(new File(p8key),
- teamId, keyId))
- .build();
- }
- @Override
- public void processMessageEvent(MessageEvent messageEvent) {
- com.juick.Message jmsg = messageEvent.getMessage();
- List<User> users = messageEvent.getUsers();
- ApnsPayloadBuilder apnsPayloadBuilder = new ApnsPayloadBuilder();
- apnsPayloadBuilder.addCustomProperty("mid", jmsg.getMid());
- apnsPayloadBuilder.addCustomProperty("uname", jmsg.getUser().getName());
- apnsPayloadBuilder.addCustomProperty("avatarUrl",
- String.format("https://i.juick.com/a/%d.png", jmsg.getUser().getUid()));
- apnsPayloadBuilder.setMutableContent(true);
- String post = PlainTextFormatter.formatPost(jmsg);
- String[] parts = post.split("\n", 2);
- apnsPayloadBuilder.setAlertTitle(parts[0]).setAlertBody(parts[1]);
- users.stream().filter(u -> u.getUid() != sandboxUserId).forEach( user -> {
- apnsPayloadBuilder.setBadgeNumber(user.getUnreadCount());
- String payload = apnsPayloadBuilder.buildWithDefaultMaximumLength();
- user.getTokens().stream().filter(t -> t.getType().equals("apns"))
- .map(ExternalToken::getToken).forEach(token -> {
- Future<PushNotificationResponse<SimpleApnsPushNotification>> notification = apns.sendNotification(
- new SimpleApnsPushNotification(token, topic, payload));
- notification.addListener((PushNotificationResponseListener<SimpleApnsPushNotification>) future -> {
- if (future.isSuccess()) {
- processAPNSResponse(token, future.getNow());
- } else {
- logger.warn("APNS error ", future.cause());
- }
- });
- });
- });
- }
-
- @Override
- public void processSubscribeEvent(SubscribeEvent subscribeEvent) {
-
- }
-
- @Override
- public void processLikeEvent(LikeEvent likeEvent) {
-
- }
-
- @Override
- public void processPingEvent(PingEvent pingEvent) {
-
- }
-
- @Override
- public void processMessageReadEvent(MessageReadEvent messageReadEvent) {
- User user = messageReadEvent.getUser();
- if (user.getUid() != sandboxUserId) {
- ApnsPayloadBuilder apnsPayloadBuilder = new ApnsPayloadBuilder();
- apnsPayloadBuilder.setBadgeNumber(user.getUnreadCount());
- String payload = apnsPayloadBuilder.buildWithDefaultMaximumLength();
- user.getTokens().stream().filter(t -> t.getType().equals("apns"))
- .map(ExternalToken::getToken).forEach(token -> {
- Future<PushNotificationResponse<SimpleApnsPushNotification>> notification = apns.sendNotification(
- new SimpleApnsPushNotification(token, topic, payload));
- notification.addListener((PushNotificationResponseListener<SimpleApnsPushNotification>) future -> {
- if (future.isSuccess()) {
- processAPNSResponse(token, future.getNow());
- } else {
- logger.warn("APNS error ", future.cause());
- }
- });
- });
- }
- }
-
- @Override
- public void processTopEvent(TopEvent topEvent) {
- Message message = topEvent.getMessage();
- if (message.getUser().getUid() != sandboxUserId) {
- ApnsPayloadBuilder apnsPayloadBuilder = new ApnsPayloadBuilder();
- message.getUser().getTokens().stream().filter(t -> t.getType().equals("apns"))
- .map(ExternalToken::getToken).forEach(token -> {
- String payload = apnsPayloadBuilder.setAlertTitle("Top").setAlertBody("Your message became popular!")
- .addCustomProperty("mid", message.getMid())
- .addCustomProperty("uname", message.getUser().getName())
- .buildWithDefaultMaximumLength();
- Future<PushNotificationResponse<SimpleApnsPushNotification>> notification = apns.sendNotification(
- new SimpleApnsPushNotification(token, topic, payload));
- notification.addListener((PushNotificationResponseListener<SimpleApnsPushNotification>) future -> {
- if (future.isSuccess()) {
- processAPNSResponse(token, future.getNow());
- } else {
- logger.warn("APNS error ", future.cause());
- }
- });
- });
- }
- }
-
- @PreDestroy
- public void close() {
- apns.close();
- }
-
- private void processAPNSResponse(String token, PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse) {
- if (pushNotificationResponse.isAccepted()) {
- logger.info("APNS accepted: {}", token);
- } else {
- String reason = pushNotificationResponse.getRejectionReason();
- logger.info("APNS rejected: {}", reason);
- if (reason.equals("BadDeviceToken")) {
- notificationsManager.getInvalidAPNSTokens().add(token);
- }
- }
- Optional<Date> invalidationDate = Optional.ofNullable(
- pushNotificationResponse.getTokenInvalidationTimestamp());
- invalidationDate.ifPresent(date -> {
- if (date.before(new Date())) {
- logger.info("Token invalidated: {}", token);
- notificationsManager.getInvalidAPNSTokens().add(token);
- }
- });
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/FirebaseManager.java b/juick-notifications/src/main/java/com/juick/components/FirebaseManager.java
deleted file mode 100644
index 1feee458..00000000
--- a/juick-notifications/src/main/java/com/juick/components/FirebaseManager.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package com.juick.components;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.api.core.ApiFuture;
-import com.google.api.core.ApiFutureCallback;
-import com.google.api.core.ApiFutures;
-import com.google.auth.oauth2.GoogleCredentials;
-import com.google.firebase.FirebaseApp;
-import com.google.firebase.FirebaseOptions;
-import com.google.firebase.messaging.FirebaseMessaging;
-import com.google.firebase.messaging.FirebaseMessagingException;
-import com.google.firebase.messaging.Message;
-import com.juick.ExternalToken;
-import com.juick.User;
-import com.juick.service.component.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.core.task.TaskExecutor;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import java.io.IOException;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class FirebaseManager implements NotificationListener {
- private static Logger logger = LoggerFactory.getLogger(FirebaseManager.class);
- @Inject
- ObjectMapper jsonMapper;
- @Value("${fcm_database_url:}")
- private String fcmDatabaseUrl;
- @Inject
- private NotificationsManager notificationsManager;
- @Inject
- private TaskExecutor taskExecutor;
-
- @PostConstruct
- public void initialize() throws IOException {
- Resource serviceAccount =
- new ClassPathResource("serviceAccount.json");
-
- FirebaseOptions options = new FirebaseOptions.Builder()
- .setCredentials(GoogleCredentials.fromStream(serviceAccount.getInputStream()))
- .setDatabaseUrl(fcmDatabaseUrl)
- .build();
-
- FirebaseApp.initializeApp(options);
- }
-
- @Override
- public void processMessageEvent(MessageEvent messageEvent) {
- com.juick.Message jmsg = messageEvent.getMessage();
- List<User> users = messageEvent.getUsers();
- // GCM
- List<String> regids = users.stream().flatMap(u -> u.getTokens().stream()).filter(d -> d.getType().equals("gcm"))
- .map(ExternalToken::getToken).collect(Collectors.toList());
- if (!regids.isEmpty()) {
- String json = null;
- try {
- json = jsonMapper.writeValueAsString(jmsg);
- } catch (JsonProcessingException e) {
- logger.warn("JSON exception", e);
- }
- logger.info(json);
- Message.Builder messageBuilder = Message.builder()
- .putData("message", json);
- regids.forEach(token -> {
- messageBuilder.setToken(token);
- ApiFuture<String> response = FirebaseMessaging.getInstance().sendAsync(messageBuilder.build());
- ApiFutures.addCallback(response, new ApiFutureCallback<String>() {
- @Override
- public void onFailure(Throwable t) {
- if (t instanceof FirebaseMessagingException) {
- FirebaseMessagingException e = (FirebaseMessagingException) t;
- logger.warn("FirebaseMessaging error: {}", e.getErrorCode());
- if (e.getErrorCode().equals("invalid-argument")
- || e.getErrorCode().equals("registration-token-not-registered")
- || e.getErrorCode().equals("invalid-registration-token")) {
- // invalid token
- logger.info("{} is scheduled to remove", token);
- notificationsManager.addInvalidGCMToken(token);
- } else {
- logger.warn("Unhandled FirebaseMessaging exception", t);
- }
- } else {
- logger.warn("Unhandled FCM exception", t);
- }
- }
-
- @Override
- public void onSuccess(String result) {
- logger.info("Successfully sent message: " + result);
- }
- }, taskExecutor);
- });
- } else {
- logger.info("GMS: no recipients");
- }
- }
-
- @Override
- public void processSubscribeEvent(SubscribeEvent subscribeEvent) {
-
- }
-
- @Override
- public void processLikeEvent(LikeEvent likeEvent) {
-
- }
-
- @Override
- public void processPingEvent(PingEvent pingEvent) {
-
- }
-
- @Override
- public void processMessageReadEvent(MessageReadEvent messageReadEvent) {
-
- }
-
- @Override
- public void processTopEvent(TopEvent topEvent) {
-
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/MPNSManager.java b/juick-notifications/src/main/java/com/juick/components/MPNSManager.java
deleted file mode 100644
index d6c99b0b..00000000
--- a/juick-notifications/src/main/java/com/juick/components/MPNSManager.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.juick.components;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.juick.ExternalToken;
-import com.juick.User;
-import com.juick.components.mpns.MPNSError;
-import com.juick.components.mpns.MPNSToken;
-import com.juick.service.component.*;
-import com.juick.util.MessageUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.text.StringEscapeUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.*;
-import org.springframework.http.converter.StringHttpMessageConverter;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Created by vital on 29.03.2017.
- */
-public class MPNSManager implements NotificationListener {
-
- private static Logger logger = LoggerFactory.getLogger(MPNSManager.class);
-
- private String accessToken;
-
- @Inject
- private ObjectMapper jsonMapper;
- @Value("${wns_application_sip:}")
- private String applicationSip;
- @Value("${wns_client_secret:}")
- private String applicationSecret;
- private RestTemplate wnsService;
-
- @Inject
- private NotificationsManager notificationsManager;
-
- @PostConstruct
- public void authenticate() throws IOException {
- String url = "https://login.live.com/accesstoken.srf";
- MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
- form.add("grant_type", "client_credentials");
- form.add("client_id", applicationSip);
- form.add("client_secret", applicationSecret);
- form.add("scope", "notify.windows.com");
- HttpHeaders httpHeaders = new HttpHeaders();
- httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
- wnsService = new RestTemplate();
- wnsService.getMessageConverters().add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
- HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(form, httpHeaders);
- ResponseEntity<String> response = wnsService.exchange(url, HttpMethod.POST, entity, String.class);
- String responseBody = response.getBody();
- HttpStatus statusCode = response.getStatusCode();
- if (statusCode != HttpStatus.OK) {
- MPNSError error = jsonMapper.readValue(responseBody, MPNSError.class);
- throw new IOException(error.getError() + ": " + error.getErrorDescription());
- }
- MPNSToken token = jsonMapper.readValue(responseBody, MPNSToken.class);
- if (token.getTokenType().length() >= 1) {
- token.setTokenType(Character.toUpperCase(token.getTokenType().charAt(0)) + token.getTokenType().substring(1));
- }
- accessToken = token.getTokenType() + " " + token.getAccessToken();
- logger.info("MPNS authenticated");
- }
-
- void sendNotification(final String url, final String xml) throws IOException {
- HttpHeaders httpHeaders = new HttpHeaders();
- httpHeaders.setContentType(new MediaType("text", "xml", StandardCharsets.UTF_8));
- httpHeaders.set("Authorization", accessToken);
- httpHeaders.set("X-WNS-Type", "wns/toast");
- HttpEntity<String> requestEntity = new HttpEntity<>(xml, httpHeaders);
- try {
- UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
- wnsService.exchange(builder.build(true).toUri(), HttpMethod.POST, requestEntity, Void.class);
- } catch (HttpClientErrorException ex) {
- HttpStatus statusCode = ex.getStatusCode();
- if (statusCode == HttpStatus.GONE) {
- // expired
- logger.info("{} is scheduled to remove", url);
- notificationsManager.addInvalidMPNSToken(url);
- } else {
- String headersContent = ex.getResponseHeaders().entrySet().stream()
- .filter(x -> x.getKey().startsWith("X-WNS-") || x.getKey().startsWith("WWW-"))
- .map(x -> x.getKey() + ": " + String.join(",", x.getValue()))
- .collect(Collectors.joining("\n"));
- throw new IOException(headersContent);
- }
- }
- }
-
- @Override
- public void processMessageEvent(MessageEvent messageEvent) {
- com.juick.Message jmsg = messageEvent.getMessage();
- List<User> users = messageEvent.getUsers();
-
- List<String> urls = users.stream().flatMap(u -> u.getTokens().stream()).filter(d -> d.getType().equals("mpns"))
- .map(ExternalToken::getToken).collect(Collectors.toList());
-
- if (urls.isEmpty()) {
- logger.info("WNS: no recipients");
- } else {
- try {
- String text1 = "@" + jmsg.getUser().getName();
- if (!jmsg.getTags().isEmpty()) {
- text1 += ":" + StringEscapeUtils.escapeXml11(MessageUtils.getTagsString(jmsg));
- }
- String text2 = StringEscapeUtils.escapeXml11(StringUtils.defaultString(jmsg.getText()));
- String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
- + "<toast>"
- + "<visual>"
- + "<binding template=\"ToastImageAndText02\">"
- + "<image id=\"1\" src=\"http://i.juick.com/as/" + jmsg.getUser().getUid() + ".png\" />"
- + "<text id=\"1\">" + text1 + "</text>"
- + "<text id=\"2\">" + text2 + "</text>"
- + "</binding>"
- + "</visual>"
- + "<commands>"
- + "<command arguments=\"/ThreadView.xaml?mid=" + jmsg.getMid() + "\" />"
- + "</commands>"
- + "</toast>";
- logger.trace(xml);
- for (String url : urls) {
- logger.info("WNS: {}", url);
- sendNotification(url, xml);
- }
- } catch (IOException | IllegalStateException ex) {
- logger.error("WNS: ", ex);
- }
- }
- }
-
- @Override
- public void processSubscribeEvent(SubscribeEvent subscribeEvent) {
-
- }
-
- @Override
- public void processLikeEvent(LikeEvent likeEvent) {
-
- }
-
- @Override
- public void processPingEvent(PingEvent pingEvent) {
-
- }
-
- @Override
- public void processMessageReadEvent(MessageReadEvent messageReadEvent) {
-
- }
-
- @Override
- public void processTopEvent(TopEvent topEvent) {
-
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/NotificationsManager.java b/juick-notifications/src/main/java/com/juick/components/NotificationsManager.java
deleted file mode 100644
index fce0bed7..00000000
--- a/juick-notifications/src/main/java/com/juick/components/NotificationsManager.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Juick
- * Copyright (C) 2013, Ugnich Anton
- *
- * 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.components;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.juick.ExternalToken;
-import com.juick.User;
-import com.juick.service.component.DisconnectedEvent;
-import com.juick.service.component.MessageEvent;
-import com.juick.service.component.MessageReadEvent;
-import com.juick.util.MessageUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.socket.CloseStatus;
-import org.springframework.web.socket.PingMessage;
-import org.springframework.web.socket.TextMessage;
-import org.springframework.web.socket.WebSocketSession;
-import org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator;
-import org.springframework.web.socket.handler.TextWebSocketHandler;
-
-import javax.annotation.Nonnull;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-
-/**
- * @author Ugnich Anton
- */
-@Component
-public class NotificationsManager extends TextWebSocketHandler {
- private static Logger logger = LoggerFactory.getLogger(NotificationsManager.class);
-
- @Inject
- private RestTemplate rest;
-
- @Inject
- private ObjectMapper jsonMapper;
-
- private final Set<String> invalidGCMTokens = Collections.synchronizedSet(new HashSet<>());
- private final Set<String> invalidMPNSTokens = Collections.synchronizedSet(new HashSet<>());
- private final Set<String> invalidAPNSTokens = Collections.synchronizedSet(new HashSet<>());
-
- @PostConstruct
- public void init() {
- closeFlag.set(false);
- }
- public void messageReceived(@Nonnull com.juick.Message jmsg) {
- if (jmsg.isService()) {
- serviceMessageReceived(jmsg);
- return;
- }
- User pmTo = jmsg.getTo();
- final List<User> users = new ArrayList<>();
- if (MessageUtils.isPM(jmsg)) {
- users.addAll(rest.exchange(String.format("http://api.juick.com/notifications?uid=%d",
- pmTo.getUid()),
- HttpMethod.GET, null, new ParameterizedTypeReference<List<User>>() {
- }).getBody());
- } else if (MessageUtils.isReply(jmsg)) {
- users.addAll(rest.exchange(String.format("http://api.juick.com/notifications?uid=%d&mid=%d&rid=%d",
- jmsg.getUser().getUid(), jmsg.getMid(), jmsg.getRid()),
- HttpMethod.GET, null, new ParameterizedTypeReference<List<User>>() {
- }).getBody());
- } else {
- users.addAll(rest.exchange(String.format("http://api.juick.com/notifications?uid=%s&mid=%s",
- jmsg.getUser().getUid(), jmsg.getMid()),
- HttpMethod.GET, null, new ParameterizedTypeReference<List<User>>() {
- }).getBody());
- }
- applicationEventPublisher.publishEvent(new MessageEvent(this, jmsg, users));
- }
- private void serviceMessageReceived(@Nonnull com.juick.Message jmsg) {
- logger.info("Message read event from {} for {}", jmsg.getUser().getName(), jmsg.getMid());
- List<User> users = rest.exchange(String.format("http://api.juick.com/notifications?uid=%d",
- jmsg.getUser().getUid()),
- HttpMethod.GET, null, new ParameterizedTypeReference<List<User>>() {
- }).getBody();
- users.forEach(user -> {
- applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, jmsg));
- });
- }
-
- public void addInvalidGCMToken(String token) {
- synchronized (invalidGCMTokens) {
- invalidGCMTokens.add(token);
- }
- }
- public Set<String> getInvalidGCMTokens() {
- return invalidGCMTokens;
- }
- public void cleanupGCMTokens() {
- logger.info("removed {} GCM tokens", invalidGCMTokens.size());
- synchronized (invalidGCMTokens) {
- invalidGCMTokens.clear();
- }
- }
- public void addInvalidMPNSToken(String token) {
- synchronized (invalidMPNSTokens) {
- invalidMPNSTokens.add(token);
- }
- }
- public Set<String> getInvalidMPNSTokens() {
- return invalidMPNSTokens;
- }
- public void cleanupMPNSTokens() {
- logger.info("removed {} MPNS tokens", invalidMPNSTokens.size());
- synchronized (invalidMPNSTokens) {
- invalidMPNSTokens.clear();
- }
- }
-
- public Set<String> getInvalidAPNSTokens() {
- return invalidAPNSTokens;
- }
- @Inject
- private ApplicationEventPublisher applicationEventPublisher;
-
- private ConcurrentWebSocketSessionDecorator session;
- private final AtomicBoolean closeFlag = new AtomicBoolean(false);
-
- @Override
- public void afterConnectionEstablished(WebSocketSession session) {
- if (!closeFlag.get()) {
- logger.info("WebSocket connected");
- this.session = new ConcurrentWebSocketSessionDecorator(session, 60000, 65535);
- }
- }
-
- @Override
- public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
- if (!closeFlag.get()) {
- logger.info("WebSocket disconnected with code {}: {}", status.getCode(), status.getReason());
- applicationEventPublisher.publishEvent(new DisconnectedEvent(this));
- }
- }
-
- @Override
- protected void handleTextMessage(WebSocketSession session, TextMessage text) throws Exception {
- if (!closeFlag.get() && this.session.getDelegate().equals(session)) {
- com.juick.Message jmsg = jsonMapper.readValue(text.asBytes(), com.juick.Message.class);
-
- if (logger.isInfoEnabled()) // prevent writeValueAsString execution if logger disabled
- logger.info("got jmsg: {}", jsonMapper.writeValueAsString(jmsg));
- messageReceived(jmsg);
- }
- }
-
- @Scheduled(fixedRate = 30000, initialDelay = 30000)
- public void ping() throws IOException {
- if (!closeFlag.get()) {
- if (session != null && session.isOpen()) {
- logger.debug("Sending WebSocket ping");
- session.sendMessage(new PingMessage());
- } else {
- applicationEventPublisher.publishEvent(new DisconnectedEvent(this));
- }
- }
- }
- @PreDestroy
- public void close() {
- closeFlag.set(true);
- }
- @Scheduled(fixedRate = 600000)
- public void cleanupTokens() {
- if (!closeFlag.get()) {
- logger.debug("initializing GCM tokens cleanup: {} tokens", getInvalidGCMTokens().size());
- deleteTokens("gcm", new ArrayList<>(getInvalidGCMTokens()));
- cleanupGCMTokens();
- logger.debug("initializing MPNS tokens cleanup: {} tokens", getInvalidMPNSTokens().size());
- deleteTokens("mpns", new ArrayList<>(getInvalidMPNSTokens()));
- cleanupMPNSTokens();
- logger.debug("initializing APNS tokens cleanup: {} tokens", getInvalidAPNSTokens().size());
- deleteTokens("apns", new ArrayList<>(getInvalidAPNSTokens()));
- cleanupMPNSTokens();
- }
- }
- private void deleteTokens(String type, List<String> devices) {
- if (devices.size() > 0) {
- List<ExternalToken> list = devices.stream()
- .map(d -> new ExternalToken(null, type, d, null)).collect(Collectors.toList());
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
- rest.exchange("http://api.juick.com/notifications",
- HttpMethod.DELETE, new HttpEntity<>(list, headers), new ParameterizedTypeReference<Void>() {
- });
- }
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/PushServer.java b/juick-notifications/src/main/java/com/juick/components/PushServer.java
deleted file mode 100644
index a590c2d1..00000000
--- a/juick-notifications/src/main/java/com/juick/components/PushServer.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.juick.components;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class PushServer {
-
- public static void main(String[] args) {
- SpringApplication app = new SpringApplication(PushServer.class);
- app.setWebApplicationType(WebApplicationType.NONE);
- app.run(args);
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/configuration/APNSConfiguration.java b/juick-notifications/src/main/java/com/juick/components/configuration/APNSConfiguration.java
deleted file mode 100644
index fbc17bc9..00000000
--- a/juick-notifications/src/main/java/com/juick/components/configuration/APNSConfiguration.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.juick.components.configuration;
-
-import com.juick.components.APNSManager;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Created by vital on 28.03.2017.
- */
-@Configuration
-@ConditionalOnProperty(name = "ios_p8_key")
-public class APNSConfiguration {
- @Bean
- public APNSManager apnsManager() {
- return new APNSManager();
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/configuration/GCMConfiguration.java b/juick-notifications/src/main/java/com/juick/components/configuration/GCMConfiguration.java
deleted file mode 100644
index 68d9f017..00000000
--- a/juick-notifications/src/main/java/com/juick/components/configuration/GCMConfiguration.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.juick.components.configuration;
-
-import com.juick.components.FirebaseManager;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Created by vital on 29.03.2017.
- */
-@Configuration
-@ConditionalOnProperty(name = "gcm_key")
-public class GCMConfiguration {
-
- @Bean
- public FirebaseManager firebaseManager() {
- return new FirebaseManager();
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java b/juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java
deleted file mode 100644
index deb0cb5b..00000000
--- a/juick-notifications/src/main/java/com/juick/components/configuration/JuickServerWebsocketConfiguration.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.juick.components.configuration;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.juick.components.NotificationsManager;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
-import org.springframework.http.client.InterceptingClientHttpRequestFactory;
-import org.springframework.http.client.support.BasicAuthorizationInterceptor;
-import org.springframework.scheduling.TaskScheduler;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
-import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.socket.client.WebSocketConnectionManager;
-import org.springframework.web.socket.client.standard.StandardWebSocketClient;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import javax.inject.Inject;
-import java.util.Collections;
-import java.util.List;
-
-@Configuration
-@EnableScheduling
-public class JuickServerWebsocketConfiguration {
- private static final Logger logger = LoggerFactory.getLogger(JuickServerWebsocketConfiguration.class);
- @Value("${websocket_url:ws://localhost:8080/ws/}")
- private String baseUri;
- @Value("${api_user:juick}")
- private String serviceUser;
- @Value("${api_password:secret}")
- private String servicePassword;
- @Inject
- ObjectMapper jsonMapper;
- @Inject
- private NotificationsManager notificationsManager;
- @Bean
- public RestTemplate rest() {
- RestTemplate rest = new RestTemplate();
- List<ClientHttpRequestInterceptor> interceptors = Collections.singletonList(
- new BasicAuthorizationInterceptor(serviceUser, servicePassword));
-
- rest.setRequestFactory(new InterceptingClientHttpRequestFactory(rest.getRequestFactory(), interceptors));
- return rest;
- }
- @Bean
- public WebSocketConnectionManager connectionManager() {
- String hash = StringUtils.EMPTY;
- try {
- ResponseEntity<String> response = rest().exchange("https://api.juick.com/auth",
- HttpMethod.GET, null, String.class);
- hash = response.getBody();
- } catch (HttpClientErrorException e) {
- logger.warn("service component is not authenticated", e);
- }
- String websocketURI = UriComponentsBuilder.fromUriString(baseUri)
- .queryParam("hash", hash).build().toUriString();
- WebSocketConnectionManager manager = new WebSocketConnectionManager(client(), notificationsManager, websocketURI);
- return manager;
- }
- @Bean
- public StandardWebSocketClient client() {
- return new StandardWebSocketClient();
- }
- @Bean
- public TaskScheduler taskScheduler() {
- return new ConcurrentTaskScheduler();
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/configuration/MPNSConfiguration.java b/juick-notifications/src/main/java/com/juick/components/configuration/MPNSConfiguration.java
deleted file mode 100644
index 4235486c..00000000
--- a/juick-notifications/src/main/java/com/juick/components/configuration/MPNSConfiguration.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.juick.components.configuration;
-
-import com.juick.components.MPNSManager;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Created by vital on 29.03.2017.
- */
-@Configuration
-@ConditionalOnProperty(name = "wns_application_sip")
-public class MPNSConfiguration {
- @Bean
- public MPNSManager mpnsClient() {
- return new MPNSManager();
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/mpns/MPNSError.java b/juick-notifications/src/main/java/com/juick/components/mpns/MPNSError.java
deleted file mode 100644
index de27641e..00000000
--- a/juick-notifications/src/main/java/com/juick/components/mpns/MPNSError.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.juick.components.mpns;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Created by vitalyster on 28.11.2016.
- */
-public class MPNSError {
- private String error;
- private String errorDescription;
-
- @JsonProperty("error")
- public String getError() {
- return error;
- }
-
- public void setError(String error) {
- this.error = error;
- }
-
- @JsonProperty("error_description")
- public String getErrorDescription() {
- return errorDescription;
- }
-
- public void setErrorDescription(String errorDescription) {
- this.errorDescription = errorDescription;
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/mpns/MPNSToken.java b/juick-notifications/src/main/java/com/juick/components/mpns/MPNSToken.java
deleted file mode 100644
index cd36831e..00000000
--- a/juick-notifications/src/main/java/com/juick/components/mpns/MPNSToken.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.juick.components.mpns;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Created by vitalyster on 28.11.2016.
- */
-public class MPNSToken {
- private String tokenType;
- private String accessToken;
- private String expiresIn;
-
- @JsonProperty("token_type")
- public String getTokenType() {
- return tokenType;
- }
-
- public void setTokenType(String tokenType) {
- this.tokenType = tokenType;
- }
-
- @JsonProperty("access_token")
- public String getAccessToken() {
- return accessToken;
- }
-
- public void setAccessToken(String accessToken) {
- this.accessToken = accessToken;
- }
-
- @JsonProperty("expires_in")
- public String getExpiresIn() {
- return expiresIn;
- }
-
- public void setExpiresIn(String expiresIn) {
- this.expiresIn = expiresIn;
- }
-}
diff --git a/juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java b/juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java
deleted file mode 100644
index b490c154..00000000
--- a/juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.juick.components.service;
-
-import com.juick.service.component.DisconnectedEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationListener;
-import org.springframework.stereotype.Component;
-import org.springframework.web.socket.client.WebSocketConnectionManager;
-
-import javax.annotation.Nonnull;
-import javax.inject.Inject;
-
-@Component
-public class JuickServerReconnectManager implements ApplicationListener<DisconnectedEvent> {
- private static Logger logger = LoggerFactory.getLogger(JuickServerReconnectManager.class);
- @Inject
- private WebSocketConnectionManager webSocketConnectionManager;
- @Override
- public void onApplicationEvent(@Nonnull DisconnectedEvent event) {
- logger.info("retrying...");
- webSocketConnectionManager.stop();
- webSocketConnectionManager.start();
- }
-}