Пример #1
0
def staff_api_console(request):
    """ Shows an html wrapper around our APIs that staff can use. """
    from canvas.js_api import get_api_calls
    import drawquest.apps.stars.api
    import drawquest.apps.stars.api
    import drawquest.apps.drawquest_auth.api
    import drawquest.apps.iap.api
    import drawquest.apps.quests.api
    import drawquest.apps.quest_comments.api
    import drawquest.apps.playback.api
    import drawquest.apps.palettes.api
    import drawquest.apps.push_notifications.api
    import drawquest.apps.following.api
    import drawquest.apps.timeline.api
    import drawquest.apps.tumblr.api
    from drawquest.api_decorators import api_functions

    api_dict = defaultdict(lambda: [])
    # Group apis by their prefix.
    api_key = lambda func: func.url.strip("/").split("/")[1]
    functions = get_api_calls(api_functions=api_functions, ignore_unfound=True)
    for key, api_calls in itertools.groupby(functions, api_key):
        api_dict[key].extend(api_calls)

    apis = []
    for key, api_calls in api_dict.items():
        apis.append(dict(name=key, commands=api_calls))
    # Order apis alphabetically
    apis = sorted(apis, key=lambda entry: entry.get("name"))
    # Inspect it.
    # @todo: Add a "staff" api for staff only calls.
    #apis = [dict(path="/api/", name="Canvas API", commands=functions)]
    # @gotcha: Be sure to use r2r, else {% csrf_token %} won't work.
    return r2r("api_wrapper.django.html", dict(apis=apis, request=request))
Пример #2
0
def debug_fact_stream(request):
    return r2r('debug_fact_stream.django.html', {
        'request': request,
        'funnels': dict((name, [step.name for step in funnel.steps],)
                        for name,funnel in Funnels.by_name.iteritems()),
        'debug_fact_channel': fact.debug_fact_channel().sync(),
    })
Пример #3
0
def facebook_iframe(request):
    fb_message_id = request.GET.get('request_ids')

    try:
        fb_user, fb = get_fb_api(request)
        app_requests = fb.request('{}/apprequests'.format(fb_user['id']))

        redirect_url = None
        for app_request in app_requests['data']:
            if not redirect_url:
                redirect_url = app_request.get('data')
            fb.delete_object(app_request['id'])

        if not redirect_url:
            redirect_url = '/'
    except NotLoggedIntoFacebookError:
        redirect_url = '/'

    context = {
        'request': request,
        'fb_message_id': fb_message_id,
        'redirect_url': redirect_url,
    }
    resp = r2r('facebook_app/facebook_iframe.django.html', context)

    resp.set_cookie('fb_message_id', fb_message_id)

    return resp
Пример #4
0
def staff_api_console(request):
    """ Shows an html wrapper around our APIs that staff can use. """
    from canvas.js_api import get_api_calls
    import drawquest.apps.stars.api
    import drawquest.apps.stars.api
    import drawquest.apps.drawquest_auth.api
    import drawquest.apps.iap.api
    import drawquest.apps.quests.api
    import drawquest.apps.quest_comments.api
    import drawquest.apps.playback.api
    import drawquest.apps.palettes.api
    import drawquest.apps.push_notifications.api
    import drawquest.apps.following.api
    import drawquest.apps.timeline.api
    import drawquest.apps.tumblr.api
    from drawquest.api_decorators import api_functions

    api_dict = defaultdict(lambda: [])
    # Group apis by their prefix.
    api_key = lambda func: func.url.strip("/").split("/")[1]
    functions = get_api_calls(api_functions=api_functions, ignore_unfound=True)
    for key, api_calls in itertools.groupby(functions, api_key):
        api_dict[key].extend(api_calls)

    apis = []
    for key, api_calls in api_dict.items():
        apis.append(dict(name=key, commands=api_calls))
    # Order apis alphabetically
    apis = sorted(apis, key=lambda entry: entry.get("name"))
    # Inspect it.
    # @todo: Add a "staff" api for staff only calls.
    # apis = [dict(path="/api/", name="Canvas API", commands=functions)]
    # @gotcha: Be sure to use r2r, else {% csrf_token %} won't work.
    return r2r("api_wrapper.django.html", dict(apis=apis, request=request))
