Skip to content

Commit 52de42b

Browse files
committed
Massive refactor, stage 2
1 parent e099270 commit 52de42b

File tree

6 files changed

+137
-4
lines changed

6 files changed

+137
-4
lines changed

IrcBot.Title/Title.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
5252
return !String.IsNullOrEmpty(toSend) ? toSend : null;
5353
}
5454

55+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
56+
{
57+
return null; // Not implemented
58+
}
59+
5560
/// <summary>
5661
/// Gets the title and any other interesting doodads of an HTML document.
5762
/// </summary>

IrcBot.Utils/Utilities.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
1818
{
1919
return message == ".ping" ? "pong" : null;
2020
}
21+
22+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
23+
{
24+
return null; // Not implemented
25+
}
2126
}
2227

2328
/// <summary>
@@ -48,6 +53,11 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
4853

4954
return null;
5055
}
56+
57+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
58+
{
59+
return null; // Not implemented
60+
}
5161
}
5262

5363
/// <summary>
@@ -68,6 +78,11 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
6878

6979
return null;
7080
}
81+
82+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
83+
{
84+
return null; // Not implemented
85+
}
7186
}
7287

7388
/// <summary>
@@ -83,6 +98,11 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
8398
}
8499
return null;
85100
}
101+
102+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
103+
{
104+
return null; // Not implemented
105+
}
86106
}
87107

88108
public class Whois : IPlugin
@@ -97,6 +117,11 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
97117
}
98118
return null;
99119
}
120+
121+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
122+
{
123+
return null; // Not implemented
124+
}
100125
}
101126

102127
/// <summary>
@@ -121,5 +146,10 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
121146
}
122147
return null; // we have no need to talk
123148
}
149+
150+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
151+
{
152+
return null; // Not implemented
153+
}
124154
}
125155
}

IrcBot.YouTube/YouTube.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,10 @@ string IPlugin.InvokeWithMessage(string source, string message, ref IrcClient cl
5050
}
5151
return to_send;
5252
}
53+
54+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
55+
{
56+
return null; // Not implemented
57+
}
5358
}
5459
}

IrcBot/IPlugin.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace IrcBot
1010
/// <summary>
1111
/// Represents a plugin implementation.
1212
/// </summary>
13+
/// <remarks>You will have to implement them all, but nothing says you don't have to do anything useful with the ones you don't need.</remarks>
1314
public interface IPlugin
1415
{
1516
/// <summary>
@@ -35,5 +36,30 @@ public interface IPlugin
3536
/// }
3637
/// </example>
3738
string InvokeWithMessage(string source, string message, ref IrcClient client);
39+
40+
/// <summary>
41+
/// Activates the plugin with a channel user changing event.
42+
/// </summary>
43+
/// <param name="channel">If applicable, the channel the event was raised from.</param>
44+
/// <param name="user">The user that joined or left.</param>
45+
/// <param name="kicker">If applicable, the operator that kicked the user.</param>
46+
/// <param name="message">If applicable, the quit, part, or kick message.</param>
47+
/// <param name="type">The type of event that was raised.</param>
48+
/// <param name="client">A reference to the IRC client, for invoke commands with.</param>
49+
/// <returns>A message to send back to the channel. If there's nothing worth sending, you can return null to send nothing.</returns>
50+
/// <remarks>
51+
/// When using the IrcClient reference, don't invoke SendMessage to the source - the bot will do this to the source with what you return.
52+
///
53+
/// Plugins retain no state other than the IrcClient's when invoked.
54+
/// </remarks>
55+
string InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client);
56+
}
57+
58+
/// <summary>
59+
/// The type of event when a channel's user is added or moved.
60+
/// </summary>
61+
public enum ChannelUserChange
62+
{
63+
Quit, Part, Join, Kick
3864
}
3965
}

IrcBot/Program.cs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ static void Main(string[] args)
6161
// assign events
6262
i.OnChannelMessage += i_OnChannelMessage;
6363
i.OnQueryMessage += i_OnQueryMessage;
64+
i.OnJoin += i_OnJoin;
65+
i.OnQuit += i_OnQuit;
66+
i.OnKick += i_OnKick;
67+
i.OnPart += i_OnPart;
6468
// init
6569
i.ActiveChannelSyncing = true;
6670
i.UseSsl = Settings.Default.SSL;
@@ -70,6 +74,27 @@ static void Main(string[] args)
7074
i.Listen();
7175
}
7276

