Browse Source

Added features to UI.

Added reconnect.
Fixed multiple bugs.
tags/3.0.0
Teknikode 4 years ago
parent
commit
85ef0f3d37

+ 105
- 15
Combot/Bot.cs View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Combot.IRCServices;
using Combot.Configurations;
using Combot.IRCServices.Messaging;
@@ -26,12 +27,15 @@ namespace Combot

private bool GhostSent;
private int CurNickChoice;
private int RetryCount;
private bool RetryAllowed;

public Bot(ServerConfig serverConfig)
{
Modules = new List<Module>();
GhostSent = false;
CurNickChoice = 0;
RetryCount = 0;
ServerConfig = serverConfig;

IRC = new IRC(serverConfig.MaxMessageLength, serverConfig.MessageSendDelay);
@@ -55,6 +59,7 @@ namespace Combot
{
GhostSent = false;
CurNickChoice = 0;
RetryAllowed = ServerConfig.Reconnect;
bool serverConnected = false;
int i = 0;
do
@@ -96,6 +101,10 @@ namespace Combot
Disconnect();
}
}
else
{
Reconnect();
}
}

/// <summary>
@@ -106,6 +115,32 @@ namespace Combot
IRC.Disconnect();
Connected = false;
LoggedIn = false;
RetryCount = 0;
RetryAllowed = false;
}

private void Reconnect()
{
if (RetryAllowed)
{
Task.Run(() =>
{
Thread.Sleep((int)Math.Pow(1000, RetryCount));
Connect();
});
}
}

private void HandleConnectEvent()
{
Connected = true;
RetryCount = 0;
}

private void HandleDisconnectEvent()
{
Connected = false;
Reconnect();
}

public void LoadModules()
@@ -118,23 +153,46 @@ namespace Combot
}
}

public void LoadModule(string location)
public bool LoadModule(string module)
{
Module newModule = new Module();
newModule.ConfigPath = location;
newModule.ConfigPath = module;
newModule.LoadConfig();

if (newModule.Enabled && !Modules.Exists(mod => mod.ClassName == newModule.ClassName))
{
if (File.Exists(string.Format(@"{0}\{1}.dll", location, newModule.Name)))
if (File.Exists(string.Format(@"{0}\{1}.dll", module, newModule.Name)))
{
Module loadedModule = newModule.CreateInstance(this);
if (loadedModule.Loaded)
{
Modules.Add(loadedModule);
return true;
}
}
}
return false;
}

public void UnloadModules()
{
List<Module> moduleList = Modules;
for (int i = 0; i < moduleList.Count; i++)
{
UnloadModule(moduleList[i].Name);
}
}

public bool UnloadModule(string moduleName)
{
Module module = Modules.Find(mod => mod.Name.ToLower() == moduleName.ToLower());
if (module != null)
{
module.Loaded = false;
Modules.Remove(module);
return true;
}
return false;
}

public bool CheckChannelAccess(string channel, string nickname, AccessType access)
@@ -216,16 +274,6 @@ namespace Combot
ParseCommandMessage(DateTime.Now, message, new Nick { Nickname = IRC.Nickname }, location, type);
}

private void HandleConnectEvent()
{
Connected = true;
}

private void HandleDisconnectEvent()
{
Connected = false;
}