Пример #5
0
def facebook_iframe(request):
    fb_message_id = request.GET.get('request_ids')

    try:
        fb_user, fb = get_fb_api(request)
        app_requests = fb.request('{}/apprequests'.format(fb_user['id']))

        redirect_url = None
        for app_request in app_requests['data']:
            if not redirect_url:
                redirect_url = app_request.get('data')
            fb.delete_object(app_request['id'])

        if not redirect_url:
            redirect_url = '/'
    except NotLoggedIntoFacebookError:
        redirect_url = '/'

    context = {
        'request': request,
        'fb_message_id': fb_message_id,
        'redirect_url': redirect_url,
    }
    resp = r2r('facebook_app/facebook_iframe.django.html', context)

    resp.set_cookie('fb_message_id', fb_message_id)

    return resp
Пример #6
0
def signup(request, skip_invite_code=None, template="signup/signup.html", success_redirect="/onboarding/start"):
    cookies_to_delete = []
    cookies_to_set = {}

    error_context = get_signup_context(request, skip_invite_code, template,
                                       cookies_to_set, cookies_to_delete)

    Metrics.signup_form_view.record(request)

    def process_response(response):
        for key in cookies_to_delete:
            response.delete_cookie(key)
        for key, val in cookies_to_set.items():
            response.set_cookie(key, val)
        return response

    if not error_context:
        # error_context is only None if this is a POST (and with no errors).
        # DEPRECATED: next and next_params. we use cookies for these now - see get_signup_context
        if request.POST.get('next'):
            next_params = request.POST.get('next_params', '')
            if next_params:
                next_params = '?' + next_params
            success_redirect = request.POST['next']
            return process_response(HttpResponseRedirect(success_redirect + next_params))
        return process_response(HttpResponseRedirect(success_redirect))
    else:
        request.session['failed_signup'] = True

    if template == "signup_prompt.django.html":
        return process_response(r2r(template, error_context))
    return process_response(r2r_jinja(template, error_context, request))
Пример #7
0
def group_about(request, name):
    category = get_object_or_404(Category, name=name)
    category_disabled = category.visibility == Visibility.DISABLED
    founder = category.founder
    moderators = list(category.moderators.values_list('username', flat=True))
    can_modify_group = category.can_modify(request.user)
    can_disable_group = category.can_disable(request.user)
    has_form = can_modify_group or can_disable_group
    return r2r('group/about.django.html', locals())
Пример #8
0
def thread(request, short_id, page=None, gotoreply=None, sort_by_top=False,
           template_name='comment/new_base_thread.django.html'):
    from apps.monster.models import MONSTER_GROUP

    if not request.user.is_authenticated() and template_name == 'comment/new_base_thread.django.html' and not features.thread_new(request):
        return logged_out_thread_view(request, short_id, page=page, gotoreply=gotoreply)

    view_data = CommentViewData(request, short_id, page=page, gotoreply=gotoreply)

    if '/p/' + short_id == request.user.kv.post_pending_signup_url.get():
        request.user.kv.post_pending_signup_url.delete()

    ctx = view_data.thread_context()

    ctx['request'] = request

    # monstermash posts redirect to monstermash app
    if ctx['op_comment'].category == MONSTER_GROUP and not ctx['viewer_is_staff']:
        return HttpResponseRedirect('/monster/{0}'.format(ctx['op_comment'].short_id()))

    # all hidden group posts are invisible to normal users
    if ctx['op_comment'].category in settings.HIDDEN_GROUPS and not ctx['viewer_is_staff']:
        return Http404()

    # If we hit the size threshold, record metric that the user is viewing a large thread
    if ctx['large_thread_view']:
        Metrics.large_thread_view.record(request)

    ctx['remix_invite_share_view'] = 'rmi' in request.GET
    if ctx['remix_invite_share_view']:
        ctx['fb_metadata']['title'] = "Come Remix With Me!"
        if ctx['op_comment'].title:
            ctx['fb_metadata']['description'] = """I just started a thread on Canvas, "{0}". Click the link to add your remix to the thread!""".format(op_comment.title)
        else:
            ctx['fb_metadata']['description'] = "I just started a thread on Canvas. Click the link to add your remix to the thread!"

    # Inviting experiment
    ctx['is_in_invite_remixers_v2'] = False

    ctx.update({
        'request': request,
        'sort_by_top': sort_by_top,
    })

    if request.is_mobile:
        return r2r_jinja("mobile/thread.html", ctx)

    if features.thread_new(request):
        ctx['has_top_remixes'] = bool(len(ctx['top_remixes']))
        if sort_by_top:
            ctx['replies'] = ctx['top_remixes']
            ctx['has_top_remixes'] = True

        return r2r_jinja('threads_new/thread.html', ctx, request)

    return r2r(template_name, ctx)
