Ejemplo n.º 1
0
def patreon_oauth_callback(request):
    code = request.GET.get("code")
    if not code:
        return render(
            request, "error.html", {
                "title": "Что-то сломалось между нами и патреоном",
                "message": "Так бывает. Попробуйте залогиниться еще раз"
            })

    try:
        auth_data = patreon.fetch_auth_data(code)
        user_data = patreon.fetch_user_data(auth_data["access_token"])
    except PatreonException as ex:
        if "invalid_grant" in str(ex):
            return render(
                request, "error.html", {
                    "title":
                    "Тут такое дело 😭",
                    "message":
                    "Авторизация патреона — говно. "
                    "Она не сразу понимает, что вы стали патроном и отдаёт "
                    "статус «отказано» в первые несколько минут, а иногда и часов. "
                    "Я уже написал им в саппорт, но пока вам надо немного подождать и авторизоваться снова. "
                    "Если долго не будет пускать — напишите мне в личку на патреоне."
                })

        return render(
            request, "error.html", {
                "message":
                "Не получилось загрузить ваш профиль с серверов патреона. "
                "Попробуйте еще раз, наверняка оно починится. "
                f"Но если нет, то вот текст ошибки, с которым можно пожаловаться мне в личку:",
                "data":
                str(ex)
            })

    membership = patreon.parse_active_membership(user_data)
    if not membership:
        return render(
            request, "error.html", {
                "title":
                "Надо быть патроном, чтобы состоять в Клубе",
                "message":
                "Кажется, вы не патроните <a href=\"https://www.patreon.com/join/vas3k\">@vas3k</a>. "
                "А это одно из основных требований для входа в Клуб.<br><br>"
                "Ещё иногда бывает, что ваш банк отказывает патреону в снятии денег. "
                "Проверьте, всё ли там у них в порядке."
            })

    now = datetime.utcnow()
    user, is_created = User.objects.get_or_create(
        membership_platform_type=User.MEMBERSHIP_PLATFORM_PATREON,
        membership_platform_id=membership.user_id,
        defaults=dict(
            email=membership.email,
            full_name=membership.full_name[:120],
            avatar=upload_image_from_url(membership.image)
            if membership.image else None,
            membership_started_at=membership.started_at,
            membership_expires_at=membership.expires_at,
            created_at=now,
            updated_at=now,
            is_email_verified=False,
            is_profile_complete=False,  # redirect new users to an intro page
        ),
    )

    if is_created:
        user.balance = membership.lifetime_support_cents / 100
    else:
        user.membership_expires_at = membership.expires_at
        user.balance = membership.lifetime_support_cents / 100  # TODO: remove when the real money comes in

    user.membership_platform_data = {
        "access_token": auth_data["access_token"],
        "refresh_token": auth_data["refresh_token"],
    }
    user.save()

    session = Session.objects.create(
        user=user,
        token=random_string(length=32),
        created_at=now,
        expires_at=user.membership_expires_at,
    )

    redirect_to = reverse("profile", args=[user.slug])

    state = request.GET.get("state")
    if state:
        redirect_to += f"?{state}"

    response = redirect(redirect_to)
    response.set_cookie(
        key="token",
        value=session.token,
        max_age=settings.SESSION_COOKIE_AGE,
        httponly=True,
        secure=not settings.DEBUG,
    )
    return response
