aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Daniel Washburn <daniel@washburn.at> 2013-04-17 14:09:54 -0400
committerGravatar Daniel Washburn <daniel@washburn.at> 2013-04-17 14:09:54 -0400
commit381bbd7e521f56fdb61e86ce9fc039e6f3b7cf91 (patch)
tree77599b9eefc686e6ea94cb83c61f065d96e00cc6
downloadpyrc-381bbd7e521f56fdb61e86ce9fc039e6f3b7cf91.tar.gz
pyrc-381bbd7e521f56fdb61e86ce9fc039e6f3b7cf91.tar.bz2
pyrc-381bbd7e521f56fdb61e86ce9fc039e6f3b7cf91.zip
Initial commit
-rw-r--r--PyRC.py237
1 files changed, 237 insertions, 0 deletions
diff --git a/PyRC.py b/PyRC.py
new file mode 100644
index 0000000..3957b24
--- /dev/null
+++ b/PyRC.py
@@ -0,0 +1,237 @@
+"""A module to connect to and interact with an Internet Relay Chat server.
+"""
+
+import socket
+import sys
+import string
+import select
+
+class client:
+ def __init__(self, (host, port, hostpass)):
+ try:
+ self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.s.setblocking(0)
+ except socket.error, msg:
+ self.s = None
+ if self.s is None:
+ print 'Could not open socket.'
+ sys.exit(1)
+
+ self.host = host
+ self.port = port
+ self.hostpass = hostpass
+ self.send_buf = ''
+ self.recv_buf = ''
+
+ def connect(self, (nick, ident, realname)):
+ """connect((nick, ident, realname))
+
+ Connects to the specified host."""
+ try:
+ self.s.connect((self.host, self.port))
+ except socket.error, msg:
+ if (msg[0] == 115):
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not connect to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ connected = False
+ while not connected:
+ try:
+ if self.hostpass:
+ self.s.send('PASS %s\r\n' % self.hostpass)
+ self.s.send('NICK %s\r\n' % nick)
+ # TODO: try alternate nicknames if the first is taken, or just fail.
+ self.s.send('USER %s %s %s :%s\r\n' % (nick, socket.gethostname(), self.host, realname))
+ connected = True
+ except socket.error, msg:
+ if msg[0] == 11 or msg[0] == 115:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not connect to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def quit(self, reason = ''):
+ """quit([reason]) -> string
+
+ Disconnects from host and returns final server messages."""
+
+ connected = True
+ while connected:
+ try:
+ if reason:
+ self.s.send('QUIT :%s\r\n' % reason)
+ connected = False
+ else:
+ self.s.send('QUIT :PyRC. http://www.pyrc.org\r\n')
+ connected = False
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def join(self, channel, key = ''):
+ """join(channel[, key])
+
+ Joins specified channel, optionally using a channel key."""
+ try:
+ self.s.send('JOIN %s %s\r\n' % (channel, key))
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def part(self, channel):
+ """part(channel)
+
+ Leaves specified channel."""
+ try:
+ self.s.send('PART %s\r\n' % channel)
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def message(self, dest, message):
+ """message(dest, message)
+
+ Sends message to specified destination. May be channel or user."""
+ try:
+ self.s.send('PRIVMSG %s :%s\r\n' % (dest, message))
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def notice(self, dest, message):
+ """notice(dest, message)
+
+ Sends notice to specified destination. May be channel or user."""
+ try:
+ self.s.send('NOTICE %s :%s\r\n' % (dest, message))
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def invite(self, dest, channel):
+ """invite(dest, channel)
+
+ Invites user to the specified channel."""
+ try:
+ self.s.send('INVITE %s %s\r\n' % (dest, channel))
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def nick(self, nickname):
+ """nick(nickname)
+
+ Changes nickname to the specified nickname."""
+ try:
+ self.s.send('NICK %s\r\n' % nickname)
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def pong(self, dest):
+ """pong(dest, message)
+
+ Sends a pong to specified destination."""
+ try:
+ self.s.send('PONG %s\r\n' % dest)
+ except socket.error, msg:
+ if msg[0] == 11:
+ pass
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not send to %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ def main_loop(self):
+ """main_loop()
+
+ Returns an array of dictionary objects, with keys 'sender',
+ 'type', 'destination', and 'message'."""
+ tempbuff = ''
+ try:
+ while 1:
+ tempbuff += self.s.recv(512)
+ except socket.error, msg:
+ if msg[0] == 11:
+ self.recv_buf += tempbuff
+ else:
+ self.s.close()
+ self.s = None
+ if self.s is None:
+ print "Could not recieve from %s %s" % (self.host, self.port)
+ sys.exit(1)
+
+ while self.recv_buf:
+ msgs = []
+ temp = self.recv_buf.split('\n')
+ self.recv_buf = temp.pop()
+ for line in temp:
+ line = line.strip()
+ line = line.split(' ')
+ if line[0] == 'PING':
+ self.pong(line[1])
+ elif line[0] == 'ERROR':
+ msgs.append({'sender': None, 'type': line[0], 'destination': None, 'message': string.join(line[1:]).lstrip(':')})
+ self.s.close()
+ else:
+ if (line[0][0] == ':'):
+ # if there is a sender (usually)
+ # [ sender, action, destination, message ]
+ msgs.append({'sender': line[0].lstrip(':'), 'type': line[1], 'destination':line[2], 'message': string.join(line[3:]).lstrip(':')})
+ else:
+ #if no sender
+ # [ '', action, destination, message ]
+ msgs.append({'sender': None, 'type': line[0], 'destination': line[1], 'message': string.join(line[2:]).lstrip(':')})
+ return msgs