コード例 #1
0
class Bot(object):
    """Slackchat bot for imitating users"""
    def __init__(self, token):
        # hardcoded
        self.blacklist = set(["markovbot", "kitty"])

        # hardcoded
        self.save_file = ".messagestore"

        # Keyed by user_id
        self.markovs = defaultdict(Markov)

        # Flag to inform polling thread of shutdown
        self.running = False
        self.slack = Slack(token)
        self.thread = None

        # Load saved MCs
        if os.path.isfile(self.save_file):
            with open(self.save_file) as handle:
                self.markovs = pickle.load(handle)
            # Clean up old versions
            for key in self.markovs:
                if not self.markovs[key]:
                    del self.markovs[key]

            # Reverse dict lookup
            id_list = [k for k in self.markovs if self.slack.users[k].name == "markovbot"]
            if id_list:
                print "Deleting introspective data"
                del self.markovs[id_list[0]]

        else:
            self.messages = defaultdict(list)


    def start(self):
        """Begin polling for messages"""
        self.running = True
        self.thread = threading.Thread(target=self.poll)
        self.thread.start()
        print "Started polling thread"

    def kill(self):
        """Kill the polling thread"""
        self.running = False
        self.thread.join()
        self.save()


    def get_history(self):
        """Download as much history as possible"""
        count = 0
        for user, text in self.slack.get_history():
            if self.add_message(user, text):
                count += 1
        print "Loaded %d messages from history" % count

    def save(self):
        """Save dictionary of MCs
        #TODO: Incremental save
        """
        with open(self.save_file, 'w+') as handle:
            pickle.dump(self.markovs, handle)

    def add_message(self, user, text):
        """Add transition counts from a received message"""
        if user and self.slack.users[user].name not in self.blacklist:
            self.markovs[user].add(text)
            return True
        else:
            return False

    def poll(self):
        """Poll slack API for messages
        TODO: Break saving state out into separate thread or at least method
        """
        count = 0
        while self.running:
            user, message = self.slack.get_message()
            # This is here to make it so we can exit cleanly
            # TODO: Something less clunky
            if message is None:
                continue
            count += 1
            # hardcoded
            if count == 50:
                self.save()
                count = 0
            print "%s: %s" % (user, message)
            self.add_message(user, message)

    def send_message(self):
        """Choose a user, generate a message for them, and send it
        TODO: Break out user selection, and make clever
        TODO: Somehow seed by previous message
        """
        if self.markovs:
            user_id = random.choice([k for k in self.markovs])
            text = self.markovs[user_id].generate()
            # hardcoded
            self.slack.send_message("bot-playground", user_id, text)
        else:
            # No data loaded
            pass