Skip to content

Commit

Permalink
Add the ability to pause & unpause DMs
Browse files Browse the repository at this point in the history
  • Loading branch information
FloatingMilkshake committed Jun 15, 2024
1 parent 9088004 commit a629d43
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
94 changes: 94 additions & 0 deletions Commands/InteractionCommands/SecurityActionInteractions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
namespace Cliptok.Commands.InteractionCommands
{
public class SecurityActionInteractions : ApplicationCommandModule
{
[SlashCommand("pausedms", "Temporarily pause DMs between server members.", defaultPermission: false)]
[HomeServer, SlashRequireHomeserverPerm(ServerPermLevel.Moderator), SlashCommandPermissions(Permissions.ModerateMembers)]
public async Task SlashPauseDMs(InteractionContext ctx, [Option("time", "The amount of time to pause DMs for. Cannot be greater than 24 hours.")] string time)
{
// need to make our own api calls because D#+ can't do this natively?

// parse time from message
DateTime t = HumanDateParser.HumanDateParser.Parse(time);
if (t <= DateTime.Now)
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Time can't be in the past!");
return;
}
if (t > DateTime.Now.AddHours(24))
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Time can't be greater than 24 hours!");
return;
}
var dmsDisabledUntil = t.ToUniversalTime().ToString("o");

// get current security actions to avoid unintentionally resetting invites_disabled_until
var currentActions = await SecurityActionHelpers.GetCurrentSecurityActions(ctx.Guild.Id);
JToken invitesDisabledUntil;
if (currentActions is null || !currentActions.HasValues)
invitesDisabledUntil = null;
else
invitesDisabledUntil = currentActions["invites_disabled_until"];

// create json body
var newSecurityActions = JsonConvert.SerializeObject(new
{
invites_disabled_until = invitesDisabledUntil,
dms_disabled_until = dmsDisabledUntil,
});

// set actions
var setActionsResponse = await SecurityActionHelpers.SetCurrentSecurityActions(ctx.Guild.Id, newSecurityActions);

// respond
if (setActionsResponse.IsSuccessStatusCode)
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Success} Successfully paused DMs for **{TimeHelpers.TimeToPrettyFormat(t.Subtract(ctx.Interaction.CreationTimestamp.DateTime.ToLocalTime()), false)}**!");
else
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Something went wrong and I wasn't able to pause DMs! Discord returned status code `{setActionsResponse.StatusCode}`.");
}

[SlashCommand("unpausedms", "Unpause DMs between server members.", defaultPermission: false)]
[HomeServer, SlashRequireHomeserverPerm(ServerPermLevel.Moderator), SlashCommandPermissions(Permissions.ModerateMembers)]
public async Task SlashUnpauseDMs(InteractionContext ctx)
{
// need to make our own api calls because D#+ can't do this natively?

// get current security actions to avoid unintentionally resetting invites_disabled_until
var currentActions = await SecurityActionHelpers.GetCurrentSecurityActions(ctx.Guild.Id);
JToken dmsDisabledUntil, invitesDisabledUntil;
if (currentActions is null || !currentActions.HasValues)
{
dmsDisabledUntil = null;
invitesDisabledUntil = null;
}
else
{
dmsDisabledUntil = currentActions["dms_disabled_until"];
invitesDisabledUntil = currentActions["invites_disabled_until"];
}

// if dms are already unpaused, return error
if (dmsDisabledUntil is null)
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} DMs are already unpaused!");
return;
}

// create json body
var newSecurityActions = JsonConvert.SerializeObject(new
{
invites_disabled_until = invitesDisabledUntil,
dms_disabled_until = (object)null,
});

// set actions
var setActionsResponse = await SecurityActionHelpers.SetCurrentSecurityActions(ctx.Guild.Id, newSecurityActions);

// respond
if (setActionsResponse.IsSuccessStatusCode)
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Success} Successfully unpaused DMs!");
else
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Something went wrong and I wasn't able to unpause DMs! Discord returned status code `{setActionsResponse.StatusCode}`.");
}
}
}
111 changes: 111 additions & 0 deletions Commands/SecurityActions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
namespace Cliptok.Commands
{
public class SecurityActions : BaseCommandModule
{
[Command("pausedms")]
[Description("Temporarily pause DMs between server members.")]
[HomeServer, RequireHomeserverPerm(ServerPermLevel.Moderator)]
public async Task PauseDMs(CommandContext ctx, [Description("The amount of time to pause DMs for."), RemainingText] string time)
{
if (string.IsNullOrWhiteSpace(time))
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} You must provide an amount of time to pause DMs for!");
return;
}

// need to make our own api calls because D#+ can't do this natively?

// parse time from message
DateTime t;
try
{
t = HumanDateParser.HumanDateParser.Parse(time);
}
catch (HumanDateParser.ParseException)
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} I didn't understand that time! Please try again.");
return;
}
if (t <= DateTime.Now)
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Time can't be in the past!");
return;
}
if (t > DateTime.Now.AddHours(24))
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Time can't be greater than 24 hours!");
return;
}
var dmsDisabledUntil = t.ToUniversalTime().ToString("o");