private void HandleJoinEvent(object sender, JoinChannelInfo info)
{
if (info.Nick.Nickname == IRC.Nickname)
@@ -459,7 +507,28 @@ namespace Combot
if (!validArguments[i].AllowedValues.Exists(val => val.ToLower() == argVal.ToLower()))
{
invalidArgs = true;
string invalidMessage = string.Format("Invalid value for \u0002{0}\u000F in \u0002{1}{2} {3}\u000F. Valid options are \u0002{4}\u000F.", validArguments[i].Name, ServerConfig.CommandPrefix, command, string.Join(" ", validArguments.Select(arg => { if (arg.Required) { return "\u001F" + arg.Name + "\u000F\u0002"; } return "[\u001F" + arg.Name + "\u000F\u0002]"; })), string.Join(", ", validArguments[i].AllowedValues));
string argHelp = string.Format(" \u0002{0}\u0002", string.Join(" ", validArguments.Select(arg =>
{
string argString = string.Empty;
if (arg.DependentArguments.Count > 0)
{
argString = "(";
}
if (arg.Required)
{
argString += "\u001F" + arg.Name + "\u001F";
}
else
{
argString += "[\u001F" + arg.Name + "\u001F]";
}
if (arg.DependentArguments.Count > 0)
{
argString += string.Format("\u0002:When {0}\u0002)", string.Join(" or ", arg.DependentArguments.Select(dep => { return string.Format("\u0002\u001F{0}\u001F\u0002=\u0002{1}\u0002", dep.Name, string.Join(",", dep.Values)); })));
}
return argString;
})));
string invalidMessage = string.Format("Invalid value for \u0002{0}\u0002 in \u0002{1}{2}\u0002{3}. Valid options are \u0002{4}\u0002.", validArguments[i].Name, ServerConfig.CommandPrefix, command, argHelp, string.Join(", ", validArguments[i].AllowedValues));
switch (messageType)
{
case MessageType.Channel:
@@ -486,7 +555,28 @@ namespace Combot
}
else
{
string missingArgument = string.Format("Missing a required argument for \u0002{0}{1} {2}\u000F. The required arguments are \u0002{3}\u000F.", ServerConfig.CommandPrefix, command, string.Join(" ", validArguments.Select(arg => { if (arg.Required) { return "\u001F" + arg.Name + "\u000F\u0002"; } return "[\u001F" + arg.Name + "\u000F\u0002]"; })), string.Join(", ", validArguments.Where(arg => arg.Required).Select(arg => arg.Name)));
string argHelp = string.Format(" \u0002{0}\u0002", string.Join(" ", validArguments.Select(arg =>
{
string argString = string.Empty;
if (arg.DependentArguments.Count > 0)
{
argString = "(";
}
if (arg.Required)
{
argString += "\u001F" + arg.Name + "\u001F";
}
else
{
argString += "[\u001F" + arg.Name + "\u001F]";
}
if (arg.DependentArguments.Count > 0)
{
argString += string.Format("\u0002:When {0}\u0002)", string.Join(" or ", arg.DependentArguments.Select(dep => { return string.Format("\u0002\u001F{0}\u001F\u0002=\u0002{1}\u0002", dep.Name, string.Join(",", dep.Values)); })));
}
return argString;
})));
string missingArgument = string.Format("Missing a required argument for \u0002{0}{1}\u0002{2}. The required arguments are \u0002{3}\u0002.", ServerConfig.CommandPrefix, command, argHelp, string.Join(", ", validArguments.Where(arg => arg.Required).Select(arg => arg.Name)));
if (messageType == MessageType.Channel || messageType == MessageType.Query)
{
IRC.SendPrivateMessage(location, missingArgument);

+ 1
- 0
Combot/Configurations/ServerConfig.cs View File

@@ -20,6 +20,7 @@ namespace Combot.Configurations
public DatabaseConfig Database { get; set; }
public string ModuleLocation { get; set; }
public bool AutoConnect { get; set; }
public bool Reconnect { get; set; }
public bool AutoRegister { get; set; }
public string CommandPrefix { get; set; }
public int JoinDelay { get; set; }

+ 4
- 0
Interface/Interface.csproj View File

@@ -52,6 +52,8 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
@@ -70,6 +72,8 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="BufferInfo.cs" />
<Compile Include="LocationInfo.cs" />
<Compile Include="ScrollToBottomAction.cs" />
<Compile Include="ViewModels\MainViewModel.cs" />
<Compile Include="ViewModels\ViewModelBase.cs" />
<Page Include="MainWindow.xaml">

+ 17
- 0
Interface/LocationInfo.cs View File

@@ -0,0 +1,17 @@
namespace Interface
{
public class LocationInfo
{
public string Name { get; set; }

public LocationInfo()
{
SetDefaults();
}

public void SetDefaults()
{
Name = string.Empty;
}
}
}

+ 33
- 6
Interface/MainWindow.xaml View File

@@ -4,20 +4,47 @@
xmlns:local="clr-namespace:Interface"
xmlns:prop="clr-namespace:Interface.Properties"
xmlns:view="clr-namespace:Interface.ViewModels"
Title="{Binding ApplicationTitle, Mode=TwoWay}" Height="372" Width="850" ResizeMode="CanResizeWithGrip">
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="{Binding ApplicationTitle, Mode=TwoWay}" Height="372" Width="850" ResizeMode="CanResize">
<Window.Resources>
<CollectionViewSource x:Key="SortedLocations" Source="{Binding LocationList}">
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
<Grid Margin="0,0,0,2">
<Button x:Name="ToggleConnectionButton" Content="{Binding ToggleConnectionText}" Margin="10,0,0,10" Command="{Binding ToggleConnection}" Height="23" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="100"/>

<ComboBox x:Name="ServerListBox" ItemsSource="{Binding ServerList, Mode=TwoWay}" SelectedItem="{Binding SelectedServer, Mode=TwoWay}" Height="25" Margin="0,10,10,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="114"/>
<ListBox x:Name="LocationListBox" ItemsSource="{Binding LocationList, Mode=TwoWay}" SelectedItem="{Binding SelectedLocation, Mode=TwoWay}" HorizontalAlignment="Right" Margin="0,40,10,38" Width="114"/>
<TextBox x:Name="InputBox" Text="{Binding InputBoxText, UpdateSourceTrigger=PropertyChanged}" Margin="115,0,129,10" TextWrapping="Wrap" Height="23" VerticalAlignment="Bottom" AcceptsReturn="True">
<ComboBox x:Name="ServerListBox" ItemsSource="{Binding ServerList, Mode=TwoWay}" SelectedItem="{Binding SelectedServer, Mode=TwoWay}" Height="25" Margin="0,10,10,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="125"/>

<ListBox x:Name="LocationListBox" ItemsSource="{Binding Source={StaticResource SortedLocations}}" SelectedItem="{Binding SelectedLocation, Mode=TwoWay}" HorizontalAlignment="Right" Margin="0,40,10,38" Width="125">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Clear Buffer" Command="{Binding ClearLocation}"></MenuItem>
<MenuItem Header="Remove" Command="{Binding RemoveLocation}"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<TextBox x:Name="InputBox" Text="{Binding InputBoxText, UpdateSourceTrigger=PropertyChanged}" Margin="115,0,140,10" TextWrapping="NoWrap" AcceptsTab="True" Height="23" VerticalAlignment="Bottom" AcceptsReturn="True">
<TextBox.InputBindings>
<KeyBinding Command="{Binding SubmitText}" Key="Enter"/>
</TextBox.InputBindings>
</TextBox>
<Button x:Name="SubmitButton" Content="Submit" Command="{Binding SubmitText}" Margin="0,0,10,10" HorizontalAlignment="Right" Width="114" Height="23" VerticalAlignment="Bottom"/>
<Button x:Name="SubmitButton" Content="Submit" Command="{Binding SubmitText}" Margin="0,0,10,10" HorizontalAlignment="Right" Width="125" Height="23" VerticalAlignment="Bottom"/>

<RichTextBox x:Name="BufferWindow" Margin="10,10,129,38" VerticalScrollBarVisibility="Auto" IsReadOnly="True">
<RichTextBox x:Name="BufferWindow" Margin="10,10,140,38" VerticalScrollBarVisibility="Auto" IsReadOnly="True">
<RichTextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Clear Buffer" Command="{Binding ClearLocation}"></MenuItem>
</ContextMenu>
</RichTextBox.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<local:ScrollToBottomAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
<FlowDocument>
<Paragraph>
<Run Text="{Binding CurrentBuffer, Mode=TwoWay}"/>

+ 13
- 0
Interface/ScrollToBottomAction.cs View File

@@ -0,0 +1,13 @@
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace Interface
{
public class ScrollToBottomAction : TriggerAction<RichTextBox>
{
protected override void Invoke(object parameter)
{
AssociatedObject.ScrollToEnd();
}
}
}

+ 139
- 40
Interface/ViewModels/MainViewModel.cs View File

@@ -7,10 +7,12 @@ using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Runtime.Remoting.Channels;
using System.Threading;
using System.Windows.Documents;
using Combot;
using Combot.IRCServices.Messaging;
using Combot.Configurations;
using Combot.IRCServices;

namespace Interface.ViewModels
{
@@ -135,8 +137,11 @@ namespace Interface.ViewModels

public DelegateCommand ToggleConnection { get; private set; }
public DelegateCommand SubmitText { get; set; }
public DelegateCommand RemoveLocation { get; set; }
public DelegateCommand ClearLocation { get; set; }

private List<BufferInfo> BufferList = new List<BufferInfo>();
private ReaderWriterLockSlim BufferLock;

public MainViewModel()
{
@@ -144,25 +149,27 @@ namespace Interface.ViewModels
Config.LoadServers();
ServerList = new ObservableCollection<string>();
LocationList = new ObservableCollection<string>();
BufferLock = new ReaderWriterLockSlim();

foreach (ServerConfig server in Config.Servers)
{
ServerList.Add(server.Name);
Bot Combot = new Bot(server);

Combot.IRC.Message.ErrorMessageEvent += (sender, e) => ErrorMessageHandler(sender, e, server.Name);
Combot.IRC.Message.ServerReplyEvent += (sender, e) => ServerReplyHandler(sender, e, server.Name);
Combot.IRC.Message.ChannelMessageReceivedEvent += (sender, e) => ChannelMessageReceivedHandler(sender, e, server.Name);
Combot.IRC.Message.ChannelNoticeReceivedEvent += (sender, e) => ChannelNoticeReceivedHandler(sender, e, server.Name);
Combot.IRC.Message.PrivateMessageReceivedEvent += (sender, e) => PrivateMessageReceivedHandler(sender, e, server.Name);
Combot.IRC.Message.PrivateNoticeReceivedEvent += (sender, e) => PrivateNoticeReceivedHandler(sender, e, server.Name);
//Combot.IRC.Message.RawMessageEvent += RawMessageHandler;
Combot.ErrorEvent += e => BotErrorHandler(e, Combot.ServerConfig.Name);
Combot.IRC.Message.ErrorMessageEvent += (sender, e) => ErrorMessageHandler(sender, e, Combot.ServerConfig.Name);
Combot.IRC.Message.ServerReplyEvent += (sender, e) => ServerReplyHandler(sender, e, Combot.ServerConfig.Name);
Combot.IRC.Message.ChannelMessageReceivedEvent += (sender, e) => ChannelMessageReceivedHandler(sender, e, Combot.ServerConfig.Name);
Combot.IRC.Message.ChannelNoticeReceivedEvent += (sender, e) => ChannelNoticeReceivedHandler(sender, e, Combot.ServerConfig.Name);
Combot.IRC.Message.PrivateMessageReceivedEvent += (sender, e) => PrivateMessageReceivedHandler(sender, e, Combot.ServerConfig.Name);
Combot.IRC.Message.PrivateNoticeReceivedEvent += (sender, e) => PrivateNoticeReceivedHandler(sender, e, Combot.ServerConfig.Name);

Combot.IRC.Message.JoinChannelEvent += (sender, e) => JoinEventHandler(sender, e, server.Name);
Combot.IRC.Message.JoinChannelEvent += (sender, e) => JoinEventHandler(sender, e, Combot.ServerConfig.Name);
Combot.IRC.Message.PartChannelEvent += (sender, e) => PartEventHandler(sender, e, Combot.ServerConfig.Name);

Combot.IRC.ConnectEvent += () => ConnectHandler(server.Name);
Combot.IRC.DisconnectEvent += () => DisconnectHandler(server.Name);
Combot.IRC.TCPErrorEvent += e => TCPErrorHandler(e, server.Name);
Combot.IRC.ConnectEvent += () => ConnectHandler(Combot.ServerConfig.Name);
Combot.IRC.DisconnectEvent += () => DisconnectHandler(Combot.ServerConfig.Name);
Combot.IRC.TCPErrorEvent += e => TCPErrorHandler(e, Combot.ServerConfig.Name);

CombotSessions.Add(Combot);
SelectedServer = server.Name;
@@ -175,51 +182,68 @@ namespace Interface.ViewModels

ToggleConnection = new DelegateCommand(ExecuteToggleConnection, CanToggleConnection);
SubmitText = new DelegateCommand(ExecuteSubmitText, CanSubmitText);
RemoveLocation = new DelegateCommand(ExecuteRemoveLocation, CanRemoveLocation);
ClearLocation = new DelegateCommand(ExecuteClearLocation, CanClearLocation);
}

private void JoinEventHandler(object sender, JoinChannelInfo info, string server)
{
AddToBuffer(server, info.Channel, string.Format("{0} has joined {1}.", info.Nick.Nickname, info.Channel));
}

private void RawMessageHandler(object sender, string message)
private void BotErrorHandler(BotError error, string server)
{
//CurrentBuffer += message + Environment.NewLine;
AddToBuffer(server, null, string.Format("[{0}] \u0002{1} Error\u0002: {2}", DateTime.Now.ToString("HH:mm:ss"), error.Type, error.Message));
}

private void TCPErrorHandler(Combot.IRCServices.TCP.TCPError error, string server)
{
AddToBuffer(server, null, string.Format("[{0}] {1}", error.Code.ToString(), error.Message));
AddToBuffer(server, null, string.Format("[{0}] \u0002TCP Error {1}\u0002: {2}", DateTime.Now.ToString("HH:mm:ss"), error.Code, error.Message));
}

private void ServerReplyHandler(object sender, IReply reply, string server)
{
AddToBuffer(server, null, reply.Message);
AddToBuffer(server, null, string.Format("[{0}] \u0002*\u0002: {1}", reply.TimeStamp.ToString("HH:mm:ss"), reply.Message));
}

private void ErrorMessageHandler(object sender, ErrorMessage message, string server)
{
AddToBuffer(server, null, message.Message);
AddToBuffer(server, null, string.Format("[{0}] \u0002*\u0002: {1}", message.TimeStamp.ToString("HH:mm:ss"), message.Message));
}

private void ChannelMessageReceivedHandler(object sender, ChannelMessage message, string server)
{
AddToBuffer(server, message.Channel, message.Message);
AddToBuffer(server, message.Channel, string.Format("[{0}] \u0002{1}\u0002: {2}", message.TimeStamp.ToString("HH:mm:ss"), message.Sender.Nickname, message.Message));
}

private void ChannelNoticeReceivedHandler(object sender, ChannelNotice message, string server)
{
AddToBuffer(server, message.Channel, message.Message);
AddToBuffer(server, message.Channel, string.Format("[{0}] \u0002{1}\u0002 -NOTICE-: {2}", message.TimeStamp.ToString("HH:mm:ss"), message.Sender.Nickname, message.Message));
}

private void PrivateMessageReceivedHandler(object sender, PrivateMessage message, string server)
{
AddToBuffer(server, message.Sender.Nickname, message.Message);
string location = message.Sender.Nickname;
if (message.Sender.Nickname.ToLower() == "nickserv" || message.Sender.Nickname.ToLower() == "chanserv")
{
location = null;
}
AddToBuffer(server, location, string.Format("[{0}] \u0002{1}\u0002: {2}", message.TimeStamp.ToString("HH:mm:ss"), message.Sender.Nickname, message.Message));
}

private void PrivateNoticeReceivedHandler(object sender, PrivateNotice message, string server)
{
AddToBuffer(server, message.Sender.Nickname, message.Message);
string location = message.Sender.Nickname;
if (message.Sender.Nickname.ToLower() == "nickserv" || message.Sender.Nickname.ToLower() == "chanserv")
{
location = null;
}
AddToBuffer(server, location, string.Format("[{0}] \u0002{1}\u0002 -NOTICE-: {2}", message.TimeStamp.ToString("HH:mm:ss"), message.Sender.Nickname, message.Message));
}

private void JoinEventHandler(object sender, JoinChannelInfo info, string server)
{
AddToBuffer(server, info.Channel, string.Format("[{0}] \u0002{1}\u0002 has joined \u0002{2}\u0002.", info.TimeStamp.ToString("HH:mm:ss"), info.Nick.Nickname, info.Channel));
}

private void PartEventHandler(object sender, PartChannelInfo info, string server)
{
AddToBuffer(server, info.Channel, string.Format("[{0}] \u0002{1}\u0002 has left \u0002{2}\u0002.", info.TimeStamp.ToString("HH:mm:ss"), info.Nick.Nickname, info.Channel));
}

private void ConnectHandler(string server)
@@ -227,6 +251,7 @@ namespace Interface.ViewModels
if (server == SelectedServer)
{
Connected = true;
AddToBuffer(server, null, "-- Connected --");
}
}

@@ -235,6 +260,7 @@ namespace Interface.ViewModels
if (server == SelectedServer)
{
Connected = false;
AddToBuffer(server, null, "-- Disconnected --");
}
}

@@ -257,33 +283,100 @@ namespace Interface.ViewModels

private void ExecuteSubmitText()
{
if (SelectedLocation != " --Server-- ")
Bot botInstance = CombotSessions.Find(bot => bot.ServerConfig.Name == SelectedServer);
if (botInstance != null && botInstance.Connected)
{
Bot botInstance = CombotSessions.Find(bot => bot.ServerConfig.Name == SelectedServer);
if (botInstance != null && botInstance.Connected)
string message = InputBoxText;
if (InputBoxText.StartsWith("/"))
{
string message = InputBoxText;
if (InputBoxText.StartsWith("/"))
MessageType type = MessageType.Query;
if (SelectedLocation.StartsWith("#") || SelectedLocation.StartsWith("&"))
{
type = MessageType.Channel;
}
message = message.Remove(0, 1);
message = string.Join("", botInstance.ServerConfig.CommandPrefix, message);
botInstance.ExecuteCommand(message, SelectedLocation, type);
}
else
{
if (SelectedLocation != " --Server-- ")
{
MessageType type = MessageType.Query;
if (SelectedLocation.StartsWith("#") || SelectedLocation.StartsWith("&"))
{
type = MessageType.Channel;
if (botInstance.IRC.Channels.Exists(chan => chan.Name == SelectedLocation))
{
botInstance.IRC.SendPrivateMessage(SelectedLocation, message);
}
else
{
AddToBuffer(SelectedServer, SelectedLocation, "You are not in this channel.");
}
}
else
{
botInstance.IRC.SendPrivateMessage(SelectedLocation, message);
}
message = message.Remove(0, 1);
message = string.Join("", botInstance.ServerConfig.CommandPrefix, message);
botInstance.ExecuteCommand(message, SelectedLocation, type);
}
else
}
InputBoxText = string.Empty;
}
}

private bool CanSubmitText()
{
if (Connected)
{
return true;
}
return false;
}

private void ExecuteRemoveLocation()
{
if (SelectedLocation != " --Server-- ")
{
string location = SelectedLocation;

if (location.StartsWith("#") || location.StartsWith("&"))
{
Bot botInstance = CombotSessions.Find(bot => bot.ServerConfig.Name == SelectedServer);
if (botInstance.IRC.Channels.Exists(chan => chan.Name == location))
{
botInstance.IRC.SendPrivateMessage(SelectedLocation, message);
botInstance.IRC.SendPart(location);
}
InputBoxText = string.Empty;
}
if (LocationList.Contains(location))
{
App.Current.Dispatcher.Invoke((Action)(() => LocationList.Remove(location)));
}
BufferLock.EnterWriteLock();
if (BufferList.Exists(buf => buf.Server == SelectedServer && buf.Location == location))
{
BufferList.RemoveAll(buf => buf.Server == SelectedServer && buf.Location == location);
}
BufferLock.ExitWriteLock();
}
}

private bool CanSubmitText()
private bool CanRemoveLocation()
{
return true;
}

private void ExecuteClearLocation()
{
string location = SelectedLocation;
BufferLock.EnterWriteLock();
if (BufferList.Exists(buf => buf.Server == SelectedServer && buf.Location == location))
{
BufferList.Find(buf => buf.Server == SelectedServer && buf.Location == location).Buffer.Clear();
}
BufferLock.ExitWriteLock();
CurrentBuffer = string.Empty;
}

private bool CanClearLocation()
{
return true;
}
@@ -304,6 +397,7 @@ namespace Interface.ViewModels
{
location = " --Server-- ";
}
BufferLock.EnterWriteLock();
if (!BufferList.Exists(buf => buf.Server == server && buf.Location == location))
{
BufferInfo newBuffer = new BufferInfo();
@@ -311,16 +405,19 @@ namespace Interface.ViewModels
newBuffer.Location = location;
BufferList.Add(newBuffer);
}
BufferLock.ExitWriteLock();
if (SelectedServer == server && !LocationList.Contains(location))
{
App.Current.Dispatcher.Invoke((Action) (() => LocationList.Add(location)));
}
BufferLock.EnterWriteLock();
BufferInfo buffer = BufferList.Find(buf => buf.Server == server && buf.Location == location);
if (buffer.Buffer.Count >= 1000)
{
buffer.Buffer.RemoveAt(0);
}
buffer.Buffer.Add(message);
BufferLock.ExitWriteLock();
ChangeBuffer();
}

@@ -336,7 +433,7 @@ namespace Interface.ViewModels
}
if (LocationList.Any())
{
SelectedLocation = LocationList.First();
SelectedLocation = " --Server-- ";
}
}

@@ -344,6 +441,7 @@ namespace Interface.ViewModels
{
if (SelectedServer != null && SelectedLocation != null)
{
BufferLock.EnterWriteLock();
if (!BufferList.Exists(buf => buf.Server == SelectedServer && buf.Location == SelectedLocation))
{
BufferInfo newBuffer = new BufferInfo();
@@ -352,6 +450,7 @@ namespace Interface.ViewModels
BufferList.Add(newBuffer);
}
CurrentBuffer = string.Join(Environment.NewLine, BufferList.Find(buf => buf.Server == SelectedServer && buf.Location == SelectedLocation).Buffer);
BufferLock.ExitWriteLock();
Connected = CombotSessions.Find(bot => bot.ServerConfig.Name == SelectedServer).Connected;
}
}

+ 24
- 5
Modules/Introductions/Introductions.cs View File

@@ -289,19 +289,38 @@ namespace Combot.Modules.Plugins
}
else
{
for (int i = 0; i < results.Count; i++)
if (results.Any())
{
string introMessage = string.Format("Introduction #\u0002{0}\u0002: {1}", i + 1, results[i]["message"]);
for (int i = 0; i < results.Count; i++)
{
string introMessage = string.Format("Introduction #\u0002{0}\u0002: {1}", i + 1, results[i]["message"]);
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendNotice(command.Nick.Nickname, introMessage);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, introMessage);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, introMessage);
break;
}
}
}
else
{
string invalid = "You do not have any introductions set.";
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendNotice(command.Nick.Nickname, introMessage);
Bot.IRC.SendPrivateMessage(command.Location, invalid);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, introMessage);
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, invalid);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, introMessage);
Bot.IRC.SendNotice(command.Nick.Nickname, invalid);
break;
}
}

