Spaces:
Running
Running
Upload auto_scheduler.py
Browse files- auto_scheduler.py +8 -12
auto_scheduler.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
-
"""VNEWS Auto Scheduler - tự động đăng
|
| 2 |
Vào các khung giờ: 7:00, 13:00, 19:00 (giờ Việt Nam)
|
| 3 |
Mỗi bài: Rewrite AI từ nguồn báo + short video tự động
|
| 4 |
-
FIX
|
| 5 |
"""
|
| 6 |
import os, re, json, time, threading, asyncio, logging, random, hashlib, html as html_lib
|
| 7 |
from datetime import datetime, timezone, timedelta, date
|
|
@@ -44,10 +44,9 @@ _STOP = set('và của các những một được trong với cho tại sau tr
|
|
| 44 |
|
| 45 |
def _clean(s):
|
| 46 |
s = html_lib.unescape(s or "")
|
| 47 |
-
# FIX: Remove malformed HTML artifacts (truncated tags without closing >)
|
| 48 |
s = s.replace('<a href=" src="', '').replace("<a href=' src='", '')
|
| 49 |
s = s.replace('<a href=" src=', '').replace("<a href=' src=", '')
|
| 50 |
-
s = re.sub(r'<[^>]+>', '', s)
|
| 51 |
return re.sub(r"\s+", " ", s).strip()
|
| 52 |
|
| 53 |
def _get_hot_topics():
|
|
@@ -92,7 +91,7 @@ def _get_hot_topics():
|
|
| 92 |
seen.add(key)
|
| 93 |
topics.append({'label': '#' + re.sub(r'\s+', '', kw.title()), 'topic': kw, 'count': count})
|
| 94 |
if len(topics) >= 20: break
|
| 95 |
-
for kw in ['World Cup 2026', 'Kinh tế Việt Nam', 'Bóng đá châu Âu', 'Công nghệ AI', 'Giá vàng', 'Thời tiết']:
|
| 96 |
if len(topics) >= 24: break
|
| 97 |
if not any(kw.lower() in s for s in seen):
|
| 98 |
topics.append({'label': '#' + re.sub(r'\s+', '', kw.title()), 'topic': kw, 'count': 0})
|
|
@@ -163,7 +162,6 @@ async def _create_ai_post(topic):
|
|
| 163 |
LOG.warning(f"No articles for topic: {topic}. Fallback.")
|
| 164 |
return await _create_fallback_post(topic, ai_ext, ai_patch)
|
| 165 |
posts = []
|
| 166 |
-
# Get schedule time label for text intro (7h sáng, 13h trưa, 19h tối)
|
| 167 |
now = datetime.now(VN_TZ)
|
| 168 |
hour = now.hour
|
| 169 |
time_label = "7h sáng" if hour == 7 else ("13h trưa" if hour == 13 else "19h tối")
|
|
@@ -176,13 +174,11 @@ async def _create_ai_post(topic):
|
|
| 176 |
text = await ai_ext.qwen_generate(prompt, image_url=art.get('image'), max_tokens=1500)
|
| 177 |
text = ai_patch._postprocess_ai_text(text, max_units=20)
|
| 178 |
src = [art.get('source', {'title': art.get('title', topic), 'url': art.get('url', ''), 'via': art.get('via', '')})]
|
| 179 |
-
# Prepend time label intro to text (giữ nguyên title là tiêu đề gốc của bài báo)
|
| 180 |
if text and not text.startswith(text_intro):
|
| 181 |
text = f"{text_intro}\n\n{text}"
|
| 182 |
if 'Nguồn tham khảo:' not in (text or ''):
|
| 183 |
text = (text or '') + "\n\n" + ai_patch._source_line(src)
|
| 184 |
img = art.get('image') or ai_ext.pollination_image_url(art.get('title', topic))
|
| 185 |
-
# Dùng art.get('title') GIỮ NGUYÊN tiêu đề gốc từ bài báo
|
| 186 |
post = ai_ext.make_post(art.get('title', topic), text, img, art.get('url', ''), 'auto_scheduled', sources=src)
|
| 187 |
try:
|
| 188 |
page_data = ai_patch._scrape_article_images(art.get('url', ''))
|
|
@@ -210,7 +206,6 @@ async def _create_ai_post(topic):
|
|
| 210 |
async def _create_fallback_post(topic, ai_ext, ai_patch):
|
| 211 |
LOG.info(f"Fallback: {topic}")
|
| 212 |
try:
|
| 213 |
-
# Still add time label to fallback posts
|
| 214 |
now = datetime.now(VN_TZ)
|
| 215 |
hour = now.hour
|
| 216 |
time_label = "7h sáng" if hour == 7 else ("13h trưa" if hour == 13 else "19h tối")
|
|
@@ -318,9 +313,10 @@ def _run_scheduled_posting():
|
|
| 318 |
label = t.get('label', '')
|
| 319 |
if label and label not in seen_labels:
|
| 320 |
seen_labels.add(label); selected.append(t['topic'])
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
|
|
|
| 324 |
LOG.info(f"Topics: {selected}")
|
| 325 |
async def _do_all():
|
| 326 |
results = []
|
|
|
|
| 1 |
+
"""VNEWS Auto Scheduler - tự động đăng 5 bài rewrite AI + shorts từ 5 chủ đề HOT
|
| 2 |
Vào các khung giờ: 7:00, 13:00, 19:00 (giờ Việt Nam)
|
| 3 |
Mỗi bài: Rewrite AI từ nguồn báo + short video tự động
|
| 4 |
+
FIX v8: Từ 3 lên 5 topics, thêm AI Thế Giới
|
| 5 |
"""
|
| 6 |
import os, re, json, time, threading, asyncio, logging, random, hashlib, html as html_lib
|
| 7 |
from datetime import datetime, timezone, timedelta, date
|
|
|
|
| 44 |
|
| 45 |
def _clean(s):
|
| 46 |
s = html_lib.unescape(s or "")
|
|
|
|
| 47 |
s = s.replace('<a href=" src="', '').replace("<a href=' src='", '')
|
| 48 |
s = s.replace('<a href=" src=', '').replace("<a href=' src=", '')
|
| 49 |
+
s = re.sub(r'<[^>]+>', '', s)
|
| 50 |
return re.sub(r"\s+", " ", s).strip()
|
| 51 |
|
| 52 |
def _get_hot_topics():
|
|
|
|
| 91 |
seen.add(key)
|
| 92 |
topics.append({'label': '#' + re.sub(r'\s+', '', kw.title()), 'topic': kw, 'count': count})
|
| 93 |
if len(topics) >= 20: break
|
| 94 |
+
for kw in ['World Cup 2026', 'Kinh tế Việt Nam', 'Bóng đá châu Âu', 'Công nghệ AI', 'AI Thế Giới', 'Giá vàng', 'Thời tiết']:
|
| 95 |
if len(topics) >= 24: break
|
| 96 |
if not any(kw.lower() in s for s in seen):
|
| 97 |
topics.append({'label': '#' + re.sub(r'\s+', '', kw.title()), 'topic': kw, 'count': 0})
|
|
|
|
| 162 |
LOG.warning(f"No articles for topic: {topic}. Fallback.")
|
| 163 |
return await _create_fallback_post(topic, ai_ext, ai_patch)
|
| 164 |
posts = []
|
|
|
|
| 165 |
now = datetime.now(VN_TZ)
|
| 166 |
hour = now.hour
|
| 167 |
time_label = "7h sáng" if hour == 7 else ("13h trưa" if hour == 13 else "19h tối")
|
|
|
|
| 174 |
text = await ai_ext.qwen_generate(prompt, image_url=art.get('image'), max_tokens=1500)
|
| 175 |
text = ai_patch._postprocess_ai_text(text, max_units=20)
|
| 176 |
src = [art.get('source', {'title': art.get('title', topic), 'url': art.get('url', ''), 'via': art.get('via', '')})]
|
|
|
|
| 177 |
if text and not text.startswith(text_intro):
|
| 178 |
text = f"{text_intro}\n\n{text}"
|
| 179 |
if 'Nguồn tham khảo:' not in (text or ''):
|
| 180 |
text = (text or '') + "\n\n" + ai_patch._source_line(src)
|
| 181 |
img = art.get('image') or ai_ext.pollination_image_url(art.get('title', topic))
|
|
|
|
| 182 |
post = ai_ext.make_post(art.get('title', topic), text, img, art.get('url', ''), 'auto_scheduled', sources=src)
|
| 183 |
try:
|
| 184 |
page_data = ai_patch._scrape_article_images(art.get('url', ''))
|
|
|
|
| 206 |
async def _create_fallback_post(topic, ai_ext, ai_patch):
|
| 207 |
LOG.info(f"Fallback: {topic}")
|
| 208 |
try:
|
|
|
|
| 209 |
now = datetime.now(VN_TZ)
|
| 210 |
hour = now.hour
|
| 211 |
time_label = "7h sáng" if hour == 7 else ("13h trưa" if hour == 13 else "19h tối")
|
|
|
|
| 313 |
label = t.get('label', '')
|
| 314 |
if label and label not in seen_labels:
|
| 315 |
seen_labels.add(label); selected.append(t['topic'])
|
| 316 |
+
# Tăng từ 3 lên 5 topics
|
| 317 |
+
if len(selected) >= 5: break
|
| 318 |
+
if len(selected) < 5:
|
| 319 |
+
selected = ['Thời sự Việt Nam', 'Kinh tế Việt Nam', 'Công nghệ AI', 'Thể thao', 'Thế giới']
|
| 320 |
LOG.info(f"Topics: {selected}")
|
| 321 |
async def _do_all():
|
| 322 |
results = []
|