Добавлены call-pushes

This commit is contained in:
RoyceDa
2026-04-01 16:06:35 +02:00
parent aa17dd8d9d
commit b07f76ba1e
7 changed files with 120 additions and 12 deletions

View File

@@ -82,8 +82,7 @@ public class FCM extends Pusher {
break;
case PushType.CALL:
/**
* Звонок для андроид используем high priority, чтобы уведомление доставлялось даже если устройство в режиме Doze,
* для iOS используем VoIP уведомление, которое доставляется даже если приложение убито
* Это только для Android, для iOS используется VoIP APNs с отдельным сертификатом
*/
androidConfig.setPriority(AndroidConfig.Priority.HIGH);
messageBuilder.setAndroidConfig(androidConfig.build());

View File

@@ -1,15 +1,94 @@
package im.rosetta.service.dispatch.push.dispatchers;
import java.io.File;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
import com.eatthepath.pushy.apns.ApnsClient;
import com.eatthepath.pushy.apns.ApnsClientBuilder;
import com.eatthepath.pushy.apns.PushNotificationResponse;
import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification;
import com.eatthepath.pushy.apns.util.TokenUtil;
import im.rosetta.service.dispatch.push.Pusher;
import im.rosetta.service.dispatch.runtime.PushType;
public class VoIPApns extends Pusher {
private ApnsClient client;
private String topic;
public VoIPApns(){
this.initializeApns();
}
private void initializeApns() {
try {
String p12Path = System.getenv("APNS_KEY_PATH");
String p12Password = System.getenv("APNS_P12_PASSWORD");
String bundleId = System.getenv("IOS_BUNDLE_ID");
if (p12Path == null || bundleId == null) {
throw new IllegalStateException("APNS_P12_PATH and IOS_BUNDLE_ID must be set");
}
this.topic = bundleId + ".voip";
this.client = new ApnsClientBuilder()
.setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST)
.setClientCredentials(new File(p12Path), p12Password)
.build();
} catch (Exception e) {
throw new RuntimeException("Failed to init VoIP APNs client", e);
}
}
@Override
public void sendPush(String token, HashMap<String, String> data) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'sendPush'");
if(data.get("type") != PushType.CALL) {
/**
* Для VoIP APNs отправляем уведомления только о входящих звонках
*/
return;
}
try {
String normalizedToken = TokenUtil.sanitizeTokenString(token);
String payload = """
{
"aps": { "content-available": 1 },
"type": "CALL",
"callId": "%s",
"from": "%s"
}
""".formatted(
escape(data.getOrDefault("callId", "")),
escape(data.getOrDefault("dialog", ""))
);
SimpleApnsPushNotification push = new SimpleApnsPushNotification(
normalizedToken,
topic,
payload,
null, // invalidation time
com.eatthepath.pushy.apns.DeliveryPriority.IMMEDIATE,
com.eatthepath.pushy.apns.PushType.VOIP // apns-push-type: voip
);
PushNotificationResponse<SimpleApnsPushNotification> response = client.sendNotification(push).get();
if (!response.isAccepted()) {
System.err.println("VoIP push rejected: " + response.getRejectionReason());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
private String escape(String v) {
return v == null ? "" : v.replace("\\", "\\\\").replace("\"", "\\\"");
}
}