Commits

Anonymous committed 3b1654f

inital files

  • Participants

Comments (0)

Files changed (6)

+syntax:glob
+*.pyc
+*~
+*.swp
+"""
+Viene lanciato il server e il client.
+Il client rimanda l'output di tutti i comandi al server.
+Il server manda l'input al client
+
+
+l'user entra con TYRION
+se ha mandato la password:
+    login(UsernamePassword(), self, IUser)
+    # unauthorized login se e' sbagliata
+
+
+"""
+
+from twisted.words.protocols import irc
+from twisted.internet import reactor, protocol
+from twisted.python import log
+from twisted.application import service, internet
+
+
+class BotNotAvailable(Exception):
+    pass
+
+
+class UserNotAvailable(Exception):
+    pass
+
+
+class ATYClientProtocol(irc.IRCClient):
+
+    nickname = "AugTy"
+    encoding = 'utf-8'
+
+    @property
+    def user(self):
+        try:
+            return self.service.users[self.nickname]
+        except KeyError:
+            raise UserNotAvailable
+
+    def handleCommand(self, command, prefix, params):
+        log.msg("BOT %s: %r" % (self.nickname, [prefix, command, params]))
+        method = getattr(self, 'irc_%s' % command, None)
+        try:
+            if method is not None:
+                method(prefix, params)
+            else:
+                self.irc_unknown(prefix, command, params)
+        except UserNotAvailable:
+            log.msg("No user available for %s" % command)
+        except:
+            log.deferr()
+
+    #def connectionMade(self):
+    #    irc.IRCClient.connectionMade(self)
+
+    #def connectionLost(self, reason):
+    #    irc.IRCClient.connectionLost(self, reason)
+
+    def signedOn(self):
+        log.msg("Bot %s signed on the remote server!" % self.nickname)
+        self.service.registerBot(self.nickname, self)
+
+    def joined(self, channel):
+        log.msg("client joined: %s" % channel)
+        self.user.joined(channel)
+
+    def irc_unknown(self, prefix, command, params):
+        self.user.sendMessage(command, *params, prefix=prefix)
+
+
+class ATYClientFactory(protocol.ClientFactory):
+
+    protocol = ATYClientProtocol
+
+    def __init__(self, service):
+        self.service = service
+
+    def buildProtocol(self, addr):
+        p = protocol.ClientFactory.buildProtocol(self, addr)
+        p.service = self.service
+        return p
+
+
+class ATYServerProtocol(irc.IRC):
+
+    encoding = 'utf-8'
+
+    nickname = ''
+    username = ''
+    realname = ''
+
+    def handleCommand(self, command, prefix, params):
+        log.msg("SERVER: %r" % ([prefix, command, params]))
+        method = getattr(self, 'irc_%s' % command, None)
+        try:
+            if method is not None:
+                method(*params)
+            else:
+                self.irc_unknown(command, params)
+        except TypeError:
+            self.sendMessage(irc.ERR_NEEDMOREPARAMS, command,
+                    ":Not enough parameters")
+        except BotNotAvailable:
+            self.notice('ATY', self.mask, 'The bot is not yet available.')
+        except:
+            log.deferr()
+
+    def irc_NICK(self, nickname):
+        self.nickname = nickname
+
+    def irc_USER(self, username, mode, unused, realname):
+        self.username = username
+        self.realname = realname
+        self.service.registerUser(self.nickname, self)
+        self.sendMessage(irc.RPL_WELCOME, ':connected to ATY IRC')
+
+    @property
+    def bot(self):
+        try:
+            return self.service.bots[self.nickname]
+        except KeyError:
+            if not self.service.botIsRunning(self.nickname):
+                bot = self.service.createBot(self.nickname)
+            raise BotNotAvailable
+
+    def botReady(self):
+        self.notice('ATY', self.mask, 'The bot is ready!')
+
+    @property
+    def mask(self):
+        return "%s!%s@%s" % (self.nickname, self.username, self.hostname)
+
+    def irc_JOIN(self, channels, keys=None):
+        channels = channels.split(',')
+        for channel in channels:
+            self.bot.join(channel)
+
+    def joined(self, channel):
+        self.join(self.mask, channel)
+
+    def irc_unknown(self, command, params):
+        log.msg("UNKNOWN: %s %s" % (command, params))
+
+
+class ATYServerFactory(protocol.ServerFactory):
+    protocol = ATYServerProtocol
+
+    def __init__(self, service):
+        self.service = service
+
+    def buildProtocol(self, addr):
+        p = protocol.ServerFactory.buildProtocol(self, addr)
+        p.service = self.service
+        return p
+
+
+class ATYService(service.MultiService):
+
+    clientFactory = ATYClientFactory
+    serverFactory = ATYServerFactory
+    
+    BOT_SERVICE = 'TYClient_%s'
+
+    def __init__(self):
+        service.MultiService.__init__(self)
+        self.bots = {}
+        self.users = {}
+
+    def createServer(self):
+        self.server = internet.TCPServer(6667, self.serverFactory(self))
+        self.server.setName('ATYServer')
+        self.addService(self.server)
+        return self.server
+
+    def createBot(self, nickname):
+        client = internet.TCPClient('irc.azzurra.org', 6667,  self.clientFactory(self))
+        client.setName(self.BOT_SERVICE % nickname)
+        # self.bots[nickname] = client
+        self.addService(client)
+        return client
+
+    def botIsRunning(self, botname):
+        try:
+            bot = self.getServiceNamed(self.BOT_SERVICE % botname)
+        except KeyError:
+            return False
+        return bot.running
+
+
+    def registerBot(self, nickname, bot):
+        log.msg("registering bot %r: %r" % (nickname, bot))
+        self.bots[nickname] = bot
+        user = self.users.get(nickname)
+        if user:
+            user.botReady()
+
+    def registerUser(self, nickname, user):
+        log.msg("registering user %r: %r" % (nickname, user))
+        self.users[nickname] = user
+
+
+if __name__ == '__main__':
+    import sys
+
+    log.startLogging(sys.stdout)
+
+    #f = ATYClientFactory()
+    #reactor.connectTCP("irc.azzurra.org", 6667, f)
+    from twisted.cred.portal import Portal
+    from twisted.words.service import InMemoryWordsRealm, IRCFactory, Group
+    from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse
+
+    portal = Portal(InMemoryWordsRealm('ATY'))
+    # portal.realm.addGroup(Group('test'))
+    portal.realm.createGroupOnRequest = True
+    checker = InMemoryUsernamePasswordDatabaseDontUse()
+    checker.addUser("tyrion", "ciao")
+    portal.registerChecker(checker)
+
+    reactor.listenTCP(6667, IRCFactory(portal.realm, portal))
+    reactor.run()
+# Read username, output from non-empty factory, drop connections
+# Use deferreds, to minimize synchronicity assumptions
+# Write application. Save in 'finger.tpy'
+
+from twisted.application import internet, service
+from twisted.internet import protocol, reactor, defer
+from twisted.protocols import basic
+
+class FingerProtocol(basic.LineReceiver):
+    def lineReceived(self, user):
+        d = self.factory.getUser(user)
+
+        def onError(err):
+            return 'Internal error in server'
+        d.addErrback(onError)
+
+        def writeResponse(message):
+            self.transport.write(message + '\r\n')
+            self.transport.loseConnection()
+        d.addCallback(writeResponse)
+
+class FingerFactory(protocol.ServerFactory):
+    protocol = FingerProtocol
+
+    def __init__(self, **kwargs):
+        self.users = kwargs
+
+    def getUser(self, user):
+        return defer.succeed(self.users.get(user, "No such user"))
+
+application = service.Application('finger', uid=1, gid=1)
+factory = FingerFactory(moshez='Happy and well')
+internet.TCPServer(79, factory).setServiceParent(
+    service.IServiceCollection(application))
+from zope.interface import implements
+
+from twisted.internet import defer
+from twisted.python import failure
+from twisted.cred import error, credentials, checkers
+from twisted.words import iwords
+
+class IRCChecker(object):
+    implements(checkers.ICredentialsChecker)
+
+    credentialInterfaces = (credentials.IUsernamePassword,
+                            credentials.IUsernameHashedPassword)
+
+    def __init__(self, db):
+        self.db = iwords.IChatService(db)
+
+    def addUser(self, name, password):
+        # this breaks the IChatService interface
+        def setPassword(user):
+            user.password = password
+        self.db.createUser(name).addCallback(setPassword)
+
+    def _cbPasswordMatch(self, matched, username):
+        if matched:
+            return username
+        else:
+            return failure.Failure(error.UnauthorizedLogin())
+
+    def requestAvatarId(self, credentials):
+        username = credentials.username # shoule be unicode
+
+        def checkPassword(user):
+            password = getattr(user, 'password', None)
+            if password:
+                d = defer.maybeDeferred(credentials.checkPassword, password)
+                return d.addCallback(self._cbPasswordMatch, username)
+            else:
+                return defer.succeed(username)
+
+        return self.db.getUser(username).addCallback(checkPassword)

