nonebot-adapter-qq 1.2.0__py3-none-any.whl → 1.3.1__py3-none-any.whl

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.
@@ -313,12 +313,12 @@ class Bot(BaseBot):
313
313
  if image := message["image"]:
314
314
  kwargs["file_type"] = 1
315
315
  kwargs["url"] = image[-1].data["url"]
316
- elif audio := message["audio"]:
317
- kwargs["file_type"] = 2
318
- kwargs["url"] = audio[-1].data["url"]
319
316
  elif video := message["video"]:
320
- kwargs["file_type"] = 3
317
+ kwargs["file_type"] = 2
321
318
  kwargs["url"] = video[-1].data["url"]
319
+ elif audio := message["audio"]:
320
+ kwargs["file_type"] = 3
321
+ kwargs["url"] = audio[-1].data["url"]
322
322
  elif file := message["file"]:
323
323
  kwargs["file_type"] = 4
324
324
  kwargs["url"] = file[-1].data["url"]
@@ -370,7 +370,7 @@ class Bot(BaseBot):
370
370
 
371
371
  async def send_to_c2c(
372
372
  self,
373
- user_id: str,
373
+ openid: str,
374
374
  message: Union[str, Message, MessageSegment],
375
375
  msg_id: Optional[str] = None,
376
376
  msg_seq: Optional[int] = None,
@@ -401,7 +401,7 @@ class Bot(BaseBot):
401
401
  media: Optional[Media] = None
402
402
  if msg_type == 7:
403
403
  media_info = await self.post_c2c_files(
404
- user_id=user_id, srv_send_msg=False, **self._extract_qq_media(message)
404
+ openid=openid, srv_send_msg=False, **self._extract_qq_media(message)
405
405
  )
406
406
  media = (
407
407
  Media(file_info=media_info.file_info) if media_info.file_info else None
@@ -409,7 +409,7 @@ class Bot(BaseBot):
409
409
  kwargs["media"] = media
410
410
 
411
411
  return await self.post_c2c_messages(
412
- user_id=user_id,
412
+ openid=openid,
413
413
  msg_type=msg_type,
414
414
  msg_id=msg_id,
415
415
  msg_seq=msg_seq,
@@ -419,7 +419,7 @@ class Bot(BaseBot):
419
419
 
420
420
  async def send_to_group(
421
421
  self,
422
- group_id: str,
422
+ group_openid: str,
423
423
  message: Union[str, Message, MessageSegment],
424
424
  msg_id: Optional[str] = None,
425
425
  msg_seq: Optional[int] = None,
@@ -450,7 +450,9 @@ class Bot(BaseBot):
450
450
  media: Optional[Media] = None
451
451
  if msg_type == 7:
452
452
  media_info = await self.post_group_files(
453
- group_id=group_id, srv_send_msg=False, **self._extract_qq_media(message)
453
+ group_openid=group_openid,
454
+ srv_send_msg=False,
455
+ **self._extract_qq_media(message),
454
456
  )
455
457
  media = (
456
458
  Media(file_info=media_info.file_info) if media_info.file_info else None
@@ -458,7 +460,7 @@ class Bot(BaseBot):
458
460
  kwargs["media"] = media
459
461
 
460
462
  return await self.post_group_messages(
461
- group_id=group_id,
463
+ group_openid=group_openid,
462
464
  msg_type=msg_type,
463
465
  msg_id=msg_id,
464
466
  msg_seq=msg_seq,
@@ -490,7 +492,7 @@ class Bot(BaseBot):
490
492
  elif isinstance(event, C2CMessageCreateEvent):
491
493
  event._reply_seq += 1
492
494
  return await self.send_to_c2c(
493
- user_id=event.author.id,
495
+ openid=event.author.id,
494
496
  message=message,
495
497
  msg_id=event.id,
496
498
  msg_seq=event._reply_seq,
@@ -498,7 +500,7 @@ class Bot(BaseBot):
498
500
  elif isinstance(event, GroupAtMessageCreateEvent):
499
501
  event._reply_seq += 1
500
502
  return await self.send_to_group(
501
- group_id=event.group_id,
503
+ group_openid=event.group_openid,
502
504
  message=message,
503
505
  msg_id=event.id,
504
506
  msg_seq=event._reply_seq,
@@ -1606,7 +1608,7 @@ class Bot(BaseBot):
1606
1608
  async def post_c2c_messages(
1607
1609
  self,
1608
1610
  *,
1609
- user_id: str,
1611
+ openid: str,
1610
1612
  msg_type: Literal[0, 1, 2, 3, 4, 7],
1611
1613
  content: Optional[str] = None,
1612
1614
  markdown: Optional[MessageMarkdown] = None,
@@ -1632,7 +1634,7 @@ class Bot(BaseBot):
1632
1634
 
1633
1635
  request = Request(
1634
1636
  "POST",
1635
- self.adapter.get_api_base().joinpath("v2", "users", user_id, "messages"),
1637
+ self.adapter.get_api_base().joinpath("v2", "users", openid, "messages"),
1636
1638
  json=exclude_none(
1637
1639
  {
1638
1640
  "msg_type": msg_type,
@@ -1669,7 +1671,7 @@ class Bot(BaseBot):
1669
1671
  async def post_c2c_files(
1670
1672
  self,
1671
1673
  *,
1672
- user_id: str,
1674
+ openid: str,
1673
1675
  file_type: Literal[1, 2, 3, 4],
1674
1676
  url: str,
1675
1677
  srv_send_msg: bool = True,
@@ -1677,7 +1679,7 @@ class Bot(BaseBot):
1677
1679
  ) -> PostC2CFilesReturn:
1678
1680
  request = Request(
1679
1681
  "POST",
1680
- self.adapter.get_api_base().joinpath("v2", "users", user_id, "files"),
1682
+ self.adapter.get_api_base().joinpath("v2", "users", openid, "files"),
1681
1683
  json=exclude_none(
1682
1684
  {
1683
1685
  "file_type": file_type,
@@ -1694,7 +1696,7 @@ class Bot(BaseBot):
1694
1696
  async def post_group_messages(
1695
1697
  self,
1696
1698
  *,
1697
- group_id: str,
1699
+ group_openid: str,
1698
1700
  msg_type: Literal[0, 1, 2, 3, 4, 7],
1699
1701
  content: Optional[str] = None,
1700
1702
  markdown: Optional[MessageMarkdown] = None,
@@ -1720,7 +1722,9 @@ class Bot(BaseBot):
1720
1722
 
1721
1723
  request = Request(
1722
1724
  "POST",
1723
- self.adapter.get_api_base().joinpath("v2", "groups", group_id, "messages"),
1725
+ self.adapter.get_api_base().joinpath(
1726
+ "v2", "groups", group_openid, "messages"
1727
+ ),
1724
1728
  json=exclude_none(
1725
1729
  {
1726
1730
  "msg_type": msg_type,
@@ -1757,7 +1761,7 @@ class Bot(BaseBot):
1757
1761
  async def post_group_files(
1758
1762
  self,
1759
1763
  *,
1760
- group_id: str,
1764
+ group_openid: str,
1761
1765
  file_type: Literal[1, 2, 3, 4],
1762
1766
  url: str,
1763
1767
  srv_send_msg: bool = True,
@@ -1765,7 +1769,7 @@ class Bot(BaseBot):
1765
1769
  ) -> PostGroupFilesReturn:
1766
1770
  request = Request(
1767
1771
  "POST",
1768
- self.adapter.get_api_base().joinpath("v2", "groups", group_id, "files"),
1772
+ self.adapter.get_api_base().joinpath("v2", "groups", group_openid, "files"),
1769
1773
  json=exclude_none(
1770
1774
  {
1771
1775
  "file_type": file_type,
@@ -14,12 +14,14 @@ from .models import (
14
14
  RichText,
15
15
  QQMessage,
16
16
  AudioAction,
17
+ FriendAuthor,
17
18
  MessageDelete,
18
19
  MessageAudited,
19
20
  ForumSourceInfo,
20
21
  MessageReaction,
21
22
  ForumAuditResult,
22
23
  ButtonInteraction,
24
+ GroupMemberAuthor,
23
25
  )
24
26
 
25
27
  E = TypeVar("E", bound="Event")
@@ -348,14 +350,6 @@ class DirectMessageDeleteEvent(MessageDeleteEvent):
348
350
  class QQMessageEvent(MessageEvent, QQMessage):
349
351
  _reply_seq: int = -1
350
352
 
351
- @override
352
- def get_user_id(self) -> str:
353
- return self.author.id
354
-
355
- @override
356
- def get_session_id(self) -> str:
357
- return self.author.id
358
-
359
353
  @override
360
354
  def get_message(self) -> Message:
361
355
  if not hasattr(self, "_message"):
@@ -367,37 +361,48 @@ class QQMessageEvent(MessageEvent, QQMessage):
367
361
  class C2CMessageCreateEvent(QQMessageEvent):
368
362
  __type__ = EventType.C2C_MESSAGE_CREATE
369
363
 
364
+ author: FriendAuthor
370
365
  to_me: bool = True
371
366
 
367
+ @override
368
+ def get_user_id(self) -> str:
369
+ return self.author.user_openid
370
+
371
+ @override
372
+ def get_session_id(self) -> str:
373
+ return f"friend_{self.author.user_openid}"
374
+
372
375
  @override
373
376
  def get_event_description(self) -> str:
374
377
  return escape_tag(
375
378
  f"Message {self.id} from {self.author.id}: {self.get_message()!r}"
376
379
  )
377
380
 
378
- @override
379
- def get_session_id(self) -> str:
380
- return f"friend_{self.author.id}"
381
-
382
381
 
383
382
  @register_event_class
384
383
  class GroupAtMessageCreateEvent(QQMessageEvent):
385
384
  __type__ = EventType.GROUP_AT_MESSAGE_CREATE
386
385
 
387
- group_id: str
386
+ author: GroupMemberAuthor
387
+ group_openid: str
388
388
  to_me: bool = True
389
389
 
390
+ @override
391
+ def get_user_id(self) -> str:
392
+ return self.author.member_openid
393
+
394
+ @override
395
+ def get_session_id(self) -> str:
396
+ return f"group_{self.group_openid}_{self.author.member_openid}"
397
+
390
398
  @override
391
399
  def get_event_description(self) -> str:
392
400
  return escape_tag(
393
- f"Message {self.id} from {self.author.id}@[Group:{self.group_id}]: "
401
+ f"Message {self.id} from "
402
+ f"{self.author.member_openid}@[Group:{self.group_openid}]: "
394
403
  f"{self.get_message()!r}"
395
404
  )
396
405
 
397
- @override
398
- def get_session_id(self) -> str:
399
- return f"group_{self.group_id}_{self.author.id}"
400
-
401
406
 
402
407
  @register_event_class
403
408
  class InteractionCreateEvent(NoticeEvent, ButtonInteraction):
@@ -587,15 +592,15 @@ class OpenForumReplyDeleteEvent(OpenForumEvent):
587
592
  # Friend Robot Event
588
593
  class FriendRobotEvent(NoticeEvent):
589
594
  timestamp: datetime
590
- open_id: str
595
+ openid: str
591
596
 
592
597
  @override
593
598
  def get_user_id(self) -> str:
594
- return self.open_id
599
+ return self.openid
595
600
 
596
601
  @override
597
602
  def get_session_id(self) -> str:
598
- return f"friend_{self.open_id}"
603
+ return f"friend_{self.openid}"
599
604
 
600
605
 
601
606
  @register_event_class
@@ -8,10 +8,11 @@ from typing import TYPE_CHECKING, Type, Union, Iterable, Optional, TypedDict, ov
8
8
  from nonebot.adapters import Message as BaseMessage
9
9
  from nonebot.adapters import MessageSegment as BaseMessageSegment
10
10
 
11
+ from .models import QQMessage
11
12
  from .utils import escape, unescape
12
13
  from .models import Message as GuildMessage
14
+ from .models import Attachment as QQAttachment
13
15
  from .models import (
14
- QQMessage,
15
16
  MessageArk,
16
17
  MessageEmbed,
17
18
  MessageKeyboard,
@@ -401,15 +402,16 @@ class Message(BaseMessage[MessageSegment]):
401
402
  if message.content:
402
403
  msg.extend(Message(message.content))
403
404
  if message.attachments:
404
- attachment_types = {
405
- "图片": "image",
406
- "语音": "audio",
407
- "视频": "video",
408
- "文件": "file",
409
- }
405
+
406
+ def content_type(seg: QQAttachment):
407
+ ct = seg.content_type.split("/", maxsplit=1)[0]
408
+ if ct in {"image", "audio", "file", "video"}:
409
+ return ct
410
+ return "file"
411
+
410
412
  msg.extend(
411
413
  Attachment(
412
- attachment_types.get(seg.content_type, "file"),
414
+ content_type(seg),
413
415
  data={"url": seg.url},
414
416
  )
415
417
  for seg in message.attachments
@@ -1,12 +1,19 @@
1
1
  from typing import List, Optional
2
+ from urllib.parse import urlparse
2
3
 
3
- from pydantic import BaseModel
4
+ from pydantic import BaseModel, validator
4
5
 
5
6
 
6
7
  # Message Attachment
7
8
  class MessageAttachment(BaseModel):
8
9
  url: str
9
10
 
11
+ @validator("url", allow_reuse=True)
12
+ def check_url(cls, v: str):
13
+ if v and not urlparse(v).hostname:
14
+ return f"https://{v}"
15
+ return v
16
+
10
17
 
11
18
  # Message Embed
12
19
  class MessageEmbedThumbnail(BaseModel):
@@ -1,11 +1,18 @@
1
1
  from datetime import datetime
2
+ from urllib.parse import urlparse
2
3
  from typing import List, Literal, Optional
3
4
 
4
- from pydantic import BaseModel
5
+ from pydantic import BaseModel, validator
5
6
 
6
7
 
7
- class Author(BaseModel):
8
+ class FriendAuthor(BaseModel):
8
9
  id: str
10
+ user_openid: str
11
+
12
+
13
+ class GroupMemberAuthor(BaseModel):
14
+ id: str
15
+ member_openid: str
9
16
 
10
17
 
11
18
  class Attachment(BaseModel):
@@ -16,6 +23,12 @@ class Attachment(BaseModel):
16
23
  size: Optional[str] = None
17
24
  url: Optional[str] = None
18
25
 
26
+ @validator("url", allow_reuse=True)
27
+ def check_url(cls, v: str):
28
+ if v and not urlparse(v).hostname:
29
+ return f"https://{v}"
30
+ return v
31
+
19
32
 
20
33
  class Media(BaseModel):
21
34
  file_info: str
@@ -23,7 +36,6 @@ class Media(BaseModel):
23
36
 
24
37
  class QQMessage(BaseModel):
25
38
  id: str
26
- author: Author
27
39
  content: str
28
40
  timestamp: str
29
41
  attachments: Optional[List[Attachment]] = None
@@ -87,7 +99,8 @@ class ButtonInteraction(BaseModel):
87
99
 
88
100
 
89
101
  __all__ = [
90
- "Author",
102
+ "FriendAuthor",
103
+ "GroupMemberAuthor",
91
104
  "Attachment",
92
105
  "Media",
93
106
  "QQMessage",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-adapter-qq
3
- Version: 1.2.0
3
+ Version: 1.3.1
4
4
  Summary: QQ adapter for nonebot2
5
5
  Home-page: https://github.com/nonebot/adapter-qq
6
6
  License: MIT
@@ -1,20 +1,20 @@
1
1
  nonebot/adapters/qq/__init__.py,sha256=u2bR9HLdgIEV22nu2VJeUFscklTUj8DN4650q0k5SHw,787
2
2
  nonebot/adapters/qq/adapter.py,sha256=NLEgraL3kMOjdoSysrpDiaWjgxlJIxDmCRyYBvTyKyI,14303
3
- nonebot/adapters/qq/bot.py,sha256=X6SZo_gZAIHj0iceR2UeCusnhvReXoEg-TRpDPQVBPA,58971
3
+ nonebot/adapters/qq/bot.py,sha256=nz0D4qEwgAji3nLQgUCaETmOo15H9VHheEOH8fubjak,59068
4
4
  nonebot/adapters/qq/config.py,sha256=9EbzpCFnWyMNXWlTZmx1WYKbEl1I9KMrTf9bIf9r7dg,1979
5
- nonebot/adapters/qq/event.py,sha256=FMeQ5CQFQcNv6_qCD79bGsDgBiVMCUR0EtGA13nGO5c,17614
5
+ nonebot/adapters/qq/event.py,sha256=iY8G4GlhzL8JvIiFdQT7R3-CmG1hsuK7kmBAH-_h2KI,17783
6
6
  nonebot/adapters/qq/exception.py,sha256=8Xa9NwYyO7Ih0owBAC_zmEiIRAA8GjgQcoJcF5ogo0g,2701
7
- nonebot/adapters/qq/message.py,sha256=fRD1R6rG8QY-mBbCXndv2wxzNgQEICiNj218o5B8k1o,11170
7
+ nonebot/adapters/qq/message.py,sha256=IJu_sDUT2Hcd0-VfT-kzBxq3mMxbzOOSiNwfBjCcgQk,11254
8
8
  nonebot/adapters/qq/models/__init__.py,sha256=AahR-O5B_1c8dMXHpDH68o4qojhF3vf4UPDGyH2MKjA,537
9
9
  nonebot/adapters/qq/models/_transformer.py,sha256=Zrhno7aJKHkLnljFuyivndRKdrxtqZZaoiXOFx0JQdU,3416
10
- nonebot/adapters/qq/models/common.py,sha256=rAhR3gJVKJVgmFky1jL68H1RPCSQlbkZgIgXYDkVIuc,2817
10
+ nonebot/adapters/qq/models/common.py,sha256=_5y9vhEexJaE7poS1ABALarpDdPCjvmNtRB-pWXeAOI,3029
11
11
  nonebot/adapters/qq/models/guild.py,sha256=4EZHvpzfPKwapCTAmI22zWaHtL0AZccIszQH3hTxoSo,11666
12
12
  nonebot/adapters/qq/models/payload.py,sha256=dg9AYDI3YjWZ3bT-mn9596glszBwmI8i751sMY_maSM,2281
13
- nonebot/adapters/qq/models/qq.py,sha256=5SFf2tjWG_MhrSjajd_M1s5I510Fxu9eyywUyNgNoiY,2101
13
+ nonebot/adapters/qq/models/qq.py,sha256=JUMJy33lvzkiLPc9XaPtt8dQvuX0-_I0o12VeBiTfiY,2425
14
14
  nonebot/adapters/qq/permission.py,sha256=0aedypl6xymhAV3UkW0vlvHTBkJeDmOef3SxG2tPcHQ,988
15
15
  nonebot/adapters/qq/store.py,sha256=X-NeSVCrxngQDPo9IXKWehERNa4sefdrYrZn5-yucF4,874
16
16
  nonebot/adapters/qq/utils.py,sha256=vU0aNRIBtU4za8-2uVoRXjjcQsBw2i0SFFGX8KOuJjE,1570
17
- nonebot_adapter_qq-1.2.0.dist-info/LICENSE,sha256=4EZBnkZPQYBvtO2KFGaUQHTO8nZ26pGeaCFchdBq_AE,1064
18
- nonebot_adapter_qq-1.2.0.dist-info/METADATA,sha256=gTzGlA64_qtQsOl-I5UDLi0pg5D7NWYja8vKaYg7MUk,2768
19
- nonebot_adapter_qq-1.2.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
20
- nonebot_adapter_qq-1.2.0.dist-info/RECORD,,
17
+ nonebot_adapter_qq-1.3.1.dist-info/LICENSE,sha256=4EZBnkZPQYBvtO2KFGaUQHTO8nZ26pGeaCFchdBq_AE,1064
18
+ nonebot_adapter_qq-1.3.1.dist-info/METADATA,sha256=eWrnLsYgG-7eAiU3dmq8uZEJNfvqzKhkjDrNUA6IEWM,2768
19
+ nonebot_adapter_qq-1.3.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
20
+ nonebot_adapter_qq-1.3.1.dist-info/RECORD,,