Compare commits
No commits in common. "dbbaef22f50516bac1ecb7a11cb4c321c263f212" and "7ad353e695db0ecfc7f48af060d2139ed65f76cc" have entirely different histories.
dbbaef22f5
...
7ad353e695
6 changed files with 37 additions and 93 deletions
50
web/app.py
50
web/app.py
|
@ -32,12 +32,6 @@ def get_db_connection():
|
||||||
conn.row_factory = sqlite3.Row
|
conn.row_factory = sqlite3.Row
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
def get_db_cursor():
|
|
||||||
"""Get a database cursor."""
|
|
||||||
if not hasattr(get_db_cursor, 'conn'):
|
|
||||||
get_db_cursor.conn = get_db_connection()
|
|
||||||
return get_db_cursor.conn.cursor()
|
|
||||||
|
|
||||||
@app.errorhandler(HTTPException)
|
@app.errorhandler(HTTPException)
|
||||||
def handle_exception(error):
|
def handle_exception(error):
|
||||||
return render_template("_error.html", error=error), error.code
|
return render_template("_error.html", error=error), error.code
|
||||||
|
@ -49,41 +43,41 @@ def i404():
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
players = conn.execute('SELECT id, username FROM players').fetchall()
|
users = conn.execute('SELECT id, username FROM users').fetchall()
|
||||||
top_players = conn.execute('''
|
top_users = conn.execute('''
|
||||||
SELECT players.id, players.username, COUNT(pulls.id) AS pull_count
|
SELECT users.id, users.username, COUNT(pulls.id) AS pull_count
|
||||||
FROM players
|
FROM users
|
||||||
LEFT JOIN pulls ON players.id = pulls.player_id
|
LEFT JOIN pulls ON users.id = pulls.user_id
|
||||||
GROUP BY players.id
|
GROUP BY users.id
|
||||||
ORDER BY pull_count DESC
|
ORDER BY pull_count DESC
|
||||||
LIMIT 5
|
LIMIT 5
|
||||||
''').fetchall()
|
''').fetchall()
|
||||||
|
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('index.html', players=players, top_players=top_players)
|
return render_template('index.html', users=users, top_users=top_users)
|
||||||
|
|
||||||
@app.route('/player/<int:id>')
|
@app.route('/user/<int:user_id>')
|
||||||
def player_profile(id):
|
def user_profile(user_id):
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
conn.row_factory = sqlite3.Row
|
conn.row_factory = sqlite3.Row
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
cursor.execute('SELECT * FROM players WHERE id = ?', (id,))
|
cursor.execute('SELECT * FROM users WHERE id = ?', (user_id,))
|
||||||
player = cursor.fetchone()
|
user = cursor.fetchone()
|
||||||
if player is None:
|
if user is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
SELECT pulls.timestamp, cards.name as card_name, cards.rarity
|
SELECT pulls.timestamp, characters.name as character_name, characters.rarity
|
||||||
FROM pulls
|
FROM pulls
|
||||||
JOIN cards ON pulls.card_id = cards.id
|
JOIN characters ON pulls.character_id = characters.id
|
||||||
WHERE pulls.player_id = ?
|
WHERE pulls.user_id = ?
|
||||||
ORDER BY pulls.timestamp DESC
|
ORDER BY pulls.timestamp DESC
|
||||||
''', (id,))
|
''', (user_id,))
|
||||||
pulls = cursor.fetchall()
|
pulls = cursor.fetchall()
|
||||||
|
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('player.html', player=player, pulls=pulls)
|
return render_template('user.html', user=user, pulls=pulls)
|
||||||
|
|
||||||
@app.route('/about')
|
@app.route('/about')
|
||||||
def about():
|
def about():
|
||||||
|
@ -93,16 +87,6 @@ def about():
|
||||||
def submit_character():
|
def submit_character():
|
||||||
return render_template('submit.html')
|
return render_template('submit.html')
|
||||||
|
|
||||||
@app.route('/players')
|
|
||||||
def player_list():
|
|
||||||
# Replace with your actual player fetching logic
|
|
||||||
|
|
||||||
cursor = get_db_cursor()
|
|
||||||
cursor.execute('SELECT * FROM players')
|
|
||||||
players = cursor.fetchall()
|
|
||||||
if not players:
|
|
||||||
return render_template('player_list.html', players=[])
|
|
||||||
return render_template('player_list.html', players=players)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host=config.BIND_ADDRESS, port=config.WEB_PORT, debug=True)
|
app.run(host=config.BIND_ADDRESS, port=config.WEB_PORT, debug=True)
|
||||||
|
|
|
@ -28,20 +28,10 @@ along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
| Kemoverse
|
| Kemoverse
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
{% block header %}{% endblock %}
|
{% block header %}{% endblock %}
|
||||||
<h1>Kemoverse</h1>
|
|
||||||
<p>A gacha in the fediverse.</p>
|
|
||||||
<nav>
|
|
||||||
<a href="{{ url_for('index') }}">Home</a>
|
|
||||||
<a href="{{ url_for('about') }}">About</a>
|
|
||||||
<a href="{{ url_for('submit_character') }}">Submit a Character</a>
|
|
||||||
<a href="{{ url_for('player_list') }}">Player List</a>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -49,6 +39,8 @@ along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer>
|
<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 %}
|
{% block footer_extra %}{% endblock %}
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -18,8 +18,8 @@ along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
{% extends "_base.html" %}
|
{% extends "_base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>About This Site</h1>
|
<h1>About This Gacha</h1>
|
||||||
<p>Kemoverse is a simple web app designed to track gacha pulls and player stats in a fun, competitive way.</p>
|
<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>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>
|
<p>Built with love, chaos, and way too much caffeine ☕.</p>
|
||||||
<a href="{{ url_for('index') }}">← Back to Home</a>
|
<a href="{{ url_for('index') }}">← Back to Home</a>
|
||||||
|
|
|
@ -18,19 +18,28 @@ along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
{% extends "_base.html" %}
|
{% extends "_base.html" %}
|
||||||
|
|
||||||
|
{% block header %}
|
||||||
|
<h1>Misskey Gacha Center</h1>
|
||||||
|
<p>Track your luck. Compare your pulls. Compete with friends.</p>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h2>🎖️ Leaderboard: Most Rolls</h2>
|
<h2>🎖️ Leaderboard: Most Rolls</h2>
|
||||||
{% for player in top_players %}
|
{% for user in top_users %}
|
||||||
<div class="leaderboard-entry">
|
<div class="leaderboard-entry">
|
||||||
{{ loop.index }}. <strong>{{ player['username'] }}</strong> — {{ player['pull_count'] }} rolls
|
{{ loop.index }}. <strong>{{ user['username'] }}</strong> — {{ user['pull_count'] }} rolls
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No pulls yet. Be the first to roll!</p>
|
<p>No pulls yet. Be the first to roll!</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
<h2>📋 All Registered Users</h2>
|
||||||
|
<ul>
|
||||||
|
{% for user in users %}
|
||||||
|
<li><a href="{{ url_for('user_profile', user_id=user['id']) }}">{{ user['username'] }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div class="note">
|
<div class="note">
|
||||||
🚀 This is a fun little gacha tracker! More features coming soon. Want to help shape it?
|
🚀 This is a fun little gacha tracker! More features coming soon. Want to help shape it?
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
<!--
|
|
||||||
Kemoverse - a gacha-style bot for the Fediverse.
|
|
||||||
Copyright © 2025 Waifu
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see https://www.gnu.org/licenses/.
|
|
||||||
-->
|
|
||||||
{% extends "_base.html" %}
|
|
||||||
|
|
||||||
{% block title %}Player List{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h1>Player List</h1>
|
|
||||||
{% if players and players|length > 0 %}
|
|
||||||
<ul>
|
|
||||||
{% for player in players %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('player_profile', id=player['id']) }}">
|
|
||||||
{{ player['username'] }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% else %}
|
|
||||||
<p>No players found.</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block footer_extra %}
|
|
||||||
<p>Player list is dynamically generated from the database.</p>
|
|
||||||
{% endblock %}
|
|
|
@ -18,8 +18,8 @@ along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
{% extends "_base.html" %}
|
{% extends "_base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="profile">
|
<div class="profile">
|
||||||
<h1>{{ player['username'] }}'s Gacha Rolls</h1>
|
<h1>{{ user['username'] }}'s Gacha Rolls</h1>
|
||||||
<p>Player ID: {{ player['id'] }}</p>
|
<p>User ID: {{ user['id'] }}</p>
|
||||||
<p>Total Rolls: {{ pulls | length }}</p>
|
<p>Total Rolls: {{ pulls | length }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -29,12 +29,12 @@ along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
{% for pull in pulls %}
|
{% for pull in pulls %}
|
||||||
<li>
|
<li>
|
||||||
<span class="timestamp">{{ pull['timestamp'] }}</span><br>
|
<span class="timestamp">{{ pull['timestamp'] }}</span><br>
|
||||||
{{ pull['card_name'] }}
|
{{ pull['character_name'] }}
|
||||||
<span class="rarity">{{ '★' * pull['rarity'] }}</span>
|
<span class="rarity">{{ '★' * pull['rarity'] }}</span>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="{{ url_for('index') }}">← Back to Home</a>
|
<a href="{{ url_for('index') }}">← Back to Users</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
Loading…
Add table
Reference in a new issue