Skip to content

Commit 3d5dc24

Browse files
authored
feat: support get_friend_list (#18)
1 parent 770c0df commit 3d5dc24

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed

lagrange/client/client.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
from lagrange.pb.message.msg_push import MsgPushBody
1818
from lagrange.pb.message.send import SendMsgRsp
1919
from lagrange.pb.service.comm import SendNudge
20+
from lagrange.pb.service.friend import (
21+
GetFriendListRsp,
22+
GetFriendListUin,
23+
PBGetFriendListRequest,
24+
propertys,
25+
)
2026
from lagrange.pb.service.group import (
2127
FetchGroupResponse,
2228
GetGrpMsgRsp,
@@ -58,7 +64,7 @@
5864
from .message.elems import Audio, Image
5965
from .message.encoder import build_message
6066
from .message.types import Element
61-
from .models import UserInfo
67+
from .models import UserInfo, BotFriend
6268
from .server_push import PushDeliver, bind_services
6369
from .wtlogin.sso import SSOPacket
6470

@@ -337,6 +343,58 @@ async def get_grp_msg(
337343
return [*filter(lambda msg: msg.rand != -1, rsp)]
338344
return rsp
339345

346+
async def get_friend_list(self):
347+
nextuin_cache: List[GetFriendListUin] = []
348+
rsp: List[BotFriend] = []
349+
frist_send = GetFriendListRsp.decode(
350+
(await self.send_oidb_svc(0xFD4, 1, PBGetFriendListRequest().encode())).data
351+
)
352+
properties: Optional[dict] = None
353+
if frist_send.next:
354+
nextuin_cache.append(frist_send.next)
355+
for raw in frist_send.friend_list:
356+
for j in raw.additional:
357+
if j.type == 1:
358+
properties = propertys(j.layer1.properties)
359+
if properties is not None:
360+
rsp.append(
361+
BotFriend(
362+
raw.uin,
363+
raw.uid,
364+
properties.get(20002),
365+
properties.get(103),
366+
properties.get(102),
367+
properties.get(27394),
368+
)
369+
)
370+
371+
while nextuin_cache:
372+
next = GetFriendListRsp.decode(
373+
(
374+
await self.send_oidb_svc(
375+
0xFD4, 1, PBGetFriendListRequest().encode()
376+
)
377+
).data
378+
)
379+
for raw in next.friend_list:
380+
for j in raw.additional:
381+
properties = propertys(j.layer1.properties)
382+
if properties is not None:
383+
rsp.append(
384+
BotFriend(
385+
raw.uin,
386+
raw.uid,
387+
properties.get(20002),
388+
properties.get(103),
389+
properties.get(102),
390+
properties.get(27394),
391+
)
392+
)
393+
if next.next:
394+
nextuin_cache.append(next)
395+
396+
return rsp
397+
340398
async def recall_grp_msg(self, grp_id: int, seq: int):
341399
payload = await self.send_uni_packet(
342400
"trpc.msg.msg_svc.MsgService.SsoGroupRecallMsg",

lagrange/client/models.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from dataclasses import dataclass
33
from datetime import datetime
44
from enum import IntEnum
5+
from typing import Optional
56
from lagrange.pb.service.group import GetInfoRspBody
67

78

@@ -65,3 +66,13 @@ def from_pb(cls, pb: GetInfoRspBody) -> "UserInfo":
6566
else:
6667
pass
6768
return rsp
69+
70+
71+
@dataclass
72+
class BotFriend:
73+
uin: int
74+
uid: Optional[str] = None
75+
nickname: Optional[str] = None
76+
remarks: Optional[str] = None
77+
personal_sign: Optional[str] = None
78+
qid: Optional[str] = None

lagrange/pb/service/friend.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from typing import List, Optional, Union
2+
3+
from lagrange.utils.binary.protobuf import ProtoStruct, proto_field
4+
5+
6+
class FriendProperty(ProtoStruct):
7+
code: int = proto_field(1)
8+
value: Optional[str] = proto_field(2, default=None)
9+
10+
11+
class FriendLayer1(ProtoStruct):
12+
properties: List[FriendProperty] = proto_field(2, default=None)
13+
14+
15+
class FriendAdditional(ProtoStruct):
16+
type: int = proto_field(1)
17+
layer1: FriendLayer1 = proto_field(2)
18+
19+
20+
class FriendInfo(ProtoStruct):
21+
uid: str = proto_field(1)
22+
custom_group: Optional[int] = proto_field(2, default=None)
23+
uin: int = proto_field(3)
24+
additional: List[FriendAdditional] = proto_field(10001)
25+
26+
27+
class GetFriendNumbers(ProtoStruct):
28+
f1: List[int] = proto_field(1)
29+
30+
31+
class GetFriendBody(ProtoStruct):
32+
type: int = proto_field(1)
33+
f2: GetFriendNumbers = proto_field(2)
34+
35+
36+
class GetFriendListUin(ProtoStruct):
37+
uin: int = proto_field(1)
38+
39+
40+
class PBGetFriendListRequest(ProtoStruct):
41+
friend_count: int = proto_field(2, default=300) # paging get num
42+
f4: int = proto_field(4, default=0)
43+
next_uin: Optional[GetFriendListUin] = proto_field(5, default=None)
44+
f6: int = proto_field(6, default=1)
45+
f7: int = proto_field(7, default=2147483647) # MaxValue
46+
body: List[GetFriendBody] = proto_field(
47+
10001,
48+
default=[
49+
GetFriendBody(type=1, f2=GetFriendNumbers(f1=[103, 102, 20002, 27394])),
50+
GetFriendBody(type=4, f2=GetFriendNumbers(f1=[100, 101, 102])),
51+
],
52+
)
53+
f10002: List[int] = proto_field(10002, default=[13578, 13579, 13573, 13572, 13568])
54+
f10003: int = proto_field(10003, default=4051)
55+
"""
56+
* GetFriendNumbers里是要拿到的东西
57+
* 102:个性签名
58+
* 103:备注
59+
* 20002:昵称
60+
* 27394:QID
61+
"""
62+
63+
64+
class GetFriendListRsp(ProtoStruct):
65+
next: Optional[GetFriendListUin] = proto_field(2, default=None)
66+
display_friend_count: int = proto_field(3)
67+
timestamp: int = proto_field(6)
68+
self_uin: int = proto_field(7)
69+
friend_list: List[FriendInfo] = proto_field(101)
70+
71+
72+
def propertys(properties: Union[List[FriendProperty], None]):
73+
if properties is None:
74+
return {}
75+
prop_dict = dict((prop.code, prop.value) for prop in properties)
76+
return prop_dict

0 commit comments

Comments
 (0)