From 7aa3a1a092b28c11d9020127480d158e42d85562 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Thu, 25 Aug 2016 03:19:06 +0200 Subject: [PATCH] Announcements converted?!?!? --- .../Commands/AutoAssignRoleCommands.cs | 4 +- .../Commands/ServerGreetCommands.cs | 537 +++++++++--------- .../Services/Database/Models/GuildConfig.cs | 17 + 3 files changed, 272 insertions(+), 286 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs index bd847420..8927720e 100644 --- a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs @@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Administration if (conf.AutoAssignRoleId == 0) return; - var role = user.Guild.Roles.Where(r => r.Id == conf.AutoAssignRoleId).FirstOrDefault(); + var role = user.Guild.Roles.FirstOrDefault(r => r.Id == conf.AutoAssignRoleId); if (role != null) await user.AddRolesAsync(role); @@ -55,7 +55,7 @@ namespace NadekoBot.Modules.Administration conf.AutoAssignRoleId = role.Id; uow.GuildConfigs.Update(conf); - await uow.CompleteAsync(); + await uow.CompleteAsync().ConfigureAwait(false); } if (role == null) diff --git a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs index 4b2f4d31..0aba311e 100644 --- a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs @@ -1,321 +1,290 @@ -//using Discord; -//using Discord.Commands; -//using NadekoBot.Classes; -//using System.Collections.Concurrent; -//using System.Linq; -//using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using NadekoBot.Attributes; +using NadekoBot.Classes; +using NadekoBot.Services; +using NadekoBot.Services.Database.Models; +using System.Collections.Concurrent; +using System.Linq; +using System.Threading.Tasks; -//// todo DB -//// todo rewrite -//namespace NadekoBot.Modules.Administration -//{ -// public partial class ServerGreetCommands -// { +// todo DB +// todo rewrite +namespace NadekoBot.Modules.Administration +{ + public partial class ServerGreetCommands + { + public static long Greeted = 0; -// public static ConcurrentDictionary AnnouncementsDictionary; + public ServerGreetCommands(DiscordModule module) + { + NadekoBot.Client.UserJoined += UserJoined; + NadekoBot.Client.UserLeft += UserLeft; + } -// public static long Greeted = 0; + private async Task UserLeft(IGuildUser user) + { + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(user.Guild.Id); + } -// public ServerGreetCommands(DiscordModule module) -// { -// AnnouncementsDictionary = new ConcurrentDictionary(); + if (!conf.SendChannelByeMessage) return; + var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.ByeMessageChannelId); -// NadekoBot.Client.UserJoined += UserJoined; -// NadekoBot.Client.UserLeft += UserLeft; + if (channel == null) //maybe warn the server owner that the channel is missing + return; -// var data = Classes.DbHandler.Instance.GetAllRows(); + var msg = conf.ChannelByeMessageText.Replace("%user%", "**" + user.Username + "**"); + if (string.IsNullOrWhiteSpace(msg)) + return; -// if (!data.Any()) return; -// foreach (var obj in data) -// AnnouncementsDictionary.TryAdd((ulong)obj.ServerId, new AnnounceControls(obj)); -// } + var toDelete = await channel.SendMessageAsync(msg).ConfigureAwait(false); + if (conf.AutoDeleteByeMessages) + { + await Task.Delay(conf.AutoDeleteGreetMessagesTimer * 1000).ConfigureAwait(false); // 5 minutes + await toDelete.DeleteAsync().ConfigureAwait(false); + } + } -// private async void UserLeft(object sender, UserEventArgs e) -// { -// try -// { -// if (!AnnouncementsDictionary.ContainsKey(e.Server.Id) || -// !AnnouncementsDictionary[e.Server.Id].Bye) return; + private async Task UserJoined(IGuildUser user) + { + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(user.Guild.Id); + } -// var controls = AnnouncementsDictionary[e.Server.Id]; -// var channel = NadekoBot.Client.GetChannel(controls.ByeChannel); -// var msg = controls.ByeText.Replace("%user%", "**" + imsg.Author.Username + "**").Trim(); -// if (string.IsNullOrEmpty(msg)) -// return; + if (conf.SendChannelGreetMessage) + { + var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.GreetMessageChannelId); -// if (controls.ByePM) -// { -// Greeted++; -// try -// { -// await imsg.Author.SendMessageAsync($"`Farewell Message From {e.Server?.Name}`\n" + msg).ConfigureAwait(false); + if (channel != null) //maybe warn the server owner that the channel is missing + { -// } -// catch { } -// } -// else -// { -// if (channel == null) return; -// Greeted++; -// var toDelete = await channel.SendMessageAsync(msg).ConfigureAwait(false); -// if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages && controls.DeleteGreetMessages) -// { -// await Task.Delay(30000).ConfigureAwait(false); // 5 minutes -// await toDelete.Delete().ConfigureAwait(false); -// } -// } -// } -// catch { } -// } + var msg = conf.ChannelGreetMessageText.Replace("%user%", "**" + user.Username + "**"); + if (!string.IsNullOrWhiteSpace(msg)) + { + var toDelete = await channel.SendMessageAsync(msg).ConfigureAwait(false); + if (conf.AutoDeleteGreetMessages) + { + await Task.Delay(conf.AutoDeleteGreetMessagesTimer * 1000).ConfigureAwait(false); // 5 minutes + await toDelete.DeleteAsync().ConfigureAwait(false); + } + } + } + } -// private async Task UserJoined(object sender, Discord.UserEventArgs e) -// { -// try -// { -// if (!AnnouncementsDictionary.ContainsKey(e.Server.Id) || -// !AnnouncementsDictionary[e.Server.Id].Greet) return; + if (conf.SendDmGreetMessage) + { + var channel = await user.CreateDMChannelAsync(); -// var controls = AnnouncementsDictionary[e.Server.Id]; -// var channel = NadekoBot.Client.GetChannel(controls.GreetChannel); + if (channel != null) + { + var msg = conf.DmGreetMessageText.Replace("%user%", "**" + user.Username + "**"); + if (!string.IsNullOrWhiteSpace(msg)) + { + var toDelete = await channel.SendMessageAsync(msg).ConfigureAwait(false); + } + } + } + } -// var msg = controls.GreetText.Replace("%user%", imsg.Author.Mention).Trim(); -// if (string.IsNullOrEmpty(msg)) -// return; -// if (controls.GreetPM) -// { -// Greeted++; -// await imsg.Author.SendMessageAsync($"`Welcome Message From {e.Server.Name}`\n" + msg).ConfigureAwait(false); -// } -// else -// { -// if (channel == null) return; -// Greeted++; -// var toDelete = await channel.SendMessageAsync(msg).ConfigureAwait(false); -// if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages && controls.DeleteGreetMessages) -// { -// await Task.Delay(30000).ConfigureAwait(false); // 5 minutes -// await toDelete.Delete().ConfigureAwait(false); -// } -// } -// } -// catch { } -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageGuild)] + public async Task GreetDel(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; -// public class AnnounceControls -// { -// private DataModels.Announcement _model { get; } + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + conf.AutoDeleteGreetMessages = !conf.AutoDeleteGreetMessages; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } -// public bool Greet { -// get { return _model.Greet; } -// set { _model.Greet = value; Save(); } -// } + if (conf.AutoDeleteGreetMessages) + await channel.SendMessageAsync("`Automatic deletion of greet messages has been enabled.`").ConfigureAwait(false); + else + await channel.SendMessageAsync("`Automatic deletion of greet messages has been disabled.`").ConfigureAwait(false); + } -// public ulong GreetChannel { -// get { return (ulong)_model.GreetChannelId; } -// set { _model.GreetChannelId = (long)value; Save(); } -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageGuild)] + public async Task ByeDel(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; -// public bool GreetPM { -// get { return _model.GreetPM; } -// set { _model.GreetPM = value; Save(); } -// } + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + conf.AutoDeleteByeMessages = !conf.AutoDeleteByeMessages; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } -// public bool ByePM { -// get { return _model.ByePM; } -// set { _model.ByePM = value; Save(); } -// } + if (conf.AutoDeleteByeMessages) + await channel.SendMessageAsync("`Automatic deletion of bye messages has been enabled.`").ConfigureAwait(false); + else + await channel.SendMessageAsync("`Automatic deletion of bye messages has been disabled.`").ConfigureAwait(false); + } -// public string GreetText { -// get { return _model.GreetText; } -// set { _model.GreetText = value; Save(); } -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageGuild)] + public async Task Greet(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; -// public bool Bye { -// get { return _model.Bye; } -// set { _model.Bye = value; Save(); } -// } -// public ulong ByeChannel { -// get { return (ulong)_model.ByeChannelId; } -// set { _model.ByeChannelId = (long)value; Save(); } -// } + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + conf.SendChannelGreetMessage = !conf.SendChannelGreetMessage; + conf.GreetMessageChannelId = channel.Id; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } -// public string ByeText { -// get { return _model.ByeText; } -// set { _model.ByeText = value; Save(); } -// } + if (conf.SendChannelGreetMessage) + await channel.SendMessageAsync("Greet announcements enabled on this channel.").ConfigureAwait(false); + else + await channel.SendMessageAsync("Greet announcements disabled.").ConfigureAwait(false); + } -// public ulong ServerId { -// get { return (ulong)_model.ServerId; } -// set { _model.ServerId = (long)value; } -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageGuild)] + public async Task DmGreet(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; -// public bool DeleteGreetMessages { -// get { -// return _model.DeleteGreetMessages; -// } -// set { -// _model.DeleteGreetMessages = value; Save(); -// } -// } + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + conf.SendDmGreetMessage = !conf.SendDmGreetMessage; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } -// public AnnounceControls(DataModels.Announcement model) -// { -// this._model = model; -// } + if (conf.SendDmGreetMessage) + await channel.SendMessageAsync("Greet announcements enabled on this channel.").ConfigureAwait(false); + else + await channel.SendMessageAsync("Greet announcements disabled.").ConfigureAwait(false); + } -// public AnnounceControls(ulong serverId) -// { -// this._model = new DataModels.Announcement(); -// ServerId = serverId; -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task GreetMsg(IMessage imsg, [Remainder] string text) + { + var channel = (ITextChannel)imsg.Channel; -// internal bool ToggleBye(ulong id) -// { -// if (Bye) -// { -// return Bye = false; -// } -// else -// { -// ByeChannel = id; -// return Bye = true; -// } -// } + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + if (!string.IsNullOrWhiteSpace(text)) + { + conf.ChannelGreetMessageText = text; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } + } -// internal bool ToggleGreet(ulong id) -// { -// if (Greet) -// { -// return Greet = false; -// } -// else -// { -// GreetChannel = id; -// return Greet = true; -// } -// } + if (string.IsNullOrWhiteSpace(text)) + { + await channel.SendMessageAsync("`Current greet message:` " + conf.ChannelGreetMessageText); + return; + } + await channel.SendMessageAsync("New greet message set.").ConfigureAwait(false); + if (!conf.SendChannelGreetMessage) + await channel.SendMessageAsync("Enable greet messsages by typing `.greet`").ConfigureAwait(false); + } -// internal bool ToggleDelete() => DeleteGreetMessages = !DeleteGreetMessages; -// internal bool ToggleGreetPM() => GreetPM = !GreetPM; -// internal bool ToggleByePM() => ByePM = !ByePM; + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task DmGreetMsg(IMessage imsg, [Remainder] string text) + { + var channel = (ITextChannel)imsg.Channel; -// private void Save() -// { -// Classes.DbHandler.Instance.Save(_model); -// } -// } + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + if (!string.IsNullOrWhiteSpace(text)) + { + conf.DmGreetMessageText = text; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } + } -// internal override void Init(CommandGroupBuilder cgb) -// { -// cgb.CreateCommand(Module.Prefix + "grdel") -// .Description($"Toggles automatic deletion of greet and bye messages. **Needs Manage Server Permissions.**| `{Prefix}grdel`") -// .Do(async e => -// { -// if (!imsg.Author.ServerPermissions.ManageServer) return; -// var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); + if (string.IsNullOrWhiteSpace(text)) + { + await channel.SendMessageAsync("`Current DM greet message:` " + conf.DmGreetMessageText); + return; + } + await channel.SendMessageAsync("New DM greet message set.").ConfigureAwait(false); + if (!conf.SendDmGreetMessage) + await channel.SendMessageAsync("Enable DM greet messsages by typing `.greet`").ConfigureAwait(false); + } -// if (ann.ToggleDelete()) -// await channel.SendMessageAsync("`Automatic deletion of greet and bye messages has been enabled.`").ConfigureAwait(false); -// else -// await channel.SendMessageAsync("`Automatic deletion of greet and bye messages has been disabled.`").ConfigureAwait(false); -// }); + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageGuild)] + public async Task Bye(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; -// cgb.CreateCommand(Module.Prefix + "greet") -// .Description($"Toggles anouncements on the current channel when someone joins the server. **Needs Manage Server Permissions.**| `{Prefix}greet`") -// .Do(async e => -// { -// if (!imsg.Author.ServerPermissions.ManageServer) return; -// var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + conf.SendChannelByeMessage = !conf.SendChannelByeMessage; + conf.ByeMessageChannelId = channel.Id; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } -// if (ann.ToggleGreet(e.Channel.Id)) -// await channel.SendMessageAsync("Greet announcements enabled on this channel.").ConfigureAwait(false); -// else -// await channel.SendMessageAsync("Greet announcements disabled.").ConfigureAwait(false); -// }); + if (conf.SendChannelByeMessage) + await channel.SendMessageAsync("Bye announcements enabled on this channel.").ConfigureAwait(false); + else + await channel.SendMessageAsync("Bye announcements disabled.").ConfigureAwait(false); + } -// cgb.CreateCommand(Module.Prefix + "greetmsg") -// .Description($"Sets a new join announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. **Needs Manage Server Permissions.**| `{Prefix}greetmsg Welcome to the server, %user%.`") -// .Parameter("msg", ParameterType.Unparsed) -// .Do(async e => -// { -// if (!imsg.Author.ServerPermissions.ManageServer) return; -// var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); -// if (string.IsNullOrWhiteSpace(msg)) -// { -// await channel.SendMessageAsync("`Current greet message:` " + ann.GreetText); -// return; -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task ByeMsg(IMessage imsg, [Remainder] string text) + { + var channel = (ITextChannel)imsg.Channel; + GuildConfig conf; + using (var uow = DbHandler.UnitOfWork()) + { + conf = uow.GuildConfigs.For(channel.Guild.Id); + if (!string.IsNullOrWhiteSpace(text)) + { + conf.ChannelByeMessageText = text; + uow.GuildConfigs.Update(conf); + await uow.CompleteAsync(); + } + } -// ann.GreetText = msg; -// await channel.SendMessageAsync("New greet message set.").ConfigureAwait(false); -// if (!ann.Greet) -// await channel.SendMessageAsync("Enable greet messsages by typing `.greet`").ConfigureAwait(false); -// }); - -// cgb.CreateCommand(Module.Prefix + "bye") -// .Description($"Toggles anouncements on the current channel when someone leaves the server. | `{Prefix}bye`") -// .Do(async e => -// { -// if (!imsg.Author.ServerPermissions.ManageServer) return; -// var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); - -// if (ann.ToggleBye(e.Channel.Id)) -// await channel.SendMessageAsync("Bye announcements enabled on this channel.").ConfigureAwait(false); -// else -// await channel.SendMessageAsync("Bye announcements disabled.").ConfigureAwait(false); -// }); - -// cgb.CreateCommand(Module.Prefix + "byemsg") -// .Description($"Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. **Needs Manage Server Permissions.**| `{Prefix}byemsg %user% has left the server.`") -// .Parameter("msg", ParameterType.Unparsed) -// .Do(async e => -// { -// if (!imsg.Author.ServerPermissions.ManageServer) return; -// var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); -// if (string.IsNullOrWhiteSpace(msg)) -// { -// await channel.SendMessageAsync("`Current bye message:` " + ann.ByeText); -// return; -// } - -// ann.ByeText = msg; -// await channel.SendMessageAsync("New bye message set.").ConfigureAwait(false); -// if (!ann.Bye) -// await channel.SendMessageAsync("Enable bye messsages by typing `.bye`.").ConfigureAwait(false); -// }); - -// cgb.CreateCommand(Module.Prefix + "byepm") -// .Description($"Toggles whether the good bye messages will be sent in a PM or in the text channel. **Needs Manage Server Permissions.**| `{Prefix}byepm`") -// .Do(async e => -// { -// if (!imsg.Author.ServerPermissions.ManageServer) return; -// var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); - - -// if (ann.ToggleByePM()) -// await channel.SendMessageAsync("Bye messages will be sent in a PM from now on.\n ⚠ Keep in mind this might fail if the user and the bot have no common servers after the user leaves.").ConfigureAwait(false); -// else -// await channel.SendMessageAsync("Bye messages will be sent in a bound channel from now on.").ConfigureAwait(false); -// if (!ann.Bye) -// await channel.SendMessageAsync("Enable bye messsages by typing `.bye`, and set the bye message using `.byemsg`").ConfigureAwait(false); -// }); - -// cgb.CreateCommand(Module.Prefix + "greetpm") -// .Description($"Toggles whether the greet messages will be sent in a PM or in the text channel. **Needs Manage Server Permissions.**| `{Prefix}greetpm`") -// .Do(async e => -// { -// if (!imsg.Author.ServerPermissions.ManageServer) return; - -// var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); - -// if (ann.ToggleGreetPM()) -// await channel.SendMessageAsync("Greet messages will be sent in a PM from now on.").ConfigureAwait(false); -// else -// await channel.SendMessageAsync("Greet messages will be sent in a bound channel from now on.").ConfigureAwait(false); -// if (!ann.Greet) -// await channel.SendMessageAsync("Enable greet messsages by typing `.greet`, and set the greet message using `.greetmsg`").ConfigureAwait(false); -// }); -// } -// } -//} + if (string.IsNullOrWhiteSpace(text)) + { + await channel.SendMessageAsync("`Current bye message:` " + conf.ChannelGreetMessageText); + return; + } + await channel.SendMessageAsync("New bye message set.").ConfigureAwait(false); + if (!conf.SendChannelByeMessage) + await channel.SendMessageAsync("Enable bye messsages by typing `.bye`").ConfigureAwait(false); + } + } +} diff --git a/src/NadekoBot/Services/Database/Models/GuildConfig.cs b/src/NadekoBot/Services/Database/Models/GuildConfig.cs index b2d16bd5..32d8ea23 100644 --- a/src/NadekoBot/Services/Database/Models/GuildConfig.cs +++ b/src/NadekoBot/Services/Database/Models/GuildConfig.cs @@ -11,5 +11,22 @@ namespace NadekoBot.Services.Database.Models public ulong GuildId { get; set; } public bool DeleteMessageOnCommand { get; set; } public ulong AutoAssignRoleId { get; set; } + //greet stuff + public bool AutoDeleteGreetMessages { get; set; } + public bool AutoDeleteByeMessages { get; set; } + public int AutoDeleteGreetMessagesTimer { get; set; } = 30; + + public ulong GreetMessageChannelId { get; set; } + public ulong ByeMessageChannelId { get; set; } + + public bool SendDmGreetMessage { get; set; } + public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!"; + + public bool SendChannelGreetMessage { get; set; } + public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!"; + + public bool SendChannelByeMessage { get; set; } + public string ChannelByeMessageText { get; set; } = "Welcome to the %server% server, %user%!"; + } }