The easy to use and full featured Irc Bot everyone is talking about!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
6.7 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using Combot.IRCServices;
using Combot.Configurations;
using Combot.IRCServices.Messaging;
using Combot.Modules;
using Module = Combot.Modules.Module;
namespace Combot
{
public class Bot
{
public event Action<CommandMessage> CommandReceivedEvent;
public event Action<BotError> ErrorEvent;
public ServerConfig ServerConfig;
public IRC IRC;
public bool Connected = false;
public static Dictionary<PrivilegeMode, AccessType> AccessTypeMapping = new Dictionary<PrivilegeMode, AccessType>() { { PrivilegeMode.v, AccessType.Voice }, { PrivilegeMode.h, AccessType.HalfOperator }, { PrivilegeMode.o, AccessType.Operator }, { PrivilegeMode.a, AccessType.SuperOperator }, { PrivilegeMode.q, AccessType.Founder } };
private List<Module> _Modules;
public Bot(ServerConfig serverConfig)
{
IRC = new IRC();
_Modules = new List<Module>();
ServerConfig = serverConfig;
IRC.ConnectEvent += HandleConnectEvent;
IRC.DisconnectEvent += HandleDisconnectEvent;
IRC.Message.ServerReplyEvent += HandleReplyEvent;
IRC.Message.ChannelMessageReceivedEvent += HandleChannelMessageReceivedEvent;
LoadModules();
}
/// <summary>
/// Trys to connect to one of the IPs of the given hostname. If the connection was successful, it will login the nick.
/// </summary>
public void Connect()
{
bool serverConnected = false;
int i = 0;
do
{
if (ServerConfig.Hosts.Count > i)
{
IPAddress[] ipList = Dns.GetHostAddresses(ServerConfig.Hosts[i].Host);
foreach (IPAddress ip in ipList)
{
serverConnected = IRC.Connect(ip, ServerConfig.Hosts[i].Port, 5000);
if (serverConnected)
{
break;
}
}
i++;
}
else
{
break;
}
}
while (!serverConnected);
if (serverConnected)
{
IRC.Login(ServerConfig.Name, new Nick() { Nickname = ServerConfig.Nickname, Host = Dns.GetHostName(), Realname = ServerConfig.Realname, Username = ServerConfig.Username });
}
}
/// <summary>
/// Disconnects from the current server.
/// </summary>
public void Disconnect()
{
IRC.Disconnect();
Connected = false;
}
public void LoadModules()
{
foreach (Module module in ServerConfig.Modules)
{
if (module.Enabled && !_Modules.Exists(mod => mod.ClassName == module.ClassName))
{
Module loadedModule = module.CreateInstance(this);
if (loadedModule.Loaded)
{
_Modules.Add(loadedModule);
}
}
}
}
private void HandleConnectEvent()
{
Connected = true;
}
private void HandleDisconnectEvent()
{
Connected = false;
}
private void HandleReplyEvent(object sender, IReply e)
{
if (e.GetType() == typeof(ServerReplyMessage))
{
ServerReplyMessage reply = (ServerReplyMessage)e;
// If the reply is Welcome, that means we are fully connected to the server and can now join the auto-join channels.
if (reply.ReplyCode == IRCReplyCode.RPL_WELCOME && Connected)
{
foreach (ChannelConfig channel in ServerConfig.Channels)
{
IRC.SendJoin(channel.Name, channel.Key);
}
}
}
}
private void HandleChannelMessageReceivedEvent(object sender, ChannelMessage e)
{
// The message was a command
if (e.Message.StartsWith(ServerConfig.CommandPrefix))
{
if (!ServerConfig.ChannelBlacklist.Contains(e.Channel)
&& !ServerConfig.NickBlacklist.Contains(e.Sender.Nickname)
)
{
ParseCommandMessage(e.TimeStamp, e.Message, e.Sender, e.Channel, LocationType.Channel);
}
}
}
private void ParseCommandMessage(DateTime timestamp, string message, Nick sender, string location, LocationType locationType)
{
// Extract command and arguments
string[] msgArgs = message.Split(new[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
string command = msgArgs[0].Remove(0, ServerConfig.CommandPrefix.Length);
List<string> argsOnly = msgArgs.ToList();
argsOnly.RemoveAt(0);
Module module = _Modules.Find(mod => mod.Commands.Exists(c => c.Triggers.Contains(command)) && mod.Loaded);
if (module != null)
{
Command cmd = module.Commands.Find(c => c.Triggers.Contains(command));
if (cmd != null)
{
CommandMessage newCommand = new CommandMessage();
newCommand.Nick.Copy(sender);
IRC.Channels.ForEach(channel => channel.Nicks.ForEach(nick =>
{
if (nick.Nickname == newCommand.Nick.Nickname)
{
newCommand.Nick.AddPrivileges(nick.Privileges);
}
}));
newCommand.TimeStamp = timestamp;
newCommand.Location = location;
newCommand.LocationType = locationType;
newCommand.Command = command;
if (argsOnly.Count > 0)
{
string[] argSplit = argsOnly.First()
.Split(new[] {' '}, cmd.Arguments.Count + 1, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < cmd.Arguments.Count; i++)
{
newCommand.Arguments.Add(argSplit[i]);
}
}
if (CommandReceivedEvent != null)
{
CommandReceivedEvent(newCommand);
}
}
}
}
}
}