Discussion:
[Twisted-Python] irc bot, reacting to: irc_ERR_NOSUCHNICK. after the code where the reactor was started
peter
2015-10-05 09:33:09 UTC
Permalink
my bot inherits from irc.IRCClient, when it sends a message to another
user who isnt online irc_ERR_NOSUCHNICK(self, prefix, command) is called.
how can i react to that message, my code is called with:


class mybot(irc.IRCClient):
...
if __name__ == "__main__":

factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )



in irc_ERR_NOSUCHNICK... i got:
error_message = "%s bot is not connected to server" %
now.strftime("%Y-%m-%d %H:%M:%S")
log.warning(error_message)


which works.
but what i really would like to have is:


if __name__ == "__main__":

factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )

if "bot not online":
"send message to antoher user"


so basically i need the information that irc_ERR_... was called after
the reactor was started.
how do you do that?
peter
2015-10-05 11:42:31 UTC
Permalink
my bot inherits from irc.IRCClient, when it sends a message to another
user who isnt online irc_ERR_NOSUCHNICK(self, prefix, command) is called.
how can i react to that message, my code is called with:


class mybot(irc.IRCClient):
...
if __name__ == "__main__":

factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )



in irc_ERR_NOSUCHNICK... i got:
error_message = "%s bot is not connected to server" %
now.strftime("%Y-%m-%d %H:%M:%S")
log.warning(error_message)


which works.
but what i really would like to have is:


if __name__ == "__main__":

factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )

if "bot not online":
"send message to antoher user"


