From 2adc291b7d76be8caad7eabad5ed19461c486da2 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 14:20:15 +0200 Subject: [PATCH 1/8] Allow mulitple configuration flags --- ChaosBot/Database/Entity/ServerConfigurationFlag.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/ChaosBot/Database/Entity/ServerConfigurationFlag.cs b/ChaosBot/Database/Entity/ServerConfigurationFlag.cs index 0640f54..f8d1ab7 100644 --- a/ChaosBot/Database/Entity/ServerConfigurationFlag.cs +++ b/ChaosBot/Database/Entity/ServerConfigurationFlag.cs @@ -10,7 +10,6 @@ namespace ChaosBot.Database.Entity [DBEntity("ServerConfigurationFlags")] public class ServerConfigurationFlag { - [DBUnique] public string key { get; } public string serializedValue { get; } From a06c6d5e91daa5aa1aea9c68c43cd8a109f81d3b Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 14:20:42 +0200 Subject: [PATCH 2/8] Try-catch the timer functionality --- ChaosBot/Discord/Services/TimerHandler.cs | 57 ++++++++++++++--------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/ChaosBot/Discord/Services/TimerHandler.cs b/ChaosBot/Discord/Services/TimerHandler.cs index 9cbdc1c..7182a8a 100644 --- a/ChaosBot/Discord/Services/TimerHandler.cs +++ b/ChaosBot/Discord/Services/TimerHandler.cs @@ -28,32 +28,43 @@ namespace ChaosBot.Discord.Services async void UpdateChannelSloganDescription() { - SocketGuild guild = _client.GetGuild(Convert.ToUInt64(serverConfig.Key)); - if (guild == null) + try { - _logger.Warn($"Guild {Convert.ToUInt64(serverConfig.Key)} not found"); - return; - } - - SocketChannel socketChannel = guild.GetChannel(Convert.ToUInt64(lodestoneChannelSloganDescriptionId)); - if (socketChannel == null) - { - _logger.Warn($"Channel {Convert.ToUInt64(lodestoneChannelSloganDescriptionId)} not found in server {guild.Name}"); - return; - } - - ITextChannel channel = socketChannel as ITextChannel; - if (channel == null) - { - _logger.Warn($"Could not cast channel {socketChannel.Id} to ITextChannel"); - return; - }; + SocketGuild guild = _client.GetGuild(Convert.ToUInt64(serverConfig.Key)); + if (guild == null) + { + _logger.Warn($"Guild {Convert.ToUInt64(serverConfig.Key)} not found"); + return; + } + + SocketChannel socketChannel = + guild.GetChannel(Convert.ToUInt64(lodestoneChannelSloganDescriptionId)); + if (socketChannel == null) + { + _logger.Warn( + $"Channel {Convert.ToUInt64(lodestoneChannelSloganDescriptionId)} not found in server {guild.Name}"); + return; + } + + ITextChannel channel = socketChannel as ITextChannel; + if (channel == null) + { + _logger.Warn($"Could not cast channel {socketChannel.Id} to ITextChannel"); + return; + } - string description = LodestoneManager.GetFreeCompanyById(serverConfig.GetValue("Lodestone:FreeCompanyId")).FreeCompany.Slogan;; - await channel.ModifyAsync(x => + if (!guild.GetUser(_client.CurrentUser.Id).GetPermissions(channel).ManageChannel) return; + + string description = LodestoneManager + .GetFreeCompanyById(serverConfig.GetValue("Lodestone:FreeCompanyId")).FreeCompany + .Slogan; + + await channel.ModifyAsync(x => { x.Topic = description; }); + } + catch (Exception ex) { - x.Topic = description; - }); + _logger.Error($"TimerHandler.UpdateChannelSloganDescription: Exception [{ex}] thrown, <[{ex.Message}]>."); + } } Timer.RunTimer(UpdateChannelSloganDescription, new TimeSpan(TimeSpan.TicksPerMinute * refreshMinutes)); From 155c9b4e7773addda58fa5125dcc2e452cb04d07 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 20:21:14 +0200 Subject: [PATCH 3/8] First version of new database system --- ChaosBot/Attribute/AssemblyController.cs | 4 +- ChaosBot/Database/Controller.cs | 333 +----------------- ChaosBot/Database/Entity/BaseEntity.cs | 30 ++ ChaosBot/Database/Entity/Points.cs | 20 +- ChaosBot/Database/Entity/Raffle.cs | 19 +- .../Entity/ServerConfigurationFlag.cs | 34 +- ChaosBot/Database/Entity/TestEntity.cs | 29 ++ ChaosBot/Database/FilterValue.cs | 16 + ChaosBot/Database/QueryBuilder.cs | 278 +++++++++++++++ ChaosBot/Database/QueryBuilderRaw.cs | 174 +++++++++ .../Repository/ConfigurationRepository.cs | 38 +- .../Database/Repository/PointsRepository.cs | 119 ++----- .../Database/Repository/RaffleRepository.cs | 128 +------ ChaosBot/Discord/Modules/PointsCommands.cs | 13 +- ChaosBot/Program.cs | 3 +- 15 files changed, 674 insertions(+), 564 deletions(-) create mode 100644 ChaosBot/Database/Entity/BaseEntity.cs create mode 100644 ChaosBot/Database/Entity/TestEntity.cs create mode 100644 ChaosBot/Database/FilterValue.cs create mode 100644 ChaosBot/Database/QueryBuilder.cs create mode 100644 ChaosBot/Database/QueryBuilderRaw.cs diff --git a/ChaosBot/Attribute/AssemblyController.cs b/ChaosBot/Attribute/AssemblyController.cs index 8d02727..2532b88 100644 --- a/ChaosBot/Attribute/AssemblyController.cs +++ b/ChaosBot/Attribute/AssemblyController.cs @@ -74,7 +74,7 @@ namespace ChaosBot.Attribute { string columnDefs = String.Join(", ", columnList.Select(c => $"{c.Item1} {c.Item2} {c.Item4}")); string query = $"CREATE TABLE {table} ({columnDefs})"; - Controller.RawQuery(query, false); + Controller.RawQuery(query, readOutput: false); } else { @@ -84,7 +84,7 @@ namespace ChaosBot.Attribute { string query = $"ALTER TABLE {table} ADD COLUMN {column.Item1} {column.Item2} {column.Item4}"; - Controller.RawQuery(query, false, true); + Controller.RawQuery(query, readOutput: false, throwError: true); } catch { diff --git a/ChaosBot/Database/Controller.cs b/ChaosBot/Database/Controller.cs index 2117ba2..b9f5d3a 100644 --- a/ChaosBot/Database/Controller.cs +++ b/ChaosBot/Database/Controller.cs @@ -26,7 +26,7 @@ namespace ChaosBot.Database /// Whether to read the output and return it as a DataFrame /// Whether to throw any exceptions or to log and shrug. /// - public static DataTable RawQuery(string query, bool readOutput = true, bool throwError = false) + public static DataTable RawQuery(string query, Dictionary parameters = null, bool readOutput = true, bool throwError = false) { DataTable dt = new DataTable(); @@ -40,11 +40,24 @@ namespace ChaosBot.Database // Start creating the command and assign the query given SqliteCommand cmd = _conn.CreateCommand(); cmd.CommandText = query; + + // Add parameters if they exist + if (parameters != null) + { + foreach (var parameter in parameters) + { + cmd.Parameters.AddWithValue(parameter.Key, parameter.Value); + } + } + + // Prepare the statement + _logger.Trace($"Database.Controller.RawQuery: Running query {cmd.CommandText}"); + cmd.Prepare(); if (readOutput) { // output needs to be read, make a reader and fill the datatable with the data - SqliteDataReader executeReader = cmd.ExecuteReader(CommandBehavior.SingleResult); + SqliteDataReader executeReader = cmd.ExecuteReader(); dt.Load(executeReader); } else @@ -71,321 +84,5 @@ namespace ChaosBot.Database return dt; } - - /// - /// Insert a list of parameters into a table in the database - /// - /// - /// string table = "SomeTable"; - /// Dictionary<string, object> parameters = new Dictionary<string, object> - /// { - /// { "someInt", 123 }, - /// { "someString", "asdf" }, - /// { "someChar", 'x' } - /// } - /// - /// Controller.InsertQuery(table, parameters); - /// - /// Table to insert into - /// List of parameters to insert to the row. Every type is a key - public static void InsertQuery(string table, Dictionary parameters) - { - try - { - using (_conn) - { - // Open the SQLite connection - _conn.Open(); - - // Start the command creation - SqliteCommand cmd = _conn.CreateCommand(); - - // Build the command bit by bit - // INSERT INTO {table} (key1, key2, key3) VALUES (@key1,@key2,@key3) - StringBuilder commandText = new StringBuilder(); - commandText.Append("INSERT INTO "); - commandText.Append(table); - commandText.Append(" ("); - - foreach (string key in parameters.Keys) - { - commandText.Append($"{key}, "); - } - - commandText.Remove(commandText.Length - 2, 2); - commandText.Append(") VALUES ("); - - foreach (string key in parameters.Keys) - { - // We use @key to indicate the parameter placeholder - commandText.Append($"@{key},"); - } - - // Remove the trailing comma - commandText.Remove(commandText.Length - 1, 1); - commandText.Append(")"); - - // Assign onto QueryCommand - cmd.CommandText = commandText.ToString(); - - // Replace all the parameters to the query - foreach (string key in parameters.Keys) - { - cmd.Parameters.AddWithValue($"@{key}", parameters.GetValueOrDefault(key)); - } - - // Prepare the parameters - cmd.Prepare(); - - // Execute, do not return anything - cmd.ExecuteNonQuery(); - - _conn.Close(); - } - } - catch (Exception ex) - { - _logger.Fatal($"Database.Controller.InsertQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); - } - } - - /// - /// Update rows in the database - /// - /// - /// string table = "SomeTable"; - /// Dictionary<string, object> values = new Dictionary<string, object> - /// { - /// {"key", "newValue"} - /// }; - /// Dictionary<string, object> parameters = new Dictionary<string, object> - /// { - /// {"key", "oldValue"} - /// }; - /// Controller.UpdateQuery(table, values, parameters); - /// - /// Table to update data in - /// List of keys to set. Equivalent of SQL: SET {key} = {value} - /// List of filters to apply in the SQL WHERE condition - public static void UpdateQuery(string table, Dictionary values, Dictionary parameters) - { - try - { - using (_conn) - { - // Open SQLite connection - _conn.Open(); - - // Create the command - SqliteCommand cmd = _conn.CreateCommand(); - - // Build the commandtext - // UPDATE {table} SET {key}=@val_{key} WHERE {key}=@fil_{key} - StringBuilder commandText = new StringBuilder(); - commandText.Append("UPDATE "); - commandText.Append(table); - commandText.Append(" SET "); - - // Build the list of values - List updateList = new List(); - foreach (string key in values.Keys) - { - updateList.Add($"{key}=@val_{key} "); - cmd.Parameters.AddWithValue($@"val_{key}", values.GetValueOrDefault(key)); - } - - // Append the list of values, comma-separated - commandText.Append(string.Join(", ", updateList)); - - // Build the list of filters - List filterList = new List(); - foreach (string key in parameters.Keys) - { - filterList.Add($"{key}=@fil_{key} "); - cmd.Parameters.AddWithValue($"@fil_{key}", parameters.GetValueOrDefault(key)); - } - - if (filterList.Count > 0) - { - // Prepend with WHERE if there are parameters - commandText.Append("WHERE "); - // Append the list of filters AND separated - commandText.Append(string.Join("AND ", filterList)); - } - - // Assign the command - cmd.CommandText = commandText.ToString(); - - // Prepare the parameters - cmd.Prepare(); - - // Execute, do not return - cmd.ExecuteNonQuery(); - - // Close connection - _conn.Close(); - } - } - catch (Exception ex) - { - _logger.Fatal($"Database.Controller.UpdateQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); - } - } - - public static int TransactionQuery(List cmds) - { - SqliteCommand command = _conn.CreateCommand(); - SqliteTransaction transaction; - - _conn.Open(); - - // Start a local transaction. - transaction = _conn.BeginTransaction(); - - // Must assign both transaction object and connection - // to Command object for a pending local transaction - command.Connection = _conn; - command.Transaction = transaction; - - try - { - foreach (var cmd in cmds) - { - command.CommandText = cmd.CommandText; - command.ExecuteNonQuery(); - } - - // Attempt to commit the transaction. - transaction.Commit(); - _logger.Info($"{cmds.Count} record(s) are written to database."); - } - catch (Exception ex) - { - _logger.Warn("Commit Exception Type: {0}", ex.GetType()); - _logger.Warn(" Message: {0}", ex.Message); - - // Attempt to roll back the transaction. - try - { - transaction.Rollback(); - } - catch (Exception ex2) - { - // This catch block will handle any errors that may have occurred - // on the server that would cause the rollback to fail, such as - // a closed connection. - _logger.Warn("Rollback Exception Type: {0}", ex2.GetType()); - _logger.Warn(" Message: {0}", ex2.Message); - } - - return 0; - } - - _conn.Close(); - return cmds.Count; - } - - public static DataTable SelectQuery(string table, string selectColumns = "*", Dictionary filterColumns = null, string orderByKey = null) - { - DataTable dt = new DataTable(); - - try - { - using (_conn) - { - _conn.Open(); - SqliteCommand cmd = _conn.CreateCommand(); - - string filter = null; - if (filterColumns != null) - { - List filterList = new List(); - foreach (string key in filterColumns.Keys) - { - filterList.Add($"{key} = @{key}"); - } - - filter = $"WHERE {Strings.Join(filterList.ToArray(), " AND ")}"; - - foreach (string key in filterColumns.Keys) - { - cmd.Parameters.AddWithValue($@"{key}", filterColumns.GetValueOrDefault(key)); - } - } - - string order = null; - if (orderByKey != null) - { - order = $"ORDER BY {orderByKey}"; - } - - string query = $"SELECT {selectColumns} FROM {table} {filter} {order}"; - - cmd.CommandText = query; - cmd.Prepare(); - SqliteDataReader executeReader = cmd.ExecuteReader(); - - dt.Load(executeReader); - - _conn.Close(); - } - } - catch (Exception ex) - { - _logger.Fatal($"Database.Controller.SelectQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); - } - - return dt; - } - - public static void DeleteQuery(string table, Dictionary filterColumns = null, string orderByKey = null, int limit = -1, int offset = -1) - { - try - { - using (_conn) - { - _conn.Open(); - SqliteCommand cmd = _conn.CreateCommand(); - - string filter = null; - if (filterColumns != null) - { - List filterList = new List(); - foreach (string key in filterColumns.Keys) - { - filterList.Add($"{key} = @{key}"); - } - - filter = $"WHERE {Strings.Join(filterList.ToArray(), " AND ")}"; - - foreach (string key in filterColumns.Keys) - { - cmd.Parameters.AddWithValue($@"{key}", filterColumns.GetValueOrDefault(key)); - } - } - - string order = null; - if (orderByKey != null) - { - order = $"ORDER BY {orderByKey}"; - } - - string limitString = limit > 0 ? $"LIMIT {limit}" : null; - string offsetString = offset > 0 ? $"OFFSET {offset}" : null; - - string query = $"DELETE FROM {table} {filter} {order} {limitString} {offsetString}"; - - cmd.CommandText = query; - cmd.Prepare(); - cmd.ExecuteNonQuery(); - - _conn.Close(); - } - } - catch (Exception ex) - { - _logger.Fatal($"Database.Controller.DeleteQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); - } - } } } \ No newline at end of file diff --git a/ChaosBot/Database/Entity/BaseEntity.cs b/ChaosBot/Database/Entity/BaseEntity.cs new file mode 100644 index 0000000..8451e7b --- /dev/null +++ b/ChaosBot/Database/Entity/BaseEntity.cs @@ -0,0 +1,30 @@ +using System; +using System.Data; +using System.Linq; +using ChaosBot.Attribute; +using ChaosBot.Database; + +namespace ChaosBot.Database.Entity +{ + public abstract class BaseEntity + { + protected BaseEntity() {} + + public abstract void SetFromRow(DataRow row); + + + protected static QueryBuilder Query() where T : BaseEntity, new() + { + var dbEntityAttribute = typeof(T).GetCustomAttributes( + typeof(DBEntity), + true + ).FirstOrDefault() as DBEntity; + if (dbEntityAttribute != null) + { + return new QueryBuilder(dbEntityAttribute.Table); + } + + throw new SystemException($"Class {typeof(T)} does not have an attribute of {typeof(DBEntity)} set"); + } + } +} \ No newline at end of file diff --git a/ChaosBot/Database/Entity/Points.cs b/ChaosBot/Database/Entity/Points.cs index a51a027..c074d88 100644 --- a/ChaosBot/Database/Entity/Points.cs +++ b/ChaosBot/Database/Entity/Points.cs @@ -1,19 +1,22 @@ +using System.Data; using ChaosBot.Attribute; namespace ChaosBot.Database.Entity { [DBEntity("PointsTable")] - public class Points + public class Points : BaseEntity { [DBPrimaryKey] [DBAutoIncrement] [DBNotNull] [DBUnique] - public int id { get; } + public int id { get; private set; } public int points { get; private set; } public string userId { get; private set; } public string guildId { get; private set; } + public Points() {} + public Points(int id, string userId, string guildId, int points) { this.id = id; @@ -28,5 +31,18 @@ namespace ChaosBot.Database.Entity this.userId = userId; this.guildId = guildId; } + + public static QueryBuilder Query() + { + return BaseEntity.Query(); + } + + public override void SetFromRow(DataRow row) + { + id = (int)row["id"]; + userId = (string)row["userId"]; + guildId = (string)row["guildId"]; + points = (int)row["points"]; + } } } \ No newline at end of file diff --git a/ChaosBot/Database/Entity/Raffle.cs b/ChaosBot/Database/Entity/Raffle.cs index d230177..4be0ade 100644 --- a/ChaosBot/Database/Entity/Raffle.cs +++ b/ChaosBot/Database/Entity/Raffle.cs @@ -1,18 +1,21 @@ +using System.Data; using ChaosBot.Attribute; namespace ChaosBot.Database.Entity { [DBEntity("RaffleTable")] - public class Raffle + public class Raffle : BaseEntity { [DBPrimaryKey] [DBAutoIncrement] [DBNotNull] [DBUnique] - public int id { get; } + public int id { get; private set; } public string userId { get; private set; } public string guildId { get; private set; } + public Raffle() {} + public Raffle(int id, string userId, string guildId) { this.id = id; @@ -25,5 +28,17 @@ namespace ChaosBot.Database.Entity this.userId = userId; this.guildId = guildId; } + + public static QueryBuilder Query() + { + return BaseEntity.Query(); + } + + public override void SetFromRow(DataRow row) + { + id = (int)row["id"]; + userId = (string)row["userid"]; + guildId = (string) row["guildid"]; + } } } \ No newline at end of file diff --git a/ChaosBot/Database/Entity/ServerConfigurationFlag.cs b/ChaosBot/Database/Entity/ServerConfigurationFlag.cs index f8d1ab7..01f79e0 100644 --- a/ChaosBot/Database/Entity/ServerConfigurationFlag.cs +++ b/ChaosBot/Database/Entity/ServerConfigurationFlag.cs @@ -1,4 +1,5 @@ using System; +using System.Data; using System.IO; using System.Text; using System.Text.Json; @@ -8,13 +9,15 @@ using ChaosBot.Attribute; namespace ChaosBot.Database.Entity { [DBEntity("ServerConfigurationFlags")] - public class ServerConfigurationFlag + public class ServerConfigurationFlag : BaseEntity { - public string key { get; } + public string key { get; private set; } - public string serializedValue { get; } + public string serializedValue { get; set; } - public long guildId { get; } + public long guildId { get; private set; } + + public ServerConfigurationFlag() {} public ServerConfigurationFlag(string key, T value, ulong guildId) { @@ -22,6 +25,29 @@ namespace ChaosBot.Database.Entity this.key = key; this.guildId = Convert.ToInt64(guildId); } + public ServerConfigurationFlag(string key, T value, long guildId) + { + this.serializedValue = Serialize(value); + this.key = key; + this.guildId = guildId; + } + public ServerConfigurationFlag(string key, long guildId) + { + this.key = key; + this.guildId = guildId; + } + + public static QueryBuilder> Query() + { + return BaseEntity.Query>(); + } + + public override void SetFromRow(DataRow row) + { + key = (string)row["key"]; + serializedValue = (string)row["serializedValue"]; + guildId = (long)row["guildId"]; + } public T GetValue() { diff --git a/ChaosBot/Database/Entity/TestEntity.cs b/ChaosBot/Database/Entity/TestEntity.cs new file mode 100644 index 0000000..195d59e --- /dev/null +++ b/ChaosBot/Database/Entity/TestEntity.cs @@ -0,0 +1,29 @@ +using System; +using System.Data; +using ChaosBot.Attribute; + +namespace ChaosBot.Database.Entity +{ + [DBEntity("TestTable")] + public class TestEntity : BaseEntity + { + public long id { get; private set; } + + public TestEntity() {} + + public TestEntity(int id) + { + this.id = id; + } + + public static QueryBuilder Query() + { + return BaseEntity.Query(); + } + + public override void SetFromRow(DataRow row) + { + id = (long)row["id"]; + } + } +} \ No newline at end of file diff --git a/ChaosBot/Database/FilterValue.cs b/ChaosBot/Database/FilterValue.cs new file mode 100644 index 0000000..23968af --- /dev/null +++ b/ChaosBot/Database/FilterValue.cs @@ -0,0 +1,16 @@ +using NLog.Filters; + +namespace ChaosBot.Database +{ + public struct FilterValue + { + public object Value; + public string Comparison; + + public FilterValue(object value, string comparison = null) + { + this.Value = value; + this.Comparison = comparison; + } + } +} \ No newline at end of file diff --git a/ChaosBot/Database/QueryBuilder.cs b/ChaosBot/Database/QueryBuilder.cs new file mode 100644 index 0000000..e970161 --- /dev/null +++ b/ChaosBot/Database/QueryBuilder.cs @@ -0,0 +1,278 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using System.Text; +using ChaosBot.Attribute; +using ChaosBot.Database.Entity; + +namespace ChaosBot.Database +{ + public class QueryBuilder where T : BaseEntity, new() + { + private string _table; + private bool _distinct; + private Dictionary _whereConditions; + private Dictionary _setList; + private List _orderKeys; + private List _groupByList; + private int _limit; + private int _offset; + public QueryBuilder(string table) + { + _table = table; + _distinct = false; + _whereConditions = new Dictionary(); + _setList = new Dictionary(); + _orderKeys = new List(); + _groupByList = new List(); + _limit = -1; + _offset = -1; + } + + /* + * Fetch all records from a database + */ + public List All() + { + QueryBuilderRaw query = new QueryBuilderRaw(); + DataTable dt = query + .Select() + .Append("*") + .FromTable(_table) + .Run(); + + List returnList = new List(); + foreach (DataRow row in dt.Rows) + { + T newObject = new T(); + newObject.SetFromRow(row); + returnList.Add(newObject); + } + + return returnList; + } + + /* + * Set a where condition + */ + public QueryBuilder Where(string key, object value, string comparison = null) + { + _whereConditions.Add(key, new FilterValue(value, comparison)); + return this; + } + + /* + * Set distinct + */ + public QueryBuilder Distinct() + { + _distinct = true; + return this; + } + + /* + * Set SET field + */ + public QueryBuilder Set(string key, object value) + { + _setList.Add(key, value); + return this; + } + + /* + * Set an order key + */ + public QueryBuilder OrderBy(string key) + { + _orderKeys.Add(key); + return this; + } + + /* + * Set a groupBy key + */ + public QueryBuilder GroupBy(string key) + { + _groupByList.Add(key); + return this; + } + + /* + * Limit amount of responses + */ + public QueryBuilder Limit(int amount) + { + _limit = amount; + return this; + } + + public QueryBuilder Offset(int amount) + { + _offset = amount; + return this; + } + + public QueryBuilder Limit(int limit, int offset) + { + Limit(limit); + return Offset(offset); + } + + /* + * Basic mathematical operations + */ + public int Count() + { + QueryBuilderRaw query = new QueryBuilderRaw(); + long amount = (long)query + .Select() + .Append("COUNT(*) as count") + .FromTable(_table) + .Run().Rows[0]["count"]; + return Convert.ToInt32(amount); + } + + /* + * Basic logical operations + */ + public bool Exists() + { + QueryBuilderRaw query = new QueryBuilderRaw(); + return (bool)query + .Select() + .Append("COUNT(*)>0 as present") + .FromTable(_table) + .Run().Rows[0]["present"]; + } + + public bool DoesNotExist() + { + QueryBuilderRaw query = new QueryBuilderRaw(); + return (bool)query + .Select() + .Append("COUNT(*)=0 as notPresent") + .FromTable(_table) + .Run().Rows[0]["notPresent"]; + } + + /* + * Actions + */ + public List Get() + { + List returnList = new List(); + + QueryBuilderRaw query = new QueryBuilderRaw(); + query + .Select(); + + if (_distinct) + query.Distinct(); + + query + .Append("*") + .FromTable(_table); + + if (_whereConditions.Keys.Count > 0) + query.Where(_whereConditions); + + if (_groupByList.Count > 0) + query.GroupBy(_groupByList); + + if (_orderKeys.Count > 0) + query.OrderBy(_orderKeys); + + if (_limit >= 0) + { + if (_offset >= 0) + { + query.Limit(_limit, _offset); + } + else + { + query.Limit(_limit); + } + } + + DataTable dt = query.Run(); + foreach (DataRow row in dt.Rows) + { + T newObject = new T(); + newObject.SetFromRow(row); + returnList.Add(newObject); + } + + return returnList; + } + + public T First() + { + Limit(1); + List list = Get(); + + if (list.Count > 0) + return list[0]; + return null; + } + + public void Insert(T obj) + { + Dictionary objectKeysAndValues = GetObjectKeysAndValues(obj); + QueryBuilderRaw query = new QueryBuilderRaw(); + query + .Insert() + .IntoTable(_table) + .Columns(new List(objectKeysAndValues.Keys)) + .Values(objectKeysAndValues); + + query.Run(); + } + + public void Update() + { + QueryBuilderRaw query = new QueryBuilderRaw(); + query + .Update() + .Table(_table) + .Set(_setList); + + if (_whereConditions.Keys.Count > 0) + query.Where(_whereConditions); + + query.Run(); + } + + public void Delete() + { + QueryBuilderRaw query = new QueryBuilderRaw(); + query + .Delete() + .FromTable(_table); + + if (_whereConditions.Keys.Count > 0) + query.Where(_whereConditions); + + query.Run(); + } + + /* + * Helpers + */ + private Dictionary GetObjectKeysAndValues(T obj) + { + var returnValue = new Dictionary(); + + foreach (PropertyInfo prop in typeof(T).GetProperties()) + { + string columnName = prop.Name; + object value = prop.GetValue(obj); + + if (value != null) + returnValue.Add(columnName, value); + } + + return returnValue; + } + } +} \ No newline at end of file diff --git a/ChaosBot/Database/QueryBuilderRaw.cs b/ChaosBot/Database/QueryBuilderRaw.cs new file mode 100644 index 0000000..78e915d --- /dev/null +++ b/ChaosBot/Database/QueryBuilderRaw.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; + +namespace ChaosBot.Database +{ + public class QueryBuilderRaw + { + private StringBuilder _query; + private Dictionary _parameters; + private int keyIndex = 0; + + public QueryBuilderRaw() + { + _query = new StringBuilder(); + _parameters = new Dictionary(); + } + + public QueryBuilderRaw Append(string text) + { + _query.Append(text); + if (!text.EndsWith(" ")) + _query.Append(" "); + return this; + } + + public DataTable Run() + { + return Controller.RawQuery(_query.ToString(), _parameters); + } + + public QueryBuilderRaw Select() + { + return Append("SELECT"); + } + + public QueryBuilderRaw Insert(string alternativeAction = null) + { + Append("INSERT"); + if (alternativeAction != null) + Append(alternativeAction); + return this; + } + + public QueryBuilderRaw Update(string alternativeAction = null) + { + Append("UPDATE"); + if (alternativeAction != null) + Append(alternativeAction); + return this; + } + + public QueryBuilderRaw Delete() + { + return Append("DELETE"); + } + + public QueryBuilderRaw Distinct() + { + return Append("DISTINCT"); + } + + public QueryBuilderRaw Table(string table) + { + return Append(table); + } + + public QueryBuilderRaw FromTable(string table) + { + Append("FROM"); + return Table(table); + } + + public QueryBuilderRaw IntoTable(string table) + { + Append("INTO"); + return Table(table); + } + + public QueryBuilderRaw Columns(List columnList) + { + Append("("); + Append(String.Join(", ", columnList)); + Append(")"); + return this; + } + + public QueryBuilderRaw Values(Dictionary keyValueList) + { + Append("VALUES ("); + List parameterKeys = new List(); + foreach (KeyValuePair pair in keyValueList) + { + string parameterName = AddParameterAndReturnKey(pair.Key, pair.Value); + parameterKeys.Add(parameterName); + } + Append(string.Join(", ", parameterKeys)); + Append(")"); + return this; + } + + public QueryBuilderRaw Set(Dictionary keyValueList) + { + Append("SET"); + List parameterKeys = new List(); + foreach (KeyValuePair pair in keyValueList) + { + string parameterName = AddParameterAndReturnKey(pair.Key, pair.Value); + parameterKeys.Add($"{pair.Key} = {parameterName}"); + } + Append(string.Join(", ", parameterKeys)); + return this; + } + + public QueryBuilderRaw Where(Dictionary whereCondition) + { + Append("WHERE"); + foreach (string key in whereCondition.Keys) + { + FilterValue value = whereCondition.GetValueOrDefault(key); + string parameterName = AddParameterAndReturnKey(key, value.Value); + Append($"{key} {value.Comparison ?? "="} {parameterName}"); + } + + return this; + } + + public QueryBuilderRaw GroupBy(List groupByList) + { + Append("GROUP BY"); + return Append(string.Join(", ", groupByList)); + } + + public QueryBuilderRaw OrderBy(List orderKeys) + { + Append("ORDER BY"); + return Append(string.Join(", ", orderKeys)); + } + + public QueryBuilderRaw Limit(int limit) + { + return Append($"LIMIT {limit}"); + } + + public QueryBuilderRaw Limit(int limit, int offset) + { + return Append($"LIMIT {limit} OFFSET {offset}"); + } + + private void AddParameter(string parameterName, object value) + { + _parameters.Add(parameterName, value); + } + + private string AddParameterAndReturnKey(string key, object value) + { + string parameterKey = GetUniqueParameterName(key); + AddParameter(parameterKey, value); + return parameterKey; + } + + private string GetStaticParameterName(string key) + { + return $"@databasevalue{key}"; + } + + private string GetUniqueParameterName(string key) + { + return $"{GetStaticParameterName(key)}_{keyIndex++}"; + } + } +} \ No newline at end of file diff --git a/ChaosBot/Database/Repository/ConfigurationRepository.cs b/ChaosBot/Database/Repository/ConfigurationRepository.cs index 70b5c6b..3f0ce88 100644 --- a/ChaosBot/Database/Repository/ConfigurationRepository.cs +++ b/ChaosBot/Database/Repository/ConfigurationRepository.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Data; using ChaosBot.Database.Entity; using Microsoft.Extensions.Configuration; -using NLog; namespace ChaosBot.Database.Repository { @@ -43,13 +42,13 @@ namespace ChaosBot.Database.Repository public static string GetValueRaw(string configurationFlag, long guildId) { - Dictionary filterColumns = new Dictionary(); - filterColumns.Add("key", configurationFlag); - filterColumns.Add("guildId", guildId); - DataTable valueTable = Controller.SelectQuery(ServersTable, filterColumns: filterColumns); - if (valueTable.Rows.Count == 1) + Dictionary filterColumns = new Dictionary(); + filterColumns.Add("key", new FilterValue(configurationFlag)); + filterColumns.Add("guildId", new FilterValue(guildId)); + ServerConfigurationFlag serverConfigurationFlag = ServerConfigurationFlag.Query().Where("key", configurationFlag).Where("guildId", guildId).First(); + if (serverConfigurationFlag != null) { - return valueTable.Rows[0]["serializedValue"].ToString(); + return serverConfigurationFlag.serializedValue; } return null; @@ -81,23 +80,22 @@ namespace ChaosBot.Database.Repository { try { - Dictionary filterColumns = new Dictionary(); - filterColumns.Add("key", configurationFlag); - filterColumns.Add("guildId", guildId); - - Dictionary newValue = new Dictionary(); - newValue.Add("key", configurationFlag); - newValue.Add("guildId", guildId); - newValue.Add("serializedValue", serializedValue); - - DataTable valueTable = Controller.SelectQuery(ServersTable, "COUNT(*)", filterColumns); - if ((long) valueTable.Rows[0]["COUNT(*)"] == 1) + int matchCount = ServerConfigurationFlag.Query().Where("key", configurationFlag).Where("guildId", guildId).Count(); + if (matchCount > 0) { - Controller.UpdateQuery(ServersTable, newValue, filterColumns); + ServerConfigurationFlag.Query() + .Where("key", configurationFlag) + .Where("guildId", guildId) + .Set("key", configurationFlag) + .Set("guildId", guildId) + .Set("serializedValue", serializedValue) + .Update(); return; } - Controller.InsertQuery(ServersTable, newValue); + ServerConfigurationFlag newValue = new ServerConfigurationFlag(configurationFlag, guildId); + newValue.serializedValue = serializedValue; + ServerConfigurationFlag.Query().Insert(newValue); } catch (Exception ex) { diff --git a/ChaosBot/Database/Repository/PointsRepository.cs b/ChaosBot/Database/Repository/PointsRepository.cs index d6145bf..3d7a068 100644 --- a/ChaosBot/Database/Repository/PointsRepository.cs +++ b/ChaosBot/Database/Repository/PointsRepository.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; using System.Data; -using System.Drawing; -using System.Linq; using ChaosBot.Database.Entity; -using Microsoft.Data.Sqlite; namespace ChaosBot.Database.Repository { @@ -14,136 +11,66 @@ namespace ChaosBot.Database.Repository public static Points[] All() { - DataTable dataTable = Controller.SelectQuery(Table); + List pointsList = Points.Query().All(); - List pointslist = new List(); - foreach (DataRow row in dataTable.Rows) - { - int id = Convert.ToInt32((long)row["id"]); - int points = Convert.ToInt32(row["points"]); - string userId = row["userId"].ToString(); - string guildId = row["guildId"].ToString(); - - pointslist.Add(new Points(id, userId, guildId, points)); - } - - return pointslist.ToArray(); + return pointsList.ToArray(); } public static Points[] All(string guildId) { - Dictionary filterDict = new Dictionary(); - filterDict.Add("guildId", guildId); + List pointsList = Points.Query().Where("guildId", guildId).All(); - DataTable dataTable = Controller.SelectQuery(Table, filterColumns: filterDict); - - List pointslist = new List(); - foreach (DataRow row in dataTable.Rows) - { - int idFetch = Convert.ToInt32((long)row["id"]); - int pointsFetch = Convert.ToInt32(row["points"]); - string userIdFetch = row["userId"].ToString(); - string guildIdFetch = row["guildId"].ToString(); - - pointslist.Add(new Points(idFetch, userIdFetch, guildIdFetch, pointsFetch)); - } - - return pointslist.ToArray(); + return pointsList.ToArray(); } public static int Total(string userId, string guildId) { - Dictionary selectfilterDict = new Dictionary(); - selectfilterDict.Add("userId", userId); - selectfilterDict.Add("guildId", guildId); - - DataTable dt = Controller.SelectQuery(Table, "points", selectfilterDict); - - if (Convert.ToInt32(dt.Rows.Count) != 0) - return Convert.ToInt32(dt.Rows[0]["points"]); - else - { - Dictionary dict = new Dictionary(); - dict.Add("userId", userId); - dict.Add("guildId", guildId); - dict.Add("points", 0); - - Controller.InsertQuery(Table, dict); - } + Points userPoints = Points.Query().Where("userId", userId).Where("guildId", guildId).First(); + if (userPoints != null) + return userPoints.points; + + Points emptyUserPoints = new Points(userId, guildId, 0); + Points.Query().Insert(emptyUserPoints); return 0; } public static int Count(string userId, string guildId) { - Dictionary selectfilterDict = new Dictionary(); - selectfilterDict.Add("userId", userId); - selectfilterDict.Add("guildId", guildId); - - DataTable dt = Controller.SelectQuery(Table, "COUNT(*)", selectfilterDict); - - return Convert.ToInt32(dt.Rows[0]["COUNT(*)"]); + return Points.Query().Where("userId", userId).Where("guildId", guildId).Count(); } public static int Add(string userId, int points, string guildId) { - Dictionary selectfilterDict = new Dictionary(); - selectfilterDict.Add("userId", userId); - selectfilterDict.Add("guildId", guildId); - DataTable dt = Controller.SelectQuery(Table, "points", selectfilterDict); - if (Convert.ToInt32(dt.Rows.Count) != 0) + Points userPoints = Points.Query().Where("userId", userId).Where("guildId", guildId).First(); + if (userPoints != null) { - Dictionary filterDict = new Dictionary(); - filterDict.Add("userId", userId); - filterDict.Add("guildId", guildId); - - Dictionary updateDict = new Dictionary(); - updateDict.Add("points", Convert.ToInt32(dt.Rows[0]["points"]) + points); - Controller.UpdateQuery(Table, updateDict, filterDict); - return Convert.ToInt32(dt.Rows[0]["points"]) + points; + Points.Query().Where("userId", userId).Where("guildId", guildId).Set("points", userPoints.points + points).Update(); + return userPoints.points + points; } - else - { - Dictionary dict = new Dictionary(); - dict.Add("userId", userId); - dict.Add("guildId", guildId); - dict.Add("points", points); + + Points newUserPoints = new Points(userId, guildId, points); - Controller.InsertQuery(Table, dict); - return points; - } + Points.Query().Insert(newUserPoints); + return points; } public static int Remove(string userId, int points, string guildId) { - Dictionary selectfilterDict = new Dictionary(); - selectfilterDict.Add("userId", userId); - selectfilterDict.Add("guildId", guildId); - DataTable dt = Controller.SelectQuery(Table, "points", selectfilterDict); - - Dictionary filterDict = new Dictionary(); - filterDict.Add("userId", userId); - filterDict.Add("guildId", guildId); - - Dictionary updateDict = new Dictionary(); - updateDict.Add("points", Convert.ToInt32(dt.Rows[0]["points"]) - points); - Controller.UpdateQuery(Table, updateDict, filterDict); - return Convert.ToInt32(dt.Rows[0]["points"]) - points; + Points userPoints = Points.Query().Where("userId", userId).Where("guildId", guildId).First(); + Points.Query().Where("userId", userId).Where("guildId", guildId).Set("points", userPoints.points - points).Update(); + return userPoints.points - points; } public static void Delete(int userId) { - Dictionary filterDict = new Dictionary(); - filterDict.Add("userId", userId); - - Controller.DeleteQuery(Table, filterDict); + Points.Query().Where("userId", userId).Delete(); } - } } diff --git a/ChaosBot/Database/Repository/RaffleRepository.cs b/ChaosBot/Database/Repository/RaffleRepository.cs index 5cc87f1..bae7c01 100644 --- a/ChaosBot/Database/Repository/RaffleRepository.cs +++ b/ChaosBot/Database/Repository/RaffleRepository.cs @@ -17,17 +17,7 @@ namespace ChaosBot.Database.Repository /// List of raffles public static Raffle[] All() { - DataTable dataTable = Controller.SelectQuery(Table); - - List raffles = new List(); - foreach (DataRow row in dataTable.Rows) - { - int id = Convert.ToInt32((long) row["id"]); - string userId = row["userId"].ToString(); - string guildId = row["guildId"].ToString(); - - raffles.Add(new Raffle(id, userId, guildId)); - } + var raffles = Raffle.Query().All(); return raffles.ToArray(); } @@ -38,21 +28,8 @@ namespace ChaosBot.Database.Repository /// /// List of raffles public static Raffle[] All(string guildId) - { - Dictionary filterDict = new Dictionary(); - filterDict.Add("guildId", guildId); - - DataTable dataTable = Controller.SelectQuery(Table, filterColumns: filterDict); - - List raffles = new List(); - foreach (DataRow row in dataTable.Rows) - { - int idFetch = Convert.ToInt32((long) row["id"]); - string userIdFetch = row["userId"].ToString(); - string guildIdFetch = row["guildId"].ToString(); - - raffles.Add(new Raffle(idFetch, userIdFetch, guildIdFetch)); - } + { + var raffles = Raffle.Query().Where("guildId", guildId).All(); return raffles.ToArray(); } @@ -62,10 +39,8 @@ namespace ChaosBot.Database.Repository /// /// Amount of raffles public static int Count() - { - DataTable dataTable = Controller.SelectQuery(Table, "COUNT(*)"); - - return Convert.ToInt32(dataTable.Rows[0]["COUNT(*)"]); + { + return Raffle.Query().Count(); } /// @@ -74,13 +49,8 @@ namespace ChaosBot.Database.Repository /// /// Amount of raffles public static int Count(string guildId) - { - Dictionary filterDict = new Dictionary(); - filterDict.Add("guildId", guildId); - - DataTable dataTable = Controller.SelectQuery(Table, "COUNT(*)", filterDict); - - return Convert.ToInt32(dataTable.Rows[0]["COUNT(*)"]); + { + return Raffle.Query().Where("guildId", guildId).Count(); } /// @@ -90,14 +60,8 @@ namespace ChaosBot.Database.Repository /// /// Amount of raffles public static int Count(string userId, string guildId) - { - Dictionary filterDict = new Dictionary(); - filterDict.Add("userId", userId); - filterDict.Add("guildId", guildId); - - DataTable dataTable = Controller.SelectQuery(Table, "COUNT(*)", filterDict); - - return Convert.ToInt32(dataTable.Rows[0]["COUNT(*)"]); + { + return Raffle.Query().Where("userId", userId).Where("guildId", guildId).Count(); } /// @@ -106,22 +70,9 @@ namespace ChaosBot.Database.Repository /// /// List of raffles public static Raffle[] SelectUser(string userId) - { - Dictionary filterDict = new Dictionary(); - filterDict.Add("userId", userId); + { + List raffles = Raffle.Query().Where("userId", userId).Get(); - DataTable dataTable = Controller.SelectQuery(Table, filterColumns: filterDict); - - List raffles = new List(); - foreach (DataRow row in dataTable.Rows) - { - int id = Convert.ToInt32((long) row["id"]); - string userIdFetch = row["userId"].ToString(); - string guildIdFetch = row["guildId"].ToString(); - - raffles.Add(new Raffle(id, userIdFetch, guildIdFetch)); - } - return raffles.ToArray(); } @@ -132,22 +83,8 @@ namespace ChaosBot.Database.Repository /// /// List of raffles public static Raffle[] SelectUser(string userId, string guildId) - { - Dictionary filterDict = new Dictionary(); - filterDict.Add("userId", userId); - filterDict.Add("guildId", guildId); - - DataTable dataTable = Controller.SelectQuery(Table, filterColumns: filterDict); - - List raffles = new List(); - foreach (DataRow row in dataTable.Rows) - { - int id = Convert.ToInt32((long) row["id"]); - string userIdFetch = row["userId"].ToString(); - string guildIdFetch = row["guildId"].ToString(); - - raffles.Add(new Raffle(id, userIdFetch, guildIdFetch)); - } + { + List raffles = Raffle.Query().Where("userId", userId).Where("guildId", guildId).Get(); return raffles.ToArray(); } @@ -158,12 +95,7 @@ namespace ChaosBot.Database.Repository /// public static void Insert(Raffle raffle) { - Dictionary dict = new Dictionary(); - - dict.Add("userId", raffle.userId); - dict.Add("guildId", raffle.guildId); - - Controller.InsertQuery(Table, dict); + Raffle.Query().Insert(raffle); } /// @@ -174,12 +106,7 @@ namespace ChaosBot.Database.Repository { foreach (var raf in raffles) { - Dictionary dict = new Dictionary(); - - dict.Add("userId", raf.userId); - dict.Add("guildId", raf.guildId); - - Controller.InsertQuery(Table, dict); + Raffle.Query().Insert(raf); } } @@ -190,17 +117,7 @@ namespace ChaosBot.Database.Repository /// Random raffle public static Raffle PickRandom(string guildId) { - Dictionary filterDict = new Dictionary(); - filterDict.Add("guildId", guildId); - - DataTable dataTable = Controller.SelectQuery(Table, "*", filterDict, "RANDOM()"); - - if (dataTable.Rows.Count == 0) return null; - DataRow row = dataTable.Rows[0]; - int idFetch = Convert.ToInt32((long)row["id"]); - string userIdFetch = row["userId"].ToString(); - string guildIdFetch = row["guildId"].ToString(); - return new Raffle(idFetch, userIdFetch, guildIdFetch); + return Raffle.Query().Where("guildId", guildId).OrderBy("RANDOM()").First(); } /// @@ -209,11 +126,7 @@ namespace ChaosBot.Database.Repository /// public static void ClearRaffle(string guildId) { - Dictionary filterDict = new Dictionary(); - - filterDict.Add("guildId", guildId); - - Controller.DeleteQuery(Table, filterDict); + Raffle.Query().Where("guildId", guildId).Delete(); } /// @@ -221,11 +134,8 @@ namespace ChaosBot.Database.Repository /// /// public static void Delete(int id) - { - Dictionary filterDict = new Dictionary(); - filterDict.Add("id", id); - - Controller.DeleteQuery(Table, filterDict); + { + Raffle.Query().Where("id", id).Delete(); } } } \ No newline at end of file diff --git a/ChaosBot/Discord/Modules/PointsCommands.cs b/ChaosBot/Discord/Modules/PointsCommands.cs index 6c5beb7..b67c733 100644 --- a/ChaosBot/Discord/Modules/PointsCommands.cs +++ b/ChaosBot/Discord/Modules/PointsCommands.cs @@ -97,20 +97,15 @@ namespace ChaosBot.Discord.Modules public async Task DeletePoints(string userMention) { ulong userId = Convert.ToUInt64(userMention.Substring(3, userMention.Length - 4)); - Dictionary filterColumns = new Dictionary - { - { "userId", userId }, - { "guildId", Context.Guild.Id } - }; int matches = PointsRepository.Count(userId.ToString(), Context.Guild.Id.ToString()); if (matches > 0) { - Controller.DeleteQuery("PointsTable", filterColumns); + Points.Query().Where("userId", userId).Where("guildId", Context.Guild.Id).Delete(); - string message = $"{Context.User.Mention} has removed <@{userId}> from the database."; - await ReplyAsync(message, false); - _logger.Info($"PointsCommands.DeletePoints: {message}"); + string message = $"{Context.User.Mention} has removed <@{userId}> from the database."; + await ReplyAsync(message, false); + _logger.Info($"PointsCommands.DeletePoints: {message}"); } else { diff --git a/ChaosBot/Program.cs b/ChaosBot/Program.cs index 3ec4c58..9338aec 100644 --- a/ChaosBot/Program.cs +++ b/ChaosBot/Program.cs @@ -36,7 +36,6 @@ namespace ChaosBot */ _logger = Logging.GenLog(); - /* * Attempt to load our custom assemblies */ @@ -46,7 +45,7 @@ namespace ChaosBot * Initialize the Discord Client and Login */ _logger.Info($"Starting Up {ConfigurationRepository.GetValue("Bot:Name")} v{ConfigurationRepository.GetValue("Bot:Version")}"); - + var discordBot = DiscordConnect.StartUp(); WebServer.WebServer.Start(new string[]{}); await discordBot; From 17170962b13f779e5b78156809af4e1de6c1bb35 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 20:51:11 +0200 Subject: [PATCH 4/8] Remove test entity --- ChaosBot/Database/Entity/TestEntity.cs | 29 -------------------------- 1 file changed, 29 deletions(-) delete mode 100644 ChaosBot/Database/Entity/TestEntity.cs diff --git a/ChaosBot/Database/Entity/TestEntity.cs b/ChaosBot/Database/Entity/TestEntity.cs deleted file mode 100644 index 195d59e..0000000 --- a/ChaosBot/Database/Entity/TestEntity.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Data; -using ChaosBot.Attribute; - -namespace ChaosBot.Database.Entity -{ - [DBEntity("TestTable")] - public class TestEntity : BaseEntity - { - public long id { get; private set; } - - public TestEntity() {} - - public TestEntity(int id) - { - this.id = id; - } - - public static QueryBuilder Query() - { - return BaseEntity.Query(); - } - - public override void SetFromRow(DataRow row) - { - id = (long)row["id"]; - } - } -} \ No newline at end of file From 81c32f1137d8104549e5a3dfa70a5c7eaeb43f58 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 20:51:33 +0200 Subject: [PATCH 5/8] Remove all string identifiers, changed to long --- ChaosBot/Database/Entity/Points.cs | 12 ++++++------ ChaosBot/Database/Entity/Raffle.cs | 12 ++++++------ ChaosBot/Database/Repository/PointsRepository.cs | 10 +++++----- ChaosBot/Database/Repository/RaffleRepository.cs | 14 +++++++------- ChaosBot/Discord/Modules/PointsCommands.cs | 10 +++++----- ChaosBot/Discord/Modules/RaffleSystem.cs | 16 ++++++++-------- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/ChaosBot/Database/Entity/Points.cs b/ChaosBot/Database/Entity/Points.cs index c074d88..b6803df 100644 --- a/ChaosBot/Database/Entity/Points.cs +++ b/ChaosBot/Database/Entity/Points.cs @@ -12,12 +12,12 @@ namespace ChaosBot.Database.Entity [DBUnique] public int id { get; private set; } public int points { get; private set; } - public string userId { get; private set; } - public string guildId { get; private set; } + public long userId { get; private set; } + public long guildId { get; private set; } public Points() {} - public Points(int id, string userId, string guildId, int points) + public Points(int id, long userId, long guildId, int points) { this.id = id; this.userId = userId; @@ -25,7 +25,7 @@ namespace ChaosBot.Database.Entity this.points = points; } - public Points(string userId, string guildId, int points) + public Points(long userId, long guildId, int points) { this.points = points; this.userId = userId; @@ -40,8 +40,8 @@ namespace ChaosBot.Database.Entity public override void SetFromRow(DataRow row) { id = (int)row["id"]; - userId = (string)row["userId"]; - guildId = (string)row["guildId"]; + userId = (long)row["userId"]; + guildId = (long)row["guildId"]; points = (int)row["points"]; } } diff --git a/ChaosBot/Database/Entity/Raffle.cs b/ChaosBot/Database/Entity/Raffle.cs index 4be0ade..d3da395 100644 --- a/ChaosBot/Database/Entity/Raffle.cs +++ b/ChaosBot/Database/Entity/Raffle.cs @@ -11,19 +11,19 @@ namespace ChaosBot.Database.Entity [DBNotNull] [DBUnique] public int id { get; private set; } - public string userId { get; private set; } - public string guildId { get; private set; } + public long userId { get; private set; } + public long guildId { get; private set; } public Raffle() {} - public Raffle(int id, string userId, string guildId) + public Raffle(int id, long userId, long guildId) { this.id = id; this.userId = userId; this.guildId = guildId; } - public Raffle(string userId, string guildId) + public Raffle(long userId, long guildId) { this.userId = userId; this.guildId = guildId; @@ -37,8 +37,8 @@ namespace ChaosBot.Database.Entity public override void SetFromRow(DataRow row) { id = (int)row["id"]; - userId = (string)row["userid"]; - guildId = (string) row["guildid"]; + userId = (long)row["userid"]; + guildId = (long) row["guildid"]; } } } \ No newline at end of file diff --git a/ChaosBot/Database/Repository/PointsRepository.cs b/ChaosBot/Database/Repository/PointsRepository.cs index 3d7a068..5bae385 100644 --- a/ChaosBot/Database/Repository/PointsRepository.cs +++ b/ChaosBot/Database/Repository/PointsRepository.cs @@ -16,7 +16,7 @@ namespace ChaosBot.Database.Repository return pointsList.ToArray(); } - public static Points[] All(string guildId) + public static Points[] All(long guildId) { List pointsList = Points.Query().Where("guildId", guildId).All(); @@ -24,7 +24,7 @@ namespace ChaosBot.Database.Repository } - public static int Total(string userId, string guildId) + public static int Total(long userId, long guildId) { Points userPoints = Points.Query().Where("userId", userId).Where("guildId", guildId).First(); @@ -37,13 +37,13 @@ namespace ChaosBot.Database.Repository } - public static int Count(string userId, string guildId) + public static int Count(long userId, long guildId) { return Points.Query().Where("userId", userId).Where("guildId", guildId).Count(); } - public static int Add(string userId, int points, string guildId) + public static int Add(long userId, int points, long guildId) { Points userPoints = Points.Query().Where("userId", userId).Where("guildId", guildId).First(); if (userPoints != null) @@ -59,7 +59,7 @@ namespace ChaosBot.Database.Repository return points; } - public static int Remove(string userId, int points, string guildId) + public static int Remove(long userId, int points, long guildId) { Points userPoints = Points.Query().Where("userId", userId).Where("guildId", guildId).First(); diff --git a/ChaosBot/Database/Repository/RaffleRepository.cs b/ChaosBot/Database/Repository/RaffleRepository.cs index bae7c01..728f242 100644 --- a/ChaosBot/Database/Repository/RaffleRepository.cs +++ b/ChaosBot/Database/Repository/RaffleRepository.cs @@ -27,7 +27,7 @@ namespace ChaosBot.Database.Repository /// /// /// List of raffles - public static Raffle[] All(string guildId) + public static Raffle[] All(long guildId) { var raffles = Raffle.Query().Where("guildId", guildId).All(); @@ -48,7 +48,7 @@ namespace ChaosBot.Database.Repository /// /// /// Amount of raffles - public static int Count(string guildId) + public static int Count(long guildId) { return Raffle.Query().Where("guildId", guildId).Count(); } @@ -59,7 +59,7 @@ namespace ChaosBot.Database.Repository /// /// /// Amount of raffles - public static int Count(string userId, string guildId) + public static int Count(long userId, long guildId) { return Raffle.Query().Where("userId", userId).Where("guildId", guildId).Count(); } @@ -69,7 +69,7 @@ namespace ChaosBot.Database.Repository /// /// /// List of raffles - public static Raffle[] SelectUser(string userId) + public static Raffle[] SelectUser(long userId) { List raffles = Raffle.Query().Where("userId", userId).Get(); @@ -82,7 +82,7 @@ namespace ChaosBot.Database.Repository /// /// /// List of raffles - public static Raffle[] SelectUser(string userId, string guildId) + public static Raffle[] SelectUser(long userId, long guildId) { List raffles = Raffle.Query().Where("userId", userId).Where("guildId", guildId).Get(); @@ -115,7 +115,7 @@ namespace ChaosBot.Database.Repository /// /// /// Random raffle - public static Raffle PickRandom(string guildId) + public static Raffle PickRandom(long guildId) { return Raffle.Query().Where("guildId", guildId).OrderBy("RANDOM()").First(); } @@ -124,7 +124,7 @@ namespace ChaosBot.Database.Repository /// Clear all Raffles for a given guild /// /// - public static void ClearRaffle(string guildId) + public static void ClearRaffle(long guildId) { Raffle.Query().Where("guildId", guildId).Delete(); } diff --git a/ChaosBot/Discord/Modules/PointsCommands.cs b/ChaosBot/Discord/Modules/PointsCommands.cs index b67c733..d5e7365 100644 --- a/ChaosBot/Discord/Modules/PointsCommands.cs +++ b/ChaosBot/Discord/Modules/PointsCommands.cs @@ -58,7 +58,7 @@ namespace ChaosBot.Discord.Modules [Alias("points info")] public async Task PointsCommandTotal() { - int cur = PointsRepository.Total(Context.User.Id.ToString(), Context.Guild.Id.ToString()); + int cur = PointsRepository.Total(Convert.ToInt64(Context.User.Id), Convert.ToInt64(Context.Guild.Id)); await ReplyAsync($"You have {cur} points.", false); } @@ -72,7 +72,7 @@ namespace ChaosBot.Discord.Modules { ulong userId = Convert.ToUInt64(user.Substring(3, user.Length - 4)); - await ReplyAsync($"{Context.User.Mention} has given <@{userId}> {amount} points for a total of {PointsRepository.Add(userId.ToString(), amount, Context.Guild.Id.ToString())} points.", false); + await ReplyAsync($"{Context.User.Mention} has given <@{userId}> {amount} points for a total of {PointsRepository.Add(Convert.ToInt64(userId), amount, Convert.ToInt64(Context.Guild.Id))} points.", false); } else await ReplyAsync($"NO ACCESS"); @@ -85,9 +85,9 @@ namespace ChaosBot.Discord.Modules public async Task RaffleCommandRemove(string user, int amount = 1) { ulong userId = Convert.ToUInt64(user.Substring(3, user.Length - 4)); - int cur = PointsRepository.Total(Context.User.Id.ToString(), Context.Guild.Id.ToString()); + int cur = PointsRepository.Total(Convert.ToInt64(Context.User.Id), Convert.ToInt64(Context.Guild.Id)); if (cur > amount) - await ReplyAsync($"{Context.User.Mention} has removed {amount} points from <@{userId}> for a total of {PointsRepository.Remove(userId.ToString(), amount, Context.Guild.Id.ToString())} points.", false); + await ReplyAsync($"{Context.User.Mention} has removed {amount} points from <@{userId}> for a total of {PointsRepository.Remove(Convert.ToInt64(userId), amount, Convert.ToInt64(Context.Guild.Id))} points.", false); else await ReplyAsync($"{Context.User.Mention} has tried to remove {amount} points from <@{userId}> they only had {cur} points. None were taken...", false); } @@ -98,7 +98,7 @@ namespace ChaosBot.Discord.Modules { ulong userId = Convert.ToUInt64(userMention.Substring(3, userMention.Length - 4)); - int matches = PointsRepository.Count(userId.ToString(), Context.Guild.Id.ToString()); + int matches = PointsRepository.Count(Convert.ToInt64(userId), Convert.ToInt64(Context.Guild.Id)); if (matches > 0) { Points.Query().Where("userId", userId).Where("guildId", Context.Guild.Id).Delete(); diff --git a/ChaosBot/Discord/Modules/RaffleSystem.cs b/ChaosBot/Discord/Modules/RaffleSystem.cs index e589429..703688f 100644 --- a/ChaosBot/Discord/Modules/RaffleSystem.cs +++ b/ChaosBot/Discord/Modules/RaffleSystem.cs @@ -140,32 +140,32 @@ namespace ChaosBot.Discord.Modules List raffles = new List(); for (int i = 0; i < amount; i++) - raffles.Add(new Raffle(userId.ToString(), Context.Guild.Id.ToString())); + raffles.Add(new Raffle(Convert.ToInt64(userId), Convert.ToInt64(Context.Guild.Id))); RaffleRepository.MassInsert(raffles); } else { - RaffleRepository.Insert(new Raffle(userId.ToString(), Context.Guild.Id.ToString())); + RaffleRepository.Insert(new Raffle(Convert.ToInt64(userId), Convert.ToInt64(Context.Guild.Id))); } sb.AppendLine($"{Context.User.Mention} has added {amount} rafflepoints to <@{userId}>."); sb.AppendLine(); - sb.AppendLine($"<@{userId}> now has {RaffleRepository.Count(userId.ToString(), Context.Guild.Id.ToString())} rafflepoints!"); + sb.AppendLine($"<@{userId}> now has {RaffleRepository.Count(Convert.ToInt64(userId), Convert.ToInt64(Context.Guild.Id))} rafflepoints!"); } private void PickRaffle(StringBuilder sb) { - Raffle winner = RaffleRepository.PickRandom(Context.Guild.Id.ToString()); + Raffle winner = RaffleRepository.PickRandom(Convert.ToInt64(Context.Guild.Id)); RaffleRepository.Delete(winner.id); sb.Append($"<@{winner.userId}> has won the raffle!"); } private void ClearRaffle(StringBuilder sb, bool noOutput = false) { - int removed = RaffleRepository.Count(Context.Guild.Id.ToString()); + int removed = RaffleRepository.Count(Convert.ToInt64(Context.Guild.Id)); - RaffleRepository.ClearRaffle(Context.Guild.Id.ToString()); + RaffleRepository.ClearRaffle(Convert.ToInt64(Context.Guild.Id)); sb.AppendLine($"{Context.User.Mention} has cleared all {removed} rafflepoints"); } @@ -174,8 +174,8 @@ namespace ChaosBot.Discord.Modules { ulong userId = Convert.ToUInt64(user.Substring(3, user.Length-4)); - sb.AppendLine($"<@{userId}>, you have {RaffleRepository.Count(userId.ToString(), Context.Guild.Id.ToString())} rafflepoints."); - sb.AppendLine($"There is a total of {RaffleRepository.Count(Context.Guild.Id.ToString())} rafflepoints."); + sb.AppendLine($"<@{userId}>, you have {RaffleRepository.Count(Convert.ToInt64(userId), Convert.ToInt64(Context.Guild.Id))} rafflepoints."); + sb.AppendLine($"There is a total of {RaffleRepository.Count(Convert.ToInt64(Context.Guild.Id))} rafflepoints."); } } } \ No newline at end of file From 3c682780a43e89b7e76baee15f7eb75d1519b6dd Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 21:56:58 +0200 Subject: [PATCH 6/8] Fix multiple where conditions and nullable fields on models --- ChaosBot/Attribute/AssemblyController.cs | 13 ++++++++++++- ChaosBot/Database/Entity/Points.cs | 3 ++- ChaosBot/Database/Entity/Raffle.cs | 3 ++- ChaosBot/Database/QueryBuilderRaw.cs | 5 +++-- ChaosBot/Discord/Modules/RaffleSystem.cs | 3 ++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ChaosBot/Attribute/AssemblyController.cs b/ChaosBot/Attribute/AssemblyController.cs index 2532b88..59d2364 100644 --- a/ChaosBot/Attribute/AssemblyController.cs +++ b/ChaosBot/Attribute/AssemblyController.cs @@ -36,7 +36,18 @@ namespace ChaosBot.Attribute foreach (PropertyInfo prop in type.GetProperties()) { string columnName = prop.Name; - string columnType = DBEntity.DataTypes.GetValueOrDefault(prop.PropertyType).ToString(); + string columnType = null; + if (prop.PropertyType.IsGenericType && + prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + Type[] typeArguments = prop.PropertyType.GetGenericArguments(); + if (typeArguments.Length == 1) + columnType = DBEntity.DataTypes.GetValueOrDefault(typeArguments[0]).ToString(); + } + else + { + columnType = DBEntity.DataTypes.GetValueOrDefault(prop.PropertyType).ToString(); + } StringBuilder constraintNameBuilder = new StringBuilder($"{table}_{columnName}"); List constraintsList = new List(); diff --git a/ChaosBot/Database/Entity/Points.cs b/ChaosBot/Database/Entity/Points.cs index b6803df..c30de71 100644 --- a/ChaosBot/Database/Entity/Points.cs +++ b/ChaosBot/Database/Entity/Points.cs @@ -1,3 +1,4 @@ +using System; using System.Data; using ChaosBot.Attribute; @@ -10,7 +11,7 @@ namespace ChaosBot.Database.Entity [DBAutoIncrement] [DBNotNull] [DBUnique] - public int id { get; private set; } + public Nullable id { get; private set; } public int points { get; private set; } public long userId { get; private set; } public long guildId { get; private set; } diff --git a/ChaosBot/Database/Entity/Raffle.cs b/ChaosBot/Database/Entity/Raffle.cs index d3da395..399de4f 100644 --- a/ChaosBot/Database/Entity/Raffle.cs +++ b/ChaosBot/Database/Entity/Raffle.cs @@ -1,3 +1,4 @@ +using System; using System.Data; using ChaosBot.Attribute; @@ -10,7 +11,7 @@ namespace ChaosBot.Database.Entity [DBAutoIncrement] [DBNotNull] [DBUnique] - public int id { get; private set; } + public Nullable id { get; private set; } public long userId { get; private set; } public long guildId { get; private set; } diff --git a/ChaosBot/Database/QueryBuilderRaw.cs b/ChaosBot/Database/QueryBuilderRaw.cs index 78e915d..2300a87 100644 --- a/ChaosBot/Database/QueryBuilderRaw.cs +++ b/ChaosBot/Database/QueryBuilderRaw.cs @@ -117,13 +117,14 @@ namespace ChaosBot.Database public QueryBuilderRaw Where(Dictionary whereCondition) { Append("WHERE"); + List whereConditionList = new List(); foreach (string key in whereCondition.Keys) { FilterValue value = whereCondition.GetValueOrDefault(key); string parameterName = AddParameterAndReturnKey(key, value.Value); - Append($"{key} {value.Comparison ?? "="} {parameterName}"); + whereConditionList.Add($"{key} {value.Comparison ?? "="} {parameterName}"); } - + Append(string.Join(" AND ", whereConditionList)); return this; } diff --git a/ChaosBot/Discord/Modules/RaffleSystem.cs b/ChaosBot/Discord/Modules/RaffleSystem.cs index 703688f..6158c29 100644 --- a/ChaosBot/Discord/Modules/RaffleSystem.cs +++ b/ChaosBot/Discord/Modules/RaffleSystem.cs @@ -157,7 +157,8 @@ namespace ChaosBot.Discord.Modules private void PickRaffle(StringBuilder sb) { Raffle winner = RaffleRepository.PickRandom(Convert.ToInt64(Context.Guild.Id)); - RaffleRepository.Delete(winner.id); + if (winner.id != null) + RaffleRepository.Delete((int)winner.id); sb.Append($"<@{winner.userId}> has won the raffle!"); } From 5b552ac310b764e6b4637cd01418afcc144686c7 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 22:00:25 +0200 Subject: [PATCH 7/8] make some methods public for testing purposes --- ChaosBot/Attribute/AssemblyController.cs | 170 ++++++++++++----------- ChaosBot/Program.cs | 43 ++++-- 2 files changed, 124 insertions(+), 89 deletions(-) diff --git a/ChaosBot/Attribute/AssemblyController.cs b/ChaosBot/Attribute/AssemblyController.cs index 59d2364..1c5cdd9 100644 --- a/ChaosBot/Attribute/AssemblyController.cs +++ b/ChaosBot/Attribute/AssemblyController.cs @@ -11,106 +11,114 @@ namespace ChaosBot.Attribute public static class AssemblyController { private static Logger _logger = Program._logger; - public static void Register() + public static void RegisterAll() { Assembly dbEntityAssembly = Assembly.GetAssembly(typeof(DBEntity)); if (dbEntityAssembly != null) { foreach (Type type in dbEntityAssembly.GetTypes()) { - try + RegisterDBEntityType(type); + } + } + } + + public static void RegisterDBEntityType(Type type) + { + try + { + if (type.GetCustomAttributes(typeof(DBEntity), true).Length > 0) + { + // Get a reference to the attribute + DBEntity dbEntity = type.GetCustomAttributes(typeof(DBEntity)).Cast().First(); + + // Generate columns + // name, type, constraintName, constraints, + List> columnList = new List>(); + + // Get the table as an easy variable + string table = dbEntity.Table; + + // Loop through all fields + foreach (PropertyInfo prop in type.GetProperties()) { - if (type.GetCustomAttributes(typeof(DBEntity), true).Length > 0) + string columnName = prop.Name; + string columnType = null; + if (prop.PropertyType.IsGenericType && + prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) { - // Get a reference to the attribute - DBEntity dbEntity = type.GetCustomAttributes(typeof(DBEntity)).Cast().First(); - - // Generate columns - // name, type, constraintName, constraints, - List> columnList = new List>(); - - // Get the table as an easy variable - string table = dbEntity.Table; + Type[] typeArguments = prop.PropertyType.GetGenericArguments(); + if (typeArguments.Length == 1) + columnType = DBEntity.DataTypes.GetValueOrDefault(typeArguments[0]).ToString(); + } + else + { + columnType = DBEntity.DataTypes.GetValueOrDefault(prop.PropertyType).ToString(); + } - // Loop through all fields - foreach (PropertyInfo prop in type.GetProperties()) + StringBuilder constraintNameBuilder = new StringBuilder($"{table}_{columnName}"); + List constraintsList = new List(); + + // Go through every attribute + foreach (object fieldAttribute in prop.GetCustomAttributes(true)) + { + if (fieldAttribute is DBFieldAttribute dBFieldAttribute) { - string columnName = prop.Name; - string columnType = null; - if (prop.PropertyType.IsGenericType && - prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) + string constraintSuffix = + DBEntity.ConstrainNames.GetValueOrDefault(dBFieldAttribute.GetType(), null); + if (constraintSuffix != null) { - Type[] typeArguments = prop.PropertyType.GetGenericArguments(); - if (typeArguments.Length == 1) - columnType = DBEntity.DataTypes.GetValueOrDefault(typeArguments[0]).ToString(); - } - else - { - columnType = DBEntity.DataTypes.GetValueOrDefault(prop.PropertyType).ToString(); - } - StringBuilder constraintNameBuilder = new StringBuilder($"{table}_{columnName}"); - List constraintsList = new List(); - - // Go through every attribute - foreach (object fieldAttribute in prop.GetCustomAttributes(true)) - { - if (fieldAttribute is DBFieldAttribute dBFieldAttribute) - { - string constraintSuffix = - DBEntity.ConstrainNames.GetValueOrDefault(dBFieldAttribute.GetType(), null); - if (constraintSuffix != null) - { - constraintNameBuilder.Append($"_{constraintSuffix}"); - constraintsList.Add($"{dBFieldAttribute.GetSQLiteQuery()}"); - } - } - } - - string constraintName = constraintNameBuilder.ToString(); - if (constraintsList.Count > 0) - { - constraintsList.Insert(0, "CONSTRAINT"); - constraintsList.Insert(1, constraintName); - } - string constraints = String.Join(" ", constraintsList); - columnList.Add(new Tuple(columnName, columnType, constraintName, constraints)); - } - - // Check table exists - bool tableExists = - Controller.RawQuery($"SELECT name FROM sqlite_master WHERE type='table' AND name='{table}'") - .Rows.Count > 0; - - if (!tableExists) - { - string columnDefs = String.Join(", ", columnList.Select(c => $"{c.Item1} {c.Item2} {c.Item4}")); - string query = $"CREATE TABLE {table} ({columnDefs})"; - Controller.RawQuery(query, readOutput: false); - } - else - { - foreach (Tuple column in columnList) - { - try - { - string query = - $"ALTER TABLE {table} ADD COLUMN {column.Item1} {column.Item2} {column.Item4}"; - Controller.RawQuery(query, readOutput: false, throwError: true); - } - catch - { - // ignored - } + constraintNameBuilder.Append($"_{constraintSuffix}"); + constraintsList.Add($"{dBFieldAttribute.GetSQLiteQuery()}"); } } } + + string constraintName = constraintNameBuilder.ToString(); + if (constraintsList.Count > 0) + { + constraintsList.Insert(0, "CONSTRAINT"); + constraintsList.Insert(1, constraintName); + } + + string constraints = String.Join(" ", constraintsList); + columnList.Add( + new Tuple(columnName, columnType, constraintName, constraints)); } - catch (Exception ex) + + // Check table exists + bool tableExists = + Controller.RawQuery($"SELECT name FROM sqlite_master WHERE type='table' AND name='{table}'") + .Rows.Count > 0; + + if (!tableExists) { - _logger.Error($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>."); + string columnDefs = String.Join(", ", columnList.Select(c => $"{c.Item1} {c.Item2} {c.Item4}")); + string query = $"CREATE TABLE {table} ({columnDefs})"; + Controller.RawQuery(query, readOutput: false); + } + else + { + foreach (Tuple column in columnList) + { + try + { + string query = + $"ALTER TABLE {table} ADD COLUMN {column.Item1} {column.Item2} {column.Item4}"; + Controller.RawQuery(query, readOutput: false, throwError: true); + } + catch + { + // ignored + } + } } } } + catch (Exception ex) + { + _logger.Error($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>."); + } } } } \ No newline at end of file diff --git a/ChaosBot/Program.cs b/ChaosBot/Program.cs index 9338aec..3b8015f 100644 --- a/ChaosBot/Program.cs +++ b/ChaosBot/Program.cs @@ -1,12 +1,13 @@ using NLog; using System; +using System.Runtime.CompilerServices; using ChaosBot.Discord; using System.Threading.Tasks; using ChaosBot.Attribute; using ChaosBot.Database.Repository; using Microsoft.Extensions.Configuration; - +[assembly: InternalsVisibleTo("ChaosBot.UnitTests")] namespace ChaosBot { internal class Program @@ -27,27 +28,26 @@ namespace ChaosBot /* * Load configuration from AppSettings.Json and save as Cfg */ - ConfigurationRepository.AppSettingsHandler = new ConfigurationBuilder() - .SetBasePath(System.IO.Directory.GetCurrentDirectory()) - .AddJsonFile(appsettingsPath, optional: false, reloadOnChange: true).Build(); + LoadConfiguration(appsettingsPath); /* * Initialize the _logger for logging purposes */ - _logger = Logging.GenLog(); + LoadLogger(); /* * Attempt to load our custom assemblies */ - AssemblyController.Register(); + RegisterAssemblyController(); /* * Initialize the Discord Client and Login */ _logger.Info($"Starting Up {ConfigurationRepository.GetValue("Bot:Name")} v{ConfigurationRepository.GetValue("Bot:Version")}"); - var discordBot = DiscordConnect.StartUp(); - WebServer.WebServer.Start(new string[]{}); + + var discordBot = LoadDiscord(); + LoadWebServer(); await discordBot; } catch (Exception ex) @@ -55,5 +55,32 @@ namespace ChaosBot _logger.Error(ex, $"Program.MainFunction: Exception [{ex}] thrown, <[{ex.Message}]>."); } } + + public static void LoadConfiguration(string appsettingsPath) + { + ConfigurationRepository.AppSettingsHandler = new ConfigurationBuilder() + .SetBasePath(System.IO.Directory.GetCurrentDirectory()) + .AddJsonFile(appsettingsPath, optional: false, reloadOnChange: true).Build(); + } + + public static void LoadLogger() + { + _logger = Logging.GenLog(); + } + + public static void RegisterAssemblyController() + { + AssemblyController.RegisterAll(); + } + + public static void LoadWebServer() + { + WebServer.WebServer.Start(new string[]{}); + } + + public static Task LoadDiscord() + { + return DiscordConnect.StartUp(); + } } } \ No newline at end of file From a8be00abc9e4a7a1976b8b062292dec839ca6d7a Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Mon, 8 Jun 2020 22:03:17 +0200 Subject: [PATCH 8/8] Write tests for database manipulation --- ChaosBot.UnitTests/DataBaseTests.cs | 84 +++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 ChaosBot.UnitTests/DataBaseTests.cs diff --git a/ChaosBot.UnitTests/DataBaseTests.cs b/ChaosBot.UnitTests/DataBaseTests.cs new file mode 100644 index 0000000..fb1397a --- /dev/null +++ b/ChaosBot.UnitTests/DataBaseTests.cs @@ -0,0 +1,84 @@ +using System; +using System.Data; +using System.Linq; +using System.Threading; +using ChaosBot.Attribute; +using ChaosBot.Database; +using ChaosBot.Database.Entity; +using NUnit.Framework; + +namespace ChaosBot.UnitTests +{ + public class DataBaseTests + { + [SetUp] + public void SetUp() + { + Program.LoadConfiguration("./appsettings.json"); + Program.LoadLogger(); + AssemblyController.RegisterDBEntityType(typeof(TestEntity)); + } + + [TearDown] + public void TearDown() + { + Controller.RawQuery("DROP TABLE TestTable;", readOutput: false); + } + + [Test] + public void Insert_CanInsertDataToDBAndDeleteFromDB_True() + { + var testEntity = new TestEntity(1); + + Assert.AreEqual(0, TestEntity.Query().Count()); + + TestEntity.Query().Insert(testEntity); + + Assert.AreEqual(1, TestEntity.Query().Count()); + + TestEntity.Query().Delete(); + + Assert.AreEqual(0, TestEntity.Query().Count()); + } + + [Test] + public void InsertUpdateDelete_CheckCanInsertUpdateAndDeleteFromDB_True() + { + Assert.AreEqual("", GetDBContent()); + TestEntity.Query().Insert(new TestEntity(5)); + Assert.AreEqual("5", GetDBContent()); + TestEntity.Query().Where("id", 5).Set("id", 6).Update(); + Assert.AreEqual("6", GetDBContent()); + TestEntity.Query().Where("id", 6).Delete(); + Assert.AreEqual("", GetDBContent()); + } + + public string GetDBContent() + { + return string.Join(" ", TestEntity.Query().Distinct().Get().Select(o => o.id).ToArray()); + } + } + + [DBEntity("TestTable")] + public class TestEntity : BaseEntity + { + public long id { get; private set; } + + public TestEntity() {} + + public TestEntity(int id) + { + this.id = id; + } + + public static QueryBuilder Query() + { + return BaseEntity.Query(); + } + + public override void SetFromRow(DataRow row) + { + id = (long)row["id"]; + } + } +} \ No newline at end of file