Add IpyBot to the public repository
git-svn-id: https://source.geekisp.com/bleep/trunk/IpyBot@259 a256dd88-e320-0410-9161-d397f098afaa
This commit is contained in:
commit
37fb1310f6
Binary file not shown.
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<project name="IpyBot" default="release" basedir=".">
|
||||
<description>
|
||||
Very basic build file for IpyBot
|
||||
</description>
|
||||
|
||||
<property name="debug" value="true" overwrite="false" />
|
||||
<property name="project.name" value="IpyBot"/>
|
||||
<property name="project.version" value="1.0.0"/>
|
||||
<tstamp property="build.date" pattern="yyyyMMdd" verbose="true" />
|
||||
|
||||
<!-- These are being definde for posterity's sake, as they may change in the future -->
|
||||
<property name="base_dir" value="${path::get-full-path('.')}"/>
|
||||
<property name="bin_dir" value="${base_dir}/bin"/>
|
||||
<property name="src_dir" value="${base_dir}/source"/>
|
||||
<property name="lib_dir" value="${base_dir}/contrib"/>
|
||||
|
||||
<target name="release" description="'Release' the IronPython code and DLLs">
|
||||
<copy todir="${bin_dir}">
|
||||
<fileset basedir="${lib_dir}">
|
||||
<include name="**.dll"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${bin_dir}">
|
||||
<fileset basedir="${src_dir}">
|
||||
<include name="**.py"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="run" description="'Release' and run the bot" depends="release">
|
||||
<echo message="Running the IpyBot"/>
|
||||
<exec workingdir="${bin_dir}" program="ipy">
|
||||
<arg value="IpyBot.py"/>
|
||||
</exec>
|
||||
</target>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
import clr
|
||||
clr.AddReference('System.Data')
|
||||
clr.AddReference('Mono.Data.SqliteClient')
|
||||
clr.AddReferenceToFile('Meebey.SmartIrc4net.dll')
|
||||
|
||||
import System
|
||||
from System import *
|
||||
from System.Collections import *
|
||||
from System.Data import *
|
||||
from System.IO import *
|
||||
from System.Net import *
|
||||
from System.Text import *
|
||||
from System.Threading import *
|
||||
|
||||
from Meebey.SmartIrc4net import *
|
||||
from Mono.Data.SqliteClient import *
|
||||
|
||||
|
||||
VERSION_STRING = 'IpyBot v0.1-dev'
|
||||
|
||||
DEFAULT_NICK = 'IpyBotDev'
|
||||
DEFAULT_SERVER = 'chat.freenode.net'
|
||||
DEFAULT_PORT = 8001
|
||||
DEFAULT_CHANNELS = ['#ipybot']
|
||||
DEFAULT_AUTHORIZED = ['rtyler', 'zachallia']
|
||||
DEFAULT_COMMAND = '!'
|
||||
|
||||
class IpyBot(object):
|
||||
server = None
|
||||
port = 0
|
||||
channel = None
|
||||
client = None
|
||||
db = None
|
||||
|
||||
def OnQueryMessage(self, sender, args):
|
||||
t = args.Data.MessageArray[0]
|
||||
if t == 'dump_channel':
|
||||
req = e.Data.MessageArray[1]
|
||||
chan = self.client.GetChannel(req)
|
||||
self.client.SendMessage(SendType.Message, e.Data.Nick, 'Topic: %s' % (chan.Topic))
|
||||
|
||||
def OnError(self, sender, args):
|
||||
self.Print('*** ERROR! : %s' % args.ErrorMessage)
|
||||
Environment.Exit(1)
|
||||
|
||||
def OnRawMessage(self, sender, args):
|
||||
if 'PRIVMSG' in args.Data.RawMessage:
|
||||
contents = args.Data.RawMessage.split(':')
|
||||
who = contents[1].split('!')[0]
|
||||
if contents[2].strip() == DEFAULT_NICK:
|
||||
self.OnMessageToMe(who, contents)
|
||||
elif len(contents) >= 3:
|
||||
self.OnMessageToChannel(who, contents)
|
||||
|
||||
def OnMessageToMe(self, who, data):
|
||||
self.Print('%s said to me: %s' % (who, data))
|
||||
|
||||
def OnMessageToChannel(self, who, data):
|
||||
message = ':'.join(data[2:])
|
||||
if message.startswith(DEFAULT_COMMAND) and len(message) > len(DEFAULT_COMMAND):
|
||||
message = message[1:].split(' ')
|
||||
if len(message):
|
||||
getattr(self, 'IpyBotCommand_%s_Handler' % (message[0]), self.IpyBotCommand_Default_Handler)(who, message)
|
||||
################################################
|
||||
## IpyBot Command Handlers
|
||||
def CheckAuthorized(self, who):
|
||||
return who in DEFAULT_AUTHORIZED
|
||||
|
||||
def IpyBotCommand_learn_Handler(self, who, data):
|
||||
if not len(data) >= 4 or not data[2] == 'is' or not self.CheckAuthorized(who):
|
||||
return
|
||||
command = data[1]
|
||||
contents = ' '.join(data[3:])
|
||||
self.Print('Learning that %s is %s' % (command, contents))
|
||||
self.Store_Command(command, contents)
|
||||
|
||||
def IpyBotCommand_version_Handler(self, who, data):
|
||||
self.client.SendMessage(SendType.Action, self.channel, 'is %s' % VERSION_STRING)
|
||||
|
||||
def IpyBotCommand_Default_Handler(self, who, message):
|
||||
if not len(message):
|
||||
return
|
||||
target = ''
|
||||
if len(message) == 3 and message[1] == '@':
|
||||
target = message[2] + ': '
|
||||
val = self.Fetch_Command(message[0])
|
||||
if not val:
|
||||
self.client.SendMessage(SendType.Message, self.channel, '"%s" is an invalid IpyBot command :(' % (message[0]))
|
||||
else:
|
||||
self.client.SendMessage(SendType.Message, self.channel, '%s%s is %s' % (target, message[0], val))
|
||||
################################################
|
||||
|
||||
|
||||
################################################
|
||||
## IpyBot Sqlite Layer
|
||||
def Store_Command(self, command, contents):
|
||||
sql = '''
|
||||
INSERT INTO %s (command, contents)
|
||||
VALUES (:cmd, :cnts)
|
||||
''' % (self.CurrentChannel())
|
||||
c = self.db.CreateCommand()
|
||||
c.CommandText = sql
|
||||
c.Parameters.Add('cmd', command)
|
||||
c.Parameters.Add('cnts', contents)
|
||||
try:
|
||||
c.ExecuteNonQuery()
|
||||
return True
|
||||
except Exception, ex:
|
||||
self.Print(ex)
|
||||
return False
|
||||
def Fetch_Command(self, command):
|
||||
self.Print('Finding %s' % command)
|
||||
sql = '''
|
||||
SELECT contents FROM %s WHERE command = "%s"
|
||||
''' % (self.CurrentChannel(), command)
|
||||
c = self.db.CreateCommand()
|
||||
c.CommandText = sql
|
||||
try:
|
||||
return c.ExecuteScalar()
|
||||
except Exception, ex:
|
||||
self.Print(ex)
|
||||
return None
|
||||
################################################
|
||||
|
||||
def Print(self, message):
|
||||
print '<%s> %s' % (Thread.CurrentThread.Name, message)
|
||||
|
||||
def CurrentChannel(self):
|
||||
return self.channel.replace('#', '')
|
||||
|
||||
def __CreateBotTable(self, name):
|
||||
sql = '''
|
||||
CREATE TABLE %s (
|
||||
command TEXT PRIMARY KEY,
|
||||
contents TEXT);
|
||||
''' % (name)
|
||||
command = self.db.CreateCommand()
|
||||
command.CommandText = sql
|
||||
try:
|
||||
command.ExecuteNonQuery()
|
||||
except Exception, ex:
|
||||
pass
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.server = kwargs.get('server')
|
||||
self.port = kwargs.get('port')
|
||||
self.channel = kwargs.get('channel')
|
||||
assert self.server and self.port and self.channel, 'Missing arguments for IpyBot() constructor!'
|
||||
|
||||
self.client = IrcClient()
|
||||
self.client.Encoding = Text.Encoding.UTF8
|
||||
self.client.SendDelay = 200
|
||||
self.client.ActiveChannelSyncing = True
|
||||
|
||||
connection = 'URI=file:%s_ipybot.db' % (self.CurrentChannel())
|
||||
self.db = SqliteConnection(connection)
|
||||
self.db.Open()
|
||||
self.__CreateBotTable(self.CurrentChannel())
|
||||
|
||||
self.client.OnQueryMessage += IrcEventHandler(self.OnQueryMessage)
|
||||
self.client.OnError += IrcEventHandler(self.OnError)
|
||||
self.client.OnRawMessage += IrcEventHandler(self.OnRawMessage)
|
||||
|
||||
def __del__(self):
|
||||
if self.db:
|
||||
self.db.Close()
|
||||
|
||||
def ReadCommands(self):
|
||||
while True:
|
||||
self.client.WriteLine(Console.ReadLine())
|
||||
|
||||
def Run(self):
|
||||
try:
|
||||
self.client.Connect(self.server, self.port)
|
||||
except ConnectionException, ex:
|
||||
self.Print("Couldn't connect! %s" % ex.Message)
|
||||
return
|
||||
|
||||
try:
|
||||
self.client.Login(DEFAULT_NICK, 'IpyBot LOLZ!', 0, 'IpyBot')
|
||||
self.client.RfcJoin(self.channel)
|
||||
|
||||
self.client.SendMessage(SendType.Action, self.channel, "clears its throat")
|
||||
|
||||
Thread(ThreadStart(self.ReadCommands)).Start()
|
||||
|
||||
self.client.Listen()
|
||||
self.client.Disconnect()
|
||||
except Exception, ex:
|
||||
self.Print(ex)
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
for channel in DEFAULT_CHANNELS:
|
||||
b = IpyBot(server=DEFAULT_SERVER, port=DEFAULT_PORT, channel=channel)
|
||||
t = Thread(ThreadStart(b.Run))
|
||||
t.Name = channel
|
||||
t.Start()
|
|
@ -0,0 +1,202 @@
|
|||
/**
|
||||
* $Id$
|
||||
* $Revision$
|
||||
* $Author$
|
||||
* $Date$
|
||||
*
|
||||
* SmartIrc4net - the IRC library for .NET/C# <http://smartirc4net.sf.net>
|
||||
* This is a simple test client for the library.
|
||||
*
|
||||
* Copyright (c) 2003-2004 Mirco Bauer <meebey@meebey.net> <http://www.meebey.net>
|
||||
*
|
||||
* Full LGPL License: <http://www.gnu.org/licenses/lgpl.txt>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
using Meebey.SmartIrc4net;
|
||||
|
||||
// This is an VERY basic example how your IRC application could be written
|
||||
// its mainly for showing how to use the API, this program just connects sends
|
||||
// a few message to a channel and waits for commands on the console
|
||||
// (raw RFC commands though! it's later explained).
|
||||
// There are also a few commands the IRC bot/client allows via private message.
|
||||
public class Test
|
||||
{
|
||||
// make an instance of the high-level API
|
||||
public static IrcClient irc = new IrcClient();
|
||||
|
||||
// this method we will use to analyse queries (also known as private messages)
|
||||
public static void OnQueryMessage(object sender, IrcEventArgs e)
|
||||
{
|
||||
switch (e.Data.MessageArray[0]) {
|
||||
// debug stuff
|
||||
case "dump_channel":
|
||||
string requested_channel = e.Data.MessageArray[1];
|
||||
// getting the channel (via channel sync feature)
|
||||
Channel channel = irc.GetChannel(requested_channel);
|
||||
|
||||
// here we send messages
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, "<channel '"+requested_channel+"'>");
|
||||
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, "Name: '"+channel.Name+"'");
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, "Topic: '"+channel.Topic+"'");
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, "Mode: '"+channel.Mode+"'");
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, "Key: '"+channel.Key+"'");
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, "UserLimit: '"+channel.UserLimit+"'");
|
||||
|
||||
// here we go through all users of the channel and show their
|
||||
// hashtable key and nickname
|
||||
string nickname_list = "";
|
||||
nickname_list += "Users: ";
|
||||
foreach (DictionaryEntry de in channel.Users) {
|
||||
string key = (string)de.Key;
|
||||
ChannelUser channeluser = (ChannelUser)de.Value;
|
||||
nickname_list += "(";
|
||||
if (channeluser.IsOp) {
|
||||
nickname_list += "@";
|
||||
}
|
||||
if (channeluser.IsVoice) {
|
||||
nickname_list += "+";
|
||||
}
|
||||
nickname_list += ")"+key+" => "+channeluser.Nick+", ";
|
||||
}
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, nickname_list);
|
||||
|
||||
irc.SendMessage(SendType.Message, e.Data.Nick, "</channel>");
|
||||
break;
|
||||
case "gc":
|
||||
GC.Collect();
|
||||
break;
|
||||
// typical commands
|
||||
case "join":
|
||||
irc.RfcJoin(e.Data.MessageArray[1]);
|
||||
break;
|
||||
case "part":
|
||||
irc.RfcPart(e.Data.MessageArray[1]);
|
||||
break;
|
||||
case "die":
|
||||
Exit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// this method handles when we receive "ERROR" from the IRC server
|
||||
public static void OnError(object sender, ErrorEventArgs e)
|
||||
{
|
||||
System.Console.WriteLine("Error: "+e.ErrorMessage);
|
||||
Exit();
|
||||
}
|
||||
|
||||
// this method will get all IRC messages
|
||||
public static void OnRawMessage(object sender, IrcEventArgs e)
|
||||
{
|
||||
System.Console.WriteLine("Received: "+e.Data.RawMessage);
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Thread.CurrentThread.Name = "Main";
|
||||
|
||||
// UTF-8 test
|
||||
irc.Encoding = System.Text.Encoding.UTF8;
|
||||
|
||||
// wait time between messages, we can set this lower on own irc servers
|
||||
irc.SendDelay = 200;
|
||||
|
||||
// we use channel sync, means we can use irc.GetChannel() and so on
|
||||
irc.ActiveChannelSyncing = true;
|
||||
|
||||
// here we connect the events of the API to our written methods
|
||||
// most have own event handler types, because they ship different data
|
||||
irc.OnQueryMessage += new IrcEventHandler(OnQueryMessage);
|
||||
irc.OnError += new ErrorEventHandler(OnError);
|
||||
irc.OnRawMessage += new IrcEventHandler(OnRawMessage);
|
||||
|
||||
string[] serverlist;
|
||||
// the server we want to connect to, could be also a simple string
|
||||
serverlist = new string[] {"irc.freenode.org"};
|
||||
int port = 6667;
|
||||
string channel = "#smartirc-test";
|
||||
try {
|
||||
// here we try to connect to the server and exceptions get handled
|
||||
irc.Connect(serverlist, port);
|
||||
} catch (ConnectionException e) {
|
||||
// something went wrong, the reason will be shown
|
||||
System.Console.WriteLine("couldn't connect! Reason: "+e.Message);
|
||||
Exit();
|
||||
}
|
||||
|
||||
try {
|
||||
// here we logon and register our nickname and so on
|
||||
irc.Login("SmartIRC", "SmartIrc4net Test Bot");
|
||||
// join the channel
|
||||
irc.RfcJoin(channel);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// here we send just 3 different types of messages, 3 times for
|
||||
// testing the delay and flood protection (messagebuffer work)
|
||||
irc.SendMessage(SendType.Message, channel, "test message ("+i.ToString()+")");
|
||||
irc.SendMessage(SendType.Action, channel, "thinks this is cool ("+i.ToString()+")");
|
||||
irc.SendMessage(SendType.Notice, channel, "SmartIrc4net rocks ("+i.ToString()+")");
|
||||
}
|
||||
|
||||
// spawn a new thread to read the stdin of the console, this we use
|
||||
// for reading IRC commands from the keyboard while the IRC connection
|
||||
// stays in its own thread
|
||||
new Thread(new ThreadStart(ReadCommands)).Start();
|
||||
|
||||
// here we tell the IRC API to go into a receive mode, all events
|
||||
// will be triggered by _this_ thread (main thread in this case)
|
||||
// Listen() blocks by default, you can also use ListenOnce() if you
|
||||
// need that does one IRC operation and then returns, so you need then
|
||||
// an own loop
|
||||
irc.Listen();
|
||||
|
||||
// when Listen() returns our IRC session is over, to be sure we call
|
||||
// disconnect manually
|
||||
irc.Disconnect();
|
||||
} catch (ConnectionException) {
|
||||
// this exception is handled because Disconnect() can throw a not
|
||||
// connected exception
|
||||
Exit();
|
||||
} catch (Exception e) {
|
||||
// this should not happen by just in case we handle it nicely
|
||||
System.Console.WriteLine("Error occurred! Message: "+e.Message);
|
||||
System.Console.WriteLine("Exception: "+e.StackTrace);
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadCommands()
|
||||
{
|
||||
// here we read the commands from the stdin and send it to the IRC API
|
||||
// WARNING, it uses WriteLine() means you need to enter RFC commands
|
||||
// like "JOIN #test" and then "PRIVMSG #test :hello to you"
|
||||
while (true) {
|
||||
irc.WriteLine(System.Console.ReadLine());
|
||||
}
|
||||
}
|
||||
|
||||
public static void Exit()
|
||||
{
|
||||
// we are done, lets exit...
|
||||
System.Console.WriteLine("Exiting...");
|
||||
System.Environment.Exit(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue