Kgshop commited on
Commit
ccd7872
·
verified ·
1 Parent(s): d3bcffb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -50
app.py CHANGED
@@ -1,5 +1,4 @@
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
 
4
  import os
5
  from flask import Flask, request, Response, render_template_string, jsonify, redirect, url_for
@@ -469,6 +468,8 @@ ADMIN_TEMPLATE = """
469
  .btn { padding: 12px 20px; font-size: 1em; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: background-color 0.2s ease; }
470
  .btn-primary { background-color: var(--admin-primary); color: #000; }
471
  .btn-primary:hover { background-color: var(--admin-primary-dark); }
 
 
472
  .user-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--padding); margin-top: var(--padding); }
473
  .user-card { background-color: var(--admin-card-bg); border-radius: var(--border-radius); padding: var(--padding); box-shadow: 0 4px 15px var(--admin-shadow); border: 1px solid var(--admin-border); display: flex; flex-direction: column; transition: transform 0.2s ease, box-shadow 0.2s ease; }
474
  .user-card:hover { transform: translateY(-5px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08); }
@@ -479,12 +480,9 @@ ADMIN_TEMPLATE = """
479
  .user-bonuses { text-align: center; margin-bottom: 1rem; }
480
  .user-bonuses .label { font-size: 0.9em; color: var(--admin-secondary); }
481
  .user-bonuses .amount { font-size: 1.8em; font-weight: 700; color: var(--admin-primary-dark); }
482
- .user-actions { display: flex; gap: 0.5rem; margin-top: auto; }
483
- .btn-manage, .btn-delete { flex: 1; padding: 10px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: background-color 0.2s; font-size: 0.9em; }
484
- .btn-manage { background-color: var(--admin-primary); color: #000; }
485
  .btn-manage:hover { background-color: var(--admin-primary-dark); }
486
- .btn-delete { background-color: var(--admin-danger); color: white; }
487
- .btn-delete:hover { background-color: #c82333; }
488
  .no-users { text-align: center; color: var(--admin-secondary); margin-top: 2rem; font-size: 1.1em; }
489
  .modal { display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(5px); }
490
  .modal-content { background-color: var(--admin-bg); margin: 10% auto; padding: var(--padding); border: 1px solid var(--admin-border); width: 90%; max-width: 600px; border-radius: var(--border-radius); position: relative; box-shadow: 0 8px 30px rgba(0,0,0,0.15); }
@@ -538,8 +536,10 @@ ADMIN_TEMPLATE = """
538
  <div class="amount">{{ "%.2f"|format(user.bonuses|float) }}</div>
539
  </div>
540
  <div class="user-actions">
541
- <button class="btn-manage" onclick='openTransactionModal({{ user|tojson }})'>Управление</button>
542
- <button class="btn-delete" onclick='deleteClient({{ user|tojson }})'>Удалить</button>
 
 
543
  </div>
544
  </div>
545
  {% endfor %}
@@ -761,28 +761,21 @@ ADMIN_TEMPLATE = """
761
  }
762
  }
763
 
