diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | cacert.pem | 76 | ||||
-rw-r--r-- | connection/__init__.py | 0 | ||||
-rw-r--r-- | connection/xmpp.py | 132 | ||||
-rwxr-xr-x | curunir | 8 | ||||
-rw-r--r-- | curunir.py | 21 |
6 files changed, 239 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b261d8d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +*.pyo diff --git a/cacert.pem b/cacert.pem new file mode 100644 index 0000000..da2e8e6 --- /dev/null +++ b/cacert.pem @@ -0,0 +1,76 @@ +-----BEGIN CERTIFICATE----- +MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 +IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB +IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA +Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO +BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi +MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ +ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ +8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 +zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y +fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 +w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc +G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k +epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q +laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ +QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU +fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 +YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w +ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY +gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe +MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 +IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy +dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw +czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 +dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl +aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC +AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg +b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB +ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc +nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg +18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c +gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl +Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY +sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T +SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF +CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum +GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk +zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW +omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGCDCCA/CgAwIBAgIBATANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 +IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB +IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA +Y2FjZXJ0Lm9yZzAeFw0wNTEwMTQwNzM2NTVaFw0zMzAzMjgwNzM2NTVaMFQxFDAS +BgNVBAoTC0NBY2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5v +cmcxHDAaBgNVBAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCrSTURSHzSJn5TlM9Dqd0o10Iqi/OHeBlYfA+e2ol9 +4fvrcpANdKGWZKufoCSZc9riVXbHF3v1BKxGuMO+f2SNEGwk82GcwPKQ+lHm9WkB +Y8MPVuJKQs/iRIwlKKjFeQl9RrmK8+nzNCkIReQcn8uUBByBqBSzmGXEQ+xOgo0J +0b2qW42S0OzekMV/CsLj6+YxWl50PpczWejDAz1gM7/30W9HxM3uYoNSbi4ImqTZ +FRiRpoWSR7CuSOtttyHshRpocjWr//AQXcD0lKdq1TuSfkyQBX6TwSyLpI5idBVx +bgtxA+qvFTia1NIFcm+M+SvrWnIl+TlG43IbPgTDZCciECqKT1inA62+tC4T7V2q +SNfVfdQqe1z6RgRQ5MwOQluM7dvyz/yWk+DbETZUYjQ4jwxgmzuXVjit89Jbi6Bb +6k6WuHzX1aCGcEDTkSm3ojyt9Yy7zxqSiuQ0e8DYbF/pCsLDpyCaWt8sXVJcukfV +m+8kKHA4IC/VfynAskEDaJLM4JzMl0tF7zoQCqtwOpiVcK01seqFK6QcgCExqa5g +eoAmSAC4AcCTY1UikTxW56/bOiXzjzFU6iaLgVn5odFTEcV7nQP2dBHgbbEsPyyG +kZlxmqZ3izRg0RS0LKydr4wQ05/EavhvE/xzWfdmQnQeiuP43NJvmJzLR5iVQAX7 +6QIDAQABo4G/MIG8MA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUHAQEEUTBPMCMG +CCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggrBgEFBQcwAoYc +aHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBBMD8GCCsGAQQB +gZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9yZy9pbmRleC5w +aHA/aWQ9MTAwDQYJKoZIhvcNAQEEBQADggIBAH8IiKHaGlBJ2on7oQhy84r3HsQ6 +tHlbIDCxRd7CXdNlafHCXVRUPIVfuXtCkcKZ/RtRm6tGpaEQU55tiKxzbiwzpvD0 +nuB1wT6IRanhZkP+VlrRekF490DaSjrxC1uluxYG5sLnk7mFTZdPsR44Q4Dvmw2M +77inYACHV30eRBzLI++bPJmdr7UpHEV5FpZNJ23xHGzDwlVks7wU4vOkHx4y/CcV +Bc/dLq4+gmF78CEQGPZE6lM5+dzQmiDgxrvgu1pPxJnIB721vaLbLmINQjRBvP+L +ivVRIqqIMADisNS8vmW61QNXeZvo3MhN+FDtkaVSKKKs+zZYPumUK5FQhxvWXtaM +zPcPEAxSTtAWYeXlCmy/F8dyRlecmPVsYGN6b165Ti/Iubm7aoW8mA3t+T6XhDSU +rgCvoeXnkm5OvfPi2RSLXNLrAWygF6UtEOucekq9ve7O/e0iQKtwOIj1CodqwqsF +YMlIBdpTwd5Ed2qz8zw87YC8pjhKKSRf/lk7myV6VmMAZLldpGJ9VzZPrYPvH5JT +oI53V93lYRE9IwCQTDz6o2CTBKOvNfYOao9PSmCnhQVsRqGP9Md246FZV/dxssRu +FFxtbUFm3xuTsdQAw+7Lzzw9IYCpX2Nl/N3gX6T0K/CFcUHUZyX7GrGXrtaZghNB +0m6lG5kngOcLqagA +-----END CERTIFICATE----- diff --git a/connection/__init__.py b/connection/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/connection/__init__.py diff --git a/connection/xmpp.py b/connection/xmpp.py new file mode 100644 index 0000000..1b2dcf1 --- /dev/null +++ b/connection/xmpp.py @@ -0,0 +1,132 @@ +from pyxmpp.all import JID, Message +from pyxmpp.streamtls import TLSSettings +from pyxmpp.client import Client +from pyxmpp.jabber.muc import * +from pyxmpp.interface import implements +from pyxmpp.interfaces import * + +class MessageHandler: + implements(IMessageHandlersProvider) + + def __init__(self, client): + self.client = client + + def get_message_handlers(self): + return [ + ("normal", self.message), + ] + + def message(self, stanza): + return Message( + to_jid=stanza.get_from(), + from_jid=stanza.get_to(), + stanza_type=stanza.get_type(), + subject=stanza.get_subject(), + body=stanza.get_body()) + +class MucHandler(MucRoomHandler): + def message_received(self, user, stanza): + if(user.same_as(self.room_state.me)): + return + + self.room_state.send_message(stanza.get_body()[::-1]) + + def user_joined(self, user, stanza): + if(not self.room_state.joined or user.same_as(self.room_state.me)): + return + + self.room_state.send_message('Willkommen, ' + user.nick) + +class PresenceHandler(object): + implements(IPresenceHandlersProvider) + + def __init__(self, client): + self.client = client + + def get_presence_handlers(self): + return [ + (None, self.presence), + ("unavailable", self.presence), + ("subscribe", self.presence_control), + ("subscribed", self.presence_control), + ("unsubscribe", self.presence_control), + ("unsubscribed", self.presence_control), + ] + + def presence(self,stanza): + msg=u"%s has become " % (stanza.get_from()) + t=stanza.get_type() + if t=="unavailable": + msg+=u"unavailable" + else: + msg+=u"available" + + show=stanza.get_show() + if show: + msg+=u"(%s)" % (show,) + + status=stanza.get_status() + if status: + msg+=u": "+status + print msg + + def presence_control(self,stanza): + msg=unicode(stanza.get_from()) + t=stanza.get_type() + if t=="subscribe": + msg+=u" has requested presence subscription." + elif t=="subscribed": + msg+=u" has accepted our presence subscription request." + elif t=="unsubscribe": + msg+=u" has canceled his subscription of our." + elif t=="unsubscribed": + msg+=u" has canceled our subscription of his presence." + + print msg + + return stanza.make_accept_response() + +class VersionHandler(object): + implements(IIqHandlersProvider, IFeaturesProvider) + + def __init__(self, client): + self.client = client + + def get_features(self): + return ["jabber:iq:version"] + + def get_iq_get_handlers(self): + return [ + ("query", "jabber:iq:version", self.get_version), + ] + + def get_iq_set_handlers(self): + return [] + + def get_version(self,iq): + iq=iq.make_result_response() + q=iq.new_query("jabber:iq:version") + q.newTextChild(q.ns(),"name","Curunir XMPP-Bot") + q.newTextChild(q.ns(),"version","0.1") + return iq + + +class XMPPConnection(Client): + _jid = JID('curunir@jabber.ccc.de/Orthanc') + _password = '' + _cert_file = 'cacert.pem' + + def __init__(self): + Client.__init__(self, self._jid, self._password, tls_settings = TLSSettings(require = True, cacert_file = self._cert_file)) + + self.interface_providers = [ + MessageHandler(self), + PresenceHandler(self), + VersionHandler(self) + ] + + def authorized(self): + Client.authorized(self) + self.room_manager = MucRoomManager(self.stream) + self.room_manager.set_handlers() + self.room_manager.join(JID('c3hl@conference.jabber.ccc.de'), 'curunir', MucHandler(), history_maxstanzas=0) @@ -0,0 +1,8 @@ +#!/bin/sh + +APP=`basename $0` +DIR=`dirname $0` + +cd "$DIR" +export PYTHONPATH="$PYTHONPATH:." +exec /usr/bin/env python -OO "$APP.py" "$@" diff --git a/curunir.py b/curunir.py new file mode 100644 index 0000000..3c6c442 --- /dev/null +++ b/curunir.py @@ -0,0 +1,21 @@ +from connection.xmpp import XMPPConnection + +import signal, sys + +run = True + +def exithandler(signum, frame): + global run + run = False + +signal.signal(signal.SIGINT, exithandler) +signal.signal(signal.SIGTERM, exithandler) +signal.signal(signal.SIGQUIT, exithandler) + +connection = XMPPConnection() +connection.connect() + +while run: + connection.stream.loop_iter(1) + +connection.disconnect() |