Skip to content

Commit

Permalink
Refactored validation within GeneralCommands and tackles various null…
Browse files Browse the repository at this point in the history
…able reference warnings via appropriate suppression or logic improvement
  • Loading branch information
mcllsti committed Nov 13, 2023
1 parent 6ba630a commit a00a2cd
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 79 deletions.
115 changes: 49 additions & 66 deletions DiscordBot.App/Commands/GeneralCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ public async Task HelpVerifyCommand(InteractionContext ctx)
[SlashCommand("pingserver", "ping server")]
public async Task PingServerCommand(InteractionContext ctx)
{
if (ctx.Channel != _discordService.CommandsChannel)
if (!IsValidInteractionContext(ctx, out string errorOutput))
{
await ctx.CreateResponseAsync("Invalid channel.");
await ctx.CreateResponseAsync(errorOutput);
return;
}

Expand All @@ -56,26 +56,14 @@ public async Task PingServerCommand(InteractionContext ctx)
[SlashCommand("remove-read-only", "remove read only from user")]
public async Task RemoveReadOnlyCommand(InteractionContext ctx, [Option("target", "target member to remove read only")] DiscordUser targetMember)
{
if (ctx.Channel != _discordService.CommandsChannel)
{
await ctx.CreateResponseAsync("Invalid channel.");
return;
}
Log.Information("RemoveReadOnlyCommand");

var senderMember = ctx.Member;

if (targetMember == null || senderMember == null)
if (!IsValidInteractionContext(ctx, out string errorOutput, targetMember))
{
await ctx.CreateResponseAsync("```SUCH MEMBERS DO NOT EXIST```");
await ctx.CreateResponseAsync(errorOutput);
return;
}

if (targetMember.Id == senderMember.Id)
{
await ctx.CreateResponseAsync("```YOU CAN'T DO THIS ACTION ON YOURSELF```");
return;
}
Log.Information("RemoveReadOnlyCommand");

var member = await _discordService.Guild.GetMemberAsync(targetMember.Id);

Expand All @@ -101,23 +89,13 @@ public async Task RemoveReadOnlyCommand(InteractionContext ctx, [Option("target"
[SlashCommand("read-only", "put read only on user")]
public async Task ReadOnlyCommand(InteractionContext ctx, [Option("target", "target member")] DiscordUser targetMember, [Option("reason", "reason for this action")] string reason)
{
if (ctx.Channel != _discordService.CommandsChannel)
return;
Log.Information("ReadOnlyCommand");

var senderMember = ctx.Member;

if (targetMember == null || senderMember == null)
if (!IsValidInteractionContext(ctx, out string errorOutput, targetMember))
{
await ctx.CreateResponseAsync("```SUCH MEMBERS DO NOT EXIST```");
await ctx.CreateResponseAsync(errorOutput);
return;
}

if (targetMember.Id == senderMember.Id)
{
await ctx.CreateResponseAsync("```YOU CAN'T DO THIS ACTION ON YOURSELF```");
return;
}
Log.Information("ReadOnlyCommand");

var member = await _discordService.Guild.GetMemberAsync(targetMember.Id);
if (member.Roles.Any(x => x.Id == _discordService.ReadOnlyRole.Id))
Expand All @@ -139,11 +117,12 @@ public async Task RemoveReadOnlyCommand(InteractionContext ctx, [Option("target"
[SlashCommand("apps", "get active applications")]
public async Task AppsCommand(InteractionContext ctx)
{
if (ctx.Channel != _discordService.CommandsChannel)
if (!IsValidInteractionContext(ctx, out string errorOutput))
{
await ctx.CreateResponseAsync("Invalid channel.");
await ctx.CreateResponseAsync(errorOutput);
return;
}

Log.Information("AppsCommand");

var waitingIssuers = await _serverDiscordApi.GetApps();
Expand All @@ -153,25 +132,28 @@ public async Task AppsCommand(InteractionContext ctx)
[SlashCommand("ann", "post announcement in server")]
public async Task AnnCommand(InteractionContext ctx, [Option("announcement", "announcement to post on the server")] string text)
{
Log.Information("AnnCommand");
if (ctx.Channel != _discordService.CommandsChannel)

if (!IsValidInteractionContext(ctx, out string errorOutput))
{
await ctx.CreateResponseAsync("Invalid channel.");
await ctx.CreateResponseAsync(errorOutput);
return;
}

Log.Information("AnnCommand");

await _serverDiscordApi.PostAnnouncement(text);
await ctx.CreateResponseAsync("Announcement sent!");
}

[SlashCommand("save", "save server state")]
public async Task SaveCommand(InteractionContext ctx)
{
if (ctx.Channel != _discordService.CommandsChannel)
if (!IsValidInteractionContext(ctx, out string errorOutput))
{
await ctx.CreateResponseAsync("Invalid channel.");
await ctx.CreateResponseAsync(errorOutput);
return;
}

Log.Information("SaveCommand");

if (await _serverDiscordApi.PostSave())
Expand All @@ -187,28 +169,16 @@ public async Task SaveCommand(InteractionContext ctx)
[SlashCommand("kick", "kick user")]
public async Task KickCommand(InteractionContext ctx, [Option("target", "target member")] DiscordUser targetMember, [Option("reason", "reason for this action")] string reason)
{
if (ctx.Channel != _discordService.CommandsChannel)
{
await ctx.CreateResponseAsync("Invalid channel.");
return;
}
Log.Information("KickCommand");

var senderMember = ctx.Member;

if (targetMember == null || senderMember == null)
if (!IsValidInteractionContext(ctx, out string errorOutput, targetMember))
{
await ctx.CreateResponseAsync("```SUCH MEMBERS DO NOT EXIST```");
await ctx.CreateResponseAsync(errorOutput);
return;
}

if (targetMember.Id == senderMember.Id)
{
await ctx.CreateResponseAsync("```YOU CAN'T DO THIS ACTION ON YOURSELF```");
return;
}
Log.Information("KickCommand");

if(await _serverDiscordApi.PostKick(nameof(_discordService.CommandsChannel), ctx.User.Id, ctx.User.Username, targetMember.Id, targetMember.Username, reason))
if (await _serverDiscordApi.PostKick(nameof(_discordService.CommandsChannel), ctx.User.Id, ctx.User.Username, targetMember.Id, targetMember.Username, reason))
{
var member = await _discordService.Guild.GetMemberAsync(targetMember.Id);
await member.RemoveAsync(reason);
Expand All @@ -222,34 +192,47 @@ public async Task SaveCommand(InteractionContext ctx)
[SlashCommand("ban", "ban user")]
public async Task BanCommand(InteractionContext ctx, [Option("target", "target member")] DiscordUser targetMember, [Option("reason", "reason for this action")] string reason)
{
if (ctx.Channel != _discordService.CommandsChannel)
if (!IsValidInteractionContext(ctx, out string errorOutput, targetMember))
{
await ctx.CreateResponseAsync("Invalid channel.");
await ctx.CreateResponseAsync(errorOutput);
return;
}

Log.Information("BanCommand");

if(await _serverDiscordApi.PostBan(nameof(_discordService.CommandsChannel), ctx.User.Id, ctx.User.Username, targetMember.Id, targetMember.Username, reason))
{
await _discordService.Guild.BanMemberAsync(targetMember.Id, 0, reason);
await ctx.CreateResponseAsync("Banned user");
return;
}

await ctx.CreateResponseAsync("Failed to ban user");
}

private bool IsValidInteractionContext(InteractionContext ctx, out string errorOutput, DiscordUser? targetMember = null)
{
errorOutput = "";
var senderMember = ctx.Member;

if (targetMember == null || senderMember == null)
if (ctx.Channel != _discordService.CommandsChannel)
{
await ctx.CreateResponseAsync("```SUCH MEMBERS DO NOT EXIST```");
return;
errorOutput = "Invalid channel.";
return false;
}

if (targetMember.Id == senderMember.Id)
if (targetMember == null || senderMember == null)
{
await ctx.CreateResponseAsync("```YOU CAN'T DO THIS ACTION ON YOURSELF```");
return;
errorOutput = "```SUCH MEMBERS DO NOT EXIST```";
return false;
}

if(await _serverDiscordApi.PostBan(nameof(_discordService.CommandsChannel), ctx.User.Id, ctx.User.Username, targetMember.Id, targetMember.Username, reason))
if (targetMember.Id == senderMember.Id)
{
await _discordService.Guild.BanMemberAsync(targetMember.Id, 0, reason);
await ctx.CreateResponseAsync("Banned user");
return;
errorOutput = "```YOU CAN'T DO THIS ACTION ON YOURSELF```";
return false;
}

await ctx.CreateResponseAsync("Failed to ban user");
return true;
}
}
6 changes: 3 additions & 3 deletions DiscordBot.App/Middlewares/BasicAuthenticationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public BasicAuthenticationHandler(

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
string authHeader = Request.Headers["Authorization"];
string? authHeader = Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic"))
{

Expand All @@ -43,9 +43,9 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);

return AuthenticateResult.Success(ticket);
return await Task.FromResult(AuthenticateResult.Success(ticket));
}
}
return AuthenticateResult.Fail("Failed to authenticate");
return await Task.FromResult(AuthenticateResult.Fail("Failed to authenticate"));
}
}
6 changes: 3 additions & 3 deletions DiscordBot.App/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
builder.Services.AddSingleton<LoginService>();
builder.Services.AddSingleton<RunnerService>();
builder.Services.AddSingleton<GuildJoinService>();
builder.Services.AddHostedService(provider => provider.GetService<RunnerService>());
builder.Services.AddHostedService(provider => provider.GetRequiredService<RunnerService>());

builder.Services.AddAuthentication("BasicAuthentication")
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);
Expand All @@ -44,15 +44,15 @@
app.UseSwaggerUI();
}

await app.Services.GetService<DiscordService>().Start();
await app.Services.GetRequiredService<DiscordService>().Start();

app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

app.Use(async (context, next) =>
{
if (!context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress))
if (context.Connection.RemoteIpAddress == null || !context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress))
{
context.Response.StatusCode = 403;
return;
Expand Down
1 change: 1 addition & 0 deletions DiscordBot.App/Services/DiscordService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

namespace DiscordBot.Services;

#nullable disable
public class DiscordService
{
public DiscordClient Client { get; private set; }
Expand Down
1 change: 1 addition & 0 deletions DiscordBot.App/Settings/DiscordSettings.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace DiscordBot.Settings;

#nullable disable
public class Roles
{
public ulong Member { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion DiscordBot.App/Settings/ServerApiSettings.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace DiscordBot.Settings;

#nullable disable
public class ServerApiSettings
{
public string Url { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion DiscordBot.Data/Models/Credentials.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace DiscordBot.Models;

#nullable disable
public class Credentials
{
public string Username { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion DiscordBot.Data/Models/DiscordUserDto.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace DiscordBot.Models;

#nullable disable
public class DiscordUserDto
{
public string Id { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion DiscordBot.Data/Models/ResponsePairDto.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace DiscordBot.Models;

#nullable disable
public class ResponsePairDto
{
public ResponsePairDto()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public BasicAuthenticationHandler(

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
string authHeader = Request.Headers["Authorization"];
string? authHeader = Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic", StringComparison.InvariantCultureIgnoreCase))
{

Expand All @@ -43,9 +43,9 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);

return AuthenticateResult.Success(ticket);
return await Task.FromResult(AuthenticateResult.Success(ticket));
}
}
return AuthenticateResult.Fail("Failed to authenticate");
return await Task.FromResult(AuthenticateResult.Fail("Failed to authenticate"));
}
}

0 comments on commit a00a2cd

Please sign in to comment.