Add eval/exec to RPC
This commit is contained in:
parent
c2e2199b02
commit
5a511944bd
|
@ -8,3 +8,4 @@ build
|
|||
pyircbot.egg-info
|
||||
dev
|
||||
docs/builder/build.sh
|
||||
examples/config.test.json
|
||||
|
|
|
@ -47,7 +47,7 @@ We can retrieve an arbitrary property from a module:
|
|||
[True, {'apikey': 'deadbeefcafe', 'defaultUnit': 'f'}]
|
||||
>>>
|
||||
|
||||
Or run a method in a module, passing args:
|
||||
Run a method in a module, passing args:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -55,6 +55,71 @@ Or run a method in a module, passing args:
|
|||
[True, {'definition': "Loyal, unlike its predecessor", 'word': 'rhobot2', 'by': 'xMopxShell'}]
|
||||
>>>
|
||||
|
||||
Or simply pass a string to eval() or exec() to do anything. In this case,
|
||||
retrieving a full stack trace of the bot, which is useful during module
|
||||
development:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> print( rpc.eval("self.bot.irc.trace()")[1] )
|
||||
|
||||
*** STACKTRACE - START ***
|
||||
|
||||
# ThreadID: 140289192748800
|
||||
File: "/usr/lib/python3.4/threading.py", line 888, in _bootstrap
|
||||
self._bootstrap_inner()
|
||||
File: "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
|
||||
self.run()
|
||||
File: "/usr/lib/python3.4/threading.py", line 1184, in run
|
||||
self.finished.wait(self.interval)
|
||||
File: "/usr/lib/python3.4/threading.py", line 552, in wait
|
||||
signaled = self._cond.wait(timeout)
|
||||
File: "/usr/lib/python3.4/threading.py", line 293, in wait
|
||||
gotit = waiter.acquire(True, timeout)
|
||||
|
||||
# ThreadID: 140289297204992
|
||||
File: "/usr/lib/python3.4/threading.py", line 888, in _bootstrap
|
||||
self._bootstrap_inner()
|
||||
File: "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
|
||||
self.run()
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/rpc.py", line 51, in run
|
||||
self.server.serve()
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/jsonrpc.py", line 1110, in serve
|
||||
self.__transport.serve( self.handle, n )
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/jsonrpc.py", line 851, in serve
|
||||
result = handler(data)
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/jsonrpc.py", line 1086, in handle
|
||||
result = self.funcs[method]( *params )
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/rpc.py", line 167, in eval
|
||||
return (True, eval(code))
|
||||
File: "<string>", line 1, in <module>
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/irccore.py", line 288, in trace
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
|
||||
# ThreadID: 140289333405504
|
||||
File: "/usr/local/bin/pyircbot", line 5, in <module>
|
||||
pkg_resources.run_script('pyircbot==4.0.0-r02', 'pyircbot')
|
||||
File: "/usr/lib/python3/dist-packages/pkg_resources.py", line 528, in run_script
|
||||
self.require(requires)[0].run_script(script_name, ns)
|
||||
File: "/usr/lib/python3/dist-packages/pkg_resources.py", line 1394, in run_script
|
||||
execfile(script_filename, namespace, namespace)
|
||||
File: "/usr/lib/python3/dist-packages/pkg_resources.py", line 55, in execfile
|
||||
exec(compile(open(fn).read(), fn, 'exec'), globs, locs)
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/EGG-INFO/scripts/pyircbot", line 32, in <module>
|
||||
bot.loop()
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/pyircbot.py", line 68, in loop
|
||||
self.irc.loop()
|
||||
File: "/usr/local/lib/python3.4/dist-packages/pyircbot-4.0.0_r02-py3.4.egg/pyircbot/irccore.py", line 56, in loop
|
||||
asyncore.loop(map=self.asynmap)
|
||||
File: "/usr/lib/python3.4/asyncore.py", line 208, in loop
|
||||
poll_fun(timeout, map)
|
||||
File: "/usr/lib/python3.4/asyncore.py", line 145, in poll
|
||||
r, w, e = select.select(r, w, e, timeout)
|
||||
|
||||
*** STACKTRACE - END ***
|
||||
|
||||
>>>
|
||||
|
||||
Careful, you can probably crash the bot by tweaking the wrong things. Only
|
||||
basic types can be passed over the RPC connection. Trying to access anything
|
||||
extra results in an error:
|
||||
|
|
|
@ -11,6 +11,7 @@ import asynchat
|
|||
import asyncore
|
||||
import logging
|
||||
import traceback
|
||||
import sys
|
||||
from socket import SHUT_RDWR
|
||||
|
||||
try:
|
||||
|
@ -279,7 +280,19 @@ class IRCCore(asynchat.async_chat):
|
|||
@staticmethod
|
||||
def trace():
|
||||
"""Return the stack trace of the bot as a string"""
|
||||
return traceback.format_exc()
|
||||
result = ""
|
||||
result += "\n*** STACKTRACE - START ***\n"
|
||||
code = []
|
||||
for threadId, stack in sys._current_frames().items():
|
||||
code.append("\n# ThreadID: %s" % threadId)
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
|
||||
if line:
|
||||
code.append(" %s" % (line.strip()))
|
||||
for line in code:
|
||||
result += line + "\n"
|
||||
result += "\n*** STACKTRACE - END ***\n"
|
||||
return result
|
||||
|
||||
" Data Methods "
|
||||
def get_nick(self):
|
||||
|
|
|
@ -41,6 +41,8 @@ class BotRPC(Thread):
|
|||
self.server.register_function( self.setPluginVar )
|
||||
self.server.register_function( self.getPluginVar )
|
||||
self.server.register_function( self.quit )
|
||||
self.server.register_function( self.eval )
|
||||
self.server.register_function( self.exec )
|
||||
|
||||
self.start()
|
||||
|
||||
|
@ -157,6 +159,20 @@ class BotRPC(Thread):
|
|||
setattr(plugin, moduleVarName, value)
|
||||
return (True, "Var set")
|
||||
|
||||
def eval(self, code):
|
||||
"""Execute arbitrary python code on the bot
|
||||
|
||||
:param code: Python code to pass to eval
|
||||
:type code: str"""
|
||||
return (True, eval(code))
|
||||
|
||||
def exec(self, code):
|
||||
"""Execute arbitrary python code on the bot
|
||||
|
||||
:param code: Python code to pass to exec
|
||||
:type code: str"""
|
||||
return (True, exec(code))
|
||||
|
||||
def quit(self, message):
|
||||
"""Tell the bot to quit IRC and exit
|
||||
|
||||
|
|
Loading…
Reference in New Issue