Spaces:
Running
Running
Fix /api/url_wall and /api/rewrite_share: generate slides properly, remove broken req._body hack, prioritize app_v2_entry routes over ai_patch
Browse files- app_v2_entry.py +33 -16
app_v2_entry.py
CHANGED
|
@@ -332,6 +332,11 @@ def _search_all(topic,limit=36):
|
|
| 332 |
for _path in ['/api/article', '/api/hot_topics', '/api/categories', '/api/storage_status']:
|
| 333 |
app.router.routes=[r for r in app.router.routes if not(getattr(r,'path',None)==_path and 'GET' in getattr(r,'methods',set()))]
|
| 334 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 335 |
_article_cache = {}
|
| 336 |
_article_cache_ttl = 1800
|
| 337 |
|
|
@@ -1405,15 +1410,8 @@ async def api_rewrite_slide(request: Request):
|
|
| 1405 |
return JSONResponse({"post": post, "slides": slides})
|
| 1406 |
|
| 1407 |
|
| 1408 |
-
|
| 1409 |
-
|
| 1410 |
-
"""Rewrite article and post to Tường AI with SLIDES + AI text."""
|
| 1411 |
-
body = await request.json()
|
| 1412 |
-
url = _clean(body.get("url", ""))
|
| 1413 |
-
ctx = _clean(body.get("context", ""))
|
| 1414 |
-
preferred_voice = body.get("voice", "") # Accept custom voice selection
|
| 1415 |
-
if not url and not ctx:
|
| 1416 |
-
return JSONResponse({"error": "Cần URL hoặc nội dung"}, status_code=400)
|
| 1417 |
data = None
|
| 1418 |
if url and url.startswith("http"):
|
| 1419 |
data = _scrape_article_for_rewrite(url)
|
|
@@ -1421,12 +1419,12 @@ async def api_rewrite_share(request: Request):
|
|
| 1421 |
paragraphs = [_clean(p) for p in ctx.split('\n') if len(_clean(p)) > 40]
|
| 1422 |
data = {'title': paragraphs[0][:80] if paragraphs else 'Bài viết', 'paragraphs': paragraphs, 'images': [], 'og_img': ''}
|
| 1423 |
if not data or not data.get('paragraphs'):
|
| 1424 |
-
return JSONResponse({"error": "Không đọc được bài viết"}, status_code=422)
|
| 1425 |
raw_text = '\n'.join(data['paragraphs'])
|
| 1426 |
if len(raw_text) < 50:
|
| 1427 |
raw_text = ctx[:14000]
|
| 1428 |
if len(raw_text) < 50:
|
| 1429 |
-
return JSONResponse({"error": "Bài viết quá ngắn"}, status_code=422)
|
| 1430 |
domain = ''
|
| 1431 |
try:
|
| 1432 |
from urllib.parse import urlparse
|
|
@@ -1450,7 +1448,7 @@ async def api_rewrite_share(request: Request):
|
|
| 1450 |
else:
|
| 1451 |
ai_text = f"Tóm tắt: {data['title']}\n\n{raw_text[:1200]}\n\nNguồn: {domain}"
|
| 1452 |
|
| 1453 |
-
# Build slides from key points
|
| 1454 |
points = _extract_key_points_rw(data['paragraphs'], max_points=12)
|
| 1455 |
images = data.get('images', [])
|
| 1456 |
slides = []
|
|
@@ -1480,10 +1478,25 @@ async def api_rewrite_share(request: Request):
|
|
| 1480 |
"language": lang,
|
| 1481 |
"ts": int(time.time())
|
| 1482 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1483 |
posts = _load_wall_posts()
|
| 1484 |
posts.insert(0, post)
|
| 1485 |
_save_wall_posts(posts)
|
| 1486 |
-
return JSONResponse({"post": post, "slides": slides})
|
| 1487 |
|
| 1488 |
|
| 1489 |
@app.post("/api/url_wall")
|
|
@@ -1493,9 +1506,13 @@ async def api_url_wall(request: Request):
|
|
| 1493 |
url = _clean(body.get("url", ""))
|
| 1494 |
if not url or not url.startswith('http'):
|
| 1495 |
return JSONResponse({"error": "URL không hợp lệ"}, status_code=400)
|
| 1496 |
-
|
| 1497 |
-
|
| 1498 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1499 |
|
| 1500 |
|
| 1501 |
def _bg():
|
|
|
|
| 332 |
for _path in ['/api/article', '/api/hot_topics', '/api/categories', '/api/storage_status']:
|
| 333 |
app.router.routes=[r for r in app.router.routes if not(getattr(r,'path',None)==_path and 'GET' in getattr(r,'methods',set()))]
|
| 334 |
|
| 335 |
+
# Remove ai_patch.py's duplicate routes so app_v2_entry's versions take priority
|
| 336 |
+
# Keep ai_patch.py's /api/ai/short/{post_id} and /api/ai/short-file/{file_id} — they work correctly
|
| 337 |
+
for _p, _m in [('/api/url_wall','POST'), ('/api/rewrite_share','POST'), ('/api/topic_post','POST')]:
|
| 338 |
+
app.router.routes=[r for r in app.router.routes if not(getattr(r,'path',None)==_p and _m in getattr(r,'methods',set()))]
|
| 339 |
+
|
| 340 |
_article_cache = {}
|
| 341 |
_article_cache_ttl = 1800
|
| 342 |
|
|
|
|
| 1410 |
return JSONResponse({"post": post, "slides": slides})
|
| 1411 |
|
| 1412 |
|
| 1413 |
+
async def _do_rewrite(url, ctx="", preferred_voice=""):
|
| 1414 |
+
"""Shared rewrite logic used by both /api/rewrite_share and /api/url_wall."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1415 |
data = None
|
| 1416 |
if url and url.startswith("http"):
|
| 1417 |
data = _scrape_article_for_rewrite(url)
|
|
|
|
| 1419 |
paragraphs = [_clean(p) for p in ctx.split('\n') if len(_clean(p)) > 40]
|
| 1420 |
data = {'title': paragraphs[0][:80] if paragraphs else 'Bài viết', 'paragraphs': paragraphs, 'images': [], 'og_img': ''}
|
| 1421 |
if not data or not data.get('paragraphs'):
|
| 1422 |
+
return None, JSONResponse({"error": "Không đọc được bài viết"}, status_code=422)
|
| 1423 |
raw_text = '\n'.join(data['paragraphs'])
|
| 1424 |
if len(raw_text) < 50:
|
| 1425 |
raw_text = ctx[:14000]
|
| 1426 |
if len(raw_text) < 50:
|
| 1427 |
+
return None, JSONResponse({"error": "Bài viết quá ngắn"}, status_code=422)
|
| 1428 |
domain = ''
|
| 1429 |
try:
|
| 1430 |
from urllib.parse import urlparse
|
|
|
|
| 1448 |
else:
|
| 1449 |
ai_text = f"Tóm tắt: {data['title']}\n\n{raw_text[:1200]}\n\nNguồn: {domain}"
|
| 1450 |
|
| 1451 |
+
# Build slides from key points
|
| 1452 |
points = _extract_key_points_rw(data['paragraphs'], max_points=12)
|
| 1453 |
images = data.get('images', [])
|
| 1454 |
slides = []
|
|
|
|
| 1478 |
"language": lang,
|
| 1479 |
"ts": int(time.time())
|
| 1480 |
}
|
| 1481 |
+
return post, None
|
| 1482 |
+
|
| 1483 |
+
|
| 1484 |
+
@app.post("/api/rewrite_share")
|
| 1485 |
+
async def api_rewrite_share(request: Request):
|
| 1486 |
+
"""Rewrite article and post to Tường AI with SLIDES + AI text."""
|
| 1487 |
+
body = await request.json()
|
| 1488 |
+
url = _clean(body.get("url", ""))
|
| 1489 |
+
ctx = _clean(body.get("context", ""))
|
| 1490 |
+
preferred_voice = body.get("voice", "")
|
| 1491 |
+
if not url and not ctx:
|
| 1492 |
+
return JSONResponse({"error": "Cần URL hoặc nội dung"}, status_code=400)
|
| 1493 |
+
post, err = await _do_rewrite(url, ctx, preferred_voice)
|
| 1494 |
+
if err:
|
| 1495 |
+
return err
|
| 1496 |
posts = _load_wall_posts()
|
| 1497 |
posts.insert(0, post)
|
| 1498 |
_save_wall_posts(posts)
|
| 1499 |
+
return JSONResponse({"post": post, "slides": post.get("slides", [])})
|
| 1500 |
|
| 1501 |
|
| 1502 |
@app.post("/api/url_wall")
|
|
|
|
| 1506 |
url = _clean(body.get("url", ""))
|
| 1507 |
if not url or not url.startswith('http'):
|
| 1508 |
return JSONResponse({"error": "URL không hợp lệ"}, status_code=400)
|
| 1509 |
+
post, err = await _do_rewrite(url, "", "")
|
| 1510 |
+
if err:
|
| 1511 |
+
return err
|
| 1512 |
+
posts = _load_wall_posts()
|
| 1513 |
+
posts.insert(0, post)
|
| 1514 |
+
_save_wall_posts(posts)
|
| 1515 |
+
return JSONResponse({"post": post, "slides": post.get("slides", [])})
|
| 1516 |
|
| 1517 |
|
| 1518 |
def _bg():
|