Skip to content

Commit

Permalink
Add /haste commands
Browse files Browse the repository at this point in the history
Closes #17
  • Loading branch information
FloatingMilkshake committed Dec 16, 2024
1 parent ccd3d50 commit 91a6d76
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 10 deletions.
84 changes: 84 additions & 0 deletions Commands/Owner/HomeServerCommands/HastebinCommands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
namespace MechanicalMilkshake.Commands.Owner.HomeServerCommands;

[Command("haste")]
[Description("Commands for managing Hastebin content.")]
public class HasteCommands
{
private static readonly string HasteApiEndpoint = "https://api.cloudflare.com/client/v4/accounts/{0}/storage/kv/namespaces/{1}/values/documents:{2}";

[Command("create")]
[Description("Create a new paste.")]
public static async Task HasteCreate(MechanicalMilkshake.SlashCommandContext ctx,
[Parameter("content"), Description("The content of the new paste.")] string content,
[Parameter("key"), Description("The name of the key for the new paste. Accepts formats \"documents:abc\" or \"abc\".")] string key = "")
{
await ctx.DeferResponseAsync();

if (Program.DisabledCommands.Contains("haste"))
{
await CommandHelpers.FailOnMissingInfo(ctx, true);
return;
}

if (string.IsNullOrWhiteSpace(key))
key = GenerateKey();
else
key = key.Replace("documents:", "");

var hasteUrl = string.Format(HasteApiEndpoint, Program.ConfigJson.Cloudflare.AccountId, Program.ConfigJson.Hastebin.NamespaceId, key);
var request = new HttpRequestMessage(HttpMethod.Put, hasteUrl);
request.Content = new StringContent(content);
request.Headers.Add("Authorization", $"Bearer {Program.ConfigJson.Cloudflare.Token}");

var response = await Program.HttpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
await ctx.FollowupAsync($"Successfully created paste: {Program.ConfigJson.Hastebin.Url}/{key}");
else
await ctx.FollowupAsync($"Failed to create paste! Cloudflare API returned code {response.StatusCode}.");
}

[Command("delete")]
[Description("Delete a paste.")]
public static async Task HasteDelete(MechanicalMilkshake.SlashCommandContext ctx,
[Parameter("key"), Description("The key of the paste to delete. Accepts formats \"documents:abc\" or \"abc\".")] string key)
{
await ctx.DeferResponseAsync();

if (Program.DisabledCommands.Contains("haste"))
{
await CommandHelpers.FailOnMissingInfo(ctx, true);
return;
}

key = key.Replace("documents:", "");
key = key.Replace($"{Program.ConfigJson.Hastebin.Url.Trim('/') + "/"}", "");

var hasteUrl = string.Format(HasteApiEndpoint, Program.ConfigJson.Cloudflare.AccountId, Program.ConfigJson.Hastebin.NamespaceId, key);
var request = new HttpRequestMessage(HttpMethod.Delete, hasteUrl);
request.Headers.Add("Authorization", $"Bearer {Program.ConfigJson.Cloudflare.Token}");

var response = await Program.HttpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
await ctx.FollowupAsync($"Successfully deleted paste: {Program.ConfigJson.Hastebin.Url}/{key}");
else
await ctx.FollowupAsync($"Failed to delete paste! Cloudflare API returned code {response.StatusCode}.");
}

// https://github.com/FloatingMilkshake/starbin/blob/aa4726b/functions/documents/index.ts#L27-L44
private static string GenerateKey()
{
Random random = new();
const string vowels = "aeiou";
const string consonants = "bcdfghjklmnpqrstvwxyz";
const int size = 6;

var key = "";
var start = random.Next(2);
for (var i = 0; i < size; i++)
{
key += i % 2 == start ? consonants[random.Next(consonants.Length)] : vowels[random.Next(vowels.Length)];
}

return key;
}
}
6 changes: 3 additions & 3 deletions Commands/Owner/HomeServerCommands/LinkCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public static async Task ListWorkerLinks(MechanicalMilkshake.SlashCommandContext
}

var requestUri =
$"https://api.cloudflare.com/client/v4/accounts/{Program.ConfigJson.WorkerLinks.AccountId}/storage/kv/namespaces/{Program.ConfigJson.WorkerLinks.NamespaceId}/keys";
$"https://api.cloudflare.com/client/v4/accounts/{Program.ConfigJson.Cloudflare.AccountId}/storage/kv/namespaces/{Program.ConfigJson.WorkerLinks.NamespaceId}/keys";
HttpRequestMessage request = new(HttpMethod.Get, requestUri);

request.Headers.Add("X-Auth-Key", Program.ConfigJson.WorkerLinks.ApiKey);
Expand Down Expand Up @@ -187,7 +187,7 @@ public static async Task ListWorkerLinks(MechanicalMilkshake.SlashCommandContext
}

var valueRequestUri =
$"https://api.cloudflare.com/client/v4/accounts/{Program.ConfigJson.WorkerLinks.AccountId}/storage/kv/namespaces/{Program.ConfigJson.WorkerLinks.NamespaceId}/values/{key}";
$"https://api.cloudflare.com/client/v4/accounts/{Program.ConfigJson.Cloudflare.AccountId}/storage/kv/namespaces/{Program.ConfigJson.WorkerLinks.NamespaceId}/values/{key}";
HttpRequestMessage valueRequest = new(HttpMethod.Get, valueRequestUri);

