Skip to content

Commit

Permalink
New AddonsAdd and AddonsDelete commands
Browse files Browse the repository at this point in the history
This will allow moderators to add and delete addons for the reptogif / reptomp4 commands
  • Loading branch information
Refragg committed Oct 21, 2022
1 parent 1f9d61e commit eb32e65
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 0 deletions.
214 changes: 214 additions & 0 deletions Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -70,8 +72,220 @@ public async Task AddonsInfo(CommandContext ctx)
// addonList.AddField($"2.1 Addons", MakeModList(addons21));
await ctx.RespondAsync(builder);
}

private const Permissions AddonsDeletePermissions = Permissions.ModerateMembers;

[Command("addonsdel")]
public async Task AddonsDelete(CommandContext ctx, params string[] _)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsDeletePermissions))
return;

await ctx.RespondAsync($"Use either {ctx.Prefix}addonsdellvl or {ctx.Prefix}addonsdelchar");
}

[Command("addonsdellvl")]
public async Task AddonsDeleteLevel(CommandContext ctx, string fileName)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsDeletePermissions))
return;

await AddonsDeleteInternal(ctx, fileName, true);
}

[Command("addonsdellvl")]
public async Task AddonsDeleteLevel(CommandContext ctx)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsDeletePermissions))
return;

await ctx.RespondAsync($"Syntax: '{ctx.Prefix}addonsdellvl (file name)'");
}

[Command("addonsdelchar")]
public async Task AddonsDeleteChar(CommandContext ctx, string fileName)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsDeletePermissions))
return;

await AddonsDeleteInternal(ctx, fileName, false);
}

[Command("addonsdelchar")]
public async Task AddonsDeleteChar(CommandContext ctx)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsDeletePermissions))
return;

await ctx.RespondAsync($"Syntax: '{ctx.Prefix}addonsdelchar (file name)'");
}

private async Task AddonsDeleteInternal(CommandContext ctx, string fileName, bool isLevel)
{
string addonsDir = isLevel ? Program.AddonsLevelsPath : Program.AddonsCharactersPath;

string filePath = Path.Combine(addonsDir, fileName);

if (!File.Exists(filePath))
{
await ctx.RespondAsync($"Addon file does not exist (\"{fileName}\")");
return;
}

File.Delete(filePath);
await ctx.RespondAsync($"Addon file succesfully deleted!");
}

private static HttpClient _httpClient;
private const Permissions AddonsAddPermissions = Permissions.ModerateMembers;
private const string MessageBoardHost = "mb.srb2.org";
private const string AddonsUriPath = "addons";
private const string DownloadUriPath = "download";

[Command("addonsadd")]
public async Task AddonsAdd(CommandContext ctx, params string[] _)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsAddPermissions))
return;

await ctx.RespondAsync($"Use either {ctx.Prefix}addonsaddlvl or {ctx.Prefix}addonsaddchar");
}

[Command("addonsaddlvl")]
public async Task AddonsAddLevel(CommandContext ctx, string addonUrl, string fileName)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsAddPermissions))
return;

await AddonsAddInternal(ctx, addonUrl, fileName, true);
}

[Command("addonsaddlvl")]
public async Task AddonsAddLevel(CommandContext ctx, string addonUrl)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsAddPermissions))
return;

await ctx.RespondAsync($"Syntax: '{ctx.Prefix}addonsaddlvl (link to addon forum page) (file name (with or without file extension))'");
}

[Command("addonsaddlvl")]
public async Task AddonsAddLevel(CommandContext ctx)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsAddPermissions))
return;

await ctx.RespondAsync($"Syntax: '{ctx.Prefix}addonsaddlvl (link to addon forum page) (file name (with or without file extension))'");
}

[Command("addonsaddchar")]
public async Task AddonsAddCharacter(CommandContext ctx, string addonUrl, string fileName)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsAddPermissions))
return;

await AddonsAddInternal(ctx, addonUrl, fileName, false);
}

[Command("addonsaddchar")]
public async Task AddonsAddCharacter(CommandContext ctx, string addonUrl)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsAddPermissions))
return;

await ctx.RespondAsync($"Syntax: '{ctx.Prefix}addonsaddchar (link to addon forum page) (file name (with or without file extension))'");
}

