Обработка пакета 16 с пуш токенами
This commit is contained in:
@@ -9,6 +9,7 @@ import com.rosetta.im.executors.Executor0Handshake;
|
|||||||
import com.rosetta.im.executors.Executor10RequestUpdate;
|
import com.rosetta.im.executors.Executor10RequestUpdate;
|
||||||
import com.rosetta.im.executors.Executor11Typeing;
|
import com.rosetta.im.executors.Executor11Typeing;
|
||||||
import com.rosetta.im.executors.Executor15RequestTransport;
|
import com.rosetta.im.executors.Executor15RequestTransport;
|
||||||
|
import com.rosetta.im.executors.Executor16PushNotification;
|
||||||
import com.rosetta.im.executors.Executor1UserInfo;
|
import com.rosetta.im.executors.Executor1UserInfo;
|
||||||
import com.rosetta.im.executors.Executor24DeviceResolve;
|
import com.rosetta.im.executors.Executor24DeviceResolve;
|
||||||
import com.rosetta.im.executors.Executor3Search;
|
import com.rosetta.im.executors.Executor3Search;
|
||||||
@@ -27,6 +28,7 @@ import com.rosetta.im.packet.Packet0Handshake;
|
|||||||
import com.rosetta.im.packet.Packet10RequestUpdate;
|
import com.rosetta.im.packet.Packet10RequestUpdate;
|
||||||
import com.rosetta.im.packet.Packet11Typeing;
|
import com.rosetta.im.packet.Packet11Typeing;
|
||||||
import com.rosetta.im.packet.Packet15RequestTransport;
|
import com.rosetta.im.packet.Packet15RequestTransport;
|
||||||
|
import com.rosetta.im.packet.Packet16PushNotification;
|
||||||
import com.rosetta.im.packet.Packet1UserInfo;
|
import com.rosetta.im.packet.Packet1UserInfo;
|
||||||
import com.rosetta.im.packet.Packet23DeviceList;
|
import com.rosetta.im.packet.Packet23DeviceList;
|
||||||
import com.rosetta.im.packet.Packet24DeviceResolve;
|
import com.rosetta.im.packet.Packet24DeviceResolve;
|
||||||
@@ -62,6 +64,17 @@ public class Boot {
|
|||||||
private Configuration configuration;
|
private Configuration configuration;
|
||||||
private ServerConfiguration serverConfiguration;
|
private ServerConfiguration serverConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конструктор по умолчанию, использует порт 3000 для сервера
|
||||||
|
*/
|
||||||
|
public Boot() {
|
||||||
|
this(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Инициализатор приложения
|
||||||
|
* @param port Порт, на котором будет работать сервер. Если не указан, то будет использован порт 3000
|
||||||
|
*/
|
||||||
public Boot(int port) {
|
public Boot(int port) {
|
||||||
this.packetManager = new PacketManager();
|
this.packetManager = new PacketManager();
|
||||||
this.eventManager = new EventManager();
|
this.eventManager = new EventManager();
|
||||||
@@ -149,7 +162,11 @@ public class Boot {
|
|||||||
this.packetManager.registerPacket(9, Packet9DeviceNew.class);
|
this.packetManager.registerPacket(9, Packet9DeviceNew.class);
|
||||||
this.packetManager.registerPacket(10, Packet10RequestUpdate.class);
|
this.packetManager.registerPacket(10, Packet10RequestUpdate.class);
|
||||||
this.packetManager.registerPacket(11, Packet11Typeing.class);
|
this.packetManager.registerPacket(11, Packet11Typeing.class);
|
||||||
|
//RESERVED 12 PACKET AVATAR (unused)
|
||||||
|
//RESERVED 13 PACKET KERNEL UPDATE (unused)
|
||||||
|
//RESERVED 14 PACKET APP UPDATE (unused)
|
||||||
this.packetManager.registerPacket(15, Packet15RequestTransport.class);
|
this.packetManager.registerPacket(15, Packet15RequestTransport.class);
|
||||||
|
this.packetManager.registerPacket(16, Packet16PushNotification.class);
|
||||||
this.packetManager.registerPacket(23, Packet23DeviceList.class);
|
this.packetManager.registerPacket(23, Packet23DeviceList.class);
|
||||||
this.packetManager.registerPacket(24, Packet24DeviceResolve.class);
|
this.packetManager.registerPacket(24, Packet24DeviceResolve.class);
|
||||||
|
|
||||||
@@ -165,6 +182,7 @@ public class Boot {
|
|||||||
this.packetManager.registerExecutor(10, new Executor10RequestUpdate(this.serverConfiguration));
|
this.packetManager.registerExecutor(10, new Executor10RequestUpdate(this.serverConfiguration));
|
||||||
this.packetManager.registerExecutor(11, new Executor11Typeing(this.clientManager, this.packetManager));
|
this.packetManager.registerExecutor(11, new Executor11Typeing(this.clientManager, this.packetManager));
|
||||||
this.packetManager.registerExecutor(15, new Executor15RequestTransport(this.serverConfiguration));
|
this.packetManager.registerExecutor(15, new Executor15RequestTransport(this.serverConfiguration));
|
||||||
|
this.packetManager.registerExecutor(16, new Executor16PushNotification());
|
||||||
this.packetManager.registerExecutor(24, new Executor24DeviceResolve(this.clientManager, this.eventManager));
|
this.packetManager.registerExecutor(24, new Executor24DeviceResolve(this.clientManager, this.eventManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Значение по умолчанию.
|
// Значение по умолчанию.
|
||||||
return 8080;
|
return 3000;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -236,6 +236,7 @@ public abstract class Repository<T> {
|
|||||||
* @param noResultType если true, то не указывать тип результата в запросе, используется для запросов типа UPDATE и DELETE
|
* @param noResultType если true, то не указывать тип результата в запросе, используется для запросов типа UPDATE и DELETE
|
||||||
* @return список сущностей
|
* @return список сущностей
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public QuerySession<T> buildQuery(String queryString, HashMap<String, Object> parameters, boolean noResultType) {
|
public QuerySession<T> buildQuery(String queryString, HashMap<String, Object> parameters, boolean noResultType) {
|
||||||
Session session = HibernateUtil.openSession();
|
Session session = HibernateUtil.openSession();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.rosetta.im.executors;
|
||||||
|
|
||||||
|
import com.rosetta.im.Failures;
|
||||||
|
import com.rosetta.im.client.tags.ECIAuthentificate;
|
||||||
|
import com.rosetta.im.database.entity.User;
|
||||||
|
import com.rosetta.im.database.repository.UserRepository;
|
||||||
|
import com.rosetta.im.packet.Packet16PushNotification;
|
||||||
|
import com.rosetta.im.service.services.UserService;
|
||||||
|
|
||||||
|
import io.orprotocol.ProtocolException;
|
||||||
|
import io.orprotocol.client.Client;
|
||||||
|
import io.orprotocol.packet.PacketExecutor;
|
||||||
|
|
||||||
|
public class Executor16PushNotification extends PacketExecutor<Packet16PushNotification> {
|
||||||
|
|
||||||
|
private final UserRepository userRepository = new UserRepository();
|
||||||
|
private final UserService userService = new UserService(userRepository);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketReceived(Packet16PushNotification packet, Client client) throws Exception, ProtocolException {
|
||||||
|
ECIAuthentificate eciAuthentificate = client.getTag(ECIAuthentificate.class);
|
||||||
|
if(eciAuthentificate == null || !eciAuthentificate.hasAuthorized()){
|
||||||
|
/**
|
||||||
|
* Клиент не авторизован, нельзя подписывать его на уведомления
|
||||||
|
*/
|
||||||
|
client.disconnect(Failures.HANDSHAKE_NOT_COMPLETED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String notificationToken = packet.getNotificationToken();
|
||||||
|
if(notificationToken.isEmpty()){
|
||||||
|
/**
|
||||||
|
* Клиент прислал пустой токен, отписывать его от уведомлений не нужно, а подписывать бессмысленно, просто игнорируем этот пакет
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
User user = userService.fromClient(client);
|
||||||
|
switch (packet.getAction()) {
|
||||||
|
case SUBSCRIBE:
|
||||||
|
userService.subscribeToPushNotifications(user, notificationToken);
|
||||||
|
break;
|
||||||
|
case UNSUBSCRIBE:
|
||||||
|
userService.unsubscribeFromPushNotifications(user, notificationToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.rosetta.im.packet;
|
||||||
|
|
||||||
|
import com.rosetta.im.packet.runtime.NetworkNotificationAction;
|
||||||
|
|
||||||
|
import io.orprotocol.Stream;
|
||||||
|
import io.orprotocol.packet.Packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet16PushNotification бросается клиентом для подписки на пуш уведомления
|
||||||
|
*/
|
||||||
|
public class Packet16PushNotification extends Packet {
|
||||||
|
|
||||||
|
private String notificationToken;
|
||||||
|
private NetworkNotificationAction action;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Stream stream) {
|
||||||
|
this.notificationToken = stream.readString();
|
||||||
|
this.action = NetworkNotificationAction.fromCode(stream.readInt8());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream write() {
|
||||||
|
Stream stream = new Stream();
|
||||||
|
stream.writeInt16(this.packetId);
|
||||||
|
stream.writeString(notificationToken);
|
||||||
|
stream.writeInt8(action.getCode());
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить токен пуш уведомлений, который нужно подписать или отписать в зависимости от action
|
||||||
|
* @return токен пуш уведомлений
|
||||||
|
*/
|
||||||
|
public String getNotificationToken() {
|
||||||
|
return notificationToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить действие, которое нужно выполнить с токеном пуш уведомлений. SUBSCRIBE - подписать этот токен на пуш уведомления, UNSUBSCRIBE - отписать этот токен от пуш уведомлений
|
||||||
|
* @return действие, которое нужно выполнить с токеном пуш уведомлений
|
||||||
|
*/
|
||||||
|
public NetworkNotificationAction getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает токен пуш уведомлений, который нужно подписать или отписать в зависимости от action
|
||||||
|
* @param notificationToken токен пуш уведомлений
|
||||||
|
*/
|
||||||
|
public void setNotificationToken(String notificationToken) {
|
||||||
|
this.notificationToken = notificationToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Устанавливает действие, которое нужно выполнить с токеном пуш уведомлений. SUBSCRIBE - подписать этот токен на пуш уведомления, UNSUBSCRIBE - отписать этот токен от пуш уведомлений
|
||||||
|
* @param action действие, которое нужно выполнить с токеном пуш уведомлений
|
||||||
|
*/
|
||||||
|
public void setAction(NetworkNotificationAction action) {
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.rosetta.im.packet.runtime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Используется в Packet16PushNotification для указания действия, которое нужно выполнить с токеном пуш уведомлений.
|
||||||
|
*/
|
||||||
|
public enum NetworkNotificationAction {
|
||||||
|
/**
|
||||||
|
* Подписать этот токен на пуш уведомления. Если токен уже был подписан, то ничего не произойдет.
|
||||||
|
*/
|
||||||
|
SUBSCRIBE(0),
|
||||||
|
/**
|
||||||
|
* Отписать этот токен от пуш уведомлений. Если токен не был подписан, то ничего не произойдет.
|
||||||
|
*/
|
||||||
|
UNSUBSCRIBE(1);
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
NetworkNotificationAction(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkNotificationAction fromCode(int code) {
|
||||||
|
for (NetworkNotificationAction action : values()) {
|
||||||
|
if (action.code == code) {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown NetworkNotificationAction code: " + code);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,4 +60,34 @@ public class UserService extends Service<UserRepository> {
|
|||||||
return user != null;
|
return user != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Подписывает пользователя на пуш уведомления, добавляя токен в его список токенов. Если токен уже был добавлен, то ничего не произойдет.
|
||||||
|
* @param user пользователь, которого нужно подписать на пуш уведомления
|
||||||
|
* @param notificationToken токен пуш уведомлений, который нужно добавить пользователю. Если токен уже был добавлен, то ничего не произойдет
|
||||||
|
*/
|
||||||
|
public void subscribeToPushNotifications(User user, String notificationToken) {
|
||||||
|
List<String> tokens = user.getNotificationsTokens();
|
||||||
|
if(tokens.contains(notificationToken)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tokens.add(notificationToken);
|
||||||
|
user.setNotificationsTokens(tokens);
|
||||||
|
this.getRepository().update(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отписывает пользователя от пуш уведомлений, удаляя токен из его списка токенов. Если токена не было, то ничего не произойдет.
|
||||||
|
* @param user пользователь, которого нужно отписать от пуш уведомлений
|
||||||
|
* @param notificationToken токен пуш уведомлений, который нужно удалить у пользователя. Если токена не было, то ничего не произойдет
|
||||||
|
*/
|
||||||
|
public void unsubscribeFromPushNotifications(User user, String notificationToken) {
|
||||||
|
List<String> tokens = user.getNotificationsTokens();
|
||||||
|
if(!tokens.contains(notificationToken)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tokens.remove(notificationToken);
|
||||||
|
user.setNotificationsTokens(tokens);
|
||||||
|
this.getRepository().update(user);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ public class Server extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(WebSocket socket, ByteBuffer byteBuffer) {
|
public void onMessage(WebSocket socket, ByteBuffer byteBuffer) {
|
||||||
Client client = socket.getAttachment();
|
Client client = socket.getAttachment();
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ public class Client {
|
|||||||
* @param key Ключ данных.
|
* @param key Ключ данных.
|
||||||
* @return Значение данных.
|
* @return Значение данных.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends ECITag> T getTag(Class<? extends ECITag> eciTagClass) {
|
public <T extends ECITag> T getTag(Class<? extends ECITag> eciTagClass) {
|
||||||
return (T) this.eciTags.get(eciTagClass);
|
return (T) this.eciTags.get(eciTagClass);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user