Beispiel #1
0
def add_blog_post(req, podcast_slug):
    site = get_site(req, podcast_slug)

    if not payment_plans.minimum(
        UserSettings.get_from_user(site.podcast.owner).plan,
        payment_plans.FEATURE_MIN_BLOG):
        raise Http404()

    data = {'site': site}

    if not req.POST:
        return _pmrender(req, 'dashboard/sites/blog/page_new.html', data)

    try:
        naive_publish = datetime.datetime.strptime(req.POST.get('publish'), '%Y-%m-%dT%H:%M') # 2015-07-09T12:00
        adjusted_publish = naive_publish - UserSettings.get_from_user(req.user).get_tz_delta()
        post = SiteBlogPost(
            site=site,
            title=req.POST.get('title'),
            slug=req.POST.get('slug'),
            body=req.POST.get('body'),
            publish=adjusted_publish
        )
        post.save()
    except Exception as e:
        print e
        data.update(error=True, default=req.POST)
        return _pmrender(req, 'dashboard/sites/blog/page_new.html', data)
    else:
        return redirect('site_manage_blog', podcast_slug=podcast_slug)
Beispiel #2
0
def podcast_dashboard(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)

    tz = UserSettings.get_from_user(req.user).tz_offset

    total_listens = analytics_query.total_listens(pod)
    total_listens_this_week = analytics_query.total_listens_this_week(pod, tz)
    subscribers = analytics_query.total_subscribers(pod)

    data = {
        'podcast': pod,
        'episodes': pod.podcastepisode_set.order_by('-publish'),
        'analytics': {
            'total_listens': total_listens,
            'total_listens_this_week': total_listens_this_week,
            'subscribers': subscribers,
        },
        'next_milestone': next(x for x in constants.MILESTONES if x > total_listens),
        'previous_milestone': [x for x in constants.MILESTONES if x <= total_listens][-1] if total_listens > 0 else 0,
        'hit_first_milestone': total_listens > constants.MILESTONES[1],  # The first "real" milestone
        'is_still_importing': pod.is_still_importing(),

        'site': None,

        'LOCALES': constants.locales,
        'SITE_PAGE_TYPES': SitePage.PAGE_TYPES,
        'SITE_THEMES': Site.SITE_THEMES,

        'N_DESTINATIONS': NotificationHook.DESTINATIONS,
        'N_TRIGGERS': NotificationHook.TRIGGERS,
    }

    try:
        data['site'] = pod.site
    except Site.DoesNotExist:
        pass

    owner_uset = UserSettings.get_from_user(pod.owner)
    if payment_plans.minimum(owner_uset.plan, payment_plans.FEATURE_MIN_COMMENT_BOX):
        all_feedback = Feedback.objects.filter(podcast=pod)
        data['feedback_all'] = all_feedback
        data['feedback'] = all_feedback.filter(episode=None).order_by('-created')
        data['feedback_episodes'] = (all_feedback.exclude(episode=None)
            .annotate(Count('episode', distinct=True))
            .select_related('episode'))

    if payment_plans.minimum(owner_uset.plan, payment_plans.PLAN_PRO):
        sparkline_data = analytics_query.get_episode_sparklines(pod, tz)
        data['sparklines'] = sparkline_data

    if payment_plans.minimum(owner_uset.plan, payment_plans.FEATURE_MIN_NOTIFICATIONS):
        data['notifications'] = NotificationHook.objects.filter(podcast=pod)
        if req.GET.get('notification_sent'):
            data['notification_sent'] = True

    if payment_plans.minimum(owner_uset.plan, payment_plans.FEATURE_MIN_COLLABORATORS):
        data['collab_error'] = req.GET.get('collaberr')

    return _pmrender(req, 'dashboard/podcast/page_podcast.html', data)
Beispiel #3
0
def set_coupon(req):
    code = req.POST.get('coupon')
    try:
        coupon = stripe.Coupon.retrieve(code)
    except stripe.error.InvalidRequestError:
        return redirect(reverse('upgrade') + '?coupon_invalid')

    if not coupon.valid:
        return redirect(reverse('upgrade') + '?coupon_invalid')

    if 'owner_id' in coupon.metadata:
        us = UserSettings.get_from_user(req.user)
        if us.plan != payment_plans.PLAN_DEMO:
            return redirect(reverse('upgrade') + '?coupon_unavailable')

        try:
            cust = us.get_stripe_customer()
        except Exception:
            pass
        else:
            if len(stripe.Invoice.list(customer=cust.id, limit=1).data):
                return redirect(reverse('upgrade') + '?coupon_unavailable')

    req.session['coupon'] = code
    return redirect(reverse('upgrade') + '?coupon_applied')
Beispiel #4
0
def _pmrender(req, template, data=None):
    data = data or {}

    class DefaultEmptyDict(collections.defaultdict):
        def __init__(self):
            super(DefaultEmptyDict, self).__init__(lambda: '')

        def get(self, _, d=''):
            return d

    data.setdefault('settings', settings)
    data.setdefault('default', DefaultEmptyDict())
    data['sign'] = lambda x: signer.sign(x.encode('utf-8')).decode('utf-8') if x else x
    if not req.user.is_anonymous():
        data.setdefault('user', req.user)

        networks = set(req.user.network_set.filter(deactivated=False))
        data.setdefault('networks', networks)

        podcasts = set(req.user.podcast_set.all())
        podcasts |= set(Podcast.objects.filter(networks__in=networks))
        podcasts |= {
            x.podcast for x in
            Collaborator.objects.filter(collaborator=req.user).select_related('podcast')}

        data.setdefault('podcasts', list(podcasts))

        uset = UserSettings.get_from_user(req.user)
        data.setdefault('user_settings', uset)
        data.setdefault('tz_delta', uset.get_tz_delta())
        data.setdefault('max_upload_size', payment_plans.MAX_FILE_SIZE[uset.plan])

    data['is_admin'] = req.user.is_staff and bool(req.GET.get('admin'))

    return render(req, template, data)
Beispiel #5
0
    def get_html_description(self, is_demo=None):
        raw = self.description
        if is_demo is None:
            us = UserSettings.get_from_user(self.podcast.owner)
            is_demo = us.plan == payment_plans.PLAN_DEMO
        available_flags = self.podcast.get_available_flair_flags(flatten=True)

        if self.flair_tip_jar and FLAIR_TIP_JAR in available_flags:
            raw += "\n\nSupport %s by donating to the [tip jar](https://pinecast.com/payments/tips/%s)." % (
                self.podcast.name,
                self.podcast.slug,
            )

        if self.flair_site_link and FLAIR_SITE_LINK in available_flags:
            raw += "\n\nFind out more at [%s](http://%s.pinecast.co)." % (self.podcast.name, self.podcast.slug)

        if self.flair_feedback and FLAIR_FEEDBACK in available_flags:
            prompt = self.get_feedback_prompt()
            fb_url = "https://pinecast.com%s" % reverse(
                "ep_comment_box", podcast_slug=self.podcast.slug, episode_id=str(self.id)
            )
            raw += "\n\n%s [%s](%s)" % (prompt, fb_url, fb_url)

        if is_demo or self.flair_powered_by and FLAIR_SITE_LINK in available_flags:
            raw += "\n\nThis podcast is powered by " "[Pinecast](https://pinecast.com)."

        markdown = gfm.markdown(raw)
        return sanitize(markdown)
