mirror of
https://github.com/tribufu/ServerManagers
synced 2026-05-06 15:17:34 +00:00
Discord Bot Scaffolding
This commit is contained in:
parent
ceb3ab73c4
commit
c4bf4906ea
24 changed files with 1119 additions and 5 deletions
|
|
@ -804,6 +804,15 @@
|
|||
<setting name="MainWindow_Top" serializeAs="String">
|
||||
<value>50</value>
|
||||
</setting>
|
||||
<setting name="DiscordBotEnabled" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="DiscordBotPrefix" serializeAs="String">
|
||||
<value>asm</value>
|
||||
</setting>
|
||||
<setting name="DiscordBotToken" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</ServerManagerTool.Config>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using ArkData;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using ServerManagerTool.Discord.Interfaces;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
|
|
@ -23,6 +23,8 @@ using System.Threading.Tasks;
|
|||
using System.Windows;
|
||||
using System.Xml;
|
||||
using WPFSharp.Globalizer;
|
||||
using ServerManagerTool.Discord;
|
||||
using ServerManagerTool.Discord.Enums;
|
||||
|
||||
namespace ServerManagerTool
|
||||
{
|
||||
|
|
@ -39,6 +41,7 @@ namespace ServerManagerTool
|
|||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private CancellationTokenSource _tokenSource;
|
||||
private GlobalizedApplication _globalizer;
|
||||
private bool _applicationStarted;
|
||||
private string _args;
|
||||
|
|
@ -144,6 +147,12 @@ namespace ServerManagerTool
|
|||
}
|
||||
}
|
||||
|
||||
public IServerManagerBot ServerManagerBot
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public static void DiscoverMachinePublicIP(bool forceOverride)
|
||||
{
|
||||
if (forceOverride || string.IsNullOrWhiteSpace(Config.Default.MachinePublicIP))
|
||||
|
|
@ -179,7 +188,11 @@ namespace ServerManagerTool
|
|||
|
||||
private IList<Plugin.Common.Lib.Profile> FetchProfiles()
|
||||
{
|
||||
return ServerManager.Instance.Servers.Select(s => new ServerManagerTool.Plugin.Common.Lib.Profile() { ProfileName = s?.Profile?.ProfileName ?? string.Empty, InstallationFolder = s?.Profile?.InstallDirectory ?? string.Empty }).ToList();
|
||||
return ServerManager.Instance.Servers.Select(s => new ServerManagerTool.Plugin.Common.Lib.Profile()
|
||||
{
|
||||
ProfileName = s?.Profile?.ProfileName ?? string.Empty,
|
||||
InstallationFolder = s?.Profile?.InstallDirectory ?? string.Empty
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public static string GetLogFolder() => IOUtils.NormalizePath(Path.Combine(Config.Default.DataDir, Config.Default.LogsDir));
|
||||
|
|
@ -218,6 +231,11 @@ namespace ServerManagerTool
|
|||
return LogManager.GetLogger(loggerName);
|
||||
}
|
||||
|
||||
private static IList<string> HandleDiscordCommand(CommandType commandType, string channelId, string profileId)
|
||||
{
|
||||
return new List<string>() { $"{commandType}; {channelId}; {profileId ?? "no profile"}" };
|
||||
}
|
||||
|
||||
private static void MigrateSettings()
|
||||
{
|
||||
var installFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
|
|
@ -412,6 +430,7 @@ namespace ServerManagerTool
|
|||
|
||||
ApplicationStarted = true;
|
||||
|
||||
var restartRequired = false;
|
||||
if (string.IsNullOrWhiteSpace(Config.Default.DataDir))
|
||||
{
|
||||
var dataDirectoryWindow = new DataDirectoryWindow();
|
||||
|
|
@ -422,6 +441,8 @@ namespace ServerManagerTool
|
|||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
restartRequired = true;
|
||||
}
|
||||
|
||||
Config.Default.ConfigDirectory = Path.Combine(Config.Default.DataDir, Config.Default.ProfilesDir);
|
||||
|
|
@ -429,6 +450,11 @@ namespace ServerManagerTool
|
|||
Config.Default.Save();
|
||||
CommonConfig.Default.Save();
|
||||
|
||||
if (restartRequired)
|
||||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
DataFileDetails.PlayerFileExtension = Config.Default.PlayerFileExtension;
|
||||
DataFileDetails.TribeFileExtension = Config.Default.TribeFileExtension;
|
||||
|
||||
|
|
@ -446,6 +472,27 @@ namespace ServerManagerTool
|
|||
|
||||
StartupUri = new Uri("Windows/AutoUpdateWindow.xaml", UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
if (Config.Default.DiscordBotEnabled)
|
||||
{
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
|
||||
ServerManagerBot = ServerManagerBotFactory.GetServerManagerBot();
|
||||
|
||||
Task discordTask = Task.Run(async () =>
|
||||
{
|
||||
await ServerManagerBot.StartAsync(Config.Default.DiscordBotPrefix, Config.Default.DiscordBotToken, Config.Default.DataDir, HandleDiscordCommand, _tokenSource.Token);
|
||||
}, _tokenSource.Token)
|
||||
.ContinueWith(t => {
|
||||
var message = t.Exception.InnerException is null ? t.Exception.Message : t.Exception.InnerException.Message;
|
||||
if (message.StartsWith("#"))
|
||||
{
|
||||
message = _globalizer.GetResourceString(message.Substring(1)) ?? message.Substring(1);
|
||||
}
|
||||
|
||||
MessageBox.Show(message, _globalizer.GetResourceString("DiscordBot_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}, TaskContinuationOptions.OnlyOnFaulted);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
|
|
@ -486,6 +533,12 @@ namespace ServerManagerTool
|
|||
|
||||
private void ShutDownApplication()
|
||||
{
|
||||
if (!(_tokenSource is null))
|
||||
{
|
||||
_tokenSource.Cancel();
|
||||
_tokenSource.Dispose();
|
||||
}
|
||||
|
||||
if (ApplicationStarted)
|
||||
{
|
||||
foreach (var server in ServerManager.Instance.Servers)
|
||||
|
|
|
|||
36
src/ARKServerManager/Config.Designer.cs
generated
36
src/ARKServerManager/Config.Designer.cs
generated
|
|
@ -2812,5 +2812,41 @@ namespace ServerManagerTool {
|
|||
return ((string)(this["DefaultDataDirectoryName"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool DiscordBotEnabled {
|
||||
get {
|
||||
return ((bool)(this["DiscordBotEnabled"]));
|
||||
}
|
||||
set {
|
||||
this["DiscordBotEnabled"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("asm")]
|
||||
public string DiscordBotPrefix {
|
||||
get {
|
||||
return ((string)(this["DiscordBotPrefix"]));
|
||||
}
|
||||
set {
|
||||
this["DiscordBotPrefix"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string DiscordBotToken {
|
||||
get {
|
||||
return ((string)(this["DiscordBotToken"]));
|
||||
}
|
||||
set {
|
||||
this["DiscordBotToken"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -779,5 +779,14 @@
|
|||
<Setting Name="DefaultDataDirectoryName" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">asmdata</Value>
|
||||
</Setting>
|
||||
<Setting Name="DiscordBotEnabled" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="DiscordBotPrefix" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">asm</Value>
|
||||
</Setting>
|
||||
<Setting Name="DiscordBotToken" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
|
|
@ -5523,4 +5523,10 @@
|
|||
<sys:String x:Key="ServerUpdate_WarningLabel">There was a problem while performing the server update. This may leave your server in a incomplete state.\r\n\r\nDo you want to continue with the server start, this could cause problems?</sys:String>
|
||||
<!--#endregion-->
|
||||
|
||||
<!--#region Discord Bot -->
|
||||
<sys:String x:Key="DiscordBot_ErrorTitle">Discord Bot Error</sys:String>
|
||||
<sys:String x:Key="DiscordBot_MissingTokenError">The discord bot requires a valid token so it can log into the discord server\r\nThis can be set in the global settings.</sys:String>
|
||||
<sys:String x:Key="DiscordBot_InvalidPrefixError">The discord bot prefix contains invalid characters. Only letters and numbers are allowed.</sys:String>
|
||||
<!--#endregion-->
|
||||
|
||||
</Globalization:GlobalizationResourceDictionary>
|
||||
|
|
@ -570,6 +570,15 @@
|
|||
<setting name="ServerFilesGridHeight" serializeAs="String">
|
||||
<value>250</value>
|
||||
</setting>
|
||||
<setting name="DiscordBotEnabled" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="DiscordBotPrefix" serializeAs="String">
|
||||
<value>csm</value>
|
||||
</setting>
|
||||
<setting name="DiscordBotToken" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</ServerManagerTool.Config>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
|
@ -4,6 +4,9 @@ using NLog.Config;
|
|||
using NLog.Targets;
|
||||
using ServerManagerTool.Common;
|
||||
using ServerManagerTool.Common.Utils;
|
||||
using ServerManagerTool.Discord;
|
||||
using ServerManagerTool.Discord.Enums;
|
||||
using ServerManagerTool.Discord.Interfaces;
|
||||
using ServerManagerTool.Enums;
|
||||
using ServerManagerTool.Lib;
|
||||
using ServerManagerTool.Plugin.Common;
|
||||
|
|
@ -37,6 +40,7 @@ namespace ServerManagerTool
|
|||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private CancellationTokenSource _tokenSource;
|
||||
private GlobalizedApplication _globalizer;
|
||||
private bool _applicationStarted;
|
||||
private string _args;
|
||||
|
|
@ -142,6 +146,12 @@ namespace ServerManagerTool
|
|||
}
|
||||
}
|
||||
|
||||
public IServerManagerBot ServerManagerBot
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public static void DiscoverMachinePublicIP(bool forceOverride)
|
||||
{
|
||||
if (forceOverride || string.IsNullOrWhiteSpace(Config.Default.MachinePublicIP))
|
||||
|
|
@ -177,7 +187,11 @@ namespace ServerManagerTool
|
|||
|
||||
private IList<Plugin.Common.Lib.Profile> FetchProfiles()
|
||||
{
|
||||
return ServerManager.Instance.Servers.Select(s => new ServerManagerTool.Plugin.Common.Lib.Profile() { ProfileName = s?.Profile?.ProfileName ?? string.Empty, InstallationFolder = s?.Profile?.InstallDirectory ?? string.Empty }).ToList();
|
||||
return ServerManager.Instance.Servers.Select(s => new ServerManagerTool.Plugin.Common.Lib.Profile()
|
||||
{
|
||||
ProfileName = s?.Profile?.ProfileName ?? string.Empty,
|
||||
InstallationFolder = s?.Profile?.InstallDirectory ?? string.Empty
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public static string GetLogFolder() => IOUtils.NormalizePath(Path.Combine(Config.Default.DataPath, Config.Default.LogsRelativePath));
|
||||
|
|
@ -216,6 +230,11 @@ namespace ServerManagerTool
|
|||
return LogManager.GetLogger(loggerName);
|
||||
}
|
||||
|
||||
private static IList<string> HandleDiscordCommand(CommandType commandType, string channelId, string profileId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void MigrateSettings()
|
||||
{
|
||||
var installFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
|
|
@ -395,6 +414,7 @@ namespace ServerManagerTool
|
|||
|
||||
this.ApplicationStarted = true;
|
||||
|
||||
var restartRequired = false;
|
||||
if (string.IsNullOrWhiteSpace(Config.Default.DataPath))
|
||||
{
|
||||
var dataDirectoryWindow = new DataDirectoryWindow();
|
||||
|
|
@ -405,6 +425,8 @@ namespace ServerManagerTool
|
|||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
restartRequired = true;
|
||||
}
|
||||
|
||||
Config.Default.ConfigPath = Path.Combine(Config.Default.DataPath, Config.Default.ProfilesRelativePath);
|
||||
|
|
@ -412,6 +434,11 @@ namespace ServerManagerTool
|
|||
Config.Default.Save();
|
||||
CommonConfig.Default.Save();
|
||||
|
||||
if (restartRequired)
|
||||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
if (e.Args.Any(a => a.StartsWith(Constants.ARG_SERVERMONITOR, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
ServerRuntime.EnableUpdateModStatus = false;
|
||||
|
|
@ -426,6 +453,27 @@ namespace ServerManagerTool
|
|||
|
||||
StartupUri = new Uri("Windows/AutoUpdateWindow.xaml", UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
if (Config.Default.DiscordBotEnabled)
|
||||
{
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
|
||||
ServerManagerBot = ServerManagerBotFactory.GetServerManagerBot();
|
||||
|
||||
Task discordTask = Task.Run(async () =>
|
||||
{
|
||||
await ServerManagerBot.StartAsync(Config.Default.DiscordBotPrefix, Config.Default.DiscordBotToken, Config.Default.DataPath, HandleDiscordCommand, _tokenSource.Token);
|
||||
}, _tokenSource.Token)
|
||||
.ContinueWith(t => {
|
||||
var message = t.Exception.InnerException is null ? t.Exception.Message : t.Exception.InnerException.Message;
|
||||
if (message.StartsWith("#"))
|
||||
{
|
||||
message = _globalizer.GetResourceString(message.Substring(1)) ?? message.Substring(1);
|
||||
}
|
||||
|
||||
MessageBox.Show(message, _globalizer.GetResourceString("DiscordBot_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}, TaskContinuationOptions.OnlyOnFaulted);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
|
|
@ -466,6 +514,12 @@ namespace ServerManagerTool
|
|||
|
||||
private void ShutDownApplication()
|
||||
{
|
||||
if (!(_tokenSource is null))
|
||||
{
|
||||
_tokenSource.Cancel();
|
||||
_tokenSource.Dispose();
|
||||
}
|
||||
|
||||
if (this.ApplicationStarted)
|
||||
{
|
||||
foreach (var server in ServerManager.Instance.Servers)
|
||||
|
|
|
|||
36
src/ConanServerManager/Config.Designer.cs
generated
36
src/ConanServerManager/Config.Designer.cs
generated
|
|
@ -1965,5 +1965,41 @@ namespace ServerManagerTool {
|
|||
return ((string)(this["DefaultDataDirectoryName"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool DiscordBotEnabled {
|
||||
get {
|
||||
return ((bool)(this["DiscordBotEnabled"]));
|
||||
}
|
||||
set {
|
||||
this["DiscordBotEnabled"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("csm")]
|
||||
public string DiscordBotPrefix {
|
||||
get {
|
||||
return ((string)(this["DiscordBotPrefix"]));
|
||||
}
|
||||
set {
|
||||
this["DiscordBotPrefix"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string DiscordBotToken {
|
||||
get {
|
||||
return ((string)(this["DiscordBotToken"]));
|
||||
}
|
||||
set {
|
||||
this["DiscordBotToken"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -545,5 +545,14 @@
|
|||
<Setting Name="DefaultDataDirectoryName" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">csmdata</Value>
|
||||
</Setting>
|
||||
<Setting Name="DiscordBotEnabled" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="DiscordBotPrefix" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">csm</Value>
|
||||
</Setting>
|
||||
<Setting Name="DiscordBotToken" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
|
|
@ -1193,4 +1193,10 @@
|
|||
<sys:String x:Key="ServerUpdate_WarningLabel">There was a problem while performing the server update. This may leave your server in a incomplete state.\r\n\r\nDo you want to continue with the server start, this could cause problems?</sys:String>
|
||||
<!--#endregion-->
|
||||
|
||||
<!--#region Discord Bot -->
|
||||
<sys:String x:Key="DiscordBot_ErrorTitle">Discord Bot Error</sys:String>
|
||||
<sys:String x:Key="DiscordBot_MissingTokenError">The discord bot requires a valid token so it can log into the discord server\r\nThis can be set in the global settings.</sys:String>
|
||||
<sys:String x:Key="DiscordBot_InvalidPrefixError">The discord bot prefix contains invalid characters. Only letters and numbers are allowed.</sys:String>
|
||||
<!--#endregion-->
|
||||
|
||||
</Globalization:GlobalizationResourceDictionary>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
using ServerManagerTool.Discord.Enums;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ServerManagerTool.Discord.Delegates
|
||||
{
|
||||
public delegate IList<string> HandleCommandDelegate(CommandType commandType, string channelId, string profileId);
|
||||
}
|
||||
15
src/ServerManager.Discord/DiscordBot.cs
Normal file
15
src/ServerManager.Discord/DiscordBot.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using ServerManagerTool.Discord.Delegates;
|
||||
|
||||
namespace ServerManagerTool.Discord
|
||||
{
|
||||
public static class DiscordBot
|
||||
{
|
||||
public const string PREFIX_DELIMITER = "!";
|
||||
|
||||
internal static HandleCommandDelegate HandleCommandCallback
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/ServerManager.Discord/Enums/CommandType.cs
Normal file
14
src/ServerManager.Discord/Enums/CommandType.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
namespace ServerManagerTool.Discord.Enums
|
||||
{
|
||||
public enum CommandType
|
||||
{
|
||||
BackupServer,
|
||||
ServerInfo,
|
||||
ServerList,
|
||||
ServerStatus,
|
||||
ShutdownServer,
|
||||
StartServer,
|
||||
StopServer,
|
||||
UpdateServer,
|
||||
}
|
||||
}
|
||||
11
src/ServerManager.Discord/Interfaces/IServerManagerBot.cs
Normal file
11
src/ServerManager.Discord/Interfaces/IServerManagerBot.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using ServerManagerTool.Discord.Delegates;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Interfaces
|
||||
{
|
||||
public interface IServerManagerBot
|
||||
{
|
||||
Task StartAsync(string commandPrefix, string discordToken, string dataDirectory, HandleCommandDelegate handleCommandCallback, CancellationToken token);
|
||||
}
|
||||
}
|
||||
151
src/ServerManager.Discord/Modules/HelpModule.cs
Normal file
151
src/ServerManager.Discord/Modules/HelpModule.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Modules
|
||||
{
|
||||
[Name("Help")]
|
||||
public sealed class HelpModule : ModuleBase<SocketCommandContext>
|
||||
{
|
||||
private const int MAX_VALUE_LENGTH = 1024;
|
||||
|
||||
private readonly CommandService _service;
|
||||
private readonly IConfigurationRoot _config;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public HelpModule(CommandService service, IConfigurationRoot config, IServiceProvider services)
|
||||
{
|
||||
_service = service;
|
||||
_config = config;
|
||||
_services = services;
|
||||
}
|
||||
|
||||
[Command("help")]
|
||||
[Summary("Provides a list of available commands")]
|
||||
public async Task HelpAsync()
|
||||
{
|
||||
var prefix = _config["DiscordSettings:Prefix"];
|
||||
|
||||
var builder = new EmbedBuilder()
|
||||
{
|
||||
Color = new Color(114, 137, 218),
|
||||
Description = "These are the commands you can use"
|
||||
};
|
||||
|
||||
foreach (var module in _service.Modules)
|
||||
{
|
||||
var moduleName = module.Name;
|
||||
|
||||
// create the list of accessible commands
|
||||
var commands = new List<string>(module.Commands.Count);
|
||||
|
||||
foreach (var cmd in module.Commands)
|
||||
{
|
||||
var result = await cmd.CheckPreconditionsAsync(Context, _services);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
commands.Add($"{prefix}{cmd.Aliases.First()}");
|
||||
}
|
||||
|
||||
// remove all duplicate commands
|
||||
commands = commands.Distinct().ToList();
|
||||
|
||||
var commandString = string.Empty;
|
||||
|
||||
foreach (var command in commands)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(command))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var commandToAdd = $"{command}\n";
|
||||
|
||||
if (commandString.Length + commandToAdd.Length > MAX_VALUE_LENGTH)
|
||||
{
|
||||
// force the output, string would be too long
|
||||
builder.AddField(x =>
|
||||
{
|
||||
x.Name = moduleName;
|
||||
x.Value = $"{commandString}\n";
|
||||
x.IsInline = false;
|
||||
});
|
||||
|
||||
// reset the module name and command string
|
||||
moduleName = $"{module.Name} cont.";
|
||||
commandString = string.Empty;
|
||||
}
|
||||
|
||||
commandString += commandToAdd;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(commandString))
|
||||
{
|
||||
builder.AddField(x =>
|
||||
{
|
||||
x.Name = moduleName;
|
||||
x.Value = $"{commandString}\n";
|
||||
x.IsInline = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await ReplyAsync(string.Empty, false, builder.Build());
|
||||
}
|
||||
|
||||
[Command("help")]
|
||||
[Summary("Searches a list of available commands")]
|
||||
public async Task HelpAsync(string command)
|
||||
{
|
||||
var searchResults = _service.Search(Context, command);
|
||||
|
||||
if (!searchResults.IsSuccess)
|
||||
{
|
||||
await ReplyAsync($"Sorry, couldn't find a command like **{command}**.");
|
||||
return;
|
||||
}
|
||||
|
||||
var prefix = _config["DiscordSettings:Prefix"];
|
||||
|
||||
var builder = new EmbedBuilder()
|
||||
{
|
||||
Color = new Color(114, 137, 218),
|
||||
Description = $"Here are some commands like **{command}**"
|
||||
};
|
||||
|
||||
foreach (var match in searchResults.Commands)
|
||||
{
|
||||
var cmd = match.Command;
|
||||
|
||||
var result = await cmd.CheckPreconditionsAsync(Context, _services);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var usage = $"{prefix}{cmd.Aliases.First()}";
|
||||
if (cmd.Parameters.Count > 0)
|
||||
{
|
||||
usage += $" {string.Join(" ", cmd.Parameters.Select(p => p.Name))}";
|
||||
}
|
||||
usage += $"\n";
|
||||
|
||||
builder.AddField(x =>
|
||||
{
|
||||
x.Name = string.Join(", ", cmd.Aliases);
|
||||
x.Value = $"Summary: {cmd.Summary}\nUsage: {usage}";
|
||||
x.IsInline = false;
|
||||
});
|
||||
}
|
||||
|
||||
await ReplyAsync(string.Empty, false, builder.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
207
src/ServerManager.Discord/Modules/ServerCommandModule.cs
Normal file
207
src/ServerManager.Discord/Modules/ServerCommandModule.cs
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
using Discord.Addons.Interactive;
|
||||
using Discord.Commands;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using ServerManagerTool.Discord.Enums;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Modules
|
||||
{
|
||||
[Name("Server Commands")]
|
||||
public sealed class ServerCommandModule : InteractiveBase
|
||||
{
|
||||
private readonly CommandService _service;
|
||||
private readonly IConfigurationRoot _config;
|
||||
|
||||
public ServerCommandModule(CommandService service, IConfigurationRoot config)
|
||||
{
|
||||
_service = service;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
[Command("backup", RunMode = RunMode.Async)]
|
||||
[Summary("Perform a backup of the server")]
|
||||
[Remarks("backup")]
|
||||
public async Task BackupServerAsync()
|
||||
{
|
||||
await BackupServerAsync(null);
|
||||
}
|
||||
|
||||
[Command("backup", RunMode = RunMode.Async)]
|
||||
[Summary("Perform a backup of the server")]
|
||||
[Remarks("backup profileId")]
|
||||
public async Task BackupServerAsync(string profileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.BackupServer, channelId, profileId);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("shutdown", RunMode = RunMode.Async)]
|
||||
[Summary("Shuts down the server properly")]
|
||||
[Remarks("shutdown")]
|
||||
public async Task ShutdownServerAsync()
|
||||
{
|
||||
await ShutdownServerAsync(null);
|
||||
}
|
||||
|
||||
[Command("shutdown", RunMode = RunMode.Async)]
|
||||
[Summary("Shuts down the server properly")]
|
||||
[Remarks("shutdown profileId")]
|
||||
public async Task ShutdownServerAsync(string profileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.ShutdownServer, channelId, profileId);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("start", RunMode = RunMode.Async)]
|
||||
[Summary("Starts the server")]
|
||||
[Remarks("start")]
|
||||
public async Task StartServerAsync()
|
||||
{
|
||||
await StartServerAsync(null);
|
||||
}
|
||||
|
||||
[Command("start", RunMode = RunMode.Async)]
|
||||
[Summary("Starts the server")]
|
||||
[Remarks("start profileId")]
|
||||
public async Task StartServerAsync(string profileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.StartServer, channelId, profileId);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("stop", RunMode = RunMode.Async)]
|
||||
[Summary("Forcibly stops the server")]
|
||||
[Remarks("stop")]
|
||||
public async Task StopServerAsync()
|
||||
{
|
||||
await StopServerAsync(null);
|
||||
}
|
||||
|
||||
[Command("stop", RunMode = RunMode.Async)]
|
||||
[Summary("Forcibly stops the server")]
|
||||
[Remarks("stop profileId")]
|
||||
public async Task StopServerAsync(string profileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.StopServer, channelId, profileId);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("update", RunMode = RunMode.Async)]
|
||||
[Summary("Updates the server")]
|
||||
[Remarks("update")]
|
||||
public async Task UpdateServerAsync()
|
||||
{
|
||||
await UpdateServerAsync(null);
|
||||
}
|
||||
|
||||
[Command("update", RunMode = RunMode.Async)]
|
||||
[Summary("Updates the server")]
|
||||
[Remarks("update profileId")]
|
||||
public async Task UpdateServerAsync(string profileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.UpdateServer, channelId, profileId);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
125
src/ServerManager.Discord/Modules/ServerQueryModule.cs
Normal file
125
src/ServerManager.Discord/Modules/ServerQueryModule.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
using Discord.Addons.Interactive;
|
||||
using Discord.Commands;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using ServerManagerTool.Discord.Enums;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Modules
|
||||
{
|
||||
[Name("Server Query")]
|
||||
public sealed class ServerQueryModule : InteractiveBase
|
||||
{
|
||||
private readonly CommandService _service;
|
||||
private readonly IConfigurationRoot _config;
|
||||
|
||||
public ServerQueryModule(CommandService service, IConfigurationRoot config)
|
||||
{
|
||||
_service = service;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
[Command("info", RunMode = RunMode.Async)]
|
||||
[Summary("Poll server for information")]
|
||||
[Remarks("info")]
|
||||
public async Task ServerInfoAsync()
|
||||
{
|
||||
await ServerInfoAsync(null);
|
||||
}
|
||||
|
||||
[Command("info", RunMode = RunMode.Async)]
|
||||
[Summary("Poll server for information")]
|
||||
[Remarks("info profileId")]
|
||||
public async Task ServerInfoAsync(string profileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.ServerInfo, channelId, profileId);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("list", RunMode = RunMode.Async)]
|
||||
[Summary("List of all servers associated with this channel")]
|
||||
[Remarks("list")]
|
||||
public async Task ServerListAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.ServerList, channelId, null);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("status", RunMode = RunMode.Async)]
|
||||
[Summary("Poll server for status")]
|
||||
[Remarks("status")]
|
||||
public async Task ServerStatusAsync()
|
||||
{
|
||||
await ServerStatusAsync(null);
|
||||
}
|
||||
|
||||
[Command("status", RunMode = RunMode.Async)]
|
||||
[Summary("Poll server for status")]
|
||||
[Remarks("status profileId")]
|
||||
public async Task ServerStatusAsync(string profileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
|
||||
|
||||
var response = DiscordBot.HandleCommandCallback?.Invoke(CommandType.ServerStatus, channelId, profileId);
|
||||
if (response is null || response.Count == 0)
|
||||
{
|
||||
await ReplyAsync("No servers associated with this channel.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var output in response)
|
||||
{
|
||||
await ReplyAsync(output);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await ReplyAsync($"'{Context.Message}' command sent and failed with exception ({ex.Message})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Globals">
|
||||
<Configurations>Debug;Release;Debug - Beta</Configurations>
|
||||
</PropertyGroup>
|
||||
|
|
@ -11,5 +11,18 @@
|
|||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Beta|AnyCPU'">
|
||||
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Discord.Addons.Interactive" Version="2.0.0" />
|
||||
<PackageReference Include="Discord.Net" Version="2.4.0" />
|
||||
<PackageReference Include="Discord.Net.Providers.WS4Net" Version="2.4.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Services\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
137
src/ServerManager.Discord/ServerManagerBot.cs
Normal file
137
src/ServerManager.Discord/ServerManagerBot.cs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
using Discord;
|
||||
using Discord.Addons.Interactive;
|
||||
using Discord.Commands;
|
||||
using Discord.Net.Providers.WS4Net;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ServerManagerTool.Discord.Delegates;
|
||||
using ServerManagerTool.Discord.Interfaces;
|
||||
using ServerManagerTool.Discord.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord
|
||||
{
|
||||
public sealed class ServerManagerBot : IServerManagerBot
|
||||
{
|
||||
internal ServerManagerBot()
|
||||
{
|
||||
}
|
||||
|
||||
private bool Started
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public async Task StartAsync(string commandPrefix, string discordToken, string dataDirectory, HandleCommandDelegate handleCommandCallback, CancellationToken token)
|
||||
{
|
||||
if (Started)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Started = true;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(commandPrefix) || string.IsNullOrWhiteSpace(discordToken))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (commandPrefix.Any(c => !char.IsLetterOrDigit(c)))
|
||||
{
|
||||
throw new Exception("#DiscordBot_InvalidPrefixError");
|
||||
}
|
||||
|
||||
if (!commandPrefix.EndsWith(DiscordBot.PREFIX_DELIMITER))
|
||||
{
|
||||
commandPrefix += DiscordBot.PREFIX_DELIMITER;
|
||||
}
|
||||
|
||||
var settings = new Dictionary<string, string>
|
||||
{
|
||||
{ "DiscordSettings:Prefix", commandPrefix },
|
||||
{ "DiscordSettings:Token", discordToken },
|
||||
{ "ServerManager:DataDirectory", dataDirectory }
|
||||
};
|
||||
|
||||
// Begin building the configuration file
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(settings)
|
||||
.Build();
|
||||
|
||||
var socketConfig = new DiscordSocketConfig
|
||||
{
|
||||
#if DEBUG
|
||||
LogLevel = LogSeverity.Verbose,
|
||||
#else
|
||||
LogLevel = LogSeverity.Info,
|
||||
#endif
|
||||
// Tell Discord.Net to cache 1000 messages per channel
|
||||
MessageCacheSize = 1000,
|
||||
};
|
||||
if (Environment.OSVersion.Version < new Version(6, 2))
|
||||
{
|
||||
// windows 7 or early
|
||||
socketConfig.WebSocketProvider = WS4NetProvider.Instance;
|
||||
}
|
||||
|
||||
var commandConfig = new CommandServiceConfig
|
||||
{
|
||||
// Force all commands to run async
|
||||
DefaultRunMode = RunMode.Async,
|
||||
#if DEBUG
|
||||
LogLevel = LogSeverity.Verbose,
|
||||
#else
|
||||
LogLevel = LogSeverity.Info,
|
||||
#endif
|
||||
};
|
||||
|
||||
// Build the service provider
|
||||
var services = new ServiceCollection()
|
||||
// Add the discord client to the service provider
|
||||
.AddSingleton(new DiscordSocketClient(socketConfig))
|
||||
// Add the command service to the service provider
|
||||
.AddSingleton(new CommandService(commandConfig))
|
||||
// Add remaining services to the provider
|
||||
.AddSingleton<CommandHandlerService>()
|
||||
.AddSingleton<InteractiveService>()
|
||||
.AddSingleton<LoggingService>()
|
||||
.AddSingleton<StartupService>()
|
||||
.AddSingleton<ShutdownService>()
|
||||
.AddSingleton<Random>()
|
||||
.AddSingleton(config);
|
||||
|
||||
// Create the service provider
|
||||
using (var provider = services.BuildServiceProvider())
|
||||
{
|
||||
// Initialize the logging service, startup service, and command handler
|
||||
provider?.GetRequiredService<LoggingService>();
|
||||
await provider?.GetRequiredService<StartupService>().StartAsync();
|
||||
provider?.GetRequiredService<CommandHandlerService>();
|
||||
|
||||
DiscordBot.HandleCommandCallback = handleCommandCallback;
|
||||
|
||||
try
|
||||
{
|
||||
// Prevent the application from closing
|
||||
await Task.Delay(Timeout.Infinite, token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
Debug.WriteLine("Task Canceled");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
Debug.WriteLine("Operation Canceled");
|
||||
}
|
||||
|
||||
await provider?.GetRequiredService<ShutdownService>().StopAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/ServerManager.Discord/ServerManagerBotFactory.cs
Normal file
19
src/ServerManager.Discord/ServerManagerBotFactory.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using ServerManagerTool.Discord.Interfaces;
|
||||
|
||||
namespace ServerManagerTool.Discord
|
||||
{
|
||||
public static class ServerManagerBotFactory
|
||||
{
|
||||
private static IServerManagerBot _serverManagerBot;
|
||||
|
||||
public static IServerManagerBot GetServerManagerBot()
|
||||
{
|
||||
if (_serverManagerBot is null)
|
||||
{
|
||||
_serverManagerBot = new ServerManagerBot();
|
||||
}
|
||||
|
||||
return _serverManagerBot;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
src/ServerManager.Discord/Services/CommandHandlerService.cs
Normal file
65
src/ServerManager.Discord/Services/CommandHandlerService.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Services
|
||||
{
|
||||
public class CommandHandlerService
|
||||
{
|
||||
private readonly DiscordSocketClient _discord;
|
||||
private readonly CommandService _commands;
|
||||
private readonly IConfigurationRoot _config;
|
||||
private readonly IServiceProvider _provider;
|
||||
|
||||
public CommandHandlerService(DiscordSocketClient discord, CommandService commands, IConfigurationRoot config, IServiceProvider provider)
|
||||
{
|
||||
_discord = discord;
|
||||
_commands = commands;
|
||||
_config = config;
|
||||
_provider = provider;
|
||||
|
||||
_discord.MessageReceived += OnMessageReceivedAsync;
|
||||
}
|
||||
|
||||
private async Task OnMessageReceivedAsync(SocketMessage s)
|
||||
{
|
||||
// Ensure the message is from a user/bot
|
||||
var msg = s as SocketUserMessage;
|
||||
if (msg is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore self when checking commands
|
||||
if (msg.Author == _discord.CurrentUser)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Tell bot to ignore itself.
|
||||
if (msg.Author.IsBot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the command context
|
||||
var context = new SocketCommandContext(_discord, msg);
|
||||
|
||||
// Check if the message has a valid command prefix
|
||||
var argPos = 0;
|
||||
if (msg.HasStringPrefix(_config["DiscordSettings:Prefix"], ref argPos) || msg.HasMentionPrefix(_discord.CurrentUser, ref argPos))
|
||||
{
|
||||
// Execute the command
|
||||
var result = await _commands.ExecuteAsync(context, argPos, _provider);
|
||||
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
// If not successful, reply with the error.
|
||||
await context.Channel.SendMessageAsync(result.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/ServerManager.Discord/Services/LoggingService.cs
Normal file
57
src/ServerManager.Discord/Services/LoggingService.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Services
|
||||
{
|
||||
public class LoggingService
|
||||
{
|
||||
private readonly DiscordSocketClient _discord;
|
||||
private readonly CommandService _commands;
|
||||
private readonly IConfigurationRoot _config;
|
||||
|
||||
private string LogDirectory { get; }
|
||||
private string LogFile => Path.Combine(LogDirectory, $"ServerManager_DiscordBot.{DateTime.Now:yyyyMMdd}.log");
|
||||
|
||||
public LoggingService(DiscordSocketClient discord, CommandService commands, IConfigurationRoot config)
|
||||
{
|
||||
_discord = discord;
|
||||
_commands = commands;
|
||||
_config = config;
|
||||
|
||||
// Get the data directory from the config file
|
||||
var rootDirectory = _config["ServerManager:DataDirectory"] ?? AppContext.BaseDirectory;
|
||||
LogDirectory = Path.Combine(rootDirectory, "logs");
|
||||
|
||||
_discord.Log += OnLogAsync;
|
||||
_commands.Log += OnLogAsync;
|
||||
}
|
||||
|
||||
private async Task OnLogAsync(LogMessage message)
|
||||
{
|
||||
// Create the log directory if it doesn't exist
|
||||
if (!Directory.Exists(LogDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(LogDirectory);
|
||||
}
|
||||
|
||||
// Create today's log file if it doesn't exist
|
||||
if (!File.Exists(LogFile))
|
||||
{
|
||||
File.Create(LogFile).Dispose();
|
||||
}
|
||||
|
||||
var logText = $"{DateTime.Now:HH:mm:ss:ffff} [{message.Severity}] {message.Source}: {message.Exception?.ToString() ?? message.Message}";
|
||||
|
||||
// Write the log text to a file
|
||||
File.AppendAllText(LogFile, logText + "\n");
|
||||
|
||||
// Write the log text to the console
|
||||
await Console.Out.WriteLineAsync(logText);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/ServerManager.Discord/Services/ShutdownService.cs
Normal file
21
src/ServerManager.Discord/Services/ShutdownService.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Services
|
||||
{
|
||||
public class ShutdownService
|
||||
{
|
||||
private readonly DiscordSocketClient _discord;
|
||||
|
||||
public ShutdownService(DiscordSocketClient discord)
|
||||
{
|
||||
_discord = discord;
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
await _discord.StopAsync();
|
||||
await _discord.LogoutAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/ServerManager.Discord/Services/StartupService.cs
Normal file
45
src/ServerManager.Discord/Services/StartupService.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Discord.Services
|
||||
{
|
||||
public class StartupService
|
||||
{
|
||||
private readonly DiscordSocketClient _discord;
|
||||
private readonly CommandService _commands;
|
||||
private readonly IConfigurationRoot _config;
|
||||
private readonly IServiceProvider _provider;
|
||||
|
||||
public StartupService(DiscordSocketClient discord, CommandService commands, IConfigurationRoot config, IServiceProvider provider)
|
||||
{
|
||||
_discord = discord;
|
||||
_commands = commands;
|
||||
_config = config;
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
{
|
||||
// Get the discord token from the config file
|
||||
var discordToken = _config["DiscordSettings:Token"];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(discordToken))
|
||||
{
|
||||
throw new Exception("#DiscordBot_MissingTokenError");
|
||||
}
|
||||
|
||||
// Login to discord
|
||||
await _discord.LoginAsync(TokenType.Bot, discordToken);
|
||||
// Connect to the websocket
|
||||
await _discord.StartAsync();
|
||||
|
||||
// Load commands and modules into the command service
|
||||
await _commands.AddModulesAsync(Assembly.GetExecutingAssembly(), _provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue