1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-17 18:48:02 -05:00

add offline messaging feature

This commit is contained in:
RaidMax
2021-07-08 21:12:09 -05:00
parent eb339bff43
commit b63803885b
24 changed files with 4744 additions and 7 deletions

View File

@ -0,0 +1,78 @@
using System;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Models.Client;
using Data.Models.Misc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Commands
{
public class OfflineMessageCommand : Command
{
private readonly IDatabaseContextFactory _contextFactory;
private readonly ILogger _logger;
private const short MaxLength = 1024;
public OfflineMessageCommand(CommandConfiguration config, ITranslationLookup layout,
IDatabaseContextFactory contextFactory, ILogger<IDatabaseContextFactory> logger) : base(config, layout)
{
Name = "offlinemessage";
Description = _translationLookup["COMMANDS_OFFLINE_MESSAGE_DESC"];
Alias = "om";
Permission = EFClient.Permission.Moderator;
RequiresTarget = true;
_contextFactory = contextFactory;
_logger = logger;
}
public override async Task ExecuteAsync(GameEvent gameEvent)
{
if (gameEvent.Data.Length > MaxLength)
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_TOO_LONG"].FormatExt(MaxLength));
return;
}
if (gameEvent.Target.ClientId == gameEvent.Origin.ClientId)
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_SELF"].FormatExt(MaxLength));
return;
}
if (gameEvent.Target.IsIngame)
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_INGAME"].FormatExt(gameEvent.Target.Name));
return;
}
await using var context = _contextFactory.CreateContext(enableTracking: false);
var server = await context.Servers.FirstAsync(srv => srv.EndPoint == gameEvent.Owner.ToString());
var newMessage = new EFInboxMessage()
{
SourceClientId = gameEvent.Origin.ClientId,
DestinationClientId = gameEvent.Target.ClientId,
ServerId = server.Id,
Message = gameEvent.Data,
};
try
{
context.Set<EFInboxMessage>().Add(newMessage);
await context.SaveChangesAsync();
gameEvent.Origin.Tell(_translationLookup["COMMANDS_OFFLINE_MESSAGE_SUCCESS"]);
}
catch (Exception ex)
{
_logger.LogError(ex, "Could not save offline message {@Message}", newMessage);
throw;
}
}
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Data.Abstractions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using EFClient = Data.Models.Client.EFClient;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Commands
{
public class ReadMessageCommand : Command
{
private readonly IDatabaseContextFactory _contextFactory;
private readonly ILogger _logger;
public ReadMessageCommand(CommandConfiguration config, ITranslationLookup layout,
IDatabaseContextFactory contextFactory, ILogger<IDatabaseContextFactory> logger) : base(config, layout)
{
Name = "readmessage";
Description = _translationLookup["COMMANDS_READ_MESSAGE_DESC"];
Alias = "rm";
Permission = EFClient.Permission.Flagged;
_contextFactory = contextFactory;
_logger = logger;
}
public override async Task ExecuteAsync(GameEvent gameEvent)
{
try
{
await using var context = _contextFactory.CreateContext();
var inboxItems = await context.InboxMessages
.Include(message => message.SourceClient)
.ThenInclude(client => client.CurrentAlias)
.Where(message => message.DestinationClientId == gameEvent.Origin.ClientId)
.Where(message => !message.IsDelivered)
.ToListAsync();
if (!inboxItems.Any())
{
gameEvent.Origin.Tell(_translationLookup["COMMANDS_READ_MESSAGE_NONE"]);
return;
}
var index = 1;
foreach (var inboxItem in inboxItems)
{
await gameEvent.Origin.Tell(_translationLookup["COMMANDS_READ_MESSAGE_SUCCESS"]
.FormatExt($"{index}/{inboxItems.Count}", inboxItem.SourceClient.CurrentAlias.Name))
.WaitAsync();
foreach (var messageFragment in inboxItem.Message.FragmentMessageForDisplay())
{
await gameEvent.Origin.Tell(messageFragment).WaitAsync();
}
index++;
}
inboxItems.ForEach(item => { item.IsDelivered = true; });
context.UpdateRange(inboxItems);
await context.SaveChangesAsync();
}
catch (Exception ex)
{
logger.LogError(ex, "Could not retrieve offline messages for {Client}", gameEvent.Origin.ToString());
throw;
}
}
}
}

View File

@ -22,6 +22,7 @@ using Serilog.Context;
using static SharedLibraryCore.Database.Models.EFClient;
using Data.Models;
using Data.Models.Server;
using Microsoft.EntityFrameworkCore;
using static Data.Models.Client.EFClient;
namespace IW4MAdmin
@ -341,6 +342,25 @@ namespace IW4MAdmin
E.Origin.Tag = clientTag.LinkedMeta.Value;
}
try
{
var factory = _serviceProvider.GetRequiredService<IDatabaseContextFactory>();
await using var context = factory.CreateContext();
var messageCount = await context.InboxMessages
.CountAsync(msg => msg.DestinationClientId == E.Origin.ClientId && !msg.IsDelivered);
if (messageCount > 0)
{
E.Origin.Tell(_translationLookup["SERVER_JOIN_OFFLINE_MESSAGES"]);
}
}
catch (Exception ex)
{
ServerLogger.LogError(ex, "Could not get offline message count for {Client}", E.Origin.ToString());
throw;
}
await E.Origin.OnJoin(E.Origin.IPAddress);
}
}

View File

@ -271,6 +271,7 @@ namespace IW4MAdmin.Application
// register the native commands
foreach (var commandType in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes()
.Concat(typeof(Program).Assembly.GetTypes().Where(type => type.Namespace == "IW4MAdmin.Application.Commands"))
.Where(_command => _command.BaseType == typeof(Command)))
{
defaultLogger.LogDebug("Registered native command type {name}", commandType.Name);