fix world

This commit is contained in:
2026-05-03 14:19:34 +03:00
parent 11f30f4c6a
commit cf23f38a6e
4 changed files with 62 additions and 27 deletions

43
db.py
View File

@@ -218,25 +218,58 @@ def init_db():
)
''')
# Clan members — links Grepolis player_ids to a clan
# Clan members — links Grepolis player_ids to a clan.
# UNIQUE on (clan_id, player_id, world_id) so the same player
# appearing in multiple worlds creates separate rows.
c.execute('''
CREATE TABLE IF NOT EXISTS clan_members (
id INTEGER PRIMARY KEY AUTOINCREMENT,
clan_id INTEGER NOT NULL REFERENCES clans(id),
player_id TEXT NOT NULL,
player_name TEXT,
world_id TEXT,
world_id TEXT NOT NULL DEFAULT '',
features TEXT NOT NULL DEFAULT 'farm,admin',
joined_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(clan_id, player_id)
UNIQUE(clan_id, player_id, world_id)
)
''')
# Migration: if clan_members still has the old UNIQUE(clan_id, player_id) constraint
# (without world_id), recreate the table with the correct 3-column constraint.
try:
tbl_sql = c.execute(
"SELECT sql FROM sqlite_master WHERE type='table' AND name='clan_members'"
).fetchone()
if tbl_sql and 'player_id, world_id' not in (tbl_sql['sql'] or ''):
c.execute('''
CREATE TABLE IF NOT EXISTS _clan_members_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
clan_id INTEGER NOT NULL REFERENCES clans(id),
player_id TEXT NOT NULL,
player_name TEXT,
world_id TEXT NOT NULL DEFAULT '',
features TEXT NOT NULL DEFAULT 'farm,admin',
joined_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(clan_id, player_id, world_id)
)
''')
c.execute('''
INSERT OR IGNORE INTO _clan_members_new
(id, clan_id, player_id, player_name, world_id, features, joined_at)
SELECT id, clan_id, player_id, player_name,
COALESCE(world_id, ''), features, joined_at
FROM clan_members
''')
c.execute('DROP TABLE clan_members')
c.execute('ALTER TABLE _clan_members_new RENAME TO clan_members')
except Exception as _e:
print(f'clan_members migration skipped: {_e}')
# Migration: Auto-assign existing users to their clan_id if they are the owner
try:
c.execute('''
UPDATE users
SET clan_id = (SELECT id FROM clans WHERE owner_id = users.id)
UPDATE users
SET clan_id = (SELECT id FROM clans WHERE owner_id = users.id)
WHERE clan_id IS NULL AND EXISTS (SELECT 1 FROM clans WHERE owner_id = users.id)
''')
except Exception:

View File

@@ -30,16 +30,17 @@ def _get_clan_from_request():
# Helper — auto-register a player_id under a clan on first push.
# ------------------------------------------------------------------
def _auto_register_member(clan_id, player_id, player_name, world_id=''):
world_id = world_id or ''
conn = get_db()
conn.execute('''
INSERT OR IGNORE INTO clan_members (clan_id, player_id, player_name, world_id)
VALUES (?, ?, ?, ?)
''', (clan_id, str(player_id), player_name or '', world_id or ''))
# Update name and world on every push (they can change)
''', (clan_id, str(player_id), player_name or '', world_id))
# Update name on every push (it can change); world_id is part of the key so no overwrite risk
conn.execute('''
UPDATE clan_members SET player_name = ?, world_id = ?
WHERE clan_id = ? AND player_id = ?
''', (player_name or '', world_id or '', clan_id, str(player_id)))
UPDATE clan_members SET player_name = ?
WHERE clan_id = ? AND player_id = ? AND world_id = ?
''', (player_name or '', clan_id, str(player_id), world_id))
conn.commit()
conn.close()

View File

@@ -127,12 +127,13 @@ def options():
if clan:
rows = conn.execute(
'''SELECT cm.id, cm.player_id, cm.player_name, cm.world_id, cm.joined_at, cm.features,
ts.updated_at
MAX(ts.updated_at) as updated_at
FROM clan_members cm
LEFT JOIN town_state ts ON ts.player_id = cm.player_id
AND ts.world_id = cm.world_id
WHERE cm.clan_id = ?
GROUP BY cm.player_id
ORDER BY cm.joined_at DESC''',
GROUP BY cm.player_id, cm.world_id
ORDER BY cm.player_name ASC, cm.world_id ASC''',
(clan['id'],)
).fetchall()
@@ -212,17 +213,17 @@ def regenerate_key():
return redirect(url_for('auth.options'))
@auth.route('/auth/clan/remove-member/<player_id>', methods=['POST'])
@auth.route('/auth/clan/remove-member/<player_id>/<path:world_id>', methods=['POST'])
@login_required
def remove_member(player_id):
def remove_member(player_id, world_id):
conn = get_db()
clan = conn.execute(
'SELECT id FROM clans WHERE owner_id = ?', (current_user.id,)
).fetchone()
if clan:
conn.execute(
'DELETE FROM clan_members WHERE clan_id = ? AND player_id = ?',
(clan['id'], player_id)
'DELETE FROM clan_members WHERE clan_id = ? AND player_id = ? AND world_id = ?',
(clan['id'], player_id, world_id)
)
conn.commit()
conn.close()
@@ -232,12 +233,12 @@ def remove_member(player_id):
# ------------------------------------------------------------------
# POST /auth/clan/update-features/<player_id>
# ------------------------------------------------------------------
@auth.route('/auth/clan/update-features/<player_id>', methods=['POST'])
@auth.route('/auth/clan/update-features/<player_id>/<path:world_id>', methods=['POST'])
@login_required
def update_member_features(player_id):
farm = 'farm' if request.form.get('farm') else None
admin = 'admin' if request.form.get('admin') else None
atk_planner = 'attack_planner' if request.form.get('attack_planner') else None
def update_member_features(player_id, world_id):
farm = 'farm' if request.form.get('farm') else None
admin = 'admin' if request.form.get('admin') else None
atk_planner = 'attack_planner' if request.form.get('attack_planner') else None
atk_planner_admin = 'attack_planner_admin' if request.form.get('attack_planner_admin') else None
features = ','.join(f for f in [farm, admin, atk_planner, atk_planner_admin] if f) or ''
@@ -248,8 +249,8 @@ def update_member_features(player_id):
).fetchone()
if clan:
conn.execute(
'UPDATE clan_members SET features = ? WHERE clan_id = ? AND player_id = ?',
(features, clan['id'], player_id)
'UPDATE clan_members SET features = ? WHERE clan_id = ? AND player_id = ? AND world_id = ?',
(features, clan['id'], player_id, world_id)
)
conn.commit()
conn.close()

View File

@@ -287,7 +287,7 @@
</td>
<td>
{% if clan.owner_id == current_user.id %}
<form method="POST" action="/auth/clan/update-features/{{ m.player_id }}" style="display:inline;">
<form method="POST" action="/auth/clan/update-features/{{ m.player_id }}/{{ m.world_id }}" style="display:inline;">
<div class="toggle-group">
<label class="toggle-label">
<input type="checkbox" name="farm" onchange="this.form.submit()" {{ 'checked' if m.feat_farm }}> 🌾 Farm
@@ -316,8 +316,8 @@
<td style="color:#8b949e; font-size:0.8rem;">{{ m.joined_at }}</td>
<td style="text-align:right;">
{% if clan.owner_id == current_user.id %}
<form method="POST" action="/auth/clan/remove-member/{{ m.player_id }}"
onsubmit="return confirm('Αφαίρεση παίκτη {{ m.player_name }}?');">
<form method="POST" action="/auth/clan/remove-member/{{ m.player_id }}/{{ m.world_id }}"
onsubmit="return confirm('Αφαίρεση {{ m.player_name }} ({{ m.world_id }})?');">
<button type="submit" class="btn-danger">Αφαίρεση</button>
</form>
{% endif %}