Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using Fragment.NetSlum.Persistence.Entities;

namespace Fragment.NetSlum.Networking.Contexts;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Fragment.NetSlum.Core.CommandBus.Contracts.Events;
using Fragment.NetSlum.Networking.Models;

namespace Fragment.NetSlum.Networking.Events;

public class AreaServerPublishedEvent : IEvent
{
public AreaServerPublishedEvent(AreaServerInformation areaServerInfo)
{
AreaServerInfo = areaServerInfo;
}

public AreaServerInformation AreaServerInfo { get; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Fragment.NetSlum.Core.CommandBus.Contracts.Events;
using Fragment.NetSlum.Networking.Services.Notifications;

namespace Fragment.NetSlum.Networking.Events.Handlers;

public class AreaServerPublishedEventHandler : EventHandler<AreaServerPublishedEvent>
{
private readonly NotificationService _notificationService;

public AreaServerPublishedEventHandler(NotificationService notificationService)
{
_notificationService = notificationService;
}

public override async ValueTask Handle(AreaServerPublishedEvent eventInfo, CancellationToken cancellationToken)
{
var sb = new StringBuilder();
sb.AppendLine($"Name: {eventInfo.AreaServerInfo.ServerName}");
sb.AppendLine($"Level: {eventInfo.AreaServerInfo.Level}");

await _notificationService.SendNotification(new NotificationService.NotificationMessage(
NotificationService.NotificationType.AreaServer, "Area Server Published", sb.ToString()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Fragment.NetSlum.Core.CommandBus.Contracts.Events;
using Fragment.NetSlum.Networking.Services.Notifications;

namespace Fragment.NetSlum.Networking.Events.Handlers;

public class AreaServerStatusUpdateEventHandler : EventHandler<AreaServerStatusUpdateEvent>
{
private readonly NotificationService _notificationService;

public AreaServerStatusUpdateEventHandler(NotificationService notificationService)
{
_notificationService = notificationService;
}

public override async ValueTask Handle(AreaServerStatusUpdateEvent eventInfo, CancellationToken cancellationToken)
{
var sb = new StringBuilder();
sb.AppendLine($"Name: {eventInfo.ServerName}");
sb.AppendLine($"Level: {eventInfo.Level}");
sb.AppendLine($"State: {eventInfo.State.ToString()}");
sb.AppendLine($"Player Count: {eventInfo.CurrentPlayerCount}");

await _notificationService.SendNotification(new NotificationService.NotificationMessage(
NotificationService.NotificationType.AreaServer, "Area Server Status Changed", sb.ToString()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@
<ProjectReference Include="..\Fragment.NetSlum.TcpServer\Fragment.NetSlum.TcpServer.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.18.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public override ValueTask<ICollection<FragmentMessage>> GetResponse(FragmentTcpS
session.AreaServerInfo!.PublicConnectionEndpoint = new IPEndPoint(
asIpAddress, BinaryPrimitives.ReadUInt16BigEndian(request.Data[4..6].Span));

_logger.LogInformation("{AreaServerInfo}", session.AreaServerInfo!.ToString());
_logger.LogInformation("Area Server Published Connection Info: {NewLine}{AreaServerInfo}", Environment.NewLine, session.AreaServerInfo!.ToString());

BaseResponse response = new AreaServerIPAddressPortResponse();
return SingleMessage(response.Build());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Threading.Tasks;
using Fragment.NetSlum.Core.CommandBus;
using Fragment.NetSlum.Core.Constants;
using Fragment.NetSlum.Core.Extensions;
using Fragment.NetSlum.Networking.Attributes;
using Fragment.NetSlum.Networking.Constants;
using Fragment.NetSlum.Networking.Events;
using Fragment.NetSlum.Networking.Objects;
using Fragment.NetSlum.Networking.Packets.Response.AreaServer;
using Fragment.NetSlum.Networking.Packets.Response;
Expand All @@ -22,11 +25,13 @@ public class AreaServerPublishDetailsRequest:BaseRequest
{
private readonly FragmentContext _database;
private readonly ILogger<AreaServerPublishDetailsRequest> _logger;
private readonly ICommandBus _commandBus;

public AreaServerPublishDetailsRequest(FragmentContext database, ILogger<AreaServerPublishDetailsRequest> logger)
public AreaServerPublishDetailsRequest(FragmentContext database, ILogger<AreaServerPublishDetailsRequest> logger, ICommandBus commandBus)
{
_database = database;
_logger = logger;
_commandBus = commandBus;
}

public override ValueTask<ICollection<FragmentMessage>> GetResponse(FragmentTcpSession session, FragmentMessage request)
Expand All @@ -50,6 +55,10 @@ public override ValueTask<ICollection<FragmentMessage>> GetResponse(FragmentTcpS
pos += 3;
session.AreaServerInfo.ServerId = request.Data[pos..];

_logger.LogInformation("Area Server Published Details: {NewLine}{AreaServerInfo}", Environment.NewLine, session.AreaServerInfo!.ToString());

_commandBus.Notify(new AreaServerPublishedEvent(session.AreaServerInfo!)).Wait();

response = new AreaServerPublishDetailsResponse { PacketType = OpCodes.Data_AreaServerPublishDetails1Success, Data = [0x00, 0x01
]
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;

namespace Fragment.NetSlum.Networking.Services.Notifications;

public class NotificationOptions
{
public class NotificationDestination
{
public required string ProviderName { get; set; }
public Dictionary<string, object?> Options { get; set; } = new Dictionary<string, object?>();

public ICollection<NotificationService.NotificationType> Types { get; set; } = [NotificationService.NotificationType.All];
}

public ICollection<NotificationDestination> Destinations { get; set; } = [];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Fragment.NetSlum.Networking.Services.Notifications.Providers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace Fragment.NetSlum.Networking.Services.Notifications;

public class NotificationService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IOptionsMonitor<NotificationOptions> _optionsMonitor;

private static readonly JsonSerializerOptions SerializerOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
Converters = { new JsonStringEnumConverter() },
};

[Flags]
public enum NotificationType
{
AreaServer = 1 << 0,
Character = 1 << 1,
All = AreaServer | Character,
}

public record NotificationMessage(NotificationType Type, string Title, string Content);

public NotificationService(IServiceScopeFactory scopeFactory, IOptionsMonitor<NotificationOptions> optionsMonitor)
{
_scopeFactory = scopeFactory;
_optionsMonitor = optionsMonitor;
}

public async Task SendNotification(NotificationMessage message)
{
using var scope = _scopeFactory.CreateScope();

var configuredNotifications = _optionsMonitor.CurrentValue.Destinations
.Where(n => n.Types.Any(t => t.HasFlag(message.Type)))
.ToList();

foreach (var destination in configuredNotifications)
{
var provider = scope.ServiceProvider.GetRequiredKeyedService<INotificationProvider>(destination.ProviderName);

var optionsType = provider.GetType().BaseType!.GetGenericArguments()[0];

var jsonOptions = JsonSerializer.Serialize(destination.Options, SerializerOptions);

await provider.Send(message, JsonSerializer.Deserialize(jsonOptions, optionsType, SerializerOptions)!);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Threading.Tasks;

namespace Fragment.NetSlum.Networking.Services.Notifications.Providers;

public interface INotificationProvider
{
public Task Send(NotificationService.NotificationMessage message, object options);
}

public abstract class AbstractNotificationProvider<TOptions> : INotificationProvider where TOptions : BaseNotificationOptions
{
protected abstract Task SendNotification(NotificationService.NotificationMessage message, TOptions options);

public async Task Send(NotificationService.NotificationMessage message, object options)
{
await SendNotification(message, (TOptions)options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Fragment.NetSlum.Networking.Services.Notifications.Providers;

public class BaseNotificationOptions
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Threading.Tasks;
using Discord;
using Discord.Webhook;

namespace Fragment.NetSlum.Networking.Services.Notifications.Providers.Discord;

public class DiscordNotificationProvider : AbstractNotificationProvider<DiscordNotificationOptions>
{
protected override async Task SendNotification(NotificationService.NotificationMessage message, DiscordNotificationOptions options)
{
using var discordClient = new DiscordWebhookClient(options.WebhookUri);

var embed = new EmbedBuilder
{
Title = message.Title,
Description = message.Content,
};

await discordClient.SendMessageAsync(embeds: [embed.Build()]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Fragment.NetSlum.Networking.Services.Notifications.Providers.Discord;

public class DiscordNotificationOptions : BaseNotificationOptions
{
public string WebhookUri { get; set; } = default!;
}
8 changes: 8 additions & 0 deletions src/Fragment.NetSlum.Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
using Fragment.NetSlum.Core.CommandBus;
using Fragment.NetSlum.Networking.Contexts;
using Fragment.NetSlum.Networking.Extensions;
using Fragment.NetSlum.Networking.Services.Notifications;
using Fragment.NetSlum.Networking.Services.Notifications.Providers;
using Fragment.NetSlum.Networking.Services.Notifications.Providers.Discord;
using Fragment.NetSlum.Networking.Stores;
using Fragment.NetSlum.Persistence;
using Fragment.NetSlum.Persistence.Extensions;
Expand Down Expand Up @@ -178,6 +181,11 @@
builder.Services.AddHostedService<ChatLobbyBackgroundService>();
builder.Services.AddScoped<GuildShopContextAccessor>();

builder.Services.Configure<NotificationOptions>(builder.Configuration.GetSection("Notifications"));

builder.Services.AddKeyedScoped<INotificationProvider, DiscordNotificationProvider>(nameof(DiscordNotificationProvider).Replace("NotificationProvider", string.Empty, StringComparison.InvariantCultureIgnoreCase));
builder.Services.AddSingleton<NotificationService>();


var app = builder.Build();

Expand Down
5 changes: 4 additions & 1 deletion src/Fragment.NetSlum.Server/serverConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,8 @@
"Authentication": {
"JwtSecret": "changeme123"
},
"AllowedOrigins": "http://localhost:3000,https://fragment.psrewired.com"
"Notifications": {
"Destinations": []
},
"AllowedOrigins": "http://localhost:3000,https://fragment.psrewired.com,https://fragment.dothackers.org"
}