Dink0 commited on
Commit
c26e5e7
·
verified ·
1 Parent(s): c5a38d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -31
app.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
 
3
  import os
4
  import re
 
5
  from typing import List, Tuple, Union
6
 
7
  import requests
@@ -32,7 +33,8 @@ class ParseRequest(BaseModel):
32
 
33
 
34
  class ParseResponse(BaseModel):
35
- markdown: str
 
36
  telegram_total: int
37
  vk_total: int
38
  errors: List[str]
@@ -42,9 +44,17 @@ class ParseResponse(BaseModel):
42
 
43
  def human_format_views(num: int) -> str:
44
  if num >= 1_000_000:
45
- formatted = f"{num / 1_000_000:.1f}M"
 
46
  else:
47
- formatted = f"{num / 1000:.1f}K"
 
 
 
 
 
 
 
48
  return formatted.replace(".", ",")
49
 
50
 
@@ -160,7 +170,7 @@ def process_telegram_link(channel_username: str, message_id: str, canonical_link
160
  return title, views
161
 
162
  except Exception as exc:
163
- return f"**Ошибка (TG)** при обработке [{canonical_link}]({canonical_link}): {exc}", 0
164
 
165
 
166
  def process_vk_link(owner_id: int, post_id: str, canonical_link: str) -> Tuple[str, int]:
@@ -228,7 +238,11 @@ def normalize_links(links: Union[List[str], str]) -> List[str]:
228
  return [line.strip() for line in raw if line.strip()]
229
 
230
 
231
- def build_markdown(lines: List[Tuple[str, str, object, object]]) -> Tuple[str, int, int, List[str]]:
 
 
 
 
232
  errors: List[str] = []
233
 
234
  tg_groups = {}
@@ -281,50 +295,90 @@ def build_markdown(lines: List[Tuple[str, str, object, object]]) -> Tuple[str, i
281
  reverse=True,
282
  )
283
 
284
- md_lines: List[str] = []
 
285
 
286
- md_lines.append("## Telegram")
287
- md_lines.append(f"**Суммарный охват постов — {human_format_views(tg_total_views)} просмотров**")
 
 
 
288
  if tg_sorted:
 
289
  for idx, (_, data) in enumerate(tg_sorted, start=1):
290
  title = data["title"] or "Telegram"
291
  items = data["items"]
292
  first_link, _first_views = items[0]
293
- line = f"{idx}. [{title}]({first_link})"
 
 
 
294
  if len(items) > 1:
295
  for link2, _v in items[1:]:
296
- line += f" + [ещё]({link2})"
297
  views_str = " + ".join(human_format_views(v) for _, v in items)
298
- line += f" — {views_str}"
299
- md_lines.append(line)
300
- else:
301
- md_lines.append("_Нет ссылок на Telegram_")
302
- md_lines.append("")
303
 
304
- md_lines.append("## ВКонтакте")
305
- md_lines.append(f"**Суммарный охват постов — {human_format_views(vk_total_views)} просмотров**")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  if vk_sorted:
 
307
  for idx, (_, data) in enumerate(vk_sorted, start=1):
308
  title = data["title"] or "VK пост"
309
  items = data["items"]
310
  first_link, _first_views = items[0]
311
- line = f"{idx}. [{title}]({first_link})"
 
 
 
312
  if len(items) > 1:
313
  for link2, _v in items[1:]:
314
- line += f" + [ещё]({link2})"
315
  views_str = " + ".join(human_format_views(v) for _, v in items)
316
- line += f" — {views_str}"
317
- md_lines.append(line)
 
 
 
 
 
 
 
 
318
  else:
319
- md_lines.append("_Нет ссылок на ВКонтакте_")
320
- md_lines.append("")
 
 
321
 
322
  if errors:
323
- md_lines.append("## Ошибки")
324
- md_lines.extend(f"- {err}" for err in errors)
325
- md_lines.append("")
 
 
 
 
 
326
 
327
- return "\n".join(md_lines), tg_total_views, vk_total_views, errors
328
 
329
 
330
  @app.get("/health")
@@ -336,7 +390,7 @@ def health_check():
336
  def parse_links(payload: ParseRequest):
337
  raw_lines = normalize_links(payload.links)
338
  if not raw_lines:
339
- return ParseResponse(markdown="", telegram_total=0, vk_total=0, errors=["Нет ссылок для обработки."])
340
 
341
  seen = set()
342
  lines: List[Tuple[str, str, object, object]] = []
@@ -363,10 +417,11 @@ def parse_links(payload: ParseRequest):
363
  else:
364
  lines.append(("unknown", link, None, None))
365
 
366
- markdown, tg_total, vk_total, errors = build_markdown(lines)
367
  return ParseResponse(
368
- markdown=markdown,
 
369
  telegram_total=tg_total,
370
  vk_total=vk_total,
371
  errors=errors,
372
- )
 
2
 
3
  import os
4
  import re
5
+ import html as html_lib
6
  from typing import List, Tuple, Union
7
 
8
  import requests
 
33
 
34
 
35
  class ParseResponse(BaseModel):
36
+ html: str
37
+ text: str
38
  telegram_total: int
39
  vk_total: int
40
  errors: List[str]
 
44
 
45
  def human_format_views(num: int) -> str:
46
  if num >= 1_000_000:
47
+ value = num / 1_000_000
48
+ suffix = "M"
49
  else:
50
+ value = num / 1000
51
+ suffix = "K"
52
+
53
+ if value.is_integer():
54
+ formatted = f"{int(value)}{suffix}"
55
+ else:
56
+ formatted = f"{value:.1f}{suffix}"
57
+
58
  return formatted.replace(".", ",")
59
 
60
 
 
170
  return title, views
171
 
172
  except Exception as exc:
173
+ return f"Ошибка (TG) при обработке {canonical_link}: {exc}", 0
174
 
175
 
176
  def process_vk_link(owner_id: int, post_id: str, canonical_link: str) -> Tuple[str, int]:
 
238
  return [line.strip() for line in raw if line.strip()]
239
 
240
 
241
+ def _escape(text: str) -> str:
242
+ return html_lib.escape(text, quote=True)
243
+
244
+
245
+ def build_output(lines: List[Tuple[str, str, object, object]]) -> Tuple[str, str, int, int, List[str]]:
246
  errors: List[str] = []
247
 
248
  tg_groups = {}
 
295
  reverse=True,
296
  )
