Timed Mute added (.mute X @User)
This commit is contained in:
@@ -2,13 +2,13 @@
|
||||
using Discord.Commands;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Attributes;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Administration
|
||||
@@ -20,6 +20,8 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
private static ConcurrentDictionary<ulong, string> guildMuteRoles { get; }
|
||||
private static ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> mutedUsers { get; }
|
||||
private static ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, Timer>> unmuteTimers { get; }
|
||||
= new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, Timer>>();
|
||||
|
||||
public static event Action<IGuildUser, MuteType> UserMuted = delegate { };
|
||||
public static event Action<IGuildUser, MuteType> UserUnmuted = delegate { };
|
||||
@@ -43,6 +45,23 @@ namespace NadekoBot.Modules.Administration
|
||||
v => new ConcurrentHashSet<ulong>(v.MutedUsers.Select(m => m.UserId))
|
||||
));
|
||||
|
||||
foreach (var conf in configs)
|
||||
{
|
||||
foreach (var x in conf.UnmuteTimers)
|
||||
{
|
||||
TimeSpan after;
|
||||
if (x.UnmuteAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
|
||||
{
|
||||
after = TimeSpan.FromMinutes(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
after = x.UnmuteAt - DateTime.UtcNow;
|
||||
}
|
||||
StartUnmuteTimer(conf.GuildId, x.UserId, after);
|
||||
}
|
||||
}
|
||||
|
||||
NadekoBot.Client.UserJoined += Client_UserJoined;
|
||||
}
|
||||
|
||||
@@ -67,10 +86,15 @@ namespace NadekoBot.Modules.Administration
|
||||
public static async Task MuteUser(IGuildUser usr)
|
||||
{
|
||||
await usr.ModifyAsync(x => x.Mute = true).ConfigureAwait(false);
|
||||
await usr.AddRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false);
|
||||
var muteRole = await GetMuteRole(usr.Guild);
|
||||
if (!usr.RoleIds.Contains(muteRole.Id))
|
||||
await usr.AddRolesAsync(muteRole).ConfigureAwait(false);
|
||||
StopUnmuteTimer(usr.GuildId, usr.Id);
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers));
|
||||
var config = uow.GuildConfigs.For(usr.Guild.Id,
|
||||
set => set.Include(gc => gc.MutedUsers)
|
||||
.Include(gc => gc.UnmuteTimers));
|
||||
config.MutedUsers.Add(new MutedUserId()
|
||||
{
|
||||
UserId = usr.Id
|
||||
@@ -78,7 +102,9 @@ namespace NadekoBot.Modules.Administration
|
||||
ConcurrentHashSet<ulong> muted;
|
||||
if (mutedUsers.TryGetValue(usr.Guild.Id, out muted))
|
||||
muted.Add(usr.Id);
|
||||
|
||||
|
||||
config.UnmuteTimers.RemoveWhere(x => x.UserId == usr.Id);
|
||||
|
||||
await uow.CompleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
UserMuted(usr, MuteType.All);
|
||||
@@ -86,11 +112,13 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
public static async Task UnmuteUser(IGuildUser usr)
|
||||
{
|
||||
StopUnmuteTimer(usr.GuildId, usr.Id);
|
||||
await usr.ModifyAsync(x => x.Mute = false).ConfigureAwait(false);
|
||||
await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false);
|
||||
try { await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false); } catch { /*ignore*/ }
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers));
|
||||
var config = uow.GuildConfigs.For(usr.Guild.Id, set => set.Include(gc => gc.MutedUsers)
|
||||
.Include(gc => gc.UnmuteTimers));
|
||||
config.MutedUsers.Remove(new MutedUserId()
|
||||
{
|
||||
UserId = usr.Id
|
||||
@@ -98,6 +126,9 @@ namespace NadekoBot.Modules.Administration
|
||||
ConcurrentHashSet<ulong> muted;
|
||||
if (mutedUsers.TryGetValue(usr.Guild.Id, out muted))
|
||||
muted.TryRemove(usr.Id);
|
||||
|
||||
config.UnmuteTimers.RemoveWhere(x => x.UserId == usr.Id);
|
||||
|
||||
await uow.CompleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
UserUnmuted(usr, MuteType.All);
|
||||
@@ -139,6 +170,79 @@ namespace NadekoBot.Modules.Administration
|
||||
return muteRole;
|
||||
}
|
||||
|
||||
public static async Task TimedMute(IGuildUser user, TimeSpan after)
|
||||
{
|
||||
await MuteUser(user).ConfigureAwait(false); // mute the user. This will also remove any previous unmute timers
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
var config = uow.GuildConfigs.For(user.GuildId, set => set.Include(x => x.UnmuteTimers));
|
||||
config.UnmuteTimers.Add(new UnmuteTimer()
|
||||
{
|
||||
UserId = user.Id,
|
||||
UnmuteAt = DateTime.UtcNow + after,
|
||||
}); // add teh unmute timer to the database
|
||||
uow.Complete();
|
||||
}
|
||||
StartUnmuteTimer(user.GuildId, user.Id, after); // start the timer
|
||||
}
|
||||
|
||||
public static void StartUnmuteTimer(ulong guildId, ulong userId, TimeSpan after)
|
||||
{
|
||||
//load the unmute timers for this guild
|
||||
var userUnmuteTimers = unmuteTimers.GetOrAdd(guildId, new ConcurrentDictionary<ulong, Timer>());
|
||||
|
||||
//unmute timer to be added
|
||||
var toAdd = new Timer(async _ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var guild = NadekoBot.Client.GetGuild(guildId); // load the guild
|
||||
if (guild == null)
|
||||
{
|
||||
RemoveUnmuteTimerFromDb(guildId, userId);
|
||||
return; // if guild can't be found, just remove the timer from db
|
||||
}
|
||||
// unmute the user, this will also remove the timer from the db
|
||||
await UnmuteUser(guild.GetUser(userId)).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
RemoveUnmuteTimerFromDb(guildId, userId); // if unmute errored, just remove unmute from db
|
||||
Administration._log.Warn("Couldn't unmute user {0} in guild {1}", userId, guildId);
|
||||
Administration._log.Warn(ex);
|
||||
}
|
||||
}, null, after, Timeout.InfiniteTimeSpan);
|
||||
|
||||
//add it, or stop the old one and add this one
|
||||
userUnmuteTimers.AddOrUpdate(userId, (key) => toAdd, (key, old) =>
|
||||
{
|
||||
old.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
return toAdd;
|
||||
});
|
||||
}
|
||||
|
||||
public static void StopUnmuteTimer(ulong guildId, ulong userId)
|
||||
{
|
||||
ConcurrentDictionary<ulong, Timer> userUnmuteTimers;
|
||||
if (!unmuteTimers.TryGetValue(guildId, out userUnmuteTimers)) return;
|
||||
|
||||
Timer removed;
|
||||
if(userUnmuteTimers.TryRemove(userId, out removed))
|
||||
{
|
||||
removed.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveUnmuteTimerFromDb(ulong guildId, ulong userId)
|
||||
{
|
||||
using (var uow = DbHandler.UnitOfWork())
|
||||
{
|
||||
var config = uow.GuildConfigs.For(guildId, set => set.Include(x => x.UnmuteTimers));
|
||||
config.UnmuteTimers.RemoveWhere(x => x.UserId == userId);
|
||||
uow.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||
@@ -170,6 +274,7 @@ namespace NadekoBot.Modules.Administration
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||
[RequireUserPermission(GuildPermission.MuteMembers)]
|
||||
[Priority(1)]
|
||||
public async Task Mute(IGuildUser user)
|
||||
{
|
||||
try
|
||||
@@ -183,6 +288,27 @@ namespace NadekoBot.Modules.Administration
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||
[RequireUserPermission(GuildPermission.MuteMembers)]
|
||||
[Priority(0)]
|
||||
public async Task Mute(int minutes, IGuildUser user)
|
||||
{
|
||||
if (minutes < 1)
|
||||
return;
|
||||
try
|
||||
{
|
||||
await TimedMute(user, TimeSpan.FromMinutes(minutes)).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalized("user_muted_time", Format.Bold(user.ToString()), minutes).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Warn(ex);
|
||||
await ReplyErrorLocalized("mute_error").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||
|
@@ -720,7 +720,7 @@ namespace NadekoBot.Modules.Music
|
||||
var embed = new EmbedBuilder()
|
||||
.WithAuthor(eab => eab.WithName(GetText("playlists_page", num)).WithMusicIcon())
|
||||
.WithDescription(string.Join("\n", playlists.Select(r =>
|
||||
GetText("playlists", "#" + r.Id, r.Name, r.Author, r.Songs.Count))))
|
||||
GetText("playlists", r.Id, r.Name, r.Author, r.Songs.Count))))
|
||||
.WithOkColor();
|
||||
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||
|
||||
|
Reference in New Issue
Block a user