From 1ef4efbc68197ea6870ab0ffb5c3a653c5d42ccb Mon Sep 17 00:00:00 2001 From: grassblock Date: Sun, 24 Aug 2025 18:19:40 +0800 Subject: [PATCH] feat: add song query as inline features --- core/inline.py | 52 ++++++++++++++++++++++++++++++++++++++++++++ helpers/songs.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 helpers/songs.py diff --git a/core/inline.py b/core/inline.py index 9c48751..6e62bb7 100644 --- a/core/inline.py +++ b/core/inline.py @@ -133,6 +133,58 @@ async def handle_inline_query(query: InlineQuery): ), ], cache_time=0) return + # 如果查询以 "是什么歌" 结尾,则尝试根据关键词获取歌曲名称 + if query_text.endswith("是什么歌"): + keywords = query_text[:-4].strip() + from helpers.songs import get_song_by_partial_match, get_song_link + # 尝试根据关键词获取歌曲名称 + song_name = get_song_by_partial_match(keywords) + song_link = get_song_link(song_name) if song_name else None + if song_name: + await query.answer(results=[ + InlineQueryResultArticle( + id="1", + title=f"我感觉你应该在找 {song_name}", + input_message_content=InputTextMessageContent( + message_text=f"你是不是在找:{song_name}\n{song_link}\n如果不是,可能你需要[在网络上搜索](https://search.bilibili.com/all?keyword={keywords})", + parse_mode=ParseMode.MARKDOWN + ), + description=f"根据关键词 '{keywords}' 找到的歌曲" + ) + ], cache_time=0) + return + else: + from helpers.songs import fetch_from_b23_api + # 如果没有在本地找到歌曲,则尝试从 Bilibili API 获取 + result = await fetch_from_b23_api(keywords) + if result: + song_name, song_link = result + await query.answer(results=[ + InlineQueryResultArticle( + id="1", + title=f"我感觉你应该在找 {song_name}", + input_message_content=InputTextMessageContent( + message_text=f"你是不是在找:{song_name}\n{song_link}\n如果不是,可能你需要[在网络上搜索](https://search.bilibili.com/all?keyword={keywords})", + parse_mode=ParseMode.MARKDOWN + ), + description=f"根据关键词 '{keywords}' 找到的歌曲" + ) + ], cache_time=0) + return + # 如果还是没有找到,则返回一个默认的结果 + else: + await query.answer(results=[ + InlineQueryResultArticle( + id="1", + title=f"抱歉,数据库中没有搜索到 '{keywords}' 的歌曲", + input_message_content=InputTextMessageContent( + message_text=f"可能你需要[在网络上搜索](https://search.bilibili.com/all?keyword={keywords})", + parse_mode=ParseMode.MARKDOWN + ), + description=f"或许你应该尝试在网上搜索" + ) + ], cache_time=0) + return # 如果没有匹配到任何内容,则返回一个默认的结果 await query.answer(results=[ InlineQueryResultArticle( diff --git a/helpers/songs.py b/helpers/songs.py new file mode 100644 index 0000000..edf7259 --- /dev/null +++ b/helpers/songs.py @@ -0,0 +1,56 @@ +# 一个暂时性的办法用来存储歌曲信息 +import aiohttp + +songs = { + "将军的小曲,三太阳的小曲": "你若三冬 - 阿悠悠", + "全斗焕的小曲,光州跑男的小曲,打成一片的小曲,无限制格斗的小曲,重拳的小曲,光州的小曲": "Shake and Sway", + "牛姐的养老保险,美国版难忘今宵,圣诞要你命": "All I Want for Christmas Is You - Mariah Carey", +} + +song_links = { + "你若三冬 - 阿悠悠": "https://www.bilibili.com/video/BV1wAdhYBEVg", + "Shake and Sway": "https://www.bilibili.com/video/av113101403850151", + "All I Want for Christmas Is You - Mariah Carey": "https://www.bilibili.com/video/BV1VJ411b7ah", +} + +def get_song_name(key): + """根据关键词获取歌曲名称""" + return songs.get(key) + +def get_song_link(key): + """根据歌曲名称获取歌曲链接""" + return song_links.get(key) + +def get_song_by_partial_match(partial_key): + """根据部分匹配获取歌曲名称""" + for key, value in songs.items(): + if partial_key in key: + return value + return None + +async def fetch_from_b23_api(song_name): + """从 Bilibili API 获取歌曲信息""" + resp = None + async with aiohttp.ClientSession() as session: + # 先访问 bilibili.com 获取 cookies + async with session.get('https://bilibili.com', headers={"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0"}) as response: + pass + + # 使用获取的 cookies 请求搜索 API + params = {'keyword': song_name} + async with session.get( + 'https://api.bilibili.com/x/web-interface/search/all/v2', + params=params, + headers={ + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0" + } + ) as response: + resp = await response.json() + if resp and resp.get('data'): + # 假设我们只取第一个视频的结果 + videos = next((item for item in resp['data']['result'] if item.get('result_type') == 'video'), None) + first_result = videos['data'][0] + title = first_result.get('title').replace('', '').replace('', '') # 清理标题中的 HTML 标签 + link = first_result.get('arcurl') + return title, link + return None \ No newline at end of file