Skip to content

Commit 8ee0434

Browse files
committed
feat(app): use custom appinfo
1 parent 48b3d9c commit 8ee0434

File tree

3 files changed

+74
-14
lines changed

3 files changed

+74
-14
lines changed

lagrange/__init__.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
from typing import Literal, Optional
1+
import json
2+
from typing import Optional
3+
4+
from lagrange.info import AppInfo
5+
from typing_extensions import Literal
26
import asyncio
37

48
from .client.client import Client as Client
@@ -18,17 +22,19 @@ class Lagrange:
1822
def __init__(
1923
self,
2024
uin: int,
21-
protocol: Literal["linux", "macos", "windows"] = "linux",
25+
protocol: Literal["linux", "macos", "windows", "custom"] = "linux",
2226
sign_url: Optional[str] = None,
2327
device_info_path="./device.json",
2428
signinfo_path="./sig.bin",
29+
custom_protocol_path="./protocol.json",
2530
):
2631
self.im = InfoManager(uin, device_info_path, signinfo_path)
2732
self.uin = uin
28-
self.info = app_list[protocol]
2933
self.sign = sign_provider(sign_url) if sign_url else None
3034
self.events = {}
3135
self.log = log
36+
self._protocol = protocol
37+
self._protocol_path = custom_protocol_path
3238

3339
def subscribe(self, event, handler):
3440
self.events[event] = handler
@@ -42,10 +48,19 @@ async def login(self, client: Client):
4248
return await client.login()
4349

4450
async def run(self):
51+
if self._protocol == "custom":
52+
log.root.debug("load custom protocol from %s" % self._protocol_path)
53+
with open(self._protocol_path, "r") as f:
54+
proto = json.loads(f.read())
55+
app_info = AppInfo.load_custom(proto)
56+
else:
57+
app_info = app_list[self._protocol]
58+
log.root.info(f"AppInfo: platform={app_info.os}, ver={app_info.build_version}({app_info.sub_app_id})")
59+
4560
with self.im as im:
4661
self.client = Client(
4762
self.uin,
48-
self.info,
63+
app_info,
4964
im.device,
5065
im.sig_info,
5166
self.sign,

lagrange/client/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ async def _send_msg_raw(self, pb: dict, *, grp_id=0, uid="") -> SendMsgRsp:
191191
sendto[1] = {2: uid}
192192
elif grp_id: # grp
193193
sendto[2] = {1: grp_id}
194-
elif uid and grp_id: # temp msg, untest
194+
elif uid and grp_id: # temp msg, untested
195195
assert uid or grp_id, "uid and grp_id"
196196
sendto[3] = {1: grp_id, 2: uid}
197197
else:

lagrange/info/app.py

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,47 @@
1+
import re
12
from dataclasses import dataclass
2-
from typing import TypedDict
3+
from typing import TypedDict, TypeVar, Union
34

45
from .serialize import JsonSerializer
56

67

8+
_T = TypeVar('_T', bound=dict[str, Union[int, str]])
9+
_trans_map = {
10+
"SsoVersion": "pt_os_version",
11+
"WtLoginSdk": "wtlogin_sdk",
12+
"AppIdQrCode": "app_id_qrcode",
13+
"MainSigMap": "main_sigmap",
14+
"SubSigMap": "sub_sigmap",
15+
}
16+
17+
def _translate_appinfo(s: _T) -> _T:
18+
out: _T = {}
19+
for k, v in s.items():
20+
if k in _trans_map:
21+
out[_trans_map[k]] = v
22+
else:
23+
k = re.sub(
24+
r'([A-Z])([^A-Z]+)',
25+
'_\g<0>',
26+
k
27+
).lstrip("_").lower()
28+
out[k] = v
29+
return out
30+
31+
732
@dataclass
833
class AppInfo(JsonSerializer):
934
os: str
1035
kernel: str
1136
vendor_os: str
1237

1338
current_version: str
14-
build_version: int
39+
# build_version: int
1540
misc_bitmap: int
1641
pt_version: str
1742
pt_os_version: int
1843
package_name: str
1944
wtlogin_sdk: str
20-
package_sign: str
2145
app_id: int
2246
sub_app_id: int
2347
app_id_qrcode: int
@@ -26,6 +50,27 @@ class AppInfo(JsonSerializer):
2650
sub_sigmap: int
2751
nt_login_type: int
2852

53+
@property
54+
def build_version(self) -> int:
55+
return int(self.current_version.split("-")[1])
56+
57+
@property
58+
def package_sign(self) -> str:
59+
# QUA?
60+
if self.os == "Windows":
61+
kernel = "WIN"
62+
elif self.os == "Linux":
63+
kernel = "LNX"
64+
elif self.os == "Mac":
65+
kernel = "MAC"
66+
else:
67+
raise NotImplementedError(self.os)
68+
return f"V1_{kernel}_NQ_{self.current_version}_RDM_B"
69+
70+
@classmethod
71+
def load_custom(cls, d: _T) -> "AppInfo":
72+
return cls(**_translate_appinfo(d))
73+
2974

3075
class AppInfoDict(TypedDict):
3176
linux: AppInfo
@@ -39,13 +84,13 @@ class AppInfoDict(TypedDict):
3984
kernel="Linux",
4085
vendor_os="linux",
4186
current_version="3.2.10-25765",
42-
build_version=25765,
87+
# build_version=25765,
4388
misc_bitmap=32764,
4489
pt_version="2.0.0",
4590
pt_os_version=19,
4691
package_name="com.tencent.qq",
4792
wtlogin_sdk="nt.wtlogin.0.0.1",
48-
package_sign="V1_LNX_NQ_3.1.2-13107_RDM_B",
93+
# package_sign="V1_LNX_NQ_3.1.2-13107_RDM_B",
4994
app_id=1600001615,
5095
sub_app_id=537234773,
5196
app_id_qrcode=13697054,
@@ -59,13 +104,13 @@ class AppInfoDict(TypedDict):
59104
kernel="Darwin",
60105
vendor_os="mac",
61106
current_version="6.9.20-17153",
62-
build_version=17153,
107+
# build_version=17153,
63108
misc_bitmap=32764,
64109
pt_version="2.0.0",
65110
pt_os_version=23,
66111
package_name="com.tencent.qq",
67112
wtlogin_sdk="nt.wtlogin.0.0.1",
68-
package_sign="V1_MAC_NQ_6.9.20-17153_RDM_B",
113+
# package_sign="V1_MAC_NQ_6.9.20-17153_RDM_B",
69114
app_id=1600001602,
70115
sub_app_id=537162356,
71116
app_id_qrcode=537162356,
@@ -79,13 +124,13 @@ class AppInfoDict(TypedDict):
79124
kernel="Windows_NT",
80125
vendor_os="win32",
81126
current_version="9.9.2-15962",
82-
build_version=15962,
127+
# build_version=15962,
83128
pt_version="2.0.0",
84129
misc_bitmap=32764,
85130
pt_os_version=23,
86131
package_name="com.tencent.qq",
87132
wtlogin_sdk="nt.wtlogin.0.0.1",
88-
package_sign="V1_WIN_NQ_9.9.2-15962_RDM_B",
133+
# package_sign="V1_WIN_NQ_9.9.2-15962_RDM_B",
89134
app_id=1600001604,
90135
sub_app_id=537138217,
91136
app_id_qrcode=537138217,

0 commit comments

Comments
 (0)