Beispiel #6
0
def new_network(req):
    uset = UserSettings.get_from_user(req.user)
    if not plans.minimum(uset.plan, plans.FEATURE_MIN_NETWORK):
        return _pmrender(req, 'dashboard/network/page_new_upgrade.html')

    if not req.POST:
        return _pmrender(req, 'dashboard/network/page_new.html')

    try:
        net = Network(
            name=req.POST.get('name'),
            owner=req.user,
            image_url=signer.unsign(req.POST.get('image-url')) if req.POST.get('image-url') else None
        )
        net.save()
        net.members.add(req.user)
        net.save()
    except Exception as e:
        print e
        return _pmrender(req,
                         'dashboard/network/page_new.html',
                         {'error': ugettext('Error while saving network details'),
                          'default': req.POST})

    return redirect('network_dashboard', network_id=net.id)
Beispiel #7
0
def edit_site(req, podcast_slug):
    site = get_site(req, podcast_slug)
    try:
        site.theme = req.POST.get('theme')
        site.cover_image_url = signer.unsign(
            req.POST.get('cover-url')) if req.POST.get('cover-url') else None
        site.logo_url = signer.unsign(
            req.POST.get('logo-url')) if req.POST.get('logo-url') else None
        site.analytics_id = req.POST.get('analytics_id')
        site.itunes_url = req.POST.get('itunes_url')
        site.stitcher_url = req.POST.get('stitcher_url')
        site.show_itunes_banner = req.POST.get('show_itunes_banner') == 'true'
        site.custom_css = req.POST.get('custom_css')
        site.custom_cname = req.POST.get('custom_cname')

        us = UserSettings.get_from_user(site.podcast.owner)
        if payment_plans.minimum(us.plan, payment_plans.FEATURE_MIN_BLOG):
            site.disqus_url = req.POST.get('disqus_url')
        if payment_plans.minimum(us.plan,
                                 payment_plans.FEATURE_MIN_SITE_FAVICON):
            site.favicon_url = signer.unsign(req.POST.get(
                'favicon-url')) if req.POST.get('favicon-url') else None

        site.save()
    except Exception as e:
        return redirect(
            reverse('podcast_dashboard', podcast_slug=podcast_slug) +
            '?error=true#settings,site-options')
    else:
        return redirect(
            reverse('podcast_dashboard', podcast_slug=podcast_slug) +
            '#settings,site-options')
Beispiel #8
0
def podcast_top_episodes(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)
    owner_uset = UserSettings.get_from_user(pod.owner)
    if not payment_plans.minimum(owner_uset.plan, payment_plans.FEATURE_MIN_COMMENT_BOX):
        return _pmrender(req, 'dashboard/podcast/page_top_episodes_upgrade.html', {'podcast': pod})

    with analytics_query.AsyncContext() as async_ctx:
        top_ep_data_query = analytics_query.get_top_episodes(unicode(pod.id), async_ctx)
    top_ep_data = top_ep_data_query()

    ep_ids = [x['episode'] for x in top_ep_data]
    episodes = PodcastEpisode.objects.filter(id__in=ep_ids)
    mapped = {unicode(ep.id): ep for ep in episodes}

    # This step is necessary to filter out deleted episodes
    top_ep_data = [x for x in top_ep_data if x['episode'] in mapped]

    # Sort the top episode data descending
    top_ep_data = reversed(sorted(top_ep_data, key=lambda x: x['podcast']))

    data = {
        'podcast': pod,
        'episodes': mapped,
        'top_ep_data': top_ep_data,
    }
    return _pmrender(req, 'dashboard/podcast/page_top_episodes.html', data)
Beispiel #9
0
def edit_blog_post(req, podcast_slug, post_slug):
    site = get_site(req, podcast_slug)
    post = get_object_or_404(SiteBlogPost, site=site, slug=post_slug)

    if not req.POST:
        return _pmrender(req, 'dashboard/sites/blog/page_edit.html', {
            'site': site,
            'post': post
        })
    try:
        naive_publish = datetime.datetime.strptime(
            req.POST.get('publish', '').split('.')[0],
            '%Y-%m-%dT%H:%M:%S')  # 2015-07-09T12:00
        adjusted_publish = naive_publish - UserSettings.get_from_user(
            req.user).get_tz_delta()
        post.title = req.POST.get('title')
        post.slug = req.POST.get('slug')
        post.body = req.POST.get('body')
        post.publish = adjusted_publish
        post.disable_comments = req.POST.get('disable_comments') == 'true'
        post.save()
    except Exception as e:
        data.update(error=True, default=req.POST)
        return _pmrender(req, 'dashboard/sites/blog/page_edit.html', data)
    else:
        return redirect(
            reverse('podcast_dashboard', podcast_slug=podcast_slug) +
            '#site,blog')
Beispiel #10
0
def send_tip(req, podcast_slug):
    pod = get_object_or_404(Podcast, slug=podcast_slug)

    try:
        amount = int(float(req.POST.get('amount')) / 100.0) * 100
        if amount < 100:
            return {'error': ugettext('Tips less than $1 are not allowed.')}
    except Exception:
        return HttpResponse(status=400)

    tip_type = req.POST.get('type')

    owner_us = UserSettings.get_from_user(pod.owner)
    if owner_us.plan == PLAN_DEMO and tip_type == 'subscribe':
        return {'error': ugettext('You cannot have recurring tips for free podcasts.')}

    if amount > PLAN_TIP_LIMITS[owner_us.plan]:
        return {'error': ugettext('That tip is too large for %s') % pod.name}


    if tip_type == 'charge':
        return _send_one_time_tip(req, pod, owner_us, amount)
    elif tip_type == 'subscribe':
        return _auth_subscription(req, pod, amount)
    else:
        return HttpResponse(status=400)
Beispiel #11
0
def add_blog_post(req, podcast_slug):
    site = get_site(req, podcast_slug)

    if not payment_plans.minimum(
            UserSettings.get_from_user(site.podcast.owner).plan,
            payment_plans.FEATURE_MIN_BLOG):
        raise Http404()

    try:
        publis_parsed = datetime.datetime.strptime(
            req.POST.get('publish', '').split('.')[0], '%Y-%m-%dT%H:%M:%S')
        post = SiteBlogPost(
            site=site,
            title=req.POST.get('title'),
            slug=req.POST.get('slug'),
            body=req.POST.get('body'),
            publish=publis_parsed,
            disable_comments=req.POST.get('disable_comments') == 'true')
        post.save()
    except Exception as e:
        print(e)
        return redirect(
            reverse('podcast_dashboard', podcast_slug=podcast_slug) +
            '?error=sblog#site,blog')
    else:
        return redirect(
            reverse('podcast_dashboard', podcast_slug=podcast_slug) +
            '#site,blog')