valueRequest.Headers.Add("X-Auth-Key", Program.ConfigJson.WorkerLinks.ApiKey);
Expand Down Expand Up @@ -252,7 +252,7 @@ await ctx.Interaction.SendPaginatedResponseAsync(false, ctx.User, pages,
await ctx.FollowupAsync(new DiscordFollowupMessageBuilder().WithContent(
$"Hmm, I couldn't send the list of links here!" +
$" You can see the full list on Cloudflare's website [here](https://dash.cloudflare.com/" +
$"{Program.ConfigJson.WorkerLinks.AccountId}/workers/kv/namespaces/{Program.ConfigJson.WorkerLinks.NamespaceId})." +
$"{Program.ConfigJson.Cloudflare.AccountId}/workers/kv/namespaces/{Program.ConfigJson.WorkerLinks.NamespaceId})." +
$" Exception details are below.\n```\n{ex.GetType()}: {ex.Message}\n```"));
}
}
Expand Down
13 changes: 11 additions & 2 deletions ConfigJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ public class ConfigJson
[JsonProperty("base")] public BaseConfig Base { get; private set; }

[JsonProperty("ids")] public IdsConfig Ids { get; private set; }

[JsonProperty("hastebin")] public HastebinConfig Hastebin { get; private set; }

[JsonProperty("workerLinks")] public WorkerLinksConfig WorkerLinks { get; private set; }

Expand Down Expand Up @@ -51,6 +53,13 @@ public class IdsConfig
[JsonProperty("ratelimitCautionChannels")] public List<string> RatelimitCautionChannels { get; private set; }
}

public class HastebinConfig
{
[JsonProperty("url")] public string Url { get; set; }

[JsonProperty("namespaceId")] public string NamespaceId { get; set; }
}

public class WorkerLinksConfig
{
[JsonProperty("baseUrl")] public string BaseUrl { get; set; }
Expand All @@ -61,8 +70,6 @@ public class WorkerLinksConfig

[JsonProperty("apiKey")] public string ApiKey { get; set; }

[JsonProperty("accountId")] public string AccountId { get; set; }

[JsonProperty("email")] public string Email { get; set; }
}

Expand All @@ -88,6 +95,8 @@ public class CloudflareConfig
[JsonProperty("zoneId")] public string ZoneId { get; set; }

[JsonProperty("token")] public string Token { get; set; }

[JsonProperty("accountId")] public string AccountId { get; set; }
}

public class LogConfig
Expand Down
18 changes: 15 additions & 3 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,28 @@ internal static async Task Main()
.WithSSL();
}

if (ConfigJson.WorkerLinks is null || ConfigJson.WorkerLinks.BaseUrl == "" || ConfigJson.WorkerLinks.Secret == "" ||
ConfigJson.WorkerLinks.NamespaceId == "" || ConfigJson.WorkerLinks.ApiKey == "" ||
ConfigJson.WorkerLinks.AccountId == "" || ConfigJson.WorkerLinks.Email == "")
if (ConfigJson.WorkerLinks is null || ConfigJson.Cloudflare is null
|| ConfigJson.WorkerLinks.BaseUrl == "" || ConfigJson.WorkerLinks.Secret == ""
|| ConfigJson.WorkerLinks.NamespaceId == "" || ConfigJson.WorkerLinks.ApiKey == ""
|| ConfigJson.Cloudflare.AccountId == "" || ConfigJson.WorkerLinks.Email == "")
{
Discord.Logger.LogWarning(BotEventId,
// ReSharper disable once LogMessageIsSentenceProblem
"Short-link commands disabled due to missing WorkerLinks information.");

DisabledCommands.Add("wl");
}

if (ConfigJson.Cloudflare is null || ConfigJson.Hastebin is null
|| ConfigJson.Cloudflare.AccountId == "" || ConfigJson.Hastebin.NamespaceId == ""
|| ConfigJson.Hastebin.Url == "")
{
Discord.Logger.LogWarning(BotEventId,
// ReSharper disable once LogMessageIsSentenceProblem
"Hastebin commands disabled due to missing Cloudflare or Hastebin information.");

DisabledCommands.Add("haste");
}

if (ConfigJson.Base is null || ConfigJson.Base.WolframAlphaAppId == "")
{
Expand Down
9 changes: 7 additions & 2 deletions config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@
"feedbackChannel": "",
"ratelimitCautionChannels": []
},

"hastebin": {
"url": "",
"namespaceId": ""
},

"workerLinks": {
"baseUrl": "",
"secret": "",
"namespaceId": "",
"apiKey": "",
"accountId": "",
"email": ""
},

Expand All @@ -44,7 +48,8 @@
"cloudflare": {
"urlPrefix": "",
"zoneId": "",
"token": ""
"token": "",
"accountId": ""
},

"logs": {
Expand Down

0 comments on commit 91a6d76

Please sign in to comment.