Hana Celeste commited on
Commit
9bfca98
·
verified ·
1 Parent(s): 632bc5a

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +96 -72
main.py CHANGED
@@ -1,5 +1,4 @@
1
  import asyncio
2
- import os
3
  import requests
4
  from fastapi import FastAPI
5
  from playwright.async_api import async_playwright
@@ -8,92 +7,117 @@ app = FastAPI()
8
 
9
  IMGBB_API_KEY = "093dee93ec19418d26cc76f40e053725"
10
 
11
- # Proxy ScrapingAnt
12
- PROXY_CONFIG = {
13
- "server": "http://proxy.scrapingant.com:8080",
14
- "username": "scrapingant&proxy_type=residential&proxy_country=VN&browser=false",
15
- "password": "20e836f16c914c2f816d9d4ab53f83b0"
16
- }
17
-
18
- async def run_logic(uid: str):
19
  async with async_playwright() as p:
20
- browser = await p.chromium.launch(headless=True, proxy=PROXY_CONFIG)
 
21
  context = await browser.new_context(
22
- accept_downloads=True,
23
- ignore_https_errors=True,
24
- viewport={'width': 1280, 'height': 1500},
25
  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"
26
  )
27
  page = await context.new_page()
28
-
29
- # CHẶN QUẢNG CÁO & TRACKER ĐỂ TIẾT KIỆM PROXY
30
- async def block_aggressively(route):
31
- if route.request.resource_type in ["image", "media", "font"] and "enka.network" not in route.request.url:
32
- await route.abort()
33
- elif any(x in route.request.url for x in ["google-analytics", "doubleclick", "playwire", "ads"]):
34
- await route.abort()
35
- else:
36
- await route.continue_()
37
-
38
- await page.route("**/*", block_aggressively)
39
 
40
  try:
41
- # Truy cập với Timeout cực lớn 120s
42
- await page.goto(f"https://akasha.cv/profile/{uid}", wait_until="commit", timeout=120000)
43
-
44
- # Đợi hàng nhân vật xuất hiện
45
- char_row = "table.custom-table tbody tr.pointer"
46
- await page.wait_for_selector(char_row, timeout=60000)
47
-
48
- # Click và đợi bảng render
49
- await page.click(char_row)
50
-
51
- # Đợi nút Download - Akasha render card khá lâu nên phải kiên nhẫn
52
- dl_btn = 'button.dl-button'
53
- await page.wait_for_selector(dl_btn, timeout=60000)
54
- await asyncio.sleep(8) # Chờ card vẽ xong hoàn toàn
55
 
56
- # Bắt đầu tải file
57
- async with page.expect_download(timeout=90000) as download_info:
58
- await page.click(dl_btn)
59
-
60
- download = await download_info.value
61
- temp_path = f"card_{uid}.png"
62
- await download.save_as(temp_path)
 
 
 
 
 
 
 
 
63
 
