Creating Wishlist2Text website – Part 2

Hello, this is a second post from a series how I build https://wishlist2text.appspot.com
You can read the previous post here. Here I am going to create first flask blueprint. Inside of wishlist2text create a folder scan_wishlist. This will be the first blueprint. Let start by creating our first form. In scan_wishlist create a file named form.py. Additional python package needs to be installed for forms.

pip install flask-wtf

Open form.py and add:

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired


class SteamidForm(FlaskForm):
    steam_id = StringField("SteamID", validators=[DataRequired()])
    submit = SubmitField("Scan")

Le’ts go line by line. At first line, I am importing FlaskForm, which is base class for all next class forms. Then I am importing form fields and validators. Then I define class SteamidForm which will be responsible to get the right output from a user. In this form, I define two fields steam_id which has a type of String and submit button which is a type of Submit field.
Next file I will create the helper.py. This file will contain a function for API call to steam. How I create it can be found in my previous posts: Steam wishlist scrapper and Get steam wishlist by username. I just final content of this file here:

import argparse
import requests
from wishlist2text.config import Config


def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-s",
        "--steam-id",
        dest="steam_id",
        help="Provide your steam ID or Steam username",
    )
    return parser.parse_args()


def get_steam_id(identificator, api_key):
    steamid = requests.get(
        f"{Config.RESOLVE_VANITY}/?key={api_key}&vanityurl={identificator}"
    )
    steamid.raise_for_status()

    steamid_response = steamid.json()["response"]
    if ("message" in steamid_response) and (
        steamid_response["message"] == "No match"
    ):
        steamid = identificator
    else:
        steamid = steamid_response["steamid"]

    test_user_exist = requests.get(
        f"{Config.GET_PLAYER_SUMMARIES_API}/?key={api_key}&steamids={steamid}"
    ).json()["response"]["players"]

    if "player" in test_user_exist and test_user_exist["player"] == [None]:
        return None

    return steamid


def scrap_wishlist(steamid):
    page_number = 0
    games_list = []

    while True:
        page = requests.get(
            f"{Config.WISHLIST_URL}/{steamid}/wishlistdata/?p={page_number}"
        ).json()

        if len(page) < 2:
            break

        games_list.extend(value["name"] for value in page.values())

        page_number += 1

    return sorted(games_list)


if __name__ == "__main__":
    steam_user = get_steam_id(get_arguments().steam_id, Config.API_KEY)
    for game in scrap_wishlist(steam_user):
        print(game)

Next, I will create routes.py. This file will contain routing logic. As usual start with imports.

from flask import Blueprint, flash, render_template, request
from wishlist2text.config import Config
from wishlist2text.scan_wishlist.form import SteamidForm
from wishlist2text.scan_wishlist.helper import get_steam_id, scrap_wishlist

In the first line, I am importing packages from the flask which I will use. In the rest of imports, I am importing packages previously created. Create a flask blueprint. Flask can be used without blueprints, but in my opinion, it helps to have a better organized file structure. 

wishlist = Blueprint("wishlist", __name__)

Current, I have only on the route and it is /. Let define it. 

@wishlist.route("/", methods=["GET", "POST"])
def scan_steam():
    form = SteamidForm()
    if form.validate_on_submit():
        steam_id = get_steam_id(request.form["steam_id"], Config.API_KEY)
        games = scrap_wishlist(steam_id)
        if not games:
            flash("Was not able to scan wishlist", "danger")
            return render_template("steamid.html", form=form)
        else:
            flash("Wishlist is scanned", "success")
            return render_template("wishlist.html", games=games)
    return render_template("steamid.html", form=form)

On the first line, I am using a decorator. In the first line, I am specifying route / and methods GET and POST. Then I define a function which will be executed when someone opens my website in the browser. I create an instance of my SteamidForm class and check if a form is valid. If the form is valid I am executing two functions from helper file get_steam_id and pass steam_id value from form filed by a user using request function from a flask. Then I am executing a scrap_wishlist function and pass steam id returned from get_steam_id. Then I am checking of scrap_wishlist returned some games. If no games returned I display a flash message with content “Was not able to scan wishlist” and bootstrap class “danger”, displaying this message will be implemented in next post in HTML. And render template on which the user needs to enter his steam id or username. If there some games returned I flash message with content “Wishlist is scanned” and bootstrap class “success”. And render template for a user with games list. At the on of function, I render a template with steamid form. This page will be displayed only for the first login before the user enters user id or name in the form. 

In the next, I am going to create HTML templates which are renders by scan_steam function.