Пример #9
0
def staff_pulse(request):
    g = Grapher(request)
    M = lambda metric, fun_name='daily_uniques': lambda d: getattr(metric, fun_name)(d)

    graphs = [
        g.gen_trailing('Daily Signups', M(Metrics.signup, 'daily_count')),
        g.gen_trailing('DAU (Daily Unique Viewers)', M(Metrics.view)),
        g.gen_trailing('Daily Unique Stickerers', M(Metrics.sticker)),
        g.gen_trailing('Daily Unique Posters', M(Metrics.post)),
    ]

    return r2r('staff/graphs.django.html', locals())
Пример #10
0
def staff_vanity_metrics(request):
    ytd = bool(request.GET.get('ytd'))
    enum_days = days if not ytd else days_ytd
    posts = Comment.all_objects.count()
    # Use the last id instead of count() so we can use this more reliably for email sending ranges.
    users = User.objects.order_by('-id')[0].id
    stickers = CommentSticker.objects.count()

    graphs = []
    for cat_name, arg_lists in Metrics.names:
        counts, uniques, unique_ips = [], [], []
        hourly_counts, hourly_uniques, hourly_unique_ips = [], [], []
        for args in arg_lists:
            name = args[0]
            metric = getattr(Metrics, name)
            counts.append({
                'name': name,
                'data': [metric.daily_count(d) for d in enum_days()],
            })
            uniques.append({
                'name': name,
                'data': [metric.daily_uniques(d) for d in enum_days()],
            })
            unique_ips.append({
                'name': name,
                'data': [metric.daily_uniques(d, True) for d in enum_days()],
            })

            if not ytd:
                hourly_counts.append({
                    'name': name,
                    'data': [metric.hourly_count(h) for h in hours()],
                })
                hourly_uniques.append({
                    'name': name,
                    'data': [metric.hourly_uniques(h) for h in hours()],
                })
                hourly_unique_ips.append({
                    'name': name,
                    'data': [metric.hourly_uniques(d, True) for d in hours()],
                })

        graphs.append({'name': cat_name + ' counts', 'data': counts, 'primary': True, 'primary_name': cat_name})
        graphs.append({'name': cat_name + ' uniques', 'data': uniques, 'primary': False})
        graphs.append({'name': cat_name + ' unique ips', 'data': unique_ips, 'primary': False})
        if not ytd:
            graphs.append({'name': cat_name + ' hourly counts', 'data': hourly_counts, 'primary': False})
            graphs.append({'name': cat_name + ' hourly uniques', 'data': hourly_uniques, 'primary': False})
            graphs.append({'name': cat_name + ' hourly unique ips', 'data': hourly_unique_ips, 'primary': False})

    return r2r('staff/vanity_metrics.django.html', locals())
Пример #11
0
def warning(request):
    if request.method == "POST":
        for name in request.POST.keys():
            match = re.match('confirm_(\d+)', name)
            if match:
                warning_id, = match.groups()
                warning = UserWarning.objects.get(user=request.user, id=warning_id)
                warning.confirm()

    warnings = list(UserWarning.objects.filter(user=request.user, confirmed=0))

    if warnings:
        return r2r('warning.django.html', locals())
    else:
        return HttpResponseRedirect('/warning/code_of_conduct')