Beispiel #12
0
def tip_flow(req, podcast_slug):
    pod = get_object_or_404(Podcast, slug=podcast_slug)
    us = UserSettings.get_from_user(pod.owner)
    if not us.stripe_payout_managed_account:
        if pod.homepage:
            return redirect(pod.homepage)
        else:
            raise Http404()

    recurring_tip = None
    pay_session = req.session.get('pay_session')
    tipper = None
    if pay_session:
        tipper = TipUser.objects.get(id=pay_session, verified=True)
        try:
            recurring_tip = RecurringTip.objects.get(
                podcast=pod, tipper=tipper, deactivated=False)
        except Exception as e:
            pass

    ctx = {'error': req.GET.get('error'),
           'recurring_tip': recurring_tip,
           'podcast': pod,
           'tipper': tipper}

    return _pmrender(req, 'payments/tip_jar/main.html', ctx)
Beispiel #13
0
    def get_html_description(self, is_demo=None):
        raw = self.description
        if is_demo is None:
            us = UserSettings.get_from_user(self.podcast.owner)
            is_demo = us.plan == payment_plans.PLAN_DEMO
        available_flags = self.podcast.get_available_flair_flags(flatten=True)

        if (self.flair_tip_jar and FLAIR_TIP_JAR in available_flags):
            raw += '\n\nSupport %s by donating to the [tip jar](https://pinecast.com/payments/tips/%s).' % (
                self.podcast.name, self.podcast.slug)

        if (self.flair_site_link and FLAIR_SITE_LINK in available_flags):
            raw += '\n\nFind out more at [%s](http://%s.pinecast.co).' % (
                self.podcast.name, self.podcast.slug)

        if (self.flair_feedback and FLAIR_FEEDBACK in available_flags):
            prompt = self.get_feedback_prompt()
            fb_url = 'https://pinecast.com%s' % reverse(
                'ep_comment_box',
                podcast_slug=self.podcast.slug,
                episode_id=str(self.id))
            raw += '\n\n%s [%s](%s)' % (prompt, fb_url, fb_url)

        if (is_demo or self.flair_powered_by
                and FLAIR_SITE_LINK in available_flags):
            raw += ('\n\nThis podcast is powered by '
                    '[Pinecast](https://pinecast.com).')

        markdown = gfm.markdown(raw)
        return sanitize(markdown)
Beispiel #14
0
def send_tip(req, podcast_slug):
    pod = get_object_or_404(Podcast, slug=podcast_slug)

    try:
        amount = int(float(req.POST.get('amount')) / 100.0) * 100
        if amount < 100:
            return {'error': ugettext('Tips less than $1 are not allowed.')}
    except Exception:
        return HttpResponse(status=400)

    tip_type = req.POST.get('type')

    owner_us = UserSettings.get_from_user(pod.owner)
    if owner_us.plan == PLAN_DEMO and tip_type == 'subscribe':
        return {'error': ugettext('You cannot have recurring tips for free podcasts.')}

    if amount > PLAN_TIP_LIMITS[owner_us.plan]:
        return {'error': ugettext('That tip is too large for %s') % pod.name}


    if tip_type == 'charge':
        return _send_one_time_tip(req, pod, owner_us, amount)
    elif tip_type == 'subscribe':
        return _auth_subscription(req, pod, amount)
    else:
        return HttpResponse(status=400)
Beispiel #15
0
def new_site(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)

    if not payment_plans.minimum(
            UserSettings.get_from_user(pod.owner).plan,
            payment_plans.FEATURE_MIN_SITES):
        raise Http404()

    try:
        site = Site(
            podcast=pod,
            theme=req.POST.get('theme'),
            cover_image_url=signer.unsign(req.POST.get('cover-url'))
            if req.POST.get('cover-url') else None,
            logo_url=signer.unsign(req.POST.get('logo-url'))
            if req.POST.get('logo-url') else None,
            analytics_id=req.POST.get('analytics_id'),
            itunes_url=req.POST.get('itunes_url'),
            stitcher_url=req.POST.get('stitcher_url'),
            show_itunes_banner=req.POST.get('show_itunes_banner') == 'true')
        site.save()
    except Exception as e:
        return redirect(
            reverse('podcast_dashboard', podcast_slug=podcast_slug) +
            '?error=true#site')
    else:
        return redirect(
            reverse('podcast_dashboard', podcast_slug=podcast_slug) + '#site')
Beispiel #16
0
def podcast_dashboard(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)

    with analytics_query.AsyncContext() as async_ctx:
        total_listens = analytics_query.total_listens(pod, async_ctx)
        total_listens_this_week = analytics_query.total_listens_this_week(pod, async_ctx)
        subscribers = analytics_query.total_subscribers(pod, async_ctx)

    listens = total_listens()

    data = {
        'podcast': pod,
        'episodes': pod.podcastepisode_set.order_by('-publish'),
        'analytics': {
            'total_listens': listens,
            'total_listens_this_week': total_listens_this_week(),
            'subscribers': subscribers(),
        },
        'next_milestone': next(x for x in MILESTONES if x > listens),
        'previous_milestone': [x for x in MILESTONES if x <= listens][-1] if listens else 0,
        'hit_first_milestone': listens > MILESTONES[1],  # The first "real" milestone
        'is_still_importing': pod.is_still_importing(),
    }

    owner_uset = UserSettings.get_from_user(pod.owner)
    if payment_plans.minimum(owner_uset.plan, payment_plans.FEATURE_MIN_COMMENT_BOX):
        data['feedback'] = Feedback.objects.filter(podcast=pod, episode=None).order_by('-created')

    return _pmrender(req, 'dashboard/podcast/page_podcast.html', data)
Beispiel #17
0
def podcast_top_episodes(req, pod):
    timeframe = req.GET.get('timeframe')
    if not timeframe:
        return None

    tz = UserSettings.get_from_user(req.user).tz_offset
    top_ep_data = query.get_top_episodes(str(pod.id), timeframe, tz)
    episodes = PodcastEpisode.objects.filter(id__in=list(top_ep_data.keys()))
    mapped = {str(ep.id): ep for ep in episodes}

    # This step is necessary to filter out deleted episodes, since deleted episodes
    # are not removed from the analytics data.
    top_ep_data = {k: v for k, v in top_ep_data.items() if k in mapped}

    # Sort the top episode data descending
    return [[ugettext('Episode'), ugettext('Count')]] + [[
        {
            'href':
            reverse('podcast_episode', podcast_slug=pod.slug,
                    episode_id=ep_id),
            'title':
            mapped[ep_id].title,
        },
        count,
    ] for ep_id, count in list(
        reversed(sorted(top_ep_data.items(), key=lambda x: x[1])))[:25]]
Beispiel #18
0
def podcast_geochart(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)
    owner_uset = UserSettings.get_from_user(pod.owner)
    if not payment_plans.minimum(owner_uset.plan, payment_plans.FEATURE_MIN_GEOANALYTICS):
        return _pmrender(req, 'dashboard/podcast/page_geochart_upgrade.html', {'podcast': pod})

    return _pmrender(req, 'dashboard/podcast/page_geochart.html', {'podcast': pod})
