aboutsummaryrefslogtreecommitdiff
path: root/juick-notifications/src/main/java/com/juick/components/APNSManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'juick-notifications/src/main/java/com/juick/components/APNSManager.java')
-rw-r--r--juick-notifications/src/main/java/com/juick/components/APNSManager.java140
1 files changed, 140 insertions, 0 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
new file mode 100644
index 00000000..c0380847
--- /dev/null
+++ b/juick-notifications/src/main/java/com/juick/components/APNSManager.java
@@ -0,0 +1,140 @@
+package com.juick.components;
+
+import com.juick.ExternalToken;
+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;
+ @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());
+ String post = PlainTextFormatter.formatPost(jmsg);
+ String[] parts = post.split("\n", 2);
+ apnsPayloadBuilder.setAlertTitle(parts[0]).setAlertBody(parts[1]);
+ users.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) {
+ List<User> users = messageReadEvent.getUsers();
+ ApnsPayloadBuilder apnsPayloadBuilder = new ApnsPayloadBuilder();
+ users.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());
+ }
+ });
+ });
+ });
+ }
+ @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);
+ }
+ });
+ }
+}