nonebot-plugin-parser 2.6.8__tar.gz → 2.6.10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/PKG-INFO +1 -1
  2. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/pyproject.toml +2 -2
  3. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/pyproject.toml.orig +2 -2
  4. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/download/__init__.py +24 -27
  5. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/download/rich.py +15 -0
  6. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/__init__.py +41 -4
  7. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/douyin/__init__.py +14 -14
  8. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/twitter.py +4 -0
  9. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/README.md +0 -0
  10. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/__init__.py +0 -0
  11. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/config.py +0 -0
  12. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/constants.py +0 -0
  13. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/download/task.py +0 -0
  14. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/download/ytdlp.py +0 -0
  15. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/exception.py +0 -0
  16. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/helper.py +0 -0
  17. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/matchers/__init__.py +0 -0
  18. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/matchers/filter.py +0 -0
  19. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/matchers/rule.py +0 -0
  20. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/__init__.py +0 -0
  21. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/acfun/__init__.py +0 -0
  22. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/acfun/video.py +0 -0
  23. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/base.py +0 -0
  24. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/article.py +0 -0
  25. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/common.py +0 -0
  26. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/dynamic.py +0 -0
  27. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/favlist.py +0 -0
  28. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/live.py +0 -0
  29. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/opus.py +0 -0
  30. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/bilibili/video.py +0 -0
  31. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/cookie.py +0 -0
  32. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/data.py +0 -0
  33. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/douyin/aweme.py +0 -0
  34. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/kuaishou/__init__.py +0 -0
  35. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/kuaishou/states.py +0 -0
  36. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/nga.py +0 -0
  37. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/task.py +0 -0
  38. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/tiktok.py +0 -0
  39. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/utils.py +0 -0
  40. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/weibo/__init__.py +0 -0
  41. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/weibo/article.py +0 -0
  42. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/weibo/common.py +0 -0
  43. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/weibo/show.py +0 -0
  44. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/xiaohongshu/__init__.py +0 -0
  45. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/xiaohongshu/common.py +0 -0
  46. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/xiaohongshu/discovery.py +0 -0
  47. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/xiaohongshu/explore.py +0 -0
  48. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/youtube/__init__.py +0 -0
  49. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/parsers/youtube/meta.py +0 -0
  50. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/__init__.py +0 -0
  51. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/base.py +0 -0
  52. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/common/__init__.py +0 -0
  53. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/common/assets.py +0 -0
  54. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/common/font.py +0 -0
  55. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/common/renderer.py +0 -0
  56. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/default.py +0 -0
  57. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/htmlrender.py +0 -0
  58. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/HYSongYunLangHeiW.ttf +0 -0
  59. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/__init__.py +0 -0
  60. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/avatar.png +0 -0
  61. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/bilibili.png +0 -0
  62. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/douyin.png +0 -0
  63. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/1.jpg +0 -0
  64. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/2.jpg +0 -0
  65. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/3.jpg +0 -0
  66. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/4.jpg +0 -0
  67. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/5.jpg +0 -0
  68. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/6.jpg +0 -0
  69. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/7.jpg +0 -0
  70. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/8.jpg +0 -0
  71. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/fallback_pic/9.jpg +0 -0
  72. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/kuaishou.png +0 -0
  73. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/play.png +0 -0
  74. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/tiktok.png +0 -0
  75. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/twitter.png +0 -0
  76. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/weibo.png +0 -0
  77. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/xiaohongshu.png +0 -0
  78. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/resources/youtube.png +0 -0
  79. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/renders/templates/card.html.jinja2 +0 -0
  80. {nonebot_plugin_parser-2.6.8 → nonebot_plugin_parser-2.6.10}/src/nonebot_plugin_parser/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nonebot-plugin-parser
3
- Version: 2.6.8
3
+ Version: 2.6.10
4
4
  Summary: NoneBot2 链接分享解析 Alconna 版, 现支持B站|抖音|快手|微博|小红书|YouTube|TikTok|Twitter|AcFun|NGA