Beispiel #19
0
def new_site(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)

    if not payment_plans.minimum(
        UserSettings.get_from_user(pod.owner).plan,
        payment_plans.FEATURE_MIN_SITES):
        raise Http404()

    data = {
        'podcast': pod,
        'themes': Site.SITE_THEMES,
    }

    if not req.POST:
        return _pmrender(req, 'dashboard/sites/page_new.html', data)

    try:
        site = Site(
            podcast=pod,
            theme=req.POST.get('theme'),
            cover_image_url=signer.unsign(req.POST.get('cover-url')) if req.POST.get('cover-url') else None,
            logo_url=signer.unsign(req.POST.get('logo-url')) if req.POST.get('logo-url') else None,
            analytics_id=req.POST.get('analytics_id'),
            itunes_url=req.POST.get('itunes_url'),
            stitcher_url=req.POST.get('stitcher_url')
        )
        site.save()
    except Exception as e:
        print e
        data.update(error=True, default=req.POST)
        return _pmrender(req, 'dashboard/sites/page_new.html', data)
    else:
        return redirect('site_options', podcast_slug=podcast_slug)
Beispiel #20
0
 def get_episodes(self):
     episodes = self.podcastepisode_set.filter(publish__lt=datetime.datetime.now(), awaiting_import=False).order_by(
         "-publish"
     )
     if UserSettings.get_from_user(self.owner).plan == payment_plans.PLAN_DEMO:
         episodes = episodes[:10]
     return episodes
Beispiel #21
0
def new_podcast(req):
    uset = UserSettings.get_from_user(req.user)
    if payment_plans.has_reached_podcast_limit(uset):
        return _pmrender(req, 'dashboard/podcast/page_new_upgrade.html')

    ctx = {'PODCAST_CATEGORIES': json.dumps(list(CATEGORIES))}

    if not req.POST:
        return _pmrender(req, 'dashboard/podcast/page_new.html', ctx)

    try:
        pod = Podcast(
            slug=req.POST.get('slug'),
            name=req.POST.get('name'),
            subtitle=req.POST.get('subtitle'),
            cover_image=signer.unsign(req.POST.get('image-url')),
            description=req.POST.get('description'),
            is_explicit=req.POST.get('is_explicit', 'false') == 'true',
            homepage=req.POST.get('homepage'),
            language=req.POST.get('language'),
            copyright=req.POST.get('copyright'),
            author_name=req.POST.get('author_name'),
            owner=req.user)
        pod.save()
        # TODO: The following line can throw an exception and create a
        # duplicate podcast if something has gone really wrong
        pod.set_category_list(req.POST.get('categories'))
    except Exception as e:
        ctx.update(default=req.POST, error=True)
        return _pmrender(req, 'dashboard/podcast/page_new.html', ctx)
    return redirect('podcast_dashboard', podcast_slug=pod.slug)
Beispiel #22
0
def _pmrender(req, template, data=None):
    data = data or {}

    class DefaultEmptyDict(collections.defaultdict):
        def __init__(self):
            super(DefaultEmptyDict, self).__init__(lambda: '')

        def get(self, _, d=''):
            return d

    data.setdefault('settings', settings)
    data.setdefault('default', DefaultEmptyDict())
    data['sign'] = lambda x: signer.sign(x) if x else x
    if not req.user.is_anonymous():
        data.setdefault('user', req.user)

        networks = req.user.network_set.filter(deactivated=False)
        data.setdefault('networks', networks)

        podcasts = set(req.user.podcast_set.all())
        for network in networks:
            for p in network.podcast_set.all():
                podcasts.add(p)
        data.setdefault('podcasts', podcasts)

        uset = UserSettings.get_from_user(req.user)
        data.setdefault('user_settings', uset)
        data.setdefault('tz_delta', uset.get_tz_delta())
        data.setdefault('max_upload_size', payment_plans.MAX_FILE_SIZE[uset.plan])

    return render(req, template, data)
Beispiel #23
0
def _pmrender(req, template, data=None):
    data = data or {}

    class DefaultEmptyDict(collections.defaultdict):
        def __init__(self):
            super(DefaultEmptyDict, self).__init__(lambda: '')

        def get(self, _, d=''):
            return d

    data.setdefault('settings', settings)
    data.setdefault('default', DefaultEmptyDict())
    data['sign'] = lambda x: signer.sign(x.encode('utf-8')).decode('utf-8') if x else x
    if not req.user.is_anonymous():
        data.setdefault('user', req.user)

        networks = req.user.network_set.filter(deactivated=False)
        data.setdefault('networks', networks)

        podcasts = list(set(
            req.user.podcast_set.all() | Podcast.objects.filter(networks__in=networks)))
        data.setdefault('podcasts', podcasts)

        uset = UserSettings.get_from_user(req.user)
        data.setdefault('user_settings', uset)
        data.setdefault('tz_delta', uset.get_tz_delta())
        data.setdefault('max_upload_size', payment_plans.MAX_FILE_SIZE[uset.plan])

    data['is_admin'] = req.user.is_staff and bool(req.GET.get('admin'))

    return render(req, template, data)
Beispiel #24
0
def tip_flow(req, podcast_slug):
    pod = get_object_or_404(Podcast, slug=podcast_slug)
    us = UserSettings.get_from_user(pod.owner)
    if not us.stripe_payout_managed_account:
        if pod.homepage:
            return redirect(pod.homepage)
        else:
            raise Http404()

    recurring_tip = None
    pay_session = req.session.get('pay_session')
    tipper = None
    if pay_session:
        tipper = TipUser.objects.get(id=pay_session, verified=True)
        try:
            recurring_tip = RecurringTip.objects.get(
                podcast=pod, tipper=tipper, deactivated=False)
        except Exception as e:
            pass

    ctx = {'error': req.GET.get('error'),
           'recurring_tip': recurring_tip,
           'podcast': pod,
           'tipper': tipper}

    return _pmrender(req, 'payments/tip_jar/main.html', ctx)
Beispiel #25
0
def importer(req):
    uset = UserSettings.get_from_user(req.user)
    if uset.plan == plans.PLAN_DEMO:
        return _pmrender(req, 'dashboard/page_importer_upgrade.html', {'reached_limit': False})
    elif plans.has_reached_podcast_limit(uset):
        return _pmrender(req, 'dashboard/page_importer_upgrade.html', {'reached_limit': True})
    else:
        return _pmrender(req, 'dashboard/page_importer.html')
Beispiel #26
0
 def get_subscription(self):
     us = UserSettings.get_from_user(self.podcast.owner)
     stripe_account = us.stripe_payout_managed_account
     try:
         return stripe.Subscription.retrieve(
             self.stripe_subscription_id, stripe_account=stripe_account)
     except stripe.error.InvalidRequestError:
         return None
Beispiel #27
0
 def get_subscription(self):
     us = UserSettings.get_from_user(self.podcast.owner)
     stripe_account = us.stripe_payout_managed_account
     try:
         return stripe.Subscription.retrieve(self.stripe_subscription_id,
                                             stripe_account=stripe_account)
     except stripe.error.InvalidRequestError:
         return None