+ 48
- 0
Modules/Owner Control/Module.config View File

@@ -401,6 +401,54 @@
],
"ShowHelp": true,
"SpamCheck": true
},
{
"Name": "Modules",
"Description": "Loads or Unloads the specified module.",
"Enabled": true,
"ChannelBlacklist": [],
"NickBlacklist": [],
"Triggers": [
"module"
],
"Arguments": [
{
"Name": "Action",
"Description": "The action you want to perform on the module.",
"AllowedValues": [
"Load",
"Unload"
],
"MessageTypes": [
0,
1,
2
],
"Required": true
},
{
"Name": "Module",
"Description": "The module you want to perform the action on.",
"AllowedValues": [],
"DependentArguments": [],
"MessageTypes": [
0,
1,
2
],
"Required": true
}
],
"AllowedMessageTypes": [
0,
1,
2
],
"AllowedAccess": [
6
],
"ShowHelp": true,
"SpamCheck": true
}
],
"Options": []

+ 117
- 0
Modules/Owner Control/Owner_Control.cs View File

@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;

@@ -203,6 +204,122 @@ namespace Combot.Modules.Plugins
break;
}
break;
case "Modules":
string moduleType = command.Arguments["Action"].ToString();
string moduleName = command.Arguments["Module"].ToString();
switch (moduleType.ToLower())
{
case "load":
if (!Bot.Modules.Exists(mod => mod.Name.ToLower() == moduleName.ToLower()))
{
string modulePath = Path.Combine(Bot.ServerConfig.ModuleLocation, moduleName);
bool loaded = Bot.LoadModule(modulePath);
if (loaded)
{
string moduleMessage = string.Format("\u0002{0}\u000F has been loaded.", moduleName);
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendPrivateMessage(command.Location, moduleMessage);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, moduleMessage);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, moduleMessage);
break;
}
}
else
{
string moduleMessage = string.Format("\u0002{0}\u000F was unable to be loaded.", moduleName);
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendPrivateMessage(command.Location, moduleMessage);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, moduleMessage);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, moduleMessage);
break;
}
}
}
else
{
string moduleInvalid = string.Format("\u0002{0}\u000F is already loaded.", moduleName);
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendPrivateMessage(command.Location, moduleInvalid);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, moduleInvalid);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, moduleInvalid);
break;
}
}
break;
case "unload":
if (Bot.Modules.Exists(mod => mod.Name.ToLower() == moduleName.ToLower()))
{
bool unloaded = Bot.UnloadModule(moduleName);
if (unloaded)
{
string moduleMessage = string.Format("\u0002{0}\u000F has been unloaded.", moduleName);
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendPrivateMessage(command.Location, moduleMessage);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, moduleMessage);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, moduleMessage);
break;
}
}
else
{
string moduleMessage = string.Format("\u0002{0}\u000F was unable to be unloaded.", moduleName);
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendPrivateMessage(command.Location, moduleMessage);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, moduleMessage);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, moduleMessage);
break;
}
}
}
else
{
string moduleInvalid = string.Format("\u0002{0}\u000F is not loaded.", moduleName);
switch (command.MessageType)
{
case MessageType.Channel:
Bot.IRC.SendPrivateMessage(command.Location, moduleInvalid);
break;
case MessageType.Query:
Bot.IRC.SendPrivateMessage(command.Nick.Nickname, moduleInvalid);
break;
case MessageType.Notice:
Bot.IRC.SendNotice(command.Nick.Nickname, moduleInvalid);
break;
}
}
break;
}
break;
}
}
}

