Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import json | |
| import time | |
| from typing import List, Dict, Tuple | |
| import random | |
| # Mock data để demo khi API bị block | |
| MOCK_DATA = { | |
| 1: [{"target": "36264"}, {"target": "5121"}, {"target": "35230"}, {"target": "235"}, {"target": "21947"}, {"target": "550"}, {"target": "42"}, {"target": "1899"}, {"target": "17642"}, {"target": "1273"}, {"target": "51935"}, {"target": "2958"}, {"target": "19823"}, {"target": "34781"}, {"target": "2107"}, {"target": "60808"}, {"target": "31736"}, {"target": "27453"}, {"target": "43726"}], | |
| 2: [{"target": "12345"}, {"target": "67890"}, {"target": "44"}, {"target": "11111"}, {"target": "22222"}], | |
| 3: [{"target": "98765"}, {"target": "44"}, {"target": "33333"}, {"target": "44444"}], | |
| 4: [{"target": "55555"}, {"target": "66666"}, {"target": "77777"}], | |
| 5: [{"target": "88888"}, {"target": "99999"}, {"target": "44"}], | |
| 6: [{"target": "12121"}, {"target": "23232"}, {"target": "34343"}], | |
| 7: [{"target": "45454"}, {"target": "56565"}, {"target": "67676"}], | |
| 8: [{"target": "78787"}, {"target": "89898"}, {"target": "90909"}], | |
| 9: [{"target": "10101"}, {"target": "20202"}, {"target": "30303"}], | |
| 10: [{"target": "40404"}, {"target": "50505"}, {"target": "60606"}], | |
| 11: [{"target": "70707"}, {"target": "80808"}, {"target": "90909"}] | |
| } | |
| def try_api_call(area: int, headers: dict) -> tuple: | |
| """ | |
| Thử gọi API thật trước, nếu lỗi thì dùng mock data | |
| """ | |
| base_url = "https://cmangax2.com/api/score_list" | |
| params = {'type': 'battle_mine', 'area': area} | |
| try: | |
| response = requests.get(base_url, params=params, headers=headers, timeout=10) | |
| if response.status_code == 200: | |
| data = response.json() | |
| if isinstance(data, list): | |
| return True, data | |
| elif isinstance(data, dict) and 'data' in data: | |
| return True, data['data'] | |
| else: | |
| return True, [] | |
| else: | |
| return False, response.status_code | |
| except Exception as e: | |
| return False, str(e) | |
| def search_target_in_api(target_id: str) -> str: | |
| """ | |
| Tìm target ID trong tất cả các area - với fallback sang mock data | |
| """ | |
| if not target_id.strip(): | |
| return "❌ Vui lòng nhập Target ID" | |
| # Headers giả lập browser | |
| headers = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', | |
| 'Accept': 'application/json, text/plain, */*', | |
| 'Accept-Language': 'en-US,en;q=0.9,vi;q=0.8', | |
| 'Accept-Encoding': 'gzip, deflate, br', | |
| 'Referer': 'https://cmangax2.com/', | |
| 'Origin': 'https://cmangax2.com', | |
| 'Connection': 'keep-alive', | |
| 'Sec-Fetch-Dest': 'empty', | |
| 'Sec-Fetch-Mode': 'cors', | |
| 'Sec-Fetch-Site': 'same-origin', | |
| 'DNT': '1' | |
| } | |
| results = [] | |
| api_working = False | |
| # Header cho output | |
| output = f"🔍 Đang tìm Target ID: **{target_id}**\n\n" | |
| for area in range(1, 12): # Area 1-11 | |
| output += f"📍 **Area {area}**: " | |
| # Thử API thật trước | |
| success, data = try_api_call(area, headers) | |
| if success: | |
| api_working = True | |
| search_data = data | |
| output += "✅ API hoạt động - " | |
| else: | |
| # Fallback sang mock data | |
| search_data = MOCK_DATA.get(area, []) | |
| if not api_working and area == 1: | |
| output += f"⚠️ API bị block (lỗi: {data}), sử dụng dữ liệu demo - " | |
| elif not api_working: | |
| output += "📊 Demo data - " | |
| # Tìm target trong data | |
| found_positions = [] | |
| for index, item in enumerate(search_data): | |
| if isinstance(item, dict) and item.get('target') == target_id.strip(): | |
| found_positions.append(index) | |
| if found_positions: | |
| output += f"✅ **FOUND!** Ô: {found_positions}\n" | |
| results.append({ | |
| 'area': area, | |
| 'positions': found_positions, | |
| 'data': search_data, | |
| 'is_mock': not success | |
| }) | |
| # Hiển thị chi tiết | |
| output += f" 📊 **Chi tiết:**\n" | |
| for pos in found_positions: | |
| if pos < len(search_data): | |
| item_detail = search_data[pos] | |
| output += f" • Ô {pos}: {json.dumps(item_detail, ensure_ascii=False)}\n" | |
| else: | |
| output += "❌ Không tìm thấy\n" | |
| # Delay | |
| time.sleep(0.5) | |
| # Thông báo về data source | |
| if not api_working: | |
| output += f"\n🛠️ **LƯU Ý**: API cmangax2.com hiện bị block (lỗi 403), app đang sử dụng dữ liệu demo để minh họa chức năng.\n" | |
| output += f"📧 **Để sửa**: Cần liên hệ admin cmangax2.com để whitelist IP hoặc cung cấp API key.\n\n" | |
| # Tổng kết | |
| output += f"{'='*50}\n" | |
| output += f"📈 **TỔNG KẾT:**\n" | |
| if results: | |
| output += f"🎯 **Tìm thấy Target '{target_id}' tại:**\n" | |
| for result in results: | |
| area = result['area'] | |
| positions = result['positions'] | |
| data_type = "Demo" if result['is_mock'] else "Live API" | |
| output += f"• **Area {area}**: Ô {positions} ({data_type})\n" | |
| # Hiển thị format như API trả về | |
| output += f"\n📋 **Format như API:**\n" | |
| for result in results: | |
| output += f"\n**Area {result['area']}** ({'Demo data' if result['is_mock'] else 'Live API'}):\n" | |
| output += "```json\n" | |
| # Chỉ hiển thị các item có target match | |
| filtered_items = [] | |
| for pos in result['positions']: | |
| if pos < len(result['data']): | |
| filtered_items.append({ | |
| 'index': pos, | |
| 'data': result['data'][pos] | |
| }) | |
| output += json.dumps(filtered_items, indent=2, ensure_ascii=False) | |
| output += "\n```\n" | |
| else: | |
| data_source = "dữ liệu demo" if not api_working else "API" | |
| output += f"❌ **Không tìm thấy Target '{target_id}' trong {data_source} (area 1-11)**\n" | |
| return output | |
| def get_area_details(area_num: str) -> str: | |
| """ | |
| Xem chi tiết một area cụ thể - với fallback sang mock data | |
| """ | |
| try: | |
| area = int(area_num.strip()) | |
| if area < 1 or area > 11: | |
| return "❌ Area phải từ 1 đến 11" | |
| except: | |
| return "❌ Vui lòng nhập số area hợp lệ" | |
| # Headers giả lập browser | |
| headers = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', | |
| 'Accept': 'application/json, text/plain, */*', | |
| 'Accept-Language': 'en-US,en;q=0.9,vi;q=0.8', | |
| 'Referer': 'https://cmangax2.com/', | |
| 'Origin': 'https://cmangax2.com' | |
| } | |
| # Thử API thật trước | |
| success, data = try_api_call(area, headers) | |
| output = f"📍 **Chi tiết Area {area}:**\n\n" | |
| if success: | |
| search_data = data | |
| output += "✅ **Dữ liệu từ API thật**\n\n" | |
| else: | |
| search_data = MOCK_DATA.get(area, []) | |
| output += f"⚠️ **API bị block (lỗi: {data}), hiển thị dữ liệu demo**\n\n" | |
| output += f"📊 **Tổng số items:** {len(search_data)}\n\n" | |
| # Hiển thị tất cả targets | |
| targets = set() | |
| for item in search_data: | |
| if isinstance(item, dict) and 'target' in item: | |
| targets.add(item['target']) | |
| output += f"🎯 **Các Target có trong area:** {sorted(targets, key=lambda x: int(x) if x.isdigit() else 0)}\n\n" | |
| # Hiển thị format đầy đủ | |
| output += "```json\n" | |
| display_data = [] | |
| for i, item in enumerate(search_data[:20]): # Chỉ hiển thị 20 item đầu | |
| display_data.append({f"{i}": item}) | |
| output += json.dumps(display_data, indent=2, ensure_ascii=False) | |
| if len(search_data) > 20: | |
| output += f"\n... và {len(search_data) - 20} items khác" | |
| output += "\n```" | |
| return output | |
| def simulate_api_fix() -> str: | |
| """ | |
| Mô phỏng hướng dẫn sửa API | |
| """ | |
| return """ | |
| # 🔧 Hướng dẫn sửa lỗi API cmangax2.com | |
| ## 🚨 Vấn đề hiện tại: | |
| - API trả về **403 Forbidden** | |
| - Server chặn requests từ Python/Scripts | |
| - App đang dùng **mock data** để demo | |
| ## 💡 Các giải pháp: | |
| ### 1. **Liên hệ Admin** 📧 | |
| ``` | |
| Email: admin@cmangax2.com | |
| Yêu cầu: Whitelist IP hoặc cung cấp API key | |
| ``` | |
| ### 2. **Browser Automation** 🤖 | |
| ```python | |
| from selenium import webdriver | |
| # Dùng browser thật để call API | |
| ``` | |
| ### 3. **Proxy/VPN** 🌐 | |
| ```python | |
| proxies = {'http': 'http://proxy:port'} | |
| requests.get(url, proxies=proxies) | |
| ``` | |
| ### 4. **Web Scraping** 🕷️ | |
| - Scrape HTML thay vì gọi API | |
| - Parse dữ liệu từ trang web | |
| ## ✅ Khi API hoạt động: | |
| App sẽ tự động chuyển từ mock data sang live data! | |
| """ | |
| # Tạo Gradio Interface | |
| with gr.Blocks(title="cmangax2 Target Finder - Alternative", theme=gr.themes.Soft()) as app: | |
| gr.Markdown("# 🎯 cmangax2 Target Finder") | |
| gr.Markdown("Tìm Target ID trong tất cả các area của cmangax2.com API (với fallback demo data)") | |
| # Status indicator | |
| with gr.Row(): | |
| status_box = gr.Markdown("🔄 **Status**: Đang kiểm tra kết nối API...") | |
| with gr.Tab("🔍 Tìm Target"): | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| target_input = gr.Textbox( | |
| label="Target ID", | |
| placeholder="Nhập Target ID (ví dụ: 44, 51935)", | |
| value="44" | |
| ) | |
| with gr.Column(scale=1): | |
| search_btn = gr.Button("🔍 Tìm kiếm", variant="primary") | |
| search_output = gr.Markdown(label="Kết quả") | |
| search_btn.click( | |
| fn=search_target_in_api, | |
| inputs=[target_input], | |
| outputs=[search_output] | |
| ) | |
| with gr.Tab("📊 Xem Area"): | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| area_input = gr.Textbox( | |
| label="Area Number", | |
| placeholder="Nhập số area (1-11)", | |
| value="1" | |
| ) | |
| with gr.Column(scale=1): | |
| area_btn = gr.Button("📊 Xem chi tiết", variant="secondary") | |
| area_output = gr.Markdown(label="Chi tiết Area") | |
| area_btn.click( | |
| fn=get_area_details, | |
| inputs=[area_input], | |
| outputs=[area_output] | |
| ) | |
| with gr.Tab("🔧 Sửa API"): | |
| fix_output = gr.Markdown(simulate_api_fix()) | |
| refresh_btn = gr.Button("🔄 Kiểm tra lại API", variant="secondary") | |
| def check_api_status(): | |
| success, _ = try_api_call(1, {}) | |
| if success: | |
| return "✅ **API hoạt động bình thường!** Dữ liệu từ server thật." | |
| else: | |
| return "❌ **API vẫn bị block.** Đang dùng mock data." | |
| refresh_btn.click( | |
| fn=check_api_status, | |
| outputs=[status_box] | |
| ) | |
| with gr.Tab("ℹ️ Hướng dẫn"): | |
| gr.Markdown(""" | |
| ## 📖 Cách sử dụng: | |
| ### 🔍 Tab "Tìm Target": | |
| 1. Nhập **Target ID** cần tìm (ví dụ: 44, 51935) | |
| 2. Nhấn **"Tìm kiếm"** | |
| 3. Xem kết quả: | |
| - ✅ **Live API**: Dữ liệu từ server thật | |
| - 📊 **Demo data**: Dữ liệu mẫu khi API bị block | |
| ### 📊 Tab "Xem Area": | |
| 1. Nhập **số area** (1-11) | |
| 2. Nhấn **"Xem chi tiết"** | |
| 3. Xem tất cả targets trong area | |
| ### 🔧 Tab "Sửa API": | |
| - Hướng dẫn khắc phục lỗi 403 | |
| - Kiểm tra trạng thái API | |
| ### 🎯 **Demo Targets có sẵn:** | |
| - **Target 44**: Area 2, 3, 5 | |
| - **Target 51935**: Area 1 | |
| - **Target 36264**: Area 1 | |
| - **Target 42**: Area 1 | |
| ### ⚠️ **Lưu ý:** | |
| - App tự động fallback sang demo data khi API bị block | |
| - Khi API hoạt động lại, sẽ dùng dữ liệu thật | |
| - Demo data chỉ để minh họa chức năng | |
| """) | |
| # Chạy ứng dụng | |
| if __name__ == "__main__": | |
| app.launch() |