Beispiel #28
0
def episode_geochart(req, podcast_slug, episode_id):
    pod = get_podcast(req, podcast_slug)
    owner_uset = UserSettings.get_from_user(pod.owner)
    ep = get_object_or_404(PodcastEpisode, podcast=pod, id=episode_id)
    if not payment_plans.minimum(owner_uset.plan, payment_plans.FEATURE_MIN_GEOANALYTICS_EP):
        return _pmrender(req, 'dashboard/episode/page_geochart_upgrade.html', {'podcast': pod, 'episode': ep})

    return _pmrender(req, 'dashboard/episode/page_geochart.html', {'podcast': pod, 'episode': ep})
Beispiel #29
0
 def get_episodes(self):
     episodes = self.get_all_episodes_raw().filter(
         publish__lt=round_now(),
         awaiting_import=False).order_by('-publish')
     us = UserSettings.get_from_user(self.owner)
     if us.plan == payment_plans.PLAN_DEMO:
         episodes = episodes[:10]
     return episodes
Beispiel #30
0
    def get_domain(self):
        if not self.custom_cname:
            return self.get_subdomain()
        us = UserSettings.get_from_user(self.podcast.owner)
        if not minimum(us.plan, FEATURE_MIN_SITES):
            return self.get_subdomain()

        return "http://%s" % self.custom_cname
Beispiel #31
0
    def get_domain(self):
        if not self.custom_cname:
            return self.get_subdomain()
        us = UserSettings.get_from_user(self.podcast.owner)
        if not minimum(us.plan, FEATURE_MIN_SITES):
            return self.get_subdomain()

        return 'http://%s' % self.custom_cname
Beispiel #32
0
def upgrade(req):
    us = UserSettings.get_from_user(req.user)
    customer = us.get_stripe_customer()

    ctx = {
        'stripe_customer': customer,
    }

    return _pmrender(req, 'payments/main.html', ctx)
Beispiel #33
0
def set_payment_method(req):
    us = UserSettings.get_from_user(req.user)
    customer = us.get_stripe_customer()
    if customer:
        customer.source = req.POST.get('token')
        customer.save()
    else:
        us.create_stripe_customer(req.POST.get('token'))

    return {'success': True, 'id': us.stripe_customer_id}
Beispiel #34
0
def manage_blog(req, podcast_slug):
    site = get_site(req, podcast_slug)

    if not payment_plans.minimum(
        UserSettings.get_from_user(site.podcast.owner).plan,
        payment_plans.FEATURE_MIN_BLOG):
        raise Http404()

    return _pmrender(req, 'dashboard/sites/blog/page_manage.html',
                     {'site': site, 'posts': site.siteblogpost_set.all().order_by('-publish')})
Beispiel #35
0
    def get_remaining_surge(self, max_size):
        uset = UserSettings.get_from_user(self.owner)
        if not payment_plans.minimum(uset.plan, payment_plans.PLAN_STARTER):
            return 0
        thirty_ago = datetime.datetime.now() - datetime.timedelta(days=30)
        last_thirty_eps = self.podcastepisode_set.filter(created__gt=thirty_ago, audio_size__gt=max_size)
        surge_count = last_thirty_eps.count()
        surge_amt = last_thirty_eps.aggregate(models.Sum("audio_size"))["audio_size__sum"] or 0
        surge_amt -= surge_count * max_size

        remaining = max_size - surge_amt
        return 0 if remaining < 0 else remaining
Beispiel #36
0
def favicon(req, podcast_slug):
    pod = get_object_or_404(Podcast, slug=podcast_slug)
    us = UserSettings.get_from_user(pod.owner)
    if not minimum(us.plan, FEATURE_MIN_SITE_FAVICON):
        return redirect('https://pinecast.com/static/img/favicon.png')

    site = get_object_or_404(models.Site, podcast=pod)

    if not site.favicon_url:
        return redirect('https://pinecast.com/static/img/favicon.png')

    return redirect(site.favicon_url)
Beispiel #37
0
def favicon(req, podcast_slug):
    pod = get_object_or_404(Podcast, slug=podcast_slug)
    us = UserSettings.get_from_user(pod.owner)
    if not minimum(us.plan, FEATURE_MIN_SITE_FAVICON):
        return redirect('https://pinecast.com/static/img/favicon.png')

    site = get_object_or_404(models.Site, podcast=pod)

    if not site.favicon_url:
        return redirect('https://pinecast.com/static/img/favicon.png')

    return redirect(site.favicon_url)
Beispiel #38
0
def podcast_new_ep(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)

    tz_delta = UserSettings.get_from_user(req.user).get_tz_delta()

    latest_episode = pod.get_most_recent_episode()
    ctx = {
        'podcast': pod,
        'latest_ep': latest_episode,
    }
    if not req.POST:
        base_default = EmptyStringDefaultDict()
        base_default['publish'] = datetime.datetime.strftime(
            datetime.datetime.now() + tz_delta,
            '%Y-%m-%dT%H:%M'  # 2015-07-09T12:00
        )
        ctx['default'] = base_default
        return _pmrender(req, 'dashboard/episode/page_new.html', ctx)

    try:
        publish_parsed = datetime.datetime.strptime(req.POST.get('publish').split('.')[0], ISO_FORMAT)
        image_url = req.POST.get('image-url')

        ep = PodcastEpisode(
            podcast=pod,
            title=req.POST.get('title'),
            subtitle=req.POST.get('subtitle'),
            publish=publish_parsed,
            description=req.POST.get('description'),
            duration=int(req.POST.get('duration-hours') or 0) * 3600 + int(req.POST.get('duration-minutes') or 0) * 60 + int(req.POST.get('duration-seconds') or 0),

            audio_url=signer.unsign(req.POST.get('audio-url')),
            audio_size=int(req.POST.get('audio-url-size')),
            audio_type=req.POST.get('audio-url-type'),

            image_url=signer.unsign(image_url) if image_url else pod.cover_image,

            copyright=req.POST.get('copyright'),
            license=req.POST.get('license'),

            explicit_override=req.POST.get('explicit_override'))
        ep.set_flair(req.POST, no_save=True)
        ep.save()
        if req.POST.get('feedback_prompt'):
            prompt = EpisodeFeedbackPrompt(episode=ep, prompt=req.POST.get('feedback_prompt'))
            prompt.save()
    except Exception as e:
        rollbar.report_exc_info(sys.exc_info(), req)
        ctx['error'] = True
        ctx['default'] = req.POST
        return _pmrender(req, 'dashboard/episode/page_new.html', ctx)
    return redirect('podcast_dashboard', podcast_slug=pod.slug)
Beispiel #39
0
    def _process(self):
        assert self.selection

        select = ', '.join(
            select_format(k, v) for
            k, v in
            self.selection.items())
        where = ''
        group_by = ''

        tz = UserSettings.get_from_user(self.req.user).tz_offset

        if self.criteria:
            where = ' AND '.join(
                where_format(k, v) for
                k, v in
                self.criteria.items()
            )
        if self.group_by:
            if isinstance(self.group_by, (list, tuple)):
                group_by = ', '.join(ident(x) for x in self.group_by)
            else:
                group_by = ident(self.group_by)

        if self.timeframe:
            tf = USER_TIMEFRAMES.get(
                self.req.GET.get('timeframe', self.timeframe),
                lambda tz: None)(tz)
            if tf:
                if where:
                    where += ' AND '
                where += tf

        if self.interval_val:
            if group_by:
                group_by += ', '
            group_by += INTERVALS[self.interval_val]

        query = 'SELECT %s FROM %s' % (select, ident(self.event_type))
        if where:
            query += ' WHERE %s' % where
        if group_by:
            query += ' GROUP BY %s' % group_by

        query += ';'

        # if settings.DEBUG:
        #     print(query)

        self.res = get_client().query(query, database=self.db)

        return self
Beispiel #40
0
def podcast_new_ep(req, podcast_slug):
    pod = get_podcast(req, podcast_slug)

    tz_delta = UserSettings.get_from_user(req.user).get_tz_delta()

    latest_episode = pod.get_most_recent_episode()
    ctx = {
        'podcast': pod,
        'latest_ep': latest_episode,
    }
    if not req.POST:
        base_default = EmptyStringDefaultDict()
        base_default['publish'] = datetime.datetime.strftime(
            datetime.datetime.now() + tz_delta,
            '%Y-%m-%dT%H:%M'  # 2015-07-09T12:00
        )
        ctx['default'] = base_default
        return _pmrender(req, 'dashboard/episode/page_new.html', ctx)

    try:
        publish_parsed = datetime.datetime.strptime(req.POST.get('publish').split('.')[0], ISO_FORMAT)
        image_url = req.POST.get('image-url')

        ep = PodcastEpisode(
            podcast=pod,
            title=req.POST.get('title'),
            subtitle=req.POST.get('subtitle'),
            publish=publish_parsed,
            description=req.POST.get('description'),
            duration=int(req.POST.get('duration-hours')) * 3600 + int(req.POST.get('duration-minutes')) * 60 + int(req.POST.get('duration-seconds')),

            audio_url=signer.unsign(req.POST.get('audio-url')),
            audio_size=int(req.POST.get('audio-url-size')),
            audio_type=req.POST.get('audio-url-type'),

            image_url=signer.unsign(image_url) if image_url else pod.cover_image,

            copyright=req.POST.get('copyright'),
            license=req.POST.get('license'),

            explicit_override=req.POST.get('explicit_override'))
        ep.set_flair(req.POST, no_save=True)
        ep.save()
        if req.POST.get('feedback_prompt'):
            prompt = EpisodeFeedbackPrompt(episode=ep, prompt=req.POST.get('feedback_prompt'))
            prompt.save()
    except Exception as e:
        raise e
        ctx['error'] = True
        ctx['default'] = req.POST
        return _pmrender(req, 'dashboard/episode/page_new.html', ctx)
    return redirect('podcast_dashboard', podcast_slug=pod.slug)
Beispiel #41
0
 def cancel(self):
     us = UserSettings.get_from_user(self.podcast.owner)
     try:
         subscription = stripe.Subscription.retrieve(
             self.stripe_subscription_id,
             stripe_account=us.stripe_payout_managed_account)
     except stripe.error.InvalidRequestError:
         pass
     else:
         subscription.delete()
     finally:
         self.deactivated = True
         self.save()
Beispiel #42
0
 def cancel(self):
     us = UserSettings.get_from_user(self.podcast.owner)
     try:
         subscription = stripe.Subscription.retrieve(
             self.stripe_subscription_id,
             stripe_account=us.stripe_payout_managed_account)
     except stripe.error.InvalidRequestError:
         pass
     else:
         subscription.delete()
     finally:
         self.deactivated = True
         self.save()
Beispiel #43
0
def signup(req):
    if not req.user.is_anonymous():
        return redirect('dashboard')

    if not req.POST:
        return _pmrender(
            req,
            'signup/main.html',
            {'email': req.GET.get('email', '')}
        )

    error = None

    if not _validate_recaptcha(req):
        error = ugettext('Your humanity was not verified')
    elif not req.POST.get('email'):
        error = ugettext('Missing email address')
    elif not req.POST.get('password'):
        error = ugettext('Come on, you need a password')
    elif len(req.POST.get('password')) < 8:
        error = ugettext('Your password needs to be at least 8 characters long')
    elif User.objects.filter(email=req.POST.get('email')).count():
        error = ugettext('That email address is already associated with an account')

    if error:
        return _pmrender(req, 'signup/main.html', {
            'error': error,
            'email': req.POST.get('email'),
        })

    try:
        u = User.objects.create_user(
            str(uuid.uuid4())[:30],
            req.POST.get('email'),
            req.POST.get('password')
        )
        u.save()
    except Exception as e:
        return _pmrender(req, 'signup/main.html', {
            'error': str(e),
            'email': req.POST.get('email'),
        })

    try:
        us = UserSettings.get_from_user(u)
        us.tz_offset = req.POST.get('timezone')
        us.save()
    except Exception:
        pass  # whatever.

    return redirect(reverse('login') + '?signup_success=true')
Beispiel #44
0
    def process_request(self, req):
        scheme = 'http' if not req.is_secure() else 'https'
        domain = req.META.get('HTTP_HOST') or req.META.get('SERVER_NAME')

        if settings.DEBUG and ':' in domain:
            domain = domain[:domain.index(':')]

        pc_forward = req.META.get('HTTP_X_PINECAST_FORWARD')
        if pc_forward:
            try:
                site = Site.objects.get(custom_cname__iexact=pc_forward)
                us = UserSettings.get_from_user(site.podcast.owner)
                if not minimum(us.plan, FEATURE_MIN_CNAME):
                    raise NotCNAMEReadyException()
                return self._resolve(req, site.podcast.slug)
            except (Site.DoesNotExist, NotCNAMEReadyException):
                pass

        pieces = domain.split('.')
        if len(pieces) != 3:
            return None

        if domain[len(pieces[0]):] not in SUBDOMAIN_HOSTS:
            return None

        try:
            pod = Podcast.objects.get(slug__iexact=pieces[0])
            site = Site.objects.get(podcast=pod)
        except (Site.DoesNotExist, Podcast.DoesNotExist):
            return None

        us = UserSettings.get_from_user(pod.owner)
        if minimum(us.plan, FEATURE_MIN_CNAME) and site.custom_cname:
            return redirect('%s://%s%s' %
                            (scheme, site.custom_cname, req.get_full_path()),
                            permanent=True)

        return self._resolve(req, pod.slug)
Beispiel #45
0
    def process_request(self, req):
        scheme = 'http' if not req.is_secure() else 'https'
        domain = req.META.get('HTTP_HOST') or req.META.get('SERVER_NAME')

        if settings.DEBUG and ':' in domain:
            domain = domain[:domain.index(':')]

        pc_forward = req.META.get('HTTP_X_PINECAST_FORWARD')
        if pc_forward:
            try:
                site = Site.objects.get(custom_cname__iexact=pc_forward)
                us = UserSettings.get_from_user(site.podcast.owner)
                if not minimum(us.plan, FEATURE_MIN_CNAME):
                    raise NotCNAMEReadyException()
                return self._resolve(req, site.podcast.slug)
            except (Site.DoesNotExist, NotCNAMEReadyException):
                pass

        pieces = domain.split('.')
        if len(pieces) != 3:
            return None

        if domain[len(pieces[0]):] not in SUBDOMAIN_HOSTS:
            return None

        try:
            pod = Podcast.objects.get(slug__iexact=pieces[0])
            site = Site.objects.get(podcast=pod)
        except (Site.DoesNotExist, Podcast.DoesNotExist):
            return None

        us = UserSettings.get_from_user(pod.owner)
        if minimum(us.plan, FEATURE_MIN_CNAME) and site.custom_cname:
            return redirect(
                '%s://%s%s' % (scheme, site.custom_cname, req.get_full_path()),
                permanent=True)

        return self._resolve(req, pod.slug)
Beispiel #46
0
def upgrade(req):
    us = UserSettings.get_from_user(req.user)
    customer = us.get_stripe_customer()

    ctx = {
        'active_coupon': req.session.get('coupon'),
        'coupon_applied': 'coupon_applied' in req.GET,
        'coupon_invalid': 'coupon_invalid' in req.GET,
        'coupon_unavailable': 'coupon_unavailable' in req.GET,
        'error': req.GET.get('error'),
        'stripe_customer': customer,
        'success': 'success' in req.GET,
    }
    return _pmrender(req, 'payments/main.html', ctx)
Beispiel #47
0
    def get_remaining_surge(self, max_size):
        uset = UserSettings.get_from_user(self.owner)
        if not payment_plans.minimum(uset.plan, payment_plans.PLAN_STARTER):
            return 0
        thirty_ago = datetime.datetime.now() - datetime.timedelta(days=30)
        last_thirty_eps = self.podcastepisode_set.filter(
            created__gt=thirty_ago, audio_size__gt=max_size)
        surge_count = last_thirty_eps.count()
        surge_amt = last_thirty_eps.aggregate(
            models.Sum('audio_size'))['audio_size__sum'] or 0
        surge_amt -= surge_count * max_size

        remaining = max_size - surge_amt
        return 0 if remaining < 0 else remaining