File twisted/plugins/aty_plugin.py

+from zope.interface import implements
+
+from twisted.python import usage
+from twisted.plugin import IPlugin
+from twisted.application.service import IServiceMaker
+from twisted.application import internet
+from twisted.cred import credentials, strcred
+from twisted.cred.portal import Portal
+
+import aty
+
+class ATYOptions(usage.Options, strcred.AuthOptionMixin):
+    supportedInterfaces = (credentials.IUsernamePassword,)
+
+    optParameters = [
+        ["port", "p", 1234, "Server port number"],
+        ["host", "h", "localhost", "Server hostname"]]
+
+
+class ATYServiceMaker(object):
+    implements(IServiceMaker, IPlugin)
+
+    tapname = 'aty'
+    description = 'Augmented Tyrion'
+    options = ATYOptions
+
+    def makeService(self, options):
+        from twisted.words.service import InMemoryWordsRealm, IRCFactory
+        from irc_auth import IRCChecker
+
+        realm = InMemoryWordsRealm('ATY')
+        realm.createGroupOnRequest = True
+
+        checker = IRCChecker(realm)
+        checker.addUser(u'tyrion', 'ciao')
+
+        #portal = Portal(realm, options['credCheckers'])
+        portal = Portal(realm)
+        portal.registerChecker(checker)
+
+        #checker = InMemoryUsernamePasswordDatabaseDontUse()
+        #checker.addUser("tyrion", "ciao")
+        #portal.registerChecker(checker)
+
+        return internet.TCPServer(6667, aty.ATYFactory(realm, portal))
+
+
+"""
+far partire il client, aspettare che si autentichi
+far partire il server, aspettare che l'user si autentichi.
+
+fai partire il server.
+fai partire i client e farli autenticare.
+il server mappa l'utente ad un client in base all'username
+
+          /  ATYServerFactory => ATYServerProtocol
+ATYServiceMaker
+          \  ATYClientFactory => ATYClientProtocol
+
+
+1) ATYClientFactory => ATYClientProtocol
+2) signedOn => startService
+
+class ATYServerFactory(protocol.ServerFactory):
+
+    def __init__(self, service):
+        self.service = service
+
+    def buildProtocol(self, addr):
+        p = protocols.ServerFactory.buildprotocol(self, addr)
+        p.service = service
+        return p
+
+
+class ATY(object):
+
+    server
+    client
+
+"""
+
+class ATYServiceMaker(object):
+    implements(IServiceMaker, IPlugin)
+
+    tapname = 'aty'
+    description = 'Augmented Tyrion'
+    options = ATYOptions
+
+    def makeService(self, options):
+        from aty import ATYService
+        
+        service = ATYService()
+        service.setName("ATY")
+        service.createServer()
+        #service.createBot('AugTy')
+
+        return service
+
+
+atyServiceMaker = ATYServiceMaker()