764
- async function deleteClient(userData) {
765
- const userId = userData.id;
766
- const userName = `${userData.first_name || ''} ${userData.last_name || ''}`.trim() || `@${userData.username || userData.phone_number}`;
767
-
768
- if (!confirm(`Вы уверены, что хотите удалить клиента ${userName} (ID: ${userId})? Это действие необратимо.`)) {
769
  return;
770
  }
771
-
772
  try {
773
  const response = await fetch('/admin/delete_client', {
774
  method: 'POST',
775
  headers: { 'Content-Type': 'application/json' },
776
  body: JSON.stringify({ user_id: userId })
777
  });
778
-
779
  const result = await response.json();
780
-
781
  if (response.ok) {
782
- alert('Клиент успешно удален.');
783
  location.reload();
784
  } else {
785
- throw new Error(result.message || 'Произошла ошибка при удалении');
786
  }
787
  } catch (error) {
788
  alert(`Ошибка: ${error.message}`);
@@ -944,38 +937,6 @@ def add_client():
944
  logging.exception("Error in /admin/add_client endpoint")
945
  return jsonify({"status": "error", "message": str(e)}), 500
946
 
947
- @app.route('/admin/delete_client', methods=['POST'])
948
- def delete_client():
949
- try:
950
- data = request.get_json()
951
- user_id = data.get('user_id')
952
-
953
- if not user_id:
954
- return jsonify({"status": "error", "message": "User ID is required"}), 400
955
-
956
- user_id_str = str(user_id)
957
-
958
- with _data_lock:
959
- all_data = load_visitor_data()
960
-
961
- if user_id_str not in all_data:
962
- return jsonify({"status": "error", "message": "User not found"}), 404
963
-
964
- del all_data[user_id_str]
965
-
966
- with open(DATA_FILE, 'w', encoding='utf-8') as f:
967
- json.dump(all_data, f, ensure_ascii=False, indent=4)
968
-
969
- logging.info(f"User {user_id_str} deleted. Data saved to {DATA_FILE}.")
970
-
971
- upload_data_to_hf_async()
972
-
973
- return jsonify({"status": "ok", "message": "Client deleted successfully"}), 200
974
-
975
- except Exception as e:
976
- logging.exception("Error in /admin/delete_client endpoint")
977
- return jsonify({"status": "error", "message": str(e)}), 500
978
-
979
 
980
  @app.route('/admin/add_transaction', methods=['POST'])
981
  def add_transaction():
@@ -1034,6 +995,43 @@ def add_transaction():
1034
  logging.exception("Error in /admin/add_transaction endpoint")
1035
  return jsonify({"status": "error", "message": str(e)}), 500
1036
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1037
  if __name__ == '__main__':
1038
  print("--- DRUZHBA BONUS SYSTEM SERVER ---")
1039
  print(f"Server starting on http://{HOST}:{PORT}")
 
1
  #!/usr/bin/env python3
 
2
 
3
  import os
4
  from flask import Flask, request, Response, render_template_string, jsonify, redirect, url_for
 
468
  .btn { padding: 12px 20px; font-size: 1em; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: background-color 0.2s ease; }
469
  .btn-primary { background-color: var(--admin-primary); color: #000; }
470
  .btn-primary:hover { background-color: var(--admin-primary-dark); }
471
+ .btn-delete { background-color: var(--admin-danger); color: white; }
472
+ .btn-delete:hover { background-color: #c82333; }
473
  .user-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--padding); margin-top: var(--padding); }
474
  .user-card { background-color: var(--admin-card-bg); border-radius: var(--border-radius); padding: var(--padding); box-shadow: 0 4px 15px var(--admin-shadow); border: 1px solid var(--admin-border); display: flex; flex-direction: column; transition: transform 0.2s ease, box-shadow 0.2s ease; }
475
  .user-card:hover { transform: translateY(-5px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08); }
 
480
  .user-bonuses { text-align: center; margin-bottom: 1rem; }
481
  .user-bonuses .label { font-size: 0.9em; color: var(--admin-secondary); }
482
  .user-bonuses .amount { font-size: 1.8em; font-weight: 700; color: var(--admin-primary-dark); }
483
+ .user-actions { margin-top: auto; display: flex; flex-direction: column; gap: 0.5rem; }
484
+ .btn-manage { display: block; width: 100%; padding: 10px; background-color: var(--admin-primary); color: #000; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: background-color 0.2s; }
 
485
  .btn-manage:hover { background-color: var(--admin-primary-dark); }
 
 
486
  .no-users { text-align: center; color: var(--admin-secondary); margin-top: 2rem; font-size: 1.1em; }
487
  .modal { display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(5px); }
488
  .modal-content { background-color: var(--admin-bg); margin: 10% auto; padding: var(--padding); border: 1px solid var(--admin-border); width: 90%; max-width: 600px; border-radius: var(--border-radius); position: relative; box-shadow: 0 8px 30px rgba(0,0,0,0.15); }
 
536
  <div class="amount">{{ "%.2f"|format(user.bonuses|float) }}</div>
537
  </div>
538
  <div class="user-actions">
539
+ <button class="btn-manage" onclick='openTransactionModal({{ user|tojson }})'>Управление бонусами</button>
540
+ {% if user.telegram_id == None %}
541
+ <button class="btn btn-delete" onclick='deleteClient("{{ user.id }}")'>Удалить клиента</button>
542
+ {% endif %}
543
  </div>
544
  </div>
545
  {% endfor %}
 
761
  }
762
  }
763
 
764
+ async function deleteClient(userId) {
765
+ if (!confirm(`Вы уверены, что хотите удалить клиента с ID ${userId}? Это действие необратимо.`)) {
 
 
 
766
  return;
767
  }
 
768
  try {
769
  const response = await fetch('/admin/delete_client', {
770
  method: 'POST',
771
  headers: { 'Content-Type': 'application/json' },
772
  body: JSON.stringify({ user_id: userId })
773
  });
 
774
  const result = await response.json();
 
775
  if (response.ok) {
 
776
  location.reload();
777
  } else {
778
+ throw new Error(result.message || 'Не удалось удалить клиента.');
779
  }
780
  } catch (error) {
781
  alert(`Ошибка: ${error.message}`);
 
937
  logging.exception("Error in /admin/add_client endpoint")
938
  return jsonify({"status": "error", "message": str(e)}), 500
939
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
 
941
  @app.route('/admin/add_transaction', methods=['POST'])
942
  def add_transaction():
 
995
  logging.exception("Error in /admin/add_transaction endpoint")
996
  return jsonify({"status": "error", "message": str(e)}), 500
997
 
998
+ @app.route('/admin/delete_client', methods=['POST'])
999
+ def delete_client():
1000
+ try:
1001
+ data = request.get_json()
1002
+ user_id = data.get('user_id')
1003
+
1004
+ if not user_id:
1005
+ return jsonify({"status": "error", "message": "User ID is required"}), 400
1006
+
1007
+ user_id_str = str(user_id)
1008
+ load_visitor_data()
1009
+
1010
+ with _data_lock:
1011
+ if user_id_str not in visitor_data_cache:
1012
+ return jsonify({"status": "error", "message": "User not found"}), 404
1013
+
1014
+ user_to_delete = visitor_data_cache[user_id_str]
1015
+ if user_to_delete.get('telegram_id') is not None:
1016
+ return jsonify({"status": "error", "message": "Cannot delete a Telegram-linked user"}), 403
1017
+
1018
+ del visitor_data_cache[user_id_str]
1019
+
1020
+ try:
1021
+ with open(DATA_FILE, 'w', encoding='utf-8') as f:
1022
+ json.dump(visitor_data_cache, f, ensure_ascii=False, indent=4)
1023
+ logging.info(f"User {user_id_str} deleted. Data saved to {DATA_FILE}.")
1024
+ upload_data_to_hf_async()
1025
+ except Exception as e:
1026
+ logging.error(f"Error saving data after deletion: {e}")
1027
+ return jsonify({"status": "error", "message": "Failed to save data after deletion"}), 500
1028
+
1029
+ return jsonify({"status": "ok", "message": "Client deleted successfully"}), 200
1030
+
1031
+ except Exception as e:
1032
+ logging.exception("Error in /admin/delete_client endpoint")
1033
+ return jsonify({"status": "error", "message": str(e)}), 500
1034
+
1035
  if __name__ == '__main__':
1036
  print("--- DRUZHBA BONUS SYSTEM SERVER ---")
1037
  print(f"Server starting on http://{HOST}:{PORT}")