Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion lagrange/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
from lagrange.pb.message.msg_push import MsgPushBody
from lagrange.pb.message.send import SendMsgRsp
from lagrange.pb.service.comm import SendNudge
from lagrange.pb.service.friend import (
GetFriendListRsp,
GetFriendListUin,
PBGetFriendListRequest,
propertys,
)
from lagrange.pb.service.group import (
FetchGroupResponse,
GetGrpMsgRsp,
Expand Down Expand Up @@ -58,7 +64,7 @@
from .message.elems import Audio, Image
from .message.encoder import build_message
from .message.types import Element
from .models import UserInfo
from .models import UserInfo, BotFriend
from .server_push import PushDeliver, bind_services
from .wtlogin.sso import SSOPacket

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

async def get_friend_list(self):
nextuin_cache: List[GetFriendListUin] = []
rsp: List[BotFriend] = []
frist_send = GetFriendListRsp.decode(
(await self.send_oidb_svc(0xFD4, 1, PBGetFriendListRequest().encode())).data
)
properties: Optional[dict] = None
if frist_send.next:
nextuin_cache.append(frist_send.next)
for raw in frist_send.friend_list:
for j in raw.additional:
if j.type == 1:
properties = propertys(j.layer1.properties)
if properties is not None:
rsp.append(
BotFriend(
raw.uin,
raw.uid,
properties.get(20002),
properties.get(103),
properties.get(102),
properties.get(27394),
)
)

while nextuin_cache:
next = GetFriendListRsp.decode(
(
await self.send_oidb_svc(
0xFD4, 1, PBGetFriendListRequest().encode()
)
).data
)
for raw in next.friend_list:
for j in raw.additional:
properties = propertys(j.layer1.properties)
if properties is not None:
rsp.append(
BotFriend(
raw.uin,
raw.uid,
properties.get(20002),
properties.get(103),
properties.get(102),
properties.get(27394),
)
)
if next.next:
nextuin_cache.append(next)

return rsp

async def recall_grp_msg(self, grp_id: int, seq: int):
payload = await self.send_uni_packet(
"trpc.msg.msg_svc.MsgService.SsoGroupRecallMsg",
Expand Down
11 changes: 11 additions & 0 deletions lagrange/client/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from dataclasses import dataclass
from datetime import datetime
from enum import IntEnum
from typing import Optional
from lagrange.pb.service.group import GetInfoRspBody


Expand Down Expand Up @@ -65,3 +66,13 @@ def from_pb(cls, pb: GetInfoRspBody) -> "UserInfo":
else:
pass
return rsp


@dataclass
class BotFriend:
uin: int
uid: Optional[str] = None
nickname: Optional[str] = None
remarks: Optional[str] = None
personal_sign: Optional[str] = None
qid: Optional[str] = None
76 changes: 76 additions & 0 deletions lagrange/pb/service/friend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from typing import List, Optional, Union

from lagrange.utils.binary.protobuf import ProtoStruct, proto_field


class FriendProperty(ProtoStruct):
code: int = proto_field(1)
value: Optional[str] = proto_field(2, default=None)


class FriendLayer1(ProtoStruct):
properties: List[FriendProperty] = proto_field(2, default=None)


class FriendAdditional(ProtoStruct):
type: int = proto_field(1)
layer1: FriendLayer1 = proto_field(2)


class FriendInfo(ProtoStruct):
uid: str = proto_field(1)
custom_group: Optional[int] = proto_field(2, default=None)
uin: int = proto_field(3)
additional: List[FriendAdditional] = proto_field(10001)


class GetFriendNumbers(ProtoStruct):
f1: List[int] = proto_field(1)


class GetFriendBody(ProtoStruct):
type: int = proto_field(1)
f2: GetFriendNumbers = proto_field(2)


class GetFriendListUin(ProtoStruct):
uin: int = proto_field(1)


class PBGetFriendListRequest(ProtoStruct):
friend_count: int = proto_field(2, default=300) # paging get num
f4: int = proto_field(4, default=0)
next_uin: Optional[GetFriendListUin] = proto_field(5, default=None)
f6: int = proto_field(6, default=1)
f7: int = proto_field(7, default=2147483647) # MaxValue
body: List[GetFriendBody] = proto_field(
10001,
default=[
GetFriendBody(type=1, f2=GetFriendNumbers(f1=[103, 102, 20002, 27394])),
GetFriendBody(type=4, f2=GetFriendNumbers(f1=[100, 101, 102])),
],
)
f10002: List[int] = proto_field(10002, default=[13578, 13579, 13573, 13572, 13568])
f10003: int = proto_field(10003, default=4051)
"""
* GetFriendNumbers里是要拿到的东西
* 102:个性签名
* 103:备注
* 20002:昵称
* 27394:QID
"""


class GetFriendListRsp(ProtoStruct):
next: Optional[GetFriendListUin] = proto_field(2, default=None)
display_friend_count: int = proto_field(3)
timestamp: int = proto_field(6)
self_uin: int = proto_field(7)
friend_list: List[FriendInfo] = proto_field(101)


def propertys(properties: Union[List[FriendProperty], None]):
if properties is None:
return {}
prop_dict = dict((prop.code, prop.value) for prop in properties)
return prop_dict