[Command("addonsaddchar")]
public async Task AddonsAddCharacter(CommandContext ctx)
{
if (!await CommandHelpers.CheckPermissions(ctx, AddonsAddPermissions))
return;

await ctx.RespondAsync($"Syntax: '{ctx.Prefix}addonsaddchar (link to addon forum page) (file name (with or without file extension))'");
}

private async Task AddonsAddInternal(CommandContext ctx, string addonUrl, string suggestedFileName, bool isLevel)
{
if (_httpClient == default)
_httpClient = new HttpClient();

if (!Uri.TryCreate(addonUrl, UriKind.Absolute, out Uri addonUri))
{
await ctx.RespondAsync("Bad addon link, try again");
return;
}

if (addonUri.Host != MessageBoardHost)
{
await ctx.RespondAsync("Addon link needs to come from the SRB2 Message Board");
return;
}

string[] urlParts = addonUri.PathAndQuery.Remove(0, 1).Split('/');
if (urlParts.Length < 2 || urlParts[0] != AddonsUriPath || string.IsNullOrWhiteSpace(urlParts[1]))
{
await ctx.RespondAsync("Bad addon link, try again");
return;
}

string downloadUrl = $"https://{MessageBoardHost}/{AddonsUriPath}/{urlParts[1]}/{DownloadUriPath}";

string fileNameNoExt = string.Empty;
string fileExtension = string.Empty;

try
{
HttpResponseMessage response = await _httpClient.GetAsync(downloadUrl);

fileExtension = string.Empty;

// Try and get the file extension form the user provided file name
int indexOfDot = suggestedFileName.LastIndexOf('.');

if (indexOfDot != -1 && suggestedFileName.Length - indexOfDot < 5) // Don't accept bogus file extensions
{
fileExtension = suggestedFileName.Substring(indexOfDot);
fileNameNoExt = suggestedFileName.Substring(0, indexOfDot);
}
else
fileNameNoExt = suggestedFileName;

// If the user didn't provide a file extension, let's try and parse it from the response's suggested file name
if (fileExtension == string.Empty && response.Content.Headers.ContentDisposition?.FileName != null)
{
string tempMbSuggestedFileName = response.Content.Headers.ContentDisposition.FileName;

// Remove the '"' character at the end of the suggested file name
string mbSuggestedFileName = tempMbSuggestedFileName.Remove(tempMbSuggestedFileName.Length - 1);

int mbIndexOfDot = mbSuggestedFileName.LastIndexOf('.');

if (mbIndexOfDot != -1 && mbSuggestedFileName.Length - mbIndexOfDot < 5) // Don't accept bogus file extensions
fileExtension = mbSuggestedFileName.Substring(mbIndexOfDot);
}

// All else failed, imply a file extension
if (fileExtension == string.Empty)
fileExtension = ".pk3";

string outputDirectory = isLevel ? Program.AddonsLevelsPath : Program.AddonsCharactersPath;

using (Stream networkStream = await response.Content.ReadAsStreamAsync())
using (FileStream fileStream = new FileStream(Path.Combine(outputDirectory, $"{fileNameNoExt}{fileExtension}"), FileMode.OpenOrCreate))
{
await networkStream.CopyToAsync(fileStream);
fileStream.Flush();
}
}
catch (Exception e)
{
await ctx.RespondAsync($"Something went wrong when downloading the addon ({downloadUrl}): {e.Message}");
return;
}

await ctx.RespondAsync($"Addon download was succesful! File name: \"{fileNameNoExt}{fileExtension}\"");
}

[Command("queue")]
public async Task ReplayQueue(CommandContext ctx)
Expand Down
4 changes: 4 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ namespace RoboBot
{
internal class Program
{
public const string AddonsRootPath = "/root/.srb2/addons/";
public const string AddonsCharactersPath = AddonsRootPath + "Characters";
public const string AddonsLevelsPath = AddonsRootPath + "Levels";

public static string timeFormat = @"ss\.ff";
public static string timeFormatWithMinutes = @"mm\:ss\.ff";
public static string timeFormatWithHours = @"hh\:mm\:ss\.ff";
Expand Down

0 comments on commit eb32e65

Please sign in to comment.