mirror of
https://github.com/Stone-Red-Software/StoneRed.NetificationApi.git
synced 2026-09-04 00:36:05 +02:00
Initial commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using StoneRed.NetificationApi.Client;
|
||||
using StoneRed.NetificationApi.Client.Models;
|
||||
using StoneRed.NetificationApi.Server;
|
||||
using StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
using StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
const string userId = "<UserId>";
|
||||
const string notificationId = "<NotifcationId>";
|
||||
const string clientId = "<ClientId>";
|
||||
const string clientSecret = "<ClientSecret>";
|
||||
|
||||
Console.WriteLine("Start client");
|
||||
NotificationApiClient notificationApiClient = new NotificationApiClient("test", clientId, clientSecret, false);
|
||||
await notificationApiClient.Start();
|
||||
Console.WriteLine("Client started");
|
||||
|
||||
notificationApiClient.RequestNotifications();
|
||||
|
||||
notificationApiClient.RequestedNotificationsReceived += (sender, args) =>
|
||||
{
|
||||
Console.WriteLine("Requested notifications received");
|
||||
foreach (NotificationReceivedData notificationReceiveData in args.Notifications)
|
||||
{
|
||||
Console.WriteLine($"Notification received: {notificationReceiveData.Id}");
|
||||
}
|
||||
};
|
||||
|
||||
notificationApiClient.NewNotificationsReceived += (sender, args) =>
|
||||
{
|
||||
Console.WriteLine("New notifications received");
|
||||
foreach (NotificationReceivedData notificationReceiveData in args.Notifications)
|
||||
{
|
||||
Console.WriteLine($"New Notification received: {notificationReceiveData.Id}");
|
||||
}
|
||||
};
|
||||
|
||||
NotificationApiServer notificationApiServer = new NotificationApiServer(clientId, clientSecret, false);
|
||||
|
||||
Console.WriteLine("Identify user");
|
||||
await notificationApiServer.Identify(new IdentifyUserData
|
||||
{
|
||||
UserId = userId,
|
||||
Email = "[email protected]"
|
||||
});
|
||||
Console.WriteLine("User identified");
|
||||
|
||||
Console.WriteLine("Send notification");
|
||||
SendNotificationData sendNotificationData = new SendNotificationData
|
||||
{
|
||||
NotificationId = notificationId,
|
||||
User = new NotificationUser
|
||||
{
|
||||
Id = userId
|
||||
}
|
||||
};
|
||||
|
||||
await notificationApiServer.Send(sendNotificationData);
|
||||
Console.WriteLine("Notification sent");
|
||||
|
||||
Console.ReadLine();
|
||||
Console.WriteLine("Stop client");
|
||||
await notificationApiClient.Stop();
|
||||
Console.WriteLine("Client stopped");
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StoneRed.NetificationApi\StoneRed.NetificationApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34616.47
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StoneRed.NetificationApi", "StoneRed.NetificationApi\StoneRed.NetificationApi.csproj", "{DED64841-1673-47C9-99E4-BD0DC01C1F2E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StoneRed.NetificationApi.Example", "StoneRed.NetificationApi.Example\StoneRed.NetificationApi.Example.csproj", "{8A7CD1F7-78E4-4265-A10A-E116D6639078}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DED64841-1673-47C9-99E4-BD0DC01C1F2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DED64841-1673-47C9-99E4-BD0DC01C1F2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DED64841-1673-47C9-99E4-BD0DC01C1F2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DED64841-1673-47C9-99E4-BD0DC01C1F2E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8A7CD1F7-78E4-4265-A10A-E116D6639078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8A7CD1F7-78E4-4265-A10A-E116D6639078}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8A7CD1F7-78E4-4265-A10A-E116D6639078}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A7CD1F7-78E4-4265-A10A-E116D6639078}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {35AE5460-29CB-4E09-A2AA-9055E6FBEF12}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace StoneRed.NetificationApi.Client.Models;
|
||||
|
||||
public class NotificationReceivedData
|
||||
{
|
||||
public required string Id { get; set; }
|
||||
public required bool Seen { get; set; }
|
||||
public required string Title { get; set; }
|
||||
public required string RedirectURL { get; set; }
|
||||
public required string ImageURL { get; set; }
|
||||
public required DateTime Date { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace StoneRed.NetificationApi.Client.Models;
|
||||
|
||||
public class NotificationsReceivedEventArgs(List<NotificationReceivedData> notifications) : EventArgs
|
||||
{
|
||||
public List<NotificationReceivedData> Notifications { get; set; } = notifications;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using StoneRed.NetificationApi.Client.Models;
|
||||
using StoneRed.NetificationApi.Client.Payloads;
|
||||
using StoneRed.NetificationApi.Utilities;
|
||||
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Net.WebSockets;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Web;
|
||||
|
||||
using Websocket.Client;
|
||||
|
||||
namespace StoneRed.NetificationApi.Client;
|
||||
|
||||
public class NotificationApiClient
|
||||
{
|
||||
public event EventHandler<NotificationsReceivedEventArgs>? RequestedNotificationsReceived;
|
||||
|
||||
public event EventHandler<NotificationsReceivedEventArgs>? NewNotificationsReceived;
|
||||
|
||||
private readonly WebsocketClient client;
|
||||
|
||||
public NotificationApiClient(string userId, string clientId, string clientSecret, bool secureMode, string baseAddress = "wss://ws.notificationapi.com")
|
||||
{
|
||||
UriBuilder uriBuilder = new UriBuilder(baseAddress);
|
||||
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||
query["envId"] = clientId;
|
||||
query["userId"] = userId;
|
||||
|
||||
if (secureMode)
|
||||
{
|
||||
query["userIdHash"] = UserIdHasher.Hash(userId, clientSecret);
|
||||
}
|
||||
|
||||
uriBuilder.Query = query.ToString();
|
||||
|
||||
client = new WebsocketClient(uriBuilder.Uri);
|
||||
|
||||
_ = client.MessageReceived.Subscribe(msg =>
|
||||
{
|
||||
Debug.WriteLine("Message:" + msg.Text);
|
||||
});
|
||||
|
||||
_ = client.MessageReceived
|
||||
.Where(msg => msg.Text is not null)
|
||||
.Where(msg => WebsocketMessageComparer.Compare(msg.Text, "inapp_web/notifications"))
|
||||
.Select(msg => WebsocketMessageConverter.ConvertWebsocketMessage<NotificationsReceivedPayload>(msg.Text!))
|
||||
.Subscribe(msg =>
|
||||
{
|
||||
if (msg.Payload is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RequestedNotificationsReceived?.Invoke(this, new NotificationsReceivedEventArgs(msg.Payload.Notifications));
|
||||
});
|
||||
|
||||
_ = client.MessageReceived
|
||||
.Where(msg => msg.Text is not null)
|
||||
.Where(msg => WebsocketMessageComparer.Compare(msg.Text, "inapp_web/new_notifications"))
|
||||
.Select(msg => WebsocketMessageConverter.ConvertWebsocketMessage<NotificationsReceivedPayload>(msg.Text!))
|
||||
.Subscribe(msg =>
|
||||
{
|
||||
if (msg.Payload is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NewNotificationsReceived?.Invoke(this, new NotificationsReceivedEventArgs(msg.Payload.Notifications));
|
||||
});
|
||||
}
|
||||
|
||||
public Task Start()
|
||||
{
|
||||
return client.StartOrFail();
|
||||
}
|
||||
|
||||
public bool RequestNotifications()
|
||||
{
|
||||
WebsocketMessage<object> message = new("inapp_web/notifications")
|
||||
{
|
||||
Payload = new
|
||||
{
|
||||
count = 50
|
||||
}
|
||||
};
|
||||
|
||||
return client.Send(JsonSerializer.Serialize(message, Configuration.JsonSerializerOptions));
|
||||
}
|
||||
|
||||
public Task Stop()
|
||||
{
|
||||
return client.StopOrFail(WebSocketCloseStatus.NormalClosure, "Normal closure");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using StoneRed.NetificationApi.Client.Models;
|
||||
|
||||
namespace StoneRed.NetificationApi.Client.Payloads;
|
||||
|
||||
internal class NotificationsReceivedPayload
|
||||
{
|
||||
public required List<NotificationReceivedData> Notifications { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Client;
|
||||
|
||||
internal class WebsocketMessage : IWebsocketMessage
|
||||
{
|
||||
public required string Route { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public WebsocketMessage(string route)
|
||||
{
|
||||
Route = route;
|
||||
}
|
||||
|
||||
public WebsocketMessage()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal class WebsocketMessage<T> : IWebsocketMessage
|
||||
{
|
||||
public required string Route { get; set; }
|
||||
public T? Payload { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public WebsocketMessage(string route)
|
||||
{
|
||||
Route = route;
|
||||
}
|
||||
|
||||
public WebsocketMessage()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal interface IWebsocketMessage
|
||||
{
|
||||
string Route { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
|
||||
public class IdentifyUserData
|
||||
{
|
||||
[JsonIgnore]
|
||||
public required string UserId { get; set; }
|
||||
|
||||
public string? Email { get; set; }
|
||||
|
||||
[JsonPropertyName("number")]
|
||||
public string? TelephoneNumber { get; set; }
|
||||
|
||||
public List<NotificationPushToken>? PushTokens { get; set; }
|
||||
public List<NotificationWebPushToken>? WebPushTokens { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public IdentifyUserData(string userId)
|
||||
{
|
||||
UserId = userId;
|
||||
}
|
||||
|
||||
public IdentifyUserData()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
|
||||
public enum NotificationPushProviders
|
||||
{
|
||||
FCM,
|
||||
APM
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
|
||||
public class NotificationPushToken
|
||||
{
|
||||
public required NotificationPushProviders Type { get; set; }
|
||||
public required string Token { get; set; }
|
||||
public required NotificationPushTokenDevice Device { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationPushToken(NotificationPushProviders type, string token, NotificationPushTokenDevice device)
|
||||
{
|
||||
Type = type;
|
||||
Token = token;
|
||||
Device = device;
|
||||
}
|
||||
|
||||
public NotificationPushToken()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
|
||||
public class NotificationPushTokenDevice
|
||||
{
|
||||
[JsonPropertyName("app_id")]
|
||||
public string? AppId { get; set; }
|
||||
|
||||
[JsonPropertyName("ad_id")]
|
||||
public string? AdId { get; set; }
|
||||
|
||||
[JsonPropertyName("device_id")]
|
||||
public required string DeviceId { get; set; }
|
||||
|
||||
public string? Platform { get; set; }
|
||||
public string? Manufacturer { get; set; }
|
||||
public string? Model { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationPushTokenDevice(string deviceId)
|
||||
{
|
||||
DeviceId = deviceId;
|
||||
}
|
||||
|
||||
public NotificationPushTokenDevice()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
|
||||
public class NotificationWebPushToken
|
||||
{
|
||||
public required NotificationWebPushTokenSub Sub { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationWebPushToken(NotificationWebPushTokenSub sub)
|
||||
{
|
||||
Sub = sub;
|
||||
}
|
||||
|
||||
public NotificationWebPushToken()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
|
||||
public class NotificationWebPushTokenKeys
|
||||
{
|
||||
public required string P256dh { get; set; }
|
||||
public required string Auth { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationWebPushTokenKeys(string p256dh, string auth)
|
||||
{
|
||||
P256dh = p256dh;
|
||||
Auth = auth;
|
||||
}
|
||||
|
||||
public NotificationWebPushTokenKeys()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
|
||||
public class NotificationWebPushTokenSub
|
||||
{
|
||||
public required string Endpoint { get; set; }
|
||||
public required NotificationWebPushTokenKeys Keys { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationWebPushTokenSub(string endpoint, NotificationWebPushTokenKeys keys)
|
||||
{
|
||||
Endpoint = endpoint;
|
||||
Keys = keys;
|
||||
}
|
||||
|
||||
public NotificationWebPushTokenSub()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using StoneRed.NetificationApi.Server.IdentifyUser;
|
||||
using StoneRed.NetificationApi.Server.Retract;
|
||||
using StoneRed.NetificationApi.Server.Send;
|
||||
using StoneRed.NetificationApi.Server.SetUserPreferences;
|
||||
using StoneRed.NetificationApi.Utilities;
|
||||
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server;
|
||||
|
||||
public class NotificationApiServer
|
||||
{
|
||||
private readonly string clientId;
|
||||
private readonly string clientSecret;
|
||||
private readonly bool secureMode;
|
||||
private readonly HttpClient httpClient;
|
||||
|
||||
public NotificationApiServer(string clientId, string clientSecret, bool secureMode, string baseAddress = "https://api.notificationapi.com") : this(new HttpClient(), clientId, clientSecret, secureMode, baseAddress)
|
||||
{
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
public NotificationApiServer(HttpClient httpClient, string clientId, string clientSecret, bool secureMode, string baseAddress = "https://api.notificationapi.com")
|
||||
{
|
||||
string authToken = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{clientId}:{clientSecret}"));
|
||||
|
||||
httpClient.BaseAddress = new Uri(new Uri(baseAddress), $"{clientId}/");
|
||||
httpClient.DefaultRequestHeaders.Add("Authorization", $"Basic {authToken}");
|
||||
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
this.secureMode = secureMode;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> Send(SendNotificationData sendNotificationData)
|
||||
{
|
||||
return await httpClient.PostAsJsonAsync("sender", sendNotificationData, Configuration.JsonSerializerOptions);
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> Retract(RetractNotificationData retractNotificationData)
|
||||
{
|
||||
return await httpClient.PostAsJsonAsync("sender/retract", retractNotificationData, Configuration.JsonSerializerOptions);
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> Identify(IdentifyUserData identifyUserData)
|
||||
{
|
||||
string authToken;
|
||||
|
||||
if (secureMode)
|
||||
{
|
||||
string hashedUserId = UserIdHasher.Hash(identifyUserData.UserId, clientSecret);
|
||||
authToken = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{clientId}:{identifyUserData.UserId}:{hashedUserId}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
authToken = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{clientId}:{identifyUserData.UserId}"));
|
||||
}
|
||||
|
||||
var requestData = new
|
||||
{
|
||||
email = identifyUserData.Email,
|
||||
number = identifyUserData.TelephoneNumber,
|
||||
};
|
||||
|
||||
HttpRequestMessage request = new(HttpMethod.Post, $"users/{identifyUserData.UserId}")
|
||||
{
|
||||
Content = JsonContent.Create(requestData, options: Configuration.JsonSerializerOptions),
|
||||
};
|
||||
|
||||
request.Headers.Add("Authorization", $"Basic {authToken}");
|
||||
|
||||
return await httpClient.SendAsync(request);
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> SetUserPreferences(SetUserPreferencesData setUserPreferencesData)
|
||||
{
|
||||
return await httpClient.PostAsJsonAsync($"user_preferences/{setUserPreferencesData.UserId}", setUserPreferencesData, Configuration.JsonSerializerOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.Retract;
|
||||
|
||||
public class RetractNotificationData
|
||||
{
|
||||
public required string UserId { get; set; }
|
||||
|
||||
public required string NotificationId { get; set; }
|
||||
|
||||
public string? SecondaryId { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public RetractNotificationData(string userId, string notificationId)
|
||||
{
|
||||
UserId = userId;
|
||||
NotificationId = notificationId;
|
||||
}
|
||||
|
||||
public RetractNotificationData()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
public class NotificationApnOptions
|
||||
{
|
||||
public int? Expiry { get; set; }
|
||||
|
||||
public int? Priority { get; set; }
|
||||
|
||||
public string? CollapseId { get; set; }
|
||||
|
||||
public string? ThreadId { get; set; }
|
||||
|
||||
public int? Badge { get; set; }
|
||||
|
||||
public string? Sound { get; set; }
|
||||
|
||||
public bool? ContentAvailable { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
internal class NotificationEmailAttachments
|
||||
{
|
||||
public required string FileName { get; set; }
|
||||
|
||||
public required string Url { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationEmailAttachments(string fileName, string url)
|
||||
{
|
||||
FileName = fileName;
|
||||
Url = url;
|
||||
}
|
||||
|
||||
public NotificationEmailAttachments()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
public class NotificationEmailOptions
|
||||
{
|
||||
public string[]? ReplyToAddresses { get; set; }
|
||||
|
||||
public string[]? CcAddresses { get; set; }
|
||||
|
||||
public string[]? BccAddresses { get; set; }
|
||||
|
||||
public string[]? Attachments { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
internal class NotificationFcmAndroidOptions
|
||||
{
|
||||
public string? CollapseKey { get; set; }
|
||||
|
||||
public string? Priority { get; set; }
|
||||
|
||||
public string? Ttl { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
internal class NotificationFcmOptions
|
||||
{
|
||||
public NotificationFcmAndroidOptions? Android { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
public class NotificationOptions
|
||||
{
|
||||
public NotificationEmailOptions? Email { get; set; }
|
||||
|
||||
public NotificationApnOptions? Apn { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
public class NotificationUser
|
||||
{
|
||||
public required string Id { get; set; }
|
||||
|
||||
public string? Email { get; set; }
|
||||
|
||||
[JsonPropertyName("number")]
|
||||
public string? TelephoneNumber { get; set; }
|
||||
|
||||
public NotificationUser()
|
||||
{
|
||||
}
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationUser(string id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.Send;
|
||||
|
||||
public class SendNotificationData
|
||||
{
|
||||
public required string NotificationId { get; set; }
|
||||
|
||||
public string? SubNotificationId { get; set; }
|
||||
|
||||
public string? TemplateId { get; set; }
|
||||
|
||||
public required NotificationUser User { get; set; }
|
||||
|
||||
public Dictionary<string, object>? MergeTags { get; set; }
|
||||
public Dictionary<string, string>? Replace { get; set; }
|
||||
|
||||
public NotificationOptions? Options { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public SendNotificationData(string notificationId, NotificationUser user)
|
||||
{
|
||||
NotificationId = notificationId;
|
||||
User = user;
|
||||
}
|
||||
|
||||
public SendNotificationData()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using StoneRed.NetificationApi.Shared;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.SetUserPreferences;
|
||||
|
||||
public class NotificationPreference
|
||||
{
|
||||
public required string NotificationId { get; set; }
|
||||
|
||||
public required NotificationChannel Channel { get; set; }
|
||||
|
||||
public required bool State { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public NotificationPreference(string notificationId, NotificationChannel channel, bool state)
|
||||
{
|
||||
NotificationId = notificationId;
|
||||
Channel = channel;
|
||||
State = state;
|
||||
}
|
||||
|
||||
public NotificationPreference()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StoneRed.NetificationApi.Server.SetUserPreferences;
|
||||
|
||||
public class SetUserPreferencesData
|
||||
{
|
||||
[JsonIgnore]
|
||||
public required string UserId { get; set; }
|
||||
|
||||
public required List<NotificationPreference> Preferences { get; set; }
|
||||
|
||||
[SetsRequiredMembers]
|
||||
public SetUserPreferencesData(string userId, List<NotificationPreference> preferences)
|
||||
{
|
||||
UserId = userId;
|
||||
Preferences = preferences;
|
||||
}
|
||||
|
||||
public SetUserPreferencesData()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace StoneRed.NetificationApi.Shared;
|
||||
|
||||
public enum NotificationChannel
|
||||
{
|
||||
EMAIL,
|
||||
INAPP_WEB,
|
||||
WEB_PUSH,
|
||||
SMS,
|
||||
PUSH,
|
||||
CALL
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Websocket.Client" Version="5.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StoneRed.NetificationApi.Utilities;
|
||||
|
||||
internal static class Configuration
|
||||
{
|
||||
public static JsonSerializerOptions JsonSerializerOptions { get; } = new JsonSerializerOptions()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
Converters =
|
||||
{
|
||||
new JsonStringEnumConverter(),
|
||||
new DateTimeConverter(),
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StoneRed.NetificationApi.Utilities;
|
||||
|
||||
internal class DateTimeConverter : JsonConverter<DateTime>
|
||||
{
|
||||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.GetDateTime().ToUniversalTime();
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToUniversalTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace StoneRed.NetificationApi.Utilities;
|
||||
|
||||
internal static class UserIdHasher
|
||||
{
|
||||
public static string Hash(string userId, string clientSecret)
|
||||
{
|
||||
using HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(clientSecret));
|
||||
return Convert.ToBase64String(hmac.ComputeHash(Encoding.ASCII.GetBytes(userId)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using StoneRed.NetificationApi.Client;
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StoneRed.NetificationApi.Utilities;
|
||||
|
||||
internal static class WebsocketMessageComparer
|
||||
{
|
||||
public static bool Compare(string? message, string route)
|
||||
{
|
||||
if (message is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WebsocketMessage? websocketMessage = JsonSerializer.Deserialize<WebsocketMessage>(message, Configuration.JsonSerializerOptions);
|
||||
|
||||
return websocketMessage?.Route == route;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using StoneRed.NetificationApi.Client;
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StoneRed.NetificationApi.Utilities;
|
||||
|
||||
internal static class WebsocketMessageConverter
|
||||
{
|
||||
public static WebsocketMessage<T> ConvertWebsocketMessage<T>(string message)
|
||||
{
|
||||
return JsonSerializer.Deserialize<WebsocketMessage<T>>(message, Configuration.JsonSerializerOptions) ?? throw new InvalidOperationException("Failed to deserialize websocket message.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user