Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
CoPokBl committed Jul 18, 2024
0 parents commit 0ea7981
Show file tree
Hide file tree
Showing 18 changed files with 474 additions and 0 deletions.
41 changes: 41 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
db.dat
config.json

# Common IntelliJ Platform excludes

# User specific
**/.idea/**/workspace.xml
**/.idea/**/tasks.xml
**/.idea/shelf/*
**/.idea/dictionaries
**/.idea/httpRequests/

# Sensitive or high-churn files
**/.idea/**/dataSources/
**/.idea/**/dataSources.ids
**/.idea/**/dataSources.xml
**/.idea/**/dataSources.local.xml
**/.idea/**/sqlDataSources.xml
**/.idea/**/dynamic.xml

# Rider
# Rider auto-generates .iml files, and contentModel.xml
**/.idea/**/*.iml
**/.idea/**/contentModel.xml
**/.idea/**/modules.xml

*.suo
*.user
.vs/
[Bb]in/
[Oo]bj/
_UpgradeReport_Files/
[Pp]ackages/
Logs/

Thumbs.db
Desktop.ini
.DS_Store

bin/
obj/
13 changes: 13 additions & 0 deletions .idea/.idea.QuoteBot/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/.idea.QuoteBot/.idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/.idea.QuoteBot/.idea/indexLayout.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions Commands/ConfigureQuotes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Discord;
using Discord.WebSocket;
using SimpleDiscordNet.Commands;

namespace QuoteBot.Commands;

public class ConfigureQuotes {
private static readonly string[] ValidForms = ["embed", "fake-msg", "bot-msg"];

[SlashCommand("configure-quotes", "Change quote settings", GuildPermission.ManageGuild)]
[SlashCommandArgument("channel", "The quotes channel to send quotes to", true, ApplicationCommandOptionType.Channel)]
[SlashCommandArgument("quote-form", "How to display quotes: 'embed', 'fake-msg' or 'bot-msg'", true, ApplicationCommandOptionType.String)]
public async Task Execute(SocketSlashCommand cmd, DiscordSocketClient client) {
IGuildChannel channel = cmd.GetArgument<IGuildChannel>("channel")!;
string form = cmd.GetArgument<string>("quote-form")!;

if (!ValidForms.Contains(form)) {
await cmd.RespondWithEmbedAsync("Configure Quotes", "Invalid quote form, must be 'embed', 'fake-msg' or 'bot-msg'.", ResponseType.Error, ephemeral: false);
return;
}

if (cmd.Channel.GetChannelType() == ChannelType.DM) {
await cmd.RespondWithEmbedAsync("Configure Quotes", "You can't do this in your DMs.", ResponseType.Error, ephemeral: false);
return;
}

if (channel is not ITextChannel textChannel) {
await cmd.RespondWithEmbedAsync("Configure Quotes", "Channel must be a text channel.", ResponseType.Error, ephemeral: true);
return;
}

Program.Storage.SetQuoteSettings(cmd.GuildId!.Value, textChannel.Id, form);
await cmd.RespondWithEmbedAsync("Configure Quotes", "Quotes have been configured in this server.", ResponseType.Success, ephemeral: true);
}
}
58 changes: 58 additions & 0 deletions Commands/QuoteCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Discord;
using Discord.WebSocket;
using GeneralPurposeLib;
using QuoteBot.Data;
using SimpleDiscordNet.Commands;

namespace QuoteBot.Commands;

