pvl/irker/irk.py
author Tero Marttila <terom@paivola.fi>
Tue, 19 Feb 2013 19:27:51 +0200
changeset 220 e533260bcefd
parent 127 f143171884f9
permissions -rw-r--r--
pvl-verkko: 0.4.1
81
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     1
"""
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     2
    Irker protocol implementation.
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     3
"""
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     4
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     5
from twisted.internet import protocol, defer
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     6
from twisted.protocols import basic
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     7
from twisted.python import log
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     8
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     9
import json, urlparse
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    10
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    11
class Irk (basic.LineOnlyReceiver) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    12
    """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    13
        A connected Irk client.
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    14
    """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    15
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    16
    delimiter = '\n'
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    17
    
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    18
    def connectionMade (self) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    19
        self.transport.logPrefix = self.logPrefix
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    20
        
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    21
        log.msg("connected", self)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    22
    
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    23
    def connectionLost (self, reason) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    24
        log.err("connection lost", reason)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    25
    
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    26
    def error (self, *args) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    27
        log.err(*args)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    28
        self.transport.loseConnection()
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    29
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    30
    def lineReceived (self, line) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    31
        """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    32
            JSON -> in
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    33
        """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    34
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    35
        try :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    36
            irk = json.loads(line)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    37
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    38
        except ValueError as ex :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    39
            # invalid
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    40
            return self.error(ex, line)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    41
        
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    42
        # dispatch
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    43
        self.factory.irkReceived(irk).addErrback(self.error, line)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    44
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    45
    def __str__ (self) :
93
d85d825cbca7 pvl.irker: handle missing transport in logPrefix (only happens when daemonized, for whatever reason)
Tero Marttila <terom@paivola.fi>
parents: 83
diff changeset
    46
        if not self.transport : return 'Irk'
d85d825cbca7 pvl.irker: handle missing transport in logPrefix (only happens when daemonized, for whatever reason)
Tero Marttila <terom@paivola.fi>
parents: 83
diff changeset
    47
81
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    48
        host = self.transport.getHost()
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    49
        peer = self.transport.getPeer()
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    50
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    51
        return "{host.host}:{host.port}:{peer.host}".format(host=host, peer=peer)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    52
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    53
    logPrefix = __str__
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    54
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    55
class IrkFactory (protocol.ServerFactory) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    56
    """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    57
        Manage connected Irk clients.
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    58
    """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    59
127
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    60
    MAXATTR = 16
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    61
81
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    62
    protocol = Irk
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    63
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    64
    def __init__ (self, irc) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    65
        self.irc = irc
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    66
    
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    67
    @defer.inlineCallbacks
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    68
    def irkReceived (self, irk) :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    69
        """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    70
            Deffered to handle lookup of target, and then sending message.
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    71
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    72
            Errbacks on failures.
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    73
        """
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    74
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    75
        log.msg(str(irk))
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    76
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    77
        if not 'to' in irk :
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    78
            raise ValueError("missing target: to")
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    79
        
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    80
        # MUST NOT be unicode
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    81
        # XXX: ValueError?
127
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    82
        url = urlparse.urlparse(str(irk.pop('to')))
81
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    83
        
127
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    84
        # connect, register, join
81
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    85
        target = yield self.irc.target(url)
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    86
        
127
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    87
        # dispatch attrs
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    88
        for attr, value in irk.iteritems() :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    89
            if len(attr) >= self.MAXATTR or not attr.islower() :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    90
                raise ValueError("invalid attr: %s" % (attr, ))
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    91
    
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    92
            method = getattr(self, 'irk_' + attr, None)
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    93
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    94
            if not method :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    95
                raise ValueError("unknown attr: %s" % (attr, ))
81
448ed86d0510 pvl.irker: irker reimplementation in Twisted
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    96
83
1cb48f2ba1e9 pvl.irker/irk: implement support for NOTICE
Tero Marttila <terom@paivola.fi>
parents: 81
diff changeset
    97
            if value :
1cb48f2ba1e9 pvl.irker/irk: implement support for NOTICE
Tero Marttila <terom@paivola.fi>
parents: 81
diff changeset
    98
                value = unicode(value)
127
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
    99
            else :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   100
                value = None
83
1cb48f2ba1e9 pvl.irker/irk: implement support for NOTICE
Tero Marttila <terom@paivola.fi>
parents: 81
diff changeset
   101
127
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   102
            method(target, value)
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   103
    
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   104
    # XXX: explicitly enable?
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   105
    def irk_privmsg (self, target, value) :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   106
        """
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   107
            Send PRIVMSG to target.
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   108
        """
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   109
        
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   110
        if not value :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   111
            # legacy
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   112
            return
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   113
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   114
        target.privmsg(value)
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   115
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   116
    def irk_notice (self, target, value) :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   117
        """
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   118
            Send NOTICE to target.
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   119
        """
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   120
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   121
        if not value :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   122
            raise ValueError("empty notice")
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   123
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   124
        target.notice(value)
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   125
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   126
    # TODO: refcounting vs join!
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   127
    def irk_part (self, target, value) :
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   128
        """
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   129
            PART target.
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   130
        """
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   131
        
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   132
        # value is optional
f143171884f9 pvl.irker: implement part
Tero Marttila <terom@paivola.fi>
parents: 93
diff changeset
   133
        target.part(value)