add quote commands and make it actually use mysql connection pooling oops

This commit is contained in:
Elijah R 2024-04-03 15:50:24 -04:00
parent deb3d978e5
commit 67903be1dd
4 changed files with 69 additions and 16 deletions

View file

@ -7,5 +7,6 @@ public class ChatlogQuery
public DateTime? FromTimestamp { get; set; } public DateTime? FromTimestamp { get; set; }
public DateTime? ToTimestamp { get; set; } public DateTime? ToTimestamp { get; set; }
public int? Count { get; set; } public int? Count { get; set; }
public bool Random { get; set; }
public string? Regex { get; set; } public string? Regex { get; set; }
} }

View file

@ -6,22 +6,21 @@ namespace EmperorPalpatine;
public class Database public class Database
{ {
private MySqlConnection db; private readonly string connstr;
public Database(ConfigDatabase config) public Database(ConfigDatabase config)
{ {
var connstr = new MySqlConnectionStringBuilder connstr = new MySqlConnectionStringBuilder
{ {
Server = config.Host, Server = config.Host,
UserID = config.Username, UserID = config.Username,
Password = config.Password, Password = config.Password,
Database = config.Database, Database = config.Database,
}; }.ToString();
db = new MySqlConnection(connstr.ToString());
} }
public async Task InitAsync() public async Task InitAsync()
{ {
await using var db = new MySqlConnection(connstr);
await db.OpenAsync(); await db.OpenAsync();
using var cmd = db.CreateCommand(); using var cmd = db.CreateCommand();
cmd.CommandText = """ cmd.CommandText = """
@ -46,6 +45,8 @@ public class Database
public async Task LogChatMessageAsync(string vm, string username, string message) public async Task LogChatMessageAsync(string vm, string username, string message)
{ {
await using var db = new MySqlConnection(connstr);
await db.OpenAsync();
await using var cmd = db.CreateCommand(); await using var cmd = db.CreateCommand();
cmd.CommandText = "INSERT INTO chatlogs (vm, username, message) VALUES (@vm, @username, @message)"; cmd.CommandText = "INSERT INTO chatlogs (vm, username, message) VALUES (@vm, @username, @message)";
cmd.Parameters.AddWithValue("@vm", vm); cmd.Parameters.AddWithValue("@vm", vm);
@ -56,6 +57,8 @@ public class Database
public async Task LogIPAsync(string vm, string username, IPAddress ip) public async Task LogIPAsync(string vm, string username, IPAddress ip)
{ {
await using var db = new MySqlConnection(connstr);
await db.OpenAsync();
await using var cmd = db.CreateCommand(); await using var cmd = db.CreateCommand();
cmd.CommandText = "SELECT COUNT(ip) FROM iplog WHERE ip = @ip AND date >= DATE_SUB(NOW(), INTERVAL 1 HOUR) AND vm = @vm AND username = @username"; cmd.CommandText = "SELECT COUNT(ip) FROM iplog WHERE ip = @ip AND date >= DATE_SUB(NOW(), INTERVAL 1 HOUR) AND vm = @vm AND username = @username";
cmd.Parameters.AddWithValue("@ip", ip.GetAddressBytes()); cmd.Parameters.AddWithValue("@ip", ip.GetAddressBytes());
@ -70,6 +73,8 @@ public class Database
public async Task<LoggedChatMessage[]> GetChatlogsAsync(ChatlogQuery q) public async Task<LoggedChatMessage[]> GetChatlogsAsync(ChatlogQuery q)
{ {
await using var db = new MySqlConnection(connstr);
await db.OpenAsync();
await using var cmd = db.CreateCommand(); await using var cmd = db.CreateCommand();
cmd.CommandText = "SELECT * FROM chatlogs"; cmd.CommandText = "SELECT * FROM chatlogs";
List<string> where = new(); List<string> where = new();
@ -104,7 +109,7 @@ public class Database
} }
if (q.Count != null) if (q.Count != null)
{ {
cmd.CommandText += " ORDER BY date DESC LIMIT @count"; cmd.CommandText += $" ORDER BY {(q.Random ? "RAND()" : "date DESC")} LIMIT @count";
cmd.Parameters.AddWithValue("@count", q.Count); cmd.Parameters.AddWithValue("@count", q.Count);
} }
await using var reader = await cmd.ExecuteReaderAsync(); await using var reader = await cmd.ExecuteReaderAsync();
@ -126,6 +131,8 @@ public class Database
public async Task<LoggedIP[]> GetIPFromUsernameAsync(string username) public async Task<LoggedIP[]> GetIPFromUsernameAsync(string username)
{ {
await using var db = new MySqlConnection(connstr);
await db.OpenAsync();
await using var cmd = db.CreateCommand(); await using var cmd = db.CreateCommand();
cmd.CommandText = "SELECT * FROM iplog WHERE username = @username"; cmd.CommandText = "SELECT * FROM iplog WHERE username = @username";
cmd.Parameters.AddWithValue("@username", username); cmd.Parameters.AddWithValue("@username", username);
@ -146,6 +153,8 @@ public class Database
public async Task<LoggedIP[]> GetUsernameFromIPAsync(IPAddress ip) public async Task<LoggedIP[]> GetUsernameFromIPAsync(IPAddress ip)
{ {
await using var db = new MySqlConnection(connstr);
await db.OpenAsync();
await using var cmd = db.CreateCommand(); await using var cmd = db.CreateCommand();
cmd.CommandText = "SELECT * FROM iplog WHERE ip = @ip"; cmd.CommandText = "SELECT * FROM iplog WHERE ip = @ip";
cmd.Parameters.AddWithValue("@ip", ip.GetAddressBytes()); cmd.Parameters.AddWithValue("@ip", ip.GetAddressBytes());

View file

@ -9,7 +9,7 @@ namespace EmperorPalpatine;
public class DiscordCommands : ApplicationCommandModule public class DiscordCommands : ApplicationCommandModule
{ {
[SlashCommand("vm", "Get info from a VM")] [SlashCommand("vm", "Get info from a VM")]
public async Task VM(InteractionContext ctx, [ChoiceProvider(typeof(VMAutocompleteProvider))] [Option("vm", "VM to get info from")] string VM) { public async Task VM(InteractionContext ctx, [Autocomplete(typeof(VMAutocompleteProvider))] [Option("vm", "VM to get info from")] string VM) {
if (Program.VMs.All(v => v.Config.Name != VM)) { if (Program.VMs.All(v => v.Config.Name != VM)) {
await ctx.CreateResponseAsync("No VM by that name found."); await ctx.CreateResponseAsync("No VM by that name found.");
return; return;
@ -71,7 +71,7 @@ public class DiscordCommands : ApplicationCommandModule
[SlashCommand("ban", "Ban a user")] [SlashCommand("ban", "Ban a user")]
public async Task Ban(InteractionContext ctx, [Option("username", "User to ban")] string username, public async Task Ban(InteractionContext ctx, [Option("username", "User to ban")] string username,
[Option("vm", "VM to ban from")] [ChoiceProvider(typeof(VMAutocompleteProvider))] string VM) { [Option("vm", "VM to ban from")] [Autocomplete(typeof(VMAutocompleteProvider))] string VM) {
if (Program.VMs.All(v => v.Config.Name != VM)) { if (Program.VMs.All(v => v.Config.Name != VM)) {
await ctx.CreateResponseAsync("No VM by that name found."); await ctx.CreateResponseAsync("No VM by that name found.");
return; return;
@ -94,7 +94,7 @@ public class DiscordCommands : ApplicationCommandModule
[SlashCommand("kick", "Kick a user")] [SlashCommand("kick", "Kick a user")]
public async Task Kick(InteractionContext ctx, [Option("username", "User to kick")] string username, public async Task Kick(InteractionContext ctx, [Option("username", "User to kick")] string username,
[Option("vm", "VM to kick from"), ChoiceProvider(typeof(VMAutocompleteProvider))] string VM) { [Option("vm", "VM to kick from"), Autocomplete(typeof(VMAutocompleteProvider))] string VM) {
if (Program.VMs.All(v => v.Config.Name != VM)) { if (Program.VMs.All(v => v.Config.Name != VM)) {
await ctx.CreateResponseAsync("No VM by that name found."); await ctx.CreateResponseAsync("No VM by that name found.");
return; return;
@ -117,7 +117,7 @@ public class DiscordCommands : ApplicationCommandModule
[SlashCommand("reboot", "Reboot a VM")] [SlashCommand("reboot", "Reboot a VM")]
public async Task Reboot(InteractionContext ctx, public async Task Reboot(InteractionContext ctx,
[Option("vm", "VM to reboot"), ChoiceProvider(typeof(VMAutocompleteProvider))] string VM) [Option("vm", "VM to reboot"), Autocomplete(typeof(VMAutocompleteProvider))] string VM)
{ {
if (Program.VMs.All(v => v.Config.Name != VM)) { if (Program.VMs.All(v => v.Config.Name != VM)) {
await ctx.CreateResponseAsync("No VM by that name found."); await ctx.CreateResponseAsync("No VM by that name found.");
@ -137,7 +137,7 @@ public class DiscordCommands : ApplicationCommandModule
[SlashCommand("restore", "Restore a VM")] [SlashCommand("restore", "Restore a VM")]
public async Task Restore(InteractionContext ctx, public async Task Restore(InteractionContext ctx,
[Option("vm", "VM to restore"), ChoiceProvider(typeof(VMAutocompleteProvider))] string VM) [Option("vm", "VM to restore"), Autocomplete(typeof(VMAutocompleteProvider))] string VM)
{ {
if (Program.VMs.All(v => v.Config.Name != VM)) { if (Program.VMs.All(v => v.Config.Name != VM)) {
await ctx.CreateResponseAsync("No VM by that name found."); await ctx.CreateResponseAsync("No VM by that name found.");
@ -196,14 +196,35 @@ public class DiscordCommands : ApplicationCommandModule
} }
await ctx.EditResponseAsync(new DiscordWebhookBuilder().AddEmbeds(IPEmbeds)); await ctx.EditResponseAsync(new DiscordWebhookBuilder().AddEmbeds(IPEmbeds));
} }
}
public class VMAutocompleteProvider : IChoiceProvider { [SlashCommand("quote", "Quote a user")]
public async Task<IEnumerable<DiscordApplicationCommandOptionChoice>> Provider() { public async Task Quote(InteractionContext ctx, [Option("username", "User to quote")] string username)
var list = new List<DiscordApplicationCommandOptionChoice>(); {
foreach (ConfigVM vm in Program.Config.VMs) { await ctx.DeferAsync();
list.Add(new DiscordApplicationCommandOptionChoice(vm.Name, vm.Name)); var chat = await Program.Database.GetChatlogsAsync(new ChatlogQuery
{
Username = username,
Count = 1,
Random = true
});
if (chat.Length == 0)
{
await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"@No messages found for {username}"));
return;
} }
return list.ToArray(); await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"> {chat[0].Message}\n- {chat[0].Username}"));
}
}
public class VMAutocompleteProvider : IAutocompleteProvider {
public Task<IEnumerable<DiscordAutoCompleteChoice>> Provider(AutocompleteContext ctx)
{
var list = new List<DiscordAutoCompleteChoice>();
foreach (ConfigVM vm in Program.Config.VMs) {
list.Add(new DiscordAutoCompleteChoice(vm.Name, vm.Name));
}
if (list.Count > 25) list.RemoveRange(24, list.Count - 25);
return Task.FromResult(list.AsEnumerable());
} }
} }

View file

@ -32,6 +32,28 @@ public class VM
this.cvm.ConnectionClosed += CvmOnConnectionClosed; this.cvm.ConnectionClosed += CvmOnConnectionClosed;
this.cvm.UserRenamed += (_, e) => CheckUsername(e.User); this.cvm.UserRenamed += (_, e) => CheckUsername(e.User);
this.cvm.UserJoined += (_, e) => CheckUsername(e); this.cvm.UserJoined += (_, e) => CheckUsername(e);
this.cvm.RegisterCommand("+quote", QuoteCommand);
}
private async void QuoteCommand(string username, string[] args)
{
if (args.Length != 1)
{
await cvm.SendChat($"@{username} Usage: +quote <username>");
return;
}
var chat = await database.GetChatlogsAsync(new ChatlogQuery
{
Username = args[0],
Count = 1,
Random = true
});
if (chat.Length == 0)
{
await cvm.SendChat($"@{username} No messages found for {args[0]}");
return;
}
await cvm.SendXSSChat($"\"{chat[0].Message}\" - {chat[0].Username}");
} }
private void CvmOnConnectionClosed(object? sender, EventArgs e) private void CvmOnConnectionClosed(object? sender, EventArgs e)