Created
February 20, 2010 19:00
-
-
Save sonicrules1234/309832 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import conf, world, sonicbotv3, thread, time, socket, shelve, simplejson, traceback, urllib, sys | |
class sonicbotd : | |
def onConnect(self, sock, address) : | |
self.sock = sock | |
self.buffer = "" | |
self.address = address[0] | |
self.status = {"connected":True} | |
print "Receiving from %s" % (self.address) | |
if self.address in ["127.1.0.1", "127.0.0.1"] : return self.startLoop() | |
def startLoop(self) : | |
while self.status["connected"] : | |
data = self.sock.recv(4096) | |
parsed = self.parseData(data) | |
self.sock.close() | |
return parsed | |
def parseData(self, data) : | |
print "[IN %s] %s" % (self.address, data) | |
self.status["connected"] = False | |
try : json = simplejson.loads(data) | |
except : | |
traceback.print_exc() | |
print data | |
json = None | |
return json | |
print "Starting..." | |
class ErrorLogger: | |
def write(self, s): | |
errors = open("errors.txt", "a") | |
errors.write(s) | |
errors.close() | |
class OutputLogger: | |
def write(self, s): | |
output = open("output.txt", "a") | |
output.write(s) | |
output.close() | |
sys.stdin.close() | |
sys.stdout = OutputLogger() | |
sys.stderr = ErrorLogger() | |
try: | |
pid = os.fork() | |
if pid > 0: | |
# exit first parent | |
sys.exit(0) | |
except OSError, e: | |
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) | |
sys.exit(1) | |
pidfile = open("pid.txt", "w") | |
pidfile.write(str(os.getpid()) + "\n") | |
pidfile.close() | |
botinstance = sonicbotv3.sonicbot() | |
thread.start_new_thread(botinstance.start, (conf.hosts[world.hostcount], conf.ports[world.hostcount])) | |
try : | |
if conf.committracker : | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
s.bind(('', 9001)) | |
s.listen(1) | |
while True : | |
conn, addr = s.accept() | |
d = sonicbotd() | |
json = d.onConnect(conn, addr) | |
try : | |
if json != None : | |
commits = shelve.open("commits.db", writeback=True) | |
if not commits.has_key("networks") : | |
commits["networks"] = {} | |
commits.sync() | |
for network in commits["networks"].keys() : | |
for channel in commits["networks"][network].keys() : | |
if json[u"repository"][u"url"].encode("utf-8") in commits["networks"][network][channel] : | |
for commit in json[u"commits"] : | |
if network in world.connections.keys() : world.connections[network].ircsend(channel, "Commit to %s by %s '%s' %s" % (json[u"repository"][u"name"].encode("utf-8"), commit[u"author"][u"name"].encode("utf-8"), commit[u"message"].encode("utf-8"), urllib.urlopen("http://is.gd/api.php?longurl=" + commit[u"url"].encode("utf-8")).read())) | |
commits.close() | |
except : traceback.print_exc() | |
else : | |
while True : | |
time.sleep(5) | |
except : | |
traceback.print_exc() | |
for connection in world.connections.keys() : | |
world.connections[connection].rawsend("QUIT :Hmm, somebody hit Ctrl-C, better /quit!\n") | |
world.connections[connection].cleanup() | |
print "Shutting down..." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# Copyright (c) 2009, Westly Ward | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions are met: | |
# * Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# * Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in the | |
# documentation and/or other materials provided with the distribution. | |
# * Neither the name of the Sonicbot Team nor the | |
# names of its contributors may be used to endorse or promote products | |
# derived from this software without specific prior written permission. | |
# | |
# THIS SOFTWARE IS PROVIDED BY Westly Ward ''AS IS'' AND ANY | |
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
# DISCLAIMED. IN NO EVENT SHALL Westly Ward BE LIABLE FOR ANY | |
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
import time, glob, shelve, traceback, os, aiml, imp, select, random | |
import socket, conf, thread, world | |
if world.pythonversion == "2.6" : | |
import ssl | |
elif True in conf.ssl : import OpenSSL | |
class sonicbot : | |
def connect(self) : | |
self.cleaningup = False | |
self.error = "" | |
"""Initiates sonicbot after it is connected""" | |
try : | |
if conf.bpass != "" : self.rawsend("PASS %s\n" % (conf.bpass)) | |
self.rawsend("NICK %s \n" % (conf.nick)) | |
self.rawsend("USER %s * * :%s\n" % (conf.ident, conf.realname)) | |
self.plugins = {} | |
for filename in glob.glob("plugins/*.pyc") : | |
os.remove(filename) | |
for plugin in glob.glob("plugins/*.py") : | |
if plugin != "plugins/__init__.py" and plugin != "plugins\\__init__.py" : | |
self.plugins[plugin.replace("plugins\\", "").replace("plugins/", "").replace(".py", "")] = imp.load_source(plugin.replace("plugins\\", "").replace("plugins/", "").replace(".py", ""), plugin) | |
world.connections[self.host] = self | |
if world.hostcount + 1 != len(conf.channels.keys()) and not self.unittest : | |
world.hostcount += 1 | |
new = sonicbot() | |
thread.start_new_thread(new.start, (conf.hosts[world.hostcount], conf.ports[world.hostcount])) | |
except : | |
errorlog = open("errorlog.txt", "a") | |
errorlog.write(traceback.format_exc() + "\n") | |
errorlog.close() | |
traceback.print_exc() | |
print "Connected to", self.host | |
try : | |
self.logf = open("raw.txt", "a") | |
self.factoids = shelve.open("factoids.db") | |
self.channels = {} | |
self.logs = {} | |
self.logs[conf.nick] = open("PMs.txt", "a") | |
if conf.ai : | |
self.ai = aiml.Kernel() | |
self.ai.learn("std-startup.xml") | |
self.ai.setBotPredicate("name", conf.nick) | |
self.ai.setBotPredicate("master", conf.owner) | |
self.ai.setBotPredicate("gender", "male") | |
self.ai.respond("load aiml b") | |
self.nicks = {} | |
self.buffer = "" | |
self.chanmodes = {} | |
self.users = shelve.open("users-%s.db" % (world.hostnicks[self.host]), writeback=True) | |
if not self.users.has_key("users") : | |
self.users["users"] = {} | |
self.users.sync() | |
for admin in conf.admin.keys() : | |
self.users["users"][admin] = {"userlevel":4, "hostname":conf.admin[admin]} | |
self.users.sync() | |
self.users["users"][conf.owner]["userlevel"] = 5 | |
self.users.sync() | |
if not self.users.has_key("channels") : | |
self.users["channels"] = {} | |
self.users.sync() | |
if not self.users.has_key("hostignores") : | |
self.users["hostignores"] = [] | |
self.users.sync() | |
self.timer = 0 | |
except : traceback.print_exc() | |
world.connections[self.host] = self | |
world.rconnections[self.sock] = self.host | |
world.instances[self.sock] = self | |
world.conlist.append(self.sock) | |
if not world.waitfordatastarted : | |
thread.start_new_thread(waitfordata, ()) | |
world.waitfordatastarted = True | |
def start(self, host, port) : | |
"""Starts the preparation for connecting""" | |
self.counter = 0 | |
error = False | |
self.unittest = False | |
self.bufferin = open("in-%s.txt" % (host), "w") | |
self.bufferout = open("out-%s.txt" % (host), "w") | |
try : | |
self.host = host | |
self.port = port | |
if conf.ipv6[conf.hosts.index(self.host)] : | |
self.iptype = socket.AF_INET6 | |
else : | |
self.iptype = socket.AF_INET | |
self.sock = socket.socket(self.iptype, socket.SOCK_STREAM) | |
if conf.ssl[conf.hosts.index(self.host)] : | |
if world.pythonversion == "2.6" : | |
self.sock = ssl.wrap_socket(self.sock) | |
except : | |
errorlog = open("errorlog.txt", "a") | |
errorlog.write(traceback.format_exc() + "\n") | |
errorlog.close() | |
traceback.print_exc() | |
try : | |
if conf.ssl[conf.hosts.index(self.host)] and world.pythonversion == "2.5" : | |
self.sock = OpenSSL.SSL.Connection(OpenSSL.SSL.Context(OpenSSL.SSL.SSLv3_METHOD), self.sock) | |
self.sock.connect((self.host, self.port)) | |
except : error = True | |
error3 = True | |
while error3 : | |
try : | |
self.sock.bind(("94.75.233.122", random.randint(60000, 65535))) | |
error3 = False | |
except : pass | |
if not error : self.connect() | |
def dataReceived(self, data): | |
"""Parses the data into a dict named info""" | |
if conf.debug : | |
print "[IN %s]" % (self.host) + data | |
self.bufferin.write(self.buffer + "\n") | |
self.logf.write("[IN]%s" % (data)) | |
error = 0 | |
lines = data.replace("\r", "").split("\n") | |
lines[0] = self.buffer + lines[0] | |
self.bufferout.write(self.buffer + "\n") | |
self.buffer = lines[-1] | |
for line in lines[:-1] : | |
if line != "" : | |
try: | |
if line.split(" ")[0] == "PING" : self.rawsend("PONG %s\n" % (line.split(" ")[1])) | |
info = {} | |
info["raw"] = line | |
info["words"] = line[1:].split(" ") | |
if info["words"][1] == "001" : | |
self.rawsend("MODE %s +B\n" % (conf.nick)) | |
self.ircsend("NickServ", "IDENTIFY %s" % (conf.bpass)) | |
for i in conf.channels[self.host] : | |
self.rawsend("JOIN %s \n" % (i)) | |
if self.host in conf.connectcommands : | |
for command in conf.connectcommands[self.host] : | |
exec(command) | |
info["whois"] = info["words"][0] | |
info["sender"] = info["whois"].split("!")[0] | |
except : traceback.print_exc() | |
try : | |
info["hostname"] = info["whois"].split("@")[1] | |
self.nicks[info["sender"]] = info["hostname"] | |
except : info["hostname"] = "Unknown" | |
try : info["mode"] = info["words"][1] | |
except : info["mode"] = "Unknown" | |
try : | |
if info["words"][2] == conf.nick : | |
info["channel"] = info["sender"] | |
else : info["channel"] = info["words"][2].replace(":", "").lower() | |
except : info["channel"] = "Unknown" | |
try : | |
if info["mode"] == "PRIVMSG" or info["mode"] == "TOPIC" : | |
if ":" in info["words"][3] : info["message"] = " ".join(info["words"][3:])[1:] | |
else : info["message"] = " ".join(info["words"][3:]) | |
else : info["message"] = "Unknown" | |
except : error = 1 | |
self.info = info | |
if error != 1 : self.prettify(info) | |
def rawsend(self, msg_out) : | |
"""Sends raw data through the socket""" | |
try : | |
self.sock.send(msg_out) | |
if conf.debug : print "[OUT]%s" % (msg_out) | |
except : | |
print "Connection lost to", self.host | |
traceback.print_exc() | |
self.cleanup() | |
def cleanup(self) : | |
"""Cleans up various variables after disconnection""" | |
if not self.cleaningup : | |
self.cleaningup = True | |
if "logf" in dir(self) : self.logf.close() | |
if "channels" in dir(self) : | |
for channel in self.channels : | |
self.logs[channel].close() | |
self.users.close() | |
self.factoids.close() | |
if self.host in world.connections.keys() : del world.connections[self.host] | |
if self.host in conf.autoreconnect : | |
self.ssl = conf.ssl[conf.hosts.index(self.host)] | |
conf.ports.pop(conf.hosts.index(self.host)) | |
conf.ssl.pop(conf.hosts.index(self.host)) | |
conf.hosts.remove(self.host) | |
conf.ssl.append(self.ssl) | |
conf.hosts.append(self.host) | |
conf.ports.append(self.port) | |
newsonicbot = sonicbot() | |
thread.start_new_thread(newsonicbot.start, (self.host, self.port)) | |
else : | |
conf.ports.pop(conf.hosts.index(self.host)) | |
conf.ssl.pop(conf.hosts.index(self.host)) | |
conf.hosts.remove(self.host) | |
del conf.channels[self.host] | |
def on_ACTION(self, info, args) : | |
"""Responds to CTCP ACTION's""" | |
self.logwrite(info["channel"], "[%s] *%s %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], " ".join(args[1:]).replace("", ""))) | |
if not conf.debug : "[%s] *%s %s\n" % (time.strftime("%H:%M:%S"), info["sender"], " ".join(args[1:]).replace("", "")) | |
if "on_ACTION" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_ACTION"].main(self, info, conf) | |
def on_TIME(self, info) : | |
"""Responds to CTCP TIME's""" | |
if "on_TIME" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_TIME"].main(self, info, conf) | |
def on_VERSION(self, info) : | |
"""Reponds to CTCP VERSION's""" | |
self.rawsend("NOTICE %s :VERSION SonicBot version 3.4.0\n" % (info["sender"])) | |
def enable_all_plugins(self, info) : | |
"""Enables all plugins for the current channel""" | |
self.users["channels"][info["channel"]]["enabled"] = [] | |
self.users.sync() | |
for plugin in self.plugins["pluginlist"].pluginlist : | |
self.users["channels"][info["channel"]]["enabled"].append(plugin) | |
self.users.sync() | |
def on_PRIVMSG(self, info) : | |
"""This function gets called whenever sonicbot receives data with the PRIVMSG commdand from the server. This includes PM's and any talking in the channels""" | |
if not info["message"]: return | |
if not info["channel"].startswith("#") : | |
if info["channel"] in self.users["channels"] : | |
if self.users["channels"][info["channel"]]["registered"] : | |
pass | |
else : | |
self.enable_all_plugins(info) | |
else : | |
self.users["channels"][info["channel"]] = {"registered":False, "enabled":[]} | |
self.users.sync() | |
self.enable_all_plugins(info) | |
if info["channel"] in self.channels : self.logwrite(info["channel"], "[%s] <%s> %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], info["message"])) | |
if info["message"][0] == conf.prefix or info["message"].split(" ")[0] == conf.nick + ":" : | |
self.command_parser(info) | |
if "on_PRIVMSG" in self.plugins["pluginlist"].eventlist: | |
self.plugins["on_PRIVMSG"].main(self, info, conf) | |
def on_JOIN(self, info) : | |
"""This function gets called whenever somebody joins a channel, including sonicbot himself""" | |
if conf.nick == info["sender"] : | |
self.logs[info["channel"]] = open("%s/%s.txt" % (conf.logdir, info["channel"]), "a") | |
self.channels[info["channel"]] = [] | |
self.chanmodes[info["channel"]] = {} | |
if info["channel"] in self.users["channels"] : | |
if self.users["channels"][info["channel"]]["registered"] : | |
pass | |
else : | |
self.enable_all_plugins(info) | |
else : | |
self.users["channels"][info["channel"]] = {"registered":False, "enabled":[]} | |
self.users.sync() | |
self.enable_all_plugins(info) | |
else : | |
if info["sender"] not in info["channel"] : self.channels[info["channel"]].append(info["sender"]) | |
self.chanmodes[info["channel"]][info["sender"]] = [] | |
self.logwrite(info["channel"], "[%s] ***%s has joined %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], info["channel"])) | |
if "on_JOIN" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_JOIN"].main(self, info, conf) | |
if info["sender"] == conf.nick : self.rawsend("WHO %s\n" % (info["channel"])) | |
def on_PART(self, info) : | |
"""This function is called whenever somebody parts the channel, including sonicbot himself""" | |
self.logwrite(info["channel"], "[%s] ***%s has parted %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], info["channel"])) | |
if conf.nick == info["sender"] : | |
self.logs[info["channel"]].close() | |
del self.channels[info["channel"]] | |
del self.chanmodes[info["channel"]] | |
else : | |
if info["sender"] in info["channel"] : self.channels[info["channel"]].remove(info["sender"]) | |
if "on_PART" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_PART"].main(self, info, conf) | |
def on_QUIT(self, info) : | |
"""This function is called whenever somebody quits, but not when sonicbot quits""" | |
quitmessage = " ".join(info["words"][2:])[1:] | |
for channel in self.channels : | |
if info["sender"] in self.channels[channel] : | |
self.channels[channel].remove(info["sender"]) | |
self.logwrite(channel, "[%s] ***%s has quit (%s)\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], quitmessage)) | |
if info["sender"] == conf.nick : self.logs[channel].close() | |
if "on_QUIT" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_QUIT"].main(self, info, conf) | |
def on_KICK(self, info) : | |
"""This function is called whenever somebody gets kicked, including sonicbot himself""" | |
recvr = info["words"][3] | |
self.logwrite(info["channel"], "[%s] **%s has kicked %s from %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], recvr, info["channel"])) | |
self.channels[info["channel"]].remove(recvr) | |
if "on_KICK" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_KICK"].main(self, info, conf) | |
def on_TOPIC(self, info) : | |
"""This function is called whenever somebody somebody changes the topic, including sonicbot himself""" | |
self.logwrite(info["channel"], '[%s] **%s has changed the topic in %s to "%s"\n' % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], info["channel"], info["message"])) | |
if "on_TOPIC" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_TOPIC"].main(self, info, conf) | |
def on_MODE(self, info) : | |
"""This function is called whenever modes are changed""" | |
try : | |
mode = info["words"][3] | |
modesymbols = {"y":"!", "h":"%", "o":"@", "v":"+", "F":"~", "q":"~", "a":"&"} | |
if len(info["words"]) > 4 : | |
recvrs = info["words"][4:] | |
recvr = 0 | |
self.logwrite(info["channel"], "[%s] **%s set mode %s on %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], mode, " ".join(recvrs))) | |
for letter in mode: | |
if letter == "+" : modetype = True | |
elif letter == "-" : modetype = False | |
else : | |
if letter in modesymbols.keys() : | |
print self.host | |
if modetype : | |
if letter not in self.chanmodes[info["channel"]][recvrs[recvr]] : | |
self.chanmodes[info["channel"]][recvrs[recvr]].append(modesymbols[letter]) | |
elif not modetype : | |
if letter in self.chanmodes[info["channel"]][recvrs[recvr]] : | |
self.chanmodes[info["channel"]][recvrs[recvr]].remove(letter) | |
recvr += 1 | |
else : | |
self.logwrite(conf.nick, "[%s] **%s set mode %s on %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], mode, info["channel"])) | |
except : | |
traceback.print_exc() | |
if "on_MODE" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_MODE"].main(self, info, conf) | |
def on_NICK(self, info) : | |
"""This function is called whenever somebody /nick's""" | |
if ":" in info["words"][2] : | |
newnick = info["words"][2][1:] | |
else : newnick = info["words"][2] | |
self.nicks[newnick] = info["hostname"] | |
if not conf.debug : print "[%s]**%s is now known as %s" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], info["words"][2][1:]) | |
for channel in self.channels : | |
if info["sender"] in self.channels[channel] : | |
self.channels[channel].remove(info["sender"]) | |
self.channels[channel].append(newnick) | |
self.chanmodes[channel][newnick] = self.chanmodes[channel][info["sender"]] | |
del self.chanmodes[channel][info["sender"]] | |
self.logwrite(channel, "[%s] **%s is now known as %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), info["sender"], newnick)) | |
if "on_NICK" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_NICK"].main(self, info, conf) | |
def on_INVITE(self, info): | |
"""This function is called whenever somebody invites sonicbot to the channel""" | |
if "on_INVITE" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_INVITE"].main(self, info, conf) | |
def on_353(self, info) : | |
"""Generates a list of nicks in the channel, also tries to see what modes they have.""" | |
try : | |
for nick in info["words"][5:] : | |
if nick != "" : | |
correctnick = nick.replace(":", "") | |
newnick = nick.replace(":", "") | |
for mode in ["!", "%", "@", "&", "~", "+"] : | |
newnick = newnick.replace(mode, "") | |
self.chanmodes[info["words"][4].lower()][newnick] = [] | |
for mode in ["!", "%", "@", "&", "~", "+"] : | |
if mode in correctnick : | |
self.chanmodes[info["words"][4].lower()][newnick].append(mode) | |
correctnick = newnick | |
self.channels[info["words"][4].lower()].append(correctnick) | |
if "on_353" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_353"].main(self, info, conf) | |
except : traceback.print_exc() | |
def on_352(self, info) : | |
self.nicks[info["words"][7]] = info["words"][5] | |
if "on_352" in self.plugins["pluginlist"].eventlist : | |
self.plugins["on_352"].main(self, info, conf) | |
def prettify(self, info) : | |
"""Takes the parsed data and decides what to do with it""" | |
args = info["message"].split(" ") | |
if info["mode"] == "PRIVMSG" : | |
if args[0] == "ACTION" : | |
self.on_ACTION(info, args) | |
elif info["message"] == "VERSION" : | |
self.on_VERSION(info) | |
elif info["message"] == "TIME" : | |
self.on_TIME(info) | |
else : | |
self.on_PRIVMSG(info) | |
elif info["mode"] == "JOIN" : | |
self.on_JOIN(info) | |
elif info["mode"] == "PART" : | |
self.on_PART(info) | |
elif info["mode"] == "QUIT": | |
self.on_QUIT(info) | |
elif info["mode"] == "KICK" : | |
recvr = info["words"][3] | |
self.on_KICK(info) | |
elif info["mode"] == "TOPIC" : | |
self.on_TOPIC(info) | |
elif info["mode"] == "MODE" : | |
self.on_MODE(info) | |
elif info["mode"] == "INVITE" : | |
self.on_INVITE(info) | |
elif info["mode"] == "NICK" : | |
self.on_NICK(info) | |
elif info["mode"] == "353" : | |
self.on_353(info) | |
elif info["mode"] == "352" : | |
self.on_352(info) | |
elif "on_%s" % (info["mode"]) in self.plugins["pluginlist"].eventlist : | |
try : | |
self.plugins['on_%s' % info["mode"]].main(self, info, conf) | |
except : | |
self.ircsend(conf.owner, traceback.format_exc()) | |
def command_parser(self, info) : | |
"""This function is called whenever somebody issues a command to sonicbot""" | |
notacommand = False | |
args = info["message"][1:].split(" ") | |
if args == [] : args.append("") | |
if info["message"].split(" ")[0] == conf.nick + ":" : | |
if conf.ai and info["sender"] not in conf.ignorelist and "sing" not in info["message"] : | |
response = self.ai.respond(" ".join(args[1:]), info["sender"]) | |
self.ircsend(info["channel"], "%s: %s" % (info["sender"], response)) | |
else : | |
args = info["message"].split(" ")[1:] | |
if args == [] : args.append("") | |
info["message"] = conf.prefix + " ".join(args) | |
if info["message"][0] == conf.prefix and info["sender"] in conf.admin and info["hostname"] in conf.admin[info["sender"]] and info["sender"] not in conf.ignorelist and info["hostname"] not in conf.hostignores : | |
if args[0] == "quit" and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]] : | |
self.rawsend("QUIT :Leaving\n") | |
# self.sock.close() | |
if self.host in conf.autoreconnect : | |
conf.autoreconnect.remove(self.host) | |
elif args[0] == "add" and " is " in info["message"]: | |
if " ".join(args[1:]).split(" is ", 1)[0] not in self.plugins["pluginlist"].pluginlist : | |
self.factoids[" ".join(args[1:]).split(" is ", 1)[0]] = info["message"].split(" is ", 1)[1] | |
self.factoids.sync() | |
self.ircsend(info["channel"], "Factoid %s was successfully added" % (" ".join(args[1:]).split(" is ")[0])) | |
else : self.ircsend(info["channel"], "There is already a plugin with that name") | |
elif args[0] == "remove" : | |
if self.factoids.has_key(" ".join(args[1:])) : | |
del self.factoids[" ".join(args[1:])] | |
self.factoids.sync() | |
self.ircsend(info["channel"], "Factoid successfully deleted") | |
else : self.ircsend(info["channel"], "That factoid does not exist!") | |
elif args[0] == "+ai" and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]] : | |
conf.ai = True | |
self.ai = aiml.Kernel() | |
self.ai.learn("std-startup.xml") | |
self.ai.setBotPredicate("name", conf.nick) | |
self.ai.setBotPredicate("master", conf.owner) | |
self.ai.setBotPredicate("gender", "male") | |
self.ai.respond("load aiml b") | |
self.ircsend(info["channel"], "AI has been turned on") | |
elif args[0] == "-ai" and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]] : | |
conf.ai = False | |
self.ircsend(info["channel"], "AI has been turned off") | |
elif args[0] == "+relay" and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]] : | |
if info["channel"] not in world.relay_channels : | |
world.relay_channels.append(info["channel"]) | |
self.ircsend(info["channel"], "This channel has been added to the relay list") | |
else : self.ircsend(info["channel"], "This channel is already on the relay list!") | |
elif args[0] == "-relay" and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]] : | |
if info["channel"] in world.relay_channels : | |
world.relay_channels.remove(info["channel"]) | |
self.ircsend(info["channel"], "This channel has been removed the relay list") | |
else : self.ircsend(info["channel"], "This channel is not on the relay list!") | |
elif args[0] == "connect" and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]]: | |
conf.hosts.append(args[1]) | |
conf.ports.append(int(args[2])) | |
world.hostcount += 1 | |
if args[3] == "1" : | |
conf.ssl.append(True) | |
else : conf.ssl.append(False) | |
if args[4] == "1" : | |
conf.ipv6.append(True) | |
else : conf.ipv6.append(False) | |
world.hostnicks[args[1]] = args[5] | |
conf.channels[args[1]] = args[6:] | |
newbotinstance = sonicbot() | |
thread.start_new_thread(newbotinstance.start, (args[1], int(args[2]))) | |
elif args[0] == "eval" and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]] : | |
try : self.ircsend(info["channel"], str(eval(" ".join(args[1:])))) | |
except : | |
traceback.print_exc() | |
self.ircsend(info["channel"], "Error") | |
elif args[0] == '+ignore' : | |
if args[1] != conf.owner : | |
conf.ignorelist.append(args[1]) | |
if args[1] in self.nicks : | |
if self.nicks[args[1]] not in conf.hostignores : | |
conf.hostignores.append(self.nicks[args[1]]) | |
self.ircsend(info["channel"], "%s will now be ignored" % (args[1])) | |
else : self.ircsend(info["channel"], "I will never ignore my owner!") | |
elif args[0] == "-ignore" : | |
if args[1] in conf.ignorelist and info["sender"] == conf.owner and info["hostname"] in conf.admin[info["sender"]] : | |
conf.ignorelist.remove(args[1]) | |
if args[1] in self.nicks : | |
if self.nicks[args[1]] in conf.hostignores : | |
conf.hostignores.remove(self.nicks[args[1]]) | |
self.ircsend(info["channel"], "%s has been removed from the ignore list" % (args[1])) | |
else : self.ircsend(info["channel"], "No such nick in the ignore list!") | |
elif args[0] == "reload" : | |
for filename in glob.glob("plugins/*.pyc") : | |
os.remove(filename) | |
temphosts = conf.hosts | |
tempports = conf.ports | |
tempssl = conf.ssl | |
tempipv6 = conf.ipv6 | |
tempignorelist = conf.ignorelist | |
temphostignores = conf.hostignores | |
reload(conf) | |
conf.hosts = temphosts | |
conf.ports = tempports | |
conf.ssl = tempssl | |
conf.ipv6 = tempipv6 | |
conf.ignorelist = tempignorelist | |
conf.hostignores = temphostignores | |
self.oldplugins = self.plugins.copy() | |
self.plugins = {} | |
print repr(self.plugins) | |
for plugin in glob.glob("plugins/*.py") : | |
if plugin != "plugins/__init__.py" and plugin != "plugins\\__init__.py" : | |
self.plugins[plugin.replace("plugins\\", "").replace("plugins/", "").replace(".py", "")] = imp.load_source(plugin.replace("plugins\\", "").replace("plugins/", "").replace(".py", ""), plugin) | |
channels = self.users["channels"] | |
for plugin in self.oldplugins["pluginlist"].pluginlist : | |
if plugin not in self.plugins["pluginlist"].pluginlist : | |
temp = self.users["channels"].keys() | |
for channel in temp : | |
if plugin in self.users["channels"]["enabled"] : | |
channels[channel]["enabled"].remove(plugin) | |
self.users["channels"] = channels | |
self.users.sync() | |
del self.oldplugins | |
self.ircsend(info["channel"], "Config and plugins reloaded.") | |
else : notacommand = True | |
if info["message"][0] == conf.prefix and info["sender"] not in conf.ignorelist and info["hostname"] not in conf.hostignores: | |
notacommand2 = False | |
if self.factoids.has_key(info["message"][1:]) : | |
self.ircsend(info["channel"], self.factoids[info["message"][1:]]) | |
elif " | " in info["message"] and args[0] not in self.plugins["pluginlist"].pluginlist: | |
if self.factoids.has_key(info["message"].split(" | ")[0][1:]) and info["message"].split(" | ", 1)[1].strip() and info["sender"] != info["channel"] : | |
if info["message"].split(" | ", 1)[1].strip() in self.channels[info["channel"]] : | |
self.ircsend(info["channel"], "%s: %s" % (info["message"].split(" | ", 1)[1].strip(), self.factoids[info["message"].split(" | ")[0][1:]])) | |
else : self.ircsend(info["channel"], "%s: %s" % (info["sender"], self.factoids[info["message"].split(" | ")[0][1:]])) | |
elif self.factoids.has_key(info["message"].split(" | ")[0][1:]) : | |
self.ircsend(info["channel"], "%s: %s" % (info["sender"], self.factoids[info["message"].split(" | ")[0][1:]])) | |
else : notacommand2 = True | |
elif args[0] in self.plugins["pluginlist"].pluginlist : | |
try : | |
arguments = eval(", ".join(self.plugins[args[0]].arguments)) | |
if args[0] in self.users["channels"][info["channel"]]["enabled"] : | |
if self.auth(info, self.plugins[args[0]].minlevel) : | |
self.plugins[args[0]].main(*arguments) | |
else : self.ircsend(info["channel"], "%s: You do not have a high enough user level and/or privleges in this channel to use that command!" % (info["sender"])) | |
else : self.ircsend(info["channel"], "That plugin is not enabled in this channel. To enable it, use ;enable %s" % (args[0])) | |
except: | |
self.error = traceback.format_exc() | |
print self.error | |
self.ircsend(info["channel"], "Error. The syntax for that command is: %s" % (eval("self.plugins['%s'].helpstring" % (args[0])))) | |
elif notacommand or notacommand2 : | |
pass | |
def ircfilter(self, string, bads=[]) : | |
"""Filters any output""" | |
for bad in bads : | |
string = string.replace(bad, "") | |
return string | |
def auth(self, info, minlevel) : | |
"""Authenticates users""" | |
if info["sender"] not in self.users["users"].keys() : | |
self.users["users"][info["sender"]] = {"hostname":[self.nicks[info["sender"]]], "userlevel":1} | |
self.users.sync() | |
if self.users["users"][info["sender"]]["userlevel"] in [0, 1] and self.nicks[info["sender"]] not in self.users["users"][info["sender"]]["hostname"]: | |
self.users["users"][info["sender"]]["hostname"].append(self.nicks[info["sender"]]) | |
self.users.sync() | |
if info["hostname"] in self.users["users"][info["sender"]]["hostname"] or minlevel == 1 : | |
if self.users["users"][info["sender"]]["userlevel"] >= minlevel : | |
if minlevel != 3 or self.users["users"][info["sender"]]["userlevel"] in [4, 5] : return True | |
else : | |
if self.users["users"][info["sender"]].has_key("channels") : | |
if info["channel"] in self.users["users"][info["sender"]]["channels"] : | |
return True | |
else : return False | |
else : return False | |
else : return False | |
else : | |
self.ircsend(info["sender"], "Your nick does not match your hostname. If you are the owner of this nick, you need to use the addhost command.") | |
return False | |
def threadedrawsend(self, msg_out, timer) : | |
"""Used for flood control""" | |
time.sleep(timer) | |
if self.host in world.connections.keys() : self.rawsend(msg_out) | |
def ircsend(self, targ_channel, msg_out) : | |
"""Sends messages and notices""" | |
for line in msg_out.split("\n") : | |
length = len("PRIVMSG %s :\n" % (targ_channel)) | |
parts = [] | |
current = "" | |
for char in line : | |
if len(current) + length < 400: | |
current += char | |
else : | |
parts.append(current) | |
current = char | |
if current != "" : | |
parts.append(current) | |
for part in parts : | |
now = time.time() | |
if now > self.timer : | |
self.timer = now + 1 | |
else : self.timer += 1 | |
extra = self.timer - now | |
if targ_channel.startswith("#") or targ_channel.lower().endswith("serv") : thread.start_new_thread(self.threadedrawsend, ("PRIVMSG %s :%s\n" % (targ_channel, self.ircfilter(part, conf.bads)), extra)) | |
else : thread.start_new_thread(self.threadedrawsend, ("NOTICE %s :%s\n" % (targ_channel, self.ircfilter(part, conf.bads)), extra)) | |
if line.startswith("\x01ACTION") : self.logwrite(targ_channel, "[%s] *%s %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), conf.nick, " ".join(part.split(" ")[1:]).replace("\x01", ""))) | |
else : self.logwrite(targ_channel, "[%s] <%s> %s\n" % (time.strftime("%b %d %Y, %H:%M:%S %Z"), conf.nick, self.ircfilter(part, conf.bads))) | |
def unittestrawsend(self, msg_out) : | |
"""Used during unit tests to overwrite rawsend()""" | |
print msg_out | |
self.unittestlog = open("unittestlog.txt", "a") | |
self.unittestlog.write(msg_out) | |
self.unittestlog.close() | |
def logwrite(self, channel, log) : | |
"""Logs things to file, also is used when relaying""" | |
if channel in self.channels : | |
self.logs[channel].write(log) | |
if not conf.debug : print log | |
if channel != conf.nick : | |
if channel in world.relay_channels : | |
for server in world.connections.keys() : | |
if server != self.host and channel in world.connections[server].channels : | |
world.connections[server].rawsend("PRIVMSG %s :[%s] %s\n" % (channel, world.hostnicks[self.host], log.split("] ", 1)[1])) | |
self.logs[channel].close() | |
self.logs[channel] = open("%s/%s.txt" % (conf.logdir, channel), "a") | |
else : self.logs[conf.nick].write(log) | |
def waitfordata() : | |
"""Actual loop of waiting for data and parsing it""" | |
while True : | |
noerror = False | |
tempconlist = world.conlist[:] | |
try : | |
connections = select.select(tempconlist, [], [], 5) | |
noerror = True | |
except : | |
for network in tempconlist : | |
try : | |
connections = select.select([network], [], [], 0) | |
except : | |
world.instances[network].cleanup() | |
world.conlist.remove(network) | |
if noerror : | |
for connection in connections[0] : | |
try : data = connection.recv(4096) | |
except : | |
traceback.print_exc() | |
data = "" | |
if data != "" : | |
world.instances[connection].dataReceived(data) | |
else: | |
print "No data, closing the connection" | |
world.instances[connection].cleanup() | |
connection.close() | |
del tempconlist | |
if "logs" not in glob.glob("*") : | |
os.mkdir("logs") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment