Exemplo n.º 1
0
    def test_time_bucket(self):
        now = datetime.now(pytz.timezone(app_config.PROJECT_TIMEZONE))
        five_hours_ago = now - timedelta(hours=5)
        ten_hours_ago = now - timedelta(hours=10)
        bucket = TimeTools.time_bucket(five_hours_ago)
        self.assertEqual(bucket, '4 hours')

        bucket = TimeTools.time_bucket(ten_hours_ago)
        self.assertEqual(bucket, '8 hours')
Exemplo n.º 2
0
    def test_time_bucket(self):
        now = datetime.now(pytz.timezone(app_config.PROJECT_TIMEZONE))
        five_hours_ago = now - timedelta(hours=5)
        ten_hours_ago = now - timedelta(hours=10)
        bucket = TimeTools.time_bucket(five_hours_ago)
        self.assertEqual(bucket, '4 hours')

        bucket = TimeTools.time_bucket(ten_hours_ago)
        self.assertEqual(bucket, '8 hours')
Exemplo n.º 3
0
    def test_humanist_time_bucket(self):
        bucket = TimeTools.humanist_time_bucket({'minutes': 5, 'seconds': 5})
        self.assertEqual(bucket, '5 minutes 5 seconds')

        bucket = TimeTools.humanist_time_bucket({'minutes': 0, 'seconds': 1})
        self.assertEqual(bucket, '1 second')

        bucket = TimeTools.humanist_time_bucket({'minutes': 5, 'seconds': 0})
        self.assertEqual(bucket, '5 minutes')

        bucket = TimeTools.humanist_time_bucket({'minutes': 1, 'seconds': 1})
        self.assertEqual(bucket, '1 minute 1 second')
Exemplo n.º 4
0
    def handle_slug_inquiry(self, message):
        """
        Respond to an inquiry about the slug with stats and charts
        """
        match = re.search(self.SLUG_SEARCH_REGEX, message.body["text"])
        slug = match.group(1)

        if slug:

            # Try to match the story to a slug to accurately get a team
            # The Google Analytics property ID comes from the team config
            # We use the default team if none is found
            stories = Story.select().where(Story.slug.contains(slug))
            team = self.config.get_team_for_stories(stories)

            linger_rows = self.get_linger_data(team=team, slug=slug)

            if not linger_rows:
                return {"text": "Sorry, I wasn't able to find linger rate stats for %s" % slug}

            median = NPRLingerRate.get_median(linger_rows)
            print "Got median"
            print median
            people = "{:,}".format(median["total_people"])
            time_text = TimeTools.humanist_time_bucket(median)

            reply = u"*%s* people spent a median *%s* on `%s`." % (people, time_text, slug)

            reply += "\n\nThis graphic appears in %s %s I am tracking:" % (
                inflector.number_to_words(len(stories)),
                inflector.plural("story", len(stories)),
            )

            for story in stories:
                reply += "\n" + "*<%s|%s>*" % (story.url, story.name.strip())

            # Get linger rate data for charting.

            all_graphics_rows = self.get_linger_data(team=team)
            all_graphics_median = NPRLingerRate.get_median(all_graphics_rows)

            attachments = [
                {
                    "fallback": slug + " update",
                    "color": "#eeeeee",
                    "title": slug,
                    "image_url": self.get_histogram_url(linger_rows, median),
                },
                {
                    "fallback": slug + " update",
                    "color": "#eeeeee",
                    "title": "How all graphics performed",
                    "image_url": self.get_histogram_url(all_graphics_rows, all_graphics_median),
                },
            ]

            return {"text": reply, "attachments": attachments}
Exemplo n.º 5
0
    def get_update_message(self, story):
        """
        Handle periodic checks on the metric.
        For each slug in the story, get the analytics we need, and craft
        an relevant update message.
        """
        story_slugs = story.slug_list()
        team = self.config.get_team_for_story(story)
        hours_since = TimeTools.hours_since(story.date)

        messages = []

        if len(story_slugs) > 1:
            # Some stories have many slugs.
            # We break out the stats into a nice little grid so they're
            # easier to read.
            message = (
                "%s hours in and here's what I know about the graphics on _%s_:"
            ) % (hours_since, story.name)

            fields = []
            for slug in story_slugs:
                stats = self.get_stats_for_slug(team=team, slug=slug)
                if stats:
                    fields.append({
                        "title": slug,
                        "value": stats['time_text'],
                        "short": True
                    })
            attachments = [{
                "fallback": story.name + " update",
                "color": "#eeeeee",
                "title": story.name,
                "title_link": story.url,
                "fields": fields
            }]

            return {'text': message, 'attachments': attachments}

        else:
            # For stories with only one slug, we have a slightly different
            # message:
            stats = self.get_stats_for_slug(team=team, slug=story_slugs[0])
            if stats:
                message = "%s hours in, *%s users* have spent a median *%s* on _%s_ (`%s`)" % (
                    hours_since, stats['people'], stats['time_text'],
                    story.name, story_slugs[0])

                return {'text': message}
