Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce channel "stickied messages" #9

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions BLART/Bot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ private async Task Init(string[] args)
Log.Debug(nameof(Init), "Setting up raid protection..");
Client.UserJoined += RaidProtection.OnUserJoined;

Log.Debug(nameof(Init), "Setting up sticky messages..");
Client.MessageReceived += StickiedMessages.OnMessageReceived;

Log.Debug(nameof(Init), "Installing slash commands..");
await SlashCommandHandler.InstallCommandsAsync();
Client.Ready += async () =>
Expand Down
36 changes: 36 additions & 0 deletions BLART/Commands/StickiedMessages/AddMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace BLART.Commands.StickiedMessages;

using BLART.Services;
using Discord.Interactions;
using Discord.WebSocket;

[Group("stick", "Commands to manage channel sticky messages.")]
public partial class StickiedMessages : InteractionModuleBase<SocketInteractionContext>
{
[SlashCommand("add", "Adds a sticky message to a channel.")]
public async Task Add([Summary("channel", "The channel to stick a message to.")]SocketTextChannel channel, [Summary("message", "The message to stick.")]string message)
{
if (!CommandHandler.CanRunStaffCmd(Context.User))
{
await RespondAsync(embed: await ErrorHandlingService.GetErrorEmbed(ErrorCodes.PermissionDenied), ephemeral: true);
return;
}

if (string.IsNullOrWhiteSpace(message))
{
await RespondAsync("Sticky message cannot be empty!", ephemeral: true);
return;
}

var sticky = DatabaseHandler.GetStickyMessage(channel.Id);
if (sticky != null)
{
await RespondAsync($"The {channel.Mention} channel already has an active sticky message! Remove it first.", ephemeral: true);
return;
}

DatabaseHandler.AddEntry(channel.Id, message, DatabaseType.StickiedMessage, Context.User.Id);
await RespondAsync($"The following sticky message has been added to the {channel.Mention} channel.", embed: await EmbedBuilderService.CreateStickyMessage(message, Context.User), ephemeral: true);

}
}
40 changes: 40 additions & 0 deletions BLART/Commands/StickiedMessages/RemoveMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace BLART.Commands.StickiedMessages;

using BLART.Services;
using Discord;
using Discord.Interactions;

public partial class StickiedMessages : InteractionModuleBase<SocketInteractionContext>
{
[SlashCommand("remove", "Removes a sticky message from a channel.")]
public async Task Remove([Summary("channel", "The channel to remove a stuck message from.")] ITextChannel channel)
{
if (!CommandHandler.CanRunStaffCmd(Context.User))
{
await RespondAsync(embed: await ErrorHandlingService.GetErrorEmbed(ErrorCodes.PermissionDenied), ephemeral: true);
return;
}

var sticky = DatabaseHandler.GetStickyMessage(channel.Id);
if (sticky == null)
{
await RespondAsync($"The {channel.Mention} channel does not have a sticky message.", ephemeral: true);
return;
}

// Remove existing message
string? id = DatabaseHandler.GetStickyMessageID(channel.Id);
if (id is not null)
{
await DeferAsync(true);

IMessage msg = await channel.GetMessageAsync(ulong.Parse(id));

if (msg is not null)
await msg.DeleteAsync(new() { AuditLogReason = "Removed message for deleted sticky message." });
}

DatabaseHandler.RemoveEntry(channel.Id, DatabaseType.StickiedMessage);
await RespondAsync($"Sticky message has been removed from the {channel.Mention} channel!", ephemeral: true);
}
}
2 changes: 2 additions & 0 deletions BLART/DatabaseType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public enum DatabaseType
BugReport,
SelfRole,
Tags,
StickiedMessage,
StickiedMessageIDs,
}
46 changes: 46 additions & 0 deletions BLART/Modules/StickiedMessages.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using BLART.Objects;
using BLART.Services;
using Discord;
using Discord.WebSocket;
using System;

namespace BLART.Modules;

public class StickiedMessages
{
public static async Task Post(StickyMessage message)
{
IGuild guild = Bot.Instance.Guild;

IGuildUser staff = await guild.GetUserAsync(message.StaffId);
staff ??= await guild.GetCurrentUserAsync();

ITextChannel textChannel = await guild.GetTextChannelAsync(message.ChannelId);
if (textChannel != null)
{
IUserMessage m = await textChannel.SendMessageAsync(embed: await EmbedBuilderService.CreateStickyMessage(message.Message, staff));
DatabaseHandler.AddEntry(m.Id, textChannel.Id.ToString(), DatabaseType.StickiedMessageIDs);
}
}

public static async Task OnMessageReceived(SocketMessage message)
{
StickyMessage? msg = DatabaseHandler.GetStickyMessage(message.Channel.Id);
if (msg is null)
return;

string? stickyId = DatabaseHandler.GetStickyMessageID(msg.ChannelId);

if (stickyId is not null)
{
IMessage current = await message.Channel.GetMessageAsync(ulong.Parse(stickyId));
if ((DateTime.UtcNow - current.Timestamp).TotalSeconds < 5)
return;

await current.DeleteAsync(new() { AuditLogReason = "Creating new sticky message." });
DatabaseHandler.RemoveEntry(current.Id, DatabaseType.StickiedMessageIDs);
}

await Post(msg);
}
}
22 changes: 22 additions & 0 deletions BLART/Objects/StickyMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BLART.Objects
{
public class StickyMessage
{
public ulong StaffId { get; set; }
public ulong ChannelId { get; set; }
public string Message { get; set; }

public StickyMessage(ulong channelId, string message, ulong staffId)
{
ChannelId = channelId;
Message = message;
StaffId = staffId;
}
}
}
82 changes: 82 additions & 0 deletions BLART/Services/DatabaseHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace BLART.Services;

