pesterchum/irc.py

300 lines
12 KiB
Python
Raw Normal View History

from PyQt4 import QtGui, QtCore
from twisted.internet.protocol import ClientFactory
from twisted.words.protocols.irc import IRCClient
from twisted.internet import reactor
import logging
2011-02-06 01:02:39 -05:00
import random
from dataobjs import Mood, PesterProfile
from generic import PesterList
2011-02-06 19:50:21 -05:00
logging.basicConfig(level=logging.INFO)
class PesterIRC(QtCore.QObject):
2011-02-13 21:01:58 -05:00
def __init__(self, config, window):
QtCore.QObject.__init__(self)
self.mainwindow = window
2011-02-13 21:01:58 -05:00
self.config = config
def IRCConnect(self):
2011-02-13 21:01:58 -05:00
server = self.config.server()
port = int(self.config.port())
nick = self.mainwindow.profile()
self.cli = PesterIRCFactory(nick, self)
logging.info("---> Logging on...")
reactor.connectTCP(server, port, self.cli)
reactor.run()
2011-02-14 16:15:32 -05:00
def closeConnection(self):
#logging.info("---> Logging on...")
# self.cli.close()
pass
@QtCore.pyqtSlot(PesterProfile)
def getMood(self, *chums):
self.cli.getMood(*chums)
@QtCore.pyqtSlot(PesterList)
def getMoods(self, chums):
self.cli.getMood(*chums)
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def sendMessage(self, text, handle):
h = unicode(handle)
2011-02-13 20:32:02 -05:00
textl = [unicode(text)]
CMD_LENGTH = 450
2011-02-13 20:32:02 -05:00
def splittext(l):
if len(l[0]) > CMD_LENGTH:
space = l[0].rfind(" ", 0,CMD_LENGTH)
2011-02-13 20:32:02 -05:00
if space == -1:
space = CMD_LENGTH
2011-02-13 20:32:02 -05:00
a = l[0][0:space]
b = l[0][space:]
if len(b) > 0:
return [a] + splittext([b])
else:
return [a]
else:
return l
textl = splittext(textl)
for t in textl:
self.cli.msg(h, t)
@QtCore.pyqtSlot(QtCore.QString, bool)
def startConvo(self, handle, initiated):
h = unicode(handle)
if initiated:
self.cli.msg(h, "PESTERCHUM:BEGIN")
self.cli.msg(h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
@QtCore.pyqtSlot(QtCore.QString)
def endConvo(self, handle):
h = unicode(handle)
self.cli.msg(h, "PESTERCHUM:CEASE")
@QtCore.pyqtSlot()
def updateProfile(self):
me = self.mainwindow.profile()
handle = me.handle
self.cli.setNick(handle)
self.updateMood()
@QtCore.pyqtSlot()
def updateMood(self):
me = self.mainwindow.profile()
self.cli.msg("#pesterchum", "MOOD >%d" % (me.mood.value()))
@QtCore.pyqtSlot()
def updateColor(self):
me = self.mainwindow.profile()
for h in self.mainwindow.convos.keys():
self.cli.msg(h, "COLOR >%s" % (self.mainwindow.profile().colorcmd()))
@QtCore.pyqtSlot(QtCore.QString)
def blockedChum(self, handle):
h = unicode(handle)
self.cli.msg(h, "PESTERCHUM:BLOCK")
@QtCore.pyqtSlot(QtCore.QString)
def unblockedChum(self, handle):
h = unicode(handle)
self.cli.msg(h, "PESTERCHUM:UNBLOCK")
@QtCore.pyqtSlot(QtCore.QString)
def requestNames(self, channel):
c = unicode(channel)
self.cli.sendMessage("NAMES", c)
@QtCore.pyqtSlot()
def requestChannelList(self):
self.cli.sendMessage("LIST")
@QtCore.pyqtSlot(QtCore.QString)
def joinChannel(self, channel):
c = unicode(channel)
self.cli.join(c)
@QtCore.pyqtSlot(QtCore.QString)
def leftChannel(self, channel):
c = unicode(channel)
self.cli.leave(c)
2011-02-06 01:02:39 -05:00
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
def kickUser(self, handle, channel):
c = unicode(channel)
h = unicode(handle)
self.cli.kick(h, c)
2011-02-06 19:50:21 -05:00
@QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
def setChannelMode(self, channel, mode, command):
c = unicode(channel)
m = unicode(mode).replace("+", "")
2011-02-06 19:50:21 -05:00
cmd = unicode(command)
if cmd == "":
cmd = None
self.cli.mode(c, True, m, cmd)
2011-02-14 16:15:32 -05:00
@QtCore.pyqtSlot()
def reconnectIRC(self):
pass
moodUpdated = QtCore.pyqtSignal(QtCore.QString, Mood)
colorUpdated = QtCore.pyqtSignal(QtCore.QString, QtGui.QColor)
messageReceived = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
memoReceived = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString)
timeCommand = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString)
namesReceived = QtCore.pyqtSignal(QtCore.QString, PesterList)
channelListReceived = QtCore.pyqtSignal(PesterList)
nickCollision = QtCore.pyqtSignal(QtCore.QString, QtCore.QString)
connected = QtCore.pyqtSignal()
userPresentUpdate = QtCore.pyqtSignal(QtCore.QString, QtCore.QString,
QtCore.QString)
class PesterIRCClient(IRCClient):
realname = "pcc30"
username = "pcc30"
def __init__(self, nick, qobj):
self.nickname = nick
self.parent = qobj
self.mainwindow = qobj.mainwindow
qobj.irc = self
def msg(self, user, message):
logging.info("---> send PRIVMSG %s %s" % (user, message))
IRCClient.msg(self, user, message)
def signedOn(self):
logging.info("---> recv WELCOME")
self.parent.connected.emit()
self.join("#pesterchum")
mychumhandle = self.mainwindow.profile().handle
mymood = self.mainwindow.profile().mood.value()
self.msg("#pesterchum", "MOOD >%d" % (mymood))
chums = self.mainwindow.chumList.chums
self.getMood(*chums)
def getMood(self, *chums):
chumglub = "GETMOOD "
for c in chums:
chandle = c.handle
if len(chumglub+chandle) >= 350:
self.msg("#pesterchum", chumglub)
chumglub = "GETMOOD "
chumglub += chandle
if chumglub != "GETMOOD ":
self.msg("#pesterchum", chumglub)
def privmsg(self, nick, chan, msg):
# do we still need this?
#msg = msg.decode("utf-8")
# display msg, do other stuff
2011-02-07 13:40:05 -05:00
if len(msg) == 0:
return
# silently ignore CTCP
if msg[0] == '\x01':
return
handle = nick[0:nick.find("!")]
logging.info("---> recv PRIVMSG %s :%s" % (handle, msg))
if chan == "#pesterchum":
# follow instructions
if msg[0:6] == "MOOD >":
try:
mood = Mood(int(msg[6:]))
except ValueError:
mood = Mood(0)
self.parent.moodUpdated.emit(handle, mood)
elif msg[0:7] == "GETMOOD":
mychumhandle = self.mainwindow.profile().handle
mymood = self.mainwindow.profile().mood.value()
if msg.find(mychumhandle, 8) != -1:
self.msg("#pesterchum", "MOOD >%d" % (mymood))
elif chan[0] == '#':
if msg[0:16] == "PESTERCHUM:TIME>":
self.parent.timeCommand.emit(chan, handle, msg[16:])
else:
self.parent.memoReceived.emit(chan, handle, msg)
else:
# private message
# silently ignore messages to yourself.
if handle == self.mainwindow.profile().handle:
return
if msg[0:7] == "COLOR >":
colors = msg[7:].split(",")
try:
colors = [int(d) for d in colors]
except ValueError:
colors = [0,0,0]
color = QtGui.QColor(*colors)
self.parent.colorUpdated.emit(handle, color)
else:
self.parent.messageReceived.emit(handle, msg)
def irc_ERR_NICKNAMEINUSE(self, prefix, params):
logging.info("---> recv NICKINUSE %s %s" % (prefix, params))
newnick = "pesterClient%d" % (random.randint(100,999))
self.setNick(newnick)
self.parent.nickCollision.emit(nick, newnick)
def userQuit(self, nick, reason):
logging.info("---> recv QUIT %s %s" % (nick, reason))
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, "", "quit")
2011-02-06 01:02:39 -05:00
self.parent.moodUpdated.emit(handle, Mood("offline"))
def userKicked(self, kickee, channel, kicker, msg):
logging.info("---> recv KICK %s %s %s %s" % (kickee, channel, kicker, msg))
self.parent.userPresentUpdate.emit(kickee, channel, "kick:%s" % (op))
2011-02-06 01:02:39 -05:00
# ok i shouldnt be overloading that but am lazy
def userLeft(self, nick, channel, reason="nanchos"):
logging.info("---> recv LEFT %s %s" % (nick, channel))
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, channel, "left")
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("offline"))
def userJoined(self, nick, channel):
logging.info("---> recv JOIN %s %s" % (nick, channel))
handle = nick[0:nick.find("!")]
self.parent.userPresentUpdate.emit(handle, channel, "join")
if channel == "#pesterchum":
self.parent.moodUpdated.emit(handle, Mood("chummy"))
def modeChannel(self, op, channel, set, modes, args):
logging.info("---> recv MODE %s %s %s %s %s" % (op, channel, set, modes, args))
if set:
modes += "+"
else:
modes += "-"
handle = ""
print args
2011-02-08 02:56:30 -05:00
self.parent.userPresentUpdate.emit(handle, channel, mode)
def userRenamed(self, oldnick, newnick):
logging.info("---> recv RENAME %s %s" % (oldnick, newnick))
newchum = PesterProfile(newnick, chumdb=self.mainwindow.chumdb)
self.parent.moodUpdated.emit(oldnick, Mood("offline"))
self.parent.userPresentUpdate.emit("%s:%s" % (oldnick, newnick), "", "nick")
if newnick in self.mainwindow.chumList.chums:
self.getMood(newchum)
def irc_RPL_NAMREPLY(self, prefix, params):
logging.info("---> recv NAMREPLY %s %s" % (prefix, params))
# namelist = names.split(" ")
# logging.info("---> recv \"NAMES %s: %d names\"" % (channel, len(namelist)))
# if not hasattr(self, 'channelnames'):
# self.channelnames = {}
# if not self.channelnames.has_key(channel):
# self.channelnames[channel] = []
# self.channelnames[channel].extend(namelist)
def irc_RPL_ENDOFNAMES(self, prefix, params):
logging.info("---> recv ENDOFNAMES %s %s" % (prefix, params))
# namelist = self.channelnames[channel]
# pl = PesterList(namelist)
# del self.channelnames[channel]
# self.parent.namesReceived.emit(channel, pl)
def irc_RPL_LISTSTART(self, prefix, params):
logging.info("---> recv LISTSTART %s %s" % (prefix, params))
# self.channel_list = []
# info = list(info)
# self.channel_field = info.index("Channel") # dunno if this is protocol
def irc_RPL_LIST(self, prefix, params):
logging.info("---> recv LIST %s %s" % (prefix, params))
# channel = info[self.channel_field]
# if channel not in self.channel_list and channel != "#pesterchum":
# self.channel_list.append(channel)
def irc_RPL_LISTEND(self, prefix, params):
logging.info("---> recv LISTEND %s %s" % (prefix, params))
# pl = PesterList(self.channel_list)
# self.parent.channelListReceived.emit(pl)
# self.channel_list = []
class PesterIRCFactory(ClientFactory):
protocol = PesterIRCClient
def __init__(self, nick, qobj):
self.irc = self.protocol(nick, qobj)
def buildProtocol(self, addr=None):
return self.irc
def clientConnectionLost(self, conn, reason):
conn.connect()
def clientConnectionFailed(self, conn, reason):
conn.connect()