rmmh / skybot Goto Github PK
View Code? Open in Web Editor NEWPython IRC bot
Home Page: https://github.com/rmmh/skybot/wiki
License: The Unlicense
Python IRC bot
Home Page: https://github.com/rmmh/skybot/wiki
License: The Unlicense
When using a browser/website API key, I get error 403 forbidden.
When using a server API key, I get error 403 forbidden.
Unhandled exception in thread started by <function run at 0x6f8699a9baa0>
Traceback (most recent call last):
File "core/main.py", line 78, in run
out = func(input.inp, **kw)
File "plugins/youtube.py", line 76, in youtube
j = http.get_json(search_api_url, **params)
File "plugins/util/http.py", line 42, in get_json
return json.loads(get(*args, **kwargs))
File "plugins/util/http.py", line 30, in get
return open(*args, **kwargs).read()
File "plugins/util/http.py", line 84, in open
return opener.open(request)
File "/usr/lib/python2.7/urllib2.py", line 410, in open
response = meth(req, response)
File "/usr/lib/python2.7/urllib2.py", line 523, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python2.7/urllib2.py", line 448, in error
return self._call_chain(*args)
File "/usr/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 531, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 403: Forbidden
How exactly do you set up the google plugin?
I'm getting my api keys from here:
https://console.developers.google.com/apis/credentials
Thanks :)
I recently got interested in IRC bots. I see them as a
powerful tool, good for startups that heavily rely on
remote workers: Async communication, SCM and CI, integration,
automated processes, etc.
Not missing anything is also important to me, I would
like to improve logs readability, and ultimately come up
with something like these logs: https://botbot.me/
HTML generation, a flask app?
Does it sound like something useful?, any advice?
Hello, I would like to ask if you could make something like letting the bot VERSION, TIME, PING etc other people, such thing as:
conn.cmd('PRIVMSG',[inp,'\x01VERSION\x01'])
say(parsed.reply())
where of course inp is the nick that's VERSION, PING, TIME you would like to get. I was looking for something similar, but couldn't find. What will help you doing it is https://github.com/PiPeep/python-ircutils/blob/master/ircutils/ctcp.py.
Regards.
How do I disable all of the default plugins?
I'm using the new GitHub for Windows client and if you run the bot it'll throw exceptions when trying to respond to VERSION requests. The problem is that it can't find Git.
Unhandled exception in thread started by <function run at 0x00000000024ED7B8>
Traceback (most recent call last):
File "core\main.py", line 66, in run
out = func(input.inp, **kw)
File "plugins\misc.py", line 61, in onjoin
ident, rev = get_version()
File "plugins\misc.py", line 12, in get_version
p = subprocess.Popen(['git', 'log', '--oneline'], stdout=subprocess.PIPE)
File "C:\Python27\lib\subprocess.py", line 679, in __init__
errread, errwrite)
File "C:\Python27\lib\subprocess.py", line 893, in _execute_child
startupinfo)
WindowsError: [Error 2] The system cannot find the file specified
might require some sort of way to register hooks on output (like sieve on input?)
would be helpful for identifying auto-kline phrases that knock bots offline
The latest change throws an unhandled exception when the plugin is called:
Unhandled exception in thread started by <function run at 0x8c4eb1c>
Traceback (most recent call last):
File "core/main.py", line 68, in run
out = func(input.inp)
File "plugins/youtube.py", line 62, in youtube_url
return get_video_description(match.group(1))
File "plugins/youtube.py", line 48, in get_video_description
j['viewCount'], 1).decode(locale.getlocale()[1])
TypeError: decode() argument 1 must be string, not None
The idea is being able to write plugins that process the input before they are parsed into commands or run through the sieves, as well as being able to modify the output before it's sent to the server.
I've written some code that provides basic (although working) support for input/output hooks. Before I go any further, I wanted some feedback as to the utility of it.
You can look at the compare view here: avidal/skybot@master...middleware
One example for an input hook would be moving the acl and bot ignoring stuff from main.py into an input hook. You could also add rate limiting by nick as an input hook easily, as well as write a plugin for flood protection as an output hook.
The dotnetpad site can take 20s or more to spin up if it's cold. Please increase the timeout for .cs and .fs to ~30 seconds.
I like the skybot framework a lot. I'm not sure how the author feels about forks & derivatives though. Is there any chance at getting a license of sort mentioned?
.twitter somebody is a retweet and the original tweet is long, the text printed is "RT @whomever blah blah blah blah blah blah bl ..."
It should just print the entire tweet.
Wolfram-Alpha does not appear to be working. It returns no results on all queries, no matter how well they work on the wolframalpha site.
if any of you has made a plugin/factoid that allows users to input a http:// link or an IP/DNS hostname make sure you check what addresses they're actually sending packets to if you're sending packets directly from the bot and not an external service (eg. google).
if you are not it is possible for an attacker to port scan your LAN via the bot using the plugin/factoid.
eg.
i recommend that a censor for the /plugins/util/http.py plugin to disallow these netmasked addresses:
192.168.0.0/16
172.16.0.0/16 to 172.31.0.0/16
10.0.0.0/8
127.0.0.0/8
169.254.0.0/16
as any of these IP addresses are LAN addresses and dont map to the internet, they shouldnt be queried at all as they can leak LAN information on to the internet.
this will not affect you if you dont have a LAN connection on the running host of the bot. (eg. a VPS or similar that only has a direct internet connection and cannot in anyway contact these addresses).
Steps to Reproduce
cd /opt virtualenv skybot
source /opt/skybot/bin/activate
pip install -r /opt/skybot/skybot/requirements.txt
python /opt/skybot/skybot/bot.py
Every time I run this and the explain.py plugin is in the plugins directory, I get this error before loading the plugins:
Traceback (most recent call last):
File "core/reload.py", line 89, in reload
eval(code, namespace)
File "plugins/explain.py", line 2, in <module>
from pycparser.cdecl import explain_c_declaration
ImportError: No module named cdecl
Does anyone else get this error? I looked at my site-packages folder in /opt/skybot/lib/python2.7/site-packages/pycparser and there is no examples directory or cdecl.py file. If this is the case for current pip installs, perhaps explain.py should be removed or refactored to not use this example code?
.twitter somebody 2
will return "error: user does not have that many tweets" if that user's second tweet is a retweet. It should return the usual "RT @whomever Blah blah blah first world problems"
There should be a way to add/remove plugins without forking skybot. Most people don't need to modify the core, but do want to customize the commands.
Git submodules + host them in gists?
The seen table in the database stops updating after a few months, seemingly spontaneously. I've had 3 long term skybots (first two were not mine, the current one is) where the .seen command will stop working after somewhere around a year. I looked at the seen table in my current database and it stopped updating 2 months ago.
Everything else using that database seems to be working as usual.
If you do a request that results in a number that is separated with a space skybot will choke. For example, request 1*10000
which will return 10 000
:
16:02:35 #ijustam <ijustam> .calc 1*10000
Unhandled exception in thread started by <function run at 0x02C17C30>
Traceback (most recent call last):
File "core\main.py", line 80, in run
out = func(input.inp)
File "plugins\gcalc.py", line 10, in calc
m = h.xpath('//h2[@class="r"]/text()')
File "src/lxml/lxml.etree.pyx", line 1587, in lxml.etree._Element.xpath (src\lxml\lxml.etree.c:61854)
File "src/lxml/xpath.pxi", line 307, in lxml.etree.XPathElementEvaluator.__call__ (src\lxml\lxml.etree.c:178516)
File "src/lxml/xpath.pxi", line 230, in lxml.etree._XPathEvaluatorBase._handle_result (src\lxml\lxml.etree.c:177452)
File "src/lxml/extensions.pxi", line 623, in lxml.etree._unwrapXPathObject (src\lxml\lxml.etree.c:171189)
File "src/lxml/extensions.pxi", line 657, in lxml.etree._createNodeSetResult (src\lxml\lxml.etree.c:171659)
File "src/lxml/extensions.pxi", line 678, in lxml.etree._unpackNodeSetEntry (src\lxml\lxml.etree.c:171886)
File "src/lxml/extensions.pxi", line 804, in lxml.etree._buildElementStringResult (src\lxml\lxml.etree.c:173487)
File "src/lxml/apihelpers.pxi", line 1417, in lxml.etree.funicode (src\lxml\lxml.etree.c:32150)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa0 in position 6: invalid start byte
The HTML result:
<h2 class="r" style="display:inline;font-size:138%">1 * 10 000 = 10 000</h2>
I wanted to open an issue to discuss what concerns there are - if any - on upgrading to Python 3 from 2.7. At the very least, I'd be interested in trying to get python 3 compatible code up with future
but there are no Python2-only dependencies, so I'm using Python 3 live.
I've already done a quick pass for the fork of skybot that I keep up, but it's always nice to push things back upstream. ( imnotjames@960e8b6 )
I hit a few problems:
tox
to check both 2 and 3 compatibility. I'm manually running two bots right now with both 2 and 3.Would there be interest in merging these changes upstream?
Skybot doesn't refresh channel states when the configuration when has changed. If a channel or server is added to the list, SkyBot must be completely restarted to finalize the changes. This should be automatic at runtime.
I'm having problems figuring out how best to address the issue of Wunderground returning data that triggers a UnicodeDecodeError. The swedish town of 'umea' seems to be a good test case.
".we umea" triggers the following traceback:
Unhandled exception in thread started by <function run at 0x7f56a5a21b90>
Traceback (most recent call last):
File "core/main.py", line 78, in run
out = func(input.inp, **kw)
File "plugins/weather.py", line 71, in weather
parsed_json = http.get_json(url)
File "plugins/util/http.py", line 42, in get_json
return json.loads(get(*args, **kwargs))
File "/usr/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
obj, end = self.scan_once(s, idx)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe5 in position 3: unexpected end of data
Unicode still confuses me and makes me question my purpose in the universe, so I don't know whether this is an issue with the JSON that wunderground returns, or whether the get_json function just doesn't like dealing with non-ASCII. I wouldn't mind trying to fix it myself and putting in a pull request, but I'm really unsure about how to edit rmmh's existing url-parsing functions without breaking everything. Anyone got a suggestion where I should start?
It might be a good idea to have a hash file to hold all of the API keys for the various plugins so that they are less easily stolen.
I'm attempting to write plugins and finding the documentation extremely lacking and the internal code that actually runs the plugins somewhat confusing. at the moment I'm specifically trying to find a list of available named arguments to each of the hooks.
i have made some new plugins and made some updates to a fork of your project.
i did make alot of changes maybe you want to use afew?
if you want a look go here https://github.com/Red-M/frogbot
Ideally, .lastfm whomever
would return "Whomever is currently listening to Some Dumb Crap by Some Idiots Nobody Cares About."
Currently it returns nothing.
For some reason when i execute the start command the bot connects to the IRC network, but does not join 2channels i added on Config.
Note that i can use commands via PM to Bot, but i want the bot on my channel.
Regards, Saloun.
Hi Scaevolus, I had an issue with the way the weather plugin wrote back to the database, in that it looked to be only writing back 'loc' - this looked to cause an issue at least doing weather lookups for UK / Europe in that without having the 'state' information included caused wunderground to always query which 'loc' you were looking for.
I've tested by writing back 'inp' instead of 'loc' to the database and so far doesn't appear to have broken anything but Python is fairly new to me and I dunno if this would cause issues that I don't know about.
So for example I changed
if inp and not dontsave:
db.execute("insert or replace into weather(nick, loc) values (?,?)",
(nick.lower(), loc))
db.commit()
to
if inp and not dontsave:
db.execute("insert or replace into weather(nick, loc) values (?,?)",
(nick.lower(), inp))
db.commit()
Example of the problem before fixing:
.we oxford, uk
Oxford, United Kingdom: Clear, 12.9C, Humidity: 87%, Wind: From the ENE at 0.0mph / 0.0km/h
.we
Could not find weather for . Possible matches include: Oxford AL USA, Oxford AR USA, Oxford CT USA, Oxford FL USA, Oxford GA USA, Oxford ID USA
(It's only stored 'oxford' in the db rather than 'oxford, uk'
Sorry if this looks like ass, I also don't know markdown very well either.
Any time a youtube search is done it returns https://youtube.com/devicesupport
pwf suggested upgrading to youtube api v3.
http://youtube-eng.blogspot.com/2015/04/bye-bye-youtube-data-api-v2.html
I'm curious if anyone has a good method of PMing everyone in a specific channel that the bot has joined. Preferably not all at once.
If not, just PMing users in general.
There should be support for per-channel/per-server whitelisting. Currently ACLs are only allow-except/deny-except for specifically named functions, which isn't so useful.
<Ipsum> .tag del Ipsum racist
But he really is a racist.
I have had no luck finding the proper format for the key-value pairs in config that Skybot is expecting to run twitter.py. Could you give us a clue? I do have the four keys needed according to twitter. Perhaps a config file in the future with some of these keys present but no values?
Add support for multiple bots sharing the same brain, like eggdrop has
Commit 4c970f6 broke custom bot prefixes because it just does a literal match of the config string in prefixes instead of the old behaviour introduced in 2b44d0a where bots can have a list of possible custom prefixes because some people like one over the other. So instead of a config prefix string of "!." allowing users to choose !command or .command, it forces users to use !.command instead.
Am I the only one who thinks this is an issue?
$ python2 bot.py
Loading plugins
Traceback (most recent call last):
File "bot.py", line 58, in
main()
File "bot.py", line 29, in main
reload(init=True)
TypeError: reload() takes no keyword arguments
At present ACTION, as a subset of PRIVMSG, is not possible to hook into without post-event regex to determine whether or not a /me actually occurred.
I'm opening this to go over a feature I'm working on that requires a bit of a change on the internals of skybot, so I thought it'd be best to open an RFC issue before I go and start throwing the pull requests out there.
I have been wanting to pull in plugins from external modules. Why? Because there are plugins that I have that I'd like to share - plugins which are useful (or useless but funny) but which I don't think fit in with the main skybot repository. They might require external modules (like a few reddit plugins I've made or the amazon plugin) or are just less useful for other folks (a plugin for an in-joke with the IRC channels the bot runs on).
I'm also be interested in pulling skybot as a dependency of a separate application so we can extend on top of it without having to copy all the files and adding in custom plugins with a simple install (eg teampeggle/ppp-helpdesk
). Right now it's painful because I have to manually sync all the changes.
It is possible to do this! I've been experimenting with a few things to do this, which mostly entails cleaning up the codebase:
Ideally, the configuration for specifying plugins would default to all plugins under skybot.plugins.*
(backwards compatibility), and if specified would then start pulling in plugins to use, setting up the reloader, etc.
After these are complete, any module within the python path can be used as a plugin! EG, if you were to pip install skybot-plugin-awesome
, you could pull it in as a fantastic new plugin without copying it to the plugins directory!
Thoughts, concerns, etc?
With the new dev, we have new code in the front end, which isn't parsed correctly. Actually I already fixed it but didn't really want to fork/pull request over a one liner. Diff follows:
diff --git a/plugins/somethingawful.py b/plugins/somethingawful.py
index 84bda1f..13dd000 100644
--- a/plugins/somethingawful.py
+++ b/plugins/somethingawful.py
@@ -30,7 +30,7 @@ def forum_link(inp, bot=None):
thread = http.get_html(showthread, threadid=inp.group(1), perpage='1',
cookies=True)
if not breadcrumbs:
return
Traceback (most recent call last):
File "core/reload.py", line 87, in reload
code = compile(open(filename, 'U').read(), filename, 'exec')
File "plugins/quote.py", line 102
def quotedelete:
^
SyntaxError: invalid syntax`
A few days ago .calc has stopped working. It would be nice to get a fix on this one
Twitter shutdown the v1 API, so all requests now return HTTP 410
I'd like to make a plugin that scrapes an RSS feed every 15-30 minutes and stores any new news items in a database. I'd like any new news items to be sent to the channel, but I can't seem to find any way to send a message without being prompted (by a command). I tried poking around with the say() and message() methods in the Input class, but couldn't get anywhere with those. Does anyone have any ideas?
You can do this
.python __import__('sys').setrecursionlimit(1)
which results in a semi-permanent disable of scybot's python environment.
This is somewhat useful when people start botspamming with .python
, but should still be fixed.
I know that Skybot has a hook for 'events', but what would about periodic scheduling or task scheduling?
Say you wanted something to run every x amount of hours or at a specified time - are there any solutions implemented to do this already or would a new hook have to be added with this functionality?
When I type .du luka 3
, it gave me:
Ich töte deine eltern.
It should be Ich töte deine eltern.
, right?
Hint: There is a function HTMLParser.HTMLParser().unescape()
that can unescape it.
When a tweet such as: https://twitter.com/awfuljams/status/667601577662787584 has a line break in it, the Twitter plugin will simply breakout at the newline, leaving an incomplete tweet.
Instead of using open
, and the util.http
module for handling HTTP requests, would there be interest in converting this over to using the requests library? It means a more generalized library with more control over the workflow.
If so, we could utilize requests-mock to create mocks more easily for tests for the plugins.
A branch using requests
in the util.http
can be found here https://github.com/imnotjames/skybot/tree/feature/use-requests-for-http but I think there's a benefit in handling everything with requests
directly.
Thoughts, concerns, etc?
hello ,
when i run skybot ,a error occured.it says "socket.timeout: timed out
"
and the all command:
Loading plugins
plugin listing:
command:
plugins/bf.py:bf:14 bf
plugins/bigassmessage.py:bam:4 bam
plugins/bitcoin.py:bitcoin:4 bitcoin
plugins/choose.py:choose:7 choose
plugins/dice.py:dice:35 dice, roll
plugins/dictionary.py:define:27 dictionary, define
plugins/dictionary.py:etymology:87 etymology, e
plugins/dictionary.py:urban:6 urban, u
plugins/dotnetpad.py:cs:53 cs
plugins/dotnetpad.py:fs:46 fs
plugins/down.py:down:6 down
plugins/drama.py:drama:10 drama, ed
plugins/explain.py:explain:5 explain
plugins/gcalc.py:calc:4 calc
plugins/google.py:gis:12 gis
plugins/google.py:google:26 google, g
plugins/hash.py:hash:16 hash
plugins/hash.py:md5:6 md5
plugins/hash.py:sha1:11 sha1
plugins/help.py:help:6 help
plugins/imdb.py:imdb:6 imdb
plugins/lastfm.py:lastfm:10 lastfm
plugins/mem.py:mem:7 mem
plugins/metacritic.py:metacritic:9 mc
plugins/mtg.py:mtg:6 mtg
plugins/oblique.py:oblique:31 oblique, o
plugins/pre.py:predb:6 predb
plugins/profile.py:profile:6 profile
plugins/pyexec.py:python:9 python
plugins/quote.py:quote:38 quote, q
plugins/religion.py:bible:4 bible, god
plugins/religion.py:koran:26 allah, koran
plugins/remember.py:forget:64 forget, f
plugins/remember.py:remember:23 remember, r
plugins/rottentomatoes.py:rottentomatoes:8 rottentomatoes, rt
plugins/seen.py:seen:25 seen
plugins/snopes.py:snopes:9 snopes
plugins/stock.py:stock:6 stock
plugins/suggest.py:suggest:8 suggest
plugins/tag.py:munge:8 munge
plugins/tag.py:tag:79 tag
plugins/tell.py:showtells:50 showtells
plugins/tell.py:tell:72 tell
plugins/tf.py:tf:9 hats, tf
plugins/translate.py:babel:108 babel
plugins/translate.py:babelext:121 babelext
plugins/translate.py:translate:66 translate
plugins/tvdb.py:tv_last:131 tv_last, tv_prev
plugins/tvdb.py:tv_next:85 tv_next, tv
plugins/twitter.py:twitter:28 twitter
plugins/validate.py:validate:10 validate
plugins/weather.py:weather:6 weather
plugins/wikipedia.py:wiki:15 wiki, w
plugins/wolframalpha.py:wolframalpha:6 wolframalpha, wa
plugins/yahooanswers.py:answer:4 answer
plugins/youtube.py:youtube:65 youtube, y
event:
plugins/misc.py:rejoin:27 KICK
plugins/misc.py:onjoin:40 004
plugins/misc.py:invite:35 INVITE
plugins/log.py:log:84 *
plugins/tell.py:tellinput:25 PRIVMSG
plugins/seen.py:seeninput:15 PRIVMSG
regex:
plugins/misc.py:version:64 ^\x01VERSION\x01$
plugins/youtube.py:youtube_url:60 (?:youtube.?(?:v=|/v/)|youtu.be/|yooouuutuuube.?id=)([-_a-z0-9]+)
plugins/somethingawful.py:forum_link:22 (?i)forums.somethingawful.com/\S+threadid=(\d+)
plugins/vimeo.py:vimeo_url:4 vimeo.com/([0-9]+)
plugins/tinyurl.py:tinyurl:4 (?i)http://(?:www.)?tinyurl.com/([A-Za-z0-9-]+)
plugins/remember.py:question:84 ^? ?(.+)
plugins/urlhistory.py:urlinput:66 ([a-zA-Z]+://|www.)[^ ]+
sieve:
plugins/sieve.py:sieve_suite:6
Connecting to IRC
Running main loop
^F
^F
Unhandled exception in thread started by <bound method crlf_tcp.run of <main.crlf_tcp object at 0x196fd50>>
Traceback (most recent call last):
File "core/irc.py", line 45, in run
self.socket.connect((self.host, self.port))
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.timeout: timed out
what should i do?
thanks!
In the documentation it says:
channel -- string, the channel the message was sent on. Equal to nick if it's a private message.
But, from what I've found, the shared argument is actually "chan" to return the channel name.
This is with the regex hook, but I'm not sure if it's system wide?
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.