77+
static void i_OnPart(object sender, PartEventArgs e)
78+
{
79+
InvokePluginWithChannelUserChange(e.Channel, e.Who, null, e.PartMessage, ChannelUserChange.Part);
80+
}
81+
82+
static void i_OnKick(object sender, KickEventArgs e)
83+
{
84+
// SmartIrc4net documentation is NOT clear on the Who/Whom mixup
85+
InvokePluginWithChannelUserChange(e.Channel, e.Whom, e.Who, e.KickReason, ChannelUserChange.Kick);
86+
}
87+
88+
static void i_OnQuit(object sender, QuitEventArgs e)
89+
{
90+
InvokePluginWithChannelUserChange(null, e.Who, null, e.QuitMessage, ChannelUserChange.Quit);
91+
}
92+
93+
static void i_OnJoin(object sender, JoinEventArgs e)
94+
{
95+
InvokePluginWithChannelUserChange(e.Channel, e.Who, null, null, ChannelUserChange.Join);
96+
}
97+
7398
static void i_OnQueryMessage(object sender, IrcEventArgs e)
7499
{
75100
InvokePluginWithMessage(e.Data.Nick, e.Data.Message);
@@ -81,7 +106,7 @@ static void i_OnChannelMessage(object sender, IrcEventArgs e)
81106
}
82107

83108
/// <summary>
84-
/// Invokes a plugin.
109+
/// Invokes a plugin with a message.
85110
/// </summary>
86111
/// <param name="source">The channel or user that sent the message.</param>
87112
/// <param name="message">The message for the plugins to handle.</param>
@@ -116,6 +141,38 @@ static void InvokePluginWithMessage(string source, string message)
116141
Debug.WriteLine(ex.ToString());
117142
}
118143
}
144+
145+
static void InvokePluginWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type)
146+
{
147+
// This doesn't matter anyways if it succeeds or not
148+
try
149+
{
150+
foreach (Type p in plugins)
151+
{
152+
Thread t = new Thread(() =>
153+
{
154+
// Why not spawn instances when we loaded them? Sometimes state likes to stick or something.
155+
string to_send = ((IPlugin)Activator.CreateInstance(p)).InvokeWithChannelUserChange(channel, user, kicker, message, type, ref i);
156+
if (!String.IsNullOrEmpty(message))
157+
{
158+
i.SendMessage(SendType.Message, channel, to_send);
159+
}
160+
});
161+
t.IsBackground = true;
162+
t.Name = p.Name;
163+
t.Start();
164+
if (!t.Join(5000))
165+
{
166+
t.Abort();
167+
Debug.WriteLine("The plugin took too long to respond.", "PluginLoader");
168+
}
169+
}
170+
}
171+
catch (Exception ex)
172+
{
173+
Debug.WriteLine(ex.ToString());
174+
}
175+
}
119176
}
120177

121178
/// <summary>

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,26 @@ A simple IrcBot. Requires SmartIrc4net, and HtmlAgilityPack (will by installed v
66

77
Modules implement the `IPlugin` interface.
88

9-
At first, it loads the files meeting `IrcBot.*.dll` match in the `PluginPath` setting, then loading the classes implementing `IPlugin`. On receiving a message, it will enumerate all plugins and invoke them. A plugin will only return non-null/`String.Empty` if it has something to say when parsing the message.
9+
At first, it loads the files meeting `IrcBot.*.dll` match in the `PluginPath` setting, then loading the classes implementing `IPlugin`. On receiving a event, it will enumerate all plugins and invoke them with the approriate instance. A plugin will only return non-null/`String.Empty` if it has something to say when parsing the message.
1010

11-
The method instance to use is:
11+
Note that if you don't have any use for a method in a plugin, simply nop it out by returning null.
1212

13-
string IPlugin.Invoke(string source, string message, ref Meebey.SmartIrc4net.IrcClient client)
13+
The method instances to use are:
14+
15+
### InvokeWithMessage
16+
17+
string IPlugin.InvokeWithMessage(string source, string message, ref Meebey.SmartIrc4net.IrcClient client)
1418

1519
`source` indicates the channel or user (in case of private message) that the message originated from, `message` indicates the message, and `client` is a reference to the bot's instance of IrcClient, which can be used for commands. The return value is what to send back to the source.
1620

1721
Best practices when making your plugin is to use "." as a prefix for commands, and not to use `client.SendMessage`, as it will send to the source what you return. (if not null)
1822

23+
### InvokeWithChannelUserChange
24+
25+
string IPlugin.InvokeWithChannelUserChange(string channel, string user, string kicker, string message, ChannelUserChange type, ref IrcClient client)
26+
27+
`channel` is the channel the event was recieved from (if applicable), `user` is the user that has been added or removed from the channel, `kicker` was the person who kicked the user (if kicked), `message` is the message/reason for the event (if applicable), `type` is a `ChannelUserChange` enumeration that represents what happened (Join, Part, Quit, Kick), and `client is a reference to the bot's instance of IrcClient.
28+
1929
### Building a module
2030

2131
To build one, you can add a project to the solution or make a simple file with these parameters to the compiler manually:

0 commit comments

Comments
 (0)