def handler(self, **args): """Allows someone to add material onto a factoid (that isn't locked) by saying "foo is also bar", for example""" import priv from irclib import Event from time import time target = self.return_to_sender(args) # args["text"] should look something like: # "moobot: foo is also bar blatz qux" # Grab the factoid to change: factoid_key = self.strip_words(args["text"], 1).split(" is ")[0] # Grab the stuff to tack on: to_add = self.strip_words(args["text"], 1).split(" is also ")[1] # Check if the factoid is locked or not locked_by = FactoIds.getLockedBy(factoid_key) if locked_by == None: message = "Factoid '%s' does not exist." % factoid_key return Event("privmsg", "", target, [message]) if priv.checkPriv(args["source"], "delete_priv") == 0 and (locked_by != "" and locked_by != args["source"]): message = "You do not have permission to delete factoid '%s." % factoid_key return Event("privmsg", "", target, [message]) # Since we don't have delete_priv, we just delete and recreate the factoid orig_factoid = FactoIds.getValueByKey(factoid_key) new_factoid = orig_factoid + ", or " + to_add FactoIds.update(factoid_key, new_factoid, args["source"]) return Event("privmsg", "", target, ["ok"])
def handler(self, **args): """Allows someone to add material onto a factoid (that isn't locked) by saying "foo is also bar", for example""" import priv from irclib import Event from time import time target = self.return_to_sender(args) # args["text"] should look something like: # "moobot: foo is also bar blatz qux" # Grab the factoid to change: factoid_key = self.strip_words(args["text"], 1).split(" is ")[0] # Grab the stuff to tack on: to_add = self.strip_words(args["text"], 1).split(" is also ")[1] # Check if the factoid is locked or not locked_by = FactoIds.getLockedBy(factoid_key) if locked_by == None: message = "Factoid '%s' does not exist." % factoid_key return Event("privmsg", "", target, [message]) if priv.checkPriv(args["source"], "delete_priv") == 0 and ( locked_by != "" and locked_by != args["source"]): message = "You do not have permission to delete factoid '%s." % factoid_key return Event("privmsg", "", target, [message]) # Since we don't have delete_priv, we just delete and recreate the factoid orig_factoid = FactoIds.getValueByKey(factoid_key) new_factoid = orig_factoid + ", or " + to_add FactoIds.update(factoid_key, new_factoid, args["source"]) return Event("privmsg", "", target, ["ok"])
def handler(self, **args): """Allows someone to alter material in a factoid by using a regular expression. Invoked like: "moobot: foo =~ s/moo/bar/".""" import priv, re, time from irclib import Event target = self.return_to_sender(args) # Grab the factoid to change: # first, drop the bot name factoid_key = " ".join(args["text"].split()[1:]) # Now split on " =~ " and take the left half factoid_key = factoid_key.split(" =~ ", 1)[0] locked_by = FactoIds.getLockedBy(factoid_key) if locked_by == None: message = "Factoid '%s' does not exist." % factoid_key return Event("privmsg", "", target, [message]) # Check for the appropriate privilege (delete_priv, even # though we aren't deleting - we are modifying, and there # is no modify priv) if priv.checkPriv(args["source"], "delete_priv") == 0 and (locked_by != "" and locked_by != args["source"]): message = "You do not have permission to modify factoid '%s." % factoid_key return Event("privmsg", "", target, [message]) # get the original factoid value factoid = FactoIds.getValueByKey(factoid_key) # Grab the regex(es) to apply # First split on =~, then split on spaces for the RHS regexes_str = args["text"].split(" =~ ", 1)[1] # Now we can't split just on spaces, because the regex itself # can have spaces in it. We gotta grab each one individually # because a regex to get them all (potentially each having # unique separators, like "s/foo/bar blatz/g s:moo:mooooo!:i # s%this%makes it hard to parse%". # # The basic algorithm is: # 1 - find out the separator character (2nd) # 2 - find the index of the third occurrence of this character # 3 - find the next space, chop off everything before it and # append it to the regex_list regex_list = [] # regex for removing leading spaces, compiling it first lead_spaces = re.compile("^\s+") while len(regexes_str) > 2: # Strip leading spaces first (so regexes with many spaces # between them don't mess things up when we assume the separator # is the second character) regexes_str = lead_spaces.sub("", regexes_str) # Separator = 2nd char separator = regexes_str[1] # Find it once, then use that as a low range # NOTE - if there is garbage at any point, ignore everything # after it second_sep = regexes_str.find(separator, 2) if second_sep == 0: break third_sep = regexes_str.find(separator, second_sep+1) if third_sep == 0: break # now the space space_index = regexes_str.find(" ", third_sep) if space_index == -1: # no space found regex_list.append(regexes_str) break else: regex_list.append(regexes_str[:space_index]) regexes_str = regexes_str[space_index:] # apply each of the regexes in order # For now we are assuming all of the regexes are search and replace # s/foo/bar/[gi] ACCEPTABLE_PREFIXES = "sy" ACCEPTABLE_SUFFIXES = "gi" for regex_string in regex_list: # Split the regex into parts - strictly, we split on the second # character, as s:foo:bar: is valid as well try: parts = regex_string.split(regex_string[1]) except IndexError: break # If we don't get four parts (even if the last is empty) # then it's not a valid regex - chastise them ... also, # if it's not one of the valid prefixes/suffixes, chastise them :) if len(parts) != 4 or \ parts[0] not in ACCEPTABLE_PREFIXES: message = "Invalid regular expression: " + regex_string return Event("privmsg", "", target, [message]) for letter in parts[3]: if letter not in ACCEPTABLE_SUFFIXES: message = "Invalid regular expression: " + regex_string return Event("privmsg", "", target, [message]) # Get some flags before we compile a regex if "g" in parts[3]: count = 0 else: count = 1 if "i" in parts[3]: case_sensitive = 0 else: case_sensitive = 1 # Make a regex object for the first pattern try: re_str = parts[1] if case_sensitive: regex = re.compile(re_str) else: regex = re.compile(re_str, re.I) except re.error: message = "Invalid regular expression: " + regex_string return Event("privmsg", "", target, [message]) # Actually perform the transformation if parts[0] == "s": factoid = regex.sub(parts[2], factoid) elif parts[0] == "y": message = "This regex not yet supported. Sorry :(" return Event("privmsg", "", target, [message]) # When all the regexes are applied, store the factoid again # with the new date as the modification date. FactoIds.update(factoid_key, factoid, args["source"]) return Event("privmsg", "", target, ["ok"])
def handler(self, **args): """ gets the factoid_value field """ import time from irclib import Event, nm_to_n # Store the ref # ref = args["ref"]() # If we were /msg'ed this, /msg it back, otherwise send it to the # channel # (set up here because there are some rather early returns for the # continue handler types and whatnot) target = self.return_to_sender(args) factoid_key = args["text"] factoid_key = self.strip_words(factoid_key, 1) # removes "moobot: " # By default we want to parse the factoid value after grabbing it from # the db, but certain flags along the way may set this flag so that we # don't do so (e.g., "literal"). dont_parse = 0 # If we are called with something like "moobot: literal foo", we want # to strip the "literal" from it as that is not part of the # factoid, unless of course nothing follows "literal", in which # case we would be looking for the factoid for "literal" if len(args["text"].split(" ")) > 1 and \ args["text"].split(" ")[1] == "literal": dont_parse = 1 # set for later, when we spit the value back factoid_key = self.strip_words(factoid_key, 1) # Strip trailing ?'s and !'s (so asking for "moobot: foo?!?!?!???" is # the same as just asking for "moobot: foo" factoid_key = self.strip_punctuation(factoid_key) text = FactoIds.getValueByKey(factoid_key, args["source"]) # If the factoid doesn't exist, simply continue trying # to match with other handlers using the continue event type if not text: return Event("continue", "", target, [""]) ### The new length stuff # Here we check to see if the total message length would be greater # than irclib.MESSAGE_SIZE_LIMIT, and if so, split it up accordingly # and return the requested one, or print out a warning. # Message format: # nickname!username@localhost privmsg #channel_name :factoid_text # self.debug("%s!%s@%s" % (ref.connection.ircname, # ref.connection.username, ref.connection.localhost)) # # msg_length = len(text) + len(" privmsg # :") + len(target) + \ # # len(ref.connection.nickname) + len(ref.connection.username) + \ # # len(ref.connection.localhost) # # self.debug(msg_length) # by default we will just say something to the target, but if the # factoid contains an <action> tag, we will make it an action # eventtype eventtype="privmsg" # If the person says something like "moobot: literal foo", we don't # want to parse the factoid, we just want to spit it back in its raw # form. Otherwise, we want to replace parentheses and pipes as well # as see if we need to change the eventtype if not dont_parse: # awkward, but supports the more general case, # instead of having to set a flag for every case # where we DO want to parse, only set a flag where # we do NOT parse # Strip spaces from the left-hand side text = text.lstrip() # Parse parentheses and pipes to come up with one random string # from many choices specified in the factoid text = FactoIds.parseSar(text) # Replace $who and $nick with the person requesting the factoid text = text.replace("$who", nm_to_n(args["source"])) if args.has_key("channel"): text = text.replace("$chan", args["channel"]) text = text.replace("$nick", nm_to_n(args["source"])) # If the new string (after previous replacements) begins with # "<action>" or "<reply>" (case insensitive), then we strip them # and possibly change the eventtype if necessary. Otherwise, we # simply say "foo is bar" back to the target. if text[:8].lower() == "<action>": eventtype="action" text = text[8:] elif text[:7].lower() == "<reply>": text = text[7:] else: text = factoid_key + " is " + text return Event(eventtype, "", target, [ text.strip() ])
def handler(self, **args): """Allows someone to alter material in a factoid by using a regular expression. Invoked like: "moobot: foo =~ s/moo/bar/".""" import priv, re, time from irclib import Event target = self.return_to_sender(args) # Grab the factoid to change: # first, drop the bot name factoid_key = " ".join(args["text"].split()[1:]) # Now split on " =~ " and take the left half factoid_key = factoid_key.split(" =~ ", 1)[0] locked_by = FactoIds.getLockedBy(factoid_key) if locked_by == None: message = "Factoid '%s' does not exist." % factoid_key return Event("privmsg", "", target, [message]) # Check for the appropriate privilege (delete_priv, even # though we aren't deleting - we are modifying, and there # is no modify priv) if priv.checkPriv(args["source"], "delete_priv") == 0 and ( locked_by != "" and locked_by != args["source"]): message = "You do not have permission to modify factoid '%s." % factoid_key return Event("privmsg", "", target, [message]) # get the original factoid value factoid = FactoIds.getValueByKey(factoid_key) # Grab the regex(es) to apply # First split on =~, then split on spaces for the RHS regexes_str = args["text"].split(" =~ ", 1)[1] # Now we can't split just on spaces, because the regex itself # can have spaces in it. We gotta grab each one individually # because a regex to get them all (potentially each having # unique separators, like "s/foo/bar blatz/g s:moo:mooooo!:i # s%this%makes it hard to parse%". # # The basic algorithm is: # 1 - find out the separator character (2nd) # 2 - find the index of the third occurrence of this character # 3 - find the next space, chop off everything before it and # append it to the regex_list regex_list = [] # regex for removing leading spaces, compiling it first lead_spaces = re.compile("^\s+") while len(regexes_str) > 2: # Strip leading spaces first (so regexes with many spaces # between them don't mess things up when we assume the separator # is the second character) regexes_str = lead_spaces.sub("", regexes_str) # Separator = 2nd char separator = regexes_str[1] # Find it once, then use that as a low range # NOTE - if there is garbage at any point, ignore everything # after it second_sep = regexes_str.find(separator, 2) if second_sep == 0: break third_sep = regexes_str.find(separator, second_sep + 1) if third_sep == 0: break # now the space space_index = regexes_str.find(" ", third_sep) if space_index == -1: # no space found regex_list.append(regexes_str) break else: regex_list.append(regexes_str[:space_index]) regexes_str = regexes_str[space_index:] # apply each of the regexes in order # For now we are assuming all of the regexes are search and replace # s/foo/bar/[gi] ACCEPTABLE_PREFIXES = "sy" ACCEPTABLE_SUFFIXES = "gi" for regex_string in regex_list: # Split the regex into parts - strictly, we split on the second # character, as s:foo:bar: is valid as well try: parts = regex_string.split(regex_string[1]) except IndexError: break # If we don't get four parts (even if the last is empty) # then it's not a valid regex - chastise them ... also, # if it's not one of the valid prefixes/suffixes, chastise them :) if len(parts) != 4 or \ parts[0] not in ACCEPTABLE_PREFIXES: message = "Invalid regular expression: " + regex_string return Event("privmsg", "", target, [message]) for letter in parts[3]: if letter not in ACCEPTABLE_SUFFIXES: message = "Invalid regular expression: " + regex_string return Event("privmsg", "", target, [message]) # Get some flags before we compile a regex if "g" in parts[3]: count = 0 else: count = 1 if "i" in parts[3]: case_sensitive = 0 else: case_sensitive = 1 # Make a regex object for the first pattern try: re_str = parts[1] if case_sensitive: regex = re.compile(re_str) else: regex = re.compile(re_str, re.I) except re.error: message = "Invalid regular expression: " + regex_string return Event("privmsg", "", target, [message]) # Actually perform the transformation if parts[0] == "s": factoid = regex.sub(parts[2], factoid) elif parts[0] == "y": message = "This regex not yet supported. Sorry :(" return Event("privmsg", "", target, [message]) # When all the regexes are applied, store the factoid again # with the new date as the modification date. FactoIds.update(factoid_key, factoid, args["source"]) return Event("privmsg", "", target, ["ok"])
def handler(self, **args): """ gets the factoid_value field """ import time from irclib import Event, nm_to_n # Store the ref # ref = args["ref"]() # If we were /msg'ed this, /msg it back, otherwise send it to the # channel # (set up here because there are some rather early returns for the # continue handler types and whatnot) target = self.return_to_sender(args) factoid_key = args["text"] factoid_key = self.strip_words(factoid_key, 1) # removes "moobot: " # By default we want to parse the factoid value after grabbing it from # the db, but certain flags along the way may set this flag so that we # don't do so (e.g., "literal"). dont_parse = 0 # If we are called with something like "moobot: literal foo", we want # to strip the "literal" from it as that is not part of the # factoid, unless of course nothing follows "literal", in which # case we would be looking for the factoid for "literal" if len(args["text"].split(" ")) > 1 and \ args["text"].split(" ")[1] == "literal": dont_parse = 1 # set for later, when we spit the value back factoid_key = self.strip_words(factoid_key, 1) # Strip trailing ?'s and !'s (so asking for "moobot: foo?!?!?!???" is # the same as just asking for "moobot: foo" factoid_key = self.strip_punctuation(factoid_key) text = FactoIds.getValueByKey(factoid_key, args["source"]) # If the factoid doesn't exist, simply continue trying # to match with other handlers using the continue event type if not text: return Event("continue", "", target, [""]) ### The new length stuff # Here we check to see if the total message length would be greater # than irclib.MESSAGE_SIZE_LIMIT, and if so, split it up accordingly # and return the requested one, or print out a warning. # Message format: # nickname!username@localhost privmsg #channel_name :factoid_text # self.debug("%s!%s@%s" % (ref.connection.ircname, # ref.connection.username, ref.connection.localhost)) # # msg_length = len(text) + len(" privmsg # :") + len(target) + \ # # len(ref.connection.nickname) + len(ref.connection.username) + \ # # len(ref.connection.localhost) # # self.debug(msg_length) # by default we will just say something to the target, but if the # factoid contains an <action> tag, we will make it an action # eventtype eventtype = "privmsg" # If the person says something like "moobot: literal foo", we don't # want to parse the factoid, we just want to spit it back in its raw # form. Otherwise, we want to replace parentheses and pipes as well # as see if we need to change the eventtype if not dont_parse: # awkward, but supports the more general case, # instead of having to set a flag for every case # where we DO want to parse, only set a flag where # we do NOT parse # Strip spaces from the left-hand side text = text.lstrip() # Parse parentheses and pipes to come up with one random string # from many choices specified in the factoid text = FactoIds.parseSar(text) # Replace $who and $nick with the person requesting the factoid text = text.replace("$who", nm_to_n(args["source"])) if args.has_key("channel"): text = text.replace("$chan", args["channel"]) text = text.replace("$nick", nm_to_n(args["source"])) # If the new string (after previous replacements) begins with # "<action>" or "<reply>" (case insensitive), then we strip them # and possibly change the eventtype if necessary. Otherwise, we # simply say "foo is bar" back to the target. if text[:8].lower() == "<action>": eventtype = "action" text = text[8:] elif text[:7].lower() == "<reply>": text = text[7:] else: text = factoid_key + " is " + text return Event(eventtype, "", target, [text.strip()])