Fix Threading Duplicate for Mute Penalty & Added !MuteInfo & Fix PM (#269)
* Resolve duplicate migration Resolve unmuting state double penalties * Change order of operation * Added MuteInfoCommand.cs * Resolve !pm and @broadcast permanently being disabled
This commit is contained in:
parent
76925a78d4
commit
cf51b83cdd
50
Plugins/Mute/Commands/MuteInfoCommand.cs
Normal file
50
Plugins/Mute/Commands/MuteInfoCommand.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using Data.Models.Client;
|
||||||
|
using Humanizer;
|
||||||
|
using SharedLibraryCore;
|
||||||
|
using SharedLibraryCore.Commands;
|
||||||
|
using SharedLibraryCore.Configuration;
|
||||||
|
using SharedLibraryCore.Interfaces;
|
||||||
|
|
||||||
|
namespace Mute.Commands;
|
||||||
|
|
||||||
|
public class MuteInfoCommand : Command
|
||||||
|
{
|
||||||
|
public MuteInfoCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
||||||
|
translationLookup)
|
||||||
|
{
|
||||||
|
Name = "muteinfo";
|
||||||
|
Description = translationLookup["PLUGINS_MUTE_COMMANDS_MUTEINFO_DESC"];
|
||||||
|
Alias = "mi";
|
||||||
|
Permission = EFClient.Permission.Moderator;
|
||||||
|
RequiresTarget = true;
|
||||||
|
SupportedGames = Plugin.SupportedGames;
|
||||||
|
Arguments = new[]
|
||||||
|
{
|
||||||
|
new CommandArgument
|
||||||
|
{
|
||||||
|
Name = translationLookup["COMMANDS_ARGS_PLAYER"],
|
||||||
|
Required = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task ExecuteAsync(GameEvent gameEvent)
|
||||||
|
{
|
||||||
|
var currentMuteMeta = await Plugin.MuteManager.GetCurrentMuteState(gameEvent.Target);
|
||||||
|
switch (currentMuteMeta.MuteState)
|
||||||
|
{
|
||||||
|
case MuteState.Muted when currentMuteMeta.Expiration is null:
|
||||||
|
gameEvent.Origin.Tell(_translationLookup["PLUGINS_MUTE_COMMANDS_MUTEINFO_SUCCESS"]
|
||||||
|
.FormatExt(gameEvent.Target.Name, currentMuteMeta.Reason));
|
||||||
|
return;
|
||||||
|
case MuteState.Muted when currentMuteMeta.Expiration.HasValue && currentMuteMeta.Expiration.Value > DateTime.UtcNow:
|
||||||
|
var remainingTime = (currentMuteMeta.Expiration.Value - DateTime.UtcNow).HumanizeForCurrentCulture();
|
||||||
|
gameEvent.Origin.Tell(_translationLookup["PLUGINS_MUTE_COMMANDS_MUTEINFO_TM_SUCCESS"]
|
||||||
|
.FormatExt(gameEvent.Target.Name, currentMuteMeta.Reason, remainingTime));
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
gameEvent.Origin.Tell(_translationLookup["PLUGINS_MUTE_COMMANDS_MUTEINFO_NONE"]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ public class MuteManager
|
|||||||
private readonly IMetaServiceV2 _metaService;
|
private readonly IMetaServiceV2 _metaService;
|
||||||
private readonly ITranslationLookup _translationLookup;
|
private readonly ITranslationLookup _translationLookup;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly SemaphoreSlim _onMuteAction = new(1, 1);
|
||||||
|
|
||||||
public MuteManager(IMetaServiceV2 metaService, ITranslationLookup translationLookup, ILogger logger)
|
public MuteManager(IMetaServiceV2 metaService, ITranslationLookup translationLookup, ILogger logger)
|
||||||
{
|
{
|
||||||
@ -26,38 +27,46 @@ public class MuteManager
|
|||||||
|
|
||||||
public async Task<MuteStateMeta> GetCurrentMuteState(EFClient client)
|
public async Task<MuteStateMeta> GetCurrentMuteState(EFClient client)
|
||||||
{
|
{
|
||||||
var clientMuteMeta = await ReadPersistentDataV2(client);
|
try
|
||||||
if (clientMuteMeta is not null) return clientMuteMeta;
|
|
||||||
|
|
||||||
// Return null if the client doesn't have old or new meta.
|
|
||||||
var muteState = await ReadPersistentDataV1(client);
|
|
||||||
clientMuteMeta = new MuteStateMeta
|
|
||||||
{
|
{
|
||||||
Reason = muteState is null ? string.Empty : _translationLookup["PLUGINS_MUTE_MIGRATED"],
|
await _onMuteAction.WaitAsync();
|
||||||
Expiration = muteState switch
|
var clientMuteMeta = await ReadPersistentDataV2(client);
|
||||||
|
if (clientMuteMeta is not null) return clientMuteMeta;
|
||||||
|
|
||||||
|
// Return null if the client doesn't have old or new meta.
|
||||||
|
var muteState = await ReadPersistentDataV1(client);
|
||||||
|
clientMuteMeta = new MuteStateMeta
|
||||||
{
|
{
|
||||||
null => DateTime.UtcNow,
|
Reason = muteState is null ? string.Empty : _translationLookup["PLUGINS_MUTE_MIGRATED"],
|
||||||
MuteState.Muted => null,
|
Expiration = muteState switch
|
||||||
_ => DateTime.UtcNow
|
{
|
||||||
},
|
null => DateTime.UtcNow,
|
||||||
MuteState = muteState ?? MuteState.Unmuted,
|
MuteState.Muted => null,
|
||||||
CommandExecuted = true
|
_ => DateTime.UtcNow
|
||||||
};
|
},
|
||||||
|
MuteState = muteState ?? MuteState.Unmuted,
|
||||||
|
CommandExecuted = true
|
||||||
|
};
|
||||||
|
|
||||||
// Migrate old mute meta, else, client has no state, so set a generic one, but don't write it to database.
|
// Migrate old mute meta, else, client has no state, so set a generic one, but don't write it to database.
|
||||||
if (muteState is not null)
|
if (muteState is not null)
|
||||||
{
|
{
|
||||||
clientMuteMeta.CommandExecuted = false;
|
clientMuteMeta.CommandExecuted = false;
|
||||||
await WritePersistentData(client, clientMuteMeta);
|
await WritePersistentData(client, clientMuteMeta);
|
||||||
await CreatePenalty(muteState.Value, Utilities.IW4MAdminClient(), client, clientMuteMeta.Expiration,
|
await CreatePenalty(muteState.Value, Utilities.IW4MAdminClient(), client, clientMuteMeta.Expiration,
|
||||||
clientMuteMeta.Reason);
|
clientMuteMeta.Reason);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
client.SetAdditionalProperty(Plugin.MuteKey, clientMuteMeta);
|
client.SetAdditionalProperty(Plugin.MuteKey, clientMuteMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clientMuteMeta;
|
return clientMuteMeta;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (_onMuteAction.CurrentCount == 0) _onMuteAction.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> Mute(Server server, EFClient origin, EFClient target, DateTime? dateTime, string reason)
|
public async Task<bool> Mute(Server server, EFClient origin, EFClient target, DateTime? dateTime, string reason)
|
||||||
@ -65,8 +74,6 @@ public class MuteManager
|
|||||||
var clientMuteMeta = await GetCurrentMuteState(target);
|
var clientMuteMeta = await GetCurrentMuteState(target);
|
||||||
if (clientMuteMeta.MuteState is MuteState.Muted && clientMuteMeta.CommandExecuted) return false;
|
if (clientMuteMeta.MuteState is MuteState.Muted && clientMuteMeta.CommandExecuted) return false;
|
||||||
|
|
||||||
await CreatePenalty(MuteState.Muted, origin, target, dateTime, reason);
|
|
||||||
|
|
||||||
clientMuteMeta = new MuteStateMeta
|
clientMuteMeta = new MuteStateMeta
|
||||||
{
|
{
|
||||||
Expiration = dateTime,
|
Expiration = dateTime,
|
||||||
@ -76,6 +83,8 @@ public class MuteManager
|
|||||||
};
|
};
|
||||||
await WritePersistentData(target, clientMuteMeta);
|
await WritePersistentData(target, clientMuteMeta);
|
||||||
|
|
||||||
|
await CreatePenalty(MuteState.Muted, origin, target, dateTime, reason);
|
||||||
|
|
||||||
// Handle game command
|
// Handle game command
|
||||||
var client = server.GetClientsAsList().FirstOrDefault(client => client.NetworkId == target.NetworkId);
|
var client = server.GetClientsAsList().FirstOrDefault(client => client.NetworkId == target.NetworkId);
|
||||||
await PerformGameCommand(server, client, clientMuteMeta);
|
await PerformGameCommand(server, client, clientMuteMeta);
|
||||||
@ -89,7 +98,10 @@ public class MuteManager
|
|||||||
if (clientMuteMeta.MuteState is MuteState.Unmuted && clientMuteMeta.CommandExecuted) return false;
|
if (clientMuteMeta.MuteState is MuteState.Unmuted && clientMuteMeta.CommandExecuted) return false;
|
||||||
if (!target.IsIngame && clientMuteMeta.MuteState is MuteState.Unmuting) return false;
|
if (!target.IsIngame && clientMuteMeta.MuteState is MuteState.Unmuting) return false;
|
||||||
|
|
||||||
await CreatePenalty(MuteState.Unmuted, origin, target, DateTime.UtcNow, reason);
|
if (clientMuteMeta.MuteState is not MuteState.Unmuting)
|
||||||
|
{
|
||||||
|
await CreatePenalty(MuteState.Unmuted, origin, target, DateTime.UtcNow, reason);
|
||||||
|
}
|
||||||
|
|
||||||
clientMuteMeta = new MuteStateMeta
|
clientMuteMeta = new MuteStateMeta
|
||||||
{
|
{
|
||||||
|
@ -38,9 +38,6 @@ public class Plugin : IPlugin
|
|||||||
|
|
||||||
switch (gameEvent.Type)
|
switch (gameEvent.Type)
|
||||||
{
|
{
|
||||||
case GameEvent.EventType.Command:
|
|
||||||
|
|
||||||
break;
|
|
||||||
case GameEvent.EventType.Join:
|
case GameEvent.EventType.Join:
|
||||||
// Check if user has any meta set, else ignore (unmuted)
|
// Check if user has any meta set, else ignore (unmuted)
|
||||||
var muteMetaJoin = await MuteManager.GetCurrentMuteState(gameEvent.Origin);
|
var muteMetaJoin = await MuteManager.GetCurrentMuteState(gameEvent.Origin);
|
||||||
@ -122,7 +119,16 @@ public class Plugin : IPlugin
|
|||||||
manager.CommandInterceptors.Add(gameEvent =>
|
manager.CommandInterceptors.Add(gameEvent =>
|
||||||
{
|
{
|
||||||
if (gameEvent.Extra is not Command command)
|
if (gameEvent.Extra is not Command command)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var muteMeta = MuteManager.GetCurrentMuteState(gameEvent.Origin).GetAwaiter().GetResult();
|
||||||
|
if (muteMeta.MuteState is not MuteState.Muted)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return !DisabledCommands.Contains(command.GetType().Name) && !command.IsBroadcast;
|
return !DisabledCommands.Contains(command.GetType().Name) && !command.IsBroadcast;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user