297
 
298
+ html_lines: List[str] = []
299
+ text_lines: List[str] = []
300
 
301
+ # --- Telegram ---
302
+ html_lines.append("<h2>Telegram</h2>")
303
+ html_lines.append(f"<b>Суммарный охват постов — {human_format_views(tg_total_views)} просмотров</b>")
304
+ text_lines.append("Telegram")
305
+ text_lines.append(f"Суммарный охват постов — {human_format_views(tg_total_views)} просмотров")
306
  if tg_sorted:
307
+ html_lines.append("<ol>")
308
  for idx, (_, data) in enumerate(tg_sorted, start=1):
309
  title = data["title"] or "Telegram"
310
  items = data["items"]
311
  first_link, _first_views = items[0]
312
+
313
+ title_html = _escape(title)
314
+ first_link_html = _escape(first_link)
315
+ line_html = f'<li><a href="{first_link_html}">{title_html}</a>'
316
  if len(items) > 1:
317
  for link2, _v in items[1:]:
318
+ line_html += f' + <a href="{_escape(link2)}">ещё</a>'
319
  views_str = " + ".join(human_format_views(v) for _, v in items)
320
+ line_html += f" — {views_str}</li>"
321
+ html_lines.append(line_html)
 
 
 
322
 
323
+ line_text = f"{idx}. {title} ({first_link})"
324
+ if len(items) > 1:
325
+ extra_links = ", ".join(link2 for link2, _v in items[1:])
326
+ line_text += f" + ещё: {extra_links}"
327
+ line_text += f" — {views_str}"
328
+ text_lines.append(line_text)
329
+ html_lines.append("</ol>")
330
+ else:
331
+ html_lines.append("<i>Нет ссылок на Telegram</i>")
332
+ text_lines.append("Нет ссылок на Telegram")
333
+ html_lines.append("<br/>")
334
+ text_lines.append("")
335
+
336
+ # --- VK ---
337
+ html_lines.append("<h2>ВКонтакте</h2>")
338
+ html_lines.append(f"<b>Суммарный охват постов — {human_format_views(vk_total_views)} просмотров</b>")
339
+ text_lines.append("ВКонтакте")
340
+ text_lines.append(f"Суммарный охват постов — {human_format_views(vk_total_views)} просмотров")
341
  if vk_sorted:
342
+ html_lines.append("<ol>")
343
  for idx, (_, data) in enumerate(vk_sorted, start=1):
344
  title = data["title"] or "VK пост"
345
  items = data["items"]
346
  first_link, _first_views = items[0]
347
+
348
+ title_html = _escape(title)
349
+ first_link_html = _escape(first_link)
350
+ line_html = f'<li><a href="{first_link_html}">{title_html}</a>'
351
  if len(items) > 1:
352
  for link2, _v in items[1:]:
353
+ line_html += f' + <a href="{_escape(link2)}">ещё</a>'
354
  views_str = " + ".join(human_format_views(v) for _, v in items)
355
+ line_html += f" — {views_str}</li>"
356
+ html_lines.append(line_html)
357
+
358
+ line_text = f"{idx}. {title} ({first_link})"
359
+ if len(items) > 1:
360
+ extra_links = ", ".join(link2 for link2, _v in items[1:])
361
+ line_text += f" + ещё: {extra_links}"
362
+ line_text += f" — {views_str}"
363
+ text_lines.append(line_text)
364
+ html_lines.append("</ol>")
365
  else:
366
+ html_lines.append("<i>Нет ссылок на ВКонтакте</i>")
367
+ text_lines.append("Нет ссылок на ВКонтакте")
368
+ html_lines.append("<br/>")
369
+ text_lines.append("")
370
 
371
  if errors:
372
+ html_lines.append("<h2>Ошибки</h2>")
373
+ html_lines.append("<ul>")
374
+ for err in errors:
375
+ html_lines.append(f"<li>{_escape(err)}</li>")
376
+ text_lines.append(f"- {err}")
377
+ html_lines.append("</ul>")
378
+ html_lines.append("<br/>")
379
+ text_lines.append("")
380
 
381
+ return "\n".join(html_lines), "\n".join(text_lines), tg_total_views, vk_total_views, errors
382
 
383
 
384
  @app.get("/health")
 
390
  def parse_links(payload: ParseRequest):
391
  raw_lines = normalize_links(payload.links)
392
  if not raw_lines:
393
+ return ParseResponse(html="", text="", telegram_total=0, vk_total=0, errors=["Нет ссылок для обработки."])
394
 
395
  seen = set()
396
  lines: List[Tuple[str, str, object, object]] = []
 
417
  else:
418
  lines.append(("unknown", link, None, None))
419
 
420
+ html, text, tg_total, vk_total, errors = build_output(lines)
421
  return ParseResponse(
422
+ html=html,
423
+ text=text,
424
  telegram_total=tg_total,
425
  vk_total=vk_total,
426
  errors=errors,
427
+ )