gawel / irc3 Goto Github PK
View Code? Open in Web Editor NEWplugable irc client library based on python's asyncio with DCC and SASL support
Home Page: https://irc3.readthedocs.io/
License: MIT License
plugable irc client library based on python's asyncio with DCC and SASL support
Home Page: https://irc3.readthedocs.io/
License: MIT License
I noticed that irc3 does not load plugins if they do not contain any "explicit features" (like @extend
), but only overwrite functions like connection_made
or server_ready
. To illustrate and reproduce this issue, execute the following code with both Python 2.7 and Python 3:
import irc3
import random
@irc3.plugin
class PluginA:
def __init__(self, bot):
self.bot = bot
self.log = self.bot.log
print("A got loaded!")
def connection_made(self):
print("A did something important.")
@irc3.extend
def i_do_not_serve_any_purpose_whatsoever(self):
pass
@irc3.plugin
class PluginB:
def __init__(self, bot):
self.bot = bot
self.log = self.bot.log
print("B got loaded!")
def connection_made(self):
print("B did something important.")
def main():
# instanciate a bot
config = dict(
nick='justinfan%d' % random.randint(1, 99999999),
host="irc.twitch.tv", port=6667,
includes=[
__name__, # this register MyPlugin
]
)
bot = irc3.IrcBot.from_config(config)
bot.run(forever=True)
if __name__ == '__main__':
main()
Output with Python 2.7.10, surprisingly:
A got loaded!
A did something important.
Output with Python 3.5.0, as expected:
A got loaded!
B got loaded!
A did something important.
B did something important.
irc3
is installed in the benny
pyvenv, while ipython3
was installed to the yuvallanger
user environment using python3 -m pip install --user ipython
.
The error:
(benny) yuvallanger@yankel-Lenovo-G505:~/projects/benny⟫ ipython3
import irc3
/home/yuvallanger/.local/lib/python3.5/site-packages/IPython/core/interactiveshell.py:712: UserWarning: Attempting to work in a virtua
lenv. If you encounter problems, please install IPython inside the virtualenv.
warn("Attempting to work in a virtualenv. If you encounter problems, please "
Python 3.5.2 (default, Jul 5 2016, 12:43:10)
Type "copyright", "credits" or "license" for more information.
IPython 5.0.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import irc3
---------------------------------------------------------------------------
DistributionNotFound Traceback (most recent call last)
<ipython-input-1-457396cbab9d> in <module>()
----> 1 import irc3
/home/yuvallanger/.virtualenvs/benny/lib/python3.5/site-packages/irc3/__init__.py in <module>()
12 from . import utils
13 from . import rfc
---> 14 from . import base
15 from irc3.compat import urlopen
16 from .compat import text_type
/home/yuvallanger/.virtualenvs/benny/lib/python3.5/site-packages/irc3/base.py in <module>()
19 version = ''
20 else:
---> 21 version = pkg_resources.get_distribution('irc3').version
22
23
/home/yuvallanger/.local/lib/python3.5/site-packages/pkg_resources/__init__.py in get_distribution(dist)
533 dist = Requirement.parse(dist)
534 if isinstance(dist, Requirement):
--> 535 dist = get_provider(dist)
536 if not isinstance(dist, Distribution):
537 raise TypeError("Expected string, Requirement, or Distribution", dist)
/home/yuvallanger/.local/lib/python3.5/site-packages/pkg_resources/__init__.py in get_provider(moduleOrReq)
413 """Return an IResourceProvider for the named module or requirement"""
414 if isinstance(moduleOrReq, Requirement):
--> 415 return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
416 try:
417 module = sys.modules[moduleOrReq]
/home/yuvallanger/.local/lib/python3.5/site-packages/pkg_resources/__init__.py in require(self, *requirements)
941 included, even if they were already activated in this working set.
942 """
--> 943 needed = self.resolve(parse_requirements(requirements))
944
945 for dist in needed:
/home/yuvallanger/.local/lib/python3.5/site-packages/pkg_resources/__init__.py in resolve(self, requirements, env, installer, replace_
conflicting)
827 if dist is None:
828 requirers = required_by.get(req, None)
--> 829 raise DistributionNotFound(req, requirers)
830 to_activate.append(dist)
831 if dist not in req:
DistributionNotFound: The 'irc3' distribution was not found and is required by the application
In [2]:
Everyone likes DCC, right?
I think CHAT and SEND would cover most use cases.
because it uses the unix command-line (wget, grep etc.). see
Line 62 in 4d99b5f
Example: @command(name='example', aliases=['foo', 'bar'])
Is there example code for a bot which is capable to receive DCC file transfers?
That would be really helpful.
Hi,
Is irc3 able to send /me commands ?
If I do a "/me say hello", and send it with bot.privmsg, the result in an irc client, is a message from the bot like "/me say hello" rather than "* bot say hello"
It looks like the library is escaping the content sent. Is there a way to call the /me command by another way ?
Thanks,
Audric
does this library support vhosts or binding to a certain address?
Given the following plugin:
# ./someplugin.py
import irc3
from irc3.plugins.command import command
from tinydb import TinyDB
@irc3.plugin
class SomePlugin(object):
def __init__(self, bot):
self.bot = bot
And following configuration file:
# ./config.ini
[bot]
nick = ABot
realname = Robo
host = irc.rizon.net
port = 6697
ssl = true
ssl_verify = CERT_NONE
includes =
irc3.plugins.command
someplugin
And invoking the bot as:
irc3 config.ini
An error is generated:
File "C:\Python27\lib\site-packages\irc3\utils.py", line 314, in maybedotted
'Not able to resolve %s' % name)
LookupError: Not able to resolve someplugin
Deleting the from tinydb import TinyDB
line from the plugin results in normal behavior.
Just trying to debug an autocommand, the commands being sent don't seem to be logged?
Maybe it's time to add it to tox.ini? Don't know how much people are already using it, but my distri has it as default for a few months now.
hi, I'm executing an irc3 bot inside a celery task. The bot correctly connects to the server but it doesn't auto connect to the channels. And it behaves in a strange way with my plugin (a plugin to print received messages): it works for the first few messages received, then nothing happens.
And it doesn't answer to pings.
If I run my code directly and not inside a celery task it works perfectly.
Currently if we have a plugin that returns a lot of data, irc3 will return it all potentially leading to flood in the channel.
It would be nice to have a plugin to restrict the output returned by irc3.
supybot for example will return the first part of the result and the next parts only if the user asks for .more
.
I have a logger bot running on Heroku using my s3_handler branch. The repository that is actually running on Heroku is here: https://github.com/singingwolfboy/edxbot However, events are being triggered twice. Here's an example of a log file that the bot generated:
09:48 edxbottest joined #edx-code-test
09:48 edxbottest joined #edx-code-test
20:49 singingwolfboy joined #edx-code-test
20:49 edxbottest joined #edx-code-test
20:49 <singingwolfboy> t-t-t-test
20:49 <edxbottest> t-t-t-test
You can see that each event is duplicated, once with the nick of the person who actually fired the event, and once with the nick of the bot. Any idea what's going on here, or how to fix it? My pull request doesn't modify any of the event-handling code at all, and I don't think there's anything special about running it on Heroku, either.
I'm trying to write a client, but am finding the behaviour when the nick
command fails a little frustrating.
As it currently stands, when the badnick
method is called, a callback is set to retry the attempt again in 30 seconds. If the user picks a new nick in the interim (potentially a long time, as this callback is set repeatedly), and then the clashing nick disconnects, the user will get renamed, despite having already selected a new nick.
I would like to forego this behaviour in my client but, as far as I can tell, I cannot remove this one line without duplicating the whole module into my program, as if I were to subclass the module, the old method would already have been registered as an event.
Have I missed something --- is there a cleaner way for me to do this?
If there is no obvious way to fix this at the moment, I wonder if it would be desirable for me to refactor this module in some way to allow for easier extension, and if there are any suggestions for how I might proceed?
Thanks for taking the time to read this --- sorry that the report is little long!
Does/could irc3 provide a way to validate if a certain irc nick exists on a server?
Edit: Disregard everything, I suck cocks.
The regex for RPL_STATSILINE
is:
"I (?P<host>\S+) . (?P<host>\S+) (?P<port>\S+) (?P<class>\S+)")
It's an error to have both groups named host, this can't possibly work.
So I'm currently trying to retrieve and set the topic of a channel but I cannot get my code to work. I've tried requesting the topic with bot.topic(chan) in a cron and then receiving the event with the event decorator and the rfc.RPL_TOPIC but that yielded no results at all.
Is there something I'm missing? I'd happily PR an example after I got a working version for this so others don't run into the same problem.
I wonder how it looks on Windows..
https://github.com/gawel/irc3/blob/master/irc3/__init__.py#L63-L71
If you trigger connection_lost, self.closed is set to True, then it calls close which immediately returns (since we just set closed to True)
Single threaded nature of python should be enough to guarantee that closed is set to True at the end of protocol.close(), so this line is not needed probably ?
https://github.com/gawel/irc3/blob/master/irc3/__init__.py#L64
It could be usefull to avoid some names collisions, for example to be able to create a !reload command with the new plugin reload system.
Exemple:
@command(name='reload', permission='admin')
def cmd_reload(self, mask, target, args):
"""
Reload a plugin on the fly
%%reload <plugins>...
"""
self.bot.reload(*args['<plugins>'])
I made some changes locally in irc3/plugins/command.py and it seems to work, but I created a gist instead a pull request because I was not sure about the changes: https://gist.github.com/metathink/4a00a1d7bc9901781e08
Currently lists are not allowed as values for the Storage-plugin and need a workaround:
# Initialize list
bot.db[key] = dict(key=[])
# Access list
bot.db[key]['key'].append(stuff)
Hi,
It's a great module and saved me a lot of time but there is some problems with rejoining password protected channels. The bot successfully joins the channel at startup, the problem lies in the plugin autojoins.py when it tries to rejoin. I looked in the code and it doesn't try joining the channel by using the strings it gets from the config file, where I put the channels in the format " " so the bot can't join the password protected channel after kick or loss of connection.
I made a workaround so my bot could rejoin by using a for-statement that iterates over an if-statement testing the return code from the startswith-method by iterating over self.channels in the event on_kick and on_err_join to rejoin by using the string gotten from the config. A more permanent fix can be made, I have one solution that can be of intrest.
It would be great if the bot could rejoin password protected channels too.
Best regards, No-0n3
When trying to connect to Hackint with SSL I couldn't because it requires verify_mode CERT_NONE
, which in turn needs check_hostname
disabled, which seems to be impossible to set via the config.
The connection part of the config I can reproduce the error with:
[bot]
nick = irc3bot
username = irc3bot
host = irc.hackint.org
port = 9999
# uncomment this if you want ssl support
ssl = true
# uncomment this if you don't want to check the certificate
ssl_verify = CERT_NONE
check_hostname = false
The error thrown:
in irc3/base.py", line 304, in get_ssl_context
context.verify_mode = verify_mode
ValueError: Cannot set verify_mode to CERT_NONE when check_hostname is enabled.
irc3 should not allow newlines to be inserted via command parameters, as this can cause IRC command injection.
For example,
bot.privmsg(chan, text)
with text="\nJOIN #channel"
would make the bot join #channel. Newlines could either be replaced by spaces, '\n' or dropped altogether (but I think spaces are probably the best option).
IrcBot.create_connection currently only calls loop.create_connection when it first connects. Also, the Task is run using the loop returned by get_event_loop() because the loop to run in is never specified in the Task constructor. On connection_lost, the loop is completely shifted over to the result of get_event_loop().
I propose shifting the loop argument to another function. The constructor, a set_loop() function, or a loop property would all work. When create_connection is called, it would then use self.loop. The protocol would call self.factory.create_connection(protocol=self.class) in connection_lost.
split_message uses .strip(), which removes whitespace. Unfortunately, '\x1f', which is used to set underline, is the 'unit seperator' and thus counts as whitespace. This means a message that starts with underlined text does not show up as underlined.
This is also true for '\x1d' (italic). '\x02' (bold), '\x03' (color), '\x0f' (reset) and '\x16' (reverse colors) are not whitespace.
Hi,
First of all thanks for this library, it's very easy to use 👍
https://github.com/gawel/irc3/blob/master/irc3/__init__.py#L208-L213
The template config.ini
mentions
# The maximum amount of lines irc3 sends at once.
# Default to 4
# flood_burst = 10
So shouldn't the range only do for i in range(flood_burst)
? Adding 1 will end up getting one line too much.
Setting it to 0 will still disable rate control so that's okay.
Thanks!
On a lot of IRC networks there are more user modes than just +v
(+
), +h
(%
) and +o
(@
). Inspircd for instance also supports +a
(&
) and +q
(~
) for channel admin (can access CS) and channel owner. irc3.plugins.userlist
currently doesn't seem to support those modes.
I don't know what the scope is of this project, IRC servers differ a lot on tiny details like this. You may or may not want do deal with these issues, but then you maybe should put this into the documentation.
It would be usefull when developing a plugin to be able to reload a specific plugin or all the plugins on the fly. I'm not sure where that new function should be available, maybe in the IrcBot instance or in a new plugin. A way to detect the reload of a plugin must also be provided, maybe a simple "before_reload" or "on_unload" method on the plugin's instance should be called.
Some servers don't like a lot of reconnection in a short period of time and this also would be usefull to make littles changes in a plugin while keeping the entire bot available for the users in the channel.
I'm having a problem with irc3 and ZNC, the problem being that irc3 connects perfectly, but it doesn't join any channels and it doesn't receive or send messages for the channels the bouncer is in, which in theory should also be channels the bot is in due to the way a bouncer works. Is this a bug, or a problem with the way I'm using irc3?
It'd be great if you could add a license to this repository. There's some code I'd like to fork to use in another project, but without a license I'm unable to do so.
Where is the backport
module coming from?
I see it being imported at https://github.com/gawel/irc3/blob/master/irc3/compat.py#L22
But it's seems to not be in the sources and pip install backport
finds nothing as well.
Due to circumstances my bot today rendered too large responses, which led to it getting killed for RevQ exceeded. It'd probably be better if irc3 would drop those messages or snip them, probably while printing a warning or something like that.
Why fix this in irc3 and not in the offending plugin? It seems like this would be an issue that could potentially and unexpectedly affect a lot of different plugins, for example if you're consuming an API which suddenly returns unexpectedly large results.
When using the shell_command plugin, the plugin will react as soon as a simple substring match of its nickname is found. Could you verify that the nickname has at least boundaries around it when it matches, eg /\b$nick\b/ ?
Sometime we want to be able to save data on disk for a plugin (say: the list of person to ping at a certain time).
It would be nice if irc3 could provide a framework to retrieve/save data on the disk.
Maybe storing the infos as dict and reading/saving it as json ?
with the latest 1.0 version of venusian plugin events are not triggered and registered anymore. with venusian 1.0a8 it does work.
Just started using IRC3 and having an issue where the program keeps thinking it is disconnected (freenode if it matters):
INFO irc3.totallynotabot We're waiting a ping for too long. Trying to reconnect...
CRITICAL irc3.totallynotabot connection lost (4350070008): 'No pong reply'
However it is not disconnected. This causes it to attempt to reconnect and then ends up making a another connection with a different username.
http://ircv3.net/specs/extensions/sasl-3.1.html
Please consider implementing support for the AUTHENTICATE extension, supported by various networks (e.g. Freenode and Mozilla) as a way to automatically identifying to Nickserv during the initial connection phase without requiring clients to PRIVMSG their credentials.
I get the following exception on FreeBSD:
File "<string>", line 17, in <module>
File "/tmp/pip_build_root/irc3/setup.py", line 40, in <module>
long_description=read('README.rst'),
File "/tmp/pip_build_root/irc3/setup.py", line 33, in read
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
File "/root/.pyenv/versions/3.4.0/lib/python3.4/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 734: ordinal not in range(128)
This is because the open
call in the read
method in setup.py is not set to read UTF-8 characters (which README.rst apparently has).
A solution would be either to make README.rst all ASCII, or to change the open() call to include the UTF-8 encoding.
Without having a server running, the doctests for irc.plugins.storage.Redis
will fail.
For example if we use '.' as a prefix's command, then the command .echo will work, but aecho, becho, etc will work too because the prefix is interpreted as a regex.
Hi, I've encountered what seems to be a bug when using the commands plugin.
Here's the fairly simple plugin.
import irc3
from irc3.plugins.command import command
import pipeau
@irc3.plugin
class Plugin:
def __init__(self, bot):
self.bot = bot
@command(permission='view')
def eddy_malou(self, mask, target, args):
"""Quotes from http://eddy-malou.com.
%%eddy_malou
"""
msg = yield from pipeau.eddy_malou()
yield msg
And here's the pipeau.eddy_malou() function :
@asyncio.coroutine
def load_page_source_async(url):
loop = asyncio.get_event_loop()
page_source = yield from loop.run_in_executor(None, load_page_source, url) # error seems to come from here
return page_source
@asyncio.coroutine
def eddy_malou():
"""Coroutine loading a quote from http://www.pipotronic.com."""
page_source = yield from load_page_source_async('http://eddy-malou.com')
soup = BeautifulSoup(page_source)
base_element = soup.find('p', { 'id': 'maloutot' })
return element_contents(base_element)
I end up with the following message :
ERROR asyncio Exception in callback <bound method event.async_callback of <bound event :(?P<mask>\S+) PRIVMSG (?P<target>\S+) :{re_cmd}(?P<cmd>\w+)(\s(?P<data>\S.*)|$) to <bound method Commands.on_command of <Commands ['!eddy_malou', '!help', '!ping', '!pipotronic']>>>>({'mask': '[email protected]', 'target': '#pipotronic', 'data': None, 'cmd': 'eddy_malou'},)
handle: Handle(<bound method event.async_callback of <bound event :(?P<mask>\S+) PRIVMSG (?P<target>\S+) :{re_cmd}(?P<cmd>\w+)(\s(?P<data>\S.*)|$) to <bound method Commands.on_command of <Commands ['!eddy_malou', '!help', '!ping', '!pipotronic']>>>>, ({'mask': '[email protected]', 'target': '#pipotronic', 'data': None, 'cmd': 'eddy_malou'},))
Traceback (most recent call last):
File "/usr/local/lib/python3.4/asyncio/events.py", line 39, in _run
self._callback(*self._args)
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/dec.py", line 55, in async_callback
return self.callback(**kwargs)
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/plugins/command.py", line 253, in on_command
return self.do_command(predicates, meth, mask, target, **kw)
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/plugins/command.py", line 309, in do_command
callback(res)
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/plugins/command.py", line 320, in command_callback
handle = self.context.call_many('privmsg', iterator(msgs))
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/base.py", line 275, in call_many
for i, arg in enumerate(args):
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/plugins/command.py", line 316, in iterator
for msg in msgs:
File "/home/jmcomets/Bundle/irc_bots/plugin.py", line 28, in eddy_malou
msg = yield from pipeau.eddy_malou()
File "/home/jmcomets/Bundle/irc_bots/pipeau.py", line 38, in eddy_malou
page_source = yield from load_page_source_async('http://eddy-malou.com')
File "/home/jmcomets/Bundle/irc_bots/pipeau.py", line 24, in load_page_source_async
page_source = yield from loop.run_in_executor(None, load_page_source, url)
File "/usr/local/lib/python3.4/asyncio/futures.py", line 349, in __iter__
assert self.done(), "yield from wasn't used with future"
AssertionError: yield from wasn't used with future
ERROR asyncio Exception in callback <bound method IrcBot.privmsg of <irc3.IrcBot object at 0x7ff8a280eb38>>('#pipotronic', Future<PENDING, [<function wrap_future.<locals>._check_cancel_other at 0x7ff8a23da488>]>)
handle: TimerHandle(97160.945039665, <bound method IrcBot.privmsg of <irc3.IrcBot object at 0x7ff8a280eb38>>, ('#pipotronic', Future<PENDING, [<function wrap_future.<locals>._check_cancel_other at 0x7ff8a23da488>]>))
Traceback (most recent call last):
File "/usr/local/lib/python3.4/asyncio/events.py", line 39, in _run
self._callback(*self._args)
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/__init__.py", line 180, in privmsg
for message in messages:
File "/home/jmcomets/.local/lib/python3.4/site-packages/irc3/utils.py", line 114, in split_message
if len(message) >= max_length:
TypeError: object of type 'Future' has no len()
I am the author of an existing IRC Bot project which is for python 2.7 and currently lacks a complete strategy for moving to python 3. The project is at https://github.com/kiwiheretic/logos-v2 and has a wiki at https://github.com/kiwiheretic/logos-v2/wiki. I am looking at your project as a possible migration option as it would be easier for me to just concentrate on plugins rather than have to maintain an entire bot. Also I wish to avoid reinventing wheels that I don't have to when I eventually move to python 3. (Especially seeing that Twisted seems unsupported on Python 3). However there are some things about your project I am not clear about and hopefully you will be able to answer them for me.
Thanking you, in advance, for your time.
Hi,
i'm trying to use the bot in order to provide an irc logger. Basicly this (heriting from RainbowLoggingHandler
for coloration of the log)
# pour un logging efficace
import logging
import logging.handlers
from rainbow_logging_handler import RainbowLoggingHandler
# pour une gestion plus jolie des path
from path import path
# to log to irc3
import irc3
class IrcHandler(RainbowLoggingHandler):
def __init__(self, nick, host, channels: list, port=6667, ssl=False, **kwargs):
super().__init__(None, kwargs)
self.channels = channels
self.bot = irc3.IrcBot(nick=nick, autojoins=channels, host=host, port=port, ssl=ssl,
includes=['irc3.plugins.core'])
self.bot.run()
def format(self, record):
message = self.colorize(record)
return message
def emit(self, record):
try:
msg = self.format(record)
msg = self._encode(msg)
for chan in self.channels:
self.bot.privmsg(chan, msg)
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
self.handleError(record)
Basicly bot.run() is blocking the process. T know it's a feature not a bug. I look into stack overflow, and find run asyncio main loop in thread (bahh) and use executor. I tried both and can't get one working. Moreover I'm not sure asyncio call are thread safe.
Normally I dont request help but if you find some time to give me advice, I would make a plugin with it and push it.
As we briefly discussed on IRC, passing SIGINT or calling self.bot.SIGINT()
exits irc3 uncleanly.
ERROR asyncio Task was destroyed but it is pending!
task: >Task pending coro=>process_queue() running at /home/brotherBox/venv/lib/python3.4/site-packages/irc3-0.9.3.dev0-py3.4.egg/irc3/init.py:209> wait_for=>Future finished result=None>>
Exception ignored in: >bound method _UnixSelectorEventLoop.del of >_UnixSelectorEventLoop running=False closed=True debug=False>>
Traceback (most recent call last):
File "/home/brotherBox/venv/lib/python3.4/site-packages/asyncio-3.4.4-py3.4.egg/asyncio/base_events.py", line 431, in del
File "/home/brotherBox/venv/lib/python3.4/site-packages/asyncio-3.4.4-py3.4.egg/asyncio/unix_events.py", line 58, in close
File "/home/brotherBox/venv/lib/python3.4/site-packages/asyncio-3.4.4-py3.4.egg/asyncio/unix_events.py", line 139, in remove_signal_handler
TypeError: signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object
I run irc3 in a virtual env, running with the following packages:
asyncio==3.4.4
beautifulsoup4==4.4.1
docopt==0.6.2
irc3==0.9.3.dev0
requests==2.10.0
venusian==1.0
I run Python 3.4 on Ubuntu 14.04.
Thank you for your consideration.
I am doing a multi-room message plugin using the following code:
from irc3.plugins.command import command
from irc3.compat import asyncio
import irc3
@irc3.plugin
class CabotPlugin(object):
def __init__(self, bot):
self.bot = bot
@irc3.event(irc3.rfc.JOIN)
def connect(self, mask, channel, **kw):
print channel
print self.bot.config.room_count
# log only when the bot connect and disconect right after
if mask.nick == self.bot.nick:
print self.bot.config.message
self.bot.privmsg(channel, self.bot.config.message)
self.disconnect()
def disconnect(self):
self.bot.quit()
self.bot.config.room_count -= 1
if self.bot.config.room_count <= 0:
self.bot.config.end_callback.set_result('OK')
def bootstrapIrc3():
loop = asyncio.get_event_loop()
end_callback = asyncio.Future()
rooms = ['Room1_test', 'Room2_test']
config = dict(
host='sinisalo.freenode.net',
port=6667,
nick='the_bot_name',
autojoins=rooms,
room_count=len(rooms),
message='the message'
)
# save the end method to be called after posting the message
config['end_callback'] = end_callback
config['includes'] = [__name__]
# Create the bot and run it once
sender = irc3.IrcBot.from_config(config)
sender.run(forever=False)
# set the asyncio resolve Future
loop.run_until_complete(end_callback)
bootstrapIrc3()
As you can see, I create a bot that connects to two rooms and react on the JOIN
event:
If the current joined user is the bot, send a message.
Then call the disconnect method, that decrease the room_count
value to really disconnect only after all messages have been posted.
Output:
INFO irc3.the_bot_name Trying to join #Room1_test
INFO irc3.the_bot_name Trying to join #Room2_test
#Room1_test
2
the message
#Room2_test
1
the message
But the message never appears on the second room.
Do you know what the trouble can be ?
Thanks !
For context, I'm working on porting a dicebot to use this library. Triggering this issue is that I'm attempting to create a command with a simple +/- numerical modifier. (example: !apoc -2
, !apoc +1
)
I've tracked this down to how IRC3 uses Docopt for command parsing, & how Docopt has an issue with using '-' to signal option commands. (docopt/docopt#158)
In the Docopt issue linked, there's a pair of workarounds provided which could work here:
Adding support for the options_first=True
flag (added in Docopt 0.6.0), and adding the ability to modify an argument string as it comes in to prefix--
.
I'm currently looking into how feasible this would be in the existing codebase, but at the least, adding the ability to flip the options_first
flag would be an improvement.
Stuff like the Makefile depend on scripts in a folder called bin/
. However, this folder is not part of the repository. Could it be added?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.