public class QuoteCommand {

[SlashCommand("quote-user", "Quote something someone said and attribute quote to user")]
[SlashCommandArgument("person", "The person you are quoting", true, ApplicationCommandOptionType.User)]
[SlashCommandArgument("message", "What they said", true, ApplicationCommandOptionType.String)]
public Task WithUser(SocketSlashCommand cmd, DiscordSocketClient client) {
IUser quotee = cmd.GetArgument<IUser>("person")!;
string message = cmd.GetArgument<string>("message")!;
return Execute(cmd, client, message, quotee: quotee);
}

[SlashCommand("quote", "Quote something someone said")]
[SlashCommandArgument("person", "The person you are quoting", true, ApplicationCommandOptionType.String)]
[SlashCommandArgument("message", "What they said", true, ApplicationCommandOptionType.String)]
public Task WithString(SocketSlashCommand cmd, DiscordSocketClient client) {
string quotee = cmd.GetArgument<string>("person")!;
string message = cmd.GetArgument<string>("message")!;
return Execute(cmd, client, message, quoteeName: quotee);
}

public async Task Execute(SocketSlashCommand cmd, DiscordSocketClient client, string msg, string? quoteeName = null, IUser? quotee = null) {
if (cmd.Channel.GetChannelType() == ChannelType.DM) {
await cmd.RespondWithEmbedAsync("Quote", "You can't do this in your DMs.", ResponseType.Error, ephemeral: false);
return;
}

ITextChannel? quotesChannel = await cmd.GetQuotesChannel(client);

if (quotesChannel == null) {
await cmd.RespondWithEmbedAsync("Error",
"There is no quotes channel configured, ask a staff member to configure it.", ResponseType.Error,
ephemeral: true);
return;
}

await cmd.DeferAsync();

await Quoting.QuoteMessage(client,
cmd.GuildId!.Value,
quoteeName ?? quotee!.Username,
cmd.User.Username,
cmd.User.Id,
quoteeName ?? quotee!.Id.ToString(),
msg,
quotee);

await cmd.ModifyWithEmbedAsync("Quotes", $"Quote has been created in {quotesChannel.Mention}.",
ResponseType.Success);
}
}
3 changes: 3 additions & 0 deletions Data/Quote.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace QuoteBot.Data;

public record Quote(ulong Quoter, string Quotee, ulong Guild, ulong MessageId, string Text, ulong? QuotedMessageChannel = null, ulong? QuotedMessageId = null);
11 changes: 11 additions & 0 deletions Data/Storage/IStorageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace QuoteBot.Data.Storage;

public interface IStorageService {
void Init();
void Deinit();

void CreateQuote(Quote quote);
void SetQuoteSettings(ulong guild, ulong channel, string form);
ulong? GetQuoteChannel(ulong guild);
string? GetQuoteForm(ulong guild);
}
80 changes: 80 additions & 0 deletions Data/Storage/SqliteStorageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System.Data.SQLite;

namespace QuoteBot.Data.Storage;

