mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 19:54:55 +00:00
was added firebase nitifying
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using FirebaseAdmin.Messaging;
|
||||
using Govor.Application.Interfaces.PushNotifications;
|
||||
using Govor.Application.Interfaces.PushNotifications.Models;
|
||||
|
||||
namespace Govor.Application.Services.PushNotifications.Providers;
|
||||
|
||||
public class FirebasePushProvider : IPushNotificationProvider
|
||||
{
|
||||
public string Name => "FCM";
|
||||
|
||||
public async Task<SendPushResult> SendToTokenAsync(string token, PushMessage message)
|
||||
{
|
||||
var msg = BuildFcmMessage(message, token: token);
|
||||
|
||||
try
|
||||
{
|
||||
string response = await FirebaseMessaging.DefaultInstance.SendAsync(msg);
|
||||
return new SendPushResult(1, 0, []);
|
||||
}
|
||||
catch (FirebaseMessagingException ex)
|
||||
{
|
||||
if (IsInvalidTokenError(ex))
|
||||
{
|
||||
return new SendPushResult(0, 1, [token]);
|
||||
}
|
||||
|
||||
throw; // return failed
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SendPushResult> SendMulticastAsync(IReadOnlyList<string> tokens, PushMessage message)
|
||||
{
|
||||
if (tokens.Count == 0)
|
||||
return new SendPushResult(0, 0, []);
|
||||
|
||||
var multicastMsg = new MulticastMessage
|
||||
{
|
||||
Tokens = tokens.ToList(),
|
||||
Notification = new Notification
|
||||
{
|
||||
Title = message.Title,
|
||||
Body = message.Body
|
||||
},
|
||||
Data = message.Data,
|
||||
Android = message.ChannelId != null ? new AndroidConfig
|
||||
{
|
||||
Notification = new AndroidNotification
|
||||
{
|
||||
ChannelId = message.ChannelId,
|
||||
Priority = NotificationPriority.HIGH
|
||||
}
|
||||
} : null
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var response = await FirebaseMessaging.DefaultInstance.SendEachForMulticastAsync(multicastMsg);
|
||||
|
||||
var failedTokens = new List<string>();
|
||||
|
||||
for (int i = 0; i < response.Responses.Count; i++)
|
||||
{
|
||||
if (!response.Responses[i].IsSuccess)
|
||||
{
|
||||
failedTokens.Add(tokens[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return new SendPushResult(
|
||||
response.SuccessCount,
|
||||
response.FailureCount,
|
||||
failedTokens
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new SendPushResult(0, tokens.Count, tokens.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private Message BuildFcmMessage(PushMessage pm, string? token = null)
|
||||
{
|
||||
var msg = new Message
|
||||
{
|
||||
Notification = new Notification { Title = pm.Title, Body = pm.Body },
|
||||
Data = pm.Data,
|
||||
Token = token
|
||||
};
|
||||
|
||||
if (pm.ChannelId is not null)
|
||||
{
|
||||
msg.Android = new AndroidConfig
|
||||
{
|
||||
Notification = new AndroidNotification { ChannelId = pm.ChannelId }
|
||||
};
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
private static bool IsInvalidTokenError(FirebaseMessagingException ex)
|
||||
{
|
||||
return ex.MessagingErrorCode is MessagingErrorCode.Unregistered
|
||||
or MessagingErrorCode.InvalidArgument
|
||||
or MessagingErrorCode.SenderIdMismatch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Govor.Application.Interfaces.PushNotifications;
|
||||
using Govor.Application.Interfaces.PushNotifications.Models;
|
||||
|
||||
namespace Govor.Application.Services.PushNotifications.Providers;
|
||||
|
||||
public class NullPushProvider : IPushNotificationProvider
|
||||
{
|
||||
public string Name => "NULL";
|
||||
|
||||
public Task<SendPushResult> SendToTokenAsync(string token, PushMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<SendPushResult> SendMulticastAsync(IReadOnlyList<string> tokens, PushMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using FirebaseAdmin.Messaging;
|
||||
using Govor.Application.Interfaces.PushNotifications;
|
||||
using Govor.Application.Interfaces.PushNotifications.Models;
|
||||
using Govor.Core.Repositories.PushTokens;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Govor.Application.Services.PushNotifications;
|
||||
|
||||
public class PushNotificationService : IPushNotificationService
|
||||
{
|
||||
private readonly IPushNotificationProvider _provider;
|
||||
private readonly IPushTokenRepository _tokenRepo;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public PushNotificationService(
|
||||
IPushNotificationProvider provider,
|
||||
IPushTokenRepository tokenRepo,
|
||||
ILogger<PushNotificationService> logger)
|
||||
{
|
||||
_provider = provider;
|
||||
_tokenRepo = tokenRepo;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task SendToUserAsync(Guid userId, string title, string body, string channelId, Dictionary<string, string>? data = null)
|
||||
{
|
||||
var tokens = await _tokenRepo.GetActiveTokensAsync(userId);
|
||||
if (tokens.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("No active push tokens for user {UserId}", userId);
|
||||
return;
|
||||
}
|
||||
|
||||
var message = new PushMessage
|
||||
{
|
||||
Title = title,
|
||||
Body = body,
|
||||
Data = data ?? new(),
|
||||
ChannelId = channelId
|
||||
};
|
||||
|
||||
var result = await _provider.SendMulticastAsync(tokens, message);
|
||||
|
||||
if (result.FailureCount > 0)
|
||||
{
|
||||
await _tokenRepo.RemoveTokensAsync(result.FailedTokens);
|
||||
_logger.LogWarning("Removed {Count} invalid FCM tokens for user {UserId}", result.FailureCount, userId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendToUsersAsync(IEnumerable<Guid> userIds, string title, string body, string channelId, Dictionary<string, string>? data = null)
|
||||
{
|
||||
if (userIds is null)
|
||||
throw new ArgumentNullException(nameof(userIds));
|
||||
|
||||
var tokens = (await _tokenRepo.GetActiveTokensUsersAsync(userIds)).AsReadOnly();
|
||||
if (tokens.Count == 0)
|
||||
return;
|
||||
|
||||
var result = await _provider.SendMulticastAsync(tokens, new PushMessage()
|
||||
{
|
||||
Title = title,
|
||||
Body = body,
|
||||
Data = data ?? new(),
|
||||
ChannelId = channelId
|
||||
});
|
||||
|
||||
if (result.FailureCount > 0)
|
||||
{
|
||||
await _tokenRepo.RemoveTokensAsync(result.FailedTokens);
|
||||
_logger.LogWarning("Removed {Count} invalid FCM tokens for users {Users}...", result.FailureCount, userIds);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendToSessionAsync(Guid sessionId, string title, string body, string channelId, Dictionary<string, string>? data = null)
|
||||
{
|
||||
var token = await _tokenRepo.GetActiveTokenBySessionAsync(sessionId);
|
||||
if(string.IsNullOrEmpty(token))
|
||||
return;
|
||||
|
||||
var result = await _provider.SendToTokenAsync(token, new PushMessage()
|
||||
{
|
||||
Title = title,
|
||||
Body = body,
|
||||
Data = data ?? new(),
|
||||
ChannelId = channelId
|
||||
});
|
||||
|
||||
if (result.FailureCount > 0)
|
||||
{
|
||||
await _tokenRepo.RemoveTokensAsync(result.FailedTokens);
|
||||
_logger.LogWarning("Removed {Count} invalid FCM tokens for session {Session}...", result.FailureCount, sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user