def updateStats(self, m): msg = StringUtil.removeFormattingAndColors(m.getTrailing()).lower() word_count = len(msg.split()) seen_types = {} pure = True for word_type, (impure, rx) in WORD_TYPES_RX.items(): if re.search(rx, msg): if impure: pure = False seen_types[word_type] = True # goat is fickle. if random.random() < .0005: pure = False user_store = KVStore.getUserStore(m) user_store.save(LAST_SEEN, time.time()) chan_store = KVStore.getChanStore(m) for store, is_channel in [(chan_store, True), (user_store, False)]: if pure: self.purity_update(m, store, is_channel) else: self.purity_fail(m, store, is_channel) store.incSave(LINE_COUNT) store.incSave(WORD_COUNT, word_count) for word_type, seen in seen_types.items(): store.incSave(word_type, 1)
def cache_url(url): """Adds a url to the cache. Returns True if we've seen it before or False if it's new.""" url_store = KVStore.getCustomStore("tumblr_urls") if url_store.has(url): return True else: url_store.save(url, time.time()) return False
def cache_search(search): """Adds a search to the cache. Returns True if we've seen it before or False if it's new.""" tokens = re.sub("[^a-z\s]", "", search.lower()).split() key = " ".join(sorted(tokens)) search_store = KVStore.getCustomStore("tumblr_searches") if search_store.has(key): return True else: search_store.save(key, time.time()) return False
def processChannelMessage(self, m): if m.sender in BOT_NAMES: return commands = { "stats": self.gen_stats_reply, "purity": self.gen_purity_reply, "sexstats": self.gen_sex_reply, } if m.modCommand in commands: reply = "I'm afraid I just don't know." parser = CommandParser(m) if parser.hasVar("user"): user = parser.get("user") if KVStore.hasUserStore(user): user_store = KVStore.getUserStore(user) reply = commands[m.modCommand](user, user_store) else: chan_store = KVStore.getChanStore(m) reply = commands[m.modCommand](m.getChanname(), chan_store) m.reply("%s: %s" % (m.sender, reply)) else: self.updateStats(m)
def set_last_post_time(): store = KVStore.getCustomStore("tumblr") now = time.time() last_post = store.save("lastPost", now) return now
def get_last_post_time(): store = KVStore.getCustomStore("tumblr") last_post = store.getOrElse("lastPost", 0.0) return last_post
def get_tumblr_store(): store = KVStore.getCustomStore("tumblr") return store
def gen_purity_highscore(self): reply = "" now = time.time() user_line = KVStore.getAllUsers(LINE_COUNT) user_score = KVStore.getAllUsers(PURITY_SCORE) user_impure = KVStore.getAllUsers(PURITY_IMPURE_COUNT) user_seen = KVStore.getAllUsers(LAST_SEEN) purity_stats = [] for user in user_line: if user in BOT_NAMES: continue line_count = user_line[user] pure_score = user_score[user] seen_time = user_seen[user] # this should only be the case for users that we have not seen # since we started tracking when a user was last seen. if seen_time is None: continue # exclude silent users or users that have been idle. if line_count < 50 or now - seen_time > 60*60*24: continue impure_count = user_impure[user] or 0 impure_ratio = impure_count / float(line_count) purity_stats.append((pure_score, impure_ratio, user)) # sort for highest purity score to lowest purity score, for the tie # breaker use the most impure to the least impure, so that: # a generally highly pure user who makes a mistake will be lower # scoring than a low purity user who curses, and a low purity user # who has a good run will beat out a high purity suer who is just # doing the normal thing. # TODO look into making an arbitrary score that combines the two # factors so that we can highlight people who are acting the # the farthest away from their normal ebhavior. purity_stats.sort(reverse=True) if not purity_stats: return reply most_pure = purity_stats[0] least_pure = purity_stats[-1] if most_pure[0] == least_pure[0]: # it's not worth reporting if the first and last place user # have the same score. (or are the same user) return reply reply += " %s is on the spoke at %d purity" % ( most_pure[2], most_pure[0]) reply += ", and %s is off in the weeds at a measly %d." % ( least_pure[2], least_pure[0]) if len(purity_stats) > 2: reply += " Here's everyone else: " results = [] for stat in purity_stats[1:-1]: results.append("%s %d" % (stat[2], stat[0])) reply += ", ".join(results) reply += "." return reply
def gen_sex_reply(self, target, store): sex_count = store.getOrElse(SEX_COUNT, 0) line_count = store.getOrElse(LINE_COUNT, 0) if line_count == 0: reply = "I haven't the slightest." else: reply = "%s has sex on the mind about %.1f%% of the time." % ( target, 100 * sex_count / float(line_count)) if not target.startswith("#"): return reply # TODO this needs to be generalized. user_line = KVStore.getAllUsers(LINE_COUNT) user_stat = KVStore.getAllUsers(SEX_COUNT) user_seen = KVStore.getAllUsers(LAST_SEEN) now = time.time() stats = [] for user in user_line: if user in BOT_NAMES: continue lines = user_line[user] stat = user_stat[user] seen = user_seen[user] if stat is None: stat = 0 # this should only be the case for users that we have not seen # since we started tracking when a user was last seen. if seen is None: continue # exclude silent users or users that have been idle. if lines < 50 or now - seen > 60*60*24: continue score = (float(stat) / lines) * 100 stats.append((score, user)) stats.sort(reverse=True) if not stats: return reply highest = stats[0] lowest = stats[-1] if highest[0] == lowest[0]: # it's not worth reporting if the first and last place user # have the same score. (or are the same user) return reply reply += " %s is a sexual predator and has sex on the mind %.1f%% of the time" % ( highest[1], highest[0]) reply += ", and %s is lonely and probably asexual at only %.1f%%." % ( lowest[1], lowest[0]) if len(stats) > 2: reply += " Here's everyone else: " results = [] for stat in stats[1:-1]: results.append("%s %.1f%%" % (stat[1], stat[0])) reply += ", ".join(results) reply += "." return reply