Newer
Older
# Copyright 2010, 2011 G24
#
# This file is part of gpy.
#
# gpy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpy 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpy. If not, see <http://www.gnu.org/licenses/>.
import math
import time
import socket
import ConfigParser
from datetime import datetime
"""Do not use!"""
self.irc.send(str + '\n\r')
self.dispatch(cmd + ' ' + target + ' :' + msg)
def say(self,target,msg):
self.send(self.config.get("connection","msgtype"),target,msg)
def reply(self,msg):
if self.recvinfo["target"] == self.vars["nick"]:
self.say(self.recvinfo["origin.nick"],msg)
else:
self.say(self.recvinfo["target"],self.recvinfo["origin.nick"] + ": " + msg)
def saypm(self,msg):
self.send("PRIVMSG",target,msg)
def cancel(self,line):
print("\033[91m{0}\033[0m".format(line))
self.log('! ' + line)
def ok(self,line):
print("\033[92m{0}\033[0m".format(line))
self.log(' ' + line)
def info(self,line):
print("\033[93m{0}\033[0m".format(line))
self.log('? ' + str(line))
def log(self,line):
log = open(self.logpath,"a")
log.write("{0} {1}\n".format(str(datetime.now()),line))
class connection(core):
def __init__(self):
# Constant.
self.version = __import__('gpy').__version__
print(" __ _ _ __ _ _ ")
print(" / _` | '_ \| | | |")
print("| (_| | |_) | |_| | http://repo.or.cz/w/gpy.git/summary")
print(" \__, | .__/ \__, |")
print(" |___/|_| |___/ {0}".format(self.version))
print('')
if 'HOME' in os.environ:
self.directory = os.environ['HOME'] + '/.gpy/'
elif 'HOMEPATH' in os.environ:
self.directory = os.environ['HOMEPATH'] + '/.gpy/'
else:
self.directory = os.getcwd() + '/var/'
print("Settings directory: %s" % self.directory)
if not os.path.exists(self.directory):
self.configpath = self.directory + 'main.cfg'
self.logpath = self.directory + 'main.log'
parser = argparse.ArgumentParser(description="Start gpy - a modular Python IRC bot.")
parser.add_argument("-c", "--makeconf", required=False, help="edit the configuration file",action='store_true')
parser.add_argument("-v", "--version", required=False, help="display version information and exit.",action='store_true')
args = parser.parse_args(sys.argv[1:])
if args.version == True:
exit()
if os.path.isfile(self.configpath) == False:
self.defaultconf()
self.makeconf()
if args.makeconf == True:
self.commands = []
self.vars = {}
self.config.read(self.configpath)
self.mainclasses = {};
self.modules = {};
tmp = (self.config.get("me","modules").strip() + ",").split(",")
for each in tmp[0:(len(tmp) - 1)]:
self.modules = __import__("gpy", globals(), locals(), [each], -1)
self.mainclasses[each] = getattr(getattr(self.modules,each),"mod_main")(self)
self.ok("Module {0} loaded.".format(each))
self.cancel("Module {0} not loaded. {1}".format(each,e))
self.vars["nick"] = self.config.get("connection","nick")
self.info("Connecting to {0} ... ".format(self.config.get("connection","network")))
try:
self.irc.connect ((self.config.get("connection","network"), self.config.getint("connection","port")))
self.dispatch('NICK ' + self.config.get("connection","nick"))
self.dispatch("USER " + self.config.get("connection","nick") + " * * :" + self.version+" http://repo.or.cz/w/gpy.git")
except Exception, e:
self.cancel("Connection failed. {0}".format(e))
return
if self.config.get("connection","ns_name") != "":
self.dispatch("PRIVMSG NICKSERV :id {0} {1}".format(self.config.get("connection","ns_name"),self.config.get("connection","ns_pwd")))
self.data = self.irc.recv(4096)
while(self.data[len(self.data)-2:len(self.data)]) != '\r\n':
self.data += self.irc.recv(4096)
if each == "": # Do nothing with empty lines
if each.split(' ')[0] == 'PING': # PING
self.dispatch('PONG ' + each.split()[1])
if len(each.strip()) != 0: # Now listen.
self.listen()
try:
for mod in self.mainclasses:
self.mainclasses[mod].listen()
except:
pass
def setvalue(self,section,option,helptext,default):
value = default
if self.config.has_section(section):
if self.config.has_option(section, option):
ivalue = self.config.get(section,option)
else:
ivalue = default
else:
self.config.add_section(section)
def my_raw(self,prompt="", default=""):
ret = raw_input("%s [%s]: "%(prompt,default))
return default if ret == "" else ret
def defaultconf(self):
self.config = ConfigParser.RawConfigParser()
self.config.read(self.configpath)
self.config.add_section("connection")
self.config.set("connection",'network','')
self.config.set("connection",'channels','')
self.config.set("connection",'nick','')
self.config.set("connection",'msgtype','')
self.config.set("connection",'ns_name','')
self.config.set("connection",'ns_pwd','')
self.config.set("connection",'port','6667')
self.config.add_section("users")
self.config.set("users",'username','')
self.config.add_section("admins")
self.config.set("admins",'username','')
self.config.add_section("me")
self.config.set("me","char",'')
self.config.set("me","modules",'admin,web,fact,calc')
with open(self.configpath, 'wb') as configfile:
self.config.write(configfile)
def set(self,section,option,text):
self.config.set(section,option,self.my_raw(text,self.config.get(section,option)))
def makeconf(self):
self.config = ConfigParser.RawConfigParser()
self.config.read(self.configpath)
self.set("connection",'network',"IRC network to connect to")
self.set("connection",'channels',"Channels to join (comma-separated, no spaces)")
self.set("connection",'nick',"My nickname")
self.set("connection",'msgtype',"Message type (privmsg or notice)")
self.set("connection",'ns_name',"NickServ username (if there is none, press ENTER)")
self.set("connection",'ns_pwd',"NickServ password (if there is none, press ENTER)")
self.set("connection",'port',"Port (if unsure, type 6667)")
username=self.my_raw("Your username (used for bot administration)",'username')
self.config.set("users",username,self.my_raw("Your password",'password'))
self.config.set("admins",username,'')
self.set("me","char","My command char(s) (separate with |)")
self.set("me","modules","Modules to load (comma-separated, no spaces, must include 'admin' module)")
with open(self.configpath, 'wb') as configfile:
self.config.write(configfile)
self.ok('Configuration file has been created.')
exit()
def listen(self):
# If we've read the MOTD - JOIN channels.
if self.recvinfo["cmd"] == "MODE":
for each in (self.config.get("connection","channels").strip() + ",").split(","):
if each != "":
self.dispatch('JOIN ' + each)
for char in self.chars():
if char=='':
break
if self.recvinfo["message"] == char: # We just said commandchar.
if self.recvinfo["cmd"] != "PRIVMSG": return
self.reply("Modules loaded: {0}.".format(str(self.mainclasses.keys())).replace('[','').replace(']','').replace('\'',''))
if self.recvinfo["message.command"] in self.mainclasses and self.recvinfo["message.params"] == "":
if self.recvinfo["cmd"] != "PRIVMSG": return
mod=self.mainclasses[self.recvinfo["message.command"]]
self.reply("{0} Includes commands: {1}.".format(mod.__doc__,str(mod.cmds.keys()) ).replace('[','').replace(']','').replace('\'',''))
if self.recvinfo["cmd"] == "INVITE":
self.dispatch("JOIN "+self.recvinfo["message"])
return
if self.recvinfo["cmd"] == "NICK" and self.recvinfo["origin.nick"] == self.vars["nick"]:
self.vars["nick"] = self.recvinfo["target"].replace(":","")
with open(self.configpath, 'w') as configfile:
self.config.write(configfile)
def parseline(self,line):
self.recvinfo = {}
self.recvinfo["origin"] = line.split(" ")[0].split(":")[1]
self.recvinfo["origin.nick"] = ""
self.recvinfo["origin.ident"] = ""
self.recvinfo["origin.host"] = ""
if self.recvinfo["origin"].find("@") != -1:
self.recvinfo["origin.nick"] = self.recvinfo["origin"].split("!")[0]
self.recvinfo["origin.ident"] = self.recvinfo["origin"].split("!")[1].split("@")[0]
self.recvinfo["origin.host"] = self.recvinfo["origin"].split("!")[1].split("@")[1]
self.recvinfo["cmd"] = line.split(" ")[1]
self.recvinfo["target"] = line.split(" ")[2]
self.recvinfo["message"] = ":".join(" ".join(line.split(" ")[3:]).split(":")[1:]).strip() #-echo Hello world.
self.recvinfo["message.command"] = ""
self.recvinfo["message.params"] = ""
if self.recvinfo["message"] != "":
for each in self.chars():
if each == '':
break
elif re.match(each,self.recvinfo["message"]) != None:
tmp = self.recvinfo["message"].replace(each,"",1) # echo Hello world.
self.recvinfo["message.command"] = tmp.split(" ")[0] # echo
self.recvinfo["message.params"] = " ".join(tmp.split(" ")[1:]).strip() # Hello world.
def chars(self):
a = (str(self.config.get("me","char"))+'|').replace('nick',self.vars['nick']).split('|')
a.remove('')
return a
class clisten():
def __init__(self,c):
self.conn=c
if hasattr(self,"addcmds"):
self.addcmds()
def listen(self):
if (self.conn.recvinfo["message.command"] in self.cmds) == False: return
if hasattr(self,"clisten"): self.clisten()
if self.conn.recvinfo["cmd"] != "PRIVMSG": return
if self.conn.recvinfo["message.params"] == "":
self.conn.reply(getattr(self,self.cmds[self.conn.recvinfo["message.command"]]).__doc__)
else:
try:
getattr(self,self.cmds[self.conn.recvinfo["message.command"]])()
except Exception,e:
self.conn.reply(str(e))