diff --git a/Content.Server/Chat/ChatManager.cs b/Content.Server/Chat/ChatManager.cs index 0339e0b741..e07d2a401e 100644 --- a/Content.Server/Chat/ChatManager.cs +++ b/Content.Server/Chat/ChatManager.cs @@ -1,7 +1,10 @@ using System.Linq; +using System.Net.Http; +using Content.Server.Interfaces; using Content.Server.Interfaces.Chat; using Content.Shared.Chat; using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Resources; @@ -19,6 +22,7 @@ namespace Content.Server.Chat #pragma warning disable 649 [Dependency] private readonly IServerNetManager _netManager; [Dependency] private readonly IPlayerManager _playerManager; + [Dependency] private readonly IMoMMILink _mommiLink; #pragma warning restore 649 public void Initialize() @@ -63,6 +67,17 @@ namespace Content.Server.Chat msg.Message = message; msg.MessageWrap = $"OOC: {player.SessionId}: {{0}}"; _netManager.ServerSendToAll(msg); + + _mommiLink.SendOOCMessage(player.SessionId.ToString(), message); + } + + public void SendHookOOC(string sender, string message) + { + var msg = _netManager.CreateNetMessage(); + msg.Channel = ChatChannel.OOC; + msg.Message = message; + msg.MessageWrap = $"OOC: (D){sender}: {{0}}"; + _netManager.ServerSendToAll(msg); } } } diff --git a/Content.Server/Content.Server.csproj b/Content.Server/Content.Server.csproj index 8ec12bac63..5fd73f4365 100644 --- a/Content.Server/Content.Server.csproj +++ b/Content.Server/Content.Server.csproj @@ -148,11 +148,13 @@ + + diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index f22666d7bc..885862d97a 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -56,6 +56,7 @@ namespace Content.Server public class EntryPoint : GameServer { private IGameTicker _gameTicker; + private IMoMMILink _mommiLink; private StatusShell _statusShell; /// @@ -160,6 +161,7 @@ namespace Content.Server IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); IoCManager.BuildGraph(); _gameTicker = IoCManager.Resolve(); @@ -167,6 +169,8 @@ namespace Content.Server IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); + _mommiLink = IoCManager.Resolve(); + var playerManager = IoCManager.Resolve(); _statusShell = new StatusShell(); @@ -184,6 +188,7 @@ namespace Content.Server base.Update(level, frameTime); _gameTicker.Update(new FrameEventArgs(frameTime)); + } } } diff --git a/Content.Server/Interfaces/Chat/IChatManager.cs b/Content.Server/Interfaces/Chat/IChatManager.cs index 7d263ed741..a853a1f876 100644 --- a/Content.Server/Interfaces/Chat/IChatManager.cs +++ b/Content.Server/Interfaces/Chat/IChatManager.cs @@ -17,5 +17,7 @@ namespace Content.Server.Interfaces.Chat void EntitySay(IEntity source, string message); void SendOOC(IPlayerSession player, string message); + + void SendHookOOC(string sender, string message); } } diff --git a/Content.Server/Interfaces/IMoMMILink.cs b/Content.Server/Interfaces/IMoMMILink.cs new file mode 100644 index 0000000000..3ce30a4fa9 --- /dev/null +++ b/Content.Server/Interfaces/IMoMMILink.cs @@ -0,0 +1,7 @@ +namespace Content.Server.Interfaces +{ + public interface IMoMMILink + { + void SendOOCMessage(string sender, string message); + } +} diff --git a/Content.Server/MoMMILink.cs b/Content.Server/MoMMILink.cs new file mode 100644 index 0000000000..1eecfc0864 --- /dev/null +++ b/Content.Server/MoMMILink.cs @@ -0,0 +1,154 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Content.Server.Interfaces; +using Content.Server.Interfaces.Chat; +using Newtonsoft.Json; +using Robust.Server.Interfaces.ServerStatus; +using Robust.Server.ServerStatus; +using Robust.Shared.Asynchronous; +using Robust.Shared.Interfaces.Configuration; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Utility; + +namespace Content.Server +{ + internal sealed class MoMMILink : IMoMMILink, IPostInjectInit + { +#pragma warning disable 649 + [Dependency] private readonly IConfigurationManager _configurationManager; + [Dependency] private readonly IStatusHost _statusHost; + [Dependency] private readonly IChatManager _chatManager; + [Dependency] private readonly ITaskManager _taskManager; +#pragma warning restore 649 + + private readonly HttpClient _httpClient = new HttpClient(); + + void IPostInjectInit.PostInject() + { + _configurationManager.RegisterCVar("status.mommiurl", null); + _configurationManager.RegisterCVar("status.mommipassword", null); + + _statusHost.AddHandler(_handleChatPost); + } + + public async void SendOOCMessage(string sender, string message) + { + var sentMessage = new MoMMIMessageOOC + { + Sender = sender, + Contents = message + }; + + await _sendMessageInternal("ooc", sentMessage); + } + + private async Task _sendMessageInternal(string type, object messageObject) + { + var url = _configurationManager.GetCVar("status.mommiurl"); + var password = _configurationManager.GetCVar("status.mommipassword"); + if (string.IsNullOrWhiteSpace(url)) + { + return; + } + + if (string.IsNullOrWhiteSpace(password)) + { + Logger.WarningS("mommi", "MoMMI URL specified but not password!"); + return; + } + + var sentMessage = new MoMMIMessageBase + { + Password = password, + Type = type, + Contents = messageObject + }; + + var jsonMessage = JsonConvert.SerializeObject(sentMessage); + var request = + await _httpClient.PostAsync(url, new StringContent(jsonMessage, Encoding.UTF8, "application/json")); + + if (!request.IsSuccessStatusCode) + { + throw new Exception($"MoMMI returned bad status code: {request.StatusCode}"); + } + } + + private bool _handleChatPost(HttpMethod method, HttpListenerRequest request, HttpListenerResponse response) + { + if (method != HttpMethod.Post || request.Url.AbsolutePath != "/ooc") + { + return false; + } + + var password = _configurationManager.GetCVar("status.mommipassword"); + OOCPostMessage message; + + using (var streamReader = new StreamReader(request.InputStream, EncodingHelpers.UTF8)) + using (var jsonReader = new JsonTextReader(streamReader)) + { + var serializer = new JsonSerializer(); + try + { + message = serializer.Deserialize(jsonReader); + } + catch (JsonSerializationException) + { + response.Respond(method, "400 Bad Request", HttpStatusCode.BadRequest, "text/plain"); + return true; + } + } + + if (message == null) + { + response.Respond(method, "400 Bad Request", HttpStatusCode.BadRequest, "text/plain"); + return true; + } + + if (message.Password != password) + { + response.Respond(method, "Incorrect password", HttpStatusCode.Forbidden, "text/plain"); + return true; + } + + _taskManager.RunOnMainThread(() => _chatManager.SendHookOOC(message.Sender, message.Contents)); + + response.Respond(method, "Message received", HttpStatusCode.OK, "text/plain"); + + return false; + } + + [JsonObject(MemberSerialization.Fields)] + private class MoMMIMessageBase + { + [JsonProperty("password")] public string Password; + + [JsonProperty("type")] public string Type; + + [JsonProperty("contents")] public object Contents; + } + + [JsonObject(MemberSerialization.Fields)] + private class MoMMIMessageOOC + { + [JsonProperty("sender")] public string Sender; + + [JsonProperty("contents")] public string Contents; + } + + [JsonObject(MemberSerialization.Fields, ItemRequired = Required.Always)] + private class OOCPostMessage + { + [JsonProperty("password")] public string Password; + + [JsonProperty("sender")] public string Sender; + + [JsonProperty("contents")] public string Contents; + } + } +} diff --git a/RobustToolbox b/RobustToolbox index 25926a17b7..33480f5527 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 25926a17b72d7e53a99720e21ac5ceb722cf99c8 +Subproject commit 33480f552783bbe6ec88ce5ac32d7ef168e749bf