forked from DesertBot/DesertBot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Chain.py
89 lines (73 loc) · 3.64 KB
/
Chain.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"""
Created on May 03, 2014
@author: StarlitGhost
"""
from twisted.plugin import IPlugin
from desertbot.moduleinterface import IModule
from desertbot.modules.commandinterface import BotCommand
from zope.interface import implementer
import re
from desertbot.message import IRCMessage
from desertbot.response import IRCResponse, ResponseType
from desertbot.utils import string
@implementer(IPlugin, IModule)
class Chain(BotCommand):
def triggers(self):
return ['chain']
def help(self, query):
return ['chain <command 1> | <command 2> [| <command n>] -'
' chains multiple commands together,'
' feeding the output of each command into the next',
'syntax: command1 params | command2 $output | command3 $var',
'$output is the output text of the previous command in the chain',
'$var is any extra var that may have been added'
' to the message by commands earlier in the chain']
def execute(self, message: IRCMessage):
# split on unescaped |
chain = re.split(r'(?<!\\)\|', message.parameters)
response = None
extraVars = {}
for link in chain:
link = link.strip()
link = re.sub(r'\\\|', r'|', link)
if response is not None:
if hasattr(response, '__iter__'):
return IRCResponse(ResponseType.Say,
"Chain Error: segment before '{}' returned a list"
.format(link),
message.replyTo)
# replace $output with output of previous command
link = link.replace('$output', response.response)
extraVars.update(response.ExtraVars)
for var, value in extraVars.items():
link = re.sub(r'\$\b{}\b'.format(re.escape(var)), '{}'.format(value), link)
else:
# replace $output with empty string if previous command had no output
# (or this is the first command in the chain,
# but for some reason has $output as a param)
link = link.replace('$output', '')
link = link.replace('$sender', message.user.nick)
if message.channel is not None:
link = link.replace('$channel', message.channel.name)
else:
link = link.replace('$channel', message.user.nick)
# build a new message out of this 'link' in the chain
inputMessage = IRCMessage(message.type, message.user, message.channel,
self.bot.commandChar + link.lstrip(),
self.bot)
# might be used at some point to tell commands they're being called from Chain
inputMessage.chained = True
if inputMessage.command.lower() in self.bot.moduleHandler.mappedTriggers:
command = self.bot.moduleHandler.mappedTriggers[inputMessage.command.lower()]
response = command.execute(inputMessage)
else:
return IRCResponse(ResponseType.Say,
"{!r} is not a recognized command trigger"
.format(inputMessage.command),
message.replyTo)
if response.response is not None:
# limit response length (chains can get pretty large)
response.response = list(string.splitUTF8(response.response.encode('utf-8'), 700))[0]
response.response = str(response.response, 'utf-8')
return response
chain = Chain()