add support for rabbit message Q for the bot
This commit is contained in:
parent
c410412097
commit
5c69da371a
5 changed files with 398 additions and 1 deletions
13
Dockerfile
13
Dockerfile
|
|
@ -152,7 +152,18 @@ ENV basic_Username='' \
|
||||||
smtp_User='me@email.addr.tld' \
|
smtp_User='me@email.addr.tld' \
|
||||||
smtp_Token='none' \
|
smtp_Token='none' \
|
||||||
smtp_SendAlertsAndLoginsTo='me@somewhere.tld' \
|
smtp_SendAlertsAndLoginsTo='me@somewhere.tld' \
|
||||||
smtp_HideStatusOutput='false'
|
smtp_HideStatusOutput='false' \
|
||||||
|
rabbit_Enabled='false' \
|
||||||
|
rabbit_HideStatusOutput='false' \
|
||||||
|
rabbit_HostIP='127.0.0.1' \
|
||||||
|
rabbit_HostUsername='guest' \
|
||||||
|
rabbit_HostPassword='guest' \
|
||||||
|
rabbit_HostPort='5672' \
|
||||||
|
rabbit_NotecardQueue='notecards' \
|
||||||
|
rabbit_CommandQueue='commands' \
|
||||||
|
rabbit_ImQueue='ims' \
|
||||||
|
rabbit_GroupImQueue='groupims' \
|
||||||
|
rabbit_LogDebug='true'
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
ENV ASPNETCORE_URLS http://+:80
|
ENV ASPNETCORE_URLS http://+:80
|
||||||
|
|
|
||||||
72
SecondBotEvents/Config/RabbitConfig.cs
Normal file
72
SecondBotEvents/Config/RabbitConfig.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
using OpenMetaverse;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Config
|
||||||
|
{
|
||||||
|
public class RabbitConfig(bool fromENV, string fromFolder = "") : Config(fromENV, fromFolder)
|
||||||
|
{
|
||||||
|
protected override void MakeSettings()
|
||||||
|
{
|
||||||
|
filename = "rabbit";
|
||||||
|
settings.Add("Enabled");
|
||||||
|
settings.Add("HideStatusOutput");
|
||||||
|
settings.Add("HostIP");
|
||||||
|
settings.Add("HostPort");
|
||||||
|
settings.Add("HostUsername");
|
||||||
|
settings.Add("HostPassword");
|
||||||
|
settings.Add("NotecardQueue");
|
||||||
|
settings.Add("CommandQueue");
|
||||||
|
settings.Add("ImQueue");
|
||||||
|
settings.Add("GroupImQueue");
|
||||||
|
settings.Add("LogDebug");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetLogDebug()
|
||||||
|
{
|
||||||
|
return ReadSettingAsBool("LogDebug", true);
|
||||||
|
}
|
||||||
|
public bool GetEnabled()
|
||||||
|
{
|
||||||
|
return ReadSettingAsBool("Enabled", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetHostIP()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("HostIP", "127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetHostUsername()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("HostUsername", "guest");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetHostPassword()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("HostPassword", "guest");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHostPort()
|
||||||
|
{
|
||||||
|
return ReadSettingAsInt("HostPort", 5672);
|
||||||
|
}
|
||||||
|
public string GetNotecardQueue()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("NotecardQueue", "notecards");
|
||||||
|
}
|
||||||
|
public string GetCommandQueue()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("CommandQueue", "commands");
|
||||||
|
}
|
||||||
|
public string GetImQueue()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("ImQueue", "ims");
|
||||||
|
}
|
||||||
|
public string GetGroupImQueue()
|
||||||
|
{
|
||||||
|
return ReadSettingAsString("GroupImQueue", "groupims");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -41,6 +41,7 @@ namespace SecondBotEvents
|
||||||
public HomeboundService HomeboundService { get { return (HomeboundService)GetService("HomeboundService"); } }
|
public HomeboundService HomeboundService { get { return (HomeboundService)GetService("HomeboundService"); } }
|
||||||
public EventsService EventsService { get { return (EventsService)GetService("EventsService"); } }
|
public EventsService EventsService { get { return (EventsService)GetService("EventsService"); } }
|
||||||
public DialogService DialogService { get { return (DialogService)GetService("DialogService"); } }
|
public DialogService DialogService { get { return (DialogService)GetService("DialogService"); } }
|
||||||
|
public RabbitService RabbitService { get { return (RabbitService)GetService("RabbitService"); } }
|
||||||
|
|
||||||
public SmtpService SmtpService { get { return (SmtpService)GetService("SmtpService"); } }
|
public SmtpService SmtpService { get { return (SmtpService)GetService("SmtpService"); } }
|
||||||
|
|
||||||
|
|
@ -177,6 +178,7 @@ namespace SecondBotEvents
|
||||||
RegisterService("ChatGptService");
|
RegisterService("ChatGptService");
|
||||||
//RegisterService("RecoveryService");
|
//RegisterService("RecoveryService");
|
||||||
RegisterService("SmtpService");
|
RegisterService("SmtpService");
|
||||||
|
RegisterService("RabbitService");
|
||||||
if (BotClient.IsLoaded() == false)
|
if (BotClient.IsLoaded() == false)
|
||||||
{
|
{
|
||||||
LogFormater.Info("Config is not loaded :(");
|
LogFormater.Info("Config is not loaded :(");
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="NRedisStack" Version="0.13.1" />
|
<PackageReference Include="NRedisStack" Version="0.13.1" />
|
||||||
|
<PackageReference Include="RabbitMQ.Client" Version="7.1.2" />
|
||||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
311
SecondBotEvents/Services/RabbitService.cs
Normal file
311
SecondBotEvents/Services/RabbitService.cs
Normal file
|
|
@ -0,0 +1,311 @@
|
||||||
|
using SecondBotEvents.Config;
|
||||||
|
using RabbitMQ.Client;
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using RabbitMQ.Client.Events;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Swan;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace SecondBotEvents.Services
|
||||||
|
{
|
||||||
|
public class RabbitService : BotServices
|
||||||
|
{
|
||||||
|
protected async Task<Task> CommandMessageEvent(object o, BasicDeliverEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JsonCommandFormat result = JsonConvert.DeserializeObject<JsonCommandFormat>(Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
if (result == null || string.IsNullOrEmpty(result.CommandName))
|
||||||
|
{
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Command Message format is invalid or missing fields. " + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Info($"Command Message UUID: {result.CommandName}, args: {String.Join(",", result.commandArgs)}");
|
||||||
|
}
|
||||||
|
SignedCommand C = new(master.CommandsService, "rabbit", result.CommandName, "", result.commandArgs, 0, "", false, 0, "", false);
|
||||||
|
master.CommandsService.RunCommand("rabbit", C, false);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Command Message decode failed " + E.Message + " raw=" + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
protected async Task<Task> NotecardMessageEvent(object o, BasicDeliverEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JsonNotecardFormat result = JsonConvert.DeserializeObject<JsonNotecardFormat>(Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
if (
|
||||||
|
result == null ||
|
||||||
|
string.IsNullOrEmpty(result.Name) ||
|
||||||
|
string.IsNullOrEmpty(result.UUID) ||
|
||||||
|
string.IsNullOrEmpty(result.Content) ||
|
||||||
|
string.IsNullOrEmpty(result.Subject)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Notecard Message format is invalid or missing fields. " + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Info($"Notecard Message Name: {result.Name}, Subject: {result.Subject}");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(result.UUID, out UUID uuid) == false)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Notecard Message UUID is not valid: " + result.UUID);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
master.BotClient.SendNotecard(result.Name, result.Content, uuid, false, result.Subject);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Notecard Message decode failed " + E.Message + " raw=" + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
protected async Task<Task> ImMessageEvent(object o, BasicDeliverEventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Message received: " + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JsonMessageFormat result = JsonConvert.DeserializeObject<JsonMessageFormat>(Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
if (result == null || string.IsNullOrEmpty(result.UUID) || string.IsNullOrEmpty(result.Message))
|
||||||
|
{
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("IM Message format is invalid or missing fields. " + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Info($"IM Message UUID: {result.UUID}, Message: {result.Message}");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(result.UUID, out UUID uuid) == false)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("IM Message UUID is not valid: " + result.UUID);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
GetClient().Self.InstantMessage(uuid, result.Message);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("IM Message decode failed " + E.Message + " raw=" + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
protected async Task<Task> GroupMessageEvent(object o, BasicDeliverEventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Message received: " + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JsonMessageFormat result = JsonConvert.DeserializeObject<JsonMessageFormat>(Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
if (result == null || string.IsNullOrEmpty(result.UUID) || string.IsNullOrEmpty(result.Message))
|
||||||
|
{
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Group IM Message format is invalid or missing fields. " + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Info($"Group Message UUID: {result.UUID}, Message: {result.Message}");
|
||||||
|
}
|
||||||
|
if (UUID.TryParse(result.UUID, out UUID uuid) == false)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Group Message UUID is not valid: " + result.UUID);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
GetClient().Self.InstantMessageGroup(uuid, result.Message);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Group IM Message decode failed " + E.Message + " raw=" + Encoding.UTF8.GetString(e.Body.ToArray()));
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public new RabbitConfig myConfig = null;
|
||||||
|
protected bool hasSecondbot = false;
|
||||||
|
public RabbitService(EventsSecondBot setMaster) : base(setMaster)
|
||||||
|
{
|
||||||
|
myConfig = new RabbitConfig(master.fromEnv, master.fromFolder);
|
||||||
|
if (myConfig.GetEnabled() == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConnectionFactory factory;
|
||||||
|
IConnection connection;
|
||||||
|
Dictionary<string, IChannel> channels = new Dictionary<string, IChannel>();
|
||||||
|
public override void Start(bool updateEnabled = false, bool setEnabledTo = false)
|
||||||
|
{
|
||||||
|
if (updateEnabled == true)
|
||||||
|
{
|
||||||
|
myConfig.setEnabled(setEnabledTo);
|
||||||
|
}
|
||||||
|
if (myConfig.GetEnabled() == false)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogFormater.Info("Rabbit service [Starting]");
|
||||||
|
running = true;
|
||||||
|
master.BotClientNoticeEvent += BotClientRestart;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void connectService()
|
||||||
|
{
|
||||||
|
if (connection != null && connection.IsOpen == true)
|
||||||
|
{
|
||||||
|
connection.CloseAsync().Await();
|
||||||
|
connection = null;
|
||||||
|
}
|
||||||
|
var endpoints = new System.Collections.Generic.List<AmqpTcpEndpoint> {
|
||||||
|
new AmqpTcpEndpoint(myConfig.GetHostIP(),myConfig.GetHostPort()),
|
||||||
|
};
|
||||||
|
ConnectionFactory factory = new ConnectionFactory();
|
||||||
|
factory.UserName = myConfig.GetHostUsername();
|
||||||
|
factory.Password = myConfig.GetHostPassword();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = factory.CreateConnectionAsync(endpoints).Await();
|
||||||
|
if (connection == null || connection.IsOpen == false)
|
||||||
|
{
|
||||||
|
LogFormater.Crit("Rabbit service [Failed to connect to RabbitMQ] stopping", true);
|
||||||
|
Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createChannelWorker(myConfig.GetNotecardQueue(), "NotecardMessageEvent");
|
||||||
|
createChannelWorker(myConfig.GetCommandQueue(), "CommandMessageEvent");
|
||||||
|
createChannelWorker(myConfig.GetImQueue(), "ImMessageEvent");
|
||||||
|
createChannelWorker(myConfig.GetGroupImQueue(), "GroupMessageEvent");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogFormater.Crit("Rabbit service [Failed to connect to RabbitMQ] " +
|
||||||
|
"" + myConfig.GetHostIP() + ":" + myConfig.GetHostPort() + " " +
|
||||||
|
"with user: " + myConfig.GetHostUsername() + "\n" +
|
||||||
|
"error:" + ex.Message, true);
|
||||||
|
Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async void createChannelWorker(string queueName, string functionpointer)
|
||||||
|
{
|
||||||
|
IChannel channel = connection.CreateChannelAsync().Await();
|
||||||
|
channels.Add(queueName, channel);
|
||||||
|
var consumer = new AsyncEventingBasicConsumer(channel);
|
||||||
|
|
||||||
|
// Use reflection to get the method by name and create a delegate
|
||||||
|
var method = typeof(RabbitService).GetMethod(functionpointer, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
if (method == null)
|
||||||
|
throw new InvalidOperationException($"Handler method '{functionpointer}' not found.");
|
||||||
|
|
||||||
|
// Create delegate matching AsyncEventHandler<BasicDeliverEventArgs>
|
||||||
|
AsyncEventHandler<BasicDeliverEventArgs> handler =
|
||||||
|
(AsyncEventHandler<BasicDeliverEventArgs>)Delegate.CreateDelegate(
|
||||||
|
typeof(AsyncEventHandler<BasicDeliverEventArgs>), this, method);
|
||||||
|
|
||||||
|
consumer.ReceivedAsync += handler;
|
||||||
|
|
||||||
|
string consumerTag = Guid.NewGuid().ToString(); // Generate a unique consumer tag.
|
||||||
|
channel.QueueDeclareAsync(
|
||||||
|
queue: queueName,
|
||||||
|
durable: true,
|
||||||
|
exclusive: false,
|
||||||
|
autoDelete: false,
|
||||||
|
arguments: null
|
||||||
|
).Await();
|
||||||
|
await channel.BasicConsumeAsync(
|
||||||
|
queue: queueName,
|
||||||
|
autoAck: true,
|
||||||
|
consumerTag: consumerTag,
|
||||||
|
noLocal: false,
|
||||||
|
exclusive: false,
|
||||||
|
arguments: null,
|
||||||
|
consumer: consumer
|
||||||
|
);
|
||||||
|
if (myConfig.GetLogDebug() == true)
|
||||||
|
{
|
||||||
|
LogFormater.Info($"Rabbit service [Consumer started for queue: {queueName}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void BotClientRestart(object o, BotClientNotice e)
|
||||||
|
{
|
||||||
|
if (e.isStart == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogFormater.Info("Rabbit service [Attached to new client]");
|
||||||
|
hasSecondbot = true;
|
||||||
|
connectService();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
if (running == true)
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
LogFormater.Info("Rabbit service [Stopping]");
|
||||||
|
if (master != null)
|
||||||
|
{
|
||||||
|
master.BotClientNoticeEvent -= BotClientRestart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Status()
|
||||||
|
{
|
||||||
|
if (myConfig == null)
|
||||||
|
{
|
||||||
|
return "No Config";
|
||||||
|
}
|
||||||
|
else if (myConfig.GetEnabled() == false)
|
||||||
|
{
|
||||||
|
return "Disabled";
|
||||||
|
}
|
||||||
|
return "Enabled";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JsonMessageFormat
|
||||||
|
{
|
||||||
|
public string UUID;
|
||||||
|
public string Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JsonCommandFormat
|
||||||
|
{
|
||||||
|
public string CommandName;
|
||||||
|
public string[] commandArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JsonNotecardFormat
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
public string Subject;
|
||||||
|
public string Content;
|
||||||
|
public string UUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue