diff --git a/db.py b/db.py index 85505711..9642686a 100644 --- a/db.py +++ b/db.py @@ -1,7 +1,7 @@ import datetime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship -from sqlalchemy import Column, BigInteger, Integer, String, DateTime, ForeignKey, Float, Enum, create_engine, UniqueConstraint, PrimaryKeyConstraint, Boolean, or_, LargeBinary +from sqlalchemy import Column, BigInteger, Integer, String, DateTime, ForeignKey, Float, Enum, create_engine, UniqueConstraint, PrimaryKeyConstraint, Boolean, or_, LargeBinary, Text import requests from errors import RequestError, NotFoundError, AlreadyExistingError import re @@ -92,9 +92,10 @@ class Steam(Base): royal = relationship("Royal", lazy="joined") steam_id = Column(String, primary_key=True) - persona_name = Column(String, nullable=False) - avatar_hex = Column(String, nullable=False) + persona_name = Column(String) + avatar_hex = Column(String) trade_token = Column(String) + most_played_game_id = Column(BigInteger) def __repr__(self): return f"" @@ -105,6 +106,9 @@ class Steam(Base): else: return self.steam_id + def most_played_game_url(self): + return f"https://steamcdn-a.akamaihd.net/steam/apps/{self.most_played_game_id}/header.jpg" + def avatar_url(self): return f"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/{self.avatar_hex[0:2]}/{self.avatar_hex}.jpg" @@ -151,7 +155,15 @@ class Steam(Base): j = r.json() self.persona_name = j["response"]["players"][0]["personaname"] self.avatar_hex = re.search(r"https://steamcdn-a\.akamaihd\.net/steamcommunity/public/images/avatars/../(.+).jpg", j["response"]["players"][0]["avatar"]).group(1) - + r = requests.get(f"http://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v0001/?key={config['Steam']['api_key']}&steamid={self.steam_id}&format=json") + if r.status_code != 200: + raise RequestError(f"Steam returned {r.status_code}") + j = r.json() + if "response" not in j \ + or "games" not in j["response"] \ + or len(j["response"]["games"]) < 1: + raise RequestError(f"Game data is private") + self.most_played_game_id = j["response"]["games"][0]["appid"] class RocketLeague(Base): __tablename__ = "rocketleague" @@ -783,6 +795,15 @@ class AprilFoolsBan(Base): datetime = Column(DateTime, nullable=False) +class CustomCSS(Base): + __tablename__ = "customcss" + + royal_id = Column(Integer, ForeignKey("royals.id"), primary_key=True) + royal = relationship("Royal", lazy="joined") + + css = Column(Text, nullable=False) + + # If run as script, create all the tables in the db if __name__ == "__main__": print("Creating new tables...") diff --git a/newuser.py b/newuser.py index 7e1945a8..e682fd79 100644 --- a/newuser.py +++ b/newuser.py @@ -13,18 +13,18 @@ except Exception as e: print(e) else: session.add(steam) -try: - dota = db.Dota.create(session, steam.steam_id) -except Exception as e: - print(e) -else: - session.add(dota) -try: - rl = db.RocketLeague.create(session, steam.steam_id) -except Exception as e: - print(e) -else: - session.add(rl) + try: + dota = db.Dota.create(session, steam.steam_id) + except Exception as e: + print(e) + else: + session.add(dota) + try: + rl = db.RocketLeague.create(session, steam.steam_id) + except Exception as e: + print(e) + else: + session.add(rl) try: osu = db.Osu.create(session, user.id, input("Osu! username: ")) except Exception as e: diff --git a/static/nryg.less b/static/nryg.less index 92fa310b..1aeee5ba 100644 --- a/static/nryg.less +++ b/static/nryg.less @@ -48,6 +48,30 @@ input[type="text"], input[type="password"] { border-radius: 10px; margin: 4px; position: relative; + + .game-title { + grid-row: 2; + font-size: smaller; + } + + .game-score { + grid-row: 3; + } + + .player { + grid-row: 1; + font-size: large; + + a { + text-decoration: none; + } + + .player-image { + width: 32px; + height: 32px; + vertical-align: middle; + } + } } .osu { @@ -57,6 +81,7 @@ input[type="text"], input[type="password"] { color: #ffffff; padding: 10px; grid-row-gap: 5px; + grid-template-columns: 25% 25% 25% 25%; .background-image { position: absolute; @@ -82,17 +107,9 @@ input[type="text"], input[type="password"] { grid-row: 1; grid-column-start: 1; grid-column-end: 4; - font-size: large; - - a { - text-decoration: none; - } .player-image { - width: 32px; - height: 32px; border-radius: 16px; - vertical-align: middle; } .player-name { @@ -101,15 +118,9 @@ input[type="text"], input[type="password"] { } .game-title { - grid-row: 2; - font-size: smaller; font-style: normal; } - .game-score { - grid-row: 3; - } - .standard { grid-column: 1; } @@ -138,6 +149,7 @@ input[type="text"], input[type="password"] { .rl { background-image: linear-gradient(to bottom,rgba(35,91,139,.5),rgba(16,54,84,.5)), linear-gradient(to right,rgba(35,91,139,.7),rgba(16,54,84,.7)); + grid-template-columns: 25% 25% 25% 25%; padding: 18px; grid-row-gap: 5px; @@ -145,39 +157,23 @@ input[type="text"], input[type="password"] { grid-row: 1; grid-column-start: 1; grid-column-end: 4; - font-size: large; - - a { - text-decoration: none; - } - - .player-image { - width: 32px; - height: 32px; - vertical-align: middle; - } .player-name { - vertical-align: middle; color: #ffffff; + text-shadow: 2px 2px 8px #359ef2, -2px 2px 8px #359ef2, 2px -2px 8px #359ef2, -2px -2px 8px #359ef2; } } .game-title { - grid-row: 2; - font-size: smaller; text-align: center; color: #41abfa; + text-shadow: 2px 2px 8px #235b8b, -2px 2px 8px #235b8b, 2px -2px 8px #235b8b, -2px -2px 8px #235b8b; } - .game-score { - grid-row: 3; - - img { - height: 36px; - display: block; - margin: auto; - } + .game-score img { + height: 36px; + display: block; + margin: auto; } .duel { @@ -203,6 +199,7 @@ input[type="text"], input[type="password"] { border: 3px solid #000000; grid-row-gap: 5px; grid-template-columns: 25% 75%; + font-family: "Radiance", sans-serif; background-image: linear-gradient(to bottom, #440b0b, #631013); color: #ffffff; @@ -210,30 +207,13 @@ input[type="text"], input[type="password"] { grid-row: 1; grid-column-start: 1; grid-column-end: 3; - font-size: large; - - a { - text-decoration: none; - } - - .player-image { - width: 32px; - height: 32px; - vertical-align: middle; - } .player-name { color: #ffffff; } } - .title { - grid-row: 2; - font-size: x-small; - } - - .number { - grid-row: 3; + .game-score.wins { font-size: x-large; } @@ -242,10 +222,6 @@ input[type="text"], input[type="password"] { text-align: center; } - .wins.number { - color: #ffb600; - } - .rank { grid-column: 2; grid-row-start: 2; @@ -259,14 +235,14 @@ input[type="text"], input[type="password"] { img.stars { position: relative; - height: 44px; - left: -44px; - margin-right: -44px; + height: 60px; + left: -60px; + margin-right: -60px; z-index: 1; } img.medal { - height: 44px; + height: 60px; } } } @@ -278,27 +254,23 @@ input[type="text"], input[type="password"] { border: 3px solid #463714; background-color: #010a13; grid-row-gap: 5px; + grid-template-columns: 40% 20% 20% 20%; .player { grid-row: 1; grid-column-start: 1; grid-column-end: 4; - font-size: large; - - a { - text-decoration: none; - } .player-image { - width: 32px; - height: 32px; - vertical-align: middle; border-radius: 16px; } } .level { grid-column: 1; + } + + .game-score.level { font-size: x-large; } @@ -314,14 +286,11 @@ input[type="text"], input[type="password"] { grid-column: 4; } - .title { - grid-row: 2; - font-size: x-small; + .game-title { text-align: center; } - .value { - grid-row: 3; + .game-score { text-align: center; margin: auto; } @@ -329,4 +298,59 @@ input[type="text"], input[type="password"] { .rank { height: 40px; } +} + +.steam { + font-family: "Motiva Sans", sans-serif; + padding: 18px; + background: url("https://steamstore-a.akamaihd.net/public/images/v6/colored_body_top2.png?v=2") center; + + .player .player-name { + grid-row: 1; + grid-column: 1; + color: #ffffff; + } + + .buttons { + grid-row: 2; + grid-column-start: 1; + grid-column-end: 3; + } + + .game-banner { + grid-row: 1; + grid-column: 2; + text-align: right; + + img { + height: 58px; + border-radius: 4px; + } + } + + a { + text-decoration: none; + display: inline-block; + } + + .button { + background-color: rgba(0,0,0,0.4); + color: #9e9d9b; + width: 32px; + height: 32px; + border-radius: 4px; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + } + + .button:hover, .button:active { + background-color: rgba(102,192,244,0.4); + color: #ffffff; + } +} + +#edit-css { + font-size: medium; } \ No newline at end of file diff --git a/templates/main.html b/templates/main.html index d83e1b52..f8530a83 100644 --- a/templates/main.html +++ b/templates/main.html @@ -12,6 +12,11 @@ Benvenuto al sito web della Royal Games! E' ancora un po' triste e spoglio, ma spero che collaboriate a migliorarlo!

