AI Update: تغییرات جایگزینی آیدی خام با نام را اعمال کن
This commit is contained in:
+44
-11
@@ -634,7 +634,7 @@ class AdminBotService:
|
|||||||
])
|
])
|
||||||
return buttons
|
return buttons
|
||||||
|
|
||||||
def _format_raw_post_caption(self, post: Post) -> str:
|
async def _format_raw_post_caption(self, post: Post) -> str:
|
||||||
published_lines = ""
|
published_lines = ""
|
||||||
if post.published_to:
|
if post.published_to:
|
||||||
published_lines = "📤 <b>وضعیت ارسال به کانالهای مقصد:</b>\n"
|
published_lines = "📤 <b>وضعیت ارسال به کانالهای مقصد:</b>\n"
|
||||||
@@ -654,8 +654,27 @@ class AdminBotService:
|
|||||||
|
|
||||||
tag_line = f"🏷 <b>موضوع:</b> #{post.subject}\n\n" if getattr(post, "subject", None) else ""
|
tag_line = f"🏷 <b>موضوع:</b> #{post.subject}\n\n" if getattr(post, "subject", None) else ""
|
||||||
|
|
||||||
|
if post.source_channel_id <= -900000000:
|
||||||
|
site_id = abs(post.source_channel_id + 900000000)
|
||||||
|
site = await self.repo.get_source_website_by_id(site_id)
|
||||||
|
if site and site.name:
|
||||||
|
source_label = f"🌐 وبسایت <b>{site.name}</b>"
|
||||||
|
elif site and site.url:
|
||||||
|
source_label = f"🌐 وبسایت <b>{site.url}</b>"
|
||||||
|
else:
|
||||||
|
source_label = f"🌐 وبسایت <code>#{site_id}</code>"
|
||||||
|
else:
|
||||||
|
src = await self.repo.get_source_by_channel_id(post.source_channel_id)
|
||||||
|
if src and src.title:
|
||||||
|
user_part = f" (@{src.username})" if src.username else ""
|
||||||
|
source_label = f"📢 کانال <b>{src.title}</b>{user_part}"
|
||||||
|
elif src and src.username:
|
||||||
|
source_label = f"📢 کانال @<b>{src.username}</b>"
|
||||||
|
else:
|
||||||
|
source_label = f"کانال <code>{post.source_channel_id}</code>"
|
||||||
|
|
||||||
caption = (
|
caption = (
|
||||||
f"📥 <b>پست جدید از مبدا (<code>{post.source_channel_id}</code>):</b>\n\n"
|
f"📥 <b>پست جدید از {source_label}:</b>\n\n"
|
||||||
f"{rejection_line}"
|
f"{rejection_line}"
|
||||||
f"{published_lines}"
|
f"{published_lines}"
|
||||||
f"{tag_line}"
|
f"{tag_line}"
|
||||||
@@ -693,7 +712,7 @@ class AdminBotService:
|
|||||||
|
|
||||||
targets = await self.repo.get_active_targets()
|
targets = await self.repo.get_active_targets()
|
||||||
keyboard = self._build_raw_post_keyboard(post, targets)
|
keyboard = self._build_raw_post_keyboard(post, targets)
|
||||||
caption = self._format_raw_post_caption(post)
|
caption = await self._format_raw_post_caption(post)
|
||||||
|
|
||||||
if refresh_only:
|
if refresh_only:
|
||||||
# Update the card that already exists instead of posting a second one.
|
# Update the card that already exists instead of posting a second one.
|
||||||
@@ -1236,10 +1255,12 @@ class AdminBotService:
|
|||||||
st_icon = "🛑 متوقف (Paused)" if is_paused else "🟢 فعال و در حال کار (Running)"
|
st_icon = "🛑 متوقف (Paused)" if is_paused else "🟢 فعال و در حال کار (Running)"
|
||||||
pause_btn_text = "▶️ راهاندازی سیستم" if is_paused else "🛑 توقف سیستم"
|
pause_btn_text = "▶️ راهاندازی سیستم" if is_paused else "🛑 توقف سیستم"
|
||||||
pause_cb = "sys_resume" if is_paused else "sys_pause"
|
pause_cb = "sys_resume" if is_paused else "sys_pause"
|
||||||
|
def_adm = await self.repo.get_default_admin_channel()
|
||||||
|
adm_label = f"<b>{def_adm.title}</b> (<code>{def_adm.channel_id}</code>)" if (def_adm and def_adm.title) else (f"<code>{self.review_channel_id}</code>" if self.review_channel_id else "تعریفنشده")
|
||||||
text = (
|
text = (
|
||||||
f"⚙️ <b>بخش کنترل و مدیریت سیستم (System Hub):</b>\n\n"
|
f"⚙️ <b>بخش کنترل و مدیریت سیستم (System Hub):</b>\n\n"
|
||||||
f"• ⚡️ <b>وضعیت کنونی سیستم:</b> <b>{st_icon}</b>\n"
|
f"• ⚡️ <b>وضعیت کنونی سیستم:</b> <b>{st_icon}</b>\n"
|
||||||
f"• 📋 <b>کانال نظارت ادمین:</b> <code>{self.review_channel_id}</code>\n\n"
|
f"• 📋 <b>کانال نظارت ادمین:</b> {adm_label}\n\n"
|
||||||
f"<i>عملیات مورد نظر را انتخاب کنید:</i>"
|
f"<i>عملیات مورد نظر را انتخاب کنید:</i>"
|
||||||
)
|
)
|
||||||
buttons = [
|
buttons = [
|
||||||
@@ -1274,7 +1295,9 @@ class AdminBotService:
|
|||||||
|
|
||||||
is_def = (source.admin_channel_id is None)
|
is_def = (source.admin_channel_id is None)
|
||||||
def_mark = "✅ " if is_def else ""
|
def_mark = "✅ " if is_def else ""
|
||||||
buttons.append([Button.inline(f"{def_mark}⚙️ پیشفرض سیستم ({self.review_channel_id})", data=f"src_set_adm:{source.id}:none")])
|
def_adm = await self.repo.get_default_admin_channel()
|
||||||
|
def_name = f" ({def_adm.title})" if (def_adm and def_adm.title) else (f" ({self.review_channel_id})" if self.review_channel_id else "")
|
||||||
|
buttons.append([Button.inline(f"{def_mark}⚙️ پیشفرض سیستم{def_name}", data=f"src_set_adm:{source.id}:none")])
|
||||||
buttons.append([Button.inline("➕ افزودن کانال ادمین جدید", data=f"src_add_adm:{source.id}")])
|
buttons.append([Button.inline("➕ افزودن کانال ادمین جدید", data=f"src_add_adm:{source.id}")])
|
||||||
buttons.append([Button.inline("🔙 بازگشت به تنظیمات کانال مبدا", data=f"src_view:{source.id}")])
|
buttons.append([Button.inline("🔙 بازگشت به تنظیمات کانال مبدا", data=f"src_view:{source.id}")])
|
||||||
return text, buttons
|
return text, buttons
|
||||||
@@ -1299,7 +1322,9 @@ class AdminBotService:
|
|||||||
|
|
||||||
is_def = (site.admin_channel_id is None)
|
is_def = (site.admin_channel_id is None)
|
||||||
def_mark = "✅ " if is_def else ""
|
def_mark = "✅ " if is_def else ""
|
||||||
buttons.append([Button.inline(f"{def_mark}⚙️ پیشفرض سیستم ({self.review_channel_id})", data=f"web_set_adm:{site.id}:none")])
|
def_adm = await self.repo.get_default_admin_channel()
|
||||||
|
def_name = f" ({def_adm.title})" if (def_adm and def_adm.title) else (f" ({self.review_channel_id})" if self.review_channel_id else "")
|
||||||
|
buttons.append([Button.inline(f"{def_mark}⚙️ پیشفرض سیستم{def_name}", data=f"web_set_adm:{site.id}:none")])
|
||||||
buttons.append([Button.inline("➕ افزودن کانال ادمین جدید", data=f"web_add_adm:{site.id}")])
|
buttons.append([Button.inline("➕ افزودن کانال ادمین جدید", data=f"web_add_adm:{site.id}")])
|
||||||
buttons.append([Button.inline("🔙 بازگشت به تنظیمات وبسایت", data=f"web_view:{site.id}")])
|
buttons.append([Button.inline("🔙 بازگشت به تنظیمات وبسایت", data=f"web_view:{site.id}")])
|
||||||
return text, buttons
|
return text, buttons
|
||||||
@@ -1432,7 +1457,9 @@ class AdminBotService:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Error deleting chunk from channel {ch_id}: {e}")
|
logger.warning(f"Error deleting chunk from channel {ch_id}: {e}")
|
||||||
|
|
||||||
summary = f"🗑 <b>پیامهای کانال نظارت <code>{ch_id}</code> پاکسازی شدند:</b>\n\n• 🗑 پیامهای حذفشده از تلگرام: <b>{deleted_tg_count}</b>\n• 🗂 پستهای بایگانیشده در سیستم: <b>{cleared_db_count}</b>"
|
adm = await self.repo.get_admin_channel_by_telegram_id(ch_id)
|
||||||
|
ch_name = f"«{adm.title}»" if adm and adm.title else f"<code>{ch_id}</code>"
|
||||||
|
summary = f"🗑 <b>پیامهای کانال نظارت {ch_name} پاکسازی شدند:</b>\n\n• 🗑 پیامهای حذفشده از تلگرام: <b>{deleted_tg_count}</b>\n• 🗂 پستهای بایگانیشده در سیستم: <b>{cleared_db_count}</b>"
|
||||||
|
|
||||||
return deleted_tg_count, cleared_db_count, summary
|
return deleted_tg_count, cleared_db_count, summary
|
||||||
|
|
||||||
@@ -1693,10 +1720,13 @@ class AdminBotService:
|
|||||||
me = await self.collector.client.get_me()
|
me = await self.collector.client.get_me()
|
||||||
userbot_status = f"🟢 آنلاین ({me.first_name})"
|
userbot_status = f"🟢 آنلاین ({me.first_name})"
|
||||||
|
|
||||||
|
def_adm = await self.repo.get_default_admin_channel()
|
||||||
|
adm_label = f"<b>{def_adm.title}</b> (<code>{def_adm.channel_id}</code>)" if (def_adm and def_adm.title) else (f"<code>{self.review_channel_id}</code>" if self.review_channel_id else "تعریفنشده")
|
||||||
|
|
||||||
welcome_text = (
|
welcome_text = (
|
||||||
"👋 <b>به پنل مدیریت سیستم هوشمند کپیکار خوش آمدید!</b>\n\n"
|
"👋 <b>به پنل مدیریت سیستم هوشمند کپیکار خوش آمدید!</b>\n\n"
|
||||||
f"• 🤖 <b>وضعیت ربات جمعآوریکننده:</b> {userbot_status}\n"
|
f"• 🤖 <b>وضعیت ربات جمعآوریکننده:</b> {userbot_status}\n"
|
||||||
f"• 📋 <b>شناسه کانال ادمینها:</b> <code>{self.review_channel_id}</code>\n\n"
|
f"• 📋 <b>کانال نظارت ادمین:</b> {adm_label}\n\n"
|
||||||
"برای مدیریت کانالها از دکمههای زیر استفاده کنید:"
|
"برای مدیریت کانالها از دکمههای زیر استفاده کنید:"
|
||||||
)
|
)
|
||||||
menu = await self.get_menu()
|
menu = await self.get_menu()
|
||||||
@@ -3250,10 +3280,13 @@ class AdminBotService:
|
|||||||
me = await self.collector.client.get_me()
|
me = await self.collector.client.get_me()
|
||||||
userbot_status = f"🟢 آنلاین ({me.first_name})"
|
userbot_status = f"🟢 آنلاین ({me.first_name})"
|
||||||
|
|
||||||
|
def_adm = await self.repo.get_default_admin_channel()
|
||||||
|
adm_label = f"<b>{def_adm.title}</b> (<code>{def_adm.channel_id}</code>)" if (def_adm and def_adm.title) else (f"<code>{self.review_channel_id}</code>" if self.review_channel_id else "تعریفنشده")
|
||||||
|
|
||||||
welcome_text = (
|
welcome_text = (
|
||||||
"👋 <b>منوی اصلی سیستم هوشمند کپیکار:</b>\n\n"
|
"👋 <b>منوی اصلی سیستم هوشمند کپیکار:</b>\n\n"
|
||||||
f"• 🤖 <b>وضعیت ربات جمعآوریکننده:</b> {userbot_status}\n"
|
f"• 🤖 <b>وضعیت ربات جمعآوریکننده:</b> {userbot_status}\n"
|
||||||
f"• 📋 <b>شناسه کانال ادمینها:</b> <code>{self.review_channel_id}</code>\n\n"
|
f"• 📋 <b>کانال نظارت ادمین:</b> {adm_label}\n\n"
|
||||||
"برای مدیریت بخشهای مختلف از دکمههای زیر استفاده کنید:"
|
"برای مدیریت بخشهای مختلف از دکمههای زیر استفاده کنید:"
|
||||||
)
|
)
|
||||||
buttons = get_persian_inline_hub_menu()
|
buttons = get_persian_inline_hub_menu()
|
||||||
@@ -3667,7 +3700,7 @@ class AdminBotService:
|
|||||||
|
|
||||||
updated_post = await self.repo.get_post_by_id(post_id)
|
updated_post = await self.repo.get_post_by_id(post_id)
|
||||||
targets = await self.repo.get_active_targets()
|
targets = await self.repo.get_active_targets()
|
||||||
new_caption = self._format_raw_post_caption(updated_post)
|
new_caption = await self._format_raw_post_caption(updated_post)
|
||||||
new_buttons = self._build_raw_post_keyboard(updated_post, targets)
|
new_buttons = self._build_raw_post_keyboard(updated_post, targets)
|
||||||
|
|
||||||
await event.edit(
|
await event.edit(
|
||||||
@@ -3689,7 +3722,7 @@ class AdminBotService:
|
|||||||
return
|
return
|
||||||
|
|
||||||
targets = await self.repo.get_active_targets()
|
targets = await self.repo.get_active_targets()
|
||||||
caption = self._format_raw_post_caption(post)
|
caption = await self._format_raw_post_caption(post)
|
||||||
buttons = self._build_raw_post_keyboard(post, targets)
|
buttons = self._build_raw_post_keyboard(post, targets)
|
||||||
|
|
||||||
await event.edit(caption, parse_mode="html", buttons=buttons)
|
await event.edit(caption, parse_mode="html", buttons=buttons)
|
||||||
|
|||||||
@@ -35,13 +35,14 @@ class ScrapeResult:
|
|||||||
duplicates: int = 0
|
duplicates: int = 0
|
||||||
error: Optional[str] = None
|
error: Optional[str] = None
|
||||||
|
|
||||||
def summary_fa(self, channel_id: int) -> str:
|
def summary_fa(self, channel_id: int, channel_title: Optional[str] = None) -> str:
|
||||||
|
name_label = f"<b>{channel_title}</b>" if channel_title else f"<code>{channel_id}</code>"
|
||||||
if self.error:
|
if self.error:
|
||||||
return f"❌ خطا در دریافت پستهای کانال <code>{channel_id}</code>: {self.error}"
|
return f"❌ خطا در دریافت پستهای کانال {name_label}: {self.error}"
|
||||||
header = (
|
header = (
|
||||||
f"✅ <b>{self.collected}</b> پست جدید از <code>{channel_id}</code> دریافت و به کانال ادمین ارسال شد."
|
f"✅ <b>{self.collected}</b> پست جدید از کانال {name_label} دریافت و به کانال ادمین ارسال شد."
|
||||||
if self.collected
|
if self.collected
|
||||||
else f"ℹ️ هیچ پست <b>جدیدی</b> در <code>{channel_id}</code> پیدا نشد."
|
else f"ℹ️ هیچ پست <b>جدیدی</b> در کانال {name_label} پیدا نشد."
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
f"{header}\n\n"
|
f"{header}\n\n"
|
||||||
@@ -388,13 +389,13 @@ class CollectorService:
|
|||||||
result.already_stored += 1
|
result.already_stored += 1
|
||||||
|
|
||||||
if progress_callback:
|
if progress_callback:
|
||||||
await progress_callback(result.summary_fa(channel_id))
|
await progress_callback(result.summary_fa(channel_id, source_title))
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await log_exception("collector.scrape_history", e, {"channel_id": channel_id, "limit": limit})
|
await log_exception("collector.scrape_history", e, {"channel_id": channel_id, "limit": limit})
|
||||||
result.error = str(e)
|
result.error = str(e)
|
||||||
if progress_callback:
|
if progress_callback:
|
||||||
await progress_callback(result.summary_fa(channel_id))
|
await progress_callback(result.summary_fa(channel_id, source_title))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def stop(self):
|
async def stop(self):
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import pytest
|
||||||
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
from services.collector import ScrapeResult
|
||||||
|
from services.admin_bot import AdminBotService
|
||||||
|
from db.models import Post, SourceChannel, SourceWebsite
|
||||||
|
|
||||||
|
def test_collector_summary_fa_with_title():
|
||||||
|
res = ScrapeResult(scanned=10, collected=5, already_stored=3, duplicates=2)
|
||||||
|
summary = res.summary_fa(channel_id=-100123456, channel_title="کانال خبری فناوری")
|
||||||
|
assert "کانال خبری فناوری" in summary
|
||||||
|
assert "<code>-100123456</code>" not in summary
|
||||||
|
|
||||||
|
def test_collector_summary_fa_fallback_to_id():
|
||||||
|
res = ScrapeResult(scanned=10, collected=0, already_stored=10, duplicates=0)
|
||||||
|
summary = res.summary_fa(channel_id=-100123456, channel_title=None)
|
||||||
|
assert "-100123456" in summary
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_admin_bot_format_raw_post_caption_telegram_channel():
|
||||||
|
repo = MagicMock()
|
||||||
|
repo.get_source_by_channel_id = AsyncMock(return_value=SourceChannel(
|
||||||
|
id=1, channel_id=-100123456, username="tech_news", title="اخبار روز تکنولوژی"
|
||||||
|
))
|
||||||
|
bot = AdminBotService(repo=repo, ai_processor=MagicMock(), queue=MagicMock())
|
||||||
|
|
||||||
|
post = Post(id=1, source_channel_id=-100123456, source_message_id=10, raw_text="متن تست پست")
|
||||||
|
caption = await bot._format_raw_post_caption(post)
|
||||||
|
|
||||||
|
assert "اخبار روز تکنولوژی" in caption
|
||||||
|
assert "@tech_news" in caption
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_admin_bot_format_raw_post_caption_website():
|
||||||
|
repo = MagicMock()
|
||||||
|
pseudo_id = -900000005
|
||||||
|
repo.get_source_website_by_id = AsyncMock(return_value=SourceWebsite(
|
||||||
|
id=5, name="دیجیاتو", url="https://digiato.com"
|
||||||
|
))
|
||||||
|
bot = AdminBotService(repo=repo, ai_processor=MagicMock(), queue=MagicMock())
|
||||||
|
|
||||||
|
post = Post(id=2, source_channel_id=pseudo_id, source_message_id=1, raw_text="خبر جدید وبسایت")
|
||||||
|
caption = await bot._format_raw_post_caption(post)
|
||||||
|
|
||||||
|
assert "دیجیاتو" in caption
|
||||||
|
assert "وبسایت" in caption
|
||||||
Reference in New Issue
Block a user