diff --git a/TShockAPI/DB/DbBuilder.cs b/TShockAPI/DB/DbBuilder.cs new file mode 100644 index 00000000..d02f993b --- /dev/null +++ b/TShockAPI/DB/DbBuilder.cs @@ -0,0 +1,89 @@ +using System.Data; +using System.Diagnostics; +using System.IO; +using Microsoft.Data.Sqlite; +using MySql.Data.MySqlClient; +using TerrariaApi.Server; +using TShockAPI.Configuration; + +namespace TShockAPI.DB; + +/// +/// Provides logic to build a DB connection. +/// +public sealed class DbBuilder +{ + private readonly TShock _caller; + private readonly TShockConfig _config; + private readonly string _savePath; + + /// + /// Initializes a new instance of the class. + /// + /// The TShock instance calling this DbBuilder. + /// The TShock configuration, supplied by at init. + /// The savePath registered by TShock. See . + public DbBuilder(TShock caller, TShockConfig config, string savePath) + { + _caller = caller; + _config = config; + _savePath = savePath; + } + + /// + /// Builds a DB connection based on the provided configuration. + /// + /// The TShock configuration. + /// + /// Default settings will result in a local sqlite database file named "tshock.db" in the current directory to be used as server DB. + /// + public IDbConnection BuildDbConnection() + { + string dbType = _config.Settings.StorageType.ToLowerInvariant(); + + return dbType switch + { + "sqlite" => BuildSqliteConnection(), + "mysql" => BuildMySqlConnection(), + _ => throw new("Invalid storage type") + }; + } + + private SqliteConnection BuildSqliteConnection() + { + string dbFilePath = Path.Combine(_savePath, _config.Settings.SqliteDBPath); + + if (Path.GetDirectoryName(dbFilePath) is not { } dbDirPath) + { + throw new DirectoryNotFoundException($"The SQLite database path '{dbFilePath}' could not be found."); + } + + Directory.CreateDirectory(dbDirPath); + + return new($"Data Source={dbFilePath}"); + } + + private MySqlConnection BuildMySqlConnection() + { + try + { + string[] hostport = _config.Settings.MySqlHost.Split(':'); + + MySqlConnectionStringBuilder connStrBuilder = new() + { + Server = hostport[0], + Port = hostport.Length > 1 ? uint.Parse(hostport[1]) : 3306, + Database = _config.Settings.MySqlDbName, + UserID = _config.Settings.MySqlUsername, + Password = _config.Settings.MySqlPassword + }; + + return new(connStrBuilder.ToString()); + } + catch (MySqlException e) + { + ServerApi.LogWriter.PluginWriteLine(_caller, e.ToString(), TraceLevel.Error); + throw new("MySql not setup correctly", e); + } + } +} diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index bd2a113e..0e453b40 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -314,37 +314,9 @@ namespace TShockAPI // Further exceptions are written to TShock's log from now on. try { - if (Config.Settings.StorageType.ToLower() == "sqlite") - { - string sql = Path.Combine(SavePath, Config.Settings.SqliteDBPath); - Directory.CreateDirectory(Path.GetDirectoryName(sql)); - DB = new Microsoft.Data.Sqlite.SqliteConnection(string.Format("Data Source={0}", sql)); - } - else if (Config.Settings.StorageType.ToLower() == "mysql") - { - try - { - var hostport = Config.Settings.MySqlHost.Split(':'); - DB = new MySqlConnection(); - DB.ConnectionString = - String.Format("Server={0}; Port={1}; Database={2}; Uid={3}; Pwd={4};", - hostport[0], - hostport.Length > 1 ? hostport[1] : "3306", - Config.Settings.MySqlDbName, - Config.Settings.MySqlUsername, - Config.Settings.MySqlPassword - ); - } - catch (MySqlException ex) - { - ServerApi.LogWriter.PluginWriteLine(this, ex.ToString(), TraceLevel.Error); - throw new Exception("MySql not setup correctly"); - } - } - else - { - throw new Exception("Invalid storage type"); - } + // Build database + DbBuilder dbBuilder = new(this, Config, SavePath); + DB = dbBuilder.BuildDbConnection(); if (Config.Settings.UseSqlLogs) Log = new SqlLog(DB, logFilename, LogClear);