// get current security actions to avoid unintentionally resetting invites_disabled_until
var currentActions = await SecurityActionHelpers.GetCurrentSecurityActions(ctx.Guild.Id);
JToken invitesDisabledUntil;
if (currentActions is null || !currentActions.HasValues)
invitesDisabledUntil = null;
else
invitesDisabledUntil = currentActions["invites_disabled_until"];

// create json body
var newSecurityActions = JsonConvert.SerializeObject(new
{
invites_disabled_until = invitesDisabledUntil,
dms_disabled_until = dmsDisabledUntil,
});

// set actions
var setActionsResponse = await SecurityActionHelpers.SetCurrentSecurityActions(ctx.Guild.Id, newSecurityActions);

// respond
if (setActionsResponse.IsSuccessStatusCode)
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Success} Successfully paused DMs for **{TimeHelpers.TimeToPrettyFormat(t.Subtract(ctx.Message.Timestamp.DateTime), false)}**!");
else
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Something went wrong and I wasn't able to pause DMs! Discord returned status code `{setActionsResponse.StatusCode}`.");
}

[Command("unpausedms")]
[Description("Unpause DMs between server members.")]
[HomeServer, RequireHomeserverPerm(ServerPermLevel.Moderator)]
public async Task UnpauseDMs(CommandContext ctx)
{
// need to make our own api calls because D#+ can't do this natively?

// get current security actions to avoid unintentionally resetting invites_disabled_until
var currentActions = await SecurityActionHelpers.GetCurrentSecurityActions(ctx.Guild.Id);
JToken dmsDisabledUntil, invitesDisabledUntil;
if (currentActions is null || !currentActions.HasValues)
{
dmsDisabledUntil = null;
invitesDisabledUntil = null;
}
else
{
dmsDisabledUntil = currentActions["dms_disabled_until"];
invitesDisabledUntil = currentActions["invites_disabled_until"];
}

// if dms are already unpaused, return error
if (dmsDisabledUntil is null)
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} DMs are already unpaused!");
return;
}

// create json body
var newSecurityActions = JsonConvert.SerializeObject(new
{
invites_disabled_until = invitesDisabledUntil,
dms_disabled_until = (object)null,
});

// set actions
var setActionsResponse = await SecurityActionHelpers.SetCurrentSecurityActions(ctx.Guild.Id, newSecurityActions);

// respond
if (setActionsResponse.IsSuccessStatusCode)
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Success} Successfully unpaused DMs!");
else
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Something went wrong and I wasn't able to unpause DMs! Discord returned status code `{setActionsResponse.StatusCode}`.");
}
}
}
1 change: 1 addition & 0 deletions GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
global using DSharpPlus.SlashCommands;
global using Microsoft.Extensions.Logging;
global using Newtonsoft.Json;
global using Newtonsoft.Json.Linq;
global using Serilog;
global using Serilog.Sinks.SystemConsole.Themes;
global using StackExchange.Redis;
Expand Down
25 changes: 25 additions & 0 deletions Helpers/SecurityActionHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Cliptok.Helpers
{
public class SecurityActionHelpers
{
public static async Task<JToken> GetCurrentSecurityActions(ulong guildId)
{
using HttpRequestMessage getActionsRequest = new(HttpMethod.Get, $"https://discord.com/api/v9/guilds/{guildId}");
getActionsRequest.Headers.Authorization = new AuthenticationHeaderValue("Bot", Environment.GetEnvironmentVariable("CLIPTOK_TOKEN") ?? Program.cfgjson.Core.Token);

var getActionsResponse = await Program.httpClient.SendAsync(getActionsRequest);
return ((JObject)JsonConvert.DeserializeObject(await getActionsResponse.Content.ReadAsStringAsync()))["incidents_data"];
}

public static async Task<HttpResponseMessage> SetCurrentSecurityActions(ulong guildId, string newSecurityActions)
{
// create & send request

using HttpRequestMessage setActionsRequest = new(HttpMethod.Put, $"https://discord.com/api/v9/guilds/{guildId}/incident-actions");
setActionsRequest.Headers.Authorization = new AuthenticationHeaderValue("Bot", Environment.GetEnvironmentVariable("CLIPTOK_TOKEN") ?? Program.cfgjson.Core.Token);

setActionsRequest.Content = new StringContent(newSecurityActions, Encoding.UTF8, "application/json");
return await Program.httpClient.SendAsync(setActionsRequest);
}
}
}

0 comments on commit a629d43

Please sign in to comment.