Spaces:
iq7se2
/
8
Runtime error

iq7se2 commited on
Commit
4ad87f6
ยท
verified ยท
1 Parent(s): 21f4d9e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +121 -44
app.py CHANGED
@@ -3,58 +3,155 @@ from flask import Flask, render_template_string
3
  from playwright.sync_api import sync_playwright
4
  from PIL import Image
5
  import img2pdf
 
6
 
7
- # --- ุงู„ุฅุนุฏุงุฏุงุช ---
8
  BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
 
9
  bot = telebot.TeleBot(BOT_TOKEN, threaded=False)
10
  app = Flask(__name__)
11
 
 
 
 
12
  @app.route('/')
13
- def home(): return "<h1>Manga Engine Active</h1>"
14
 
15
- def fetch_chapter_with_playwright(url):
 
16
  with sync_playwright() as p:
17
- # ุชุดุบูŠู„ ู…ุชุตูุญ ู…ุฎููŠ (Headless)
18
  browser = p.chromium.launch(headless=True)
19
  context = browser.new_context(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
20
  page = context.new_page()
21
-
22
  try:
23
- # ุงู„ุฐู‡ุงุจ ู„ู„ุฑุงุจุท ูˆุงู„ุงู†ุชุธุงุฑ ุญุชู‰ ูŠุชู… ุชุญู…ูŠู„ ุงู„ุดุจูƒุฉ ุจุงู„ูƒุงู…ู„ (ู…ุซู„ HakuNeko)
24
  page.goto(url, wait_until="networkidle", timeout=60000)
25
-
26
- # ุงู„ุชู…ุฑูŠุฑ ู„ุฃุณูู„ ุงู„ุตูุญุฉ ุจุจุทุก ู„ุถู…ุงู† ุชุญู…ูŠู„ ุตูˆุฑ (Lazy Loading)
27
- for _ in range(5):
28
- page.mouse.wheel(0, 1000)
29
  time.sleep(1)
30
 
31
- # ุงุณุชุฎุฑุงุฌ ุฑูˆุงุจุท ุงู„ุตูˆุฑ ุงู„ุชูŠ ุชู†ุชู‡ูŠ ุจุงู…ุชุฏุงุฏุงุช ุตูˆุฑ ู…ุนุฑูˆูุฉ
32
  images = page.query_selector_all("img")
33
- img_data_list = []
34
-
35
  for img in images:
36
  src = img.get_attribute("src") or img.get_attribute("data-src")
37
  if src and any(ext in src.lower() for ext in ['.jpg', '.jpeg', '.png', '.webp']):
38
- # ุชุญูˆูŠู„ ุงู„ุตูˆุฑุฉ ุฅู„ู‰ Bytes
39
  res = page.request.get(src)
40
- if res.status == 200 and len(res.body()) > 20000:
41
- img_data_list.append(Image.open(io.BytesIO(res.body())).convert('RGB'))
42
-
43
  browser.close()
44
- return img_data_list
45
- except Exception as e:
46
  browser.close()
47
  return []
48
 
49
- def process_engine(sample_url, start, end):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  base_part = re.sub(r'/(?:chapter-)?\d+$', '', sample_url.strip().rstrip('/'))
51
  is_azora = "azoramoon" in sample_url
52
  pdf_files = []
53
 
54
  for i in range(int(start), int(end) + 1):
55
  target_url = f"{base_part}/chapter-{i}" if is_azora else f"{base_part}/{i}"
56
- imgs = fetch_chapter_with_playwright(target_url)
57
-
58
  if imgs:
59
  fname = f"Chapter_{i}.pdf"
60
  imgs[0].save(fname, save_all=True, append_images=imgs[1:], format='PDF')
@@ -62,34 +159,14 @@ def process_engine(sample_url, start, end):
62
 
63
  if not pdf_files: return None
64
 
65
- zip_name = f"Engine_Manga_{int(time.time())}.zip"
66
  with zipfile.ZipFile(zip_name, 'w') as zipf:
67
  for f in pdf_files:
68
  zipf.write(f); os.remove(f)
69
  return zip_name
70
 
71
- @bot.message_handler(func=lambda m: True)
72
- def handle_msg(message):
73
- try:
74
- url, range_part = message.text.strip().split(' ')
75
- start, end = range_part.split('-')
76
-
77
- status = bot.reply_to(message, "๐Ÿš€ ุฌุงุฑูŠ ุชุดุบูŠู„ ู…ุญุฑูƒ ุงู„ู…ุญุงูƒุงุฉ... ู‚ุฏ ูŠุณุชุบุฑู‚ ูˆู‚ุชุงู‹ ุฃุทูˆู„ ู„ุชุฌุงูˆุฒ ุงู„ุญู…ุงูŠุฉ.")
78
- zip_path = process_engine(url, start, end)
79
-
80
- if zip_path:
81
- with open(zip_path, 'rb') as f:
82
- bot.send_document(message.chat.id, f, caption=f"โœ… ุงู„ู…ุญุฑูƒ ู†ุฌุญ ููŠ ุณุญุจ ุงู„ูุตูˆู„ {start}-{end}")
83
- os.remove(zip_path)
84
- bot.delete_message(message.chat.id, status.message_id)
85
- else:
86
- bot.edit_message_text("โŒ ุงู„ู…ุญุฑูƒ ู„ู… ูŠุฌุฏ ุตูˆุฑุงู‹. ู‚ุฏ ุชูƒูˆู† ุงู„ุญู…ุงูŠุฉ ู…ุชุทูˆุฑุฉ ุฌุฏุงู‹.", message.chat.id, status.message_id)
87
- except:
88
- bot.reply_to(message, "โš ๏ธ ุงู„ุชู†ุณูŠู‚: ุงู„ุฑุงุจุท ู…ุณุงูุฉ 1-5")
89
-
90
- # ุชุดุบูŠู„ ุงู„ุจูˆุช ูˆุงู„ุณูŠุฑูุฑ
91
  if __name__ == "__main__":
92
- # ุชุซุจูŠุช ุงู„ู…ุชุตูุญุงุช ุงู„ู…ุทู„ูˆุจุฉ ู„ู€ Playwright ุนู†ุฏ ุงู„ุชุดุบูŠู„ ุงู„ุฃูˆู„
93
  os.system("playwright install chromium")
94
  threading.Thread(target=lambda: bot.infinity_polling(), daemon=True).start()
95
  app.run(host="0.0.0.0", port=7860)
 
3
  from playwright.sync_api import sync_playwright
4
  from PIL import Image
5
  import img2pdf
6
+ from telebot import types
7
 
8
+ # --- ุงู„ุฅุนุฏุงุฏุงุช ุงู„ุนุงู…ุฉ ---
9
  BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
10
+ ADMIN_HANDLE = "@svipfast"
11
  bot = telebot.TeleBot(BOT_TOKEN, threaded=False)
12
  app = Flask(__name__)
13
 
14
+ # ุชุฎุฒูŠู† ู…ุคู‚ุช ู„ุจูŠุงู†ุงุช ุงู„ู…ุณุชุฎุฏู…ูŠู†
15
+ user_data = {}
16
+
17
  @app.route('/')
18
+ def home(): return "<h1>Manga Engine Professional is Running</h1>"
19
 
20
+ # --- ู…ุญุฑูƒ ุงู„ุณุญุจ (Playwright) ---
21
+ def fetch_images(url):
22
  with sync_playwright() as p:
 
23
  browser = p.chromium.launch(headless=True)
24
  context = browser.new_context(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
25
  page = context.new_page()
 
26
  try:
 
27
  page.goto(url, wait_until="networkidle", timeout=60000)
28
+ # ุงู„ุชู…ุฑูŠุฑ ู„ุถู…ุงู† ุชุญู…ูŠู„ ุงู„ุตูˆุฑ (Lazy Load)
29
+ for _ in range(4):
30
+ page.mouse.wheel(0, 1500)
 
31
  time.sleep(1)
32
 
 
33
  images = page.query_selector_all("img")
34
+ img_list = []
 
35
  for img in images:
36
  src = img.get_attribute("src") or img.get_attribute("data-src")
37
  if src and any(ext in src.lower() for ext in ['.jpg', '.jpeg', '.png', '.webp']):
 
38
  res = page.request.get(src)
39
+ if res.status == 200 and len(res.body()) > 25000:
40
+ img_list.append(Image.open(io.BytesIO(res.body())).convert('RGB'))
 
41
  browser.close()
42
+ return img_list
43
+ except:
44
  browser.close()
45
  return []
46
 
47
+ # --- ูˆุงุฌู‡ุฉ ุงู„ุจูˆุช ---
48
+
49
+ @bot.message_handler(commands=['start'])
50
+ def send_welcome(message):
51
+ markup = types.InlineKeyboardMarkup(row_width=1)
52
+ btn1 = types.InlineKeyboardButton("๐Ÿ“ฅ ุงุจุฏุฃ ุชุญู…ูŠู„ ู…ุงู†ุฌุง", callback_data="start_download")
53
+ btn2 = types.InlineKeyboardButton("โ„น๏ธ ุดุฑุญ ุทุฑูŠู‚ุฉ ุงู„ุฑูˆุงุจุท", callback_data="how_to_url")
54
+ btn3 = types.InlineKeyboardButton("๐Ÿ‘จโ€๐Ÿ’ป ุชูˆุงุตู„ ู…ุน ุงู„ุฅุฏุงุฑุฉ", url=f"https://t.me/{ADMIN_HANDLE.replace('@','')}")
55
+ markup.add(btn1, btn2, btn3)
56
+
57
+ welcome_text = (
58
+ "<b>ู…ุฑุญุจุงู‹ ุจูƒ ููŠ ู†ุธุงู… ุณุญุจ ุงู„ู…ุงู†ุฌุง ุงู„ุฅุญุชุฑุงููŠ ๐Ÿš€</b>\n\n"
59
+ "ู‡ุฐุง ุงู„ู†ุธุงู… ู…ุฏุนูˆู… ุจู…ุญุฑูƒ ู…ุญุงูƒุงุฉ ู…ุชุทูˆุฑ ู„ุชุฌุงูˆุฒ ุงู„ุญู…ุงูŠุฉ ูˆุณุญุจ ุงู„ูุตูˆู„ ุจุฃุนู„ู‰ ุฌูˆุฏุฉ ู…ู…ูƒู†ุฉ.\n\n"
60
+ f"ู„ู„ุฏุนู… ุงู„ูู†ูŠ: {ADMIN_HANDLE}"
61
+ )
62
+ bot.send_message(message.chat.id, welcome_text, parse_mode="HTML", reply_markup=markup)
63
+
64
+ @bot.callback_query_handler(func=lambda call: True)
65
+ def callback_query(call):
66
+ if call.data == "start_download":
67
+ bot.answer_callback_query(call.id)
68
+ msg = bot.send_message(call.message.chat.id, "<b>ุงู„ุฑุฌุงุก ุฅุฑุณุงู„ ุฑุงุจุท ุงู„ู…ุงู†ุฌุง ุงู„ู…ุฑุงุฏ ุชุญู…ูŠู„ู‡ุง:</b>", parse_mode="HTML")
69
+ bot.register_next_step_handler(msg, get_manga_url)
70
+
71
+ elif call.data == "how_to_url":
72
+ help_text = (
73
+ "<b>๐Ÿ’ก ูƒูŠู ุชุญุตู„ ุนู„ู‰ ุงู„ุฑุงุจุท ุงู„ุตุญูŠุญุŸ</b>\n\n"
74
+ "ูŠุฌุจ ุฃู† ูŠู†ุชู‡ูŠ ุงู„ุฑุงุจุท ุจุฑู‚ู… ุงู„ูุตู„ ู„ูŠุนู…ู„ ุงู„ู†ุธุงู… ุชู„ู‚ุงุฆูŠุงู‹:\n\n"
75
+ "โœ… <b>ุฃุฒูˆุฑุง:</b>\n<code>https://azoramoon.com/series/manga-name/chapter-1</code>\n\n"
76
+ "โœ… <b>ุฃูˆู„ูŠู…ุจูˆุณ:</b>\n<code>https://olympustaff.com/series/manga-name/1</code>\n\n"
77
+ "โš ๏ธ ุชุฃูƒุฏ ู…ู† ู†ุณุฎ ุงู„ุฑุงุจุท ู…ู† ุงู„ู…ุชุตูุญ ู…ุจุงุดุฑุฉ."
78
+ )
79
+ bot.send_message(call.message.chat.id, help_text, parse_mode="HTML")
80
+
81
+ def get_manga_url(message):
82
+ url = message.text.strip()
83
+ if not url.startswith("http"):
84
+ bot.reply_to(message, "โŒ ุงู„ุฑุงุจุท ุบูŠุฑ ุตุงู„ุญ. ูŠุฑุฌู‰ ุงู„ุจุฏุก ุจู€ http")
85
+ return
86
+
87
+ user_data[message.chat.id] = {'url': url}
88
+
89
+ markup = types.InlineKeyboardMarkup()
90
+ markup.add(types.InlineKeyboardButton("๐ŸŽฏ ูุตู„ ูˆุงุญุฏ ูู‚ุท", callback_data="type_single"),
91
+ types.InlineKeyboardButton("๐Ÿ“ฆ ุญุฒู…ุฉ ูุตูˆู„ (ู…ุฏู‰)", callback_data="type_range"))
92
+ markup.add(types.InlineKeyboardButton("โฉ ุชุญู…ูŠู„ 10 ูุตูˆู„ ู‚ุงุฏู…ุฉ", callback_data="type_auto_10"))
93
+
94
+ bot.send_message(message.chat.id, "<b>ุงุฎุชุฑ ุทุฑูŠู‚ุฉ ุงู„ุชุญู…ูŠู„ ุงู„ู…ูุถู„ุฉ:</b>", parse_mode="HTML", reply_markup=markup)
95
+
96
+ @bot.callback_query_handler(func=lambda call: call.data.startswith("type_"))
97
+ def handle_type_selection(call):
98
+ chat_id = call.message.chat.id
99
+ if chat_id not in user_data: return
100
+
101
+ if call.data == "type_single":
102
+ msg = bot.send_message(chat_id, "๐Ÿ”ข ุฃุฑุณู„ ุฑู‚ู… ุงู„ูุตู„ ุงู„ู…ุฑุงุฏ ุชุญู…ูŠู„ู‡:")
103
+ bot.register_next_step_handler(msg, lambda m: start_process(m, "single"))
104
+
105
+ elif call.data == "type_range":
106
+ msg = bot.send_message(chat_id, "๐Ÿ”ข ุฃุฑุณู„ ุงู„ู†ุทุงู‚ ุงู„ู…ุทู„ูˆุจ (ู…ุซุงู„: 1-10):")
107
+ bot.register_next_step_handler(msg, lambda m: start_process(m, "range"))
108
+
109
+ elif call.data == "type_auto_10":
110
+ msg = bot.send_message(chat_id, "๐Ÿ”ข ุฃุฑุณู„ ุฑู‚ู… ุงู„ูุตู„ ุงู„ุฐูŠ ุชุฑูŠุฏ ุงู„ุจุฏุก ู…ู†ู‡:")
111
+ bot.register_next_step_handler(msg, lambda m: start_process(m, "auto10"))
112
+
113
+ def start_process(message, mode):
114
+ chat_id = message.chat.id
115
+ url = user_data[chat_id]['url']
116
+
117
+ try:
118
+ if mode == "single":
119
+ start, end = message.text, message.text
120
+ elif mode == "range":
121
+ start, end = message.text.split('-')
122
+ elif mode == "auto10":
123
+ start = int(message.text)
124
+ end = start + 9
125
+
126
+ status_msg = bot.send_message(chat_id, f"<b>โณ ุฌุงุฑูŠ ุชุดุบูŠู„ ุงู„ู…ุญุฑูƒ...</b>\n๐Ÿ”„ ู…ุนุงู„ุฌุฉ ุงู„ูุตูˆู„ ู…ู† {start} ุฅู„ู‰ {end}", parse_mode="HTML")
127
+
128
+ # ุชู†ููŠุฐ ุงู„ุณุญุจ
129
+ zip_path = run_engine_logic(url, start, end)
130
+
131
+ if zip_path:
132
+ with open(zip_path, 'rb') as f:
133
+ caption = (
134
+ "<b>โœ… ุชู…ุช ุนู…ู„ูŠุฉ ุงู„ุณุญุจ ุจู†ุฌุงุญ</b>\n\n"
135
+ f"๐Ÿ“‚ <b>ุงู„ุญุฒู…ุฉ:</b> {start} - {end}\n"
136
+ f"๐Ÿ‘ค <b>ุจูˆุงุณุทุฉ:</b> {ADMIN_HANDLE}"
137
+ )
138
+ bot.send_document(chat_id, f, caption=caption, parse_mode="HTML")
139
+ os.remove(zip_path)
140
+ bot.delete_message(chat_id, status_msg.message_id)
141
+ else:
142
+ bot.edit_message_text(f"โŒ ูุดู„ ุงู„ู…ุญุฑูƒ ููŠ ุฅูŠุฌุงุฏ ุงู„ุตูˆุฑ. ุชูˆุงุตู„ ู…ุน {ADMIN_HANDLE}", chat_id, status_msg.message_id)
143
+
144
+ except Exception as e:
145
+ bot.send_message(chat_id, "โš ๏ธ ุญุฏุซ ุฎุทุฃ ููŠ ุฅุฏุฎุงู„ ุงู„ุจูŠุงู†ุงุช. ูŠุฑุฌู‰ ุงู„ู…ุญุงูˆู„ุฉ ู…ุฑุฉ ุฃุฎุฑู‰.")
146
+
147
+ def run_engine_logic(sample_url, start, end):
148
  base_part = re.sub(r'/(?:chapter-)?\d+$', '', sample_url.strip().rstrip('/'))
149
  is_azora = "azoramoon" in sample_url
150
  pdf_files = []
151
 
152
  for i in range(int(start), int(end) + 1):
153
  target_url = f"{base_part}/chapter-{i}" if is_azora else f"{base_part}/{i}"
154
+ imgs = fetch_images(target_url)
 
155
  if imgs:
156
  fname = f"Chapter_{i}.pdf"
157
  imgs[0].save(fname, save_all=True, append_images=imgs[1:], format='PDF')
 
159
 
160
  if not pdf_files: return None
161
 
162
+ zip_name = f"Manga_Pack_{int(time.time())}.zip"
163
  with zipfile.ZipFile(zip_name, 'w') as zipf:
164
  for f in pdf_files:
165
  zipf.write(f); os.remove(f)
166
  return zip_name
167
 
168
+ # --- ุชุดุบูŠู„ ุงู„ุชุทุจูŠู‚ ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  if __name__ == "__main__":
 
170
  os.system("playwright install chromium")
171
  threading.Thread(target=lambda: bot.infinity_polling(), daemon=True).start()
172
  app.run(host="0.0.0.0", port=7860)