aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/notificators/NotificatorTraccar.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/traccar/notificators/NotificatorTraccar.java')
-rw-r--r--src/main/java/org/traccar/notificators/NotificatorTraccar.java124
1 files changed, 117 insertions, 7 deletions
diff --git a/src/main/java/org/traccar/notificators/NotificatorTraccar.java b/src/main/java/org/traccar/notificators/NotificatorTraccar.java
index 5bcd18b5e..e354adccb 100644
--- a/src/main/java/org/traccar/notificators/NotificatorTraccar.java
+++ b/src/main/java/org/traccar/notificators/NotificatorTraccar.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Anton Tananaev (anton@traccar.org)
+ * Copyright 2020 - 2023 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,15 +15,125 @@
*/
package org.traccar.notificators;
-import org.traccar.Context;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.traccar.config.Config;
import org.traccar.config.Keys;
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+import org.traccar.model.User;
+import org.traccar.notification.NotificationFormatter;
+import org.traccar.session.cache.CacheManager;
+import org.traccar.storage.Storage;
+import org.traccar.storage.StorageException;
+import org.traccar.storage.query.Columns;
+import org.traccar.storage.query.Condition;
+import org.traccar.storage.query.Request;
-public class NotificatorTraccar extends NotificatorFirebase {
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import jakarta.json.JsonObject;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
- public NotificatorTraccar() {
- super(
- "https://www.traccar.org/push/",
- Context.getConfig().getString(Keys.NOTIFICATOR_TRACCAR_KEY));
+@Singleton
+public class NotificatorTraccar implements Notificator {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NotificatorTraccar.class);
+
+ private final NotificationFormatter notificationFormatter;
+ private final Client client;
+ private final Storage storage;
+ private final CacheManager cacheManager;
+
+ private final String url;
+ private final String key;
+
+ public static class NotificationObject {
+ @JsonProperty("title")
+ private String title;
+ @JsonProperty("body")
+ private String body;
+ @JsonProperty("sound")
+ private String sound;
+ }
+
+ public static class Message {
+ @JsonProperty("registration_ids")
+ private String[] tokens;
+ @JsonProperty("notification")
+ private NotificationObject notification;
+ }
+
+ @Inject
+ public NotificatorTraccar(
+ Config config, NotificationFormatter notificationFormatter, Client client,
+ Storage storage, CacheManager cacheManager) {
+ this.notificationFormatter = notificationFormatter;
+ this.client = client;
+ this.storage = storage;
+ this.cacheManager = cacheManager;
+ this.url = "https://www.traccar.org/push/";
+ this.key = config.getString(Keys.NOTIFICATOR_TRACCAR_KEY);
+ }
+
+ @Override
+ public void send(org.traccar.model.Notification notification, User user, Event event, Position position) {
+ if (user.hasAttribute("notificationTokens")) {
+
+ var shortMessage = notificationFormatter.formatMessage(user, event, position, "short");
+
+ NotificationObject item = new NotificationObject();
+ item.title = shortMessage.getSubject();
+ item.body = shortMessage.getBody();
+ item.sound = "default";
+
+ String[] tokenArray = user.getString("notificationTokens").split("[, ]");
+ List<String> registrationTokens = new ArrayList<>(Arrays.asList(tokenArray));
+
+ Message message = new Message();
+ message.tokens = user.getString("notificationTokens").split("[, ]");
+ message.notification = item;
+
+ var request = client.target(url).request().header("Authorization", "key=" + key);
+ try (Response result = request.post(Entity.json(message))) {
+ var json = result.readEntity(JsonObject.class);
+ List<String> failedTokens = new LinkedList<>();
+ var responses = json.getJsonArray("responses");
+ for (int i = 0; i < responses.size(); i++) {
+ var response = responses.getJsonObject(i);
+ if (!response.getBoolean("success")) {
+ var error = response.getJsonObject("error");
+ String errorCode = error.getString("code");
+ if (errorCode.equals("messaging/invalid-argument")
+ || errorCode.equals("messaging/registration-token-not-registered")) {
+ failedTokens.add(registrationTokens.get(i));
+ }
+ LOGGER.warn("Push user {} error - {}", user.getId(), error.getString("message"));
+ }
+ }
+ if (!failedTokens.isEmpty()) {
+ registrationTokens.removeAll(failedTokens);
+ if (registrationTokens.isEmpty()) {
+ user.getAttributes().remove("notificationTokens");
+ } else {
+ user.set("notificationTokens", String.join(",", registrationTokens));
+ }
+ storage.updateObject(user, new Request(
+ new Columns.Include("attributes"),
+ new Condition.Equals("id", user.getId())));
+ cacheManager.updateOrInvalidate(true, user);
+ }
+ } catch (StorageException e) {
+ LOGGER.warn("Push error", e);
+ }
+ }
}
}