myprecious/__main__.py (view raw)
1from flask import Flask, request, render_template, url_for, redirect
2from flask_login import LoginManager, UserMixin, login_user, logout_user, current_user
3from werkzeug.utils import secure_filename
4from contextlib import suppress
5from Db import init_db, get_user_from_username, get_user_from_id, add_user_to_queue
6import os, json, base64
7import Constants as c
8if c.DEBUG_SWITCH:
9 from GamesApiTest import search_game
10else:
11 from GamesApi import search_game
12
13app = Flask(__name__)
14login_manager = LoginManager(app)
15
16class User(UserMixin):
17 def __init__(self, user_id, username, password, email):
18 self.id = user_id
19 self.username = username
20 self.password = password
21 self.email = email
22
23def construct_user(id, username, password, email):
24 try:
25 return User(int(id), username, password, email)
26 except TypeError:
27 return None
28
29def render(template):
30 return render_template(template, user=current_user)
31
32def handle_platform(game, platform):
33 try:
34 game_cover = "https:" + game["cover"]["url"]
35 except KeyError:
36 game_cover = c.MISSING_COVER_URL
37 temp_obj = {
38 "game_id": game["id"],
39 "platform_id": platform["id"],
40 "cover": game_cover,
41 "title": game["name"],
42 "platform": platform["name"]
43 }
44 temp_json = json.dumps(temp_obj)
45 temp_bytes = temp_json.encode("utf-8")
46 temp_base64 = base64.b64encode(temp_bytes)
47 temp_obj["info"] = temp_base64.decode("utf-8")
48 return temp_obj
49
50def handle_response(response):
51 return [ [ handle_platform(game, platform) for platform in game["platforms"] ] for game in response ]
52
53def collapse_list_of_lists(l):
54 return [ item for sublist in l for item in sublist ]
55
56@login_manager.user_loader
57def load_user(user_id):
58 lu = get_user_from_id(user_id)
59 if lu is None:
60 return None
61 return construct_user(lu[0], lu[1], lu[2], lu[3])
62
63@app.route('/')
64def route_index():
65 return render("index.html")
66
67@app.route('/login', methods=['GET', 'POST'])
68def route_login():
69 if current_user.is_authenticated:
70 return redirect('/')
71
72 if request.method == "GET":
73 return render("login.html")
74
75 form = request.form
76 username = form["username"].lower()
77 password = form["password"]
78 try:
79 remember = bool(form["remember"])
80 except KeyError:
81 remember = False
82
83 r = get_user_from_username(username)
84 if r is None:
85 return render_template("login.html", user=current_user, last_user=username)
86 user = construct_user(r[0], r[1], r[2], r[3])
87
88 if user is None:
89 return redirect(url_for("login"))
90
91 if user.password == password:
92 login_user(user, remember=remember)
93 return redirect("/")
94 else:
95 return render_template("login.html", user=current_user, last_user=username)
96
97@app.route('/register', methods=['GET', 'POST'])
98def route_register():
99 if current_user.is_authenticated:
100 return redirect('/')
101
102 if request.method == "GET":
103 return render("register.html")
104
105 form = request.form
106 username = form["username"].lower()
107 email = form["email"].lower()
108 password = form["password"]
109
110 if len(password) < c.MIN_PW_LENGTH or len(username) < c.MIN_USERNAME_LENGTH:
111 return render_template("register.html", user=current_user, error="Your username or password is too short.")
112
113 if len(password) > c.MAX_LENGTH or len(username) > c.MAX_LENGTH:
114 return render_template("register.html", user=current_user, error="Your username or password is too long.")
115
116 res = add_user_to_queue(username, password, email)
117 if res == None:
118 return render_template("register.html", user=current_user, error="This username is already registered.")
119 return render("register_done.html")
120
121@app.route('/logout')
122def route_logout():
123 logout_user()
124 return redirect("/")
125
126@app.route('/search', methods=['GET', 'POST'])
127def route_search():
128 if not current_user.is_authenticated:
129 return redirect('/login')
130 if request.method == 'GET':
131 return render("search.html")
132
133 query = request.form["query"]
134 search_response = search_game(query)
135
136 games = collapse_list_of_lists(handle_response(search_response))
137 return render_template("search.html", user=current_user, games=games, query=query)
138
139@app.route('/upload', methods=['GET', 'POST'])
140def route_upload():
141 if not current_user.is_authenticated:
142 return redirect('/login')
143 if request.method == 'GET':
144 info = request.args.get("info")
145 if info is None:
146 return render_template("upload.html", user=current_user, game=c.NO_GAME)
147 # info = base64
148 base64_bytes = info.encode('utf-8')
149 message_bytes = base64.b64decode(base64_bytes)
150 message = message_bytes.decode('utf-8')
151 game = json.loads(message)
152 return render_template("upload.html", user=current_user, game=game)
153
154 f = request.files['file']
155 try:
156 game_id = int(request.form['game_id'])
157 platform_id = int(request.form['platform_id'])
158 except ValueError:
159 return redirect("/upload")
160
161 # TODO: use IGDB api to validate game_id, platform_id and title before adding
162 # TODO: save game in DB
163
164 save_folder = os.path.join(c.BASE_DIRECTORY, c.CONTENT_DIRECTORY, str(current_user.id), str(game_id), str(platform_id))
165 with suppress(FileExistsError):
166 os.makedirs(save_folder)
167 if f.filename is None:
168 return redirect("/upload")
169 save_file = os.path.join(save_folder, secure_filename(f.filename))
170 f.save(save_file)
171 return render("index.html")
172
173
174@app.route('/admin', methods=['GET', 'POST'])
175def route_admin():
176 if not current_user.is_authenticated:
177 return redirect('/')
178
179 if current_user.id != 1:
180 return redirect('/')
181
182 if request.method == "GET":
183 return render("admin.html")
184
185 return render("admin.html")
186
187@app.route('/about')
188def route_about():
189 return render("about.html")
190
191if __name__ == "__main__":
192 app.debug=c.DEBUG_SWITCH
193 app.secret_key = c.SECRET_KEY
194 app.config['SESSION_TYPE'] = 'filesystem'
195 init_db()
196 app.run(port=1111)