Writing a blocking shell around a twisted IRC client

I am trying to write a dead simple interface for an IRC library, for example:

import simpleirc

connection = simpleirc.Connect('irc.freenode.net', 6667)
channel = connection.join('foo')
find_command = re.compile(r'google ([a-z]+)').findall

for msg in channel:
    for t in find_command(msg):
        channel.say("http://google.com/search?q=%s" % t)

Working from their example , I ran into a problem (the code is a bit long, so I pasted it here ). Since the call channel.__next__should be returned when calling callback <IRCClient instance>.privmsg, it seems that there is no clean option. Using exceptions or threads seems wrong here, is there an easier (blocking?) Way to use twisted that will make this possible?

+3
source share
1 answer

, Twisted "", , , , , , .

, , , . :

import re
from twisted.internet import reactor, protocol
from twisted.words.protocols import irc

find_command = re.compile(r'google ([a-z]+)').findall

class Googler(irc.IRCClient):
    def privmsg(self, user, channel, message):
        for text in find_command(message):
            self.say(channel, "http://google.com/search?q=%s" % (text,))

def connect():
    cc = protocol.ClientCreator(reactor, Googler)
    return cc.connectTCP(host, port)

def run(proto):
    proto.join(channel)

def main():
    d = connect()
    d.addCallback(run)
    reactor.run()

( ). : inlineCallbacks:

import re
from twisted.internet import reactor, protocol, defer
from twisted.words.protocols import irc

find_command = re.compile(r'google ([a-z]+)').findall

class Googler(irc.IRCClient):
    def privmsg(self, user, channel, message):
        for text in find_command(message):
            self.say(channel, "http://google.com/search?q=%s" % (text,))

@defer.inlineCallbacks
def run():
    cc = protocol.ClientCreator(reactor, Googler)
    proto = yield cc.connectTCP(host, port)
    proto.join(channel)

def main():
    run()
    reactor.run()

addCallbacks. yield . , , Googler API ( IRCClient Twisted, - ). , Googler.join Channel , Channel :

@defer.inlineCallbacks
def run():
    cc = protocol.ClientCreator(reactor, Googler)
    proto = yield cc.connectTCP(host, port)
    channel = proto.join(channel)
    for msg in channel:
        msg = yield msg
        for text in find_command(msg):
            channel.say("http://google.com/search?q=%s" % (text,))

API . , yield , , .;)

. , , . . - corotwine, CPython, Channel , , . :

from corotwine import protocol

def run():
    proto = Googler()
    transport = protocol.gConnectTCP(host, port)
    proto.makeConnection(transport)
    channel = proto.join(channel)
    for msg in channel:
        for text in find_command(msg):
            channel.say("http://google.com/search?q=%s" % (text,))

Channel, :

from corotwine import defer

class Channel(object):
    def __init__(self, ircClient, name):
        self.ircClient = ircClient
        self.name = name

    def __iter__(self):
        while True:
            d = self.ircClient.getNextMessage(self.name)
            message = defer.blockOn(d)
            yield message

, , Googler, getNextMessage, , IRCClient:

from twisted.internet import defer

class Googler(irc.IRCClient):
    def connectionMade(self):
        irc.IRCClient.connectionMade(self)
        self._nextMessages = {}

    def getNextMessage(self, channel):
        if channel not in self._nextMessages:
            self._nextMessages[channel] = defer.DeferredQueue()
        return self._nextMessages[channel].get()

    def privmsg(self, user, channel, message):
        if channel not in self._nextMessages:
            self._nextMessages[channel] = defer.DeferredQueue()
        self._nextMessages[channel].put(message)

, run , .

from greenlet import greenlet

def main():
    greenlet(run).switch()
    reactor.run()

run , ( "" , ), . , corotwine run. , run , "" . , .

, , Twisted . .

+10

Source: https://habr.com/ru/post/1742206/


All Articles