Пример #12
0
def staff_api_console(request):
    """ Shows an html wrapper around our APIs that staff can use. """
    from canvas.js_api import get_api_calls

    api_dict = defaultdict(lambda: [])
    # Group apis by their prefix.
    api_key = lambda func: func.url.strip("/").split("/")[1]
    functions = get_api_calls()
    for key, api_calls in itertools.groupby(functions, api_key):
        api_dict[key].extend(api_calls)

    apis = []
    for key, api_calls in api_dict.items():
        apis.append(dict(name=key, commands=api_calls))
    # Order apis alphabetically
    apis = sorted(apis, key=lambda entry: entry.get("name"))
    # Inspect it.
    # @todo: Add a "staff" api for staff only calls.
    #apis = [dict(path="/api/", name="Canvas API", commands=functions)]
    return r2r("api_wrapper.django.html", dict(apis=apis, request=request))
Пример #13
0
def staff_user_view(request, username, key="user"):
    user = get_object_or_404(User, username=username)

    kwargs = {key: user}
    related = ['user', 'moderator']
    comment_log = CommentModerationLog.objects.filter(**kwargs).order_by('-id').select_related(*(related+['comment', 'comment__parent_comment']))[:100]
    user_log = UserModerationLog.objects.filter(**kwargs).select_related(*related)

    time_dilation = user.kv.time_dilation.get()
    time_dilation_start = user.kv.time_dilation_start.get()
    time_dilation_end = user.kv.time_dilation_end.get()
    if time_dilation_start and time_dilation_end:
        time_dilation_days = int((time_dilation_end - time_dilation_start) / 86400)
    else:
        time_dilation_days = 0

    sorted_logs = sorted(list(comment_log) + list(user_log), key=lambda log: -log.timestamp)

    # Warm the in-process-cache for the template uses of reply_content.details.
    CachedCall.multicall([log.comment.reply_content.details for log in comment_log if log.comment.reply_content])

    logs = [(log, render_to_string('staff/modlog/' + log.log_template, {'log': log})) for log in sorted_logs]

    return r2r('staff/user_view.django.html', locals())
Пример #14
0
def staff_action(request):
    stickerers, posters, viewers = [], [], []

    def safediv(num, div):
        return float(num) / div if div != 0 else 0

    def intersect(metric, today):
        yesterday = today - datetime.timedelta(1)
        yesterday_signups = Metrics.signup.uniques(yesterday)
        today_metric = metric.uniques(today)
        returning_metric = RedisSet(gen_temp_key())
        redis.sinterstore(returning_metric.key, [yesterday_signups.key, today_metric.key])
        return safediv(returning_metric.scard(), yesterday_signups.scard())

    g = Grapher(request)
    M = lambda metric: lambda d: intersect(metric, d) * 100

    graphs = [
        g.gen_trailing('2nd day viewer %', M(Metrics.view)),
        g.gen_trailing('2nd day stickerers %', M(Metrics.sticker)),
        g.gen_trailing('2nd day posters %', M(Metrics.post)),
    ]

    return r2r('staff/graphs.django.html', locals())
Пример #15
0
def signup(request,
           skip_invite_code=None,
           template="signup/signup.html",
           success_redirect="/onboarding/start"):
    cookies_to_delete = []
    cookies_to_set = {}

    error_context = get_signup_context(request, skip_invite_code, template,
                                       cookies_to_set, cookies_to_delete)

    Metrics.signup_form_view.record(request)

    def process_response(response):
        for key in cookies_to_delete:
            response.delete_cookie(key)
        for key, val in cookies_to_set.items():
            response.set_cookie(key, val)
        return response

    if not error_context:
        # error_context is only None if this is a POST (and with no errors).
        # DEPRECATED: next and next_params. we use cookies for these now - see get_signup_context
        if request.POST.get('next'):
            next_params = request.POST.get('next_params', '')
            if next_params:
                next_params = '?' + next_params
            success_redirect = request.POST['next']
            return process_response(
                HttpResponseRedirect(success_redirect + next_params))
        return process_response(HttpResponseRedirect(success_redirect))
    else:
        request.session['failed_signup'] = True

    if template == "signup_prompt.django.html":
        return process_response(r2r(template, error_context))
    return process_response(r2r_jinja(template, error_context, request))
Пример #16
0
def staff_ip_user_history(request, ip):
    ip_int = ip_to_int(ip)
    history = IP(ip_int).user_history.with_scores[:]
    users = User.objects.in_bulk_list([user for (user, ts) in history])
    history = zip(users, [ts for (user, ts) in history])
    return r2r('staff/user_history.django.html', locals())
