|
1
|
|
|
# coding=utf-8 |
|
2
|
|
|
""" |
|
3
|
|
|
py.py - Sopel Python Eval Module |
|
4
|
|
|
Copyright 2008, Sean B. Palmer, inamidst.com |
|
5
|
|
|
Licensed under the Eiffel Forum License 2. |
|
6
|
|
|
|
|
7
|
|
|
https://sopel.chat |
|
8
|
|
|
""" |
|
9
|
|
|
from __future__ import unicode_literals, absolute_import, print_function, division |
|
10
|
|
|
|
|
11
|
|
|
import sys |
|
12
|
|
|
|
|
13
|
|
|
from requests import get |
|
14
|
|
|
|
|
15
|
|
|
from sopel.config.types import StaticSection, ValidatedAttribute |
|
16
|
|
|
from sopel.module import commands, example |
|
17
|
|
|
|
|
18
|
|
|
if sys.version_info.major < 3: |
|
19
|
|
|
from urllib import quote as _quote |
|
20
|
|
|
|
|
21
|
|
|
def quote(s): |
|
22
|
|
|
return _quote(s.encode('utf-8')).decode('utf-8') |
|
23
|
|
|
else: |
|
24
|
|
|
from urllib.parse import quote |
|
25
|
|
|
|
|
26
|
|
|
|
|
27
|
|
|
class PySection(StaticSection): |
|
28
|
|
|
oblique_instance = ValidatedAttribute('oblique_instance', |
|
29
|
|
|
default='https://oblique.sopel.chat/') |
|
30
|
|
|
"""The Oblique instance to use when evaluating Python expressions""" |
|
31
|
|
|
|
|
32
|
|
|
|
|
33
|
|
|
def configure(config): |
|
34
|
|
|
""" |
|
35
|
|
|
| name | example | purpose | |
|
36
|
|
|
| ---- | ------- | ------- | |
|
37
|
|
|
| oblique_instance | https://oblique.sopel.chat/ | The Oblique instance to use when evaluating Python expressions (see <https://github.com/sopel-irc/oblique>) | |
|
38
|
|
|
""" |
|
39
|
|
|
config.define_section('py', PySection) |
|
40
|
|
|
config.py.configure_setting( |
|
41
|
|
|
'oblique_instance', |
|
42
|
|
|
'Enter the base URL of a custom Oblique instance (optional): ' |
|
43
|
|
|
) |
|
44
|
|
|
|
|
45
|
|
|
|
|
46
|
|
|
def setup(bot): |
|
47
|
|
|
bot.config.define_section('py', PySection) |
|
48
|
|
|
|
|
49
|
|
|
if not any( |
|
50
|
|
|
bot.config.py.oblique_instance.startswith(prot) |
|
51
|
|
|
for prot in ['http://', 'https://'] |
|
52
|
|
|
): |
|
53
|
|
|
raise ValueError('Oblique instance URL must start with a protocol.') |
|
54
|
|
|
|
|
55
|
|
|
if not bot.config.py.oblique_instance.endswith('/'): |
|
56
|
|
|
bot.config.py.oblique_instance += '/' |
|
57
|
|
|
|
|
58
|
|
|
|
|
59
|
|
|
@commands('py') |
|
60
|
|
|
@example('.py len([1,2,3])', '3', online=True) |
|
61
|
|
|
def py(bot, trigger): |
|
62
|
|
|
"""Evaluate a Python expression.""" |
|
63
|
|
|
if not trigger.group(2): |
|
64
|
|
|
return bot.reply('I need an expression to evaluate.') |
|
65
|
|
|
|
|
66
|
|
|
query = trigger.group(2) |
|
67
|
|
|
uri = bot.config.py.oblique_instance + 'py/' |
|
68
|
|
|
answer = get(uri + quote(query)).content.decode('utf-8') |
|
69
|
|
|
if answer: |
|
70
|
|
|
# bot.say can potentially lead to 3rd party commands triggering. |
|
71
|
|
|
bot.reply(answer) |
|
72
|
|
|
else: |
|
73
|
|
|
bot.reply('Sorry, no result.') |
|
74
|
|
|
|
|
75
|
|
|
|
|
76
|
|
|
if __name__ == "__main__": |
|
77
|
|
|
from sopel.test_tools import run_example_tests |
|
78
|
|
|
run_example_tests(__file__) |
|
79
|
|
|
|