diff --git a/.gitignore b/.gitignore index 11530b5..e5543ec 100644 --- a/.gitignore +++ b/.gitignore @@ -185,3 +185,5 @@ cython_debug/ gacha_game*.db gacha_game*.db.* config*.ini + +.idea \ No newline at end of file diff --git a/web/app.py b/web/app.py index f68084c..61ed38f 100644 --- a/web/app.py +++ b/web/app.py @@ -1,6 +1,8 @@ -from flask import Flask, render_template import sqlite3 +from flask import Flask, render_template, abort +from werkzeug.exceptions import HTTPException + app = Flask(__name__) DB_PATH = "./gacha_game.db" # Adjust path if needed @@ -9,6 +11,14 @@ def get_db_connection(): conn.row_factory = sqlite3.Row return conn +@app.errorhandler(HTTPException) +def handle_exception(error): + return render_template("_error.html", error=error), error.code + +@app.route("/i404") +def i404(): + return abort(404) + @app.route('/') def index(): conn = get_db_connection() @@ -33,6 +43,8 @@ def user_profile(user_id): cursor.execute('SELECT * FROM users WHERE id = ?', (user_id,)) user = cursor.fetchone() + if user is None: + abort(404) cursor.execute(''' SELECT pulls.timestamp, characters.name as character_name, characters.rarity diff --git a/web/static/style.css b/web/static/style.css new file mode 100644 index 0000000..74231c1 --- /dev/null +++ b/web/static/style.css @@ -0,0 +1,92 @@ +body { + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + background-color: #f4f6fa; + color: #333; + margin: 0; + padding: 0; + } + + header { + background-color: #7289da; + color: white; + padding: 20px; + text-align: center; + } + + header h1 { + margin: 0; + font-size: 2.5em; + } + + header p { + margin-top: 5px; + font-size: 1.1em; + } + + .container { + max-width: 800px; + margin: 30px auto; + padding: 20px; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.07); + } + + h2 { + border-bottom: 1px solid #ccc; + padding-bottom: 8px; + margin-top: 30px; + } + + ul { + list-style-type: none; + padding-left: 0; + } + + li { + margin: 10px 0; + } + + a { + text-decoration: none; + color: #2c3e50; + font-weight: bold; + background-color: #e3eaf3; + padding: 8px 12px; + border-radius: 6px; + display: inline-block; + transition: background-color 0.2s; + } + + a:hover { + background-color: #cdd8e6; + } + + .leaderboard-entry { + margin-bottom: 8px; + padding: 6px 10px; + background: #f9fafc; + border-left: 4px solid #7289da; + border-radius: 5px; + } + + footer { + text-align: center; + margin-top: 40px; + font-size: 0.9em; + color: #888; + } + + .note { + background: #fcfcf0; + border: 1px dashed #bbb; + padding: 10px; + border-radius: 8px; + margin-top: 30px; + font-size: 0.95em; + color: #666; + } + + .footer-link { + margin: 0 10px; + } \ No newline at end of file diff --git a/web/templates/_base.html b/web/templates/_base.html new file mode 100644 index 0000000..a1f1b22 --- /dev/null +++ b/web/templates/_base.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> +<head> + <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}"> + <link rel="shortcut icon" href="{{ url_for('static', filename='logo.png') }}"> + <title> + {% if title %} + {{ title }} + {% else %} + {% block title %}{% endblock %} + {% endif %} + | Kemoverse + </title> +</head> +<body> + <header> + {% block header %}{% endblock %} + </header> + + <div class="container"> + {% block content %}{% endblock %} + </div> + + <footer> + <a class="footer-link" href="{{ url_for('about') }}">About</a> + <a class="footer-link" href="{{ url_for('submit_character') }}">Submit a Character</a> + {% block footer_extra %}{% endblock %} + </footer> +</body> +</html> diff --git a/web/templates/_error.html b/web/templates/_error.html new file mode 100644 index 0000000..defc5d8 --- /dev/null +++ b/web/templates/_error.html @@ -0,0 +1,8 @@ +{% extends "_base.html" %} +{% block title %} + {{ error.code }} +{% endblock %} +{% block content %} + <h2>{{ error.code }} - {{ error.name }} </h2> + <p>{{ error.description }}</p> +{% endblock %} \ No newline at end of file diff --git a/web/templates/about.html b/web/templates/about.html index 89519db..184fde9 100644 --- a/web/templates/about.html +++ b/web/templates/about.html @@ -1,13 +1,9 @@ -<!DOCTYPE html> -<html> -<head> - <title>About - Misskey Gacha Center</title> -</head> -<body> +{% extends "_base.html" %} + +{% block content %} <h1>About This Gacha</h1> <p>This is a playful Misskey-themed gacha tracker made with Flask and SQLite.</p> <p>All rolls are stored, stats are tracked, and characters are added manually for now.</p> <p>Built with love, chaos, and way too much caffeine ☕.</p> <a href="{{ url_for('index') }}">← Back to Home</a> -</body> -</html> +{% endblock %} \ No newline at end of file diff --git a/web/templates/index.html b/web/templates/index.html index e9b1680..f9bf7a0 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -1,110 +1,11 @@ -<!DOCTYPE html> -<html> -<head> - <title>Misskey Gacha Center</title> - <style> - body { - font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; - background-color: #f4f6fa; - color: #333; - margin: 0; - padding: 0; - } +{% extends "_base.html" %} - header { - background-color: #7289da; - color: white; - padding: 20px; - text-align: center; - } +{% block header %} + <h1>Misskey Gacha Center</h1> + <p>Track your luck. Compare your pulls. Compete with friends.</p> +{% endblock %} - header h1 { - margin: 0; - font-size: 2.5em; - } - - header p { - margin-top: 5px; - font-size: 1.1em; - } - - .container { - max-width: 800px; - margin: 30px auto; - padding: 20px; - background-color: #ffffff; - border-radius: 10px; - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.07); - } - - h2 { - border-bottom: 1px solid #ccc; - padding-bottom: 8px; - margin-top: 30px; - } - - ul { - list-style-type: none; - padding-left: 0; - } - - li { - margin: 10px 0; - } - - a { - text-decoration: none; - color: #2c3e50; - font-weight: bold; - background-color: #e3eaf3; - padding: 8px 12px; - border-radius: 6px; - display: inline-block; - transition: background-color 0.2s; - } - - a:hover { - background-color: #cdd8e6; - } - - .leaderboard-entry { - margin-bottom: 8px; - padding: 6px 10px; - background: #f9fafc; - border-left: 4px solid #7289da; - border-radius: 5px; - } - - footer { - text-align: center; - margin-top: 40px; - font-size: 0.9em; - color: #888; - } - - .note { - background: #fcfcf0; - border: 1px dashed #bbb; - padding: 10px; - border-radius: 8px; - margin-top: 30px; - font-size: 0.95em; - color: #666; - } - - .footer-link { - margin: 0 10px; - } - </style> -</head> -<body> - - <header> - <h1>Misskey Gacha Center</h1> - <p>Track your luck. Compare your pulls. Compete with friends.</p> - </header> - - <div class="container"> +{% block content %} <h2>🎖️ Leaderboard: Most Rolls</h2> {% for user in top_users %} @@ -125,13 +26,4 @@ <div class="note"> 🚀 This is a fun little gacha tracker! More features coming soon. Want to help shape it? </div> - - </div> - - <footer> - <a class="footer-link" href="{{ url_for('about') }}">About</a> - <a class="footer-link" href="{{ url_for('submit_character') }}">Submit a Character</a> - </footer> - -</body> -</html> +{% endblock %} \ No newline at end of file diff --git a/web/templates/submit.html b/web/templates/submit.html index 5dc5ac9..d0424b8 100644 --- a/web/templates/submit.html +++ b/web/templates/submit.html @@ -1,12 +1,8 @@ -<!DOCTYPE html> -<html> -<head> - <title>Submit a Character - Misskey Gacha Center</title> -</head> -<body> +{% extends "_base.html" %} + +{% block content %} <h1>Submit a Character</h1> <p>Want to add a new character to the gacha pool?</p> <p>This feature will be available soon. Stay tuned!</p> <a href="{{ url_for('index') }}">← Back to Home</a> -</body> -</html> +{% endblock %} \ No newline at end of file diff --git a/web/templates/user.html b/web/templates/user.html index 0004052..8010538 100644 --- a/web/templates/user.html +++ b/web/templates/user.html @@ -1,57 +1,5 @@ -<!DOCTYPE html> -<html> -<head> - <title>{{ user['username'] }}'s Rolls</title> - <style> - body { - font-family: Arial, sans-serif; - background-color: #f4f4f8; - margin: 0; - padding: 20px; - } - .profile, .pulls { - background-color: white; - padding: 15px; - border-radius: 10px; - box-shadow: 0 0 10px rgba(0,0,0,0.1); - margin-bottom: 20px; - } - h1, h2 { - margin-top: 0; - } - ul { - list-style-type: none; - padding: 0; - } - li { - padding: 10px 0; - border-bottom: 1px solid #eee; - } - .rarity { - color: gold; - font-weight: bold; - margin-left: 8px; - } - .timestamp { - color: #888; - font-size: 0.9em; - } - a { - display: inline-block; - margin-top: 20px; - color: #333; - text-decoration: none; - background-color: #ddd; - padding: 8px 12px; - border-radius: 5px; - } - a:hover { - background-color: #bbb; - } - </style> -</head> -<body> - +{% extends "_base.html" %} +{% block content %} <div class="profile"> <h1>{{ user['username'] }}'s Gacha Rolls</h1> <p>User ID: {{ user['id'] }}</p> @@ -72,6 +20,4 @@ </div> <a href="{{ url_for('index') }}">← Back to Users</a> - -</body> -</html> +{% endblock %} \ No newline at end of file