From b8c482e5a9b3937d5b4c59fbf856b90f083252a9 Mon Sep 17 00:00:00 2001 From: Madpeter <57852827+Madpeterz@users.noreply.github.com> Date: Fri, 28 Jun 2024 05:30:46 +0100 Subject: [PATCH] offline IM support --- LibreMetaverse/AgentManager.cs | 74 ++++++++++++-------- SecondBotEvents/Services/BotClientService.cs | 1 + SecondBotEvents/Services/DataStoreService.cs | 15 +++- 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/LibreMetaverse/AgentManager.cs b/LibreMetaverse/AgentManager.cs index dc659b5..e64fefd 100644 --- a/LibreMetaverse/AgentManager.cs +++ b/LibreMetaverse/AgentManager.cs @@ -39,6 +39,7 @@ using OpenMetaverse.Interfaces; using OpenMetaverse.Messages.Linden; using System.Net.Http; using System.Threading.Tasks; +using System.Collections; namespace OpenMetaverse { @@ -3976,44 +3977,61 @@ namespace OpenMetaverse if (m_InstantMessage == null) { return; } // don't bother if we don't have any listeners OSD result = OSDParser.Deserialize(data); - if (!(result is OSDMap respMap) || respMap.Count == 0 || respMap.ContainsKey("messages")) + if (result == null) { - Logger.Log("Failed to retrieve offline messages because the capability returned invalid shiz.", - Helpers.LogLevel.Warning); + Logger.Log("Failed to decode offline messages from data, trying legacy method (Null reply)", + Helpers.LogLevel.Warning); RetrieveInstantMessagesLegacy(); return; } - - if (respMap["messages"] is OSDArray msgArray) + if(result.Type != OSDType.Array) { - foreach (var osd in msgArray) + Logger.Log("Failed to decode offline messages from data trying legacy method (Wrong unpack type expected array)", + Helpers.LogLevel.Warning); + RetrieveInstantMessagesLegacy(); + return; + } + try + { + OSDArray respMap = (OSDArray)result; + ArrayList listEntrys = respMap.ToArrayList(); + foreach(OSDArray listEntry in listEntrys) { - var msg = (OSDMap)osd; + foreach(OSDMap msg in listEntry) + { - InstantMessage message; - message.FromAgentID = msg["from_agent_id"].AsUUID(); - message.FromAgentName = msg["from_agent_name"].AsString(); - message.ToAgentID = msg["to_agent_id"].AsUUID(); - message.RegionID = msg["region_id"].AsUUID(); - message.Dialog = (InstantMessageDialog)msg["dialog"].AsInteger(); - message.IMSessionID = msg["transaction-id"].AsUUID(); - message.Timestamp = new DateTime(msg["timestamp"].AsInteger()); - message.Message = msg["message"].AsString(); - message.Offline = msg.ContainsKey("offline") - ? (InstantMessageOnline)msg["offline"].AsInteger() - : InstantMessageOnline.Offline; - message.ParentEstateID = msg.ContainsKey("parent_estate_id") - ? msg["parent_estate_id"].AsUInteger() : 1; - message.Position = msg.ContainsKey("position") - ? msg["position"].AsVector3() - : new Vector3(msg["local_x"], msg["local_y"], msg["local_z"]); - message.BinaryBucket = msg.ContainsKey("binary_bucket") - ? msg["binary_bucket"].AsBinary() : new byte[] { 0 }; - message.GroupIM = msg.ContainsKey("from_group") && msg["from_group"].AsBoolean(); + InstantMessage message; + message.FromAgentID = msg["from_agent_id"].AsUUID(); + message.FromAgentName = msg["from_agent_name"].AsString(); + message.ToAgentID = msg["to_agent_id"].AsUUID(); + message.RegionID = msg["region_id"].AsUUID(); + message.Dialog = (InstantMessageDialog)msg["dialog"].AsInteger(); + message.IMSessionID = msg["transaction-id"].AsUUID(); + message.Timestamp = new DateTime(msg["timestamp"].AsInteger()); + message.Message = msg["message"].AsString(); + message.Offline = msg.ContainsKey("offline") + ? (InstantMessageOnline)msg["offline"].AsInteger() + : InstantMessageOnline.Offline; + message.ParentEstateID = msg.ContainsKey("parent_estate_id") + ? msg["parent_estate_id"].AsUInteger() : 1; + message.Position = msg.ContainsKey("position") + ? msg["position"].AsVector3() + : new Vector3(msg["local_x"], msg["local_y"], msg["local_z"]); + message.BinaryBucket = msg.ContainsKey("binary_bucket") + ? msg["binary_bucket"].AsBinary() : new byte[] { 0 }; + message.GroupIM = msg.ContainsKey("from_group") && msg["from_group"].AsBoolean(); - OnInstantMessage(new InstantMessageEventArgs(message, null)); + OnInstantMessage(new InstantMessageEventArgs(message, null)); + } } } + catch + { + Logger.Log("Failed to decode offline messages from data trying legacy method (Switch from OSD to OSDMap failed)", + Helpers.LogLevel.Warning); + RetrieveInstantMessagesLegacy(); + return; + } } /// diff --git a/SecondBotEvents/Services/BotClientService.cs b/SecondBotEvents/Services/BotClientService.cs index c3c1c3b..46da80a 100644 --- a/SecondBotEvents/Services/BotClientService.cs +++ b/SecondBotEvents/Services/BotClientService.cs @@ -175,6 +175,7 @@ namespace SecondBotEvents.Services client.Network.SimDisconnected += BotSimDisconnected; client.Network.LoginProgress += BotLoginStatus; } + public void Login() { ResetClient(); diff --git a/SecondBotEvents/Services/DataStoreService.cs b/SecondBotEvents/Services/DataStoreService.cs index a44aaa9..62bc1be 100644 --- a/SecondBotEvents/Services/DataStoreService.cs +++ b/SecondBotEvents/Services/DataStoreService.cs @@ -884,6 +884,7 @@ namespace SecondBotEvents.Services GetClient().Groups.GroupRoleDataReply += GroupRoles; GetClient().Estate.EstateBansReply += EstateBans; GetClient().Groups.RequestCurrentGroups(); + GetClient().Self.RetrieveInstantMessages(); } readonly string[] hard_blocked_agents = new[] { "secondlife", "second life" }; protected void ChatFromSim(object o, ChatEventArgs e) @@ -1015,6 +1016,7 @@ namespace SecondBotEvents.Services protected void ImEvent(object o, InstantMessageEventArgs e) { + switch(e.IM.Dialog) { case InstantMessageDialog.GroupNotice: @@ -1030,6 +1032,7 @@ namespace SecondBotEvents.Services case InstantMessageDialog.SessionSend: case InstantMessageDialog.MessageFromAgent: { + AddAvatar(e.IM.FromAgentID, e.IM.FromAgentName); if (groupsKey2Name.ContainsKey(e.IM.IMSessionID) == true) { // group IM @@ -1037,11 +1040,17 @@ namespace SecondBotEvents.Services RecordChat(e.IM.IMSessionID, e.IM.FromAgentName, e.IM.Message); break; } - AddAvatar(e.IM.FromAgentID, e.IM.FromAgentName); - OpenChatWindow(false, e.IM.IMSessionID, e.IM.FromAgentID); + UUID SessionID = e.IM.IMSessionID; + string message = e.IM.Message; + if (e.IM.Offline == InstantMessageOnline.Offline) + { + SessionID = UUID.Random(); + message = "{AV offline} " + message; + } + OpenChatWindow(false, SessionID, e.IM.FromAgentID); if (e.IM.FromAgentID != GetClient().Self.AgentID) { - RecordChat(e.IM.IMSessionID, e.IM.FromAgentName, e.IM.Message); + RecordChat(SessionID, e.IM.FromAgentName, e.IM.Message); } break; }