I'm looking to see if there is anything in this I could have done better or see if could have structured the code better. Here is the project on GitHub.
import socket
import string
import sys
import os
path = "plugins/"
plugins = []
# Load plugins
sys.path.insert(0, path)
for f in os.listdir(path):
fname, ext = os.path.splitext(f)
if ext == '.py':
mod = __import__(fname)
plugins.append(getattr(mod, fname))
sys.path.pop(0)
class IRC_Client(object):
"""docstring for IRC_Client"""
sock = ""
def __init__(self, ircserver, ircnicklist, ircident, ircrealname,
ircchanlist, nickpassword=None, ircport=6667):
super(IRC_Client, self).__init__()
if not isinstance(ircnicklist, list):
raise TypeError("nicklist is not an instance of list")
elif not isinstance(ircchanlist, list):
raise TypeError("chanlist is not an instance of list")
self.ircnicklist = ircnicklist
self.ircident = ircident
self.ircrealname = ircrealname
self.ircchanlist = ircchanlist
self.ircserver = ircserver
self.ircport = ircport
self.nickpassword = nickpassword
def createconnection(self):
self.sock = socket.socket()
self.sock.connect((self.ircserver, self.ircport))
def sendmessage(self, sender, message):
sent = "PRIVMSG %s :%s\r\n" % (sender, message)
self.sock.send(sent)
def sendpong(self, sender):
sent = "PONG %s\r\n" % sender
self.sock.send(sent)
def sendnotice(self, sender, message):
sent = "NOTICE %s :%s\r\n" % (sender, message)
self.sock.send(sent)
def sendctcp(self):
pass
def setnick(self, nick):
self.sock.send("NICK %s\r\n" % nick)
def joinchannel(self, channel):
self.sock.send("JOIN %s\r\n" % channel)
def getusernick(self, serverbuffer):
usernick = serverbuffer[0].split("!")
usernick = usernick[0].replace(":", "")
return usernick
def getusermessage(self, serverbuffer):
message = ""
if len(serverbuffer) >= 4:
serverbuffer[3] == serverbuffer[3][1:]
for i in range(3, len(serverbuffer)):
message += serverbuffer[i] + " "
return message
def getchannel(self, serverbuffer):
if len(serverbuffer):
return serverbuffer[2]
def serverreplies(self, serverbuffer):
serverbuffer = string.split(string.rstrip(serverbuffer))
if serverbuffer[0].lower() == 'ping':
self.sendpong(serverbuffer[0])
if serverbuffer[1] == "431":
print "No nick was given"
exit()
if serverbuffer[1] == "432":
print "Erroneus nick"
exit()
if serverbuffer[1] == "433":
if len(self.ircnicklist) != 0:
self.setnick(self.ircnicklist.pop())
else:
raise IndexError("All nicks from nicklist are in use")
for channel in self.ircchanlist:
self.joinchannel(channel)
def commandparser(self, line):
line = string.split(string.rstrip(line.lower()))
if (len(line) >= 4 and line[1] == 'privmsg'):
map(lambda command: command(self, line), plugins)
def connect(self):
self.createconnection()
self.setnick(self.ircnicklist[0])
self.sock.send("USER %s %s bla :%s\r\n"
% (self.ircident, self.ircserver, self.ircrealname))
if not self.nickpassword:
pass
else:
self.sock.send("PASS %s\r\n" % self.nickpassword)
for channel in self.ircchanlist:
self.joinchannel(channel)
def loop(self):
readbuffer = ""
while 1:
readbuffer = self.sock.recv(1024)
temp = string.split(readbuffer, "\n")
readbuffer = temp.pop()
for line in temp:
print line
self.serverreplies(line)
self.commandparser(line)
logger(self, line)
def runclient(self):
self.connect()
self.loop()
def logger(ircclientinstance, serverbuffer):
serverbuffer = string.split(string.rstrip(serverbuffer))
if serverbuffer[1].lower() == "privmsg":
if serverbuffer[2] in ircclientinstance.ircchanlist:
filename = ("%s.log" % serverbuffer[2])
f = open(filename, 'a+')
f.write("<%s>%s\n" % (ircclientinstance.getusernick(
serverbuffer), ircclientinstance.getusermessage(serverbuffer)))
f.close()
else:
filename = ("%s.log" % ircclientinstance.getusernick(serverbuffer))
f = open(filename, 'a+')
f.write("<%s>%s\n" % (ircclientinstance.getusernick(
serverbuffer), ircclientinstance.getusermessage(serverbuffer)))
f.close()
if __name__ == "__main__":
# TODO: config file? maybe
mybot = IRC_Client('irc.freenode.net', ['swaglorde', 'swaglordeh'], 'swaglorde',
'swaglorde', ['#dtest'])
mybot.runclient()
Example of a plugin:
I am thinking about converting my plugin system to a class based system. I am also not sure if it would better, but I do have a bit of code I am reusing with every plugin.
import requests
def showInfo(tvname):
tvname = tvname.replace(' ', '+')
tvinfo = requests.get(
"http://services.tvrage.com/tools/quickinfo.php?show=" + tvname).text
try:
tvdata = tvinfo.split('\n')
tvinfo = []
for data in tvdata:
data = data.split('@')
tvinfo.append(data)
return tvinfo
except:
return None
def next(ircclientinstance, serverbuffer):
commandname = 'next'
commands = {':!': True, ':.': False, ':@': True}
# This needs to be included in all plugins that take arguements
commandarguements = ""
parseargs = serverbuffer[3:][1:]
for x in parseargs:
commandarguements += x.strip() + " "
if commandarguements == '':
output = "No info found :3"
else:
try:
tvinfo = showInfo(commandarguements)
output = "[%s] :: [Next: %s] [Airs: %s]" % (
tvinfo[1][1], tvinfo[7][1].replace('^', ' '), tvinfo[15][1])
except:
output = "No info found :3"
# this needs to be included with all plugins
if serverbuffer[3][2:] == commandname:
if serverbuffer[3][:2] in commands:
notice = commands.get(serverbuffer[3][:2])
if not notice:
if serverbuffer[1] == "privmsg":
if serverbuffer[2] in ircclientinstance.ircchanlist:
ircclientinstance.sendmessage(serverbuffer[2], output)
else:
ircclientinstance.sendmessage(
ircclientinstance.getusernick(serverbuffer), output)
else:
ircclientinstance.sendnotice(
ircclientinstance.getusernick(serverbuffer), output)
1 Answer 1
A few comments regarding the main code:
- Try to order imports alphabetically
- Use underscores to separate words in method names (
createconnection
->create_connection
,sendmessage
,send_message
, etc.) - Use class attributes instead of hardcded constants (
"431"
->self.ERR_NONICKNAMEGIVEN
,"432"
->self.ERR_ERRONEUSNICKNAME
, etc.) - Use
if
/elif
/elif
instead ofif
/if
/if
to avoid unnecessary checks - Use the
logging
module instead ofprint
statements. - To check if a list is not empty use just the list name
self.ircnicklist
instead oflen(self.ircnicklist) != 0
- Review exception types. Is
IndexError
really appropriate when there are no more elements in the list?l - Prefer to use list comprehensions instead of
map
Remove
pass
if isn't really useful. Instead of:if not self.nickpassword: pass else: self.sock.send("PASS %s\r\n" % self.nickpassword)
write:
if self.nickpassword: self.sock.send("PASS %s\r\n" % self.nickpassword)
Instead of
while 1
usewhile True
Use context managers to open and close files. Instead of:
f = open(filename, 'a+') f.write("<%s>%s\n" % (ircclientinstance.getusernick( serverbuffer), ircclientinstance.getusermessage(serverbuffer))) f.close()
write:
with open(filename, 'a+') as f: f.write("<%s>%s\n" % (ircclientinstance.getusernick(serverbuffer), ircclientinstance.getusermessage(serverbuffer)))
I hope this helps.
Explore related questions
See similar questions with these tags.