]>
jfr.im git - irc/quakenet/qwebirc.git/blob - qwebirc/ircclient.py
1 import twisted
, sys
, codecs
2 from twisted
.words
.protocols
import irc
3 from twisted
.internet
import reactor
, protocol
4 from twisted
.web
import resource
, server
5 from twisted
.protocols
import basic
7 import hmac
, time
, config
8 from config
import HMACTEMPORAL
9 HMACKEY
= hmac
.HMAC(key
=config
.HMACKEY
)
13 h
.update("%d %s" % (int(time
.time() / HMACTEMPORAL
), " ".join(args
)))
16 def utf8_iso8859_1(data
, table
=dict((x
, x
.decode("iso-8859-1")) for x
in map(chr, range(0, 256)))):
17 return (table
.get(data
.object[data
.start
]), data
.start
+1)
19 codecs
.register_error("mixed-iso-8859-1", utf8_iso8859_1
)
23 return x
.decode("utf-8", "mixed-iso-8859-1")
24 except UnicodeDecodeError:
25 return x
.decode("iso-8859-1", "ignore")
27 class QWebIRCClient(basic
.LineReceiver
):
29 def __init__(self
, *args
, **kwargs
):
30 self
.__nickname
= "(unregistered)"
32 def dataReceived(self
, data
):
33 basic
.LineReceiver
.dataReceived(self
, data
.replace("\r", ""))
35 def lineReceived(self
, line
):
36 line
= irc_decode(irc
.lowDequote(line
))
39 prefix
, command
, params
= irc
.parsemsg(line
)
40 self
.handleCommand(command
, prefix
, params
)
41 except irc
.IRCBadMessage
:
42 self
.badMessage(line
, *sys
.exc_info())
45 self
.__nickname
= params
[0]
47 if self
.__perform
is not None:
48 for x
in self
.__perform
:
51 elif command
== "NICK":
52 nick
= prefix
.split("!", 1)[0]
53 if nick
== self
.__nickname
:
54 self
.__nickname
= params
[0]
56 def badMessage(self
, args
):
57 self("badmessage", args
)
59 def handleCommand(self
, command
, prefix
, params
):
60 self("c", command
, prefix
, params
)
62 def __call__(self
, *args
):
63 self
.factory
.publisher
.event(args
)
65 def write(self
, data
):
66 self
.transport
.write("%s\r\n" % irc
.lowQuote(data
.encode("utf-8")))
68 def connectionMade(self
):
69 basic
.LineReceiver
.connectionMade(self
)
72 f
= self
.factory
.ircinit
73 nick
, ident
, ip
, realname
= f
["nick"], f
["ident"], f
["ip"], f
["realname"]
74 self
.__nickname
= nick
75 self
.__perform
= f
.get("perform")
77 hmac
= hmacfn(ident
, ip
)
78 self
.write("USER %s bleh bleh %s %s :%s" % (ident
, ip
, hmac
, realname
))
79 self
.write("NICK %s" % nick
)
81 self
.factory
.client
= self
85 return "<QWebIRCClient: %s!%s@%s>" % (self
.__nickname
, self
.factory
.ircinit
["ident"], self
.factory
.ircinit
["ip"])
87 def connectionLost(self
, reason
):
89 self
.disconnect("Connection to IRC server lost: %s" % self
.lastError
)
91 self
.disconnect("Connection to IRC server lost.")
92 self
.factory
.client
= None
93 basic
.LineReceiver
.connectionLost(self
, reason
)
95 def error(self
, message
):
96 self
.lastError
= message
97 self
.write("QUIT :qwebirc exception: %s" % message
)
98 self
.transport
.loseConnection()
100 def disconnect(self
, reason
):
101 self("disconnect", reason
)
102 self
.factory
.publisher
.disconnect()
104 class QWebIRCFactory(protocol
.ClientFactory
):
105 protocol
= QWebIRCClient
106 def __init__(self
, publisher
, **kwargs
):
108 self
.publisher
= publisher
109 self
.ircinit
= kwargs
111 def write(self
, data
):
112 self
.client
.write(data
)
114 def error(self
, reason
):
115 self
.client
.error(reason
)
117 def clientConnectionFailed(self
, connector
, reason
):
118 protocol
.ClientFactory
.clientConnectionFailed(self
, connector
, reason
)
119 self
.publisher
.event(["disconnect", "Connection to IRC server failed."])
120 self
.publisher
.disconnect()
122 def createIRC(*args
, **kwargs
):
123 f
= QWebIRCFactory(*args
, **kwargs
)
124 reactor
.connectTCP(config
.IRCSERVER
, config
.IRCPORT
, f
)
127 if __name__
== "__main__":
128 e
= createIRC(lambda x
: 2, nick
="slug__moo", ident
="mooslug", ip
="1.2.3.6", realname
="mooooo")