Commit 4c7352b

benny-dou <60535774+benny-dou@users.noreply.github.com>
2025-09-01 16:22:05
feat(social): add options to customize caption components
1 parent 4aa4a73
src/preview/douyin.py
@@ -34,6 +34,11 @@ async def preview_douyin(
     platform: str = "douyin",
     douyin_provider: str = PROVIDER.DOUYIN,
     douyin_comments_provider: str = PROVIDER.DOUYIN_COMMENTS,
+    *,
+    show_author: bool = True,
+    show_pubdate: bool = True,
+    show_statistics: bool = True,
+    show_description: bool = True,
     **kwargs,
 ):
     """Preview douyin or tiktok link in the message.
@@ -75,15 +80,15 @@ async def preview_douyin(
         await modify_progress(text="❌抖音解析失败", force_update=True, **kwargs)
         return
     texts = ""
-    if author := data.get("author"):
-        texts += f"\n🎶**[{author}]({url})**"
-    if ts := data.get("create_time"):
-        dt = datetime.fromtimestamp(ts).astimezone(ZoneInfo(TZ))
+    if true(show_author) and data.get("author"):
+        texts += f"\n🎶**[{data['author']}]({url})**"
+    if true(show_pubdate) and data.get("create_time"):
+        dt = datetime.fromtimestamp(data["create_time"]).astimezone(ZoneInfo(TZ))
         texts += f"\n🕒{dt:%Y-%m-%d %H:%M:%S}"
-    if statistics := data.get("statistics"):
-        texts += f"\n{statistics}"
-    if decs := data.get("desc"):
-        texts += f"\n{decs}"
+    if true(show_statistics) and data.get("statistics"):
+        texts += f"\n{data['statistics']}"
+    if true(show_description) and data.get("desc"):
+        texts += f"\n{data['desc']}"
 
     comments = []
     if comments_list := await get_comments(data["aweme_id"], platform, douyin_comments_provider):
src/preview/instagram.py
@@ -31,6 +31,10 @@ async def preview_instagram(
     *,
     instagram_provider: str = PROVIDER.INSTAGRAM,
     instagram_comments: bool = True,
+    show_author: bool = True,
+    show_pubdate: bool = True,
+    show_statistics: bool = True,
+    show_description: bool = True,
     **kwargs,
 ):
     """Preview instagram link in the message.
@@ -86,17 +90,17 @@ async def preview_instagram(
         statistics += f"💬{readable_count(comment)}"
 
     texts = ""
-    if fullname := glom(data, "owner.full_name", default=""):
+    if true(show_author) and (fullname := glom(data, "owner.full_name", default="")):
         texts += f"🏞**[{fullname}]({url})**\n"
 
     if metadata_node := glom(data, "edge_media_to_caption.edges.0", default=None):
-        if ts := glom(metadata_node, "node.created_at", default=0):
+        if true(show_pubdate) and (ts := glom(metadata_node, "node.created_at", default=0)):
             dt = datetime.fromtimestamp(float(ts)).astimezone(ZoneInfo(TZ))
             create_time = f"{dt:%Y-%m-%d %H:%M:%S}"
             texts += f"🕒{create_time}\n"
-        if statistics:
+        if true(show_statistics) and statistics:
             texts += f"{statistics}\n"
-        if description := glom(metadata_node, "node.text", default=""):
+        if true(show_description) and (description := glom(metadata_node, "node.text", default="")):
             texts += f"{description}\n"
     # parse comments
     comments: list[str] = []
src/preview/twitter.py
@@ -31,6 +31,10 @@ async def preview_twitter(
     twitter_provider: str = PROVIDER.TWITTER,
     *,
     twitter_comments: bool = True,
+    show_author: bool = True,
+    show_pubdate: bool = True,
+    show_device: bool = True,
+    show_statistics: bool = True,
     **kwargs,
 ):
     """Preview twitter link in the message.
@@ -144,16 +148,15 @@ async def preview_twitter(
     master_handle = master_info.get("handle", "")
     # 被回复主推
     if master_info:
-        msg += "🔗**该链接推文为主推下的一条跟推**\n"
         msg += "🕊**主推文内容:**"
-        if author := master_info.get("author"):
-            msg += f"\n🕊[{author}](https://x.com/{master_info['handle']}/status/{master_info['post_id']})"
-        if time_str := master_info.get("time"):
-            msg += f"\n🕒{time_str}"
-        if device := master_info.get("device"):
-            msg += f"📱{device}"
-        if statistics := master_info.get("statistics"):
-            msg += f"\n{statistics}"
+        if true(show_author) and master_info.get("author"):
+            msg += f"\n🕊[{master_info['author']}](https://x.com/{master_info['handle']}/status/{master_info['post_id']})"
+        if true(show_pubdate) and master_info.get("time"):
+            msg += f"\n🕒{master_info['time']}"
+        if true(show_device) and master_info.get("device"):
+            msg += f"📱{master_info['device']}"
+        if true(show_statistics) and master_info.get("statistics"):
+            msg += f"\n{master_info['statistics']}"
         if part_strs["first"]:
             msg += f"\n🏞{part_strs['first']}属于主推"
         if texts := master_info.get("texts"):
@@ -173,15 +176,14 @@ async def preview_twitter(
     if master_info:
         msg += f"\n🕊**{this_tweet_type}内容:**"
 
-    if author := this_info.get("author"):
-        msg += f"\n🕊[{author}]({url})"
-
-    if time_str := this_info.get("time"):
-        msg += f"\n🕒{time_str}"
-    if device := this_info.get("device"):
-        msg += f"📱{device}"
-    if statistics := this_info.get("statistics"):
-        msg += f"\n{statistics}"
+    if true(show_author) and this_info.get("author"):
+        msg += f"\n🕊[{this_info['author']}]({url})"
+    if true(show_pubdate) and this_info.get("time"):
+        msg += f"\n🕒{this_info['time']}"
+    if true(show_device) and this_info.get("device"):
+        msg += f"📱{this_info['device']}"
+    if true(show_statistics) and this_info.get("statistics"):
+        msg += f"\n{this_info['statistics']}"
     if part_strs["middle"] and (this_info["has_master"] or this_info["has_quote"]):  # 当有supp_info时, 附加图片数量说明
         msg += f"\n🏞{part_strs['middle']}属于{this_tweet_type}"
 
@@ -200,15 +202,15 @@ async def preview_twitter(
         # 有时候引用推文时会在正文末尾附带引推链接, 这里去掉
         quote_x_url = f"https://x.com/{quote_info.get('handle', '')}/status/{quote_info.get('post_id', '')}"
         msg = remove_twitter_suffix(msg, post_id=quote_info["post_id"], same_id_only=True)
-        msg += "\n🔁**本推文还引用下述推文:**"
-        if author := quote_info.get("author"):
-            msg += f"\n🕊[{author}]({quote_x_url})"
-        if time_str := quote_info.get("time"):
-            msg += f"\n🕒{time_str}"
-        if device := quote_info.get("device"):
-            msg += f"📱{device}"
-        if statistics := quote_info.get("statistics"):
-            msg += f"\n{statistics}"
+        msg += "\n🔁**引推内容:**"
+        if true(show_author) and quote_info.get("author"):
+            msg += f"\n🕊[{quote_info['author']}]({quote_x_url})"
+        if true(show_pubdate) and quote_info.get("time"):
+            msg += f"\n🕒{quote_info['time']}"
+        if true(show_device) and quote_info.get("device"):
+            msg += f"📱{quote_info['device']}"
+        if true(show_statistics) and quote_info.get("statistics"):
+            msg += f"\n{quote_info['statistics']}"
         if part_strs["last"]:
             msg += f"\n🏞{part_strs['last']}属于引推"
 
src/preview/weibo.py
@@ -36,6 +36,11 @@ async def preview_weibo(
     *,
     weibo_provider: str = PROVIDER.WEIBO,
     weibo_comments: bool = True,
+    show_author: bool = True,
+    show_pubdate: bool = True,
+    show_ip: bool = True,
+    show_device: bool = True,
+    show_statistics: bool = True,
     **kwargs,
 ):
     """Preview weibo link in the message.
@@ -82,20 +87,20 @@ async def preview_weibo(
             part_strs[k] = "图片及视频均"
 
     msg = ""
-    if author := this_info.get("author"):
-        msg += f"\n🧣**[{author}]({this_info.get('author_url', 'weibo.com')})**"
+    if true(show_author) and this_info.get("author"):
+        msg += f"\n🧣**[{this_info['author']}]({this_info.get('author_url', 'weibo.com')})**"
 
-    if dt := this_info["dt"]:
-        msg += f"\n🕒{dt}"
+    if true(show_pubdate) and this_info["dt"]:
+        msg += f"\n🕒{this_info['dt']}"
 
-    if region := this_info.get("region"):
-        msg += f" 📍{region}"
+    if true(show_ip) and this_info.get("region"):
+        msg += f" 📍{this_info['region']}"
 
-    if device := this_info.get("device"):
-        msg += f"\n📱{device}"
+    if true(show_device) and this_info.get("device"):
+        msg += f"\n📱{this_info['device']}"
 
-    if statistics := this_info.get("statistics"):
-        msg += f"\n{statistics}"
+    if true(show_statistics) and this_info.get("statistics"):
+        msg += f"\n{this_info['statistics']}"
 
     if part_strs["first"] and quote_info:  # 当有quote_info时, 附加图片数量说明:
         msg += f"\n🏞{part_strs['first']}属于本帖"
@@ -106,20 +111,20 @@ async def preview_weibo(
     media = this_info.get("media", [])
     if quote_info:
         msg += "\n🔁转帖内容:"
-        if author := quote_info.get("author"):
-            msg += f"\n🧣[{author}](https://m.weibo.cn/detail/{quote_info['post_id']})"
+        if true(show_author) and quote_info.get("author"):
+            msg += f"\n🧣[{quote_info['author']}](https://m.weibo.cn/detail/{quote_info['post_id']})"
 
-        if dt := quote_info.get("dt"):
-            msg += f"\n🕒{dt}"
+        if true(show_pubdate) and quote_info.get("dt"):
+            msg += f"\n🕒{quote_info['dt']}"
 
-        if region := quote_info.get("region"):
-            msg += f" 📍{region}"
+        if true(show_ip) and quote_info.get("region"):
+            msg += f" 📍{quote_info['region']}"
 
-        if device := quote_info.get("device"):
-            msg += f"\n📱{device}"
+        if true(show_device) and quote_info.get("device"):
+            msg += f"\n📱{quote_info['device']}"
 
-        if statistics := quote_info.get("statistics"):
-            msg += f"\n{statistics}"
+        if true(show_statistics) and quote_info.get("statistics"):
+            msg += f"\n{quote_info['statistics']}"
 
         if part_strs["last"]:
             msg += f"\n🏞{part_strs['last']}属于转帖"
src/preview/xiaohongshu.py
@@ -5,7 +5,7 @@ from zoneinfo import ZoneInfo
 
 import yaml
 from bs4 import BeautifulSoup
-from glom import glom
+from glom import Coalesce, glom
 from loguru import logger
 from pyrogram.client import Client
 from pyrogram.types import Message
@@ -19,6 +19,7 @@ from messages.sender import send2tg
 from messages.utils import summay_media
 from networking import download_file, download_first_success_urls, download_media, hx_req
 from others.emoji import emojify
+from utils import true
 
 
 async def preview_xhs(
@@ -30,6 +31,12 @@ async def preview_xhs(
     *,
     is_xhs_link: bool = False,
     xhs_provider: str = PROVIDER.XHS,
+    show_author: bool = True,
+    show_title: bool = True,
+    show_pubdate: bool = True,
+    show_ip: bool = True,
+    show_statistics: bool = True,
+    show_description: bool = True,
     **kwargs,
 ):
     """Preview xiaohongshu link in the message.
@@ -98,26 +105,23 @@ async def preview_xhs(
             else:
                 media.append({"photo": download_file(img_url, suffix=".jpg", proxy=PROXY.XHS, stream=True, **kwargs)})
 
-    title = note.get("title", "")
-    author = note.get("user", {}).get("nickname", "")
-    ts = note.get("time", 0) / 1000
-
     texts = ""
-    if author := note.get("user", {}).get("nickname") or note.get("user", {}).get("nickName"):
+    if true(show_author) and (author := glom(note, Coalesce("user.nickname", "user.nickName"), default="")):
         texts += f"🍠[{author}]({url})\n"
-    if ts := note.get("time"):
-        dt = datetime.fromtimestamp(float(ts) / 1000).astimezone(ZoneInfo(TZ))
+    if true(show_pubdate) and note.get("time"):
+        dt = datetime.fromtimestamp(float(note["time"]) / 1000).astimezone(ZoneInfo(TZ))
         texts += f"🕒{dt:%Y-%m-%d %H:%M:%S}"
-        if region := note.get("ipLocation"):
-            texts += f"📍{region}\n"
+        if true(show_ip) and note.get("ipLocation"):
+            texts += f"📍{note['ipLocation']}\n"
         else:
             texts += "\n"
-    if statistics := xhs_info.get("statistics"):
-        texts += f"{statistics}\n"
-    if title := note.get("title", ""):
-        texts += f"📝**{title}**\n"
+    if true(show_statistics) and xhs_info.get("statistics"):
+        texts += f"{xhs_info['statistics']}\n"
+    if true(show_title) and note.get("title"):
+        texts += f"📝**{note['title']}**\n"
     desc = note.get("desc", "").replace("[话题]#", "")
-    texts += desc
+    if true(show_description):
+        texts += desc
     comments = get_xhs_comments(xhs_info.get("soup"))  # Not implemented yet
     await modify_progress(text=f"⏬正在下载:\n{summay_media(media)}", force_update=True, **kwargs)
     media = await download_media(media, **kwargs)
src/ytdlp/main.py
@@ -50,6 +50,11 @@ async def preview_ytdlp(
     ytdlp_send_subtitle: bool = False,
     subtitle_force_file: bool = False,
     to_telegraph: bool = True,
+    show_author: bool = True,
+    show_title: bool = True,
+    show_pubdate: bool = True,
+    show_statistics: bool = True,
+    show_description: bool = True,
     **kwargs,
 ) -> list[Message]:
     """Preview ytdlp link in the message.
@@ -102,7 +107,20 @@ async def preview_ytdlp(
     if not info:
         return []
     info |= vinfo  # merge video info
-    captions = await generate_captions(info, url, platform, vid, bvid, bilibili_comments=bilibili_comments, youtube_comments=youtube_comments)
+    captions = await generate_captions(
+        info,
+        url=url,
+        platform=platform,
+        vid=vid,
+        bvid=bvid,
+        bilibili_comments=bilibili_comments,
+        youtube_comments=youtube_comments,
+        show_author=show_author,
+        show_title=show_title,
+        show_pubdate=show_pubdate,
+        show_statistics=show_statistics,
+        show_description=show_description,
+    )
     # add send_from_user prefix to caption
     prefix = kwargs.get("send_from_user", "")
     texts = f"{prefix}{captions['caption']}"
@@ -159,7 +177,21 @@ async def preview_ytdlp(
     return messages
 
 
-async def generate_captions(info: dict, url: str, platform: str, vid: str, bvid: str, *, bilibili_comments: bool, youtube_comments: bool) -> dict:
+async def generate_captions(
+    info: dict,
+    url: str,
+    platform: str,
+    vid: str,
+    bvid: str,
+    *,
+    bilibili_comments: bool,
+    youtube_comments: bool,
+    show_author: bool = True,
+    show_title: bool = True,
+    show_pubdate: bool = True,
+    show_statistics: bool = True,
+    show_description: bool = True,
+) -> dict:
     """Generate captions."""
     captions = ""
     results = {}
@@ -173,7 +205,8 @@ async def generate_captions(info: dict, url: str, platform: str, vid: str, bvid:
         results["author"] = f"{emoji}[{info['author']}]({url})"
     else:
         results["author"] = f"{emoji}[原始链接]({url})"
-    captions += f"{results['author']}\n"
+    if true(show_author):
+        captions += f"{results['author']}\n"
 
     # date
     if info.get("pubdate"):
@@ -184,19 +217,20 @@ async def generate_captions(info: dict, url: str, platform: str, vid: str, bvid:
         results["create_time"] = "🕒" + info["update_date"]
     else:
         results["create_time"] = ""
-    if results["create_time"]:
+    if true(show_pubdate) and results["create_time"]:
         captions += f"{results['create_time']}\n"
 
     results["statistics"] = info.get("statistics", "")
-    if results["statistics"]:
+    if true(show_statistics) and results["statistics"]:
         captions += f"{results['statistics']}\n"
 
     # title
     if info.get("title"):
         results["title"] = f"📝[{info['title']}]({url})"
-        captions += f"{results['title']}\n"
     else:
         results["title"] = ""
+    if true(show_title) and results["title"]:
+        captions += f"{results['title']}\n"
 
     # desc
     if (desc := info.get("description")) and (desc != "-"):
@@ -204,9 +238,10 @@ async def generate_captions(info: dict, url: str, platform: str, vid: str, bvid:
         soup = BeautifulSoup(desc, "html.parser")
         desc_text = soup_to_text(soup)
         results["description"] = make_bvid_clickable(desc_text)
-        captions += f"{results['description']}\n"
     else:
         results["description"] = ""
+    if true(show_description) and results["description"]:
+        captions += f"{results['description']}\n"
 
     # comments
     comment_list = []
@@ -264,7 +299,6 @@ async def send_media(
     video_messages = []
     audio_message = None
     video_target, audio_target = get_target_chats(message, ytdlp_video_target, ytdlp_audio_target, **kwargs)
-
     reply_msg_id = kwargs.get("reply_msg_id", 0)
     reply_parameters = get_reply_to(message.id, reply_msg_id)