diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index 1d1ffac27..a9ff28487 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -15,12 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WelcomePlugin", "Plugins\We {D51EECEB-438A-47DA-870F-7D7B41BC24D6} = {D51EECEB-438A-47DA-870F-7D7B41BC24D6} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VotemapPlugin", "Plugins\VoteMap\VotemapPlugin.csproj", "{428D8EB9-ECA3-4A66-AA59-3A944378C33F}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{26E8B310-269E-46D4-A612-24601F16065F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FastRestartPlugin", "Plugins\FastRestart\FastRestartPlugin.csproj", "{1479DE87-ACB5-4046-81C8-A0BA5041227D}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C8F3945-0AEF-4949-A1F7-B18E952E50BC}" ProjectSection(SolutionItems) = preProject _customcallbacks.gsc = _customcallbacks.gsc @@ -33,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Plugins\Tests\Test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebfrontCore", "WebfrontCore\WebfrontCore.csproj", "{65340D7D-5831-406C-ACAD-B13BA634BDE2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfanityDeterment", "Plugins\ProfanityDeterment\ProfanityDeterment.csproj", "{3EA31029-C76F-4C8E-AFD4-79F77DEA7033}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -149,66 +147,6 @@ Global {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release-Stable|x64.Build.0 = Release-Stable|x64 {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release-Stable|x86.ActiveCfg = Release-Stable|x86 {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release-Stable|x86.Build.0 = Release-Stable|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|x64.ActiveCfg = Debug|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|x64.Build.0 = Debug|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|x86.ActiveCfg = Debug|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|x86.Build.0 = Debug|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Any CPU.Build.0 = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x64.ActiveCfg = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x64.Build.0 = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x86.ActiveCfg = Release-Stable|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x86.Build.0 = Release-Stable|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|Mixed Platforms.Build.0 = Release-Nightly|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|x64.ActiveCfg = Release-Nightly|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|x64.Build.0 = Release-Nightly|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|x86.ActiveCfg = Release-Nightly|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|x86.Build.0 = Release-Nightly|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Stable|Any CPU.ActiveCfg = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Stable|Mixed Platforms.ActiveCfg = Release-Stable|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Stable|Mixed Platforms.Build.0 = Release-Stable|x86 - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Stable|x64.ActiveCfg = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Stable|x64.Build.0 = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Stable|x86.ActiveCfg = Release-Stable|Any CPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Stable|x86.Build.0 = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|x64.ActiveCfg = Debug|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|x64.Build.0 = Debug|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|x86.ActiveCfg = Debug|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|x86.Build.0 = Debug|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Any CPU.Build.0 = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x64.ActiveCfg = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x64.Build.0 = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x86.ActiveCfg = Release-Stable|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x86.Build.0 = Release-Stable|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|Mixed Platforms.Build.0 = Release-Nightly|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|x64.ActiveCfg = Release-Nightly|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|x64.Build.0 = Release-Nightly|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|x86.ActiveCfg = Release-Nightly|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|x86.Build.0 = Release-Nightly|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Stable|Any CPU.ActiveCfg = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Stable|Mixed Platforms.ActiveCfg = Release-Stable|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Stable|Mixed Platforms.Build.0 = Release-Stable|x86 - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Stable|x64.ActiveCfg = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Stable|x64.Build.0 = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Stable|x86.ActiveCfg = Release-Stable|Any CPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Stable|x86.Build.0 = Release-Stable|Any CPU {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -271,6 +209,38 @@ Global {65340D7D-5831-406C-ACAD-B13BA634BDE2}.Release-Stable|x64.Build.0 = Release|Any CPU {65340D7D-5831-406C-ACAD-B13BA634BDE2}.Release-Stable|x86.ActiveCfg = Release|x86 {65340D7D-5831-406C-ACAD-B13BA634BDE2}.Release-Stable|x86.Build.0 = Release|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|x64.ActiveCfg = Debug|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|x64.Build.0 = Debug|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|x86.ActiveCfg = Debug|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Debug|x86.Build.0 = Debug|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|Any CPU.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|x64.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|x64.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|x86.ActiveCfg = Release|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release|x86.Build.0 = Release|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|Any CPU.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|Any CPU.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|Mixed Platforms.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|Mixed Platforms.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|x64.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|x64.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|x86.ActiveCfg = Release|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Nightly|x86.Build.0 = Release|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|Any CPU.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|Any CPU.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|Mixed Platforms.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|Mixed Platforms.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|x64.ActiveCfg = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|x64.Build.0 = Release|Any CPU + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|x86.ActiveCfg = Release|x86 + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033}.Release-Stable|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -278,9 +248,8 @@ Global GlobalSection(NestedProjects) = preSolution {4785AB75-66F3-4391-985D-63A5A049A0FA} = {26E8B310-269E-46D4-A612-24601F16065F} {AF097E6B-48D5-4452-9CCF-0A81A21F341D} = {26E8B310-269E-46D4-A612-24601F16065F} - {428D8EB9-ECA3-4A66-AA59-3A944378C33F} = {26E8B310-269E-46D4-A612-24601F16065F} - {1479DE87-ACB5-4046-81C8-A0BA5041227D} = {26E8B310-269E-46D4-A612-24601F16065F} {B8C2A759-8663-4F6F-9BA4-19595F5E12C1} = {26E8B310-269E-46D4-A612-24601F16065F} + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033} = {26E8B310-269E-46D4-A612-24601F16065F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {84F8F8E0-1F73-41E0-BD8D-BB6676E2EE87} diff --git a/Plugins/EventAPI/EventAPI.csproj b/Plugins/EventAPI/EventAPI.csproj deleted file mode 100644 index e77c8c238..000000000 --- a/Plugins/EventAPI/EventAPI.csproj +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Debug - AnyCPU - {C9E821BF-23AD-4CB5-B7F9-B3B99B606650} - Library - Properties - EventAPI - EventAPI - v4.5.2 - 512 - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - bin\Release-Stable\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - x86 - bin\x86\Debug\ - DEBUG;TRACE - - - x86 - bin\x86\Release\ - true - - - x86 - bin\x86\Release-Stable\ - true - - - - {d51eeceb-438a-47da-870f-7d7b41bc24d6} - SharedLibrary - False - - - - - - - - - - - copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)BUILD\plugins\" - - - \ No newline at end of file diff --git a/Plugins/EventAPI/Plugin.cs b/Plugins/EventAPI/Plugin.cs deleted file mode 100644 index 07bbf9fc0..000000000 --- a/Plugins/EventAPI/Plugin.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -using SharedLibrary; -using SharedLibrary.Interfaces; -using SharedLibrary.Objects; - -namespace EventAPI -{ - class Events : IPlugin - { - public static Queue APIEvents { get; private set; } - public static List ActiveServers; - - DateTime lastClear; - int flaggedMessages; - List flaggedMessagesText; - - public String Name => "Event API Plugin"; - - public float Version => 1.0f; - - public string Author => "RaidMax"; - - public async Task OnLoadAsync(IManager manager) - { - APIEvents = new Queue(); - flaggedMessagesText = new List(); - ActiveServers = new List(); - } - - public async Task OnUnloadAsync() - { - APIEvents.Clear(); - ActiveServers.Clear(); - } - - public async Task OnTickAsync(Server S) - { - return; - } - - public async Task OnEventAsync(Event E, Server S) - { - if (E.Type == Event.GType.Start) - { - ActiveServers.Add(S); - } - - if (E.Type == Event.GType.Stop) - { - ActiveServers.RemoveAll(s => s.GetHashCode() == S.GetHashCode()); - } - - if (E.Type == Event.GType.Connect) - { - AddRestEvent(new RestEvent(RestEvent.EventType.NOTIFICATION, RestEvent.EventVersion.IW4MAdmin, E.Origin.Name + " has joined " + S.Hostname, E.Type.ToString(), S.Hostname, E.Origin.Name)); - } - - if (E.Type == Event.GType.Disconnect) - { - AddRestEvent(new RestEvent(RestEvent.EventType.NOTIFICATION, RestEvent.EventVersion.IW4MAdmin, E.Origin.Name + " has left " + S.Hostname, E.Type.ToString(), S.Hostname, E.Origin.Name)); - } - - if (E.Type == Event.GType.Say) - { - if (E.Data.Length != 0 && E.Data[0] != '!') - AddRestEvent(new RestEvent(RestEvent.EventType.NOTIFICATION, RestEvent.EventVersion.IW4MAdmin, E.Data, "Chat", E.Origin.Name, "")); - } - - if (E.Type == Event.GType.Report) - { - AddRestEvent(new RestEvent(RestEvent.EventType.ALERT, RestEvent.EventVersion.IW4MAdmin, $"**{E.Origin.Name}** has reported **{E.Target.Name}** for: {E.Data.Trim()}", E.Target.Name, E.Origin.Name, "")); - } - - if (E.Type == Event.GType.Say && E.Origin.Level < Player.Permission.Moderator) - { - string message = E.Data.ToLower(); - bool flagged = message.Contains(" wh ") || - message.Contains("hax") || - message.Contains("cheat") || - message.Contains(" hack ") || - message.Contains("aim") || - message.Contains("wall") || - message.Contains("cheto") || - message.Contains("hak") || - message.Contains(" bot "); - - if (flagged) - { - flaggedMessages++; - flaggedMessagesText.Add(String.Format("{0}: {1}", E.Origin.Name, E.Data)); - } - - if (flaggedMessages > 3) - { - await E.Owner.Broadcast("If you suspect someone of ^5CHEATING ^7use the ^5!report ^7command"); - - AddRestEvent(new RestEvent(RestEvent.EventType.ALERT, RestEvent.EventVersion.IW4MAdmin, "Chat indicates there may be a cheater", "Alert", E.Owner.Hostname, "")); - AddRestEvent(new RestEvent(RestEvent.EventType.NOTIFICATION, RestEvent.EventVersion.IW4MAdmin, String.Join("\n", flaggedMessagesText), "Chat Monitor", E.Owner.Hostname, "")); - flaggedMessages = 0; - } - - else if ((DateTime.Now - lastClear).TotalMinutes >= 3) - { - flaggedMessages = 0; - flaggedMessagesText.Clear(); - lastClear = DateTime.Now; - } - } - } - - public static void AddRestEvent(RestEvent E) - { - if (APIEvents.Count > 20) - APIEvents.Dequeue(); - APIEvents.Enqueue(E); - } - } -} diff --git a/Plugins/FastRestart/Plugin.cs b/Plugins/FastRestart/Plugin.cs deleted file mode 100644 index 14599452d..000000000 --- a/Plugins/FastRestart/Plugin.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Collections.Generic; - -using SharedLibrary; -using SharedLibrary.Interfaces; -using SharedLibrary.Network; -using SharedLibrary.Helpers; -using SharedLibrary.Objects; - -namespace Plugin -{ - public class FastRestartConfig : Serialize - { - public bool Enabled; - } - - public class CEnableFastRestart : Command - { - public CEnableFastRestart() : base("frenable", "enable fast restarting at the end of a map", "fre", Player.Permission.SeniorAdmin, false) { } - - public override async Task ExecuteAsync(Event E) - { - FastRestartPlugin.ConfigManager.UpdateProperty(E.Owner, new KeyValuePair("Enabled", true)); - await E.Origin.Tell("Fast restarting is now enabled for this server"); - } - } - - public class CDisableFastRestart : Command - { - public CDisableFastRestart() : base("fredisable", "disable fast restarting at the end of a map", "frd", Player.Permission.SeniorAdmin, false) { } - - public override async Task ExecuteAsync(Event E) - { - FastRestartPlugin.ConfigManager.UpdateProperty(E.Owner, new KeyValuePair("Enabled", false)); - await E.Origin.Tell("Fast restarting is now disabled for this server"); - } - } - - public class FastRestartPlugin : IPlugin - { - bool MatchEnded; - DateTime MatchEndTime; - Dictionary FastRestarts; - - public static ConfigurationManager ConfigManager { get; private set; } - - public string Name => "Fast Restarter"; - - public float Version => 1.0f; - - public string Author => "RaidMax"; - - public async Task OnEventAsync(Event E, Server S) - { - if (E.Type == Event.GType.Start) - { - ConfigManager.AddConfiguration(S); - if (ConfigManager.GetConfiguration(S).Keys.Count == 0) - ConfigManager.AddProperty(S, new KeyValuePair("Enabled", false)); - - FastRestarts.Add(S.GetHashCode(), 0); - - try - { - await S.GetDvarAsync("scr_intermission_time"); - } - - catch (SharedLibrary.Exceptions.DvarException) - { - await S.SetDvarAsync("scr_intermission_time", 20); - } - } - } - - public async Task OnLoadAsync(IManager manager) - { - ConfigManager = new ConfigurationManager(typeof(FastRestartPlugin)); - FastRestarts = new Dictionary(); - } - - public async Task OnTickAsync(Server S) - { - if ((bool)ConfigManager.GetConfiguration(S)["Enabled"] == false) - return; - - MatchEnded = (await S.GetDvarAsync("scr_gameended")).Value == 1; - - if (MatchEnded && MatchEndTime == DateTime.MinValue) - MatchEndTime = DateTime.Now; - - int intermissionTime = 20; - - try - { - var intermissionTimeDvar = await S.GetDvarAsync("scr_intermission_time"); - intermissionTime = intermissionTimeDvar.Value; - } - - catch(SharedLibrary.Exceptions.DvarException) - { - await S.SetDvarAsync("scr_intermission_time", 20); - } - - // I'm pretty sure the timelength from game ended to scoreboard popup is 2000ms - if (MatchEnded && (DateTime.Now - MatchEndTime).TotalSeconds >= intermissionTime - 2) - { - if (FastRestarts[S.GetHashCode()] >= 8) - { - await S.ExecuteCommandAsync("map_restart"); - FastRestarts[S.GetHashCode()] = 0; - } - - else - { - await S.ExecuteCommandAsync("fast_restart"); - FastRestarts[S.GetHashCode()] = FastRestarts[S.GetHashCode()] + 1; - } - - MatchEndTime = DateTime.MinValue; - } - } - - public async Task OnUnloadAsync() - { - - } - } -} diff --git a/Plugins/MessageBoard/Encryption.cs b/Plugins/MessageBoard/Encryption.cs deleted file mode 100644 index 6453979d1..000000000 --- a/Plugins/MessageBoard/Encryption.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Security.Cryptography; -using System.Text; - -//http://codereview.stackexchange.com/questions/96494/user-password-encryption-in-c + SCrypt -namespace MessageBoard.Encryption -{ - - public static class PasswordHasher - { - public static byte[] ComputeHash(string password, byte[] salt) - { - byte[] pwBytes = Encoding.UTF8.GetBytes(password); - byte[] hashBytes = new byte[64]; - CryptSharp.Utility.SCrypt.ComputeKey(pwBytes, salt, 16384, 8, 1, null, hashBytes); - return hashBytes; - } - - public static byte[] GenerateSalt(int saltByteSize = 24) - { - RNGCryptoServiceProvider saltGenerator = new RNGCryptoServiceProvider(); - byte[] salt = new byte[saltByteSize]; - saltGenerator.GetBytes(salt); - return salt; - } - - public static bool VerifyPassword(String password, byte[] passwordSalt, byte[] passwordHash) - { - byte[] computedHash = ComputeHash(password, passwordSalt); - return AreHashesEqual(computedHash, passwordHash); - } - - //Length constant verification - prevents timing attack - private static bool AreHashesEqual(byte[] firstHash, byte[] secondHash) - { - int minHashLength = firstHash.Length <= secondHash.Length ? firstHash.Length : secondHash.Length; - var xor = firstHash.Length ^ secondHash.Length; - for (int i = 0; i < minHashLength; i++) - xor |= firstHash[i] ^ secondHash[i]; - return 0 == xor; - } - } -} \ No newline at end of file diff --git a/Plugins/MessageBoard/Events.cs b/Plugins/MessageBoard/Events.cs deleted file mode 100644 index 26f74b530..000000000 --- a/Plugins/MessageBoard/Events.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MessageBoard.Events -{ - public delegate void ActionEventHandler(User origin, EventArgs e); -} diff --git a/Plugins/MessageBoard/Exceptions.cs b/Plugins/MessageBoard/Exceptions.cs deleted file mode 100644 index 33bd19284..000000000 --- a/Plugins/MessageBoard/Exceptions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MessageBoard.Exceptions -{ - public class ThreadException : Exception - { - public ThreadException(string msg) : base(msg) { } - } - - public class UserException : Exception - { - public UserException(string msg) : base(msg) { } - } - - public class SessionException : Exception - { - public SessionException(string msg) : base(msg) { } - } - - public class CategoryException : Exception - { - public CategoryException(string msg) : base(msg) { } - } - - public class PermissionException: Exception - { - public PermissionException(string msg) : base(msg) { } - } -} - \ No newline at end of file diff --git a/Plugins/MessageBoard/Forum.cs b/Plugins/MessageBoard/Forum.cs deleted file mode 100644 index 90730b52d..000000000 --- a/Plugins/MessageBoard/Forum.cs +++ /dev/null @@ -1,1376 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using System.Text; -using SharedLibrary; -using System.Collections.Specialized; - - -namespace MessageBoard.Forum -{ - public class Manager - { - private List forumPages; - private List activeSessions; - private Storage.Database database; - - private const int MAX_SESSIONS = 64; - public const int TITLE_MAXLENGTH = 30; - public const int CONTENT_MAXLENGTH = 8192; - public const int USERNAME_MAXLENGTH = 30; - public const int PASSWORD_MAXLENGTH = 64; - - public Rank guestRank; - public Rank UserRank; - public Rank ModRank; - public Rank AdminRank; - - public enum ErrorCode - { - NO_ERROR, - GLOBAL_PERMISSIONDENIED, - USER_DUPLICATE, - USER_INVALID, - USER_BADCREDENTIALS, - USER_EMPTYCREDENTIALS, - USER_NOTAUTHORIZED, - USER_PASSWORDTOOLONG, - USER_USERNAMETOOLONG, - USER_BADPROFILEDATA, - SESSION_INVALID, - THREAD_BADDATA, - THREAD_EMPTYDATA, - THREAD_CONTENTTOOLONG, - THREAD_TITLETOOLONG, - THREAD_INVALID, - REPLY_SAVEFAILED, - CATEGORY_INVALID, - CATEGORY_EMPTY, - USER_MISMATCHEDPASSWORD - } - - public Manager() - { - forumPages = new List(); - activeSessions = new List(); - database = new Storage.Database("Database/forum.db", null); - } - - public void startSession(string sessionID) - { - try - { - Session newSession = getSession(sessionID); - newSession.sessionStartTime = DateTime.Now; - addSession(newSession); - } - - catch (Exceptions.SessionException) - { - //Console.WriteLine("No session was found so we are adding a new one"); - Session newSession = new Session(new User(), sessionID); - addSession(newSession); - } - } - - public Session getSession(string sessionID) - { - Session requestedSession = activeSessions.Find(sess => sess.sessionID == sessionID); - - if (requestedSession == null) - requestedSession = database.getSession(sessionID); - - if (requestedSession == null) - throw new Exceptions.SessionException("Session not found"); - - return requestedSession; - } - - public User getUser(int userID) - { - User requestedUser = database.getUser(userID); - - if (requestedUser == null) - throw new Exceptions.UserException("User not found"); - - return requestedUser; - } - - public User getUser(string username) - { - User requestedUser = database.getUser(username); - - if (requestedUser == null) - throw new Exceptions.UserException("User not found"); - - return requestedUser; - } - - public ForumThread getThread(int threadID) - { - ForumThread requestedThread = database.getThread(threadID); - - if (requestedThread == null) - throw new Exceptions.ThreadException("Thread not found"); - - return requestedThread; - } - - public Post getPost(int postID) - { - Post requestedPost = database.getReply(postID); - - if (requestedPost == null) - throw new Exceptions.ThreadException("Post not found"); - - return requestedPost; - } - - public List getReplies(int threadID) - { - return database.getRepliesFromThreadID(threadID); - } - - public Post getReply(int replyID) - { - Post reply = database.getReply(replyID); - - if (reply == null) - throw new Exceptions.ThreadException("Reply not found"); - - return reply; - } - - public ErrorCode addPost(ForumThread parentThread, Post newPost) - { - int addedPost = database.addReply(newPost); - if (addedPost > 0) - { - parentThread.replies++; - parentThread.updatedDate = DateTime.Now; - database.updateThread(parentThread); - database.updateUser(newPost.author); - return ErrorCode.NO_ERROR; - } - - return ErrorCode.REPLY_SAVEFAILED; - } - - private ErrorCode addSession(Session sess) - { - if (activeSessions.Count >= MAX_SESSIONS) - activeSessions.RemoveAt(0); - - activeSessions.RemoveAll(x => x.sessionUser.ranking.name == "Guest" && x.sessionID == sess.sessionID); - - //Console.WriteLine(String.Format("Adding new session [{0}] [{1}]", sess.sessionID, sess.sessionUser.username)); - - if (activeSessions.Find(x => x.sessionID == sess.sessionID) == null) - activeSessions.Add(sess); - - // if it's a guest session, we don't want to save them in the database... - if (sess.sessionUser.ranking.name != "Guest") - { - database.setSession(sess.sessionUser.id, sess.sessionID); - sess.sessionUser.lastLogin = DateTime.Now; - database.updateUser(sess.sessionUser); - } - - return ErrorCode.NO_ERROR; - } - - public void removeSession(string sessID) - { - activeSessions.RemoveAll(x => x.sessionID == sessID); - database.removeSession(sessID); - } - - public ProfileSettings getProfileSettings(int userid) - { - var retrieved = database.getProfileSettings(userid); - if (retrieved == null) - { - if (userid > 0) - { - var profile = new ProfileSettings(userid); - database.addProfileSettings(profile); - return profile; - } - return new ProfileSettings(0); - } - else - return retrieved; - } - - public ErrorCode addUser(User newUser, Session userSession) - { - if (database.userExists(newUser.username, newUser.email)) - return ErrorCode.USER_DUPLICATE; - - // first added user is going to be admin - if (database.getNumUsers() == 0) - newUser.ranking = AdminRank; - - User createdUser = database.addUser(newUser, userSession); - database.addProfileSettings(new ProfileSettings(createdUser.id)); - removeSession(userSession.sessionID); - return addSession(new Session(createdUser, userSession.sessionID)); - } - - public void updateUser(User updatedUser) - { - database.updateUser(updatedUser); - } - - public void updateUserProfile(ProfileSettings updatedUserProfile) - { - database.updateProfileSettings(updatedUserProfile); - } - - public ErrorCode updateThread(ForumThread newThread) - { - if (database.updateThread(newThread)) - return ErrorCode.NO_ERROR; - - else - return ErrorCode.THREAD_INVALID; - } - - public ErrorCode updateReply(Post updatedReply) - { - if (database.updateReply(updatedReply)) - return ErrorCode.NO_ERROR; - else - return ErrorCode.THREAD_INVALID; - } - - public ErrorCode addThread(ForumThread newThread) - { - if (database.addThread(newThread) > 0) - return ErrorCode.NO_ERROR; - else - return ErrorCode.THREAD_INVALID; - } - - public ErrorCode authorizeUser(string username, string password, string sessionID) - { - User toAuth = database.getUser(username); - - if (toAuth == null) - return ErrorCode.USER_BADCREDENTIALS; - - bool validCredentials = Encryption.PasswordHasher.VerifyPassword(password, Convert.FromBase64String(toAuth.getPasswordSalt()), Convert.FromBase64String(toAuth.getPasswordHash())); - - if (!validCredentials) - return ErrorCode.USER_BADCREDENTIALS; - - addSession(new Session(toAuth, sessionID)); - return ErrorCode.NO_ERROR; - } - - public List getAllCategories() - { - return database.getAllCategories(); - } - - public List getRecentThreads(int catID) - { - return database.getRecentThreads(catID); - } - - public List getCategoryThreads(int categoryID) - { - return database.getCategoryThreads(categoryID); - } - - public Category getCategory(int id) - { - Category cat = database.getCategory(id); - - if (cat == null) - throw new Exceptions.CategoryException("Category not found"); - - return cat; - } - - public List getSessions() - { - return activeSessions; - } - - public void Start() - { - var login = new Pages.Login(); - var loginJSON = new Pages.LoginJSON(); - var register = new Pages.Register(); - var registerJSON = new Pages.RegisterJSON(); - var userinfoJSON = new Pages.userinfoJSON(); - var viewUser = new Pages.ViewUser(); - var userCP = new Pages.UserCP(); - var updateUserJSON = new Pages.updateUserJSON(); - var categoriesJSON = new Pages.categoriesJSON(); - var category = new Pages.ViewCategory(); - var categorythreadsJSON = new Pages.categorythreadsJSON(); - var home = new Pages.Home(); - var recentthreadsJSON = new Pages.recentthreadsJSON(); - var postthread = new Pages.PostThread(); - var postthreadJSON = new Pages.postthreadJSON(); - var editthreadJSON = new Pages.editthreadJSON(); - var threadJSON = new Pages.threadJSON(); - var viewthread = new Pages.ViewThread(); - var logout = new Pages.LogOut(); - var stats = new Pages.StatsJSON(); - - forumPages.Add(login); - forumPages.Add(loginJSON); - forumPages.Add(register); - forumPages.Add(registerJSON); - forumPages.Add(userinfoJSON); - forumPages.Add(viewUser); - forumPages.Add(userCP); - forumPages.Add(updateUserJSON); - forumPages.Add(categoriesJSON); - forumPages.Add(category); - forumPages.Add(categorythreadsJSON); - forumPages.Add(home); - forumPages.Add(recentthreadsJSON); - forumPages.Add(postthread); - forumPages.Add(postthreadJSON); - forumPages.Add(editthreadJSON); - forumPages.Add(threadJSON); - forumPages.Add(viewthread); - forumPages.Add(logout); - forumPages.Add(stats); - - SharedLibrary.WebService.PageList.Add(login); - SharedLibrary.WebService.PageList.Add(loginJSON); - SharedLibrary.WebService.PageList.Add(register); - SharedLibrary.WebService.PageList.Add(registerJSON); - SharedLibrary.WebService.PageList.Add(userinfoJSON); - SharedLibrary.WebService.PageList.Add(viewUser); - SharedLibrary.WebService.PageList.Add(userCP); - SharedLibrary.WebService.PageList.Add(updateUserJSON); - SharedLibrary.WebService.PageList.Add(categoriesJSON); - SharedLibrary.WebService.PageList.Add(category); - SharedLibrary.WebService.PageList.Add(categorythreadsJSON); - SharedLibrary.WebService.PageList.Add(home); - SharedLibrary.WebService.PageList.Add(recentthreadsJSON); - SharedLibrary.WebService.PageList.Add(postthread); - SharedLibrary.WebService.PageList.Add(postthreadJSON); - SharedLibrary.WebService.PageList.Add(editthreadJSON); - SharedLibrary.WebService.PageList.Add(threadJSON); - SharedLibrary.WebService.PageList.Add(viewthread); - SharedLibrary.WebService.PageList.Add(logout); - SharedLibrary.WebService.PageList.Add(stats); - - guestRank = database.getRank("Guest"); - UserRank = database.getRank("User"); - ModRank = database.getRank("Moderator"); - AdminRank = database.getRank("Administrator"); - } - - public void Stop() - { - //session logouts - //checkme - foreach (var page in forumPages) - SharedLibrary.WebService.PageList.Remove(page); - } - } - - - public class Pages - { - public abstract class JSONPage : IPage - { - protected Session currentSession; - - public bool Visible() - { - return false; - } - - public virtual string GetPath() - { - return "/forum"; - } - - public string GetName() - { - return "JSONPage"; - } - - public virtual HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary requestHeaders) - { - HttpResponse resp = new HttpResponse(); - resp.contentType = "application/json"; - resp.additionalHeaders = new Dictionary(); - - if (requestHeaders.ContainsKey("Cookie")) - { - //Console.WriteLine("JSON request contains session header - " + requestHeaders["Cookie"]); - string cookie = requestHeaders["Cookie"].Split('=')[1]; - Plugin.Main.ManagerInstance.startSession(cookie); - currentSession = Plugin.Main.ManagerInstance.getSession(cookie); - } - - else - { - string sessionID = Convert.ToBase64String(Encryption.PasswordHasher.GenerateSalt()); - resp.additionalHeaders.Add("Set-Cookie", "IW4MAdmin_ForumSession=" + sessionID + "; path=/; expires=Sat, 01 May 2025 12:00:00 GMT"); - currentSession = new Session(new User(), sessionID); - Plugin.Main.ManagerInstance.startSession(sessionID); - currentSession = Plugin.Main.ManagerInstance.getSession(sessionID); - } - - return resp; - } - } - - abstract public class ForumPage : HTMLPage - { - public ForumPage(bool visible) : base(visible) { } - public abstract override string GetName(); - public override string GetPath() - { - return base.GetPath() + "/forum"; - } - public override Dictionary GetHeaders(IDictionary requestHeaders) - { - return base.GetHeaders(requestHeaders); - } - - protected string templatation(string bodyContent) - { - StringBuilder S = new StringBuilder(); - S.Append(base.LoadHeader()); - S.Append(bodyContent); - S.Append(base.LoadFooter()); - - return S.ToString(); - } - } - - public class Login : ForumPage - { - public Login() : base(true) - { - - } - - public override string GetName() - { - return "Forum"; - } - - public override string GetPath() - { - return base.GetPath() + "/login"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - return templatation(LoadFile("forum\\login.html")); - } - } - - public class Register : ForumPage - { - public Register(): base(false) - { - - } - - public override string GetName() - { - return "Register"; - } - - public override string GetPath() - { - return base.GetPath() + "/register"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = LoadFile("forum\\register.html"); - return templatation(content); - } - } - - public class Home : ForumPage - { - public Home() : base(false) - { - - } - - public override string GetName() - { - return "Forum - Home"; - } - - public override string GetPath() - { - return base.GetPath() + "/home"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = LoadFile("forum\\home.html"); - return templatation(content); - } - } - - public class PostThread : ForumPage - { - public PostThread() : base(false) - { - - } - - public override string GetName() - { - return "Forum - Post New Thread"; - } - - public override string GetPath() - { - return base.GetPath() + "/postthread"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = LoadFile("forum\\postthread.html"); - return templatation(content); - } - } - - public class ViewCategory : ForumPage - { - public ViewCategory() : base(false) - { - - } - - public override string GetName() - { - return "Forum - Category View"; - } - - public override string GetPath() - { - return base.GetPath() + "/category"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = LoadFile("forum\\category.html"); - return templatation(content); - } - } - - public class ViewUser : ForumPage - { - public ViewUser() : base(false) - { - - } - - public override string GetName() - { - return "Forum - View User"; - } - - public override string GetPath() - { - return base.GetPath() + "/user"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = LoadFile("forum\\user.html"); - return templatation(content); - } - } - - public class UserCP : ForumPage - { - public UserCP() : base(false) - { - - } - - public override string GetName() - { - return "Forum - User Control Panel"; - } - - public override string GetPath() - { - return base.GetPath() + "/usercp"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = LoadFile("forum\\usercp.html"); - return templatation(content); - } - } - - public class ViewThread : ForumPage - { - public ViewThread() : base(false) - { - - } - - public override string GetName() - { - return "Forum - View Thread"; - } - - public override string GetPath() - { - return base.GetPath() + "/thread"; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = LoadFile("forum\\thread.html"); - return templatation(content); - } - } - - public class LogOut : ForumPage - { - public LogOut() : base(false) - { - - } - - public override string GetName() - { - return "Forum - Log Out"; - } - - public override string GetPath() - { - return base.GetPath() + "/logout"; - } - - public override Dictionary GetHeaders(IDictionary requestHeaders) - { - Plugin.Main.ManagerInstance.removeSession(requestHeaders["Cookie"].Split('=')[1]); - return new Dictionary() { { "Set-Cookie", "IW4MAdmin_ForumSession=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT" } }; - } - - public override string GetContent(NameValueCollection querySet, IDictionary headers) - { - string content = @""; - return templatation(content); - } - } - - public class RegisterJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_register"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - - var result = new ActionResponse(); - result.success = false; - result.destination = base.GetPath() + "/error"; - - try { - - string username = DNA.Text.TextEngine.Text(querySet["username"]); - string password = DNA.Text.TextEngine.Text(querySet["password"]); - string email = DNA.Text.TextEngine.Text(querySet["email"]); - - bool validEmail = Regex.IsMatch(email, - @"^(?("")("".+?(? Manager.USERNAME_MAXLENGTH) - throw new Exceptions.UserException("Username is too long"); - - if (password.Length > Manager.PASSWORD_MAXLENGTH) - throw new Exceptions.UserException("Password is too long"); - - byte[] passwordSalt = Encryption.PasswordHasher.GenerateSalt(); - string b64PasswordHash = Convert.ToBase64String(Encryption.PasswordHasher.ComputeHash(password, passwordSalt)); - - User registeringUser = new User(username, querySet["hiddenUsername"], email, b64PasswordHash, Convert.ToBase64String(passwordSalt), Plugin.Main.ManagerInstance.UserRank); - - currentSession = new Session(registeringUser, currentSession.sessionID); - var addUserResult = Plugin.Main.ManagerInstance.addUser(registeringUser, currentSession); - - if (addUserResult != Manager.ErrorCode.NO_ERROR) - { - result.errorCode = addUserResult; - } - - else - { - result.destination = base.GetPath() + "/home"; - result.success = true; - result.errorCode = Manager.ErrorCode.NO_ERROR; - } - } - - catch (Exception E) - { - //logme - result.errorCode = Manager.ErrorCode.USER_INVALID; - } - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(result); - return resp; - } - } - - public class userinfoJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_userinfo"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - - UserInfo info = new UserInfo(); - bool validUserSelection = true; - - try - { - int userid = Convert.ToInt32(querySet["id"]); - info.user = Plugin.Main.ManagerInstance.getUser(userid); - info.profile = Plugin.Main.ManagerInstance.getProfileSettings(userid); - } - - catch (FormatException) - { - // logme - validUserSelection = false; - } - - catch (Exceptions.UserException) - { - //logme - validUserSelection = false; - } - - if (!validUserSelection) - { - info.user = currentSession.sessionUser; - try - { - info.profile = Plugin.Main.ManagerInstance.getProfileSettings(info.user.id); - } - - catch (Exceptions.UserException) - { - //logme - } - } - - /*// this should not be a thing but ok... - Player matchedPlayer = Plugin.Main.stupidServer.clientDB.getPlayer(querySet["ip"]); - - if (matchedPlayer != null) - info.matchedUsername = matchedPlayer.Name;*/ - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(info); - return resp; - } - } - - public class updateUserJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_updateuser"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - var aResp = new ActionResponse(); - - bool passwordUpdateRequest = false; - - if (querySet["username"] == null || currentSession.sessionUser.id == 0) - aResp.errorCode = Manager.ErrorCode.USER_INVALID; - else if (querySet["bannercolor"] == null) - aResp.errorCode = Manager.ErrorCode.USER_BADPROFILEDATA; - if (querySet["updatedpassword"] != null && querySet["updatedpasswordrepeat"] != null && querySet["updatedpassword"].Length > 0 && querySet["updatedpasswordrepeat"].Length > 0) - passwordUpdateRequest = true; - - if (aResp.errorCode == Manager.ErrorCode.NO_ERROR) - { - string username = DNA.Text.TextEngine.Text(querySet["username"]); - string bannercolor = DNA.Text.TextEngine.Text(querySet["bannercolor"]); - string avatarURL = DNA.Text.TextEngine.Text(querySet["avatarurl"]); - string password = null; - - if (passwordUpdateRequest) - { - password = DNA.Text.TextEngine.Text(querySet["updatedpassword"]); - string passwordRepeat = DNA.Text.TextEngine.Text(querySet["updatedpasswordrepeat"]); - if (!password.Equals(passwordRepeat)) - { - password = null; - aResp.errorCode = Manager.ErrorCode.USER_MISMATCHEDPASSWORD; - } - - else if (password.Length > Manager.PASSWORD_MAXLENGTH) - { - password = null; - aResp.errorCode = Manager.ErrorCode.USER_PASSWORDTOOLONG; - } - } - - User existingUser = null; - try - { - existingUser = Plugin.Main.ManagerInstance.getUser(username); - } - - catch (Exceptions.UserException) - { - - } - - - if (existingUser != null && existingUser.id != currentSession.sessionUser.id) - aResp.errorCode = Manager.ErrorCode.USER_DUPLICATE; - else - { - var profile = Plugin.Main.ManagerInstance.getProfileSettings(currentSession.sessionUser.id); - if (username.Length <= Manager.USERNAME_MAXLENGTH) - currentSession.sessionUser.updateUsername(username); - else - aResp.errorCode = Manager.ErrorCode.USER_USERNAMETOOLONG; - currentSession.sessionUser.updateAvatar(avatarURL); - - if (passwordUpdateRequest && aResp.errorCode == Manager.ErrorCode.NO_ERROR) - { - byte[] passwordSalt = Encryption.PasswordHasher.GenerateSalt(); - string b64PasswordHash = Convert.ToBase64String(Encryption.PasswordHasher.ComputeHash(password, passwordSalt)); - currentSession.sessionUser.updatePassword(Convert.ToBase64String(passwordSalt), b64PasswordHash); - } - - Plugin.Main.ManagerInstance.updateUser(currentSession.sessionUser); - if (bannercolor.Length == 7) - profile.bannerColor = bannercolor; - Plugin.Main.ManagerInstance.updateUserProfile(profile); - - } - } - - aResp.success = aResp.errorCode == Manager.ErrorCode.NO_ERROR; - if (aResp.success) - aResp.destination = "usercp"; - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(aResp); - return resp; - } - } - - public class LoginJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_login"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - ActionResponse aResp = new ActionResponse(); - aResp.success = false; - - try - { - string username = DNA.Text.TextEngine.Text(querySet["username"]); - string password = DNA.Text.TextEngine.Text(querySet["password"]); - - var result = Plugin.Main.ManagerInstance.authorizeUser(username, password, currentSession.sessionID); - aResp.success = result == Manager.ErrorCode.NO_ERROR; - aResp.errorCode = result; - aResp.destination = "home"; - } - - catch (KeyNotFoundException) - { - aResp.errorCode = Manager.ErrorCode.USER_EMPTYCREDENTIALS; - } - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(aResp); - return resp; - } - } - - public class categoriesJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_categories"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - var categories = Plugin.Main.ManagerInstance.getAllCategories(); - - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(categories); - return resp; - } - } - - public class recentthreadsJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_recentthreads"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - - try - { - List threads = new List(); - var categories = Plugin.Main.ManagerInstance.getAllCategories(); - - foreach (var t in categories) - { - if ((t.permissions.Find(x => x.rankID == currentSession.sessionUser.ranking.id).actionable & Permission.Action.READ) != Permission.Action.READ) - continue; - - HomeThread thread = new HomeThread(); - thread.categoryTitle = t.title; - thread.categoryDescription = t.description; - thread.categoryID = t.id; - thread.recentThreads = Plugin.Main.ManagerInstance.getRecentThreads(t.id); - - threads.Add(thread); - } - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(threads); - } - catch (Exception e) - { - //logme - resp.content = ""; - } - - return resp; - } - } - - public class categorythreadsJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_categorythreads"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - var aResp = new ActionResponse(); - - try - { - var category = Plugin.Main.ManagerInstance.getCategory(Convert.ToInt32(querySet["id"])); - - if ((category.permissions.Find(x => x.rankID == currentSession.sessionUser.ranking.id).actionable & Permission.Action.READ) != Permission.Action.READ) - throw new Exceptions.PermissionException("User cannot view this category"); - - var categoryThreads = Plugin.Main.ManagerInstance.getCategoryThreads(category.id); - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(categoryThreads); - return resp; - } - - catch (FormatException) - { - //logme - aResp.errorCode = Manager.ErrorCode.CATEGORY_INVALID; - } - - catch (Exceptions.CategoryException) - { - //logme - aResp.errorCode = Manager.ErrorCode.CATEGORY_INVALID; - } - - catch (Exceptions.PermissionException) - { - aResp.errorCode = Manager.ErrorCode.GLOBAL_PERMISSIONDENIED; - } - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(aResp); - return resp; - } - } - - public class threadJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_thread"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - var aResp = new ActionResponse(); - aResp.success = false; - aResp.errorCode = Manager.ErrorCode.NO_ERROR; - - try - { - if (querySet.Get("id") != null) - { - var thread = Plugin.Main.ManagerInstance.getThread(Convert.ToInt32(querySet["id"])); - - if ((thread.threadCategory.permissions.Find(x => x.rankID == currentSession.sessionUser.ranking.id).actionable & Permission.Action.READ) != Permission.Action.READ) - throw new Exceptions.PermissionException("User cannot view this post"); - - var replies = Plugin.Main.ManagerInstance.getReplies(thread.id); - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(new ThreadView(thread, replies)); - aResp.success = true; - } - - else if (querySet.Get("replyid") != null) - { - var thread = Plugin.Main.ManagerInstance.getReply(Convert.ToInt32(querySet["replyid"])); - - //if ((thread.threadCategory.permissions.Find(x => x.rankID == currentSession.sessionUser.ranking.id).actionable & Permission.Action.READ) != Permission.Action.READ) - // throw new Exceptions.PermissionException("User cannot view this post"); - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(thread); - aResp.success = true; - } - } - - catch (FormatException) - { - aResp.errorCode = Manager.ErrorCode.THREAD_INVALID; - } - - catch (Exceptions.ThreadException) - { - aResp.errorCode = Manager.ErrorCode.THREAD_INVALID; - } - - catch (Exceptions.PermissionException) - { - aResp.errorCode = Manager.ErrorCode.GLOBAL_PERMISSIONDENIED; - } - - if (aResp.success == false) - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(aResp); - - return resp; - } - } - - public class editthreadJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_editthread"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - var aResp = new ActionResponse(); - aResp.success = false; - aResp.errorCode = Manager.ErrorCode.NO_ERROR; - - try - { - if (querySet.Get("id") != null) - { - var thread = Plugin.Main.ManagerInstance.getThread(Convert.ToInt32(querySet["id"])); - - if (thread.author.id != currentSession.sessionUser.id && (thread.threadCategory.permissions.Find(x => x.rankID == currentSession.sessionUser.ranking.id).actionable & Permission.Action.MODIFY) != Permission.Action.MODIFY) - throw new Exceptions.PermissionException("User cannot modify this post"); - - if (querySet.Get("delete") != null) - { - thread.visible = false; - aResp.errorCode = Plugin.Main.ManagerInstance.updateThread(thread); - aResp.success = aResp.errorCode == Manager.ErrorCode.NO_ERROR; - aResp.destination = "category?id=" + thread.threadCategory.id; - } - - else if (querySet.Get("update") != null) - { - if (querySet.Get("content") == null || querySet.Get("title") == null) - throw new Exceptions.ThreadException("Invalid update data"); - - if (querySet.Get("content").Length > Manager.CONTENT_MAXLENGTH) - { - aResp.errorCode = Manager.ErrorCode.THREAD_CONTENTTOOLONG; - } - - else if (querySet.Get("title").Length > Manager.TITLE_MAXLENGTH) - { - aResp.errorCode = Manager.ErrorCode.THREAD_TITLETOOLONG; - } - - else - { - //fixsecurity - var fmtr = new DNA.Text.BBCodeFormatter(); - string content = fmtr.Format(Uri.UnescapeDataString(querySet["content"])); - string title = DNA.Text.TextEngine.Text(Uri.UnescapeDataString(querySet["title"])); - - if (thread.updateTitle(title) && thread.updateContent(content)) - { - aResp.errorCode = Plugin.Main.ManagerInstance.updateThread(thread); - aResp.success = aResp.errorCode == Manager.ErrorCode.NO_ERROR; - aResp.destination = "thread?id=" + thread.id; - } - else - aResp.errorCode = Manager.ErrorCode.THREAD_EMPTYDATA; - } - } - } - - else if (querySet.Get("replyid") != null) - { - var reply = Plugin.Main.ManagerInstance.getReply(Convert.ToInt32(querySet["replyid"])); - - if (currentSession.sessionUser.id == 0 || reply.author.id != currentSession.sessionUser.id && (reply.threadCategory.permissions.Find(x => x.rankID == currentSession.sessionUser.ranking.id).actionable & Permission.Action.MODIFY) != Permission.Action.MODIFY) - throw new Exceptions.PermissionException("User cannot modify this reply"); - - if (querySet.Get("delete") != null) - { - reply.visible = false; - aResp.errorCode = Plugin.Main.ManagerInstance.updateReply(reply); - aResp.success = aResp.errorCode == Manager.ErrorCode.NO_ERROR; - aResp.destination = "thread?id=" + reply.threadid; - } - - else if (querySet.Get("content") != null) - { - if (querySet.Get("content") == null || querySet.Get("title") == null) - throw new Exceptions.ThreadException("Invalid update data"); - - if (querySet.Get("content").Length > Manager.CONTENT_MAXLENGTH) - { - aResp.errorCode = Manager.ErrorCode.THREAD_CONTENTTOOLONG; - } - - else if (querySet.Get("title").Length > Manager.TITLE_MAXLENGTH) - { - aResp.errorCode = Manager.ErrorCode.THREAD_TITLETOOLONG; - } - - else - { - int threadID = Convert.ToInt32(querySet["threadid"]); - //fixsecurity - var fmtr = new DNA.Text.BBCodeFormatter(); - string content = fmtr.Format(Uri.UnescapeDataString(querySet["content"])); - string title = DNA.Text.TextEngine.Text(Uri.UnescapeDataString(querySet["title"])); - - if (reply.updateTitle(title) && reply.updateContent(content)) - { - aResp.errorCode = Plugin.Main.ManagerInstance.updateReply(reply); - aResp.success = aResp.errorCode == Manager.ErrorCode.NO_ERROR; - aResp.destination = "thread?id=" + threadID; - } - else - aResp.errorCode = Manager.ErrorCode.THREAD_EMPTYDATA; - } - } - - } - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(aResp); - } - - catch (FormatException) - { - aResp.errorCode = Manager.ErrorCode.THREAD_INVALID; - } - - catch (Exceptions.ThreadException) - { - aResp.errorCode = Manager.ErrorCode.THREAD_INVALID; - } - - catch (Exceptions.PermissionException) - { - aResp.errorCode = Manager.ErrorCode.GLOBAL_PERMISSIONDENIED; - } - - if (aResp.success == false) - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(aResp); - - return resp; - } - } - - public class postthreadJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_postthread"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - ActionResponse aResp = new ActionResponse(); - - if (currentSession.sessionUser.ranking.equivalentRank < Player.Permission.Trusted) - { - aResp.errorCode = Manager.ErrorCode.USER_NOTAUTHORIZED; - } - - else - { - try - { - if (querySet["content"].Length < Manager.CONTENT_MAXLENGTH && querySet["title"].Length <= Manager.TITLE_MAXLENGTH) - { - - var fmtr = new DNA.Text.BBCodeFormatter(); - string content = fmtr.Format(Uri.UnescapeDataString(querySet["content"])); - string title = DNA.Text.TextEngine.Text(Uri.UnescapeDataString(querySet["title"])); - - if (querySet.Get("threadid") != null) - { - var replyThread = Plugin.Main.ManagerInstance.getThread(Convert.ToInt32(querySet.Get("threadid"))); - var reply = new Post(title, replyThread.getID(), content, currentSession.sessionUser); - - aResp.errorCode = Plugin.Main.ManagerInstance.addPost(replyThread, reply); - aResp.destination = String.Format("thread?id={0}", replyThread.id); - aResp.success = aResp.errorCode == Manager.ErrorCode.NO_ERROR; - } - - else - { - Category threadCategory = Plugin.Main.ManagerInstance.getCategory(Convert.ToInt32(querySet["category"])); - - if ((threadCategory.permissions.Find(x => x.rankID == currentSession.sessionUser.ranking.id).actionable & Permission.Action.WRITE) == Permission.Action.WRITE) - { - ForumThread newThread = new ForumThread(title, content, currentSession.sessionUser, threadCategory); - - aResp.errorCode = Plugin.Main.ManagerInstance.addThread(newThread); - aResp.destination = String.Format("category?id={0}", threadCategory.id); - aResp.success = aResp.errorCode == Manager.ErrorCode.NO_ERROR; - } - - else - aResp.errorCode = Manager.ErrorCode.USER_NOTAUTHORIZED; - } - } - - else if (querySet["title"].Length > Manager.TITLE_MAXLENGTH) - aResp.errorCode = Manager.ErrorCode.THREAD_TITLETOOLONG; - else - aResp.errorCode = Manager.ErrorCode.THREAD_CONTENTTOOLONG; - } - - catch (Exceptions.ThreadException) - { - aResp.errorCode = Manager.ErrorCode.THREAD_BADDATA; - } - - catch (NullReferenceException) - { - //logme - aResp.errorCode = Manager.ErrorCode.THREAD_EMPTYDATA; - } - } - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(aResp); - return resp; - } - } - - public class StatsJSON : JSONPage - { - public override string GetPath() - { - return base.GetPath() + "/_stats"; - } - - public override HttpResponse GetPage(NameValueCollection querySet, IDictionary requestHeaders) - { - var resp = base.GetPage(querySet, requestHeaders); - StatView stats = new StatView(); - - stats.onlineUsers = new List(); - - foreach (Session s in Plugin.Main.ManagerInstance.getSessions()) - { - if (s.sessionUser.ranking.id > 0 && (DateTime.Now - s.sessionStartTime).TotalMinutes < 5 && s.sessionUser.username != "Guest") - stats.onlineUsers.Add(s.sessionUser); - } - stats.onlineUsers.OrderByDescending(x => x.ranking.equivalentRank); - - resp.content = Newtonsoft.Json.JsonConvert.SerializeObject(stats); - return resp; - } - } - - - protected struct StatView - { - public List onlineUsers; - } - - protected struct ActionResponse - { - public bool success; - public string destination; - public Manager.ErrorCode errorCode; - } - - protected struct HomeThread - { - public string categoryTitle; - public string categoryDescription; - public int categoryID; - public List recentThreads; - } - - protected struct ThreadView - { - public ForumThread Thread; - public List Replies; - - public ThreadView(ForumThread t, List r) - { - Thread = t; - Replies = r; - } - } - } -} \ No newline at end of file diff --git a/Plugins/MessageBoard/Identifiable.cs b/Plugins/MessageBoard/Identifiable.cs deleted file mode 100644 index 5cfb228be..000000000 --- a/Plugins/MessageBoard/Identifiable.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MessageBoard -{ - interface Identifiable - { - int getID(); - } -} diff --git a/Plugins/MessageBoard/MessageboardPlugin.csproj b/Plugins/MessageBoard/MessageboardPlugin.csproj deleted file mode 100644 index 315145846..000000000 --- a/Plugins/MessageBoard/MessageboardPlugin.csproj +++ /dev/null @@ -1,158 +0,0 @@ - - - - - Debug - AnyCPU - {E46C85BD-A99C-484E-BCCE-0F1831C5925E} - Library - Properties - MessageBoard - MessageboardPlugin - v4.5 - 512 - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - bin\Release-Stable\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - x86 - bin\x86\Debug\ - TRACE;DEBUG - - - x86 - bin\x86\Release\ - true - - - x86 - bin\x86\Release-Stable\ - true - - - - - - - - - - - - - - - - - ..\..\packages\CodeKicker.BBCode.5.0.0.0\lib\net35\CodeKicker.BBCode.dll - - - ..\..\packages\CryptSharp.1.2.0.1\lib\net35\CryptSharp.dll - - - ..\..\packages\DNA.Text.2.1.1.10633\lib\DNA.Text.dll - - - ..\..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll - - - - - ..\..\Admin\lib\System.Data.SQLite.dll - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - - - - {d51eeceb-438a-47da-870f-7d7b41bc24d6} - SharedLibrary - False - - - - - mkdir "$(SolutionDir)Admin\bin\$(ConfigurationName)\forum" - -xcopy /E /Y "$(TargetDir)forum" "$(SolutionDir)Admin\bin\$(ConfigurationName)\forum" - -copy /Y "$(TargetDir)DNA.Text.dll" "$(SolutionDir)Admin\bin\$(ConfigurationName)\lib\DNA.Text.dll" -copy /Y "$(TargetDir)CryptSharp.dll" "$(SolutionDir)Admin\bin\$(ConfigurationName)\lib\CryptSharp.dll" -copy /Y "$(TargetDir)CodeKicker.BBcode.dll" "$(SolutionDir)Admin\bin\$(ConfigurationName)\lib\CodeKicker.BBcode.dll" - -if $(ConfigurationName) == Debug copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)BUILD\plugins\" - - - \ No newline at end of file diff --git a/Plugins/MessageBoard/Plugin.cs b/Plugins/MessageBoard/Plugin.cs deleted file mode 100644 index ebdb9c545..000000000 --- a/Plugins/MessageBoard/Plugin.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using SharedLibrary; -using SharedLibrary.Interfaces; -using System.Threading.Tasks; - -namespace MessageBoard.Plugin -{ - public class Main : IPlugin - { - public static Forum.Manager ManagerInstance { get; private set; } - - public string Author - { - get - { - return "RaidMax"; - } - } - - public float Version - { - get - { - return 0.1f; - } - } - - public string Name - { - get - { - return "Message Board Plugin"; - } - } - - public async Task OnLoadAsync(IManager manager) - { - ManagerInstance = new Forum.Manager(); - ManagerInstance.Start(); - } - - public async Task OnUnloadAsync() - { - ManagerInstance.Stop(); - } - - public async Task OnTickAsync(Server S) - { - return; - } - - public async Task OnEventAsync(Event E, Server S) - { - } - } -} diff --git a/Plugins/MessageBoard/Rank.cs b/Plugins/MessageBoard/Rank.cs deleted file mode 100644 index c438f68bb..000000000 --- a/Plugins/MessageBoard/Rank.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using SharedLibrary.Objects; - -namespace MessageBoard -{ - public class Rank : Identifiable - { - public string name; - public Player.Permission equivalentRank; - public int id; - - /// - /// Initial creation - /// - /// - /// - /// - public Rank(string name, Player.Permission equivalentRank) - { - this.name = name; - this.equivalentRank = equivalentRank; - id = 0; - } - - public Rank(int id, string name, Player.Permission equivalentRank) - { - this.name = name; - this.equivalentRank = equivalentRank; - this.id = id; - } - - public int getID() - { - return id; - } - } - - public class Permission - { - [Flags] - public enum Action - { - NONE = 0x0, - READ = 0x1, - WRITE = 0x2, - MODIFY = 0x4, - DELETE = 0x8 - } - - public int rankID; - public Action actionable; - - public Permission(int rankID, Action actionable) - { - this.rankID = rankID; - this.actionable = actionable; - } - } -} diff --git a/Plugins/MessageBoard/Session.cs b/Plugins/MessageBoard/Session.cs deleted file mode 100644 index 91396bfbd..000000000 --- a/Plugins/MessageBoard/Session.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MessageBoard -{ - public class Session - { - public User sessionUser; - public string sessionID { get; private set; } - public DateTime sessionStartTime; - - public Session(User sessionUser, string sessionID) - { - this.sessionUser = sessionUser; - this.sessionID = sessionID; - sessionStartTime = DateTime.Now; - } - - } -} diff --git a/Plugins/MessageBoard/Storage.cs b/Plugins/MessageBoard/Storage.cs deleted file mode 100644 index 7d89c6fc8..000000000 --- a/Plugins/MessageBoard/Storage.cs +++ /dev/null @@ -1,623 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Data; - -namespace MessageBoard.Storage -{ - class Database : SharedLibrary._Database - { - public Database(String FN, SharedLibrary.Interfaces.ILogger logger) : base(FN, logger) { } - - public override void Init() - { - if (!System.IO.File.Exists(FileName)) - { - string createClientTable = @"CREATE TABLE IF NOT EXISTS [USERS] ( - [id] INTEGER PRIMARY KEY AUTOINCREMENT, - [ranking] INTEGER DEFAULT 0, - [username] TEXT COLLATE NOCASE NOT NULL, - [email] TEXT NOT NULL, - [passwordhash] TEXT NOT NULL, - [passwordsalt] TEXT NOT NULL, - [lastlogin] TEXT NOT NULL, - [creationdate] TEXT NOT NULL, - [subscribedthreads] TEXT DEFAULT 0, - [avatarurl] TEXT - );"; - - string createSessionTable = @"CREATE TABLE IF NOT EXISTS [SESSIONS] ( - [sessionid] TEXT NOT NULL, - [sessionuserid] INTEGER NOT NULL, - FOREIGN KEY(sessionuserid) REFERENCES USERS(id) - );"; - - string createRankingTable = @"CREATE TABLE IF NOT EXISTS [RANKS] ( - [id] INTEGER PRIMARY KEY AUTOINCREMENT, - [name] TEXT UNIQUE NOT NULL, - [equivalentrank] INTEGER DEFAULT 0 - );"; - - string createCategoryTable = @"CREATE TABLE IF NOT EXISTS [CATEGORIES] ( - [id] INTEGER PRIMARY KEY AUTOINCREMENT, - [title] TEXT NOT NULL, - [description] TEXT NOT NULL, - [permissions] BLOB - );"; - - string createThreadTable = @"CREATE TABLE IF NOT EXISTS [THREADS] ( - [id] INTEGER PRIMARY KEY AUTOINCREMENT, - [title] TEXT NOT NULL, - [categoryid] INTEGER NOT NULL, - [replies] INTEGER DEFAULT 0, - [authorid] INTEGER NOT NULL, - [creationdate] TEXT NOT NULL, - [updateddate] TEXT NOT NULL, - [content] TEXT NOT NULL, - [visible] INTEGER DEFAULT 1, - FOREIGN KEY(authorid) REFERENCES USERS(id), - FOREIGN KEY(categoryid) REFERENCES CATEGORIES(id) - );"; - - string createReplyTable = @"CREATE TABLE IF NOT EXISTS [REPLIES] ( - [id] INTEGER PRIMARY KEY AUTOINCREMENT, - [title] TEXT NOT NULL, - [authorid] INT NOT NULL, - [threadid] INT NOT NULL, - [creationdate] TEXT NOT NULL, - [updateddate] TEXT NOT NULL, - [content] TEXT NOT NULL, - [visible] INTEGER DEFAULT 1, - FOREIGN KEY(authorid) REFERENCES USERS(id), - FOREIGN KEY(threadid) REFERENCES THREADS(id) - );"; - - string createUserProfileTable = @"CREATE TABLE IF NOT EXISTS [PROFILES] ( - [id] INTEGER PRIMARY KEY AUTOINCREMENT, - [userid] INTEGER NOT NULL, - [showemail] INTEGER DEFAULT 1, - [bannercolor] TEXT DEFAULT '#ff6633', - [birthday] TEXT, - [showage] INTEGER DEFAULT 0 - );"; - - - ExecuteNonQuery(createClientTable); - ExecuteNonQuery(createSessionTable); - ExecuteNonQuery(createRankingTable); - ExecuteNonQuery(createCategoryTable); - ExecuteNonQuery(createThreadTable); - ExecuteNonQuery(createReplyTable); - ExecuteNonQuery(createUserProfileTable); - - Rank guestRank = new Rank(1, "Guest", SharedLibrary.Player.Permission.User); - Rank userRank = new Rank(2, "User", SharedLibrary.Player.Permission.Trusted); - Rank modRank = new Rank(3, "Moderator", SharedLibrary.Player.Permission.Moderator); - Rank adminRank = new Rank(4, "Administrator", SharedLibrary.Player.Permission.Owner); - - addRank(guestRank); - addRank(userRank); - addRank(modRank); - addRank(adminRank); - - List defaultCatPerms = new List { - new Permission(guestRank.getID(), Permission.Action.READ), - new Permission(userRank.getID(), Permission.Action.READ | Permission.Action.WRITE), - new Permission(modRank.getID(), Permission.Action.READ | Permission.Action.WRITE | Permission.Action.MODIFY), - new Permission(adminRank.getID(), Permission.Action.READ | Permission.Action.WRITE | Permission.Action.MODIFY | Permission.Action.DELETE) - }; - - Category defaultCat = new Category(1, "Default Category", "This is the default category.", defaultCatPerms); - addCategory(defaultCat); - } - } - - #region SESSIONS - public Session getSession(string sessionID) - { - DataTable Result = GetDataTable("SESSIONS", new KeyValuePair("sessionid", sessionID)); - - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - int userID = Int32.Parse(ResponseRow["sessionuserid"].ToString()); - User sessionUser = getUser(userID); - - // this shouldn't happen.. but it might :c - if (sessionUser == null) - return null; - - Session foundSession = new Session(sessionUser, sessionID); - return foundSession; - } - - else - return null; - } - - public Session setSession(int userID, string sessionID) - { - // prevent duplicated tuples - if (getSession(sessionID) != null) - { - updateSession(sessionID, userID); - return getSession(sessionID); - } - - Dictionary newSession = new Dictionary(); - - newSession.Add("sessionid", sessionID); - newSession.Add("sessionuserid", userID); - - Insert("SESSIONS", newSession); - - return getSession(sessionID); - } - - public void removeSession(string sessionID) - { - ExecuteNonQuery(String.Format("DELETE FROM SESSIONS WHERE sessionid = '{0}'", sessionID)); - } - - public bool updateSession(string sessionID, int userID) - { - if (getSession(sessionID) == null) - return false; - - Dictionary updatedSession = new Dictionary(); - updatedSession.Add("sessionuserid", userID); - - Update("SESSIONS", updatedSession, new KeyValuePair("sessionid", sessionID)); - return true; - } - #endregion - - #region USERS - private User getUserFromDataTable(DataTable Result) - { - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - int id = Convert.ToInt32(ResponseRow["id"].ToString()); - string passwordHash = ResponseRow["passwordhash"].ToString(); - string passwordSalt = ResponseRow["passwordsalt"].ToString(); - string username = ResponseRow["username"].ToString(); - string email = ResponseRow["email"].ToString(); - DateTime lastLogon = DateTime.Parse(ResponseRow["lastlogin"].ToString()); - DateTime creationDate = DateTime.Parse(ResponseRow["creationdate"].ToString()); - Rank ranking = getRank(Convert.ToInt32(ResponseRow["ranking"])); - string avatarURL = ResponseRow["avatarurl"].ToString(); - string posts = GetDataTable(String.Format("select (select count(*) from THREADS where authorid = {0}) + (select count(*) from REPLIES where authorid = {0}) as posts;", id)).Rows[0]["posts"].ToString(); - - User foundUser = new User(id, passwordHash, passwordSalt, username, email, Convert.ToInt32(posts), lastLogon, creationDate, ranking, avatarURL); - return foundUser; - } - - return null; - } - - private Dictionary getDataTableFromUser(User addedUser) - { - Dictionary newUser = new Dictionary(); - - newUser.Add("username", addedUser.username); - newUser.Add("email", addedUser.email); - newUser.Add("passwordhash", addedUser.getPasswordHash()); - newUser.Add("passwordsalt", addedUser.getPasswordSalt()); - newUser.Add("lastlogin", SharedLibrary.Utilities.DateTimeSQLite(addedUser.lastLogin)); - newUser.Add("creationdate", SharedLibrary.Utilities.DateTimeSQLite(addedUser.creationDate)); - //newUser.Add("subscribedthreads", String.Join(",", addedUser.subscribedThreads)); - newUser.Add("ranking", addedUser.ranking.getID()); - newUser.Add("avatarurl", addedUser.avatarURL); - - return newUser; - } - - public User getUser(int userid) - { - DataTable Result = GetDataTable("USERS", new KeyValuePair("id", userid)); - - return getUserFromDataTable(Result); - } - - public User getUser(string username) - { - DataTable Result = GetDataTable("USERS", new KeyValuePair("username", username)); - - return getUserFromDataTable(Result); - } - - public bool userExists(string username, string email) - { - String Query = String.Format("SELECT * FROM USERS WHERE username = '{0}' or email = '{1}'", username, email); - DataTable Result = GetDataTable(Query); - - return Result.Rows.Count > 0; - } - - /// - /// Returns ID of added user - /// - /// - /// - /// - public User addUser(User addedUser, Session userSession) - { - var newUser = getDataTableFromUser(addedUser); - Insert("USERS", newUser); - - // fixme - User createdUser = getUser(addedUser.username); - return createdUser; - } - - public bool updateUser(User updatedUser) - { - var user = getDataTableFromUser(updatedUser); - Update("USERS", user, new KeyValuePair("id", updatedUser.getID())); - - return true; - } - - public int getNumUsers() - { - var Result = GetDataTable("SELECT COUNT(id) AS userCount FROM `USERS`;"); - return Convert.ToInt32(Result.Rows[0]["userCount"]); - } - #endregion - - #region CATEGORIES - private Category getCategoryFromDataTable(DataTable Result) - { - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - - int id = Convert.ToInt32(ResponseRow["id"]); - string title = ResponseRow["title"].ToString(); - string description = ResponseRow["description"].ToString(); - string permissions = Encoding.UTF8.GetString((byte[])ResponseRow["permissions"]); - List perms = Newtonsoft.Json.JsonConvert.DeserializeObject>(permissions); - - Category requestedCategory = new Category(id, title, description, perms); - return requestedCategory; - } - - return null; - } - - public void addCategory(Category addingCategory) - { - Dictionary newCategory = new Dictionary(); - - newCategory.Add("title", addingCategory.title); - newCategory.Add("description", addingCategory.description); - newCategory.Add("permissions", Newtonsoft.Json.JsonConvert.SerializeObject(addingCategory.permissions)); - - Insert("CATEGORIES", newCategory); - } - - public Category getCategory(int id) - { - string Query = String.Format("SELECT * FROM CATEGORIES WHERE id = {0}", id); - DataTable Result = GetDataTable(Query); - - return getCategoryFromDataTable(Result); - } - - public List getAllCategories() - { - string Query = String.Format("SELECT id FROM CATEGORIES"); - List cats = new List(); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - { - for (int i = 0; i < Result.Rows.Count; i++) - cats.Add(getCategory(Convert.ToInt32(Result.Rows[i]["id"]))); - } - - return cats; - } - #endregion - - #region THREADS - - public Dictionary getDataTableFromThread(ForumThread Thread) - { - Dictionary newThread = new Dictionary(); - newThread.Add("title", Thread.title); - newThread.Add("categoryid", Thread.threadCategory.getID()); - newThread.Add("replies", Thread.replies); - newThread.Add("authorid", Thread.author.getID()); - newThread.Add("creationdate", SharedLibrary.Utilities.DateTimeSQLite(Thread.creationDate)); - newThread.Add("updateddate", SharedLibrary.Utilities.DateTimeSQLite(Thread.updatedDate)); - newThread.Add("content", Thread.content); - newThread.Add("visible", Convert.ToInt32(Thread.visible)); - - return newThread; - } - - public int addThread(ForumThread Thread) - { - Insert("THREADS", getDataTableFromThread(Thread)); - return getThreadID(Thread.creationDate); - } - - - public bool updateThread(ForumThread updatedThread) - { - var user = getDataTableFromThread(updatedThread); - Update("THREADS", user, new KeyValuePair("id", updatedThread.getID())); - - return true; - } - - public ForumThread getThread(int id) - { - DataTable Result = GetDataTable("THREADS", new KeyValuePair("id", id)); - - return getThreadFromDataTable(Result); - } - - private ForumThread getThreadFromDataTable(DataTable Result) - { - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - int id = Convert.ToInt32(ResponseRow["id"].ToString()); - int categoryid = Convert.ToInt32(ResponseRow["categoryid"].ToString()); - int authorid = Convert.ToInt32(ResponseRow["authorid"].ToString()); - int replies = Convert.ToInt32(ResponseRow["replies"].ToString()); - string title = ResponseRow["title"].ToString(); - - var category = getCategory(categoryid); - var author = getUser(authorid); - - bool visible = Convert.ToBoolean((Convert.ToInt32(ResponseRow["visible"]))); - - DateTime creationDate = DateTime.Parse(ResponseRow["creationdate"].ToString()); - DateTime updatedDate = DateTime.Parse(ResponseRow["updateddate"].ToString()); - string content = ResponseRow["content"].ToString(); - - ForumThread retrievedThread = new ForumThread(id, title, visible, content, replies, author, category, creationDate, updatedDate); - return retrievedThread; - } - - return null; - } - - // we have no other unique id yet - private int getThreadID(DateTime creationDate) - { - string Query = String.Format("SELECT * FROM THREADS WHERE creationdate = \"{0}\"", SharedLibrary.Utilities.DateTimeSQLite(creationDate)); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - return Convert.ToInt32(Result.Rows[0]["id"].ToString()); - - return 0; - } - - public List getRecentThreads(int categoryID) - { - List threads = new List(); - string Query = String.Format("SELECT id FROM THREADS WHERE categoryid = {0} AND visible = 1 ORDER BY `updateddate` DESC LIMIT 3", categoryID); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - { - for (int i = 0; i < Result.Rows.Count; i++) - threads.Add(getThread(Convert.ToInt32(Result.Rows[i]["id"]))); - } - - return threads; - } - - public List getCategoryThreads(int categoryID) - { - List threads = new List(); - string Query = String.Format("SELECT id FROM THREADS WHERE categoryid = {0} and visible = 1 ORDER BY `updateddate` DESC", categoryID); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - { - for (int i = 0; i < Result.Rows.Count; i++) - threads.Add(getThread(Convert.ToInt32(Result.Rows[i]["id"]))); - } - - return threads; - } - #endregion - - #region RANKING - public int addRank(Rank newRank) - { - Dictionary rank = new Dictionary(); - rank.Add("name", newRank.name); - rank.Add("equivalentrank", (int)newRank.equivalentRank); - - Insert("RANKS", rank); - - Rank r = getRank(newRank.name); - - if (r == null) - return 0; - - return r.getID(); - } - - public Rank getRank(string rankName) - { - DataTable Result = GetDataTable("RANKS", new KeyValuePair("name", rankName)); - - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - string name = ResponseRow["name"].ToString(); - int equivRank = Convert.ToInt32(ResponseRow["equivalentrank"].ToString()); - int id = Convert.ToInt32(ResponseRow["id"].ToString()); - - Rank retrievedRank = new Rank(id, name, (SharedLibrary.Player.Permission)equivRank); - return retrievedRank; - } - - return null; - } - - public Rank getRank(int rankID) - { - DataTable Result = GetDataTable("RANKS", new KeyValuePair("id", rankID)); - - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - string name = ResponseRow["name"].ToString(); - int equivRank = Convert.ToInt32(ResponseRow["equivalentrank"].ToString()); - - Rank retrievedRank = new Rank(rankID, name, (SharedLibrary.Player.Permission)equivRank); - return retrievedRank; - } - - return null; - } - #endregion - - #region REPLIES - public int addReply(Post reply) - { - Insert("REPLIES", getDataTableFromReply(reply)); - return getReplyID(reply.creationDate); - } - - public bool updateReply(Post reply) - { - return Update("REPLIES", getDataTableFromReply(reply), new KeyValuePair("id", reply.id)); - } - - public Post getReply(int id) - { - DataTable Result = GetDataTable("REPLIES", new KeyValuePair("id", id)); - - return getReplyFromDataTable(Result); - } - - public List getRepliesFromThreadID(int threadID) - { - List replies = new List(); - //var Result = GetDataTable("REPLIES", new KeyValuePair("threadid", threadID)); - var Result = GetDataTable("SELECT * FROM REPLIES WHERE threadid = " + threadID + " AND visible = 1"); - - foreach (DataRow row in Result.Rows) - { - replies.Add(getReply(Convert.ToInt32(row["id"].ToString()))); - } - - return replies; - } - - private Dictionary getDataTableFromReply(Post reply) - { - Dictionary newReply = new Dictionary(); - newReply.Add("title", reply.title); - newReply.Add("authorid", reply.author.getID()); - newReply.Add("threadid", reply.threadid); - newReply.Add("creationdate", SharedLibrary.Utilities.DateTimeSQLite(reply.creationDate)); - newReply.Add("updateddate", SharedLibrary.Utilities.DateTimeSQLite(reply.updatedDate)); - newReply.Add("content", reply.content); - newReply.Add("visible", Convert.ToInt32(reply.visible)); - - return newReply; - } - - private Post getReplyFromDataTable(DataTable Result) - { - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - int id = Convert.ToInt32(ResponseRow["id"].ToString()); - int threadid = Convert.ToInt32(ResponseRow["threadid"].ToString()); - int authorid = Convert.ToInt32(ResponseRow["authorid"].ToString()); - string title = ResponseRow["title"].ToString(); - var author = getUser(authorid); - - DateTime creationDate = DateTime.Parse(ResponseRow["creationdate"].ToString()); - DateTime updatedDate = DateTime.Parse(ResponseRow["updateddate"].ToString()); - string content = ResponseRow["content"].ToString(); - - bool visible = Convert.ToBoolean((Convert.ToInt32(ResponseRow["visible"]))); - - Post retrievedPost = new Post(id, threadid, visible, title, content, author, creationDate, updatedDate); - return retrievedPost; - } - - return null; - } - - // we have no other unique id yet - private int getReplyID(DateTime creationDate) - { - DataTable Result = GetDataTable("REPLIES", new KeyValuePair("creationdate", SharedLibrary.Utilities.DateTimeSQLite(creationDate))); - - if (Result != null && Result.Rows.Count > 0) - return Convert.ToInt32(Result.Rows[0]["id"].ToString()); - - return 0; - } - #endregion - - #region PROFILES - private ProfileSettings getProfileFromDataTable(DataTable Result) - { - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - int id = Convert.ToInt32(ResponseRow["id"].ToString()); - int userID = Convert.ToInt32(ResponseRow["userid"].ToString()); - bool showEmail = Convert.ToBoolean(Convert.ToInt32(ResponseRow["showemail"].ToString())); - string bannerColor = ResponseRow["bannercolor"].ToString(); - DateTime birthday = DateTime.Parse(ResponseRow["birthday"].ToString()); - bool showAge = Convert.ToBoolean(Convert.ToInt32(ResponseRow["showage"].ToString())); - - ProfileSettings foundProfile = new ProfileSettings(id, userID, showEmail, bannerColor, birthday, showAge); - return foundProfile; - } - - return null; - } - - private Dictionary getDataTableFromProfile(ProfileSettings addedSettings) - { - Dictionary newSettings = new Dictionary(); - - if(addedSettings.id > 0) - newSettings.Add("id", addedSettings.id); - newSettings.Add("userid", addedSettings.userid); - newSettings.Add("showemail", Convert.ToInt32(addedSettings.showEmail)); - newSettings.Add("bannercolor", addedSettings.bannerColor); - newSettings.Add("birthday", SharedLibrary.Utilities.DateTimeSQLite(addedSettings.birthday)); - newSettings.Add("showage", Convert.ToInt32(addedSettings.showAge)); - - return newSettings; - } - - public ProfileSettings getProfileSettings(int userid) - { - DataTable Result = GetDataTable("PROFILES", new KeyValuePair("userid", userid)); - - return getProfileFromDataTable(Result); - } - - public bool addProfileSettings(ProfileSettings newProfile) - { - return Insert("PROFILES", getDataTableFromProfile(newProfile)); - } - - public bool updateProfileSettings(ProfileSettings updatedProfile) - { - return Update("PROFILES", getDataTableFromProfile(updatedProfile), new KeyValuePair("userid", updatedProfile.userid)); - } - - #endregion - } -} diff --git a/Plugins/MessageBoard/Thread.cs b/Plugins/MessageBoard/Thread.cs deleted file mode 100644 index e52172c61..000000000 --- a/Plugins/MessageBoard/Thread.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MessageBoard -{ - - public class Post : ForumThread - { - /// - /// Initial creation - /// - /// - /// - /// - /// - /// - - public int threadid; - - public Post(string title, int threadid, string content, User author) : base (title, content, author, null) - { - this.threadid = threadid; - } - - public Post(int id, int threadid, bool visible, string title, string content, User author, DateTime creationDate, DateTime updatedDate) : base(id, title, visible, content, 0, author, null, creationDate, updatedDate) - { - this.lastModificationString = SharedLibrary.Utilities.GetTimePassed(creationDate); - this.threadid = threadid; - } - - } - - - public class Category : Identifiable - { - public int id { get; private set; } - public string title { get; private set; } - public string description { get; private set; } - public List permissions { get; private set; } - - public Category(string title, string description) - { - this.title = title; - this.description = description; - this.permissions = new List(); - id = 0; - } - - public Category(int id, string title, string description, List permissions) - { - this.title = title; - this.description = description; - this.id = id; - this.permissions = permissions; - } - - public int getID() - { - return id; - } - } - - public class ForumThread : Identifiable - { - public string title { get; private set; } - public string content { get; private set; } - public string formattedContent { get; private set; } - public User author { get; private set; } - public Category threadCategory { get; private set; } - public DateTime creationDate { get; private set; } - public DateTime updatedDate; - public string lastModificationString { get; protected set; } - public int id { get; private set; } - public int replies; - public bool visible = true; - - /// - /// Initial creation - /// - /// - /// - /// - public ForumThread(string title, string content, User author, Category threadCategory) - { - if (content.Length == 0) - throw new Exceptions.ThreadException("Post is empty"); - if (author == null) - throw new Exceptions.ThreadException("No author of post"); - if (title.Length == 0) - throw new Exceptions.ThreadException("Title is empty"); - - this.title = title; - this.content = content; - this.author = author; - this.threadCategory = threadCategory; - creationDate = DateTime.Now; - updatedDate = DateTime.Now; - replies = 0; - id = 0; - } - - /// - /// Loading from database - /// - /// - /// - /// - /// - /// - public ForumThread(int id, string title, bool visible, string content, int replies, User author, Category threadCategory, DateTime creationDate, DateTime updatedDate) - { - this.id = id; - this.replies = replies; - this.title = title; - this.content = content; - this.formattedContent = CodeKicker.BBCode.BBCode.ToHtml(this.content); - this.author = author; - this.threadCategory = threadCategory; - this.creationDate = creationDate; - this.updatedDate = updatedDate; - this.lastModificationString = SharedLibrary.Utilities.GetTimePassed(updatedDate); - this.visible = visible; - } - - public int getID() - { - return id; - } - - public bool updateContent(string content) - { - if (content != null && content.Length > 0) - { - this.content = content; - return true; - } - - return false; - } - - public bool updateTitle(string title) - { - if (title != null && title.Length > 0) - { - this.title = title; - return true; - } - - return false; - } - } -} diff --git a/Plugins/MessageBoard/User.cs b/Plugins/MessageBoard/User.cs deleted file mode 100644 index 5a21741f7..000000000 --- a/Plugins/MessageBoard/User.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System; -using System.Collections.Generic; -using SharedLibrary; - -namespace MessageBoard -{ - public class User : Identifiable - { - private string passwordHash; // byte array -> b64 string - private string passwordSalt; // byte array -> b64 string - public DateTime lastLogin; - public string lastLoginString; - public readonly DateTime creationDate; - public int id { get; private set; } - public string avatarURL; - - public string username { get; private set; } - public string email { get; private set; } - public Rank ranking; - - public int posts; - public int privateMessages; - public int warnings; - - public List subscribedThreads { get; private set; } - - public User() - { - username = "Guest"; - ranking = Plugin.Main.ManagerInstance.guestRank; - } - - /// - /// When creating a new user - /// - /// - /// - /// - /// - /// - /// - /// - public User(string username, string matchedUsername, string email, string passwordHash, string passwordSalt, Rank ranking) - { - if (username.Length < 1) - throw new Exceptions.UserException("Username is empty"); - if (email.Length < 1) - throw new Exceptions.UserException("Email is empty"); - - lastLogin = DateTime.Now; - subscribedThreads = new List(); - - this.username = username; - this.email = email; - this.posts = 0; - this.privateMessages = 0; - this.warnings = 0; - this.ranking = ranking; - this.passwordHash = passwordHash; - this.passwordSalt = passwordSalt; - this.creationDate = DateTime.Now; - this.avatarURL = ""; - - id = 0; - } - - public User(int id, string passwordHash, string passwordSalt, string username, string email, int posts, DateTime lastLogin, DateTime creationDate, Rank ranking, string avatarURL) - { - this.id = id; - this.passwordHash = passwordHash; - this.passwordSalt = passwordSalt; - this.username = username; - this.email = email; - this.lastLogin = lastLogin; - this.creationDate = creationDate; - this.ranking = ranking; - this.avatarURL = avatarURL; - this.posts = posts; - - this.lastLoginString = SharedLibrary.Utilities.GetTimePassed(lastLogin); - } - - public int getID() - { - return this.id; - } - - public string getPasswordSalt() - { - return this.passwordSalt; - } - - public string getPasswordHash() - { - return this.passwordHash; - } - - public void updateUsername(string username) - { - if (username != null && username.Length > 0) - this.username = username; - } - - public void updateAvatar(string avatarURL) - { - this.avatarURL = avatarURL; - } - - public void updatePassword(string salt, string hash) - { - if (salt.Length > 0 && hash.Length > 0) - { - passwordHash = hash; - passwordSalt = salt; - } - } - } - - public class ProfileSettings - { - public int id { get; private set; } - public int userid { get; private set; } - public bool showEmail { get; private set; } - public string bannerColor; - public DateTime birthday { get; private set; } - public bool showAge { get; private set; } - - public ProfileSettings(int userid) - { - id = 0; - this.userid = userid; - showEmail = true; - showAge = true; - } - - public ProfileSettings(int id, int userid, bool showEmail, string bannerColor, DateTime birthday, bool showAge) - { - this.id = id; - this.userid = userid; - this.showEmail = showEmail; - this.bannerColor = bannerColor; - this.birthday = birthday; - this.showAge = showAge; - } - - public void hideEmail(bool shouldHide) - { - if (shouldHide) - showEmail = false; - else - showEmail = true; - } - - public void hideAge(bool shouldHide) - { - if (shouldHide) - showAge = false; - else - showAge = true; - } - } - - public struct UserInfo - { - public User user; - public ProfileSettings profile; - } -} diff --git a/Plugins/MessageBoard/app.config b/Plugins/MessageBoard/app.config deleted file mode 100644 index f95f0907c..000000000 --- a/Plugins/MessageBoard/app.config +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/Plugins/MessageBoard/forum/category.html b/Plugins/MessageBoard/forum/category.html deleted file mode 100644 index ea3137904..000000000 --- a/Plugins/MessageBoard/forum/category.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - Post - - - - - - - - - - - - - diff --git a/Plugins/MessageBoard/forum/home.html b/Plugins/MessageBoard/forum/home.html deleted file mode 100644 index 8f9511ee0..000000000 --- a/Plugins/MessageBoard/forum/home.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - Online Users - - - - - - - - diff --git a/Plugins/MessageBoard/forum/login.html b/Plugins/MessageBoard/forum/login.html deleted file mode 100644 index 0beeb644a..000000000 --- a/Plugins/MessageBoard/forum/login.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - Login - - - - - Username - - Password - - Register - - - - diff --git a/Plugins/MessageBoard/forum/postthread.html b/Plugins/MessageBoard/forum/postthread.html deleted file mode 100644 index 1ce18012e..000000000 --- a/Plugins/MessageBoard/forum/postthread.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - Post New Thread - - - - - - - - - - - - - - - - - - diff --git a/Plugins/MessageBoard/forum/register.html b/Plugins/MessageBoard/forum/register.html deleted file mode 100644 index 3560d26d4..000000000 --- a/Plugins/MessageBoard/forum/register.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Register - - - - - - - - - Username - - Password - - Verify Password - - Email - - - - - diff --git a/Plugins/MessageBoard/forum/thread.html b/Plugins/MessageBoard/forum/thread.html deleted file mode 100644 index c2bfe5d4a..000000000 --- a/Plugins/MessageBoard/forum/thread.html +++ /dev/null @@ -1,209 +0,0 @@ - - Home » - - - - - - - _ - _ - - - _ - - - Reply - - - - - - Edit - - _ - - - - - - - - - - - - - - - - - - diff --git a/Plugins/MessageBoard/forum/user.html b/Plugins/MessageBoard/forum/user.html deleted file mode 100644 index a289bb007..000000000 --- a/Plugins/MessageBoard/forum/user.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - _ - - - - _ - - - - _ - - - - _ - - - - _ - - - - - - - - - - -User Control Panel - - - diff --git a/Plugins/MessageBoard/forum/usercp.html b/Plugins/MessageBoard/forum/usercp.html deleted file mode 100644 index 2a521b138..000000000 --- a/Plugins/MessageBoard/forum/usercp.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - Username - - - - Banner Color - - - - - - New Password - - - - Repeat New Password - - - - - - - Avatar URL - - - - - diff --git a/Plugins/MessageBoard/packages.config b/Plugins/MessageBoard/packages.config deleted file mode 100644 index 46ebbfbe0..000000000 --- a/Plugins/MessageBoard/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Plugins/ProfanityDeterment/Configuration.cs b/Plugins/ProfanityDeterment/Configuration.cs new file mode 100644 index 000000000..2a807909a --- /dev/null +++ b/Plugins/ProfanityDeterment/Configuration.cs @@ -0,0 +1,36 @@ +using SharedLibrary.Interfaces; +using System; +using System.Collections.Generic; +using System.Text; +using SharedLibrary; + +namespace ProfanityDeterment +{ + class Configuration : IBaseConfiguration + { + public List OffensiveWords { get; set; } + public bool EnableProfanityDeterment { get; set; } + public string ProfanityWarningMessage { get; set; } + public string ProfanityKickMessage { get; set; } + public int KickAfterInfringementCount { get; set; } + + public IBaseConfiguration Generate() + { + OffensiveWords = new List() + { + "nigger", + "nigga", + "fuck" + }; + + EnableProfanityDeterment = Utilities.PromptBool("Enable profanity deterring"); + ProfanityWarningMessage = "Please do not use profanity on this server"; + ProfanityKickMessage = "Excessive use of profanity"; + KickAfterInfringementCount = 2; + + return this; + } + + public string Name() => "Configuration"; + } +} diff --git a/Plugins/ProfanityDeterment/Plugin.cs b/Plugins/ProfanityDeterment/Plugin.cs new file mode 100644 index 000000000..12966546a --- /dev/null +++ b/Plugins/ProfanityDeterment/Plugin.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Threading.Tasks; +using SharedLibrary; +using SharedLibrary.Configuration; +using SharedLibrary.Interfaces; + +namespace ProfanityDeterment +{ + public class Plugin : IPlugin + { + public string Name => "ProfanityFilter"; + + public float Version => 0.1f; + + public string Author => "RaidMax"; + + BaseConfigurationHandler Settings; + ConcurrentDictionary ProfanityCounts; + IManager Manager; + Task CompletedTask = Task.FromResult(false); + + public async Task OnEventAsync(Event E, Server S) + { + if (E.Type == Event.GType.Connect) + { + if (!ProfanityCounts.TryAdd(E.Origin.ClientId, new Tracking(E.Origin))) + { + S.Logger.WriteWarning("Could not add client to profanity tracking"); + } + + } + + if (E.Type == Event.GType.Disconnect) + { + if (!ProfanityCounts.TryRemove(E.Origin.ClientId, out Tracking old)) + { + S.Logger.WriteWarning("Could not remove client from profanity tracking"); + } + } + + if (E.Type == Event.GType.Say) + { + var objectionalWords = Settings.Configuration().OffensiveWords; + bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Data.ToLower().Contains(w)) != null; + + if (containsObjectionalWord) + { + var clientProfanity = ProfanityCounts[E.Origin.ClientId]; + if (clientProfanity.Infringements >= Settings.Configuration().KickAfterInfringementCount) + { + await clientProfanity.Client.Kick(Settings.Configuration().ProfanityKickMessage, new SharedLibrary.Objects.Player() + { + ClientId = 1 + }); + } + + else if (clientProfanity.Infringements < Settings.Configuration().KickAfterInfringementCount) + { + clientProfanity.Infringements++; + + await clientProfanity.Client.Warn(Settings.Configuration().ProfanityWarningMessage, new SharedLibrary.Objects.Player() + { + ClientId = 1 + }); + } + } + } + } + + public async Task OnLoadAsync(IManager manager) + { + // load custom configuration + Settings = new BaseConfigurationHandler("ProfanityDetermentSettings"); + if (Settings.Configuration() == null) + { + Settings.Set((Configuration)new Configuration().Generate()); + await Settings.Save(); + } + + ProfanityCounts = new ConcurrentDictionary(); + Manager = manager; + } + + public Task OnTickAsync(Server S) => CompletedTask; + + public Task OnUnloadAsync() => CompletedTask; + } +} diff --git a/Plugins/FastRestart/FastRestartPlugin.csproj b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj similarity index 79% rename from Plugins/FastRestart/FastRestartPlugin.csproj rename to Plugins/ProfanityDeterment/ProfanityDeterment.csproj index d7e6eb706..316a45359 100644 --- a/Plugins/FastRestart/FastRestartPlugin.csproj +++ b/Plugins/ProfanityDeterment/ProfanityDeterment.csproj @@ -4,12 +4,12 @@ Debug AnyCPU - {1479DE87-ACB5-4046-81C8-A0BA5041227D} + {3EA31029-C76F-4C8E-AFD4-79F77DEA7033} Library Properties - FastRestartPlugin - FastRestartPlugin - v4.5 + ProfanityDeterment + ProfanityDeterment + v4.5.2 512 @@ -21,7 +21,7 @@ prompt 4 - + pdbonly true bin\Release\ @@ -30,45 +30,44 @@ 4 - x86 + true bin\x86\Debug\ DEBUG;TRACE - - + full x86 - bin\x86\Release\ - true - - - bin\Release-Stable\ - TRACE - true - pdbonly - AnyCPU prompt MinimumRecommendedRules.ruleset - - bin\x86\Release-Stable\ + + bin\x86\Release\ + TRACE + true + pdbonly x86 - false + prompt + MinimumRecommendedRules.ruleset + + + + {d51eeceb-438a-47da-870f-7d7b41bc24d6} SharedLibrary + False diff --git a/Plugins/FastRestart/Properties/AssemblyInfo.cs b/Plugins/ProfanityDeterment/Properties/AssemblyInfo.cs similarity index 85% rename from Plugins/FastRestart/Properties/AssemblyInfo.cs rename to Plugins/ProfanityDeterment/Properties/AssemblyInfo.cs index 8ae88d4fc..8a75c3220 100644 --- a/Plugins/FastRestart/Properties/AssemblyInfo.cs +++ b/Plugins/ProfanityDeterment/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("FastRestartPlugin")] +[assembly: AssemblyTitle("ProfanityDeterment")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("FastRestartPlugin")] -[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyProduct("ProfanityDeterment")] +[assembly: AssemblyCopyright("Copyright © 2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -20,7 +20,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("1479de87-acb5-4046-81c8-a0ba5041227d")] +[assembly: Guid("3ea31029-c76f-4c8e-afd4-79f77dea7033")] // Version information for an assembly consists of the following four values: // diff --git a/Plugins/ProfanityDeterment/Tracking.cs b/Plugins/ProfanityDeterment/Tracking.cs new file mode 100644 index 000000000..becef1fe4 --- /dev/null +++ b/Plugins/ProfanityDeterment/Tracking.cs @@ -0,0 +1,19 @@ +using SharedLibrary.Objects; +using System; +using System.Collections.Generic; +using System.Text; + +namespace ProfanityDeterment +{ + class Tracking + { + public Player Client { get; private set; } + public int Infringements { get; set; } + + public Tracking(Player client) + { + Client = client; + Infringements = 0; + } + } +} diff --git a/Plugins/VoteMap/Plugin.cs b/Plugins/VoteMap/Plugin.cs deleted file mode 100644 index 83606c413..000000000 --- a/Plugins/VoteMap/Plugin.cs +++ /dev/null @@ -1,303 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -using SharedLibrary; -using SharedLibrary.Network; -using SharedLibrary.Interfaces; -using SharedLibrary.Objects; - -namespace Votemap_Plugin -{ - /// - /// Allow clients to vote for the next map at the end of a round - /// Map choices are defined in the server - /// - public class VoteMap : Command - { - public VoteMap() : base("vote", "vote for the next map", "v", Player.Permission.User, false, new CommandArgument[] - { - new CommandArgument() - { - Name = "map", - Required = true - } - }) - { } - - /// - /// Properties of Event E - /// Owner: The server the event came from - /// Origin: The player generating the event - /// Target: Optional target the player specified - /// Data: Chat message which triggered the command event - /// - /// This is the `say` event that comes from the server - public override async Task ExecuteAsync(Event E) - { - var voting = Vote.GetServerVotes(E.Owner.GetPort()); - - // we only want to allow a vote during a vote session - if (voting.voteInSession) - { - if (voting.ClientHasVoted(E.Origin.NetworkId.ToString())) - await E.Origin.Tell("You have already voted. Use ^5!vc ^7to ^5cancel ^7your vote"); - else - { - string mapSearch = E.Data.ToLower().Trim(); - // probably not the most optimized way to match the map.. but nothing is time critical here - Map votedMap = E.Owner.Maps.Find(m => (m.Alias.ToLower().Contains(mapSearch) || m.Name.Contains(mapSearch))); - if (votedMap == null) - await E.Origin.Tell("^1" + E.Data + " is not a recognized map"); - else - { - voting.CastClientVote(E.Origin.NetworkId.ToString(), votedMap); - await E.Origin.Tell("You voted for ^5" + votedMap.Alias); - } - } - } - - else - await E.Origin.Tell("There is no vote in session"); - } - } - - public class VoteCancel : Command - { - public VoteCancel() : base("votecancel", "cancel your vote for the next map", "vc", Player.Permission.User, false) { } - - public override async Task ExecuteAsync(Event E) - { - var voting = Vote.GetServerVotes(E.Owner.GetPort()); - - if (voting.voteInSession) - { - if (voting.ClientHasVoted(E.Origin.NetworkId.ToString())) - { - voting.CancelClientVote(E.Origin.NetworkId.ToString()); - await E.Origin.Tell("Vote cancelled"); - } - - else - { - await E.Origin.Tell("You have no vote to cancel"); - } - } - - else - await E.Origin.Tell("There is no vote in session"); - } - } - - public class Vote : IPlugin - { - public class VoteData - { - public string guid; - public Map map; - } - - public class MapResult - { - public Map map; - public int voteNum; - } - - public class ServerVoting - { - public int ServerId - { - get; private set; - } - public bool voteInSession; - public bool matchEnded; - public bool votePassed; - public bool waitForLoad; - public DateTime voteTimeStart; - public DateTime loadStartTime; - public List VoteList - { - get; private set; - } - - public ServerVoting(int id) - { - ServerId = id; - voteInSession = false; - votePassed = false; - matchEnded = false; - waitForLoad = true; - VoteList = new List(); - } - - public int GetTotalVotes() - { - return VoteList.Count; - } - - public bool ClientHasVoted(string guid) - { - return VoteList.Exists(x => (x.guid == guid)); - } - - public void CastClientVote(string guid, Map map) - { - var vote = new VoteData() - { - guid = guid, - map = map - }; - VoteList.Add(vote); - } - - public void CancelClientVote(string guid) - { - VoteList.RemoveAll(x => (x.guid == guid)); - } - - public MapResult GetTopVotedMap() - { - List results = new List(); - MapResult result = new MapResult() - { - map = new Map("Remain", "Remain"), - voteNum = 0 - }; - foreach (var vote in VoteList) - { - if (!results.Exists(x => (x.map.Name == vote.map.Name))) - { - MapResult newResult = new MapResult() - { - map = vote.map, - voteNum = 1 - }; - results.Add(newResult); - } - - else - { - var map = results.Find(x => x.map.Name == vote.map.Name); - map.voteNum += 1; - } - } - - foreach (var map in results) - if (map.voteNum > result.voteNum) - result = map; - - return result; - } - - } - - private static List serverVotingList; - public static int minVotes = 3; - - public string Author => "RaidMax"; - - public float Version => 1.0f; - - public string Name => "Votemap Plugin"; - - public async Task OnLoadAsync(IManager manager) - { - serverVotingList = new List(); - } - - public async Task OnUnloadAsync() - { - serverVotingList.Clear(); - } - - /// - /// The server monitor thread calls this about every 1 second - /// This is not high-precision, but will run 1 time per second - /// - /// - public async Task OnTickAsync(Server S) - { - var serverVotes = GetServerVotes(S.GetPort()); - - if (serverVotes != null) - { - - if ((DateTime.Now - serverVotes.loadStartTime).TotalSeconds < 30 /* || S.getPlayers().Count < 3*/) - return; - else - serverVotes.waitForLoad = false; - - // dvar that is set & updated by the game script... - serverVotes.matchEnded = (await S.GetDvarAsync("scr_gameended")).Value == 1; - - /* - Console.WriteLine("==========================="); - Console.WriteLine("Match ended->" + serverVotes.matchEnded); - Console.WriteLine("Vote in session->" + serverVotes.voteInSession); - Console.WriteLine("Vote passed->" + serverVotes.votePassed);*/ - - if (!serverVotes.voteInSession && serverVotes.matchEnded && serverVotes.voteTimeStart == DateTime.MinValue) - { - await S.Broadcast("Voting has started for the ^5next map"); - await S.Broadcast("Type ^5!v ^7to vote for the nextmap!"); - serverVotes.voteInSession = true; - serverVotes.voteTimeStart = DateTime.Now; - return; - } - - if (!serverVotes.voteInSession && serverVotes.votePassed && (DateTime.Now - serverVotes.voteTimeStart).TotalSeconds > 30) - { - await S.LoadMap(serverVotes.GetTopVotedMap().map.Name); - serverVotes.votePassed = false; - return; - } - - if (serverVotes.voteInSession) - { - if ((DateTime.Now - serverVotes.voteTimeStart).TotalSeconds > 25) - { - serverVotes.voteInSession = false; - - MapResult m = serverVotes.GetTopVotedMap(); - await S.Broadcast("Voting has ended!"); - - if (m.voteNum < minVotes && S.GetPlayersAsList().Count > 4) - await S.Broadcast("Vote map failed. At least ^5" + minVotes + " ^7people must choose the same map"); - else - { - await S.Broadcast(String.Format("Next map is ^5{0} ^7- [^2{1}/{2}^7] votes", m.map.Alias, m.voteNum, serverVotes.GetTotalVotes())); - serverVotes.votePassed = true; - } - } - } - } - } - - public async Task OnEventAsync(Event E, Server S) - { - if (E.Type == Event.GType.Start) - { - serverVotingList.Add(new ServerVoting(S.GetPort())); - } - - if (E.Type == Event.GType.Stop) - { - serverVotingList.RemoveAll(x => x.ServerId == S.GetPort()); - } - - if (E.Type == Event.GType.MapEnd || E.Type == Event.GType.MapChange) - { - var serverVotes = GetServerVotes(S.GetPort()); - serverVotes.VoteList.Clear(); - serverVotes.voteTimeStart = DateTime.MinValue; - serverVotes.loadStartTime = DateTime.Now; - serverVotes.waitForLoad = true; - } - } - - public static ServerVoting GetServerVotes(int serverID) - { - return serverVotingList.Find(x => (x.ServerId == serverID)); - } - } -} \ No newline at end of file diff --git a/Plugins/VoteMap/VotemapPlugin.csproj b/Plugins/VoteMap/VotemapPlugin.csproj deleted file mode 100644 index 247506d31..000000000 --- a/Plugins/VoteMap/VotemapPlugin.csproj +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Debug - AnyCPU - {428D8EB9-ECA3-4A66-AA59-3A944378C33F} - Library - Properties - Votemap_Plugin - VotemapPlugin - v4.5 - 512 - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - bin\Release-Stable\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - x86 - bin\x86\Debug\ - TRACE;DEBUG - - - x86 - bin\x86\Release\ - true - - - x86 - bin\x86\Release-Stable\ - true - - - - {d51eeceb-438a-47da-870f-7d7b41bc24d6} - SharedLibrary - False - - - - - - - - - - - if $(ConfigurationName) == Debug copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)BUILD\plugins\" - - - \ No newline at end of file diff --git a/SharedLibrary/Utilities.cs b/SharedLibrary/Utilities.cs index 0fec39441..3451f7e65 100644 --- a/SharedLibrary/Utilities.cs +++ b/SharedLibrary/Utilities.cs @@ -390,5 +390,11 @@ namespace SharedLibrary } public static bool IsPrivileged(this Player p) => p.Level > Player.Permission.User; + + public static bool PromptBool(string question) + { + Console.Write($"{question}? [y/n]: "); + return (Console.ReadLine().ToLower().FirstOrDefault() as char?) == 'y'; + } } } diff --git a/WebfrontCore/ViewComponents/ServerListViewComponent.cs b/WebfrontCore/ViewComponents/ServerListViewComponent.cs index 65e8694ac..1a9559eea 100644 --- a/WebfrontCore/ViewComponents/ServerListViewComponent.cs +++ b/WebfrontCore/ViewComponents/ServerListViewComponent.cs @@ -26,7 +26,8 @@ namespace WebfrontCore.ViewComponents .Select(p => new PlayerInfo() { Name = p.Name, - ClientId = p.ClientId + ClientId = p.ClientId, + Level = p.Level.ToString() }).ToList(), ChatHistory = s.ChatHistory.ToArray() }).ToList();