root/imbot/Commands.py

Revision 107, 4.7 kB (checked in by pantley2, 3 years ago)

IMBOT: various fixes (listed below)

Ask.py: ask() takes a tuple'd sentence now instead of a string sentence

Cleaner.py: added two functions to check for garbage input

Commands.py: commands are now only accepted by Darin, Nikhil, and Felix (to prevent EOH users from causing chaos)

Filters/translate html to english.yml: updated to include ampersands in regexp replacing

Log.py: added error catching to SABBrain.txt deletion, because multiple threads can attempt to delete it at the same time (it was crashing, so I assume that's the cause)

MessageQueue.py: uses the new bad-input detectors from the end of Cleaner.py

SABBrain.py:
* put a try/except around is_word_nva() because something is passing it bad input (a period and a quesiton mark instead of a tuple)
* added some logging to compute_sentence_weight() in an attempt to determine if it penalizes repeated sentences correctly
* replaced "error!!!" with "lol", in case it pops up in a real conversation
* the diff says generate_reply() is completely changed, but I'm not sure why... hopefully I'm committing a better version and not an older version

sigartbot.py: now sends typing notifications, but I don't think they actually work

Line 
1 import re
2 from time import time
3 from Scraper import Scraper
4
5 class Commands:
6         def __init__(self, brain):
7                 ''' Map commands to the functions that handle them '''
8                 self.brain = brain
9                 self.scraper = Scraper(self.brain)
10                 self.handler = {
11                         'help': self.help,
12                         'list': self.help,
13                         'save': self.save,
14                         'quit': self.quit,
15                         'exit': self.quit,
16                         'close': self.quit,
17                         'signoff': self.quit,
18                         'debug': self.debug,
19                         'away': self.away,
20                         'back': self.back,
21                         'load': self.load,
22                         'toggle': self.toggle,
23                         'talkto': self.talkto,
24                         'sendim': self.sendim,
25                         'scrape': self.scrape
26                 }
27        
28         def run(self, their_name, message):
29                 ''' Returns True if a command was executed, or False if the message wasn't a command '''
30                 # restrict the usage of commands to a small selection of trustworthy screennames
31                 if their_name not in ['thepiant', 'nikhiljohri', 'zaquekyos']:
32                         return False
33                
34                 # compare the message to the format of a command
35                 regexp_result = re.match(r'(##?|!!?|//?)(\w+)(.*)', re.sub('<.*?>', '', message.lower()))
36                
37                 # if the message looks like it contains a command
38                 if regexp_result != None:
39                         # extract the command information from it
40                         (identifier, command, self.arguments) = regexp_result.groups()
41                        
42                         # if the command exists
43                         if self.handler.has_key(command) and callable(self.handler[command]):
44                                 # and return its result to the command's sender
45                                 time_start = time()
46                                
47                                 # disable exception handling when debugging
48                                 if self.brain.log.enabled:
49                                         command_text = self.handler[command]()
50                                 else:
51                                         try:
52                                                 # run the command
53                                                 command_text = self.handler[command]()
54                                                
55                                                 # if the command forgot to return a value, don't crash
56                                                 if command_text == None:
57                                                         command_text = "the command returned an ambiguous result"
58                                         except:
59                                                 command_text = self.handler[command].__doc__
60                                
61                                 # return the result to the person who ran the command
62                                 self.brain.queue.add_outgoing(their_name, command_text, 100)
63                                 return True
64                 return False
65        
66         def help(self):
67                 ''' /help COMMAND ... learn how to use a specific command'''
68                 command = self.arguments.strip().lower()
69                 if self.handler.has_key(command):
70                         return self.handler[command].__doc__
71                 return 'available commands: ' + ', '.join(self.handler.keys()) + " (note that some commands are simply aliases for others)"
72        
73         def save(self):
74                 ''' /save ... saves the current brain to disk '''
75                 self.brain.save()
76                 return "Brain data saved :-)"
77        
78         def quit(self):
79                 ''' /quit ... saves the current brain to disk and halts program execution '''
80                 print "\nSigning off...\n"
81                 self.save()
82                 sys.exit(0)
83        
84         def debug(self):
85                 ''' /debug ... toggles debug logging on/off '''
86                 self.brain.log.enabled = not self.brain.log.enabled
87                 return "Logging is now %s" % ('ON :-\\' if self.brain.log.enabled else 'OFF :-)')
88        
89         def away(self):
90                 ''' /away ... puts up an away message '''
91                 self.setAway('I am away from my computer right now.')
92                 return "I'm away =-O"
93        
94         def back(self):
95                 ''' /back ... comes back from an away state '''
96                 self.setAway(None)
97                 return "I'm back! :-D"
98        
99         def load(self):
100                 ''' /load ... reads information from *.pickle and *.yml files into the bot '''
101                 if (self.brain.load_brain()):
102                         return "I loaded brain data from files :-)"
103                 else:
104                         # teach it one sentence to prevent it from not being able to respond
105                         self.brain.parse_incoming_message("billyg", "billyg", "lol")
106                         return "There was nothing to load! I now know nothing :'("
107        
108         def toggle(self):
109                 ''' /toggle MODE ... changes the enabled status of a mode '''
110                 mode = self.arguments.strip().lower()
111                
112                 # if the mode exists, toggle it, otherwise provide some help
113                 if len(mode) > 0 and (re.sub('\W', '', mode) == mode) and (mode != "none") and self.brain.toggle.has_key(mode):
114                         self.brain.toggle[mode] = not self.brain.toggle[mode]
115                         return "%s mode is now %s" % (mode, "ON 8-)" if self.brain.toggle[mode] else "OFF :-(")
116                 else:
117                         return "Current modes: %s" % str(self.brain.toggle)
118        
119         def talkto(self):
120                 ''' /talkto SCREENNAME ... sends a greeting to someone '''
121                 screenname = self.brain.cleaner.simplify(self.arguments)
122                 self.brain.queue.add_outgoing(screenname, "hi", 100)
123                 return "I sent a message to %s :-)" % screenname
124        
125         # sendim screenname message
126         def sendim(self):
127                 ''' /sendim SCREENNAME MESSAGE ... sends a message to someone '''
128                 # send 'message' to 'screenname'
129                 (screename, text) = self.arguments.strip().split(' ', 1)
130                
131                 sn = screename.strip()
132                 text = text.strip()
133                
134                 # send the message
135                 self.brain.queue.add_outgoing(screename, text, 100)
136                 return 'I sent "%s" to %s :-)' % (text, screename)
137        
138         def scrape(self):
139                 ''' Scrape external sources of data to learn information quickly '''
140                 time_start = time()
141                 self.scraper.learn()
142                 return "Scraping took %s seconds" % (time() - time_start)
143        
144        
Note: See TracBrowser for help on using the browser.