Exemplo n.º 6
0
    def get_update_message(self, story):
        """
        Handle periodic checks on the metric.
        For each slug in the story, get the analytics we need, and craft
        an relevant update message.
        """
        story_slugs = story.slug_list()
        team = self.config.get_team_for_story(story)
        hours_since = TimeTools.hours_since(story.date)

        messages = []

        if len(story_slugs) > 1:
            # Some stories have many slugs.
            # We break out the stats into a nice little grid so they're
            # easier to read.
            message = ("%s hours in and here's what I know about the graphics on _%s_:") % (hours_since, story.name)

            fields = []
            for slug in story_slugs:
                stats = self.get_stats_for_slug(team=team, slug=slug)
                if stats:
                    fields.append({"title": slug, "value": stats["time_text"], "short": True})
            attachments = [
                {
                    "fallback": story.name + " update",
                    "color": "#eeeeee",
                    "title": story.name,
                    "title_link": story.url,
                    "fields": fields,
                }
            ]

            return {"text": message, "attachments": attachments}

        else:
            # For stories with only one slug, we have a slightly different
            # message:
            stats = self.get_stats_for_slug(team=team, slug=story_slugs[0])
            if stats:
                message = "%s hours in, *%s users* have spent a median *%s* on _%s_ (`%s`)" % (
                    hours_since,
                    stats["people"],
                    stats["time_text"],
                    story.name,
                    story_slugs[0],
                )

                return {"text": message}
Exemplo n.º 7
0
    def get_stats_for_slug(self, team, slug):
        """
        Return clean stats about how long people looked at a slug
        """
        linger_rows = self.get_linger_data(team=team, slug=slug)

        if not linger_rows:
            return False

        median = NPRLingerRate.get_median(linger_rows)
        return {
            'median': median,
            'people': "{:,}".format(median['total_people']),
            'time_text': TimeTools.humanist_time_bucket(median)
        }
Exemplo n.º 8
0
    def test_humanist_time_bucket(self):
        bucket = TimeTools.humanist_time_bucket({
            'minutes': 5,
            'seconds': 5
        })
        self.assertEqual(bucket, '5 minutes 5 seconds')

        bucket = TimeTools.humanist_time_bucket({
            'minutes': 0,
            'seconds': 1
        })
        self.assertEqual(bucket, '1 second')

        bucket = TimeTools.humanist_time_bucket({
            'minutes': 5,
            'seconds': 0
        })
        self.assertEqual(bucket, '5 minutes')

        bucket = TimeTools.humanist_time_bucket({
            'minutes': 1,
            'seconds': 1
        })
        self.assertEqual(bucket, '1 minute 1 second')
Exemplo n.º 9
0
    def get_stats_for_slug(self, team, slug):
        """
        Return clean stats about how long people looked at a slug
        """
        linger_rows = self.get_linger_data(team=team, slug=slug)

        if not linger_rows:
            return False

        median = NPRLingerRate.get_median(linger_rows)
        return {
            "median": median,
            "people": "{:,}".format(median["total_people"]),
            "time_text": TimeTools.humanist_time_bucket(median),
        }
Exemplo n.º 10
0
def handle_linger_update(message):
    if 'doing' not in message.body['text']:
        return

    m = GRUBER_URLINTEXT_PAT.findall(message.body['text'])

    if not m[0]:
        return

    url = str(m[0][0])
    url = url.replace('&amp;', '&')
    logger.info("Looking for url %s" % url)

    try:
        story = Story.select().where(Story.url == url).get()
    except:
        message.reply("Sorry, I don't have stats for %s" % url)
        return

    story_time_bucket = story.time_bucket()
    stats_per_slug = analytics.get_linger_data_for_story(story)

    if len(stats_per_slug) is not 0:
        reply = ("Here's what I know about the graphics on _%s_:") % (
            story.name.strip())

        fields = []
        for stat in stats_per_slug:
            time = TimeTools.humanist_time_bucket(stat['stats'])
            fields.append({
                "title": stat['slug'],
                "value": time,
                "short": True
            })

        attachments = [{
            "fallback": story.name + " update",
            "color": "#eeeeee",
            "title": story.name,
            "title_link": story.url,
            "fields": fields
        }]

        # Use send_message instead of message.reply, otherwise we lose
        # the bot icon.
        slackTools.send_message(message.body['channel'], reply, attachments)
