Added Core module support. Things are unstable

This commit is contained in:
2024-07-14 19:33:53 +03:00
parent 6599428043
commit 3f8590b8f3
13 changed files with 285 additions and 28 deletions
+57
View File
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DiscordBotCore.Interfaces;
using DiscordBotCore.Others;
using DiscordBotCore.Others.Actions;
namespace DiscordBot.Bot.Actions
{
internal class Module : ICommandAction
{
public string ActionName => "module";
public string Description => "Access module commands";
public string Usage => "module <name>";
public IEnumerable<InternalActionOption> ListOfOptions => [];
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
public Task Execute(string[] args)
{
string command = args[0];
switch(command)
{
case "list":
ListLoadedModules();
break;
default:
return Task.CompletedTask;
}
return Task.CompletedTask;
}
private void ListLoadedModules()
{
var modules = DiscordBotCore.Application.CurrentApplication.GetLoadedCoreModules();
foreach (var module in modules)
{
Type moduleType = module.Key;
List<object> moduleList = module.Value;
Console.WriteLine($"Module Type: {moduleType.Name}");
foreach (dynamic mod in moduleList)
{
Console.WriteLine($"Module: {mod.Name}");
}
}
}
}
}
+16 -7
View File
@@ -2,7 +2,6 @@
using DiscordBotCore.Online; using DiscordBotCore.Online;
using DiscordBotCore.Others; using DiscordBotCore.Others;
using DiscordBotCore.Others.Actions; using DiscordBotCore.Others.Actions;
using DiscordBotCore.Others.Logger;
using DiscordBotCore.Plugin; using DiscordBotCore.Plugin;
using System; using System;
@@ -10,6 +9,12 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordBotCore.Others.Exceptions; using DiscordBotCore.Others.Exceptions;
using DiscordBotCore.Loaders;
using DiscordBotCore.Interfaces.Modules;
using DiscordBotCore.Interfaces.Logger;
using DiscordBotCore.Modules;
using System.Linq;
using System.Collections.Immutable;
namespace DiscordBotCore namespace DiscordBotCore
@@ -21,9 +26,9 @@ namespace DiscordBotCore
{ {
public static Application CurrentApplication { get; private set; } = null!; public static Application CurrentApplication { get; private set; } = null!;
private static readonly string _DefaultLogMessageFormat = "{ThrowTime} {SenderName} {Message}";
private static readonly string _ConfigFile = "./Data/Resources/config.json"; private static readonly string _ConfigFile = "./Data/Resources/config.json";
private static readonly string _PluginsDatabaseFile = "./Data/Resources/plugins.json"; private static readonly string _PluginsDatabaseFile = "./Data/Resources/plugins.json";
private static readonly string _ModuleFolder = "./Data/Modules";
private static readonly string _ResourcesFolder = "./Data/Resources"; private static readonly string _ResourcesFolder = "./Data/Resources";
private static readonly string _PluginsFolder = "./Data/Plugins"; private static readonly string _PluginsFolder = "./Data/Plugins";
@@ -36,10 +41,13 @@ namespace DiscordBotCore
public string PluginDatabase => ApplicationEnvironmentVariables["PluginDatabase"] ?? _PluginsDatabaseFile; public string PluginDatabase => ApplicationEnvironmentVariables["PluginDatabase"] ?? _PluginsDatabaseFile;
public string LogFile => $"{ApplicationEnvironmentVariables["LogFolder"]}/{DateTime.Now.ToLongDateString().Replace(" / ", "")}.log"; public string LogFile => $"{ApplicationEnvironmentVariables["LogFolder"]}/{DateTime.Now.ToLongDateString().Replace(" / ", "")}.log";
private ModuleManager _ModuleManager;
public SettingsDictionary<string, string> ApplicationEnvironmentVariables { get; private set; } public SettingsDictionary<string, string> ApplicationEnvironmentVariables { get; private set; }
public InternalActionManager InternalActionManager { get; private set; } public InternalActionManager InternalActionManager { get; private set; }
public ILogger Logger => _ModuleManager.GetModule<ILogger>();
public IPluginManager PluginManager { get; private set; } public IPluginManager PluginManager { get; private set; }
public Logger Logger { get; private set; }
public Bot.App DiscordBotClient { get; internal set; } public Bot.App DiscordBotClient { get; internal set; }
public static async Task CreateApplication() public static async Task CreateApplication()
@@ -63,9 +71,10 @@ namespace DiscordBotCore
await CurrentApplication.ApplicationEnvironmentVariables.SaveToFile(); await CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
} }
CurrentApplication.Logger = CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("LogMessageFormat") ? CurrentApplication.ApplicationEnvironmentVariables.Add("ModuleFolder", _ModuleFolder);
new Logger(CurrentApplication.ApplicationEnvironmentVariables["LogMessageFormat"]) :
new Logger(_DefaultLogMessageFormat); CurrentApplication._ModuleManager = new(_ModuleFolder);
await CurrentApplication._ModuleManager.LoadModules();
if (!File.Exists(_PluginsDatabaseFile)) if (!File.Exists(_PluginsDatabaseFile))
{ {
@@ -88,6 +97,7 @@ namespace DiscordBotCore
} }
public IReadOnlyDictionary<Type, List<object>> GetLoadedCoreModules() => _ModuleManager.LoadedModules.AsReadOnly();
private static void PopulateEnvWithDefault() private static void PopulateEnvWithDefault()
{ {
@@ -102,7 +112,6 @@ namespace DiscordBotCore
CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"] = _PluginsFolder; CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"] = _PluginsFolder;
CurrentApplication.ApplicationEnvironmentVariables["ArchiveFolder"] = _ArchivesFolder; CurrentApplication.ApplicationEnvironmentVariables["ArchiveFolder"] = _ArchivesFolder;
CurrentApplication.ApplicationEnvironmentVariables["PluginDatabase"] = _PluginsDatabaseFile; CurrentApplication.ApplicationEnvironmentVariables["PluginDatabase"] = _PluginsDatabaseFile;
CurrentApplication.ApplicationEnvironmentVariables["LogMessageFormat"] = _DefaultLogMessageFormat;
CurrentApplication.ApplicationEnvironmentVariables["MaxParallelDownloads"] = _MaxParallelDownloads; CurrentApplication.ApplicationEnvironmentVariables["MaxParallelDownloads"] = _MaxParallelDownloads;
} }
+19 -9
View File
@@ -1,19 +1,29 @@
using DiscordBotCore.Others; using DiscordBotCore.Interfaces.Modules;
using DiscordBotCore.Others;
using System; using System;
using System.Collections.Generic;
namespace DiscordBotCore.Interfaces.Logger namespace DiscordBotCore.Interfaces.Logger
{ {
public interface ILogger public interface ILogger : IBaseModule
{ {
public struct FormattedMessage { public string Message; public LogType Type; } public struct FormattedMessage {
public string LogMessageFormat { get; set; } public string Message;
public LogType Type;
}
public void Log(ILogMessage message); string LogMessageFormat { get; set; }
public void LogException(Exception exception, object Sender, bool logFullStack = false);
public event EventHandler<FormattedMessage> OnFormattedLog; event EventHandler<FormattedMessage> OnFormattedLog;
public event EventHandler<ILogMessage> OnRawLog; event EventHandler<ILogMessage> OnRawLog;
void Log(ILogMessage message);
void Log(ILogMessage message, string format);
void Log(string message);
void Log(string message, LogType logType);
void Log(string message, LogType logType, string format);
void Log(string message, object Sender);
void Log(string message, object Sender, LogType type);
void LogException(Exception exception, object Sender, bool logFullStack = false);
} }
} }
@@ -0,0 +1,8 @@
using System;
namespace DiscordBotCore.Interfaces.Modules
{
public interface IBaseModule
{
}
}
@@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace DiscordBotCore.Interfaces.Modules
{
public interface IModule<T> where T : IBaseModule
{
public string Name { get; }
public T Module { get; }
public Task Initialize();
}
}
+70
View File
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.Modules;
using System.Reflection;
using Discord.Commands;
namespace DiscordBotCore.Loaders
{
internal class ModuleLoader
{
private string _moduleFolder;
public ModuleLoader(string moduleFolder)
{
_moduleFolder = moduleFolder;
}
public Task LoadFileModules()
{
var files = Directory.GetFiles(_moduleFolder, "*.dll");
foreach (var file in files)
{
try
{
Assembly.LoadFrom(file);
}
catch (Exception e)
{
Console.WriteLine($"Error loading module {file}: {e.Message}");
}
}
return Task.CompletedTask;
}
public Task<List<IModule<T>>> LoadModules<T>() where T : IBaseModule
{
var moduleType = typeof(IModule<T>);
var moduleTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => moduleType.IsAssignableFrom(p) && !p.IsInterface);
var modules = new List<IModule<T>>();
foreach (var module in moduleTypes)
{
try
{
var instance = (IModule<T>?)Activator.CreateInstance(module);
if (instance == null)
{
Console.WriteLine($"Error loading module {module.Name}: Could not create instance");
continue;
}
modules.Add(instance);
}
catch (Exception e)
{
Console.WriteLine($"Error loading module {module.Name}: {e.Message}");
}
}
return Task.FromResult(modules);
}
}
}
+52
View File
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.Logger;
using DiscordBotCore.Interfaces.Modules;
using DiscordBotCore.Loaders;
namespace DiscordBotCore.Modules
{
internal class ModuleManager
{
private string _moduleFolder;
internal Dictionary<Type, List<object>> LoadedModules { get; private set; }
public ModuleManager(string moduleFolder)
{
_moduleFolder = moduleFolder;
LoadedModules = new Dictionary<Type, List<object>>();
}
public T GetModule<T>() where T : IBaseModule
{
if(!LoadedModules.ContainsKey(typeof(T)))
throw new Exception($"No module loaded with this signature: {nameof(T)}");
IModule<T> module = (IModule<T>)LoadedModules[typeof(T)][0];
return module.Module;
}
public async Task LoadModules()
{
ModuleLoader loader = new ModuleLoader(_moduleFolder);
await loader.LoadFileModules();
// Load All Loggers
var loggers = await loader.LoadModules<ILogger>();
foreach (var logger in loggers)
{
await logger.Initialize();
Console.WriteLine("Module Loaded: " + logger.Name);
}
LoadedModules.Add(typeof(ILogger), loggers.Cast<object>().ToList());
}
}
}
@@ -58,6 +58,9 @@ public class SettingsDictionary<TKey, TValue>
public void Add(TKey key, TValue value) public void Add(TKey key, TValue value)
{ {
if (_Dictionary.ContainsKey(key))
return;
_Dictionary.Add(key, value); _Dictionary.Add(key, value);
} }
+22
View File
@@ -0,0 +1,22 @@
using DiscordBotCore;
using DiscordBotCore.Interfaces.Logger;
using DiscordBotCore.Interfaces.Modules;
namespace LoggerModule
{
public class Entry : IModule<ILogger>
{
public string Name => "Logger Module";
const string _LogFolder = "./Data/Logs/";
const string _LogFormat = "{ThrowTime} {SenderName} {Message}";
public ILogger Module { get; private set; }
public Task Initialize()
{
ILogger logger = new Logger(_LogFolder, _LogFormat);
Module = logger;
return Task.CompletedTask;
}
}
}
@@ -1,8 +1,7 @@
using DiscordBotCore.Interfaces.Logger; using DiscordBotCore.Interfaces.Logger;
using DiscordBotCore.Others;
using System; namespace LoggerModule
namespace DiscordBotCore.Others.Logger
{ {
internal sealed class LogMessage : ILogMessage internal sealed class LogMessage : ILogMessage
{ {
@@ -1,11 +1,7 @@
using System; using DiscordBotCore.Interfaces.Logger;
using System.Collections.Generic; using DiscordBotCore.Others;
using System.IO;
using System.Linq;
using DiscordBotCore.Interfaces.Logger; namespace LoggerModule;
namespace DiscordBotCore.Others.Logger;
public sealed class Logger : ILogger public sealed class Logger : ILogger
{ {
@@ -17,10 +13,11 @@ public sealed class Logger : ILogger
public event EventHandler<ILogger.FormattedMessage> OnFormattedLog; public event EventHandler<ILogger.FormattedMessage> OnFormattedLog;
public event EventHandler<ILogMessage> OnRawLog; public event EventHandler<ILogMessage> OnRawLog;
public Logger(string logMessageFormat) public Logger(string logFolder, string logMessageFormat)
{ {
this.LogMessageFormat = logMessageFormat; this.LogMessageFormat = logMessageFormat;
_LogFileStream = File.Open(Application.CurrentApplication.LogFile, FileMode.Append, FileAccess.Write, FileShare.Read); var logFile = logFolder + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
_LogFileStream = File.Open(logFile, FileMode.Append, FileAccess.Write, FileShare.Read);
} }
/// <summary> /// <summary>
+13
View File
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DiscordBotCore\DiscordBotCore.csproj" />
</ItemGroup>
</Project>
+6
View File
@@ -6,6 +6,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBot", "DiscordBot\Di
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotCore", "DiscordBotCore\DiscordBotCore.csproj", "{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotCore", "DiscordBotCore\DiscordBotCore.csproj", "{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoggerModule", "LoggerModule\LoggerModule.csproj", "{B7FC821B-031E-4656-9B8B-AC5D678E047A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -20,6 +22,10 @@ Global
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Debug|Any CPU.Build.0 = Debug|Any CPU {5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Release|Any CPU.ActiveCfg = Release|Any CPU {5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Release|Any CPU.Build.0 = Release|Any CPU {5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Release|Any CPU.Build.0 = Release|Any CPU
{B7FC821B-031E-4656-9B8B-AC5D678E047A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7FC821B-031E-4656-9B8B-AC5D678E047A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7FC821B-031E-4656-9B8B-AC5D678E047A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7FC821B-031E-4656-9B8B-AC5D678E047A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE