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')
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)
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)
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)
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)
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')
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')
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})
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)
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)
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
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})
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
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')})
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]
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
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)
def get_available_flair_flags(self, flatten=False): plan = UserSettings.get_from_user(self.owner).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) try: if payment_plans.minimum(plan, payment_plans.FEATURE_MIN_SITES) and self.site: flags.append(FLAIR_SITE_LINK) except Exception: # FIXME: Catch the correct exception here. # `RelatedObjectDoesNotExist` is a strange and fickle beast. pass if flatten: return flags else: return [(f, FLAIR_FLAGS_MAP[f]) for f in flags]
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]
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)
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)
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
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')
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)
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): return HttpResponseForbidden() resp = view(req, pod, *args[1:], **kwargs) if not isinstance(resp, (dict, list, bool, str, unicode, int, float)): # Handle HttpResponse/HttpResponseBadRequest/etc return resp return JsonResponse(resp, safe=False)
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
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)
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'), '%Y-%m-%dT%H:%M:00.000Z') 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: 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')
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')
def minimum_plan(user_settings, plan): if isinstance(user_settings, User): user_settings = UserSettings.get_from_user(user_settings) return payment_plans.minimum(user_settings.plan, plan)
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) def pop_until_lt(arr, field, comp, max=-1): count = 0 while arr: if getattr(arr[0], field) >= comp: yield arr.pop(0) else: return if max > 0: count += 1 if count == max: break if not arr: return if max > 0: ignored = 0 while arr: if getattr(arr[0], field) >= comp: ignored += 1 arr.pop(0) else: break if ignored: yield ignored 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 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, 'PODCAST_CATEGORIES': json.dumps(list(CATEGORIES)), 'SITE_THEMES': Site.SITE_THEMES, 'N_DESTINATIONS': NotificationHook.DESTINATIONS, 'N_TRIGGERS': NotificationHook.TRIGGERS, 'pop_until_lt': pop_until_lt, } 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)) 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 return _pmrender(req, 'dashboard/podcast/page_podcast.html', data)