1 | ##NEEDS |
||
2 | #adding a bold character for '<user> MEANT so say' |
||
3 | |||
4 | from event import Event |
||
5 | import requests |
||
6 | |||
7 | try: |
||
8 | from basemodule import BaseModule |
||
9 | except ImportError: |
||
10 | from modules.basemodule import BaseModule |
||
11 | |||
12 | class Replace(BaseModule): |
||
13 | def post_init(self): |
||
14 | |||
15 | self.bot.mem_store['replace'] = {} |
||
16 | replace = Event("__.r__") |
||
17 | replace.define(msg_definition=".*") |
||
18 | replace.subscribe(self) |
||
19 | |||
20 | self.bot.register_event(replace, self) |
||
21 | |||
22 | self.help = ".r <search string> | <replacement text> OR s/<search string>/<replacement string>" |
||
23 | self.MAX_BUFFER_SIZE = 300 |
||
24 | self.MAX_HISTORY_SIZE = 10 |
||
25 | |||
26 | View Code Duplication | def add_buffer(self, event=None, debug=False): |
|
0 ignored issues
–
show
Duplication
introduced
by
![]() |
|||
27 | """Takes a channel name and line passed to it and stores them in the bot's mem_store dict |
||
28 | for future access. The dict will have channel as key. The value to that key will be a list |
||
29 | of formatted lines of activity. |
||
30 | If the buffer size is not yet exceeded, lines are just added. If the buffer |
||
31 | is maxed out, the oldest line is removed and newest one inserted at the beginning. |
||
32 | """ |
||
33 | if debug: |
||
34 | print "Line: " + event.line |
||
35 | print "Verb: " + event.verb |
||
36 | print "Channel: " + event.channel |
||
37 | print "" |
||
38 | if not event: |
||
39 | return |
||
40 | #there are certain things we want to record in history, like nick changes and quits |
||
41 | #these often add to the humor of a quote. however, these are not specific to a channel |
||
42 | #in IRC and our bot does not maintain a userlist per channel. Therefore, when nick |
||
43 | #changes and quits occur, we will add them to every buffer. This is not technically |
||
44 | #correct behavior and could very well lead to quits/nick changes that are not visible |
||
45 | #showing up in a quote, but it's the best we can do at the moment |
||
46 | if not event.channel: |
||
47 | #discard events with unwanted verbs |
||
48 | if event.verb not in ["QUIT", "NICK"]: |
||
49 | return |
||
50 | try: |
||
51 | for chan in self.bot.mem_store['replace'].keys(): |
||
52 | if len(self.bot.mem_store['replace'][chan]) >= self.MAX_BUFFER_SIZE: |
||
53 | self.bot.mem_store['replace'][chan].pop() |
||
54 | line = self.format_line(event) |
||
55 | if line: |
||
56 | self.bot.mem_store['replace'][chan].insert(0, line) |
||
57 | except KeyError, IndexError: |
||
58 | print "Replace add_buffer() error when no event channel" |
||
59 | #now we continue with normal, per channel line addition |
||
60 | #create a dictionary associating the channel with an empty list if it doesn't exist yet |
||
61 | # END if not event.channel: |
||
62 | else: |
||
63 | if event.channel not in self.bot.mem_store['replace']: |
||
64 | self.bot.mem_store['replace'][event.channel] = [] |
||
65 | try: |
||
66 | #check for the length of the buffer. if it's too long, pop the last item |
||
67 | if len(self.bot.mem_store['replace'][event.channel]) >= self.MAX_BUFFER_SIZE: |
||
68 | self.bot.mem_store['replace'][event.channel].pop() |
||
69 | #get a line by passing event to format_line |
||
70 | #insert the line into the first position in the list |
||
71 | line = self.format_line(event) |
||
72 | if line: |
||
73 | self.bot.mem_store['replace'][event.channel].insert(0, line) |
||
74 | except IndexError: |
||
75 | print "Replace add_buffer() error. Couldn't access the list index." |
||
76 | |||
77 | def format_line(self, event): |
||
78 | """Takes an event and formats a string appropriate for quotation from it""" |
||
79 | #format all strings based on the verb |
||
80 | if event.verb == "": |
||
81 | return '' |
||
82 | elif event.verb == "PRIVMSG": |
||
83 | #special formatting for ACTION strings |
||
84 | if event.msg.startswith('\001ACTION'): |
||
85 | #strip out the word ACTION from the msg |
||
86 | return ' * %s %s\n' % (event.user, event.msg[7:]) |
||
87 | else: |
||
88 | return '<%s> %s\n' % (event.user, event.msg) |
||
89 | else: |
||
90 | #no matching verbs found. just ignore the line |
||
91 | return '' |
||
92 | |||
93 | def get_replacement_message(self, channel=None, find_msg=''): |
||
94 | """Looks through the mem_store to find the most recent message containing find_msg""" |
||
95 | if not channel: |
||
96 | #print "couldnt find channel" |
||
97 | return None |
||
98 | #must have at least one msg to search for and channel to look it up in |
||
99 | if len(find_msg) == 0 or not channel: |
||
100 | #print "find_msg is empty" |
||
101 | return None |
||
102 | #search for a matching string and saves the index of that entry. |
||
103 | #Searches from most recent to oldest. |
||
104 | found_index = -1 |
||
105 | for index, line in enumerate(self.bot.mem_store['replace'][channel]): |
||
106 | message = line |
||
107 | msg_index = message.find(">") |
||
108 | message = message[msg_index:] |
||
109 | #print line |
||
110 | #if the current entry of mem_store contains our string, we set the index and then BREAK to stop looking |
||
111 | if find_msg.decode('utf-8','ignore') in message: |
||
112 | found_index = index |
||
113 | break |
||
114 | #check to see if index values are positive. if not, string was not found and we're done |
||
115 | if found_index == -1 : |
||
116 | #print "couldnt find a good match" |
||
117 | return None |
||
118 | #returns the entire line |
||
119 | submission = self.bot.mem_store['replace'][channel][found_index] |
||
120 | return submission |
||
121 | |||
122 | def handle(self, event): |
||
123 | #first we see if we're going to try a replace or just add a line to the mem_store |
||
124 | View Code Duplication | if event.msg.startswith(".r "): |
|
0 ignored issues
–
show
|
|||
125 | #split the msg with '.r ' stripped off beginning and divide into a search string and replace string |
||
126 | string_token = event.msg[3:].split('|', 1) |
||
127 | find_msg = string_token[0].rstrip() |
||
128 | try: |
||
129 | replace_msg = string_token[1].lstrip() #if there's nothing after the pipe, then this resolves to '' which is fine |
||
130 | except IndexError: |
||
131 | return |
||
132 | #looking for a message containing our search string |
||
133 | newString = self.get_replacement_message(event.channel, find_msg) |
||
134 | |||
135 | #because the mem_store line shows "<user> message", we have to split up the username and their message |
||
136 | #this actually works to our advantage so we dont have to do additional calls to find out who sent what |
||
137 | msg_index = newString.find(">") |
||
138 | message = newString[msg_index + 2:] |
||
139 | message = message.replace(find_msg, replace_msg) |
||
140 | user = newString[1:msg_index] |
||
141 | #pybot sends the new replacement message to the chat |
||
142 | self.say(event.channel, user + " MEANT to say: " + message) |
||
143 | # because both .r and s// are valid formats now |
||
144 | View Code Duplication | if event.msg.startswith("s/"): |
|
145 | #alternative notation: s/<substring to replace>/<substring to replace with> |
||
146 | string_token = event.msg[2:].split('/', 1) |
||
147 | find_msg = string_token[0] |
||
148 | try: |
||
149 | replace_msg = string_token[1] |
||
150 | except IndexError: |
||
151 | return |
||
152 | #looking for a message containing our search string |
||
153 | newString = self.get_replacement_message(event.channel, find_msg) |
||
154 | |||
155 | #because the mem_store line shows "<user> message", we have to split up the username and their message |
||
156 | #this actually works to our advantage so we dont have to do additional calls to find out who sent what |
||
157 | msg_index = newString.find(">") |
||
158 | message = newString[msg_index + 2:] |
||
159 | message = message.replace(find_msg, replace_msg) |
||
160 | user = newString[1:msg_index] |
||
161 | #pybot sends the new replacement message to the chat |
||
162 | self.say(event.channel, user + " MEANT to say: " + message) |
||
163 | if event.user != self.bot.NICK : |
||
164 | self.add_buffer(event) |
||
165 |