public class SqliteStorageService : IStorageService {
private const string ConnectionString = "Data Source=db.dat";
private SQLiteConnection _connection = null!;

public void Init() {
_connection = new SQLiteConnection(ConnectionString);
_connection.Open();
CreateTables();
}

private void CreateTables() {
SQLiteCommand cmd = new(@"
CREATE TABLE IF NOT EXISTS quotes (
quoter VARCHAR(64),
quotee VARCHAR(64),
guild VARCHAR(64),
message_id VARCHAR(64),
quote TEXT,
quoted_message_channel VARCHAR(64),
quoted_message_id VARCHAR(64)
);
CREATE TABLE IF NOT EXISTS guild_configs (
guild VARCHAR(64) PRIMARY KEY,
channel_id VARCHAR(64),
form VARCHAR(16)
)
", _connection);
cmd.ExecuteNonQuery();
}

public void Deinit() {
_connection.Dispose();
}

public void CreateQuote(Quote quote) {
using SQLiteCommand cmd = new("INSERT INTO quotes (quoter, quotee, guild, message_id, quote, quoted_message_channel, quoted_message_id) " +
"VALUES (@quoter, @quotee, @guild, @message_id, @quote, @quoted_message_channel, @quoted_message_id);", _connection);
cmd.Parameters.AddWithValue("quoter", quote.Quoter.ToString());
cmd.Parameters.AddWithValue("quotee", quote.Quotee);
cmd.Parameters.AddWithValue("guild", quote.Guild.ToString());
cmd.Parameters.AddWithValue("message_id", quote.MessageId.ToString());
cmd.Parameters.AddWithValue("quote", quote.Text);
cmd.Parameters.AddWithValue("quoted_message_channel", quote.QuotedMessageChannel.ToString());
cmd.Parameters.AddWithValue("quoted_message_id", quote.QuotedMessageId.ToString());
cmd.ExecuteNonQuery();
}

public void SetQuoteSettings(ulong guild, ulong channel, string form) {
using SQLiteCommand cmd = new("INSERT OR REPLACE INTO guild_configs (guild, channel_id, form) VALUES (@guild, @channel, @form);", _connection);
cmd.Parameters.AddWithValue("guild", guild.ToString());
cmd.Parameters.AddWithValue("channel", channel.ToString());
cmd.Parameters.AddWithValue("form", form);
cmd.ExecuteNonQuery();
}

public ulong? GetQuoteChannel(ulong guild) {
using SQLiteCommand cmd = new("SELECT channel_id FROM guild_configs WHERE guild = @guild;", _connection);
cmd.Parameters.AddWithValue("guild", guild.ToString());
using SQLiteDataReader reader = cmd.ExecuteReader();
if (!reader.Read()) {
return null;
}
return ulong.Parse(reader.GetString(0));
}

public string? GetQuoteForm(ulong guild) {
using SQLiteCommand cmd = new("SELECT form FROM guild_configs WHERE guild = @guild;", _connection);
cmd.Parameters.AddWithValue("guild", guild.ToString());
using SQLiteDataReader reader = cmd.ExecuteReader();
if (!reader.Read()) {
return null;
}
return reader.GetString(0);
}
}
9 changes: 9 additions & 0 deletions DefaultConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using GeneralPurposeLib;

namespace QuoteBot;

public static class DefaultConfig {
public static Dictionary<string, Property> Values = new() {
{ "token", "xxxxxxxxxxxxxxx" }
};
}
37 changes: 37 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using GeneralPurposeLib;
using QuoteBot.Data.Storage;
using SimpleDiscordNet;

namespace QuoteBot;

public static class Program {
public static IStorageService Storage = null!;

public static async Task Main(string[] args) {
Logger.Init(LogLevel.Debug);
Config config = new(DefaultConfig.Values);

Storage = new SqliteStorageService();
Storage.Init();

SimpleDiscordBot bot = new(config["token"]);

bot.Log += message => {
Logger.Info(message.Message);
if (message.Exception != null) {
Logger.Info(message.Exception);
}
return Task.CompletedTask;
};

bot.Client.Ready += () => {
bot.UpdateCommands();
bot.Client.SetCustomStatusAsync("Watching for funny quotes");
Logger.Info("Bot ready");
return Task.CompletedTask;
};
await bot.StartBot();
Logger.Info("Bot started");
await bot.WaitAsync();
}
}
22 changes: 22 additions & 0 deletions QuoteBot.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.15.2" />
<PackageReference Include="GeneralPurposeLib" Version="1.2.1" />
<PackageReference Include="System.Data.SQLite" Version="1.0.118" />
</ItemGroup>

<ItemGroup>
<Reference Include="SimpleDiscordNet">
<HintPath>SimpleDiscordNet.dll</HintPath>
</Reference>
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions QuoteBot.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuoteBot", "QuoteBot.csproj", "{132496D3-908A-4419-BB25-A08E11448FDE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{132496D3-908A-4419-BB25-A08E11448FDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{132496D3-908A-4419-BB25-A08E11448FDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{132496D3-908A-4419-BB25-A08E11448FDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{132496D3-908A-4419-BB25-A08E11448FDE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Loading

0 comments on commit 0ea7981

Please sign in to comment.