Merge pull request 'Исправление ошибок и новые уведомления' (#16) from dev into main
All checks were successful
Build rosetta-wss / build (push) Successful in 4m39s
All checks were successful
Build rosetta-wss / build (push) Successful in 4m39s
Reviewed-on: #16
This commit was merged in pull request #16.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
name: Build rosetta-wss
|
name: Build rosetta-wss
|
||||||
|
run-name: Build and Deploy WSS
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package im.rosetta.client;
|
package im.rosetta.client;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import im.rosetta.client.tags.ECIAuthentificate;
|
import im.rosetta.client.tags.ECIAuthentificate;
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ public class ClientManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClientConnected(String publicKey) {
|
public boolean isClientConnected(String publicKey) {
|
||||||
HashSet<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
Set<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
||||||
if(clients == null){
|
if(clients == null){
|
||||||
/**
|
/**
|
||||||
* Нет клиентов с таким публичным ключом
|
* Нет клиентов с таким публичным ключом
|
||||||
@@ -59,7 +59,7 @@ public class ClientManager {
|
|||||||
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
* @throws ProtocolException если произошла ошибка при отправке пакета клиенту
|
||||||
*/
|
*/
|
||||||
public void sendPacketToAuthorizedPK(String publicKey, Packet packet) throws ProtocolException {
|
public void sendPacketToAuthorizedPK(String publicKey, Packet packet) throws ProtocolException {
|
||||||
HashSet<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
Set<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
||||||
if(clients == null){
|
if(clients == null){
|
||||||
/**
|
/**
|
||||||
* Нет клиентов с таким публичным ключом, значит отправлять некому
|
* Нет клиентов с таким публичным ключом, значит отправлять некому
|
||||||
@@ -91,7 +91,7 @@ public class ClientManager {
|
|||||||
*/
|
*/
|
||||||
public void retranslate(Client client, Packet packet) throws ProtocolException{
|
public void retranslate(Client client, Packet packet) throws ProtocolException{
|
||||||
ECIAuthentificate eciAuthentificate = client.getTag(ECIAuthentificate.class);
|
ECIAuthentificate eciAuthentificate = client.getTag(ECIAuthentificate.class);
|
||||||
HashSet<Client> clients = this.clientIndexer
|
Set<Client> clients = this.clientIndexer
|
||||||
.getClients(ECIAuthentificate.class, "publicKey", eciAuthentificate.getPublicKey());
|
.getClients(ECIAuthentificate.class, "publicKey", eciAuthentificate.getPublicKey());
|
||||||
if(clients == null){
|
if(clients == null){
|
||||||
/**
|
/**
|
||||||
@@ -129,7 +129,7 @@ public class ClientManager {
|
|||||||
* @return список клиентов с таким публичным ключом, может быть пустым, если клиентов с таким публичным ключом нет
|
* @return список клиентов с таким публичным ключом, может быть пустым, если клиентов с таким публичным ключом нет
|
||||||
*/
|
*/
|
||||||
public List<Client> getPKClients(String publicKey) {
|
public List<Client> getPKClients(String publicKey) {
|
||||||
HashSet<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
Set<Client> clients = this.clientIndexer.getClients(ECIAuthentificate.class, "publicKey", publicKey);
|
||||||
if(clients == null){
|
if(clients == null){
|
||||||
/**
|
/**
|
||||||
* Нет клиентов с таким публичным ключом
|
* Нет клиентов с таким публичным ключом
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import java.util.concurrent.Executors;
|
|||||||
import com.google.auth.oauth2.GoogleCredentials;
|
import com.google.auth.oauth2.GoogleCredentials;
|
||||||
import com.google.firebase.FirebaseApp;
|
import com.google.firebase.FirebaseApp;
|
||||||
import com.google.firebase.FirebaseOptions;
|
import com.google.firebase.FirebaseOptions;
|
||||||
|
import com.google.firebase.messaging.ApnsConfig;
|
||||||
|
import com.google.firebase.messaging.Aps;
|
||||||
|
import com.google.firebase.messaging.ApsAlert;
|
||||||
import com.google.firebase.messaging.FirebaseMessaging;
|
import com.google.firebase.messaging.FirebaseMessaging;
|
||||||
import com.google.firebase.messaging.Message;
|
import com.google.firebase.messaging.Message;
|
||||||
import com.google.firebase.messaging.Notification;
|
import com.google.firebase.messaging.Notification;
|
||||||
@@ -51,13 +54,7 @@ public class FirebaseDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void sendPushNotification(String publicKey, String title, String messageText, String senderPublicKey) {
|
||||||
* Отправляет push-уведомление пользователю с данным публичным ключом (асинхронно)
|
|
||||||
* @param publicKey публичный ключ пользователя
|
|
||||||
* @param title заголовок уведомления
|
|
||||||
* @param messageText текст уведомления
|
|
||||||
*/
|
|
||||||
public void sendPushNotification(String publicKey, String title, String messageText) {
|
|
||||||
executor.submit(() -> {
|
executor.submit(() -> {
|
||||||
try {
|
try {
|
||||||
List<String> tokens = userService.getNotificationsTokens(publicKey);
|
List<String> tokens = userService.getNotificationsTokens(publicKey);
|
||||||
@@ -72,6 +69,17 @@ public class FirebaseDispatcher {
|
|||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
.setBody(messageText)
|
.setBody(messageText)
|
||||||
.build())
|
.build())
|
||||||
|
.setApnsConfig(ApnsConfig.builder()
|
||||||
|
.setAps(Aps.builder()
|
||||||
|
.setMutableContent(true)
|
||||||
|
.setSound("default")
|
||||||
|
.setAlert(ApsAlert.builder()
|
||||||
|
.setTitle(title)
|
||||||
|
.setBody(messageText)
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.putData("sender_public_key", senderPublicKey)
|
||||||
.setToken(token)
|
.setToken(token)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -86,6 +94,30 @@ public class FirebaseDispatcher {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отправляет push-уведомление пользователю с данным публичным ключом (асинхронно)
|
||||||
|
* @param publicKey публичный ключ пользователя
|
||||||
|
* @param title заголовок уведомления
|
||||||
|
* @param messageText текст уведомления
|
||||||
|
*/
|
||||||
|
public void sendPushNotification(String publicKey, String title, String messageText) {
|
||||||
|
sendPushNotification(publicKey, title, messageText, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Отправляет push-уведомление нескольким пользователям (асинхронно)
|
||||||
|
* @param publicKeys список публичных ключей пользователей
|
||||||
|
* @param title заголовок уведомления
|
||||||
|
* @param messageText текст уведомления
|
||||||
|
*/
|
||||||
|
public void sendPushNotification(List<String> publicKeys, String title, String messageText, String senderPublicKey) {
|
||||||
|
executor.submit(() -> {
|
||||||
|
for (String publicKey : publicKeys) {
|
||||||
|
sendPushNotificationSync(publicKey, title, messageText, senderPublicKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Отправляет push-уведомление нескольким пользователям (асинхронно)
|
* Отправляет push-уведомление нескольким пользователям (асинхронно)
|
||||||
* @param publicKeys список публичных ключей пользователей
|
* @param publicKeys список публичных ключей пользователей
|
||||||
@@ -95,12 +127,12 @@ public class FirebaseDispatcher {
|
|||||||
public void sendPushNotification(List<String> publicKeys, String title, String messageText) {
|
public void sendPushNotification(List<String> publicKeys, String title, String messageText) {
|
||||||
executor.submit(() -> {
|
executor.submit(() -> {
|
||||||
for (String publicKey : publicKeys) {
|
for (String publicKey : publicKeys) {
|
||||||
sendPushNotificationSync(publicKey, title, messageText);
|
sendPushNotificationSync(publicKey, title, messageText, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendPushNotificationSync(String publicKey, String title, String messageText) {
|
private void sendPushNotificationSync(String publicKey, String title, String messageText, String senderPublicKey) {
|
||||||
try {
|
try {
|
||||||
List<String> tokens = userService.getNotificationsTokens(publicKey);
|
List<String> tokens = userService.getNotificationsTokens(publicKey);
|
||||||
if (tokens == null || tokens.isEmpty()) {
|
if (tokens == null || tokens.isEmpty()) {
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ import java.util.List;
|
|||||||
|
|
||||||
import im.rosetta.client.ClientManager;
|
import im.rosetta.client.ClientManager;
|
||||||
import im.rosetta.client.tags.ECIAuthentificate;
|
import im.rosetta.client.tags.ECIAuthentificate;
|
||||||
|
import im.rosetta.database.entity.User;
|
||||||
import im.rosetta.database.repository.BufferRepository;
|
import im.rosetta.database.repository.BufferRepository;
|
||||||
import im.rosetta.database.repository.GroupRepository;
|
import im.rosetta.database.repository.GroupRepository;
|
||||||
|
import im.rosetta.database.repository.UserRepository;
|
||||||
import im.rosetta.packet.Packet11Typeing;
|
import im.rosetta.packet.Packet11Typeing;
|
||||||
import im.rosetta.packet.Packet7Read;
|
import im.rosetta.packet.Packet7Read;
|
||||||
import im.rosetta.packet.base.PacketBaseDialog;
|
import im.rosetta.packet.base.PacketBaseDialog;
|
||||||
import im.rosetta.service.services.BufferService;
|
import im.rosetta.service.services.BufferService;
|
||||||
|
import im.rosetta.service.services.UserService;
|
||||||
import io.orprotocol.ProtocolException;
|
import io.orprotocol.ProtocolException;
|
||||||
import io.orprotocol.client.Client;
|
import io.orprotocol.client.Client;
|
||||||
import io.orprotocol.packet.PacketManager;
|
import io.orprotocol.packet.PacketManager;
|
||||||
@@ -29,6 +31,8 @@ public class MessageDispatcher {
|
|||||||
private final BufferRepository bufferRepository = new BufferRepository();
|
private final BufferRepository bufferRepository = new BufferRepository();
|
||||||
private final BufferService bufferService;
|
private final BufferService bufferService;
|
||||||
private final FirebaseDispatcher firebaseDispatcher = new FirebaseDispatcher();
|
private final FirebaseDispatcher firebaseDispatcher = new FirebaseDispatcher();
|
||||||
|
private final UserRepository userRepository = new UserRepository();
|
||||||
|
private final UserService userService = new UserService(userRepository);
|
||||||
|
|
||||||
public MessageDispatcher(ClientManager clientManager, PacketManager packetManager) {
|
public MessageDispatcher(ClientManager clientManager, PacketManager packetManager) {
|
||||||
this.clientManager = clientManager;
|
this.clientManager = clientManager;
|
||||||
@@ -101,7 +105,7 @@ public class MessageDispatcher {
|
|||||||
/**
|
/**
|
||||||
* Отправляем PUSH уведомление
|
* Отправляем PUSH уведомление
|
||||||
*/
|
*/
|
||||||
this.firebaseDispatcher.sendPushNotification(groupMembersPublicKeys, "Rosetta", "New message in group");
|
this.firebaseDispatcher.sendPushNotification(groupMembersPublicKeys, "Rosetta", "New message in group", toPublicKey.replace("#group:", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,7 +119,13 @@ public class MessageDispatcher {
|
|||||||
public void sendPeer(PacketBaseDialog packet, Client client, boolean bufferizationNeed) throws ProtocolException {
|
public void sendPeer(PacketBaseDialog packet, Client client, boolean bufferizationNeed) throws ProtocolException {
|
||||||
String fromPublicKey = packet.getFromPublicKey();
|
String fromPublicKey = packet.getFromPublicKey();
|
||||||
String toPublicKey = packet.getToPublicKey();
|
String toPublicKey = packet.getToPublicKey();
|
||||||
|
User user = this.userService.fromClient(client);
|
||||||
|
if(user == null){
|
||||||
|
/**
|
||||||
|
* Если пользователь не найден, то не отправляем сообщение, так как у нас нет информации о том, кто отправляет сообщение
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Ретранслируем сообщение ВСЕМ авторизованным сессиям отправителя КРОМЕ текущей,
|
* Ретранслируем сообщение ВСЕМ авторизованным сессиям отправителя КРОМЕ текущей,
|
||||||
* чтобы синхронизировать отправленные сообщения
|
* чтобы синхронизировать отправленные сообщения
|
||||||
@@ -154,7 +164,7 @@ public class MessageDispatcher {
|
|||||||
/**
|
/**
|
||||||
* Отправляем PUSH уведомление получателю
|
* Отправляем PUSH уведомление получателю
|
||||||
*/
|
*/
|
||||||
this.firebaseDispatcher.sendPushNotification(toPublicKey, "Rosetta", "New message");
|
this.firebaseDispatcher.sendPushNotification(toPublicKey, user.getTitle(), "New message");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package io.orprotocol.index;
|
package io.orprotocol.index;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import io.orprotocol.client.Client;
|
import io.orprotocol.client.Client;
|
||||||
@@ -19,14 +19,8 @@ public class ClientIndexer {
|
|||||||
* Ключ третьего уровня - значение поля.
|
* Ключ третьего уровня - значение поля.
|
||||||
* Значение - клиент.
|
* Значение - клиент.
|
||||||
* Структура: tagClass -> indexName -> indexValue -> Client
|
* Структура: tagClass -> indexName -> indexValue -> Client
|
||||||
*
|
|
||||||
*
|
|
||||||
* В качестве клиента используем HashSet потому что он очень хорош для операции contains,
|
|
||||||
* в отличие от ArrayList, который при поиске перебирает элементы один за другим,
|
|
||||||
* HashSet использует хэш таблицу и находит нужный объект почти
|
|
||||||
* мгновенно, независимо от того, 10 там элементов или миллион.
|
|
||||||
*/
|
*/
|
||||||
private final Map<Class<?>, Map<String, Map<Object, HashSet<Client>>>> indices
|
private final ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, ConcurrentHashMap<Object, Set<Client>>>> indices
|
||||||
= new ConcurrentHashMap<>();
|
= new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public <T extends ECITag> void indexTag(Client client, Class<T> tagClass, T tag) {
|
public <T extends ECITag> void indexTag(Client client, Class<T> tagClass, T tag) {
|
||||||
@@ -53,7 +47,7 @@ public class ClientIndexer {
|
|||||||
* Если использовать putIfAbsent, то он вернет null если значение там уже есть,
|
* Если использовать putIfAbsent, то он вернет null если значение там уже есть,
|
||||||
* что не подходит
|
* что не подходит
|
||||||
*/
|
*/
|
||||||
Map<String, Map<Object, HashSet<Client>>> tagIndices = this.indices.computeIfAbsent(
|
ConcurrentHashMap<String, ConcurrentHashMap<Object, Set<Client>>> tagIndices = this.indices.computeIfAbsent(
|
||||||
tagClass,
|
tagClass,
|
||||||
k -> new ConcurrentHashMap<>());
|
k -> new ConcurrentHashMap<>());
|
||||||
|
|
||||||
@@ -76,7 +70,7 @@ public class ClientIndexer {
|
|||||||
/**
|
/**
|
||||||
* Инициализируем имя индекса, почему compute, а не put - написано выше
|
* Инициализируем имя индекса, почему compute, а не put - написано выше
|
||||||
*/
|
*/
|
||||||
Map<Object, HashSet<Client>> index = tagIndices.computeIfAbsent(
|
Map<Object, Set<Client>> index = tagIndices.computeIfAbsent(
|
||||||
indexName,
|
indexName,
|
||||||
k -> new ConcurrentHashMap<>()
|
k -> new ConcurrentHashMap<>()
|
||||||
);
|
);
|
||||||
@@ -86,7 +80,7 @@ public class ClientIndexer {
|
|||||||
* с одинковыми индексами, хотя такого лучше избегать, желательно чтобы индексы
|
* с одинковыми индексами, хотя такого лучше избегать, желательно чтобы индексы
|
||||||
* были уникальными, тогда обработка будет быстрее всего
|
* были уникальными, тогда обработка будет быстрее всего
|
||||||
*/
|
*/
|
||||||
HashSet<Client> clients = index.computeIfAbsent(indexValue, k -> new HashSet<>());
|
Set<Client> clients = index.computeIfAbsent(indexValue, k -> ConcurrentHashMap.newKeySet());
|
||||||
/**
|
/**
|
||||||
* Добавляем клиента в инициализиованный индекс
|
* Добавляем клиента в инициализиованный индекс
|
||||||
*/
|
*/
|
||||||
@@ -117,7 +111,7 @@ public class ClientIndexer {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public <T extends ECITag> void removeTagIndex(Client client, Class<T> tagClass) {
|
public <T extends ECITag> void removeTagIndex(Client client, Class<T> tagClass) {
|
||||||
Map<String, Map<Object, HashSet<Client>>> tagIndices = indices.get(tagClass);
|
ConcurrentHashMap<String, ConcurrentHashMap<Object, Set<Client>>> tagIndices = indices.get(tagClass);
|
||||||
if (tagIndices == null) {
|
if (tagIndices == null) {
|
||||||
/**
|
/**
|
||||||
* Индекса и так не было, удалять нечего
|
* Индекса и так не было, удалять нечего
|
||||||
@@ -128,12 +122,12 @@ public class ClientIndexer {
|
|||||||
/**
|
/**
|
||||||
* Удаляем все ключи indexName по tagClass если Client == client
|
* Удаляем все ключи indexName по tagClass если Client == client
|
||||||
*/
|
*/
|
||||||
for (Map<Object, HashSet<Client>> index : tagIndices.values()) {
|
for (ConcurrentHashMap<Object, Set<Client>> index : tagIndices.values()) {
|
||||||
/**
|
/**
|
||||||
* contains всегда использует переопределенный equals, по этому
|
* contains всегда использует переопределенный equals, по этому
|
||||||
* обьекты клиентов сравниваются нормально
|
* обьекты клиентов сравниваются нормально
|
||||||
*/
|
*/
|
||||||
for(HashSet<Client> clients : index.values()){
|
for(Set<Client> clients : index.values()){
|
||||||
if(!clients.contains(client)){
|
if(!clients.contains(client)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -147,9 +141,9 @@ public class ClientIndexer {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public void removeClientFromIndex(Client client) {
|
public void removeClientFromIndex(Client client) {
|
||||||
for(Map<String, Map<Object, HashSet<Client>>> tagIndices : this.indices.values()){
|
for(Map<String, ConcurrentHashMap<Object, Set<Client>>> tagIndices : this.indices.values()){
|
||||||
for(Map<Object, HashSet<Client>> index : tagIndices.values()){
|
for(Map<Object, Set<Client>> index : tagIndices.values()){
|
||||||
for(HashSet<Client> clients : index.values()){
|
for(Set<Client> clients : index.values()){
|
||||||
/**
|
/**
|
||||||
* Этот тройной цикл не такой страшный, так как мы всего лишь
|
* Этот тройной цикл не такой страшный, так как мы всего лишь
|
||||||
* проходим по всем тегам (их немного), дальше идем по всем значениям в тегах
|
* проходим по всем тегам (их немного), дальше идем по всем значениям в тегах
|
||||||
@@ -173,7 +167,7 @@ public class ClientIndexer {
|
|||||||
* @param indexValue значение в теге
|
* @param indexValue значение в теге
|
||||||
* @return список клиентов с заданными значениями
|
* @return список клиентов с заданными значениями
|
||||||
*/
|
*/
|
||||||
public <T extends ECITag> HashSet<Client> getClients(Class<T> tagClass, String indexName, Object indexValue) {
|
public <T extends ECITag> Set<Client> getClients(Class<T> tagClass, String indexName, Object indexValue) {
|
||||||
if(indexName == null || indexValue == null){
|
if(indexName == null || indexValue == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -181,12 +175,12 @@ public class ClientIndexer {
|
|||||||
/**
|
/**
|
||||||
* Получение по индексу простое, так как каждое из заданных значений и есть ключ
|
* Получение по индексу простое, так как каждое из заданных значений и есть ключ
|
||||||
*/
|
*/
|
||||||
Map<String, Map<Object, HashSet<Client>>> tagIndices = indices.get(tagClass);
|
ConcurrentHashMap<String, ConcurrentHashMap<Object, Set<Client>>> tagIndices = indices.get(tagClass);
|
||||||
if (tagIndices == null) {
|
if (tagIndices == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Object, HashSet<Client>> index = tagIndices.get(indexName);
|
ConcurrentHashMap<Object, Set<Client>> index = tagIndices.get(indexName);
|
||||||
if (index == null) {
|
if (index == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user