From f990f56bf0802a0273addbccb1c0becacbed6033 Mon Sep 17 00:00:00 2001 From: Madpeter <57852827+Madpeterz@users.noreply.github.com> Date: Tue, 24 Sep 2024 21:30:26 +0100 Subject: [PATCH] Revert "remove the events service replaced by on events" This reverts commit 3f1f717fb154db2d5f01376e5803b634de090e48. --- Dockerfile | 17 + SecondBotEvents/Config/EventsConfig.cs | 126 ++++++ SecondBotEvents/Services/EventsService.cs | 496 ++++++++++++++++++++++ 3 files changed, 639 insertions(+) create mode 100644 SecondBotEvents/Config/EventsConfig.cs create mode 100644 SecondBotEvents/Services/EventsService.cs diff --git a/Dockerfile b/Dockerfile index e5f14e3..e8af814 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,6 +53,23 @@ ENV basic_Username='' \ discord_ClientToken='' \ discord_AllowDiscordCommands='false' \ discord_hideChatterName='false' \ + events_Enabled='false' \ + events_GroupMemberJoins='false' \ + events_GroupMemberLeaves='false' \ + events_GroupMemberEventsGroupUUID='' \ + events_GuestEntersArea='false' \ + events_GuestLeavesArea='false' \ + events_GuestTrackingSimname='' \ + events_GuestTrackingParcelname='' \ + events_SimAlertMessage='false' \ + events_StatusMessage='false' \ + events_MoneyEvent='false' \ + events_ChangeSim='false' \ + events_ChangeParcel='false' \ + events_OutputChannel=-1 \ + events_OutputIMuuid='00000000-0000-0000-0000-000000000000' \ + events_OutputHttpURL='none' \ + events_OutputSecret='notset' \ homebound_Enabled='false' \ homebound_HomeSimSlUrl='' \ homebound_BackupSimSLUrl='' \ diff --git a/SecondBotEvents/Config/EventsConfig.cs b/SecondBotEvents/Config/EventsConfig.cs new file mode 100644 index 0000000..bd7a9f6 --- /dev/null +++ b/SecondBotEvents/Config/EventsConfig.cs @@ -0,0 +1,126 @@ +using OpenMetaverse; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SecondBotEvents.Config +{ + public class EventsConfig : Config + { + public EventsConfig(bool fromENV, string fromFolder = "") : base(fromENV, fromFolder) { } + protected override void MakeSettings() + { + filename = "events"; + settings.Add("Enabled"); + settings.Add("GroupMemberJoins"); + settings.Add("GroupMemberLeaves"); + settings.Add("GroupMemberEventsGroupUUID"); + + settings.Add("GuestEntersArea"); + settings.Add("GuestLeavesArea"); + settings.Add("GuestTrackingSimname"); + settings.Add("GuestTrackingParcelname"); + + + settings.Add("SimAlertMessage"); + settings.Add("StatusMessage"); + settings.Add("MoneyEvent"); + + + settings.Add("ChangeSim"); + settings.Add("ChangeParcel"); + + settings.Add("OutputChannel"); + settings.Add("OutputIMuuid"); + settings.Add("OutputHttpURL"); + settings.Add("OutputSecret"); + settings.Add("HideStatusOutput"); + } + + public string GetOutputSecret() + { + return ReadSettingAsString("OutputSecret", "donttellanyone"); + } + + public string GetGuestTrackingSimname() + { + return ReadSettingAsString("GuestTrackingSimname", "example"); + } + + public string GetGuestTrackingParcelname() + { + return ReadSettingAsString("GuestTrackingParcelname", "example"); + } + + public string GetGroupMemberEventsGroupUUID() + { + return ReadSettingAsString("GroupMemberEventsGroupUUID", UUID.Zero.ToString()); + } + + public string GetOutputHttpURL() + { + return ReadSettingAsString("OutputHttpURL", "n/a"); + } + + public string GetOutputIMuuid() + { + return ReadSettingAsString("OutputIMuuid", UUID.Zero.ToString()); + } + + public int GetOutputChannel() + { + return ReadSettingAsInt("OutputChannel", -1); + } + + public bool GetGroupMemberJoins() + { + return ReadSettingAsBool("GroupMemberJoins", true); + } + + public bool GetGroupMemberLeaves() + { + return ReadSettingAsBool("GroupMemberLeaves", true); + } + + public bool GetGuestEntersArea() + { + return ReadSettingAsBool("GuestEntersArea", true); + } + + public bool GetGuestLeavesArea() + { + return ReadSettingAsBool("GuestLeavesArea", true); + } + + public bool GetChangeSim() + { + return ReadSettingAsBool("ChangeSim", true); + } + + public bool GetChangeParcel() + { + return ReadSettingAsBool("ChangeParcel", true); + } + + public bool GetSimAlertMessage() + { + return ReadSettingAsBool("SimAlertMessage", true); + } + + public bool GetStatusMessage() + { + return ReadSettingAsBool("StatusMessage", true); + } + + public bool GetMoneyEvent() + { + return ReadSettingAsBool("MoneyEvent", true); + } + + public bool GetEnabled() + { + return ReadSettingAsBool("Enabled", false); + } + } + +} \ No newline at end of file diff --git a/SecondBotEvents/Services/EventsService.cs b/SecondBotEvents/Services/EventsService.cs new file mode 100644 index 0000000..85c71ac --- /dev/null +++ b/SecondBotEvents/Services/EventsService.cs @@ -0,0 +1,496 @@ +using OpenMetaverse; +using SecondBotEvents.Config; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using Newtonsoft.Json; +using System.Linq; +using Swan; +using RestSharp; + +namespace SecondBotEvents.Services +{ + public class EventsService : BotServices + { + protected new EventsConfig myConfig; + protected bool botConnected = false; + protected string lastSimName = ""; + protected UUID TrackGroupUUID = UUID.Zero; + protected List GroupMembers = new List(); + protected bool GroupLoaded = false; + protected List AvatarsOnSim = new List(); + protected bool GuestListLoaded = false; + protected string lastparcelname = ""; + protected UUID OutputAvatar = UUID.Zero; + protected long lastGroupMembershipUpdate = 0; + + + public void InventoryUpdateEvent(Dictionary detail) + { + if (InventoryEvents.ContainsKey(detail["itemtype"]) == true) + { + foreach(string A in InventoryEvents[detail["itemtype"]]) + { + string output = JsonConvert.SerializeObject(detail); + if(UUID.TryParse(A, out UUID OutputAvatar) == true) + { + if (OutputAvatar != UUID.Zero) + { + GetClient().Self.InstantMessage(OutputAvatar, output); + } + } + else if (A.StartsWith("http") == true) + { + long unixtime = SecondbotHelpers.UnixTimeNow(); + string token = SecondbotHelpers.GetSHA1(unixtime.ToString() + "EventService" + GetClient().Self.AgentID + output+master.CommandsService.myConfig.GetSharedSecret()); + var client = new RestClient(A); + var request = new RestRequest("Inventory/Update", Method.Post); + request.AddParameter("token", token); + request.AddParameter("unixtime", unixtime.ToString()); + request.AddParameter("method", "Inventory"); + request.AddParameter("action", "Update"); + request.AddParameter("botname", GetClient().Self.Name); + request.AddParameter("event", output); + request.AddHeader("content-type", "application/x-www-form-urlencoded"); + client.ExecutePostAsync(request); + } + else if (int.TryParse(A, out int chann) == true) + { + if (chann >= 0) + { + GetClient().Self.Chat(output, chann, ChatType.Normal); + } + } + + } + } + } + + Dictionary> InventoryEvents = new Dictionary>(); + public void AddInventoryEvent(string inventoryType, string outputTarget) + { + if(InventoryEvents.ContainsKey(inventoryType) == false) + { + InventoryEvents.Add(inventoryType, new List()); + } + if (InventoryEvents[inventoryType].Contains(outputTarget) == false) + { + InventoryEvents[inventoryType].Add(outputTarget); + } + } + + public EventsService(EventsSecondBot setMaster) : base(setMaster) + { + myConfig = new EventsConfig(master.fromEnv, master.fromFolder); + if(myConfig.GetEnabled() == false) + { + return; + } + if (UUID.TryParse(myConfig.GetOutputIMuuid(), out OutputAvatar) == false) + { + OutputAvatar = UUID.Zero; + } + if (UUID.TryParse(myConfig.GetGroupMemberEventsGroupUUID(), out TrackGroupUUID) == false) + { + TrackGroupUUID = UUID.Zero; + } + } + public override string Status() + { + if (myConfig == null) + { + return "No Config"; + } + else if (myConfig.GetHideStatusOutput() == true) + { + return "hidden"; + } + else if (myConfig.GetEnabled() == false) + { + return "- Not requested -"; + } + else if (botConnected == false) + { + return "Waiting for bot"; + } + TimedEvents(); + return "Active"; + } + + protected void BotClientRestart(object o, BotClientNotice e) + { + LogFormater.Info("Events service [Attached to new client]"); + GetClient().Network.LoggedOut += BotLoggedOut; + GetClient().Network.SimConnected += BotLoggedIn; + } + + protected void BotLoggedOut(object o, LoggedOutEventArgs e) + { + GetClient().Network.SimConnected += BotLoggedIn; + botConnected = false; + LogFormater.Info("Events service [Bot commands disabled]"); + removeEvents(); + } + + protected void BotLoggedIn(object o, SimConnectedEventArgs e) + { + GetClient().Network.SimConnected -= BotLoggedIn; + botConnected = true; + // attach events + GetClient().Self.MoneyBalanceReply += BotMoneyEvent; + GetClient().Network.SimChanged += BotChangedSim; + GetClient().Groups.GroupMembersReply += BotGroupMembers; + GetClient().Self.AlertMessage += BotAlertMessage; + } + + protected long lastAvUpdate = 0; + protected string avatarhash = ""; + protected void TrackAvatarsOnParcel() + { + if ((myConfig.GetGuestTrackingSimname() != GetClient().Network.CurrentSim.Name) || (myConfig.GetGuestTrackingParcelname() != lastparcelname)) + { + AvatarsOnSim = new List(); + GuestListLoaded = false; + return; + } + long dif = SecondbotHelpers.UnixTimeNow() - lastAvUpdate; + if(dif < 30) + { + // only check for changes every 30 secs + return; + } + lastAvUpdate = SecondbotHelpers.UnixTimeNow(); + + string hashstring = ""; + List avs = new List(); + foreach(Avatar A in GetClient().Network.CurrentSim.ObjectsAvatars.Copy().Values) + { + avs.Add(A.ID); + hashstring = hashstring+A.ID.ToString(); + } + string hash = SecondbotHelpers.GetSHA1(hashstring); + if (hash == avatarhash) + { + return; + } + avatarhash = hash; + + if (GuestListLoaded == true) + { + List joined = new List(); + List tracked = new List(); + foreach (UUID a in AvatarsOnSim) + { + tracked.Add(a); + } + foreach (UUID a in avs) + { + if (tracked.Contains(a) == true) + { + tracked.Remove(a); + continue; + } + joined.Add(a); + } + if ((tracked.Count > 0) || (joined.Count > 0)) + { + if ((tracked.Count > 0) && (myConfig.GetGuestLeavesArea() == true)) + { + foreach (UUID a in tracked) + { + GuestTrackingEvent(a, "exit"); + } + } + if ((joined.Count > 0) && (myConfig.GetGuestEntersArea() == true)) + { + foreach (UUID a in joined) + { + GuestTrackingEvent(a, "enter"); + } + } + } + } + AvatarsOnSim = avs; + GuestListLoaded = true; + } + protected void TimedEvents() + { + int localid = GetClient().Parcels.GetParcelLocalID(GetClient().Network.CurrentSim, GetClient().Self.SimPosition); + if (GetClient().Network.CurrentSim.Parcels.ContainsKey(localid) == false) + { + GetClient().Parcels.GetParcelLocalID(GetClient().Network.CurrentSim, GetClient().Self.SimPosition); + return; + } + if(lastparcelname != GetClient().Network.CurrentSim.Parcels[localid].Name) + { + BotChangedParcel(GetClient().Network.CurrentSim.Parcels[localid].Name); + } + TrackAvatarsOnParcel(); + if(TrackGroupUUID != UUID.Zero) + { + long dif = SecondbotHelpers.UnixTimeNow() - lastGroupMembershipUpdate; + if (dif > 120) + { + lastGroupMembershipUpdate = SecondbotHelpers.UnixTimeNow(); + GetClient().Groups.RequestGroupMembers(TrackGroupUUID); + } + } + } + + protected void removeEvents() + { + botConnected = false; + if (GetClient() != null) + { + GetClient().Self.MoneyBalanceReply -= BotMoneyEvent; + GetClient().Network.SimChanged -= BotChangedSim; + GetClient().Groups.GroupMembersReply -= BotGroupMembers; + GetClient().Self.AlertMessage -= BotAlertMessage; + } + } + + protected void PushEvent(string eventname, Dictionary args) + { + OnEvent e = new OnEvent( + GetClient().Self.AgentID.ToString(), + eventname, + args, + myConfig.GetOutputSecret() + ); + string output = JsonConvert.SerializeObject(e); + if(myConfig.GetOutputChannel() >= 0) + { + GetClient().Self.Chat(output, myConfig.GetOutputChannel(), ChatType.Normal); + } + if(OutputAvatar != UUID.Zero) + { + GetClient().Self.InstantMessage(OutputAvatar, output); + } + if(myConfig.GetOutputHttpURL() != null) + { + long unixtime = SecondbotHelpers.UnixTimeNow(); + string token = SecondbotHelpers.GetSHA1(unixtime.ToString() + "EventService" + GetClient().Self.AgentID + output + master.CommandsService.myConfig.GetSharedSecret()); + var client = new RestClient(myConfig.GetOutputHttpURL()); + var request = new RestRequest("Event/Service", Method.Post); + request.AddParameter("token", token); + request.AddParameter("unixtime", unixtime.ToString()); + request.AddParameter("method", "Dialog"); + request.AddParameter("action", "Relay"); + request.AddParameter("botname", GetClient().Self.Name); + request.AddParameter("event", output); + request.AddHeader("content-type", "application/x-www-form-urlencoded"); + client.ExecutePostAsync(request); + } + + } + + protected void BotAlertMessage(object senderm, AlertMessageEventArgs e) + { + if(myConfig.GetSimAlertMessage() == false) + { + return; + } + Dictionary args = new Dictionary(); + args.Add("Message", e.Message); + args.Add("NotificationId", e.NotificationId); + PushEvent("AlertMessage", args); + } + + protected void BotChangedParcel(string newparcelname) + { + if (myConfig.GetChangeParcel() == false) + { + return; + } + Dictionary args = new Dictionary(); + args.Add("oldparcel", lastparcelname); + args.Add("newparcel", newparcelname); + lastparcelname = newparcelname; + PushEvent("ChangedParcel", args); + } + + protected void BotStatusMessage(object sender, SystemStatusMessage e) + { + if((e.changed == false) || (myConfig.GetStatusMessage() == false)) + { + return; + } + Dictionary args = new Dictionary(); + args.Add("Message", e.message); + PushEvent("StatusMessage", args); + } + + protected void BotGroupMembers(object sender, GroupMembersReplyEventArgs e) + { + if(e.GroupID != TrackGroupUUID) + { + return; + } + if(GroupLoaded == true) + { + List joined = new List(); + List tracked = new List(); + foreach (UUID a in GroupMembers) + { + tracked.Add(a); + } + master.DataStoreService.GetAvatarNames(tracked); + foreach (UUID a in e.Members.Keys) + { + if(tracked.Contains(a) == true) + { + tracked.Remove(a); + continue; + } + joined.Add(a); + } + if((tracked.Count > 0) && (myConfig.GetGroupMemberLeaves() == true)) + { + foreach(UUID a in tracked) + { + GroupMembershipEvent(a, "leave"); + } + } + if ((joined.Count > 0) && (myConfig.GetGroupMemberJoins() == true)) + { + foreach (UUID a in joined) + { + GroupMembershipEvent(a, "join"); + } + } + } + + GroupMembers = new List(); + foreach (UUID a in e.Members.Keys) + { + GroupMembers.Add(a); + } + GroupLoaded = true; + } + + protected void GroupMembershipEvent(UUID avatar, string action) + { + Dictionary args = new Dictionary(); + args.Add("uuid", avatar.ToString()); + args.Add("name", master.DataStoreService.GetAvatarName(avatar)); + args.Add("action", action); + PushEvent("GroupMembership", args); + } + + protected void GuestTrackingEvent(UUID avatar, string action) + { + Dictionary args = new Dictionary(); + args.Add("uuid", avatar.ToString()); + args.Add("name", master.DataStoreService.GetAvatarName(avatar)); + args.Add("action", action); + PushEvent("GuestTracking", args); + } + + protected void BotChangedSim(object sender, SimChangedEventArgs e) + { + if(myConfig.GetChangeSim() == false) + { + return; + } + Dictionary args = new Dictionary(); + args.Add("lastsim", lastSimName); + args.Add("newsim", GetClient().Network.CurrentSim.Name); + PushEvent("ChangedSim", args); + lastSimName = e.PreviousSimulator.Name; + } + + protected void BotMoneyEvent(object sender, MoneyBalanceReplyEventArgs e) + { + if(myConfig.GetMoneyEvent() == false) + { + return; + } + Dictionary args = new Dictionary(); + args.Add("fromuuid", e.TransactionInfo.SourceID.ToString()); + args.Add("touuid", e.TransactionInfo.DestID.ToString()); + args.Add("amount", e.TransactionInfo.Amount.ToString()); + args.Add("balance", e.Balance.ToString()); + args.Add("fromname", master.DataStoreService.GetAvatarName(e.TransactionInfo.SourceID)); + args.Add("toname", master.DataStoreService.GetAvatarName(e.TransactionInfo.DestID)); + args.Add("transactionid", e.TransactionID.ToString()); + PushEvent("MoneyEvent", args); + } + + + + public override void Start(bool updateEnabled = false, bool setEnabledTo = false) + { + if (updateEnabled) + { + myConfig.setEnabled(setEnabledTo); + } + if (myConfig.GetEnabled() == false) + { + LogFormater.Info("Events service [Disabled]"); + return; + } + Stop(); + running = true; + master.BotClientNoticeEvent += BotClientRestart; + master.SystemStatusMessagesEvent += BotStatusMessage; + } + + public override void Stop() + { + if (myConfig.GetEnabled() == false) + { + return; + } + running = false; + master.BotClientNoticeEvent -= BotClientRestart; + master.SystemStatusMessagesEvent -= BotStatusMessage; + removeEvents(); + } + } + + public class OnEvent + { + public string EventName = ""; + public Dictionary Data = new Dictionary(); + public string Hash = ""; + public long Unixtime = 0; + public string BotUUID = ""; + + public OnEvent(string eventBotUUID, string setEventName, Dictionary eventData, string Secret) + { + BotUUID = eventBotUUID; + EventName = setEventName; + Data = eventData; + Unixtime = SecondbotHelpers.UnixTimeNow(); + SignEvent(Secret); + } + + public string getJson() + { + return ""; + } + + + + protected void SignEvent(string Secret) + { + string raw = BotUUID+ EventName; + foreach(string A in Data.Values) + { + raw = raw + A; + } + raw = raw + Unixtime.ToString() + Secret; + Hash = SecondbotHelpers.GetSHA1(raw); + } + } + + public class GuestUpdateEvent + { + public string parcelName = ""; + public string regionName = ""; + public string avatarName = ""; + public UUID avatarUUID = UUID.Zero; + public bool entered = false; + } +}