Exemplo n.º 11
0
    def handle_slug_inquiry(self, message):
        """
        Respond to an inquiry about the slug with stats and charts
        """
        match = re.search(self.SLUG_SEARCH_REGEX, message.body['text'])
        slug = match.group(1)

        if slug:

            # Try to match the story to a slug to accurately get a team
            # The Google Analytics property ID comes from the team config
            # We use the default team if none is found
            stories = Story.select().where(Story.slug.contains(slug))
            team = self.config.get_team_for_stories(stories)

            linger_rows = self.get_linger_data(team=team, slug=slug)

            if not linger_rows:
                return {
                    'text':
                    "Sorry, I wasn't able to find linger rate stats for %s" %
                    slug
                }

            median = NPRLingerRate.get_median(linger_rows)
            print "Got median"
            print median
            people = "{:,}".format(median['total_people'])
            time_text = TimeTools.humanist_time_bucket(median)

            reply = u"*%s* people spent a median *%s* on `%s`." % (
                people, time_text, slug)

            reply += '\n\nThis graphic appears in %s %s I am tracking:' % (
                inflector.number_to_words(
                    len(stories)), inflector.plural('story', len(stories)))

            for story in stories:
                reply += '\n' + '*<%s|%s>*' % (story.url, story.name.strip())

            # Get linger rate data for charting.

            all_graphics_rows = self.get_linger_data(team=team)
            all_graphics_median = NPRLingerRate.get_median(all_graphics_rows)

            attachments = [{
                "fallback":
                slug + " update",
                "color":
                "#eeeeee",
                "title":
                slug,
                "image_url":
                self.get_histogram_url(linger_rows, median)
            }, {
                "fallback":
                slug + " update",
                "color":
                "#eeeeee",
                "title":
                "How all graphics performed",
                "image_url":
                self.get_histogram_url(all_graphics_rows, all_graphics_median)
            }]

            return {'text': reply, 'attachments': attachments}
Exemplo n.º 12
0
 def time_bucket(self):
     return TimeTools.time_bucket(self.date)
Exemplo n.º 13
0
def handle_slug_question(message):
    m = re.search(LINGER_RATE_REGEX, message.body['text'])

    if not m:
        return

    slug = m.group(1)

    if slug:
        median = analytics.get_linger_rate(slug)
        stories = Story.select().where(Story.slug.contains(slug))

        message.reply("Ok! I'm looking up %s. This may take a second." % slug)

        if median:
            people = "{:,}".format(median['total_people'])
            time_text = TimeTools.humanist_time_bucket(median)
            reply = u"*%s* people spent a median *%s* on `%s`." % (
                people, time_text, slug)

            # List the stories this slug appears on
            reply += '\n\nThis graphic appears in %s %s:' % (
                inflector.number_to_words(
                    len(stories)), inflector.plural('story', len(stories)))

            for story in stories:
                reply += '\n' + '*<%s|%s>*' % (story.url, story.name.strip())

            # Get linger rate data
            linger_rows = analytics.get_linger_rows(slug)
            linger_histogram_url = ChartTools.linger_histogram_link(
                linger_rows, median)

            all_graphics_rows = analytics.get_linger_rows()
            all_graphics_median = analytics.get_linger_rate()
            all_histogram = ChartTools.linger_histogram_link(
                all_graphics_rows, all_graphics_median)

            attachments = [{
                "fallback": slug + " update",
                "color": "#eeeeee",
                "title": slug,
                "image_url": linger_histogram_url
            }, {
                "fallback": slug + " update",
                "color": "#eeeeee",
                "title": "How all graphics performed",
                "image_url": all_histogram
            }]

            # Get scroll data, if any.
            scroll_depth_rows = analytics.get_depth_rate(slug)
            if scroll_depth_rows:
                scroll_histogram_url = ChartTools.scroll_histogram_link(
                    scroll_depth_rows)

                if stories[0].screenshot:
                    scroll_histogram_url = ChartTools.add_screenshot_to_chart(
                        stories[0].screenshot, scroll_histogram_url)

                attachments.append({
                    "fallback": slug + " update",
                    "color": "#eeeeee",
                    "title": "How far down did people scroll?",
                    "image_url": scroll_histogram_url
                })

            slackTools.send_message(message.body['channel'],
                                    reply,
                                    attachments,
                                    unfurl_links=False)

        else:
            message.reply("I wasn't able to figure out the linger rate of %s" %
                          slug)
Exemplo n.º 14
0
 def time_bucket(self):
     return TimeTools.time_bucket(self.article_posted)
Exemplo n.º 15
0
 def time_bucket(self):
     return TimeTools.time_bucket(self.date)