Ejemplo n.º 1
0
    def publish(self, post):
        """Push a Post to every publisher.

        :return: a list of Publications.
        """
        if post.publish_at and post.publish_at > _now():
            # This should never happen; the method should not have been
            # called.
            self.log.warn(
                "Not publishing %s until %s", post.content,
                post.publish_at.strftime(self.TIME_FORMAT)
            )
            return []
        
        publications = []
        for publisher in self.publishers:
            publication, is_new = self.make_publication(
                publisher, post
            )
            if not is_new and not publication.error:
                # There was a previous, successful attempt to publish
                # this Post. Skip this Publisher.
                continue
            try:
                self.post_to_publisher(publisher, post, publication)
            except Exception, e:
                message = repr(e.message)
                publication.report_failure("Uncaught exception: %s" % e.message)
            publications.append(publication)
Ejemplo n.º 2
0
 def setup(self):
     super(TestBotModel, self).setup()
     self.now = _now()
     
     self.bot = self._botmodel()
     self.the_past = self.now - datetime.timedelta(days=1)
     self.the_future = self.now + datetime.timedelta(days=1)
Ejemplo n.º 3
0
 def schedule_next_post(self, just_published=[]):
     """Assuming that a post was just published, set the time at which the
     next post should be published.
     """
     how_long = self._next_scheduled_post(just_published)
     if how_long:
         self.model.next_post_time = _now() + how_long
Ejemplo n.º 4
0
 def state_needs_update(self):
     """Does this bot's internal state need to be updated?"""
     if self.state_update_schedule is None:
         # This bot doesn't update state on a schedule.
         return False
     now = _now()
     update_at = now + datetime.timedelta(
         minutes=self.state_update_schedule
     )
     last_update = self.model.last_state_update_time
     return not last_update or now > update_at
Ejemplo n.º 5
0
    def process_bot(self, bot_model):
        implementation = bot_model.implementation
        if self.args.force:
            bot_model.next_post_time = _now()
        posts = implementation.publishable_posts
        if self.args.dry_run:
            print bot_model.name
            for post in posts:
                print post.content
                print "-" * 80
                return

        # We're doing this for real.
        for post in posts:
            for publication in implementation.publish(post):
                publication.post.bot.log.info(publication.display())
        self.config._db.commit()
Ejemplo n.º 6
0
    def process_bot(self, bot_model):

        now = _now()
        recent = bot_model.recent_posts().limit(1).all()
        if not recent:
            bot_model.log.info("Has never posted.")
        else:
            [recent] = recent
            bot_model.log.info("Most recent post: %s" % recent.content)
            for publication in recent.publications:
                if publication.error:
                    bot_model.log.info(
                        "%s ERROR: %s" %
                        (publication.service, publication.error))
                else:
                    bot_model.log.info("%s posted %dm ago (%s)" % (
                        publication.service,
                        (now -
                         publication.most_recent_attempt).total_seconds() / 60,
                        publication.most_recent_attempt,
                    ))

        def announce_list(count, content, what):
            if count == 1:
                item = "post"
            else:
                item = "posts"
            bot_model.log.info("%d %s %s" % (count, item, what))
            bot_model.log.info("Next up: %s" % content)

        # Announce scheduled posts.
        scheduled = bot_model.scheduled
        next_post_time = bot_model.next_post_time
        if len(scheduled) > 0:
            first = scheduled[0]
            announce_list(len(scheduled), first.content, "scheduled")
            next_post_time = first.publish_at or bot_model.next_post_time

        # Announce backlog posts.
        try:
            backlog = bot_model.backlog
            if backlog:
                first = backlog[0]
                announce_list(len(backlog), first, "in backlog")
        except ValueError, e:
            pass
Ejemplo n.º 7
0
 def new_post(self):
     """Scrape the site and get a number of new Posts out of it."""
     response = self.make_request()
     if response.status_code == 304: # Not Modified
         return
     utcnow = datetime.datetime.utcnow()
     now = _now()
     new_last_update_time = None
     posts = []
     for post in self.scrape(response):
         if not isinstance(post, Post):
             post, ignore = Post.from_content(
                 bot=self.model, content=post
             )
         if not post.publish_at:
             post.publish_at = now
         posts.append(post)
     self.model.last_state_update_time = utcnow
     return posts
Ejemplo n.º 8
0
    def schedule_posts(self, filehandle):
        """Create some number of posts to be published at specific times.

        It's better to override _schedule_posts() -- this method
        just calls that method and does some error checking.
        
        :return: A list of newly scheduled Posts.
        """
        scheduled = self._schedule_posts(filehandle)
        if isinstance(scheduled, Post):
            scheduled = [scheduled]
        now = _now()
        for post in scheduled:
            continue
            if post.publish_at and post.publish_at < now:
                raise InvalidPost(
                    "A new post can't be scheduled for the past. (%s was scheduled for %s)" % (
                        post.content.encode("ascii", errors="replace"), post.publish_at
                    )
                )
        return scheduled
Ejemplo n.º 9
0
    def test_publishable_posts_returns_all_scheduled_posts(self):
        bot = self._bot()
        now = _now()
        yesterday = now - datetime.timedelta(days=1)
        day_before = now - datetime.timedelta(days=2)
        tomorrow = now + datetime.timedelta(days=1)
        publish_yesterday = self._post(bot.model,
                                       "yesterday",
                                       publish_at=yesterday)
        publish_earlier = self._post(bot.model,
                                     "day before",
                                     publish_at=day_before)
        publish_later = self._post(bot.model, "tomorrow", publish_at=tomorrow)

        # publishable_posts returns all posts that should have been
        # published by now.
        eq_([publish_earlier, publish_yesterday], bot.publishable_posts)

        # Since the scheduled posts weren't _created_ by the
        # publishable_posts, they don't go away when you call
        # publishable_posts once. They will stick around until they're
        # published.
        eq_([publish_earlier, publish_yesterday], bot.publishable_posts)
Ejemplo n.º 10
0
 def _schedule_posts(self):
     yesterday = _now() - datetime.timedelta(days=1)
     post, is_new = Post.from_content(self.model,
                                      "the past!",
                                      publish_at=yesterday)
     return [post]
Ejemplo n.º 11
0
 def _schedule_posts(self):
     tomorrow = _now() + datetime.timedelta(days=1)
     post, is_new = Post.from_content(self.model,
                                      "the future!",
                                      publish_at=tomorrow)
     return post