using System.Globalization;
using System.Net;
using System.Threading.Channels;
using BLART.Objects;
using Discord;
using Microsoft.Data.Sqlite;
Expand Down Expand Up @@ -75,6 +76,22 @@ public static async Task Init(bool updateTables = false)
"CREATE TABLE IF NOT EXISTS Tags(Id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, tag TEXT)";
cmd.ExecuteNonQuery();
}

using (SqliteCommand cmd = conn.CreateCommand())
{
Log.Info(nameof(Init), "Creating sticked messages table..");
cmd.CommandText =
"CREATE TABLE IF NOT EXISTS StickiedMessages(Id INTEGER PRIMARY KEY AUTOINCREMENT, channelId TEXT, message TEXT, staffId TEXT)";
cmd.ExecuteNonQuery();
}

using (SqliteCommand cmd = conn.CreateCommand())
{
Log.Info(nameof(Init), "Creating sticked messages ID table..");
cmd.CommandText =
"CREATE TABLE IF NOT EXISTS StickiedMessagesIDs(Id INTEGER PRIMARY KEY AUTOINCREMENT, messageId TEXT, channelId TEXT)";
cmd.ExecuteNonQuery();
}
}

await BugReporting.LoadDatabaseEntries();
Expand All @@ -96,6 +113,8 @@ public static void AddEntry(ulong id, string description, DatabaseType type, ulo
DatabaseType.BugReport => "INSERT INTO BugReports(messageId, threadId) VALUES(@id, @string)",
DatabaseType.SelfRole => "INSERT INTO SelfRoles(roleId) VALUES(@id)",
DatabaseType.Tags => "INSERT INTO Tags(name, tag) VALUES(@name, @tag)",
DatabaseType.StickiedMessage => "INSERT INTO StickiedMessages(channelId, message, staffId) VALUES(@id, @string, @staff)",
DatabaseType.StickiedMessageIDs => "INSERT INTO StickiedMessagesIDs(messageId, channelId) VALUES(@id, @string)",
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};

Expand Down Expand Up @@ -141,6 +160,8 @@ public static void RemoveEntry(int id, DatabaseType type)
DatabaseType.BugReport => "DELETE FROM BugReports WHERE Id=@id",
DatabaseType.SelfRole => "DELETE FROM SelfRoles WHERE Id=@id",
DatabaseType.Tags => "DELETE FROM Tags WHERE Id=@id",
DatabaseType.StickiedMessage => "DELETE FROM StickiedMessages WHERE Id=@id",
DatabaseType.StickiedMessageIDs => "DELETE FROM StickiedMessagesIDs WHERE Id=@id",
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};

Expand All @@ -166,6 +187,8 @@ public static void RemoveEntry(ulong userId, DatabaseType type)
DatabaseType.Ban => "DELETE FROM Bans WHERE UserId=@id",
DatabaseType.BugReport => "DELETE FROM BugReports WHERE messageId=@id OR threadId=@id",
DatabaseType.SelfRole => "DELETE FROM SelfRoles WHERE roleId=@id",
DatabaseType.StickiedMessage => "DELETE FROM StickiedMessages WHERE channelId=@id",
DatabaseType.StickiedMessageIDs => "DELETE FROM StickiedMessagesIDs WHERE messageId=@id",
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};

Expand Down Expand Up @@ -438,4 +461,63 @@ public static List<string> GetTagNames()

return tags;
}

public static StickyMessage? GetStickyMessage(ulong channelId)
{
StickyMessage? stick = null;
using (SqliteConnection conn = new(_connectionString))
{
conn.Open();
using (SqliteCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM StickiedMessages WHERE channelId=@id";
cmd.Parameters.AddWithValue("@id", channelId.ToString());

using (SqliteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string message = reader.GetString(2);
string staffId = reader.GetString(3);
stick = new StickyMessage(channelId, message, ulong.Parse(staffId));
break;
}
}
}

conn.Close();
}

return stick;
}

public static string? GetStickyMessageID(ulong channelId)
{
string? result = null;

ITextChannel channel = Bot.Instance.Guild.GetTextChannel(channelId);
if (channel is null)
return result;

using (SqliteConnection conn = new(_connectionString))
{
conn.Open();
using (SqliteCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM StickiedMessagesIDs WHERE channelId=@id";
cmd.Parameters.AddWithValue("@id", channelId.ToString());

using (SqliteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result = reader.GetString(1);
break;
}
}
}
}

return result;
}
}
6 changes: 6 additions & 0 deletions BLART/Services/EmbedBuilderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ public static async Task<Embed> CreateBasicEmbed(string title, string descriptio
Log.Info(nameof(CreateBasicEmbed), $"Sending embed {title}.");
return await Task.Run(() => new EmbedBuilder().WithTitle(title).WithDescription(description).WithColor(color).WithCurrentTimestamp().WithFooter(Footer).Build());
}

public static async Task<Embed> CreateStickyMessage(string message, IUser staff)
{
Log.Info(nameof(CreateBasicEmbed), $"Sending sticky embed {message}.");
return await Task.Run(() => new EmbedBuilder().WithTitle("Stickied Message").WithDescription(message).WithColor(Color.Blue).WithCurrentTimestamp().WithFooter(Footer).WithAuthor(staff).Build());
}
}