Ejemplo n.º 2
0
def initialize(config, board_slug, upload_favicons, always_yes):
    yaml_file = os.path.join(BASE_DIR, config)
    with open(yaml_file) as f:
        try:
            config = yaml.load(f.read(), Loader=yaml.FullLoader)
        except yaml.YAMLError as ex:
            print(f"Bad YAML file '{yaml_file}': {ex}")
            exit(1)

    if not always_yes:
        input(
            f"Initializing feeds from {yaml_file}. Press Enter to continue...")

    for board_index, board_config in enumerate(config.get("boards") or []):
        if board_slug and board_config["slug"] != board_slug:
            continue

        board_name = board_config.get("name") or board_config["slug"]
        print(f"Creating board: {board_name}...")
        board, is_created = Board.objects.update_or_create(
            slug=board_config["slug"],
            defaults=dict(
                name=board_name or board_config["slug"],
                avatar=board_config["curator"].get("avatar"),
                curator_name=board_config["curator"].get("name"),
                curator_title=board_config["curator"].get("title"),
                curator_footer=board_config["curator"].get("footer"),
                curator_bio=board_config["curator"].get("bio"),
                curator_url=board_config["curator"].get("url"),
                is_private=board_config.get("is_private"),
                is_visible=board_config.get("is_visible"),
                index=board_index,
            ))

        for block_index, block_config in enumerate(
                board_config.get("blocks") or []):
            block_name = block_config.get("name") or ""
            print(f"\nCreating block: {block_name}...")
            block, is_created = BoardBlock.objects.update_or_create(
                board=board,
                slug=block_config["slug"],
                defaults=dict(
                    name=block_name,
                    index=block_index,
                    view=block_config.get("view") or BoardBlock.DEFAULT_VIEW,
                ))

            if not block_config.get("feeds"):
                continue

            updated_feed_urls = set()

            for feed_index, feed_config in enumerate(
                    block_config.get("feeds") or []):
                feed_name = feed_config.get("name")
                feed_mix = feed_config.get("mix")
                if feed_mix:
                    feed_url = feed_config.get(
                        "url") or f"mix:{'|'.join(feed_mix)}"
                    feed_rss = None
                else:
                    feed_url = feed_config["url"]
                    feed_rss = feed_config["rss"]

                updated_feed_urls.add(feed_url)

                print(f"Creating or updating feed {feed_name} ({feed_url})...")

                feed, is_created = BoardFeed.objects.update_or_create(
                    board=board,
                    block=block,
                    url=feed_url,
                    defaults=dict(
                        rss=feed_rss,
                        mix=feed_mix,
                        name=feed_name,
                        comment=feed_config.get("comment"),
                        icon=feed_config.get("icon"),
                        index=feed_index,
                        columns=feed_config.get("columns") or 1,
                        conditions=feed_config.get("conditions"),
                        is_parsable=feed_config.get("is_parsable", True),
                        view=feed_config.get("view") or BoardFeed.DEFAULT_VIEW,
                    ))

                html = None

                if not feed.mix:
                    if not feed.icon:
                        feed.icon = DOMAIN_FAVICONS.get(parse_domain(feed_url))

                    if not feed.icon:
                        html = html or load_page_html(feed_url)
                        icon = feed_config.get("icon")
                        if not icon:
                            icon = find_favicon(feed_url, html)
                            print(f"- found favicon: {icon}")

                            if upload_favicons:
                                icon = upload_image_from_url(icon)
                                print(f"- uploaded favicon: {icon}")

                        feed.icon = icon

                feed.save()

            # delete unused feeds
            BoardFeed.objects.filter(
                board=board,
                block=block).exclude(url__in=updated_feed_urls).delete()

        # delete unused blocks
        BoardBlock.objects.filter(board=board, ).exclude(slug__in={
            block["slug"]
            for block in board_config.get("blocks") or []
        }).delete()

    print("Done ✅")
Ejemplo n.º 3
0
def patreon_oauth_callback(request):
    code = request.GET.get("code")
    if not code:
        return render(
            request, "error.html", {
                "message":
                "Что-то сломалось между нами и патреоном. Так бывает. Попробуйте залогиниться еще раз."
            })

    try:
        auth_data = patreon.fetch_auth_data(code)
        user_data = patreon.fetch_user_data(auth_data["access_token"])
    except PatreonException as ex:
        if "invalid_grant" in str(ex):
            return render(
                request, "error.html", {
                    "message":
                    "Тут такое дело. Авторизация патреона — говно. "
                    "Она не сразу понимает, что вы стали моим патроном и отдаёт мне ошибку. "
                    "Я уже написал им в саппорт, но пока вам надо немного подождать и авторизоваться снова. "
                    "Обычно тогда срабатывает. Если нет — напишите мне в личные сообщения на патреоне."
                })

        return render(
            request, "error.html", {
                "message":
                "Не получилось загрузить ваш профиль с серверов патреона. "
                "Попробуйте еще раз, наверняка оно починится. "
                f"Но если нет, то вот текст ошибки, с которым можно пожаловаться мне в личку:",
                "data":
                str(ex)
            })

    membership = patreon.parse_active_membership(user_data)
    if not membership:
        return render(
            request, "error.html", {
                "message":
                "Надо быть патроном чтобы состоять в клубе.<br>"
                '<a href="https://www.patreon.com/join/vas3k">Станьте им здесь!</a>'
            })

    now = datetime.utcnow()
    user, is_created = User.objects.get_or_create(
        membership_platform_type=User.MEMBERSHIP_PLATFORM_PATREON,
        membership_platform_id=membership.user_id,
        defaults=dict(
            email=membership.email,
            full_name=membership.full_name[:120],
            avatar=upload_image_from_url(membership.image)
            if membership.image else None,
            membership_started_at=membership.started_at,
            membership_expires_at=membership.expires_at,
            created_at=now,
            updated_at=now,
            is_email_verified=False,
            is_profile_complete=False,  # redirect new users to an intro page
        ),
    )

    if is_created:
        user.balance = membership.lifetime_support_cents / 100
    else:
        user.membership_expires_at = membership.expires_at
        user.balance = membership.lifetime_support_cents / 100  # TODO: remove when the real money comes in

    user.membership_platform_data = {
        "access_token": auth_data["access_token"],
        "refresh_token": auth_data["refresh_token"],
    }
    user.save()

    session = Session.objects.create(
        user=user,
        token=random_string(length=32),
        created_at=now,
        expires_at=first_day_of_next_month(now),
    )

    redirect_to = reverse("profile", args=[user.slug])

    state = request.GET.get("state")
    if state:
        redirect_to += f"?{state}"

    response = redirect(redirect_to)
    response.set_cookie(
        key="token",
        value=session.token,
        max_age=settings.SESSION_COOKIE_AGE,
        httponly=True,
        secure=not settings.DEBUG,
    )
    return response