File twisted/plugins/cred_irc.py

+from zope.interface import implements
+
+from twisted import plugin
+from twisted.cred.strcred import ICheckerFactory
+from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse
+from twisted.cred.credentials import IUsernamePassword, IUsernameHashedPassword
+
+from irc_auth import IRCChecker
+
+
+class IRCCheckerFactory(object):
+    implements(ICheckerFactory, plugin.IPlugin)
+    authType = 'irc'
+    authHelp = 'nope.'
+    argStringFormat = 'A colon-separated list (name:password:...)'
+    credentialInterfaces = (IUsernamePassword,
+                            IUsernameHashedPassword)
+
+    def generateChecker(self, argstring):
+        """
+        This checker factory expects to get a list of
+        username:password pairs, with each pair also separated by a
+        colon. For example, the string 'alice:f:bob:g' would generate
+        two users, one named 'alice' and one named 'bob'.
+        """
+        checker = IRCChecker() # FIXME
+        if argstring:
+            pieces = argstring.split(':')
+            if len(pieces) % 2:
+                from twisted.cred.strcred import InvalidAuthArgumentString
+                raise InvalidAuthArgumentString(
+                    "argstring must be in format U:P:...")
+            for i in range(0, len(pieces), 2):
+                username, password = pieces[i], pieces[i+1]
+                checker.addUser(username, password)
+        return checker
+
+
+
+ircCheckerFactory = IRCCheckerFactory()