statistika
1from datetime import datetime, timedelta 2import hashlib 3import os 4import re 5import sqlite3 6import time 7from threading import Thread 8 9from flask import Flask, g, jsonify, redirect, render_template, request, session 10from flask_cors import CORS 11import requests 12 13# import db_initialization 14import db_management 15import statistika_logger 16 17app = Flask(__name__) 18app.secret_key = os.urandom(24) # для работы session 19 20CORS(app) 21 22log = statistika_logger.get_logger(__name__) 23 24 25def get_db_connection() -> sqlite3.Connection: 26 """ 27 Функция, которая получает соединение с базой данных. 28 Если соединение не существует, устанавливает новое соединение с использованием SQLite с 'data.db'. 29 Возвращает существующее или новосозданное соединение с базой данных. 30 """ 31 db_connection = getattr(g, '_database', None) 32 if db_connection is None: 33 # для тестирования 34 # раскомментировать, если необходимо пересоздать БД 35 # os.remove('../data.db') 36 if not os.path.exists('../data.db'): 37 db_connection = g._database = sqlite3.connect('../data.db') 38 db_initialization.create_tables(db_connection) 39 db_initialization.load_test_data(db_connection) 40 else: 41 db_connection = g._database = sqlite3.connect('../data.db') 42 return db_connection 43 44 45@app.teardown_appcontext 46def close_db_connection(exception: Exception) -> None: 47 """ 48 Функция завершения, которая закрывает соединение с базой данных. 49 Параметры: 50 - exception: Исключение, которое вызвало завершение, если таковое имеется. 51 """ 52 db_connection = getattr(g, '_database', None) 53 if db_connection is not None: 54 db_connection.close() 55 56 57def update_players_tournaments() -> None: 58 """ 59 Постоянно обновляет турниры игроков в БД. 60 61 Извлекает список игроков из БД и для каждого игрока 62 извлекает турниры из Интернета и обновляет базу данных, если 63 турниры разные. Между каждой итерацией проходит 1 день. 64 """ 65 # log.warning('Updating players tournaments...') 66 67 # Подключаемся к БД. 68 con = sqlite3.connect('../data.db') 69 cursor = con.cursor() 70 71 while True: 72 # Получаем список игроков. 73 query = "SELECT player_id FROM players" 74 players_ids: list[str] = [row[0] for row in cursor.execute(query).fetchall()] 75 76 # Проход по всем игрокам. 77 for player_id in players_ids: 78 # Запрос на получение турниров игрока из БД. 79 query = "SELECT tournaments FROM players WHERE player_id = ?" 80 tournaments_in_db: str = cursor.execute(query, (player_id,)).fetchall()[0][0] 81 82 # Запрос на получение турниров игрока {player_id} из Интернета. 83 # log.warning(f'Запрос на получение турниров игрока {player_id} из Интернета.') 84 try: 85 url = f'https://api.rating.chgk.net/players/{player_id}/tournaments' 86 response = requests.get(url=url) 87 if response.status_code != 200: 88 raise Exception( 89 f'Something wrong with request to API. Status code: {response.status_code}, from {url}') 90 91 tournaments_in_web = [i['idtournament'] for i in response.json()] 92 tournaments_in_web = ','.join(map(str, tournaments_in_web)) 93 94 # Коли записи разнятся, обновляем БД. 95 # log.warning(f'Обновляем БД для игрока {player_id}.') 96 if tournaments_in_web != tournaments_in_db: 97 query = "UPDATE players SET tournaments = ? WHERE player_id = ?" 98 cursor.execute(query, (tournaments_in_web, player_id)) 99 con.commit() 100 time.sleep(2) 101 # Если 404, то предполагаем неполадки сети, логируем, ждём 1 час и продолжаем. 102 except Exception as e: 103 # log.error(e) 104 time.sleep(60 * 60) # 1-hour sleep after error 105 continue 106 107 # После прохода по всем игрокам ждём 1 день. 108 time.sleep(60 * 60 * 24) # 1 day 109 110 111thread = Thread(target=update_players_tournaments) 112thread.start() 113 114 115@app.route('/') 116def index(): 117 """ 118 Обработчик маршрута для корневого URL-адреса ("/"). Очищает сеанс, извлекает данные из БД, 119 добавляет имена столбцов в начало данных, преобразует данные в формат JSON, сортирует их по полю "_sum_minus_2", 120 а затем отображает шаблон index.html с отсортированными данными и именами столбцов. 121 """ 122 session.clear() 123 124 # Получаем данные из базы 125 db_connection = get_db_connection() 126 data, columns = db_management.get_maintable(db_connection) 127 128 # Добавление названий столбцов в начало 129 thead = ['Команда', 'Сумма', 'Сумма - 2'] + columns[3:] 130 131 # Преобразование данных в формат JSON 132 json_data = to_json(data, columns) 133 134 # Сортировка по сумме 135 data = sorted(json_data, key=lambda x: x['_sum_minus_2'], reverse=True) 136 137 return render_template('index.html', thead=thead, data=data) 138 139 140@app.route('/login', methods=['POST', 'GET']) 141def admin_login(): 142 """ 143 Обрабатывает логин в систему. Считывает с формы логин/пароль (index.html). 144 145 Проверяет в базе наличие хэша пароля. В случае успеха делает редирект на основную страницу. 146 Помечает успешный залогин в кукисе session[login] = login. 147 В противном случае - пишет Fail и отображает страницу ввода пароля снова. 148 """ 149 db_connection = get_db_connection() 150 cursor = db_connection.cursor() 151 152 log.info('Logon.') 153 154 if request.method == 'POST': 155 login = request.form.get('login') 156 password = request.form.get('password') 157 query = 'SELECT salt FROM users WHERE login = :login' 158 login_exists = cursor.execute(query, {'login': login}).fetchall() 159 160 if login_exists: 161 log.info('There is a salt') 162 salt = login_exists[0][0] 163 164 password_hash = hashlib.scrypt(password=bytes(password, encoding='UTF-8'), 165 salt=bytes(salt, encoding='UTF-8'), 166 n=2 ** 14, r=8, p=1, dklen=64).hex() 167 168 query = """ 169 SELECT 170 count(1) _count 171 FROM 172 users 173 WHERE 174 login =:login 175 AND 176 hash =:hash 177 """ 178 179 data = {'login': login, 'hash': password_hash} 180 181 if cursor.execute(query, data).fetchall()[0][0]: 182 session['login'] = login 183 return redirect('/main_table') 184 else: 185 return render_template('login.html', message='Fail.') 186 187 return render_template('login.html') 188 189 190@app.route('/main_table') 191def main_table(): 192 """ 193 Функция, которая служит обработчиком маршрута для таблицы. Отображает шаблон 'main_table.html'. 194 """ 195 log.info('Function main_table() was called...') 196 197 thread_status = '🟢' if thread.is_alive() else '🔴' 198 199 if session.get('login'): 200 if request.method == 'GET': 201 return render_template('main_table.html', thread_status=thread_status) 202 if request.method == 'POST': 203 log.debug(request.data) 204 else: 205 return redirect('/login') 206 207 208@app.route('/add_game', methods=['GET']) 209def add_game() -> str: 210 return render_template('add_game.html') 211 212 213@app.route('/add_player', methods=['GET', 'POST']) 214def add_player(): 215 db_connection = get_db_connection() 216 # Получаем список команд 217 teams = [i[0] for i in db_management.get_teams(db_connection)] 218 return render_template('add_player.html', teams=teams) 219 220 221@app.route('/add_score', methods=['GET', 'POST']) 222def add_score(): 223 db_connection = get_db_connection() 224 data = [i[0] for i in db_management.get_teams(db_connection)] 225 226 message = '' 227 if request.method == 'POST': 228 log.debug(request.form) 229 message = 'Данные внесли.' 230 return render_template('add_score.html', data=data, message=message) 231 232 233@app.route('/add_team', methods=['GET']) 234def add_team(): 235 return render_template('add_team.html') 236 237 238@app.route('/get_columns', methods=['GET']) 239def get_columns() -> list[dict]: 240 """ 241 Функция для извлечения названий столбцов из таблицы базы данных и преобразования их в определенный формат 242 для отображения. 243 """ 244 # Подключение к базе данных SQLite и получение данных для главной таблицы 245 db_connection = get_db_connection() 246 data, columns = db_management.get_maintable(db_connection) 247 248 transformed_columns = [] 249 250 # Цикл для преобразования каждого элемента массива строк в объект 251 for column in columns: 252 if column == 'team_name': 253 field_title = "Команда" 254 elif column == '_sum_': 255 field_title = 'Cумма' 256 elif column == '_sum_minus_2': 257 field_title = 'Cум(-2)' 258 else: 259 field_title = '.'.join((column.split('-')[2], column.split('-')[1])) 260 261 transformed_columns.append({ 262 # Пример условной логики для определения значения editor 263 'editor': 'input', # if column == 'team_name' else 'number' 264 'field': column, 265 'hozAlign': 'center' if column == 'summa_2' else 'left', 266 'sorter': 'number', 267 'title': field_title, 268 'validator': 'numeric', 269 # 'contextMenu': 'cellContextMenu' 270 }) 271 return transformed_columns 272 273 274def to_json(data, columns): 275 """Вспомогательная функция для преобразования данных в формат JSON.""" 276 log.info('Function to_json() was called...') 277 json_data = [] 278 for row in data: 279 row_data = {} 280 for i in range(0, len(columns)): 281 row_data[columns[i]] = row[i] 282 json_data.append(row_data) 283 284 return json_data 285 286 287@app.route('/get_data', methods=['GET']) 288def get_data(): 289 if request.referrer is None: 290 return 'Що таке?' 291 292 db_connection = get_db_connection() 293 294 who = request.referrer.split('/')[-1] 295 match who: 296 case 'main_table': 297 data, columns = db_management.get_maintable(db_connection) 298 return to_json(data, columns) 299 case 'add_player': 300 data = db_management.get_players(db_connection) 301 log.debug(data) 302 columns = ['fio', 'player_id', 'team_name'] # менять на человеческие 'ФИО', 'ИД игрока' в table_players.js 303 return to_json(data, columns) 304 case 'add_team': 305 data = db_management.get_teams(db_connection) 306 columns = ['Name'] 307 return to_json(data, columns) 308 309 310@app.route('/check_packet', methods=['POST']) 311def check_packet(): 312 log.debug(request.json) 313 packets = [i for i in request.json if i] 314 answer = [] 315 for packet_id in packets: 316 r = requests.get(f'https://rating.maii.li/b/tournament/{packet_id}/') 317 318 pattern = r'/\/b\/player\/(\d+)/gm' 319 matches = re.findall(pattern, r.text) 320 print(matches) 321 print(len(matches)) 322 answer.append(matches) 323 324 return jsonify(success=True, data=''.join(answer)) 325 326 327@app.route('/test', methods=['POST', 'GET']) 328def test(): 329 if request.method == 'POST': 330 log.debug(request.data.decode('utf-8')) 331 data = request.data.decode('utf-8') 332 log.info('OK') 333 # json_data = [ 334 # {'id': 1, 'name': "Tiger Nixon", 'position': "System Architect", 'office': "Edinburgh", 'extension': "5421", 335 # 'startDate': "2011/04/25", 'salary': "Tiger Nixon"} 336 # ] 337 # lll = {'data': [[1, 'test', 78], 338 # [2, 'test2', 145], 339 # [3, 'test3', 23], 340 # [4, 'test4', 45]], 341 # 'columns': ['id', 'name', 'position'] 342 # } 343 344 return render_template('tablecelledit.html') 345 346 347@app.route('/update', methods=['POST', 'GET']) 348def update(): 349 if request.method == 'POST': 350 db_connection = get_db_connection() 351 who = request.referrer.split('/')[-1] 352 match who: 353 case 'main_table': 354 log.debug(request.json) 355 date = (datetime.today() - timedelta(days=1)).strftime('%Y-%m-%d') 356 db_management.update_main_table(db_connection, request.json, date) 357 # case 'add_player': 358 # return render_template('add_player.html') 359 # case 'add_team': 360 # return render_template('add_team.html') 361 return {'success': True} 362 363 364# @app.route('/update_from_github', methods=['POST', 'GET']) 365# def update_from_github() -> jsonify:# todo 366# """ 367# Функция для обновления данных из GitHub. 368# Эта функция скачивает последние изменения в репозитории и обновляет проект. 369# """ 370# # print(request.json) 371# cmd = 'echo "kek" > lol.kek' 372# os.system(cmd) 373# # cmd = 'sudo touch lol.kek' 374# cmd = 'sudo ./update.sh' 375# os.system(cmd) 376# print(cmd) 377# # return jsonify(success=True, data=request.json) 378# return str(request.json) 379 380 381@app.route('/update_table_players', methods=['POST']) 382def update_table_players(): 383 """ 384 Функция для обновления таблицы игроков данными, полученными через POST-запрос. 385 Эта функция добавляет нового игрока в таблицу players, используя его полное имя (fio) и идентификатор игрока. 386 В случае успешного выполнения возвращает JSON-ответ с сообщением об успехе, в противном случае возвращает сообщение 387 об ошибке. 388 """ 389 db_connection = get_db_connection() 390 cursor = db_connection.cursor() 391 try: 392 d = request.json 393 log.debug(d) 394 fio = d['playerFIO'] 395 player_id = d['playerName'] 396 team_name = d['teamName'] 397 log.debug(fio, player_id, team_name) 398 # Получаем идентификатор команды 399 query = 'select id from teams where name = ?' 400 cursor.execute(query, (team_name,)) 401 team_id = cursor.fetchone()[0] 402 log.debug(team_id) 403 # Записываем данные в таблицу players 404 query = 'insert into players (fio, player_id, team_id) values (?, ?, ?)' 405 cursor.execute(query, (fio, player_id, team_id)) 406 db_connection.commit() 407 log.info(f'Записали игрока {fio} в таблицу players.') 408 409 response = {'success': True} 410 return jsonify(response) 411 412 except Exception as e: 413 log.error(f'Error: {e}') 414 return jsonify(success=False, error=str(e)) 415 416 417@app.route('/update_table_teams', methods=['POST']) 418def update_table_teams(): 419 """ 420 Функция для обновления таблицы команд данными, полученными через POST-запрос. 421 Эта функция добавляет новую команду в таблицу teams. 422 В случае успешного выполнения возвращает JSON-ответ с сообщением об успехе, в противном случае возвращает сообщение 423 об ошибке. 424 """ 425 db_connection = get_db_connection() 426 cursor = db_connection.cursor() 427 try: 428 log.debug(request.json) 429 d = request.json 430 log.debug(type(d)) 431 t_name = d['team_name'] 432 query = 'insert into teams(name) values (?)' 433 cursor.execute(query, (t_name,)) 434 db_connection.commit() 435 436 response = {'success': True} 437 return jsonify(response) 438 439 except Exception as e: 440 log.error(f'Error: {e}') 441 return jsonify(success=False, error=str(e)) 442 443 444@app.errorhandler(404) 445def page_not_found(error): 446 """Отображает страницу ошибки в случае перехода на несуществующую страницу.""" 447 return render_template('404.html', error=error), 404 448 449 450if __name__ == '__main__': 451 app.run(debug=True, host='0.0.0.0', port=5555)
26def get_db_connection() -> sqlite3.Connection: 27 """ 28 Функция, которая получает соединение с базой данных. 29 Если соединение не существует, устанавливает новое соединение с использованием SQLite с 'data.db'. 30 Возвращает существующее или новосозданное соединение с базой данных. 31 """ 32 db_connection = getattr(g, '_database', None) 33 if db_connection is None: 34 # для тестирования 35 # раскомментировать, если необходимо пересоздать БД 36 # os.remove('../data.db') 37 if not os.path.exists('../data.db'): 38 db_connection = g._database = sqlite3.connect('../data.db') 39 db_initialization.create_tables(db_connection) 40 db_initialization.load_test_data(db_connection) 41 else: 42 db_connection = g._database = sqlite3.connect('../data.db') 43 return db_connection
Функция, которая получает соединение с базой данных. Если соединение не существует, устанавливает новое соединение с использованием SQLite с 'data.db'. Возвращает существующее или новосозданное соединение с базой данных.
46@app.teardown_appcontext 47def close_db_connection(exception: Exception) -> None: 48 """ 49 Функция завершения, которая закрывает соединение с базой данных. 50 Параметры: 51 - exception: Исключение, которое вызвало завершение, если таковое имеется. 52 """ 53 db_connection = getattr(g, '_database', None) 54 if db_connection is not None: 55 db_connection.close()
Функция завершения, которая закрывает соединение с базой данных. Параметры:
- exception: Исключение, которое вызвало завершение, если таковое имеется.
58def update_players_tournaments() -> None: 59 """ 60 Постоянно обновляет турниры игроков в БД. 61 62 Извлекает список игроков из БД и для каждого игрока 63 извлекает турниры из Интернета и обновляет базу данных, если 64 турниры разные. Между каждой итерацией проходит 1 день. 65 """ 66 # log.warning('Updating players tournaments...') 67 68 # Подключаемся к БД. 69 con = sqlite3.connect('../data.db') 70 cursor = con.cursor() 71 72 while True: 73 # Получаем список игроков. 74 query = "SELECT player_id FROM players" 75 players_ids: list[str] = [row[0] for row in cursor.execute(query).fetchall()] 76 77 # Проход по всем игрокам. 78 for player_id in players_ids: 79 # Запрос на получение турниров игрока из БД. 80 query = "SELECT tournaments FROM players WHERE player_id = ?" 81 tournaments_in_db: str = cursor.execute(query, (player_id,)).fetchall()[0][0] 82 83 # Запрос на получение турниров игрока {player_id} из Интернета. 84 # log.warning(f'Запрос на получение турниров игрока {player_id} из Интернета.') 85 try: 86 url = f'https://api.rating.chgk.net/players/{player_id}/tournaments' 87 response = requests.get(url=url) 88 if response.status_code != 200: 89 raise Exception( 90 f'Something wrong with request to API. Status code: {response.status_code}, from {url}') 91 92 tournaments_in_web = [i['idtournament'] for i in response.json()] 93 tournaments_in_web = ','.join(map(str, tournaments_in_web)) 94 95 # Коли записи разнятся, обновляем БД. 96 # log.warning(f'Обновляем БД для игрока {player_id}.') 97 if tournaments_in_web != tournaments_in_db: 98 query = "UPDATE players SET tournaments = ? WHERE player_id = ?" 99 cursor.execute(query, (tournaments_in_web, player_id)) 100 con.commit() 101 time.sleep(2) 102 # Если 404, то предполагаем неполадки сети, логируем, ждём 1 час и продолжаем. 103 except Exception as e: 104 # log.error(e) 105 time.sleep(60 * 60) # 1-hour sleep after error 106 continue 107 108 # После прохода по всем игрокам ждём 1 день. 109 time.sleep(60 * 60 * 24) # 1 day
Постоянно обновляет турниры игроков в БД.
Извлекает список игроков из БД и для каждого игрока извлекает турниры из Интернета и обновляет базу данных, если турниры разные. Между каждой итерацией проходит 1 день.
116@app.route('/') 117def index(): 118 """ 119 Обработчик маршрута для корневого URL-адреса ("/"). Очищает сеанс, извлекает данные из БД, 120 добавляет имена столбцов в начало данных, преобразует данные в формат JSON, сортирует их по полю "_sum_minus_2", 121 а затем отображает шаблон index.html с отсортированными данными и именами столбцов. 122 """ 123 session.clear() 124 125 # Получаем данные из базы 126 db_connection = get_db_connection() 127 data, columns = db_management.get_maintable(db_connection) 128 129 # Добавление названий столбцов в начало 130 thead = ['Команда', 'Сумма', 'Сумма - 2'] + columns[3:] 131 132 # Преобразование данных в формат JSON 133 json_data = to_json(data, columns) 134 135 # Сортировка по сумме 136 data = sorted(json_data, key=lambda x: x['_sum_minus_2'], reverse=True) 137 138 return render_template('index.html', thead=thead, data=data)
Обработчик маршрута для корневого URL-адреса ("/"). Очищает сеанс, извлекает данные из БД, добавляет имена столбцов в начало данных, преобразует данные в формат JSON, сортирует их по полю "_sum_minus_2", а затем отображает шаблон index.html с отсортированными данными и именами столбцов.
141@app.route('/login', methods=['POST', 'GET']) 142def admin_login(): 143 """ 144 Обрабатывает логин в систему. Считывает с формы логин/пароль (index.html). 145 146 Проверяет в базе наличие хэша пароля. В случае успеха делает редирект на основную страницу. 147 Помечает успешный залогин в кукисе session[login] = login. 148 В противном случае - пишет Fail и отображает страницу ввода пароля снова. 149 """ 150 db_connection = get_db_connection() 151 cursor = db_connection.cursor() 152 153 log.info('Logon.') 154 155 if request.method == 'POST': 156 login = request.form.get('login') 157 password = request.form.get('password') 158 query = 'SELECT salt FROM users WHERE login = :login' 159 login_exists = cursor.execute(query, {'login': login}).fetchall() 160 161 if login_exists: 162 log.info('There is a salt') 163 salt = login_exists[0][0] 164 165 password_hash = hashlib.scrypt(password=bytes(password, encoding='UTF-8'), 166 salt=bytes(salt, encoding='UTF-8'), 167 n=2 ** 14, r=8, p=1, dklen=64).hex() 168 169 query = """ 170 SELECT 171 count(1) _count 172 FROM 173 users 174 WHERE 175 login =:login 176 AND 177 hash =:hash 178 """ 179 180 data = {'login': login, 'hash': password_hash} 181 182 if cursor.execute(query, data).fetchall()[0][0]: 183 session['login'] = login 184 return redirect('/main_table') 185 else: 186 return render_template('login.html', message='Fail.') 187 188 return render_template('login.html')
Обрабатывает логин в систему. Считывает с формы логин/пароль (index.html).
Проверяет в базе наличие хэша пароля. В случае успеха делает редирект на основную страницу. Помечает успешный залогин в кукисе session[login] = login. В противном случае - пишет Fail и отображает страницу ввода пароля снова.
191@app.route('/main_table') 192def main_table(): 193 """ 194 Функция, которая служит обработчиком маршрута для таблицы. Отображает шаблон 'main_table.html'. 195 """ 196 log.info('Function main_table() was called...') 197 198 thread_status = '🟢' if thread.is_alive() else '🔴' 199 200 if session.get('login'): 201 if request.method == 'GET': 202 return render_template('main_table.html', thread_status=thread_status) 203 if request.method == 'POST': 204 log.debug(request.data) 205 else: 206 return redirect('/login')
Функция, которая служит обработчиком маршрута для таблицы. Отображает шаблон 'main_table.html'.
222@app.route('/add_score', methods=['GET', 'POST']) 223def add_score(): 224 db_connection = get_db_connection() 225 data = [i[0] for i in db_management.get_teams(db_connection)] 226 227 message = '' 228 if request.method == 'POST': 229 log.debug(request.form) 230 message = 'Данные внесли.' 231 return render_template('add_score.html', data=data, message=message)
239@app.route('/get_columns', methods=['GET']) 240def get_columns() -> list[dict]: 241 """ 242 Функция для извлечения названий столбцов из таблицы базы данных и преобразования их в определенный формат 243 для отображения. 244 """ 245 # Подключение к базе данных SQLite и получение данных для главной таблицы 246 db_connection = get_db_connection() 247 data, columns = db_management.get_maintable(db_connection) 248 249 transformed_columns = [] 250 251 # Цикл для преобразования каждого элемента массива строк в объект 252 for column in columns: 253 if column == 'team_name': 254 field_title = "Команда" 255 elif column == '_sum_': 256 field_title = 'Cумма' 257 elif column == '_sum_minus_2': 258 field_title = 'Cум(-2)' 259 else: 260 field_title = '.'.join((column.split('-')[2], column.split('-')[1])) 261 262 transformed_columns.append({ 263 # Пример условной логики для определения значения editor 264 'editor': 'input', # if column == 'team_name' else 'number' 265 'field': column, 266 'hozAlign': 'center' if column == 'summa_2' else 'left', 267 'sorter': 'number', 268 'title': field_title, 269 'validator': 'numeric', 270 # 'contextMenu': 'cellContextMenu' 271 }) 272 return transformed_columns
Функция для извлечения названий столбцов из таблицы базы данных и преобразования их в определенный формат для отображения.
275def to_json(data, columns): 276 """Вспомогательная функция для преобразования данных в формат JSON.""" 277 log.info('Function to_json() was called...') 278 json_data = [] 279 for row in data: 280 row_data = {} 281 for i in range(0, len(columns)): 282 row_data[columns[i]] = row[i] 283 json_data.append(row_data) 284 285 return json_data
Вспомогательная функция для преобразования данных в формат JSON.
288@app.route('/get_data', methods=['GET']) 289def get_data(): 290 if request.referrer is None: 291 return 'Що таке?' 292 293 db_connection = get_db_connection() 294 295 who = request.referrer.split('/')[-1] 296 match who: 297 case 'main_table': 298 data, columns = db_management.get_maintable(db_connection) 299 return to_json(data, columns) 300 case 'add_player': 301 data = db_management.get_players(db_connection) 302 log.debug(data) 303 columns = ['fio', 'player_id', 'team_name'] # менять на человеческие 'ФИО', 'ИД игрока' в table_players.js 304 return to_json(data, columns) 305 case 'add_team': 306 data = db_management.get_teams(db_connection) 307 columns = ['Name'] 308 return to_json(data, columns)
311@app.route('/check_packet', methods=['POST']) 312def check_packet(): 313 log.debug(request.json) 314 packets = [i for i in request.json if i] 315 answer = [] 316 for packet_id in packets: 317 r = requests.get(f'https://rating.maii.li/b/tournament/{packet_id}/') 318 319 pattern = r'/\/b\/player\/(\d+)/gm' 320 matches = re.findall(pattern, r.text) 321 print(matches) 322 print(len(matches)) 323 answer.append(matches) 324 325 return jsonify(success=True, data=''.join(answer))
328@app.route('/test', methods=['POST', 'GET']) 329def test(): 330 if request.method == 'POST': 331 log.debug(request.data.decode('utf-8')) 332 data = request.data.decode('utf-8') 333 log.info('OK') 334 # json_data = [ 335 # {'id': 1, 'name': "Tiger Nixon", 'position': "System Architect", 'office': "Edinburgh", 'extension': "5421", 336 # 'startDate': "2011/04/25", 'salary': "Tiger Nixon"} 337 # ] 338 # lll = {'data': [[1, 'test', 78], 339 # [2, 'test2', 145], 340 # [3, 'test3', 23], 341 # [4, 'test4', 45]], 342 # 'columns': ['id', 'name', 'position'] 343 # } 344 345 return render_template('tablecelledit.html')
348@app.route('/update', methods=['POST', 'GET']) 349def update(): 350 if request.method == 'POST': 351 db_connection = get_db_connection() 352 who = request.referrer.split('/')[-1] 353 match who: 354 case 'main_table': 355 log.debug(request.json) 356 date = (datetime.today() - timedelta(days=1)).strftime('%Y-%m-%d') 357 db_management.update_main_table(db_connection, request.json, date) 358 # case 'add_player': 359 # return render_template('add_player.html') 360 # case 'add_team': 361 # return render_template('add_team.html') 362 return {'success': True}
382@app.route('/update_table_players', methods=['POST']) 383def update_table_players(): 384 """ 385 Функция для обновления таблицы игроков данными, полученными через POST-запрос. 386 Эта функция добавляет нового игрока в таблицу players, используя его полное имя (fio) и идентификатор игрока. 387 В случае успешного выполнения возвращает JSON-ответ с сообщением об успехе, в противном случае возвращает сообщение 388 об ошибке. 389 """ 390 db_connection = get_db_connection() 391 cursor = db_connection.cursor() 392 try: 393 d = request.json 394 log.debug(d) 395 fio = d['playerFIO'] 396 player_id = d['playerName'] 397 team_name = d['teamName'] 398 log.debug(fio, player_id, team_name) 399 # Получаем идентификатор команды 400 query = 'select id from teams where name = ?' 401 cursor.execute(query, (team_name,)) 402 team_id = cursor.fetchone()[0] 403 log.debug(team_id) 404 # Записываем данные в таблицу players 405 query = 'insert into players (fio, player_id, team_id) values (?, ?, ?)' 406 cursor.execute(query, (fio, player_id, team_id)) 407 db_connection.commit() 408 log.info(f'Записали игрока {fio} в таблицу players.') 409 410 response = {'success': True} 411 return jsonify(response) 412 413 except Exception as e: 414 log.error(f'Error: {e}') 415 return jsonify(success=False, error=str(e))
Функция для обновления таблицы игроков данными, полученными через POST-запрос. Эта функция добавляет нового игрока в таблицу players, используя его полное имя (fio) и идентификатор игрока. В случае успешного выполнения возвращает JSON-ответ с сообщением об успехе, в противном случае возвращает сообщение об ошибке.
418@app.route('/update_table_teams', methods=['POST']) 419def update_table_teams(): 420 """ 421 Функция для обновления таблицы команд данными, полученными через POST-запрос. 422 Эта функция добавляет новую команду в таблицу teams. 423 В случае успешного выполнения возвращает JSON-ответ с сообщением об успехе, в противном случае возвращает сообщение 424 об ошибке. 425 """ 426 db_connection = get_db_connection() 427 cursor = db_connection.cursor() 428 try: 429 log.debug(request.json) 430 d = request.json 431 log.debug(type(d)) 432 t_name = d['team_name'] 433 query = 'insert into teams(name) values (?)' 434 cursor.execute(query, (t_name,)) 435 db_connection.commit() 436 437 response = {'success': True} 438 return jsonify(response) 439 440 except Exception as e: 441 log.error(f'Error: {e}') 442 return jsonify(success=False, error=str(e))
Функция для обновления таблицы команд данными, полученными через POST-запрос. Эта функция добавляет новую команду в таблицу teams. В случае успешного выполнения возвращает JSON-ответ с сообщением об успехе, в противном случае возвращает сообщение об ошибке.
445@app.errorhandler(404) 446def page_not_found(error): 447 """Отображает страницу ошибки в случае перехода на несуществующую страницу.""" 448 return render_template('404.html', error=error), 404
Отображает страницу ошибки в случае перехода на несуществующую страницу.