Ejemplo n.º 4
0
def initialize(config, board_slug, upload_favicons, always_yes):
    yaml_file = os.path.join(BASE_DIR, config)
    with open(yaml_file) as f:
        try:
            config = yaml.load(f.read(), Loader=yaml.FullLoader)
        except yaml.YAMLError as ex:
            print(f"Bad YAML file '{yaml_file}': {ex}")
            exit(1)

    if not always_yes:
        input(
            f"Initializing feeds from {yaml_file}. Press Enter to continue...")

    for board_index, board_config in enumerate(config.get("boards") or []):
        if board_slug and board_config["slug"] != board_slug:
            continue

        board_name = board_config.get("name") or board_config["slug"]
        print(f"Creating board: {board_name}...")
        board, is_created = Board.objects.get_or_create(
            slug=board_config["slug"],
            defaults=dict(
                name=board_name,
                avatar=board_config["curator"].get("avatar"),
                curator_name=board_config["curator"].get("name"),
                curator_title=board_config["curator"].get("title"),
                curator_footer=board_config["curator"].get("footer"),
                curator_bio=board_config["curator"].get("bio"),
                curator_url=board_config["curator"].get("url"),
                is_private=board_config.get("is_private"),
                is_visible=board_config.get("is_visible"),
                index=board_index,
            ))
        if not is_created:
            # update existing values
            board.name = board_config.get("name") or board_config["slug"]
            board.avatar = board_config["curator"].get("avatar")
            board.curator_name = board_config["curator"].get("name")
            board.curator_title = board_config["curator"].get("title")
            board.curator_footer = board_config["curator"].get("footer")
            board.curator_bio = board_config["curator"].get("bio")
            board.curator_url = board_config["curator"].get("url")
            board.is_private = board_config.get("is_private")
            board.is_visible = board_config.get("is_visible")
            board.index = board_index
            board.save()

        for block_index, block_config in enumerate(
                board_config.get("blocks") or []):
            block_name = block_config.get("name") or ""
            print(f"\nCreating block: {block_name}...")
            block, is_created = BoardBlock.objects.get_or_create(
                board=board,
                slug=block_config["slug"],
                defaults=dict(name=block_name, index=block_index))

            if not is_created:
                block.index = block_index
                block.name = block_name
                block.save()

            if not block_config.get("feeds"):
                continue

            for feed_index, feed_config in enumerate(
                    block_config.get("feeds") or []):
                feed_name = feed_config.get("name")
                feed_url = feed_config["url"]

                print(f"Creating or updating feed: {feed_name}...")

                feed, is_created = BoardFeed.objects.get_or_create(
                    board=board,
                    block=block,
                    url=feed_config["url"],
                    defaults=dict(rss=feed_config.get("rss"),
                                  name=feed_name,
                                  comment=feed_config.get("comment"),
                                  icon=feed_config.get("icon"),
                                  index=feed_index,
                                  columns=feed_config.get("columns") or 1,
                                  conditions=feed_config.get("conditions"),
                                  is_parsable=feed_config.get(
                                      "is_parsable", True)))

                if not is_created:
                    feed.rss = feed_config.get("rss")
                    feed.name = feed_name
                    feed.comment = feed_config.get("comment")
                    feed.index = feed_index
                    feed.columns = feed_config.get("columns") or 1
                    feed.conditions = feed_config.get("conditions")
                    feed.is_parsable = feed_config.get("is_parsable", True)

                html = None

                if not feed.rss:
                    html = html or load_page_html(feed_url)
                    rss_url = feed_config.get("rss")
                    if not rss_url:
                        rss_url = find_rss_feed(feed_url, html)
                        if not rss_url:
                            print(f"RSS feed for '{feed_name}' not found. "
                                  f"Please specify 'rss' key.")
                            exit(1)
                        print(f"- found RSS: {rss_url}")

                    feed.rss = rss_url

                if not feed.icon:
                    html = html or load_page_html(feed_url)
                    icon = feed_config.get("icon")
                    if not icon:
                        icon = find_favicon(feed_url, html)
                        print(f"- found favicon: {icon}")

                        if upload_favicons:
                            icon = upload_image_from_url(icon)
                            print(f"- uploaded favicon: {icon}")

                    feed.icon = icon

                feed.save()

            # delete unused feeds
            BoardFeed.objects.filter(
                board=board, block=block).exclude(url__in={
                    feed["url"]
                    for feed in block_config.get("feeds") or []
                }).delete()

        # delete unused blocks
        BoardBlock.objects.filter(board=board, ).exclude(slug__in={
            block["slug"]
            for block in board_config.get("blocks") or []
        }).delete()

    print("Done ✅")