Beispiel #48
0
    def _process(self):
        assert self.selection

        select = ', '.join(
            select_format(k, v) for k, v in self.selection.items())
        where = ''
        group_by = ''

        tz = UserSettings.get_from_user(self.req.user).tz_offset

        if self.criteria:
            where = ' AND '.join(
                where_format(k, settings.INFLUXDB_CONDITION_OVERRIDES.get(
                    k, v)) for k, v in self.criteria.items())
        if self.group_by:
            if isinstance(self.group_by, (list, tuple)):
                group_by = ', '.join(ident(x) for x in self.group_by)
            else:
                group_by = ident(self.group_by)

        if self.timeframe:
            tf = USER_TIMEFRAMES.get(
                self.req.GET.get('timeframe', self.timeframe)
                if not self.force_timeframe else self.timeframe,
                lambda tz: None)(tz)
            if tf:
                if where:
                    where += ' AND '
                where += tf

        if self.interval_val:
            if group_by:
                group_by += ', '
            group_by += INTERVALS[self.interval_val] % (
                -1 * self._get_tz_offset().total_seconds() // 3600)

        query = 'SELECT %s FROM %s' % (select, ident(self.event_type))
        if where:
            query += ' WHERE %s' % where
        if group_by:
            query += ' GROUP BY %s' % group_by

        query += ';'

        if settings.DEBUG:
            print(query)

        self.res = get_client().query(query, database=self.db)

        return self
Beispiel #49
0
def upgrade(req):
    us = UserSettings.get_from_user(req.user)
    customer = us.get_stripe_customer()

    ctx = {
        'active_coupon': req.session.get('coupon'),
        'coupon_applied': 'coupon_applied' in req.GET,
        'coupon_invalid': 'coupon_invalid' in req.GET,
        'coupon_unavailable': 'coupon_unavailable' in req.GET,
        'error': req.GET.get('error'),
        'stripe_customer': customer,
        'success': 'success' in req.GET,
    }
    return _pmrender(req, 'payments/main.html', ctx)
Beispiel #50
0
def dashboard(req):
    ctx = {
        'success': req.GET.get('success'),
        'error': req.GET.get('error'),
    }

    us = UserSettings.get_from_user(req.user)
    if us.coupon_code:
        try:
            ctx['coupon'] = stripe.Coupon.retrieve(us.coupon_code)
        except Exception as e:
            if settings.DEBUG:
                raise e

    return _pmrender(req, 'dashboard/dashboard.html', ctx)
Beispiel #51
0
def dashboard(req):
    ctx = {
        'success': req.GET.get('success'),
        'error': req.GET.get('error'),
    }

    us = UserSettings.get_from_user(req.user)
    if us.coupon_code:
        try:
            ctx['coupon'] = stripe.Coupon.retrieve(us.coupon_code)
        except Exception as e:
            if settings.DEBUG:
                raise e

    return _pmrender(req, 'dashboard/dashboard.html', ctx)
Beispiel #52
0
def signup(req):
    if not req.user.is_anonymous():
        return redirect('dashboard')

    if not req.POST:
        return _pmrender(req, 'signup/main.html',
                         {'email': req.GET.get('email', '')})

    error = None

    if not _validate_recaptcha(req):
        error = ugettext('Your humanity was not verified')
    elif not req.POST.get('email'):
        error = ugettext('Missing email address')
    elif not req.POST.get('password'):
        error = ugettext('Come on, you need a password')
    elif len(req.POST.get('password')) < 8:
        error = ugettext(
            'Your password needs to be at least 8 characters long')
    elif User.objects.filter(email=req.POST.get('email')).count():
        error = ugettext(
            'That email address is already associated with an account')

    if error:
        return _pmrender(req, 'signup/main.html', {
            'error': error,
            'email': req.POST.get('email'),
        })

    try:
        u = User.objects.create_user(
            str(uuid.uuid4())[:30], req.POST.get('email'),
            req.POST.get('password'))
        u.save()
    except Exception as e:
        return _pmrender(req, 'signup/main.html', {
            'error': str(e),
            'email': req.POST.get('email'),
        })

    try:
        us = UserSettings.get_from_user(u)
        us.tz_offset = req.POST.get('timezone')
        us.save()
    except Exception:
        pass  # whatever.

    return redirect(reverse('login') + '?signup_success=true')
Beispiel #53
0
        def wrapper(*args, **kwargs):
            req = args[0]
            if not req.user:
                return HttpResponseForbidden()

            pod = get_podcast(req, req.GET.get("podcast"))

            uset = UserSettings.get_from_user(pod.owner)
            if not plans.minimum(uset.plan, minimum_plan) and not req.user.is_staff:
                return HttpResponseForbidden()

            resp = view(req, pod, *args[1:], **kwargs)
            if not isinstance(resp, (dict, list, bool, int, float) + StringTypes) and resp is not None:
                # Handle HttpResponse/HttpResponseBadRequest/etc
                return resp
            return JsonResponse(resp, safe=False)
Beispiel #54
0
def _get_podcast(req, **kwargs):
    podcast = get_object_or_404(Podcast, **kwargs)
    us = UserSettings.get_from_user(podcast.owner)
    if not minimum(us.plan, FEATURE_MIN_NOTIFICATIONS):
        raise HttpResponseForbidden()

    if req.user.is_staff:
        return podcast

    if req.user == podcast.owner:
        return podcast

    pods = Network.objects.filter(deactivated=False, members__in=[req.user], podcast__in=[podcast])
    if not pods.count():
        raise Http404()

    return podcast
Beispiel #55
0
def upgrade_set_plan(req):
    new_plan = req.POST.get('plan')
    if new_plan not in AVAILABLE_PLANS:
        return redirect('upgrade')

    new_plan_val = AVAILABLE_PLANS[new_plan]

    us = UserSettings.get_from_user(req.user)
    result = us.set_plan(new_plan_val, req.session.get('coupon'))

    if not result:
        return redirect('upgrade')
    elif result == 'card_error':
        return redirect(reverse('upgrade') + '?error=card')
    else:
        req.session['coupon'] = None
        return redirect(reverse('upgrade') + '?success')
Beispiel #56
0
        def wrapper(*args, **kwargs):
            req = args[0]
            if not req.user:
                return HttpResponseForbidden()

            pod = get_podcast(req, req.GET.get('podcast'))

            uset = UserSettings.get_from_user(pod.owner)
            if (not plans.minimum(uset.plan, minimum_plan)
                    and not req.user.is_staff):
                return HttpResponseForbidden()

            resp = view(req, pod, *args[1:], **kwargs)
            if not isinstance(resp, (dict, list, bool, int, float) +
                              StringTypes) and resp is not None:
                # Handle HttpResponse/HttpResponseBadRequest/etc
                return resp
            return JsonResponse(resp, safe=False)
Beispiel #57
0
def new_podcast(req):
    uset = UserSettings.get_from_user(req.user)
    if payment_plans.has_reached_podcast_limit(uset):
        return _pmrender(req, 'dashboard/podcast/page_new_upgrade.html')

    ctx = {
        'LOCALES': constants.locales,

        'reached_podcast_limit': payment_plans.has_reached_podcast_limit(uset)
    }

    if not req.POST:
        return _pmrender(req, 'dashboard/podcast/page_new.html', ctx)

    # Basic validation
    if (not req.POST.get('slug') or not req.POST.get('name')):
        ctx.update(default=req.POST, error=True)
        return _pmrender(req, 'dashboard/podcast/page_new.html', ctx)

    try:
        pod = Podcast(
            slug=req.POST.get('slug'),
            name=req.POST.get('name'),
            subtitle=req.POST.get('subtitle'),
            cover_image=signer.unsign(req.POST.get('image-url')),
            description=req.POST.get('description'),
            is_explicit=req.POST.get('is_explicit', 'false') == 'true',
            homepage=req.POST.get('homepage'),
            language=req.POST.get('language'),
            copyright=req.POST.get('copyright'),
            author_name=req.POST.get('author_name'),
            owner=req.user)
        pod.clean()
        pod.save()
    except Exception as e:
        ctx.update(default=req.POST, error=True)
        return _pmrender(req, 'dashboard/podcast/page_new.html', ctx)

    try:
        pod.set_category_list(req.POST.get('categories'))
    except Exception:
        pass

    return redirect('podcast_dashboard', podcast_slug=pod.slug)
Beispiel #58
0
def set_tip_cashout(req):
    try:
        dob = iso8601.parse_date(req.POST.get('dob'))
    except Exception:
        return {'success': False, 'error': 'invalid dob'}

    forwarded_for = req.META.get('HTTP_X_FORWARDED_FOR')
    if forwarded_for:
        ip = forwarded_for.split(',')[0]
    else:
        ip = req.META.get('REMOTE_ADDR')

    legal_entity = {
        'address': {
            'city': req.POST.get('addressCity'),
            'state': req.POST.get('addressState'),
            'postal_code': req.POST.get('addressZip'),
            'line1': req.POST.get('addressStreet'),
            'line2': req.POST.get('addressSecond'),
        },
        'ssn_last_4': req.POST.get('ssnLastFour'),
        'dob': {
            'day': dob.day,
            'month': dob.month,
            'year': dob.year,
        },
        'first_name': req.POST.get('firstName'),
        'last_name': req.POST.get('lastName'),
        'type': 'individual',
    }

    us = UserSettings.get_from_user(req.user)
    account = us.get_stripe_managed_account()
    if account:
        account.external_account = req.POST.get('token')
        for key in legal_entity:
            setattr(account.legal_entity, key, legal_entity[key])
        account.save()
    else:
        us.create_stripe_managed_account(req.POST.get('token'), ip,
                                         legal_entity)

    return {'success': True}
Beispiel #59
0
def get_episodes(req):
    pod_slug = req.GET.get('podcast')
    network = req.GET.get('network_id')
    start_date = req.GET.get('start_date')

    if not pod_slug and not network:
        return []

    pods = set()
    if pod_slug:
        pods.add(get_podcast(req, pod_slug))

    if network:
        net = get_object_or_404(Network, id=network, members__in=[req.user])
        pods = pods | set(net.podcast_set.all())

    if not pods:
        return []

    query = PodcastEpisode.objects.filter(
        podcast__in=list(pods),
        publish__lt=datetime.datetime.now(),
        awaiting_import=False
    ).select_related('podcast')
    if start_date:
        try:
            parsed_date = datetime.datetime.strptime(start_date, '%Y-%m-%dT%H:%M:%S')
        except ValueError:
            raise Http404()
        query = query.filter(publish__gte=parsed_date)

    uset = UserSettings.get_from_user(req.user)
    tz_delta = uset.get_tz_delta()
    return [
        {'id': ep.id,
         'title': ep.title,
         'podcastSlug': ep.podcast.slug,
         'publish': (ep.publish + tz_delta).strftime('%Y-%m-%dT%H:%M:%S')} for
        ep in
        sorted(query, key=lambda x: x.publish)
    ]
Beispiel #60
0
    def get_available_flair_flags(self, flatten=False):
        us = UserSettings.get_from_user(self.owner)
        plan = us.plan
        flags = []
        if payment_plans.minimum(plan, payment_plans.PLAN_STARTER):
            # This is inside a conditional because it's forced on for free
            # users.
            flags.append(FLAIR_POWERED_BY)
        if payment_plans.minimum(plan, payment_plans.FEATURE_MIN_COMMENT_BOX):
            flags.append(FLAIR_FEEDBACK)
        if us.stripe_payout_managed_account:
            flags.append(FLAIR_TIP_JAR)

        if payment_plans.minimum(
                plan, payment_plans.FEATURE_MIN_SITES) and self.get_site():
            flags.append(FLAIR_SITE_LINK)

        if flatten:
            return flags
        else:
            return [(f, FLAIR_FLAGS_MAP[f]) for f in flags]