5
5
  Keywords: acfun,bilibili,douyin,kuaishou,nga,nonebot,nonebot2,tiktok,twitter,video,weibo,xiaohongshu,youtube
6
6
  Author: fllesser
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-parser"
3
- version = "2.6.8"
3
+ version = "2.6.10"
4
4
  description = "NoneBot2 链接分享解析 Alconna 版, 现支持B站|抖音|快手|微博|小红书|YouTube|TikTok|Twitter|AcFun|NGA"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -113,7 +113,7 @@ conflicts = [[
113
113
  [tool.bumpversion]
114
114
  tag = true
115
115
  commit = true
116
- current_version = "2.6.8"
116
+ current_version = "2.6.10"
117
117
  message = "release: bump vesion from {current_version} to {new_version}"
118
118
 
119
119
  [[tool.bumpversion.files]]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-parser"
3
- version = "2.6.8"
3
+ version = "2.6.10"
4
4
  description = "NoneBot2 链接分享解析 Alconna 版, 现支持B站|抖音|快手|微博|小红书|YouTube|TikTok|Twitter|AcFun|NGA"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -115,7 +115,7 @@ conflicts = [
115
115
  [tool.bumpversion]
116
116
  tag = true
117
117
  commit = true
118
- current_version = "2.6.8"
118
+ current_version = "2.6.10"
119
119
  message = "release: bump vesion from {current_version} to {new_version}"
120
120
 
121
121
  [[tool.bumpversion.files]]
@@ -7,7 +7,7 @@ import aiofiles
7
7
  import curl_cffi
8
8
  from nonebot import logger, get_driver
9
9
 
10
- from .rich import progress_bar, add_progress_task
10
+ from .rich import add_progress_task
11
11
  from .task import auto_task
12
12
  from ..utils import merge_av, safe_unlink, generate_file_name, is_module_available
13
13
  from ..config import pconfig
@@ -61,15 +61,14 @@ class StreamDownloader:
61
61
  response.raise_for_status()
62
62
  content_length = self._validate_content_length(response)
63
63
 
64
- with progress_bar:
65
- update_progress = add_progress_task(
66
- f"httpx | {file_path.name}",
67
- content_length,
68
- )
69
- async with aiofiles.open(file_path, "wb") as file:
70
- async for chunk in response.aiter_bytes(chunk_size):
71
- await file.write(chunk)
72
- update_progress(advance=len(chunk))
64
+ update_progress = add_progress_task(
65
+ f"httpx | {file_path.name}",
66
+ content_length,
67
+ )
68
+ async with aiofiles.open(file_path, "wb") as file:
69
+ async for chunk in response.aiter_bytes(chunk_size):
70
+ await file.write(chunk)
71
+ update_progress(advance=len(chunk))
73
72
 
74
73
  return file_path
75
74
 
@@ -90,15 +89,14 @@ class StreamDownloader:
90
89
  response.raise_for_status()
91
90
  content_length = self._validate_content_length(response)
92
91
 
93
- with progress_bar:
94
- update_progress = add_progress_task(
95
- f"curl_cffi | {file_path.name}",
96
- content_length,
97
- )
98
- async with aiofiles.open(file_path, "wb") as file:
99
- async for chunk in response.aiter_content(chunk_size=8192):
100
- await file.write(chunk)
101
- update_progress(advance=len(chunk))
92
+ update_progress = add_progress_task(
93
+ f"curl_cffi | {file_path.name}",
94
+ content_length,
95
+ )
96
+ async with aiofiles.open(file_path, "wb") as file:
97
+ async for chunk in response.aiter_content(chunk_size=8192):
98
+ await file.write(chunk)
99
+ update_progress(advance=len(chunk))
102
100
 
103
101
  return file_path
104
102
 
@@ -220,14 +218,13 @@ class StreamDownloader:
220
218
  video_path = pconfig.cache_dir / video_name
221
219
 
222
220
  try:
223
- with progress_bar:
224
- async with aiofiles.open(video_path, "wb") as f:
225
- update_progress = add_progress_task(desc=video_name)
226
- for url in await self._get_m3u8_slices(m3u8_url):
227
- async with self.client.stream("GET", url, headers=ext_headers) as response:
228
- async for chunk in response.aiter_bytes(chunk_size=1024 * 1024):
229
- await f.write(chunk)
230
- update_progress(advance=len(chunk))
221
+ async with aiofiles.open(video_path, "wb") as f:
222
+ update_progress = add_progress_task(desc=video_name)
223
+ for url in await self._get_m3u8_slices(m3u8_url):
224
+ async with self.client.stream("GET", url, headers=ext_headers) as response:
225
+ async for chunk in response.aiter_bytes(chunk_size=1024 * 1024):
226
+ await f.write(chunk)
227
+ update_progress(advance=len(chunk))
231
228
  except httpx.HTTPError:
232
229
  await safe_unlink(video_path)
233
230
  logger.exception("m3u8 视频下载失败")
@@ -23,3 +23,18 @@ def add_progress_task(
23
23
  task_id = progress_bar.add_task(description=desc, total=total)
24
24
  progress_bar.start_task(task_id)
25
25
  return partial(progress_bar.update, task_id)
26
+
27
+
28
+ from nonebot import get_driver
29
+
30
+ driver = get_driver()
31
+
32
+
33
+ @driver.on_startup
34
+ async def enter_progress_bar():
35
+ progress_bar.start()
36
+
37
+
38
+ @driver.on_shutdown
39
+ async def exit_progress_bar():
40
+ progress_bar.stop()
@@ -6,10 +6,16 @@ from collections.abc import AsyncGenerator
6
6
 
7
7
  from msgspec import convert
8
8
  from nonebot import logger
9
- from bilibili_api import HEADERS, Credential, select_client, request_settings
9
+ from bilibili_api import (
10
+ HEADERS,
11
+ Credential,
12
+ get_client,
13
+ select_client,
14
+ request_settings,
15
+ )
10
16
  from bilibili_api.opus import Opus
11
17
  from bilibili_api.video import Video
12
- from bilibili_api.login_v2 import QrCodeLogin, QrCodeLoginEvents
18
+ from bilibili_api.login_v2 import QrCodeLogin, QrCodeLoginEvents, QrCodeLoginChannel
13
19
 
14
20
  from ..base import (
15
21
  BaseParser,
@@ -35,6 +41,7 @@ class BilibiliParser(BaseParser):
35
41
  platform: ClassVar[Platform] = Platform(name=PlatformEnum.BILIBILI, display_name="哔哩哔哩")
36
42
 
37
43
  def __init__(self):
44
+ super().__init__()
38
45
  self.headers = HEADERS.copy()
39
46
  self._credential: Credential | None = None
40
47
  self._cookies_file = pconfig.config_dir / "bilibili_cookies.json"
@@ -353,18 +360,48 @@ class BilibiliParser(BaseParser):
353
360
 
354
361
  async def login_with_qrcode(self) -> bytes:
355
362
  """通过二维码登录获取哔哩哔哩登录凭证"""
356
- self._qr_login = QrCodeLogin()
363
+ self._qr_login = QrCodeLogin(platform=QrCodeLoginChannel.WEB)
357
364
  await self._qr_login.generate_qrcode()
358
365
 
359
366
  qr_pic = self._qr_login.get_qrcode_picture()
360
367
  return qr_pic.content
361
368
 
369
+ @staticmethod
370
+ async def check_state(qr: QrCodeLogin):
371
+ client = get_client()
372
+ resp = await client.request(
373
+ method="GET",
374
+ url="https://passport.bilibili.com/x/passport-login/web/qrcode/poll",
375
+ params={"qrcode_key": qr._QrCodeLogin__qr_key}, # pyright: ignore[reportAttributeAccessIssue]
376
+ )
377
+ result: dict = resp.json()["data"] # pyright: ignore[reportIndexIssue]
378
+ code = result["code"]
379
+ if code == 86101:
380
+ return QrCodeLoginEvents.SCAN
381
+ elif code == 86090:
382
+ return QrCodeLoginEvents.CONF
383
+ elif code == 86038:
384
+ return QrCodeLoginEvents.TIMEOUT
385
+ else:
386
+ ac_time_value = result["refresh_token"]
387
+ cookies = resp.cookies
388
+ sessdata = cookies["SESSDATA"]
389
+ bili_jct = cookies["bili_jct"]
390
+ dedeuserid = cookies["DedeUserID"]
391
+ qr._QrCodeLogin__credential = Credential( # pyright: ignore[reportAttributeAccessIssue]
392
+ sessdata=sessdata,
393
+ bili_jct=bili_jct,
394
+ dedeuserid=dedeuserid,
395
+ ac_time_value=ac_time_value,
396
+ )
397
+ return QrCodeLoginEvents.DONE
398
+
362
399
  async def check_qr_state(self) -> AsyncGenerator[str]:
363
400
  """检查二维码登录状态"""
364
401
  scan_tip_pending = True
365
402
 
366
403
  for _ in range(30):
367
- state = await self._qr_login.check_state()
404
+ state = await self.check_state(self._qr_login)
368
405
  match state:
369
406
  case QrCodeLoginEvents.DONE:
370
407
  yield "登录成功"
@@ -74,20 +74,6 @@ class DouyinParser(BaseParser):
74
74
  timestamp=aweme.create_time,
75
75
  url=aweme.share_url.split("?")[0],
76
76
  )
77
- if music := aweme.music:
78
- if not music.is_original_sound:
79
- if music.play_url.uri == "":
80
- extra = json.loads(music.extra)
81
- music_url = extra.get("original_song_url")
82
- else:
83
- music_url = music.play_url.uri
84
- if music_url:
85
- result.contents.append(
86
- self.create_audio(
87
- url_or_task=music_url,
88
- duration=music.duration,
89
- )
90
- )
91
77
 
92
78
  # 添加图片内容
93
79
  if images := aweme.images:
@@ -107,6 +93,20 @@ class DouyinParser(BaseParser):
107
93
  self.create_video(url_or_task=image_video.play_addr.url),
108
94
  ]
109
95
  )
96
+ if music := aweme.music:
97
+ if not music.is_original_sound:
98
+ if music.play_url.uri == "":
99
+ extra = json.loads(music.extra)
100
+ music_url = extra.get("original_song_url")
101
+ else:
102
+ music_url = music.play_url.uri
103
+ if music_url:
104
+ result.contents.append(
105
+ self.create_audio(
106
+ url_or_task=music_url,
107
+ duration=music.duration,
108
+ )
109
+ )
110
110
  # 添加视频内容
111
111
  elif video := aweme.video:
112
112
  result.video = self.create_video(
@@ -57,6 +57,10 @@ decoder = Decoder(VxTwitterResponse)
57
57
  class TwitterParser(BaseParser):
58
58
  platform: ClassVar[Platform] = Platform(name=PlatformEnum.TWITTER, display_name="小蓝鸟")
59
59
 
60
+ def __init__(self):
61
+ super().__init__()
62
+ self.headers = {"User-Agent": "python-httpx/0.28.1"}
63
+
60
64
  @handle("x.com", r"x.com/[0-9-a-zA-Z_]{1,20}/status/([0-9]+)")
61
65
  async def _parse(self, searched: re.Match[str]) -> ParseResult:
62
66
  url = f"https://{searched.group(0)}"