- Attualmente, sto sviluppando i profili RYG! Clicca qui per vedere il tuo. + Attualmente, sto sviluppando i profili RYG!

+ {% endblock %} \ No newline at end of file diff --git a/templates/minis/dota.html b/templates/minis/dota.html index 21e3e430..dcebfce1 100644 --- a/templates/minis/dota.html +++ b/templates/minis/dota.html @@ -1,15 +1,23 @@ +
-
+
Vittorie
-
+
{{ dota.wins }}
diff --git a/templates/minis/lol.html b/templates/minis/lol.html index b7dd7f5f..c49e0d3e 100644 --- a/templates/minis/lol.html +++ b/templates/minis/lol.html @@ -10,36 +10,36 @@ {{ lol.summoner_name }}
-
+
LIVELLO
-
+
{{ lol.level }}
-
+
SOLO/DUO
-
+
{% if lol.solo_division is none %} {% else %} {% endif %}
-
+
FLEX
-
+
{% if lol.flex_division is none %} {% else %} {% endif %}
-
+
3V3
-
+
{% if lol.twtr_division is none %} {% else %} diff --git a/templates/minis/rl.html b/templates/minis/rl.html index 50856cc7..8f7ecc73 100644 --- a/templates/minis/rl.html +++ b/templates/minis/rl.html @@ -4,7 +4,7 @@
- + {{ rl.steam.persona_name }} diff --git a/templates/minis/steam.html b/templates/minis/steam.html new file mode 100644 index 00000000..3e6909ef --- /dev/null +++ b/templates/minis/steam.html @@ -0,0 +1,45 @@ + + +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ {% if steam.trade_token %} + +
+ +
+
+ {% endif %} +
+ {% if steam.most_played_game_id %} + +
+ +
+
+ {% endif %} +
+
\ No newline at end of file diff --git a/templates/profile.html b/templates/profile.html index 0c2c4711..dd67a638 100644 --- a/templates/profile.html +++ b/templates/profile.html @@ -4,12 +4,20 @@ {{ royal.username }} {% endblock %} +{% block posthead %} + {% if css %} + + {% endif %} +{% endblock %} + {% block body %}

