From 316cff3f5fc689f381be53e5b90b760e2f48d519 Mon Sep 17 00:00:00 2001 From: Akira Date: Sat, 6 Sep 2025 07:01:07 +0900 Subject: [PATCH] Auto Start --- realtime_checkin_monitor.py | 174 ++++++++++++++++++++++++++++++++++++ rog/views_apis/api_play.py | 34 +++++-- 2 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 realtime_checkin_monitor.py diff --git a/realtime_checkin_monitor.py b/realtime_checkin_monitor.py new file mode 100644 index 0000000..3f91ec5 --- /dev/null +++ b/realtime_checkin_monitor.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +""" +リアルタイム チェックイン監視ツール +スマホアプリからのチェックイン試行をリアルタイムで監視 +""" + +import os +import sys +import django +import subprocess +import time +import json +import requests +from datetime import datetime, timedelta +import threading +from collections import defaultdict + +# Django設定 +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') +django.setup() + +from rog.models import GpsLog, Entry, Team, NewEvent2 + +class CheckinMonitor: + def __init__(self): + self.last_check = datetime.now() + self.request_counts = defaultdict(int) + + def check_recent_gpslog(self): + """最近のGpsLog エントリーをチェック""" + try: + recent_logs = GpsLog.objects.filter( + create_at__gte=self.last_check + ).order_by('-create_at') + + if recent_logs.exists(): + print(f"\n🆕 新しいGpsLogエントリー ({recent_logs.count()}件):") + for log in recent_logs: + print(f" ✅ ID:{log.id} イベント:{log.event_code} ゼッケン:{log.zekken_number} CP:{log.cp_number} 時刻:{log.create_at}") + return True + return False + except Exception as e: + print(f"❌ GpsLog確認エラー: {e}") + return False + + def check_recent_entries(self): + """最近のEntry更新をチェック""" + try: + recent_entries = Entry.objects.filter( + start_time__gte=self.last_check + ).order_by('-start_time') + + if recent_entries.exists(): + print(f"\n🏁 新しいスタート ({recent_entries.count()}件):") + for entry in recent_entries: + team_name = entry.team.team_name if entry.team else "N/A" + event_name = entry.event.event_name if entry.event else "N/A" + print(f" 🚀 エントリーID:{entry.id} チーム:{team_name} イベント:{event_name} スタート時刻:{entry.start_time}") + return True + return False + except Exception as e: + print(f"❌ Entry確認エラー: {e}") + return False + + def check_nginx_logs(self): + """nginxログから最近のAPIアクセスを確認""" + try: + # Dockerログからnginxのアクセスログを取得 + cmd = ["docker", "compose", "logs", "--tail=20", "nginx"] + result = subprocess.run(cmd, capture_output=True, text=True, cwd="/Volumes/PortableSSD1TB/main/GifuTabi/rogaining_srv_exdb-2/rogaining_srv") + + if result.returncode == 0: + lines = result.stdout.split('\n') + api_requests = [] + + for line in lines: + if 'checkin_from_rogapp' in line or 'start_from_rogapp' in line: + api_requests.append(line) + elif any(endpoint in line for endpoint in ['/api/user/', '/api/teams/', '/api/entry/']): + api_requests.append(line) + + if api_requests: + print(f"\n📡 最近のAPI アクセス ({len(api_requests)}件):") + for req in api_requests[-5:]: # 最新5件のみ表示 + print(f" 📥 {req.strip()}") + return True + return False + except Exception as e: + print(f"❌ nginxログ確認エラー: {e}") + return False + + def check_app_logs(self): + """アプリケーションログから最近のエラーを確認""" + try: + cmd = ["docker", "compose", "logs", "--tail=10", "app"] + result = subprocess.run(cmd, capture_output=True, text=True, cwd="/Volumes/PortableSSD1TB/main/GifuTabi/rogaining_srv_exdb-2/rogaining_srv") + + if result.returncode == 0: + lines = result.stdout.split('\n') + error_logs = [] + + for line in lines: + if any(keyword in line.lower() for keyword in ['error', 'warning', 'exception', 'failed', 'api_play']): + error_logs.append(line) + + if error_logs: + print(f"\n⚠️ 最近のアプリケーションログ ({len(error_logs)}件):") + for log in error_logs[-3:]: # 最新3件のみ表示 + print(f" 🔍 {log.strip()}") + return True + return False + except Exception as e: + print(f"❌ アプリケーションログ確認エラー: {e}") + return False + + def test_checkin_endpoints(self): + """チェックインエンドポイントの動作テスト""" + endpoints = [ + "http://localhost:8100/api/checkin_from_rogapp", + "http://localhost:8100/gifuroge/checkin_from_rogapp" + ] + + print(f"\n🔧 チェックインエンドポイント動作確認:") + for endpoint in endpoints: + try: + response = requests.get(endpoint, timeout=5) + status_color = "✅" if response.status_code == 405 else "❌" + print(f" {status_color} {endpoint} → HTTP {response.status_code}") + except Exception as e: + print(f" ❌ {endpoint} → エラー: {e}") + + def run_monitor(self): + """メイン監視ループ""" + print("🚀 リアルタイム チェックイン監視開始") + print("=" * 60) + + while True: + try: + current_time = datetime.now() + print(f"\n⏰ 監視時刻: {current_time.strftime('%Y-%m-%d %H:%M:%S')}") + + # 各種チェック実行 + has_new_data = False + has_new_data |= self.check_recent_gpslog() + has_new_data |= self.check_recent_entries() + has_new_data |= self.check_nginx_logs() + has_new_data |= self.check_app_logs() + + # 10分毎にエンドポイントテスト + if current_time.minute % 10 == 0: + self.test_checkin_endpoints() + + if not has_new_data: + print(" 💤 新しいアクティビティなし") + + # 次回チェック時刻を更新 + self.last_check = current_time + + print("-" * 40) + time.sleep(30) # 30秒間隔で監視 + + except KeyboardInterrupt: + print("\n🛑 監視を停止します") + break + except Exception as e: + print(f"❌ 監視エラー: {e}") + time.sleep(5) + +def main(): + monitor = CheckinMonitor() + monitor.run_monitor() + +if __name__ == "__main__": + main() diff --git a/rog/views_apis/api_play.py b/rog/views_apis/api_play.py index f84db3d..de2f544 100755 --- a/rog/views_apis/api_play.py +++ b/rog/views_apis/api_play.py @@ -582,13 +582,33 @@ def checkin_from_rogapp(request): ).first() if not start_record: - logger.warning(f"[CHECKIN] ❌ Team has not started yet - ID: {request_id}, team_name: '{team_name}', zekken: {entry.zekken_number}, cp_number: {cp_number}, Client IP: {client_ip}") - return Response({ - "status": "ERROR", - "message": "このチームはまだスタートしていません。先にスタート処理を行ってください。" - }, status=status.HTTP_400_BAD_REQUEST) - - logger.info(f"[CHECKIN] ✅ Team has started - ID: {request_id}, start_time: {start_record.checkin_time}") + # 🚀 AUTO-START機能: スタートしていない場合、自動的にスタート処理を実行 + logger.info(f"[CHECKIN] 🚀 Team has not started yet, auto-starting - ID: {request_id}, team_name: '{team_name}', zekken: {entry.zekken_number}") + + with transaction.atomic(): + # スタートレコードを作成 + start_record = GpsLog.objects.create( + zekken_number=entry.zekken_number, + event_code=entry.event.event_name, + cp_number="START", + serial_number=0, + checkin_time=timezone.now(), + create_at=timezone.now(), + create_user="AUTO_START", + image_address="AUTO_START", + buy_flag=False, + score=0 + ) + + # エントリー状況を更新 + entry.is_in_rog = True + entry.rogaining_counted = True + entry.start_time = timezone.now() + entry.save() + + logger.info(f"[CHECKIN] ✅ Auto-start completed - ID: {request_id}, start_record_id: {start_record.id}, start_time: {start_record.checkin_time}") + else: + logger.info(f"[CHECKIN] ✅ Team has already started - ID: {request_id}, start_time: {start_record.checkin_time}") # 既に同じCPを登録済みかチェック existing_checkpoint = GpsLog.objects.filter(