Пример #1
0
def listen(req, episode_id):
    ep = get_object_or_404(PodcastEpisode, id=episode_id)
    if not analyze.is_bot(req) and req.method == 'GET':
        browser, device, os = analyze.get_device_type(req)
        analytics_log.write('listen', {
            'podcast': unicode(ep.podcast.id),
            'episode': unicode(ep.id),
            'source': 'embed' if req.GET.get('embed') else 'direct',
            'profile': {
                'ip': analyze.get_request_ip(req),
                'ua': req.META.get('HTTP_USER_AGENT'),
                'browser': browser,
                'device': device,
                'os': os,
            },
        }, req=req)

    return redirect(_asset(ep.audio_url))
Пример #2
0
def feed(req, podcast_slug):
    pod = get_object_or_404(Podcast, slug=podcast_slug)

    if pod.rss_redirect:
        return redirect(pod.rss_redirect, permanent=True)

    items = []
    episodes = pod.get_episodes()
    is_demo = UserSettings.get_from_user(pod.owner).plan == plans.PLAN_DEMO

    for ep in episodes:
        ep_url = _asset(ep.audio_url + '?x-source=rss&x-episode=%s' % str(ep.id))

        md_desc = ep.get_html_description(is_demo=is_demo)

        explicit_tag = ''
        if ep.explicit_override != PodcastEpisode.EXPLICIT_OVERRIDE_CHOICE_NONE:
            explicit_tag = '<itunes:explicit>%s</itunes:explicit>' % (
                'yes' if ep.explicit_override == PodcastEpisode.EXPLICIT_OVERRIDE_CHOICE_EXPLICIT else 'clean')

        items.append('\n'.join([
            '<item>',
                '<title>%s</title>' % escape(ep.title),
                '<description><![CDATA[%s]]></description>' % md_desc,
                '<link>%s</link>' % escape(ep_url),
                '<guid isPermaLink="false">https://pinecast.com/guid/%s</guid>' % escape(str(ep.id)),
                '<pubDate>%s</pubDate>' % formatdate(time.mktime(ep.publish.timetuple())),
                explicit_tag,
                '<itunes:author>%s</itunes:author>' % escape(pod.author_name),
                '<itunes:subtitle>%s</itunes:subtitle>' % escape(ep.subtitle),
                '<itunes:image href=%s />' % quoteattr(_asset(ep.image_url)),
                '<itunes:duration>%s</itunes:duration>' % escape(ep.formatted_duration()),
                '<enclosure url=%s length=%s type=%s />' % (
                    quoteattr(ep_url), quoteattr(str(ep.audio_size)), quoteattr(ep.audio_type)),
                ('<dc:copyright>%s</dc:copyright>' % escape(ep.copyright)) if ep.copyright else '',
                ('<dc:rights>%s</dc:rights>' % escape(ep.license)) if ep.license else '',
            '</item>',
        ]))

    categories = sorted([c.category for c in pod.podcastcategory_set.all()], key=lambda c: len(c))
    category_map = {}
    for cat in categories:
        spl = cat.split('/')
        cursor = category_map
        for i in spl:
            cursor.setdefault(i, {})
            cursor = cursor[i]

    def render_cat(c):
        for k, v in c.items():
            if not v:
                yield '<itunes:category text=%s />' % quoteattr(k)
            else:
                yield '<itunes:category text=%s>%s</itunes:category>' % (
                    quoteattr(k), '\n'.join(render_cat(v)))

    content = [
        '<?xml version="1.0" encoding="UTF-8"?>',
        '<rss xmlns:atom="http://www.w3.org/2005/Atom"',
        '     xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"',
        '     xmlns:dc="http://purl.org/dc/elements/1.1/"',
        '     version="2.0">',
        '<channel>',
            '<title>%s</title>' % escape(pod.name),
            '<link>%s</link>' % escape(pod.homepage),
            '<language>%s</language>' % escape(pod.language),
            '<copyright>%s</copyright>' % escape(pod.copyright),
            '<generator>Pinecast (https://pinecast.com)</generator>',
            ('<itunes:subtitle>%s</itunes:subtitle>' % escape(pod.subtitle)) if pod.subtitle else '',
            '<itunes:author>%s</itunes:author>' % escape(pod.author_name),
            '<description><![CDATA[%s]]></description>' % pod.description,
            '<itunes:owner>',
                '<itunes:name>%s</itunes:name>' % escape(pod.author_name),
                '<itunes:email>%s</itunes:email>' % escape(pod.owner.email),
            '</itunes:owner>',
            '<itunes:explicit>%s</itunes:explicit>' % ('yes' if pod.is_explicit else 'no'),
            '<itunes:image href=%s />' % quoteattr(_asset(pod.cover_image)),
            '\n'.join(render_cat(category_map)),
            '\n'.join(items),
        '</channel>',
        '</rss>',
    ]
    if UserSettings.get_from_user(pod.owner).plan == plans.PLAN_DEMO:
        if len(episodes) > 10:
            content.append('<!-- This feed is truncated because the owner is not a paid customer. -->')
        else:
            content.append('<!-- This feed will be truncated at 10 items because the owner is not a paid customer. -->')

    if not analyze.is_bot(req):
        browser, device, os = analyze.get_device_type(req)
        analytics_log.write('subscribe', {
            'id': analyze.get_request_hash(req),
            'podcast': unicode(pod.id),
            'profile': {
                'ip': analyze.get_request_ip(req),
                'ua': req.META.get('HTTP_USER_AGENT'),
                'browser': browser,
                'device': device,
                'os': os,
            },
        }, req=req)

    resp = HttpResponse('\n'.join(c for c in content if c), content_type='application/rss+xml')
    resp.setdefault('Cache-Control', 'public, max-age=120')
    return resp
Пример #3
0
def log(req):
    if req.GET.get("access") != settings.LAMBDA_ACCESS_SECRET:
        return HttpResponse(status=400)

    try:
        parsed = json.loads(req.POST.get("payload"))
    except Exception:
        return HttpResponse(status=400)

    ts_formats = ["[%d/%b/%Y:%H:%M:%S %z]", "[%d/%b/%Y:%H:%M:%S +0000]", "[%d/%m/%Y:%H:%M:%S +0000]"]  # For cdn

    listens_to_log = []

    # Make sure we don't iterate over something that's not iterable
    try:
        assert list(parsed)
    except Exception:
        return HttpResponse(status=400)

    for blob in parsed:
        fr = FakeReq(blob)
        if analyze.is_bot(fr):
            continue

        try:
            ep = PodcastEpisode.objects.get(id=blob["episode"])
        except PodcastEpisode.DoesNotExist:
            continue

        raw_ts = blob.get("ts")
        ts = None
        for f in ts_formats:
            try:
                ts = datetime.datetime.strptime(raw_ts, f)
                break
            except ValueError:
                continue

        # If we couldn't parse the timestamp, whatever.
        if not ts:
            rollbar.report_message("Got unparseable date: %s" % raw_ts, "error")
            continue

        browser, device, os = analyze.get_device_type(fr)
        print "Logging record of listen for %s" % unicode(ep.id)

        listens_to_log.append(
            {
                "podcast": unicode(ep.podcast.id),
                "episode": unicode(ep.id),
                "source": blob.get("source"),
                "profile": {
                    "ip": blob.get("ip"),
                    "ua": blob.get("userAgent"),
                    "browser": browser,
                    "device": device,
                    "os": os,
                },
                "timestamp": ts.isoformat(),
            }
        )

    analytics_log.write_many("listen", listens_to_log)

    return HttpResponse(status=204)