add offline messaging feature
This commit is contained in:
parent
e2116712e7
commit
ed8067a4a2
78
Application/Commands/OfflineMessageCommand.cs
Normal file
78
Application/Commands/OfflineMessageCommand.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
79
Application/Commands/ReadMessageCommand.cs
Normal file
79
Application/Commands/ReadMessageCommand.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
10
Data/Abstractions/IAuditFields.cs
Normal file
10
Data/Abstractions/IAuditFields.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Data.Abstractions
|
||||
{
|
||||
public class IAuditFields
|
||||
{
|
||||
DateTime CreatedDateTime { get; set; }
|
||||
DateTime? UpdatedDateTime { get; set; }
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ using Data.Models;
|
||||
using Data.Models.Client;
|
||||
using Data.Models.Client.Stats;
|
||||
using Data.Models.Client.Stats.Reference;
|
||||
using Data.Models.Misc;
|
||||
using Data.Models.Server;
|
||||
|
||||
namespace Data.Context
|
||||
@ -38,6 +39,12 @@ namespace Data.Context
|
||||
|
||||
#endregion
|
||||
|
||||
#region MISC
|
||||
|
||||
public DbSet<EFInboxMessage> InboxMessages { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
private void SetAuditColumns()
|
||||
{
|
||||
return;
|
||||
|
@ -8,7 +8,7 @@
|
||||
<PackageId>RaidMax.IW4MAdmin.Data</PackageId>
|
||||
<Title>RaidMax.IW4MAdmin.Data</Title>
|
||||
<Authors />
|
||||
<PackageVersion>1.0.3</PackageVersion>
|
||||
<PackageVersion>1.0.4</PackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
1355
Data/Migrations/MySql/20210709010749_AddEFInboxMessage.Designer.cs
generated
Normal file
1355
Data/Migrations/MySql/20210709010749_AddEFInboxMessage.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
70
Data/Migrations/MySql/20210709010749_AddEFInboxMessage.cs
Normal file
70
Data/Migrations/MySql/20210709010749_AddEFInboxMessage.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Data.Migrations.MySql
|
||||
{
|
||||
public partial class AddEFInboxMessage : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "InboxMessages",
|
||||
columns: table => new
|
||||
{
|
||||
InboxMessageId = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
CreatedDateTime = table.Column<DateTime>(nullable: false),
|
||||
UpdatedDateTime = table.Column<DateTime>(nullable: true),
|
||||
SourceClientId = table.Column<int>(nullable: false),
|
||||
DestinationClientId = table.Column<int>(nullable: false),
|
||||
ServerId = table.Column<long>(nullable: true),
|
||||
Message = table.Column<string>(nullable: true),
|
||||
IsDelivered = table.Column<bool>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_InboxMessages", x => x.InboxMessageId);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFClients_DestinationClientId",
|
||||
column: x => x.DestinationClientId,
|
||||
principalTable: "EFClients",
|
||||
principalColumn: "ClientId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFServers_ServerId",
|
||||
column: x => x.ServerId,
|
||||
principalTable: "EFServers",
|
||||
principalColumn: "ServerId",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFClients_SourceClientId",
|
||||
column: x => x.SourceClientId,
|
||||
principalTable: "EFClients",
|
||||
principalColumn: "ClientId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_DestinationClientId",
|
||||
table: "InboxMessages",
|
||||
column: "DestinationClientId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_ServerId",
|
||||
table: "InboxMessages",
|
||||
column: "ServerId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_SourceClientId",
|
||||
table: "InboxMessages",
|
||||
column: "SourceClientId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "InboxMessages");
|
||||
}
|
||||
}
|
||||
}
|
@ -935,6 +935,44 @@ namespace Data.Migrations.MySql
|
||||
b.ToTable("EFPenalties");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b =>
|
||||
{
|
||||
b.Property<int>("InboxMessageId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CreatedDateTime")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("DestinationClientId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IsDelivered")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.HasColumnType("longtext CHARACTER SET utf8mb4");
|
||||
|
||||
b.Property<long?>("ServerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("SourceClientId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime?>("UpdatedDateTime")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.HasKey("InboxMessageId");
|
||||
|
||||
b.HasIndex("DestinationClientId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.HasIndex("SourceClientId");
|
||||
|
||||
b.ToTable("InboxMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Server.EFServer", b =>
|
||||
{
|
||||
b.Property<long>("ServerId")
|
||||
@ -1282,6 +1320,25 @@ namespace Data.Migrations.MySql
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b =>
|
||||
{
|
||||
b.HasOne("Data.Models.Client.EFClient", "DestinationClient")
|
||||
.WithMany()
|
||||
.HasForeignKey("DestinationClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Data.Models.Server.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId");
|
||||
|
||||
b.HasOne("Data.Models.Client.EFClient", "SourceClient")
|
||||
.WithMany()
|
||||
.HasForeignKey("SourceClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b =>
|
||||
{
|
||||
b.HasOne("Data.Models.Server.EFServer", "Server")
|
||||
|
1381
Data/Migrations/Postgresql/20210709010920_AddEFInboxMessage.Designer.cs
generated
Normal file
1381
Data/Migrations/Postgresql/20210709010920_AddEFInboxMessage.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
namespace Data.Migrations.Postgresql
|
||||
{
|
||||
public partial class AddEFInboxMessage : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "InboxMessages",
|
||||
columns: table => new
|
||||
{
|
||||
InboxMessageId = table.Column<int>(nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
|
||||
CreatedDateTime = table.Column<DateTime>(nullable: false),
|
||||
UpdatedDateTime = table.Column<DateTime>(nullable: true),
|
||||
SourceClientId = table.Column<int>(nullable: false),
|
||||
DestinationClientId = table.Column<int>(nullable: false),
|
||||
ServerId = table.Column<long>(nullable: true),
|
||||
Message = table.Column<string>(nullable: true),
|
||||
IsDelivered = table.Column<bool>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_InboxMessages", x => x.InboxMessageId);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFClients_DestinationClientId",
|
||||
column: x => x.DestinationClientId,
|
||||
principalTable: "EFClients",
|
||||
principalColumn: "ClientId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFServers_ServerId",
|
||||
column: x => x.ServerId,
|
||||
principalTable: "EFServers",
|
||||
principalColumn: "ServerId",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFClients_SourceClientId",
|
||||
column: x => x.SourceClientId,
|
||||
principalTable: "EFClients",
|
||||
principalColumn: "ClientId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_DestinationClientId",
|
||||
table: "InboxMessages",
|
||||
column: "DestinationClientId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_ServerId",
|
||||
table: "InboxMessages",
|
||||
column: "ServerId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_SourceClientId",
|
||||
table: "InboxMessages",
|
||||
column: "SourceClientId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "InboxMessages");
|
||||
}
|
||||
}
|
||||
}
|
@ -958,6 +958,45 @@ namespace Data.Migrations.Postgresql
|
||||
b.ToTable("EFPenalties");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b =>
|
||||
{
|
||||
b.Property<int>("InboxMessageId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn);
|
||||
|
||||
b.Property<DateTime>("CreatedDateTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<int>("DestinationClientId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("IsDelivered")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<long?>("ServerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("SourceClientId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime?>("UpdatedDateTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.HasKey("InboxMessageId");
|
||||
|
||||
b.HasIndex("DestinationClientId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.HasIndex("SourceClientId");
|
||||
|
||||
b.ToTable("InboxMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Server.EFServer", b =>
|
||||
{
|
||||
b.Property<long>("ServerId")
|
||||
@ -1307,6 +1346,25 @@ namespace Data.Migrations.Postgresql
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b =>
|
||||
{
|
||||
b.HasOne("Data.Models.Client.EFClient", "DestinationClient")
|
||||
.WithMany()
|
||||
.HasForeignKey("DestinationClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Data.Models.Server.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId");
|
||||
|
||||
b.HasOne("Data.Models.Client.EFClient", "SourceClient")
|
||||
.WithMany()
|
||||
.HasForeignKey("SourceClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b =>
|
||||
{
|
||||
b.HasOne("Data.Models.Server.EFServer", "Server")
|
||||
|
1354
Data/Migrations/Sqlite/20210703141113_AddEFInboxMessage.Designer.cs
generated
Normal file
1354
Data/Migrations/Sqlite/20210703141113_AddEFInboxMessage.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
69
Data/Migrations/Sqlite/20210703141113_AddEFInboxMessage.cs
Normal file
69
Data/Migrations/Sqlite/20210703141113_AddEFInboxMessage.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Data.Migrations.Sqlite
|
||||
{
|
||||
public partial class AddEFInboxMessage : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "InboxMessages",
|
||||
columns: table => new
|
||||
{
|
||||
InboxMessageId = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
CreatedDateTime = table.Column<DateTime>(nullable: false),
|
||||
UpdatedDateTime = table.Column<DateTime>(nullable: true),
|
||||
SourceClientId = table.Column<int>(nullable: false),
|
||||
DestinationClientId = table.Column<int>(nullable: false),
|
||||
ServerId = table.Column<long>(nullable: true),
|
||||
Message = table.Column<string>(nullable: true),
|
||||
IsDelivered = table.Column<bool>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_InboxMessages", x => x.InboxMessageId);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFClients_DestinationClientId",
|
||||
column: x => x.DestinationClientId,
|
||||
principalTable: "EFClients",
|
||||
principalColumn: "ClientId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFServers_ServerId",
|
||||
column: x => x.ServerId,
|
||||
principalTable: "EFServers",
|
||||
principalColumn: "ServerId",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_InboxMessages_EFClients_SourceClientId",
|
||||
column: x => x.SourceClientId,
|
||||
principalTable: "EFClients",
|
||||
principalColumn: "ClientId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_DestinationClientId",
|
||||
table: "InboxMessages",
|
||||
column: "DestinationClientId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_ServerId",
|
||||
table: "InboxMessages",
|
||||
column: "ServerId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InboxMessages_SourceClientId",
|
||||
table: "InboxMessages",
|
||||
column: "SourceClientId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "InboxMessages");
|
||||
}
|
||||
}
|
||||
}
|
@ -934,6 +934,44 @@ namespace Data.Migrations.Sqlite
|
||||
b.ToTable("EFPenalties");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b =>
|
||||
{
|
||||
b.Property<int>("InboxMessageId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedDateTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("DestinationClientId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsDelivered")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long?>("ServerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SourceClientId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("UpdatedDateTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("InboxMessageId");
|
||||
|
||||
b.HasIndex("DestinationClientId");
|
||||
|
||||
b.HasIndex("ServerId");
|
||||
|
||||
b.HasIndex("SourceClientId");
|
||||
|
||||
b.ToTable("InboxMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Server.EFServer", b =>
|
||||
{
|
||||
b.Property<long>("ServerId")
|
||||
@ -1281,6 +1319,25 @@ namespace Data.Migrations.Sqlite
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b =>
|
||||
{
|
||||
b.HasOne("Data.Models.Client.EFClient", "DestinationClient")
|
||||
.WithMany()
|
||||
.HasForeignKey("DestinationClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Data.Models.Server.EFServer", "Server")
|
||||
.WithMany()
|
||||
.HasForeignKey("ServerId");
|
||||
|
||||
b.HasOne("Data.Models.Client.EFClient", "SourceClient")
|
||||
.WithMany()
|
||||
.HasForeignKey("SourceClientId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b =>
|
||||
{
|
||||
b.HasOne("Data.Models.Server.EFServer", "Server")
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Data.Abstractions;
|
||||
|
||||
namespace Stats.Models
|
||||
{
|
||||
public class AuditFields
|
||||
public class AuditFields : IAuditFields
|
||||
{
|
||||
[Required]
|
||||
public DateTime CreatedDateTime { get; set; } = DateTime.UtcNow;
|
||||
|
35
Data/Models/Misc/EFInboxMessage.cs
Normal file
35
Data/Models/Misc/EFInboxMessage.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Data.Models.Client;
|
||||
using Data.Models.Server;
|
||||
using Stats.Models;
|
||||
|
||||
namespace Data.Models.Misc
|
||||
{
|
||||
public class EFInboxMessage : AuditFields
|
||||
{
|
||||
[Key]
|
||||
public int InboxMessageId { get; set; }
|
||||
|
||||
[Required]
|
||||
public int SourceClientId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(SourceClientId))]
|
||||
public EFClient SourceClient { get; set; }
|
||||
|
||||
[Required]
|
||||
public int DestinationClientId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(DestinationClientId))]
|
||||
public EFClient DestinationClient { get; set; }
|
||||
|
||||
public long? ServerId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(ServerId))]
|
||||
public EFServer Server { get; set; }
|
||||
|
||||
public string Message { get; set; }
|
||||
|
||||
public bool IsDelivered { get; set; }
|
||||
}
|
||||
}
|
@ -529,6 +529,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||
StrainAngleBetween = Strain.LastDistance,
|
||||
TimeSinceLastEvent = (int)Strain.LastDeltaTime,
|
||||
WeaponReference = hit.WeaponReference,
|
||||
HitLocationReference = hit.GetAdditionalProperty<string>("HitLocationReference"),
|
||||
SessionSnapHits = sessionSnapHits,
|
||||
SessionAverageSnapValue = sessionAverageSnapAmount
|
||||
};
|
||||
|
@ -639,6 +639,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
TimeSinceLastAttack = long.Parse(lastAttackTime),
|
||||
GameName = (int) attacker.CurrentServer.GameName
|
||||
};
|
||||
|
||||
hit.SetAdditionalProperty("HitLocationReference", hitLoc);
|
||||
|
||||
if (hit.HitLoc == (int) IW4Info.HitLocation.shield)
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ namespace SharedLibraryCore.Commands
|
||||
|
||||
if (!gameEvent.CanPerformActionOnTarget())
|
||||
{
|
||||
gameEvent.Origin.Tell(_translationLookup["COMMANDS_RUN_AS_FAIL_PERM"]);
|
||||
gameEvent.Origin.Tell(_translationLookup["COMMANDS_RUN_AS_FAIL_PERM"].FormatExt(gameEvent.Target.Name));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -53,11 +53,18 @@ namespace SharedLibraryCore.Commands
|
||||
gameEvent.Owner.Manager.AddEvent(impersonatedCommandEvent);
|
||||
|
||||
var result = await impersonatedCommandEvent.WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken);
|
||||
await result.WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken);
|
||||
|
||||
// remove the added command response
|
||||
foreach (var output in result.Output)
|
||||
// todo: something weird happening making this change required
|
||||
var responses = gameEvent.Owner.Manager.ProcessingEvents
|
||||
.Where(ev => ev.Value.CorrelationId == impersonatedCommandEvent.CorrelationId)
|
||||
.SelectMany(ev => ev.Value.Output)
|
||||
.ToList();
|
||||
|
||||
foreach (var output in responses)
|
||||
{
|
||||
gameEvent.Origin.Tell(_translationLookup["COMMANDS_RUN_AS_SUCCESS"].FormatExt(output));
|
||||
await gameEvent.Origin.Tell(_translationLookup["COMMANDS_RUN_AS_SUCCESS"].FormatExt(output)).WaitAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ namespace SharedLibraryCore.Database.Models
|
||||
using (LogContext.PushProperty("Server", CurrentServer?.ToString()))
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Client {client} is joining the game from {source}", ToString(), ipAddress.HasValue ? "Status" : "Log");
|
||||
|
||||
|
||||
if (ipAddress != null)
|
||||
{
|
||||
IPAddress = ipAddress;
|
||||
|
@ -44,7 +44,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.10" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="RaidMax.IW4MAdmin.Data" Version="1.0.3" />
|
||||
<PackageReference Include="RaidMax.IW4MAdmin.Data" Version="1.0.4" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
|
||||
<PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
@ -1070,6 +1070,31 @@ namespace SharedLibraryCore
|
||||
return value?.ToNumericalString(precision);
|
||||
}
|
||||
|
||||
public static string[] FragmentMessageForDisplay(this string message)
|
||||
{
|
||||
var messages = new List<string>();
|
||||
var length = 48;
|
||||
|
||||
if (message.Length <= length)
|
||||
{
|
||||
return new[] {message};
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < message.Length - length; i += length)
|
||||
{
|
||||
messages.Add(new string(message.Skip(i).Take(length).ToArray()));
|
||||
}
|
||||
|
||||
var left = message.Length - length;
|
||||
|
||||
if (left > 0)
|
||||
{
|
||||
messages.Add(new string(message.Skip(i).Take(left).ToArray()));
|
||||
}
|
||||
|
||||
return messages.ToArray();
|
||||
}
|
||||
|
||||
public static string FindRuleForReason(this string reason, ApplicationConfiguration appConfig, Server server)
|
||||
{
|
||||
// allow for penalty presets
|
||||
|
Loading…
Reference in New Issue
Block a user