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 %}
![Non classificato]({{ url_for('static', filename='lol-rank-icons/provisional.png') }})
{% else %}
![{{ lol.solo_division.name|capitalize }} {{ lol.solo_rank.name }}]({{ url_for('static', filename='lol-rank-icons/' + lol.solo_division.name|lower + )
{% endif %}
-
+
FLEX
-
+
{% if lol.flex_division is none %}
![Non classificato]({{ url_for('static', filename='lol-rank-icons/provisional.png') }})
{% else %}
![{{ lol.flex_division.name|capitalize }} {{ lol.flex_rank.name }}]({{ url_for('static', filename='lol-rank-icons/' + lol.flex_division.name|lower + )
{% endif %}
-
+
3V3
-
+
{% if lol.twtr_division is none %}
![Non classificato]({{ url_for('static', filename='lol-rank-icons/provisional.png') }})
{% 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.most_played_game_id %}
+
+
+
![](https://steamcdn-a.akamaihd.net/steam/apps/{{ steam.most_played_game_id }}/header.jpg)
+
+
+ {% 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__)