- Profilo di {{ royal.username }} + Profilo di {{ royal.username }} {% if session.get('user_id', '') == royal.id %}Modifica{% endif %}

- {% if osu %} - {% include "minis/osu.html" %} + {% if steam %} + {% include "minis/steam.html" %} {% endif %} {% if rl %} {% include "minis/rl.html" %} @@ -17,6 +25,9 @@ {% if dota %} {% include "minis/dota.html" %} {% endif %} + {% if osu %} + {% include "minis/osu.html" %} + {% endif %} {% if lol %} {% include "minis/lol.html" %} {% endif %} diff --git a/templates/setcss.html b/templates/setcss.html new file mode 100644 index 00000000..6c45ed3d --- /dev/null +++ b/templates/setcss.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} + +{% block pagetitle %} + CSS +{% endblock %} + +{% block body %} +

+ CSS +

+
+ + +
+{% endblock %} \ No newline at end of file diff --git a/webserver.py b/webserver.py index 387dbd98..cffc671b 100644 --- a/webserver.py +++ b/webserver.py @@ -1,10 +1,8 @@ from flask import Flask, render_template, request, abort, redirect, url_for from flask import session as fl_session import db -from sqlalchemy import func, alias import bcrypt import configparser -import requests app = Flask(__name__) @@ -19,8 +17,11 @@ app.secret_key = config["Flask"]["secret_key"] @app.route("/") def page_main(): - if fl_session.get("username"): - return render_template("main.html", easter_egg=config["Flask"]["easter_egg"]) + if fl_session.get("user_id"): + db_session = db.Session() + royals = db_session.query(db.Royal).all() + db_session.close() + return render_template("main.html", royals=royals) return redirect(url_for("page_login")) @@ -32,12 +33,14 @@ def page_profile(name: str): db_session.close() abort(404) return + css = db_session.query(db.CustomCSS).filter_by(royal=user).one_or_none() + steam = db_session.query(db.Steam).filter_by(royal=user).one_or_none() osu = db_session.query(db.Osu).filter_by(royal=user).one_or_none() rl = db_session.query(db.RocketLeague).join(db.Steam).filter_by(royal=user).one_or_none() dota = db_session.query(db.Dota).join(db.Steam).filter_by(royal=user).one_or_none() lol = db_session.query(db.LeagueOfLegends).filter_by(royal=user).one_or_none() db_session.close() - return render_template("profile.html", royal=user, osu=osu, rl=rl, dota=dota, lol=lol) + return render_template("profile.html", royal=user, css=css, osu=osu, rl=rl, dota=dota, lol=lol, steam=steam) @app.route("/login") @@ -56,10 +59,10 @@ def page_loggedin(): abort(403) return if user.password is None: - fl_session["username"] = username + fl_session["user_id"] = user.id return redirect(url_for("page_password")) if bcrypt.checkpw(bytes(password, encoding="utf8"), user.password): - fl_session["username"] = username + fl_session["user_id"] = user.id return redirect(url_for("page_main")) else: abort(403) @@ -68,16 +71,16 @@ def page_loggedin(): @app.route("/password", methods=["GET", "POST"]) def page_password(): - username = fl_session.get("username") + user_id = fl_session.get("user_id") if request.method == "GET": - if username is None: + if user_id is None: abort(403) return return render_template("password.html") elif request.method == "POST": new_password = request.form.get("new", "") db_session = db.Session() - user = db_session.query(db.Royal).filter_by(username=username).one() + user = db_session.query(db.Royal).filter_by(id=user_id).one() if user.password is None: user.password = bcrypt.hashpw(bytes(new_password, encoding="utf8"), bcrypt.gensalt()) db_session.commit() @@ -89,6 +92,32 @@ def page_password(): return +@app.route("/setcss", methods=["GET", "POST"]) +def page_setcss(): + user_id = fl_session.get("user_id") + db_session = db.Session() + ccss = db_session.query(db.CustomCSS).filter_by(royal_id=user_id).one_or_none() + if request.method == "GET": + db_session.close() + if user_id is None: + abort(403) + return + return render_template("setcss.html", css=ccss.css) + elif request.method == "POST": + if user_id is None: + abort(403) + return + if ccss is None: + ccss = db.CustomCSS(royal_id=user_id, css=request.form.get("css", "")) + db_session.add(ccss) + else: + ccss.css = request.form.get("css", "") + db_session.commit() + royal = db_session.query(db.Royal).filter_by(id=user_id).one() + db_session.close() + return redirect(url_for("page_profile", name=royal.username)) + + if __name__ == "__main__": try: app.run(host="0.0.0.0", port=1234, debug=__debug__)