Пример #17
0
def staff_user_ip_history(request, username):
    user = get_object_or_404(User, username=username)
    ip_history = [(int_to_ip(ip), timestamp) for (ip, timestamp) in user.redis.ip_history.with_scores[:]]
    return r2r('staff/ip_history.django.html', locals())
Пример #18
0
def draw(request):
    # Get the content_id of what we are remixing, or our blank white PNG if nothing.
    cid = request.GET.get('cid', Content.DRAW_FROM_SCRATCH_PK)
    remixing = get_object_or_404(Content.all_objects, id=cid).details()
    return r2r('draw.django.html', locals())
Пример #19
0
def staff_api_console(request):
    """ Shows an html wrapper around our APIs that staff can use. """
    apis = _apis()
    return r2r("api_wrapper.django.html", dict(apis=apis, request=request))
Пример #20
0
def group_new(request):
    ctx = {
        'found_limit_reached': request.user.found_limit_reached(),
        'request': request,
    }
    return r2r('group/new.django.html', ctx)
Пример #21
0
def signup_share_prompt(request):
    post_pending_signup_url = request.user.kv.post_pending_signup_url.get()
    return r2r('share_prompt.django.html', locals())
Пример #22
0
def numbers(request):
    now = time.time()
    trailing_7day = now - 7 * 24 * 60 * 60

    fmt = lambda n, tot: "%0.0f (%0.2f%%)" % (n, float(n)/tot*100) if tot else None

    all_users = User.objects.all()
    all_images = Content.all_objects.count()
    all_remixes = Content.all_objects.exclude(remix_of=None).count()

    l7d_images = Content.all_objects.filter(timestamp__gt=trailing_7day).count()
    l7d_remixes = Content.all_objects.exclude(remix_of=None).filter(timestamp__gt=trailing_7day).count()

    max_user_id = User.objects.order_by('-id')[0].id
    trailing_1000_users = User.objects.filter(id__gte=max_user_id-1000)

    women = lambda u: u.filter(facebookuser__gender=Gender.FEMALE).count()
    viral = lambda u: (u.aggregate(c=Count('sent_invites__invitee')).get('c', 0)
                       + u.aggregate(c=Count('facebook_sent_invites__invitee')).get('c', 0))

    sections = [
        (   'All time',
            [('Images', all_images), ('Remixes', fmt(all_remixes, all_images))]
        ),
        (   'Last 7 days',
            [('Images', l7d_images), ('Remixes', fmt(l7d_remixes, l7d_images))]
        ),
        (   'Trailing 1000 users',
            [('Women', women(trailing_1000_users)), ('Invited users (virality)', viral(trailing_1000_users))]
        ),
        (   'All Users',
            [('Women', women(all_users)), ('Invited users (virality)', viral(all_users))]
        ),
    ]

    trailing_7day_dau = [Metrics.view.daily_uniques(d) for d in days(7)]
    users = User.objects.count()
    daily = sum(trailing_7day_dau) / 7.0
    weekly = redis.scard(Metrics.view.trailing_uniques(7, gen_temp_key()))
    monthly = redis.scard(Metrics.view.trailing_uniques(30, gen_temp_key()))

    sections += [
        (   'Uniques (by view)',
            [
                ('all users', users),
                ('daily (trailing 7day average)', fmt(daily, users)),
                ('weekly (trailing 7day cumulative)', fmt(weekly, users)),
                ('monthly (trailing 30day cumulative)', fmt(monthly, users)),
            ],
        ),
    ]

    #u = lambda table, cutoff: fmt(User.objects.annotate(count=Count(table)).filter(count__gt=cutoff).count(), users)
    #
    #sections += [
    #    (   'Uniques (actions)',
    #        [
    #            ('all users', users),
    #            ('stickered', u('commentsticker', 0)),
    #            ('stickered 25 times', u('commentsticker', 24)),
    #            ('posted', u('comment', 0)),
    #            ('posted 25 times', u('comment', 24)),
    #            ('remixed', u('comment__reply_content__remix_of', 0)),
    #            ('remixed 25 times', u('comment__reply_content__remix_of', 24)),
    #        ],
    #    ),
    #]

    return r2r('staff/numbers.django.html', locals())
