Issues (12)

modules/replace.py (3 issues)

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
This code seems to be duplicated in your project.
Loading history...
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
This code seems to be duplicated in your project.
Loading history...
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/"):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
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