64
- # Upload ImgBB
65
- with open(temp_path, "rb") as file:
66
- res = requests.post(
67
- "https://api.imgbb.com/1/upload",
68
- data={"key": IMGBB_API_KEY},
69
- files={"image": file.read()},
70
- timeout=60
71
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  await browser.close()
74
- if os.path.exists(temp_path): os.remove(temp_path)
 
 
 
 
 
75
 
76
- result = res.json()
77
- if result.get('success'):
78
- return result['data']['url']
79
- raise Exception(f"ImgBB Fail: {result.get('error')}")
80
 
81
  except Exception as e:
82
- if 'browser' in locals(): await browser.close()
83
- if os.path.exists(f"card_{uid}.png"): os.remove(f"card_{uid}.png")
84
- raise e
85
 
86
- @app.get("/akasha")
87
- async def generate(uid: str):
88
- # Thử lại tối đa 2 lần
89
- for i in range(2):
90
- try:
91
- url = await run_logic(uid)
92
- return {"uid": uid, "card_url": url}
93
- except Exception as e:
94
- if i == 1: return {"uid": uid, "card_url": f"Error: {str(e)}"}
95
- await asyncio.sleep(5)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
  @app.get("/")
98
  def home():
99
- return {"status": "Aggressive Blocking API is Live"}
 
 
 
 
 
 
 
1
  import asyncio
 
2
  import requests
3
  from fastapi import FastAPI
4
  from playwright.async_api import async_playwright
 
7
 
8
  IMGBB_API_KEY = "093dee93ec19418d26cc76f40e053725"
9
 
10
+ async def get_enka_data(uid: str, char_name: str = None):
 
 
 
 
 
 
 
11
  async with async_playwright() as p:
12
+ # Khởi tạo trình duyệt
13
+ browser = await p.chromium.launch(headless=True, args=['--no-sandbox'])
14
  context = await browser.new_context(
15
+ viewport={'width': 1920, 'height': 1080},
 
 
16
  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"
17
  )
18
  page = await context.new_page()
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  try:
21
+ url = f"https://enka.network/u/{uid}/"
22
+ print(f"📡 Truy cập Enka: {url}")
23
+ await page.goto(url, wait_until="networkidle", timeout=60000)
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ # --- LOGIC CHỌN NHÂN VẬT ---
26
+ if char_name:
27
+ # Tự động viết hoa chữ cái đầu để khớp với URL ảnh của Enka (vd: citlali -> Citlali)
28
+ formatted_name = char_name.capitalize()
29
+ # Tìm avatar dựa trên thuộc tính style chứa link ảnh nhân vật
30
+ char_selector = f"//div[contains(@class, 'avatar')]//figure[contains(@style, '{formatted_name}')]"
31
+
32
+ try:
33
+ await page.wait_for_selector(char_selector, timeout=10000)
34
+ await page.click(char_selector)
35
+ print(f"✅ Đã chọn nhân vật: {formatted_name}")
36
+ # Đợi 2s để Enka render lại thông số nhân vật mới
37
+ await asyncio.sleep(2)
38
+ except:
39
+ print(f"⚠️ Không tìm thấy nhân vật '{formatted_name}', dùng mặc định.")
40
 
41
+ # --- LOGIC CHỤP CARD ---
42
+ btn_selector = 'button[data-icon="image"]'
43
+ await page.wait_for_selector(btn_selector, timeout=20000)
44
+ await page.click(btn_selector)
45
+
46
+ # Chờ ảnh Blob (Card đã render xong)
47
+ img_selector = '.Loda img[src^="blob:"]'
48
+ await page.wait_for_selector(img_selector, timeout=30000)
49
+
50
+ # Chuyển ảnh từ Blob sang Base64
51
+ img_base64 = await page.evaluate("""
52
+ async () => {
53
+ const img = document.querySelector('.Loda img[src^="blob:"]');
54
+ const res = await fetch(img.src);
55
+ const blob = await res.blob();
56
+ return new Promise(r => {
57
+ const reader = new FileReader();
58
+ reader.onloadend = () => r(reader.result.split(',')[1]);
59
+ reader.readAsDataURL(blob);
60
+ });
61
+ }
62
+ """)
63
 
64
  await browser.close()
65
+
66
+ # --- UPLOAD IMGBB ---
67
+ res = requests.post(
68
+ "https://api.imgbb.com/1/upload",
69
+ data={"key": IMGBB_API_KEY, "image": img_base64}
70
+ )
71
 
72
+ return res.json().get('data', {}).get('url', "Lỗi Upload")
 
 
 
73
 
74
  except Exception as e:
75
+ if 'browser' in locals():
76
+ await browser.close()
77
+ return f"Error: {str(e)}"
78
 
79
+ # --- ENDPOINTS ---
80
+
81
+ @app.get("/gen")
82
+ async def generate(uid: str, char: str = None):
83
+ """
84
+ Endpoint lấy Card nhân vật.
85
+ Sử dụng: /gen?uid=890096220&char=citlali
86
+ """
87
+ url = await get_enka_data(uid, char)
88
+ return {
89
+ "uid": uid,
90
+ "char_requested": char or "default",
91
+ "card_url": url
92
+ }
93
+
94
+ @app.get("/list")
95
+ async def list_chars(uid: str):
96
+ """Lấy danh sách tên nhân vật đang hiển thị để Bot dễ gọi"""
97
+ async with async_playwright() as p:
98
+ browser = await p.chromium.launch(headless=True, args=['--no-sandbox'])
99
+ page = await browser.new_page()
100
+ await page.goto(f"https://enka.network/u/{uid}/", wait_until="networkidle")
101
+
102
+ chars = await page.evaluate("""
103
+ () => {
104
+ const items = document.querySelectorAll('.CharacterList .avatar figure.chara');
105
+ return Array.from(items).map(el => {
106
+ const style = el.getAttribute('style');
107
+ const match = style.match(/UI_AvatarIcon_Side_(.*?)\\./);
108
+ return match ? match[1] : null;
109
+ }).filter(n => n !== null);
110
+ }
111
+ """)
112
+ await browser.close()
113
+ return {"uid": uid, "available_characters": chars}
114
 
115
  @app.get("/")
116
  def home():
117
+ return {
118
+ "status": "Enka API Ready",
119
+ "usage": {
120
+ "get_card": "/gen?uid=890096220&char=citlali",
121
+ "list_chars": "/list?uid=890096220"
122
+ }
123
+ }