Пример #23
0
def sticker_values(request):
    sorted_stickers = sorted([(stick.sort_key(1), stick) for stick in stickers.all_stickers()], reverse=True)
    return r2r('staff/sticker_values.django.html', locals())
Пример #24
0
def staff_vintage(request):
    vintage_today = calculate_vintage(datetime.date.today())
    vintage_yesterday = calculate_vintage(datetime.date.today() - datetime.timedelta(1))
    daily_cohorts = calculate_cohort(datetime.date.today(), 7, 7)
    weekly_cohorts = calculate_cohort(datetime.date.today(), 8, 8, rollup=7)
    return r2r('staff/vintage.django.html', locals())
Пример #25
0
def staff_user_browse(request):
    if request.method == "POST":
        email = request.POST['email']
        matched_user = User.objects.get_or_none(email=email)
    recent_disablings = User.objects.filter(is_active=False, user_warnings__disable_user=True).annotate(issued=Max('user_warnings__issued')).order_by('-issued')
    return r2r('staff/user_browse.django.html', locals())
Пример #26
0
def staff_api_console(request):
    """ Shows an html wrapper around our APIs that staff can use. """
    apis = _apis()
    return r2r("api_wrapper.django.html", dict(apis=apis, request=request))
Пример #27
0
def unsubscribe(request):
    token = request.REQUEST.get('token', '')
    email = request.REQUEST.get('email')
    user_id = request.REQUEST.get('user_id')

    token_user = User.objects.get_or_none(id=user_id) if user_id else None

    unsubscribed = False
    unsubscribed_on_get = False

    if user_id and util.token(user_id) == token and token_user:
        user = token_user

    elif email and util.token(email) == token:
        # No user_id associated with the sent email, unsubscribe this email address from all email
        find_user = User.objects.filter(email=email)
        # If there is one and only one user with that email address, then pick them, otherwise we'll fall back to just an email address
        user = find_user[0] if find_user.count() == 1 else None

    elif request.user.is_authenticated():
        # Token mismatch, but we have a logged in user.
        user = request.user

    else:
        error = True
        return r2r('unsubscribe.django.html', locals())

    all_actions = EmailChannel.all_handled_actions()

    if user:
        subscriptions = user.kv.subscriptions

        # We need to handle any posts that are passed in the URL
        comment_id = request.GET.get('post')
        if comment_id:
            try:
                unsubscribed_post = Comment.objects.get(pk=int(comment_id))
            except ObjectDoesNotExist:
                pass
            else:
                user.redis.mute_thread(unsubscribed_post)
                unsubscribed_from_thread = unsubscribed_on_get = unsubscribed = True
                Metrics.mute_thread.record(request)

        # Support for unsubscribe headers.
        # We support passing in 'actions'
        action = request.REQUEST.get('action')
        if action and action in EmailChannel.all_handled_actions():
            unsubscribed_on_get = unsubscribed = True
            user.kv.subscriptions.unsubscribe(action)
            Metrics.unsubscribe_action.record(request, action=action, method=request.method)

        if request.method == 'POST':
            # Handle the 'ALL' case separately because the semantics for it are inverted.
            # ie, if ALL is checked, it means to DISABLE. While if REMIXED is checked, it means ENABLE.
            handle_unsubscribe_post(user, request.REQUEST, request)

        # We use this dictionary to render the checkboxes in the html.
        unsubscribed = unsubscribed or get_unsubscriptions(user, all_actions)

        unsubscribed_settings = get_unsubscriptions(user)
    else:
        unsubscribe_newsletter(email)
        unsubscribed = True
        Metrics.unsubscribe_email_address.record(request)

    return r2r('unsubscribe.django.html', locals())
Пример #28
0
def direct_to_django_template(request, template, **kwargs):
    return r2r('%s' % template, dict(kwargs, request=request))
Пример #29
0
def processlist(request):
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("SHOW FULL PROCESSLIST")
    processlist = cursor.fetchall()
    return r2r('staff/processlist.django.html', locals())
Пример #30
0
def epic_sticker_messages(request):
    stickers = CommentSticker.objects.exclude(epic_message='').order_by('-id')
    total = len(stickers)
    return r2r('staff/epic_sticker_messages.django.html', locals())