+ 11
- 0
Modules/Seen/Module.config View File

@@ -25,6 +25,17 @@
2
],
"Required": true
},
{
"Name": "Channel",
"Description": "The channel you want to get last seen information for.",
"AllowedValues": [],
"MessageTypes": [
0,
1,
2
],
"Required": false
}
],
"AllowedMessageTypes": [

+ 118
- 46
Modules/Seen/Seen.cs View File

@@ -25,7 +25,7 @@ namespace Combot.Modules.Plugins

private void GetLastSeen(CommandMessage command)
{
string channel = command.Arguments.ContainsKey("Channel") ? command.Arguments["Channel"] : command.Location;
string channel = command.Arguments.ContainsKey("Channel") ? command.Arguments["Channel"] : null;
Database database = new Database(Bot.ServerConfig.Database);
List<Dictionary<string, object>> channelList = GetChannelList(database, channel, command.Arguments["Nickname"]);
List<Dictionary<string, object>> partList = GetPartList(database, channel, command.Arguments["Nickname"]);
@@ -39,28 +39,28 @@ namespace Combot.Modules.Plugins
{
DateTime chanTime = (DateTime)channelList.First()["date_added"];
TimeSpan difference = DateTime.Now.Subtract(chanTime);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago saying the following in \u0002{2}\u0002: {3}", command.Arguments["Nickname"], ConvertToDifference(difference), channel, channelList.First()["message"]);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago saying the following in \u0002{2}\u0002: {3}", command.Arguments["Nickname"], ConvertToDifference(difference), channelList.First()["name"], channelList.First()["message"]);
lastSeenList.Add(new Dictionary<DateTime, string>() { { chanTime, message } });
}
if (partList.Any())
{
DateTime partTime = (DateTime)partList.First()["date_added"];
TimeSpan difference = DateTime.Now.Subtract(partTime);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago leaving \u0002{2}\u0002.", command.Arguments["Nickname"], ConvertToDifference(difference), channel);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago leaving \u0002{2}\u0002.", command.Arguments["Nickname"], ConvertToDifference(difference), channelList.First()["name"]);
lastSeenList.Add(new Dictionary<DateTime, string>() { { partTime, message } });
}
if (joinList.Any())
{
DateTime joinTime = (DateTime)joinList.First()["date_added"];
TimeSpan difference = DateTime.Now.Subtract(joinTime);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago joining \u0002{2}\u0002.", command.Arguments["Nickname"], ConvertToDifference(difference), channel);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago joining \u0002{2}\u0002.", command.Arguments["Nickname"], ConvertToDifference(difference), channelList.First()["name"]);
lastSeenList.Add(new Dictionary<DateTime, string>() { { joinTime, message } });
}
if (kickList.Any())
{
DateTime kickTime = (DateTime)kickList.First()["date_added"];
TimeSpan difference = DateTime.Now.Subtract(kickTime);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago being kicked from \u0002{2}\u0002 with the reason: {3}", command.Arguments["Nickname"], ConvertToDifference(difference), channel, kickList.First()["message"]);
string message = string.Format("I last saw \u0002{0}\u0002 {1} ago being kicked from \u0002{2}\u0002 with the reason: {3}", command.Arguments["Nickname"], ConvertToDifference(difference), channelList.First()["name"], kickList.First()["message"]);
lastSeenList.Add(new Dictionary<DateTime, string>() { { kickTime, message } });
}
if (quitList.Any())
@@ -98,7 +98,15 @@ namespace Combot.Modules.Plugins
}
else
{
string notFound = string.Format("I have not seen \u0002{0}\u0002 in \u0002{1}\u0002.", command.Arguments["Nickname"], channel);
string notFound = string.Empty;
if (channel != null)
{
notFound = string.Format("I have not seen \u0002{0}\u0002 in \u0002{1}\u0002.", command.Arguments["Nickname"], channel);
}
else
{
notFound = string.Format("I have not seen \u0002{0}\u0002.", command.Arguments["Nickname"]);
}
switch (command.MessageType)
{
case MessageType.Channel:
@@ -116,58 +124,122 @@ namespace Combot.Modules.Plugins

private List<Dictionary<string, object>> GetChannelList(Database database, string channel, string nickname)
{
string search = "SELECT `channelmessages`.`message`, `channelmessages`.`date_added` FROM `channelmessages` " +
"INNER JOIN `nicks` " +
"ON `channelmessages`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelmessages`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelmessages`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, channel, nickname });
if (channel != null)
{
string search = "SELECT `channelmessages`.`message`, `channelmessages`.`date_added`, `channels`.`name` FROM `channelmessages` " +
"INNER JOIN `nicks` " +
"ON `channelmessages`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelmessages`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelmessages`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] {Bot.ServerConfig.Name, channel, nickname});
}
else
{
string search = "SELECT `channelmessages`.`message`, `channelmessages`.`date_added`, `channels`.`name` FROM `channelmessages` " +
"INNER JOIN `nicks` " +
"ON `channelmessages`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelmessages`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelmessages`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `nicks`.`nickname` = {1} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, nickname });
}
}

private List<Dictionary<string, object>> GetPartList(Database database, string channel, string nickname)
{
string search = "SELECT `channelparts`.`date_added` FROM `channelparts` " +
"INNER JOIN `nicks` " +
"ON `channelparts`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelparts`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelparts`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, channel, nickname });
if (channel != null)
{
string search = "SELECT `channelparts`.`date_added`, `channels`.`name` FROM `channelparts` " +
"INNER JOIN `nicks` " +
"ON `channelparts`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelparts`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelparts`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] {Bot.ServerConfig.Name, channel, nickname});
}
else
{
string search = "SELECT `channelparts`.`date_added`, `channels`.`name` FROM `channelparts` " +
"INNER JOIN `nicks` " +
"ON `channelparts`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelparts`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelparts`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `nicks`.`nickname` = {1} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, nickname });
}
}

private List<Dictionary<string, object>> GetJoinList(Database database, string channel, string nickname)
{
string search = "SELECT `channeljoins`.`date_added` FROM `channeljoins` " +
"INNER JOIN `nicks` " +
"ON `channeljoins`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channeljoins`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channeljoins`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, channel, nickname });
if (channel != null)
{
string search = "SELECT `channeljoins`.`date_added`, `channels`.`name` FROM `channeljoins` " +
"INNER JOIN `nicks` " +
"ON `channeljoins`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channeljoins`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channeljoins`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] {Bot.ServerConfig.Name, channel, nickname});
}
else
{
string search = "SELECT `channeljoins`.`date_added`, `channels`.`name` FROM `channeljoins` " +
"INNER JOIN `nicks` " +
"ON `channeljoins`.`nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channeljoins`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channeljoins`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `nicks`.`nickname` = {1} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, nickname });
}
}

private List<Dictionary<string, object>> GetKickList(Database database, string channel, string nickname)
{
string search = "SELECT `channelkicks`.`date_added`, `channelkicks`.`reason` FROM `channelkicks` " +
"INNER JOIN `nicks` " +
"ON `channelkicks`.`kicked_nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelkicks`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelkicks`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, channel, nickname });
if (channel != null)
{
string search = "SELECT `channelkicks`.`date_added`, `channelkicks`.`reason`, `channels`.`name` FROM `channelkicks` " +
"INNER JOIN `nicks` " +
"ON `channelkicks`.`kicked_nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelkicks`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelkicks`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `channels`.`name` = {1} AND `nicks`.`nickname` = {2} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] {Bot.ServerConfig.Name, channel, nickname});
}
else
{
string search = "SELECT `channelkicks`.`date_added`, `channelkicks`.`reason`, `channels`.`name` FROM `channelkicks` " +
"INNER JOIN `nicks` " +
"ON `channelkicks`.`kicked_nick_id` = `nicks`.`id` " +
"INNER JOIN `channels` " +
"ON `channelkicks`.`channel_id` = `channels`.`id` " +
"INNER JOIN `servers` " +
"ON `channelkicks`.`server_id` = `servers`.`id` " +
"WHERE `servers`.`name` = {0} AND `nicks`.`nickname` = {1} " +
"ORDER BY date_added DESC LIMIT 1";
return database.Query(search, new object[] { Bot.ServerConfig.Name, nickname });
}
}

private List<Dictionary<string, object>> GetQuitList(Database database, string nickname)

Loading…
Cancel
Save