so basically i need the information that irc_ERR_... was called after
the reactor was started.
how do you do that?
Glyph Lefkowitz
2015-10-05 21:12:09 UTC
Permalink
my bot inherits from irc.IRCClient, when it sends a message to another user who isnt online irc_ERR_NOSUCHNICK(self, prefix, command) is called.
...
factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )
error_message = "%s bot is not connected to server" % now.strftime("%Y-%m-%d %H:%M:%S")
log.warning(error_message)
which works.
factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )
"send message to antoher user"
so basically i need the information that irc_ERR_... was called after the reactor was started.
how do you do that?
Use Endpoints <https://twistedmatrix.com/documents/15.4.0/core/howto/endpoints.html> so you get a nice `DeferredÂŽ back from connectTCP.
Add a callback to that Deferred.
Add a method to `XdccBotFactoryÂŽ that returns a `DeferredÂŽ that fires when its message is successfully sent and acknowledged, and then add a callback to that `DeferredÂŽ.
@inlineCallbacks
factory = XdccBotFactory(channel, nickname, xdccbot, xdccrequests)
endpoint = clientFromString(reactor, "...")
bot = yield endpoint.connect(factory)
online = yield bot.isBotOnline()
"send message to another user"
"ok"
Does this make sense?

-glyph
peter
2015-10-07 06:38:45 UTC
Permalink
Post by peter
my bot inherits from irc.IRCClient, when it sends a message to
another user who isnt online irc_ERR_NOSUCHNICK(self, prefix,
command) is called.
...
factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )
error_message = "%s bot is not connected to server" %
now.strftime("%Y-%m-%d %H:%M:%S")
log.warning(error_message)
which works.
factory = XdccBotFactory( channel, nickname, xdccbot, xdccrequests )
reactor.connectTCP( server, 6667, factory )
"send message to antoher user"
so basically i need the information that irc_ERR_... was called after
the reactor was started.
how do you do that?
1. Use Endpoints
<https://twistedmatrix.com/documents/15.4.0/core/howto/endpoints.html>
so you get a nice `DeferredŽ back from connectTCP.
2. Add a callback to that Deferred.
3. Add a method to `XdccBotFactoryŽ that returns a `DeferredŽ that
fires when its message is successfully sent and acknowledged, and
then add a callback to /that/ `DeferredŽ.
If you were to use inlineCallbacks to inline the callbacks you're
Post by peter
@inlineCallbacks
factory = XdccBotFactory(channel, nickname, xdccbot, xdccrequests)
endpoint = clientFromString(reactor, "...")
bot = *yield* endpoint.connect(factory)
online = *yield* bot.isBotOnline()
"send message to another user"
"ok"
Does this make sense?
-glyph
_______________________________________________
Twisted-Python mailing list
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
im sure youre solution is just fine, could you show me how you would
contruct isBotOnline?
im assuming that code would go into the class "mybot", next to
irc_ERR_NOSUCKNICK?
Glyph Lefkowitz
2015-10-07 07:49:45 UTC
Permalink
im sure youre solution is just fine, could you show me how you would contruct isBotOnline?
im assuming that code would go into the class "mybot", next to irc_ERR_NOSUCKNICK?
The problem with just doing that is that there is no affirmative response that a message was sent, so there's no way to fire the deferred successfully if that's all you're doing. Instead, you can use the ISON command to determine if the bot is online (and of course, the bot might go offline between the check and sending the message, so you will need to handle that case somehow too).

Since doing this is somewhat obscure, here's a working script that just checks if a nick specified on the command line is online on freenode:

from __future__ import print_function
from twisted.internet.defer import Deferred, inlineCallbacks
from twisted.words.protocols.irc import IRCClient
from twisted.internet.endpoints import clientFromString
from twisted.internet.protocol import Factory

class mybot(IRCClient, object):
def __init__(self):
self._isonQueue = []
self.motdReceived = Deferred()

def irc_RPL_ISON(self, prefix, params):
username, d = self._isonQueue.pop(0)
d.callback((username in params[1]))

def isOnline(self, username):
d = Deferred()
self.sendLine("ISON " + username)
self._isonQueue.append((username, d))
return d

def irc_RPL_ENDOFMOTD(self, prefix, params):
self.motdReceived.callback(None)

@inlineCallbacks
def main(reactor, nick):
endpoint = clientFromString(reactor, "tcp:chat.freenode.net:6667")
proto = yield endpoint.connect(Factory.forProtocol(mybot))
print("Waiting for MOTD...")
yield proto.motdReceived
print("Querying...")
isOnline = yield proto.isOnline(nick)
if isOnline:
print(nick, "is online!")
else:
print(nick, "is *NOT* online!")

from twisted.internet.task import react
from sys import argv
react(main, argv[1:])


-glyph
peter
2015-10-07 08:35:23 UTC
Permalink
Post by Glyph Lefkowitz
Post by peter
im sure youre solution is just fine, could you show me how you would
contruct isBotOnline?
im assuming that code would go into the class "mybot", next to irc_ERR_NOSUCKNICK?
The problem with just doing that is that there is no affirmative
response that a message was sent, so there's no way to fire the
deferred successfully if that's all you're doing. Instead, you can
use the ISON command to determine if the bot is online (and of course,
the bot might go offline between the check and sending the message, so
you will need to handle that case somehow too).
Since doing this is somewhat obscure, here's a working script that
*from* *__future__* *import* print_function
*from* *twisted.internet.defer* *import* Deferred, inlineCallbacks
*from**twisted.words.protocols.irc**import*IRCClient
*from**twisted.internet.endpoints**import*clientFromString
*from**twisted.internet.protocol**import*Factory
self._isonQueue = []
self.motdReceived = Deferred()
username, d = self._isonQueue.pop(0)
d.callback((username *in* params[1]))
d = Deferred()
self.sendLine("ISON " + username)
self._isonQueue.append((username, d))
*return* d
self.motdReceived.callback(None)
@inlineCallbacks
endpoint = clientFromString(reactor, "tcp:chat.freenode.net:6667")
proto = *yield* endpoint.connect(Factory.forProtocol(mybot))
*print*("Waiting for MOTD...")
*yield* proto.motdReceived
*print*("Querying...")
isOnline = *yield* proto.isOnline(nick)
*print*(nick, "is online!")
*print*(nick, "is *NOT* online!")
*from**twisted.internet.task**import*react
*from**sys**import*argv
react(main, argv[1:])
-glyph
_______________________________________________
Twisted-Python mailing list
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
thank you very much, i will try to adapt that solution to my code.
Loading...