def __init__(self, version=None, description=None): """ Handles command-line arg parsing and loading of data. """ # Set up file paths. self.package_data_path = join(dirname(__file__), "data") self.data_path = join(getcwd(), "babbler.data") self.pid_path = join(getcwd(), "babbler.pid") self.log_path = join(getcwd(), "babbler.log") self.options_path = join(self.package_data_path, "options.yml") self.eliza_path = join(self.package_data_path, "eliza.yml") # Load persisted data. self.data = PersistentDict(path=self.data_path) existing_options = {} if self.data.load(): existing_options = self.data["options"] # Migrate from 0.1 format. if "todo" in self.data: self.data["feed"] = RespondingFeed() self.data["feed"].todo = self.data.pop("todo") self.data["feed"].done = self.data.pop("done") # Migrate from 0.2 format. feed = self.data["feed"] if isinstance(feed, Feed): self.data["feed"] = RespondingFeed() self.data["feed"].todo = feed.todo self.data["feed"].done = feed.done else: print print "Initial setup. Data will be saved to '%s'" % self.data_path print # Load options. options = Options(self.options_path, existing=existing_options, description=description, version=version) self.data["options"] = options.parse_args() self.data.save() # Set up the Twitter API object. api = Api(**dict([(k, v) for k, v in self.data["options"].items() if k.split("_")[0] in ("consumer", "access")])) self.twitter = api
class Bot(object): def __init__(self, version=None, description=None): """ Handles command-line arg parsing and loading of data. """ # Set up file paths. self.package_data_path = join(dirname(__file__), "data") self.data_path = join(getcwd(), "babbler.data") self.pid_path = join(getcwd(), "babbler.pid") self.log_path = join(getcwd(), "babbler.log") self.options_path = join(self.package_data_path, "options.yml") self.eliza_path = join(self.package_data_path, "eliza.yml") # Load persisted data. self.data = PersistentDict(path=self.data_path) existing_options = {} if self.data.load(): existing_options = self.data["options"] # Migrate from 0.1 format. if "todo" in self.data: self.data["feed"] = RespondingFeed() self.data["feed"].todo = self.data.pop("todo") self.data["feed"].done = self.data.pop("done") # Migrate from 0.2 format. feed = self.data["feed"] if isinstance(feed, Feed): self.data["feed"] = RespondingFeed() self.data["feed"].todo = feed.todo self.data["feed"].done = feed.done else: print print "Initial setup. Data will be saved to '%s'" % self.data_path print # Load options. options = Options(self.options_path, existing=existing_options, description=description, version=version) self.data["options"] = options.parse_args() self.data.save() # Set up the Twitter API object. api = Api(**dict([(k, v) for k, v in self.data["options"].items() if k.split("_")[0] in ("consumer", "access")])) self.twitter = api def run(self, as_daemon=False): """ Main event loop that gets the entries from the feed and posts them to Twitter. """ # Set up logging. logger_args = {"format": "%(asctime)-15s %(levelname)-5s %(message)s"} if as_daemon: self.kill() daemonize(self.pid_path) logger_args.update({"filename": self.log_path, "filemode": "wb"}) logging.basicConfig(**logger_args) log_level = getattr(logging, self.data["options"]["log_level"]) logging.getLogger().setLevel(log_level) logging.debug("\n\nUsing options:\n\n%s\n" % self.data["options"]) # Set up the feed. self.data.setdefault("feed", RespondingFeed()) feed_options = dict(twitter=self.twitter, max_len=TWEET_MAX_LEN, eliza_path=self.eliza_path, **self.data["options"]) self.data["feed"].setup(feed_options) self.data.save() # Set up hashtagging. tagger = Tagger(scorer=self.hashtag_score, data_path=self.package_data_path, min_length=self.data["options"]["hashtag_min_length"]) # Main loop. try: for entry in self.data["feed"]: try: # Twitter reply. tweet = "%s %s" % (entry["to"], entry["title"]) reply_to = entry["id"] except KeyError: # Feed entry. tweet = entry["title"] reply_to = None for tag in tagger.tags(entry["title"]): tag = " #" + tag # Extra check to ensure tag isn't already in the tweet. if (len(tweet + tag) <= TWEET_MAX_LEN and tag.strip().lower() not in tweet.lower()): tweet += tag # Post to Twitter. done = True try: if not self.data["options"]["dry_run"]: self.twitter.PostUpdate(tweet, reply_to) except Exception, e: logging.error("Error tweeting '%s': %s" % (tweet, e)) # Mark the entry as done if it's a duplicate. done = str(e) == "Status is a duplicate." if done: logging.info("Tweeted: %s" % tweet) # Move the entry from "todo" to "done" and save. self.data["feed"].process() if not self.data["options"]["dry_run"]: self.data.save() except Exception, e: logging.critical("Shutting down on unhandled error: %s" % e)