├── .gitignore
├── CreateKey2.1.exe
├── LICENSE
├── PyWeChatSpy
├── 1660944441
│ └── WeChatSpy3.0.dll
├── SpyK.exe
├── __init__.py
├── command.py
├── games
│ ├── __init__.py
│ └── truth_or_dare.py
├── proto
│ ├── spy_pb2.py
│ └── wx_pb2.py
├── service
│ ├── API.md
│ ├── __init__.py
│ ├── app.py
│ └── config.py
├── spy.py
└── ui
│ ├── __init__.py
│ ├── profilephotos
│ └── default.png
│ └── ui.py
├── README.md
├── UI.py
├── client_example.py
├── example.py
├── example_rpc_client.py
├── example_rpc_server.py
├── images
├── 1.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
├── 5.jpg
├── 6.jpg
├── 7.jpg
├── bqstz.jpg
└── e.gif
├── pai1pai.py
├── requirements.txt
├── rpc_client_tools.py
├── rpc_server_tools.py
├── service_example.py
└── ui_example.py
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | .idea
3 | dist
4 | PyWeChatSpy.egg-info
5 | *.log
6 | *.xor
7 | *.toml
8 | qrcode.png
9 | venv
10 | *.jpg
--------------------------------------------------------------------------------
/CreateKey2.1.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/CreateKey2.1.exe
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [2020] [veikai]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/PyWeChatSpy/1660944441/WeChatSpy3.0.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/PyWeChatSpy/1660944441/WeChatSpy3.0.dll
--------------------------------------------------------------------------------
/PyWeChatSpy/SpyK.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/PyWeChatSpy/SpyK.exe
--------------------------------------------------------------------------------
/PyWeChatSpy/__init__.py:
--------------------------------------------------------------------------------
1 | from .spy import WeChatSpy
2 | # ,-.----.
3 | # \ / \ .---. ,----.. ,---, ___ .--.--.
4 | # | : \ /. ./| / / \,--.' | ,--.'|_ / / '.,-.----.
5 | # | | .\ : .--'. ' ; | : | | : | | :,'| : /`. /\ / \
6 | # . : |: | /__./ \ : | . | ;. : : : : : ' :; | |--` | : |
7 | # | | \ : .--,.--'. ' \' . ,---. . ; /--`: | |,--. ,--.--. .;__,' / | : ;_ | | .\ : .--,
8 | # | : . / /_ .//___/ \ | ' ' / \; | ; | : ' |/ \| | | \ \ `.. : |: | /_ ./|
9 | # ; | |`-, ' , ' ; \ \; :/ / | : | | | /' .--. .-. :__,'| : `----. | | \ :, ' , ' :
10 | # | | ; /___/ \: |\ ; ` . ' / . | '___' : | | |\__\/: . . ' : |__ __ \ \ | : . /___/ \: |
11 | # : ' | . \ ' | . \ .\ ' ; /' ; : .'| | ' | :," .--.; | | | '.'|/ /`--' : |`-'. \ ' |
12 | # : : : \ ; : \ \ ' \ ' | / ' | '/ | : :_:,/ / ,. | ; : '--'. /: : : \ ; :
13 | # | | : \ \ ; : ' |--"| : | : /| | ,' ; : .' \| , / `--'---' | | : \ \ ;
14 | # `---'.| : \ \ \ \ ; \ \ / \ \ .' `--'' | , .-./ ---`-' `---'.| : \ \
15 | # `---` \ ' ; '---" `----' `---` `--`---' `---` \ ' ;
16 | # `--` `--`
17 | WECHAT_SUPPORTED = ["3.0.0.57"]
18 |
19 | __version__ = "3.1.11.0"
20 |
--------------------------------------------------------------------------------
/PyWeChatSpy/command.py:
--------------------------------------------------------------------------------
1 | PROFESSIONAL_KEY = 9527 # 系统设置
2 | WECHAT_CONNECTED = 100 # socket连接
3 | HEART_BEAT = 101 # 心跳
4 | WECHAT_DISCONNECT = 102 # socket断开
5 | WECHAT_LOGIN = 200 # 微信登录
6 | WECHAT_LOGOUT = 201 # 微信登出
7 | CHAT_MESSAGE = 202 # 聊天消息
8 | GROUP_MEMBER_DETAILS = 203 # 群成员详情
9 | GROUP_MEMBER_EVENT = 204 # 群成员变动
10 | GET_ACCOUNT_DETAILS = 300 # 账号详情
11 | GET_CONTACTS_LIST = 301 # 联系人列表
12 | GET_CONTACT_DETAILS = 302 # 联系人详情
13 | SEND_TEXT = 303
14 | SEND_FILE = 304
15 | USER_LOGOUT = 305
16 | SEND_ANNOUNCEMENT = 306
17 | ACCEPT_NEW_CONTACT = 307
18 | SET_REMARK = 308
19 | SHARE_CHATROOM = 309
20 | REMOVE_CHATROOM_MEMBER = 310
21 | REMOVE_CONTACT = 311
22 | SEND_MINI_PROGRAM = 312
23 | SEND_LINK_CARD = 313
24 | DECRYPT_IMAGE = 314
25 | CREATE_CHATROOM = 315
26 | SET_CHATROOM_NAME = 316
27 | GET_CONTACT_STATUS = 317
28 | GET_LOGIN_QRCODE = 318
29 | SEND_CARD = 319
30 | GET_GROUP_ENTER_URL = 320
31 | ACCOUNT_DETAILS = 400
32 | CONTACTS_LIST = 401
33 | CONTACT_DETAILS = 402
34 | CREATE_GROUP_CALLBACK = 403
35 | LOGIN_QRCODE = 404
36 | GROUP_ENTER_URL = 405
37 | SEND_TEXT_CALLBACK = 406
38 | SEND_XML_CALLBACK = 407
39 | SEND_IMAGE_CALLBACK = 408
40 |
--------------------------------------------------------------------------------
/PyWeChatSpy/games/__init__.py:
--------------------------------------------------------------------------------
1 | from .truth_or_dare import TruthOrDare
2 |
--------------------------------------------------------------------------------
/PyWeChatSpy/games/truth_or_dare.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 | from ..command import CHAT_MESSAGE, CONTACT_DETAILS
3 | from ..proto import spy_pb2
4 | from ..spy import WeChatSpy
5 | from lxml import etree
6 |
7 |
8 | class TruthOrDare:
9 | def __init__(self, spy: WeChatSpy):
10 | self.spy = spy
11 | self.admin = None
12 | self.group = None
13 | self.group_member = dict()
14 | self.count = 0
15 | self.records = []
16 | self.record = dict()
17 | self.ask = []
18 | self.answer = []
19 |
20 | def game(self, func):
21 | @wraps(func)
22 | def wrapper(data):
23 | if data.type == CHAT_MESSAGE:
24 | chat_message = spy_pb2.ChatMessage()
25 | chat_message.ParseFromString(data.bytes)
26 | for message in chat_message.message:
27 | _type = message.type # 消息类型 1.文本|3.图片...自行探索
28 | _from = message.wxidFrom.str # 消息发送方
29 | _to = message.wxidTo.str # 消息接收方
30 | # if _to == "filehelper":
31 | # print(message)
32 | content = message.content.str # 消息内容
33 | _from_group_member = ""
34 | if _from.endswith("@chatroom"): # 群聊消息
35 | _from_group_member = message.content.str.split(':\n', 1)[0] # 群内发言人
36 | content = message.content.str.split(':\n', 1)[-1] # 群聊消息内容
37 | if _type == 1: # 文本消息
38 | if not self.group and content == "真心话大冒险":
39 | self.admin = _from_group_member
40 | if _from_group_member == "":
41 | self.group = _to
42 | else:
43 | self.group = _from
44 | self.spy.get_contact_details(self.group)
45 | elif self.admin == _from_group_member:
46 | if content == "开始":
47 | self.count += 1
48 | self.record.clear()
49 | self.ask.clear()
50 | self.answer.clear()
51 | self.spy.send_text(self.group, f"第{self.count}轮游戏开始,请掷骰子")
52 | elif content == "结算":
53 | values = self.record.values()
54 | _max = max(values)
55 | _min = min(values)
56 | for k, v in self.record.items():
57 | if v == _max:
58 | self.ask.append(k)
59 | elif v == _min:
60 | self.answer.append(k)
61 | ask = answer = ""
62 | for w in self.ask:
63 | ask += f"{self.group_member[w]} "
64 | # w_ask = ",".join(self.ask)
65 | for w in self.answer:
66 | answer = f"{self.group_member[w]} "
67 | # w_answer = ",".join(self.answer)
68 | message = f"第{self.count}轮游戏结算,请{ask}向{answer}提问"
69 | self.spy.send_text(self.group, message)
70 | elif _type == 47:
71 | if _from == self.group or _to == self.group:
72 | xml = etree.XML(content)
73 | game_type = xml.xpath("/msg/gameext/@type")[0]
74 | if game_type == "2": # 骰子游戏
75 | fromusername = xml.xpath("/msg/emoji/@fromusername")[0]
76 | value = int(xml.xpath("/msg/gameext/@content")[0]) - 3
77 | if not self.record.get(fromusername):
78 | self.record[fromusername] = value
79 | elif data.type == CONTACT_DETAILS:
80 | contact_details_list = spy_pb2.Contacts()
81 | contact_details_list.ParseFromString(data.bytes)
82 | for contact_details in contact_details_list.contactDetails: # 遍历联系人详情
83 | wxid = contact_details.wxid.str # 联系人wxid
84 | if wxid == self.group:
85 | # nickname = contact_details.nickname.str # 联系人昵称
86 | # remark = contact_details.remark.str # 联系人备注
87 | group_member_list = contact_details.groupMemberList # 群成员列表
88 | member_count = group_member_list.memberCount # 群成员数量
89 | for group_member in group_member_list.groupMember: # 遍历群成员
90 | member_wxid = group_member.wxid # 群成员wxid
91 | member_nickname = group_member.nickname # 群成员昵称
92 | self.group_member[member_wxid] = member_nickname
93 | self.spy.send_text(
94 | self.group, f"游戏成员[{member_count}]加载完成,游戏准备就绪,请管理员发送'开始'开始游戏,发送'结算'结算此轮游戏")
95 | func(data)
96 | return wrapper
97 |
98 |
--------------------------------------------------------------------------------
/PyWeChatSpy/proto/spy_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: spy.proto
4 |
5 | from google.protobuf import descriptor as _descriptor
6 | from google.protobuf import message as _message
7 | from google.protobuf import reflection as _reflection
8 | from google.protobuf import symbol_database as _symbol_database
9 | # @@protoc_insertion_point(imports)
10 |
11 | _sym_db = _symbol_database.Default()
12 |
13 |
14 | # import wx_pb2 as wx__pb2
15 | from . import wx_pb2 as wx__pb2
16 |
17 |
18 | DESCRIPTOR = _descriptor.FileDescriptor(
19 | name='spy.proto',
20 | package='spy',
21 | syntax='proto3',
22 | serialized_options=None,
23 | serialized_pb=b'\n\tspy.proto\x12\x03spy\x1a\x08wx.proto\"/\n\x0b\x43hatMessage\x12 \n\x07message\x18\x01 \x03(\x0b\x32\x0f.wx.ChatMessage\"\xeb\x01\n\x0e\x41\x63\x63ountDetails\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\x10\n\x08nickname\x18\x02 \x01(\t\x12\x10\n\x08wechatid\x18\x03 \x01(\t\x12\x11\n\tautograph\x18\x04 \x01(\t\x12\x16\n\x0eprofilePhotoHD\x18\x05 \x01(\t\x12\x14\n\x0cprofilePhoto\x18\x06 \x01(\t\x12\r\n\x05phone\x18\x07 \x01(\t\x12\r\n\x05\x65mail\x18\x08 \x01(\t\x12\n\n\x02qq\x18\t \x01(\x03\x12\x0b\n\x03sex\x18\n \x01(\x05\x12\x0c\n\x04\x63ity\x18\x0b \x01(\t\x12\x10\n\x08province\x18\x0c \x01(\t\x12\x0f\n\x07\x63ountry\x18\r \x01(\t\"6\n\x08\x43ontacts\x12*\n\x0e\x63ontactDetails\x18\x01 \x03(\x0b\x32\x12.wx.ContactDetails\"9\n\x0bTextMessage\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\x0e\n\x06wxidAt\x18\x02 \x01(\t\x12\x0c\n\x04text\x18\x03 \x01(\t\"-\n\x0b\x46ileMessage\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\x10\n\x08\x66ilePath\x18\x02 \x01(\t\"\xae\x01\n\nXmlMessage\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\r\n\x05title\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x65sc\x18\x03 \x01(\t\x12\r\n\x05\x61ppId\x18\x04 \x01(\t\x12\r\n\x05route\x18\x05 \x01(\t\x12\x0b\n\x03url\x18\x06 \x01(\t\x12\x11\n\timagePath\x18\x07 \x01(\t\x12\x10\n\x08username\x18\x08 \x01(\t\x12\x14\n\x0cweappiconurl\x18\t \x01(\t\x12\x0f\n\x07\x61ppname\x18\n \x01(\t\"=\n\x12\x43ontactApplication\x12\x17\n\x0f\x65ncryptusername\x18\x01 \x01(\t\x12\x0e\n\x06ticket\x18\x02 \x01(\t\"m\n\x08Response\x12\x0c\n\x04type\x18\x01 \x01(\x05\x12\r\n\x05\x62ytes\x18\x02 \x01(\x0c\x12\x0b\n\x03pid\x18\x03 \x01(\x05\x12\x0c\n\x04port\x18\x04 \x01(\x05\x12\n\n\x02id\x18\x05 \x01(\t\x12\x0c\n\x04\x63ode\x18\x06 \x01(\x05\x12\x0f\n\x07message\x18\x07 \x01(\t\"2\n\x07Request\x12\x0c\n\x04type\x18\x01 \x01(\x05\x12\r\n\x05\x62ytes\x18\x02 \x01(\x0c\x12\n\n\x02id\x18\x03 \x01(\t\"d\n\x13\x43reateGroupCallback\x12\x1e\n\x04wxid\x18\x01 \x01(\x0b\x32\x10.wx.WeChatString\x12-\n\nmemberData\x18\x02 \x03(\x0b\x32\x19.wx.CreateGroupMemberData\"l\n\x12GroupMemberDetails\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\x14\n\x0c\x64\x65tailsCount\x18\x02 \x01(\x05\x12\x32\n\x12groupMemberDetails\x18\x03 \x03(\x0b\x32\x16.wx.GroupMemberDetails\"E\n\x10GroupMemberEvent\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\x10\n\x08wxidJoin\x18\x02 \x03(\t\x12\x11\n\twxidLeave\x18\x03 \x03(\t\"6\n\x0bLoginQRCode\x12\x12\n\nqrcodeSize\x18\x01 \x01(\x05\x12\x13\n\x0bqrcodeBytes\x18\x02 \x01(\x0c\"\x1c\n\rGroupEnterUrl\x12\x0b\n\x03url\x18\x02 \x01(\tb\x06proto3'
24 | ,
25 | dependencies=[wx__pb2.DESCRIPTOR,])
26 |
27 |
28 |
29 |
30 | _CHATMESSAGE = _descriptor.Descriptor(
31 | name='ChatMessage',
32 | full_name='spy.ChatMessage',
33 | filename=None,
34 | file=DESCRIPTOR,
35 | containing_type=None,
36 | fields=[
37 | _descriptor.FieldDescriptor(
38 | name='message', full_name='spy.ChatMessage.message', index=0,
39 | number=1, type=11, cpp_type=10, label=3,
40 | has_default_value=False, default_value=[],
41 | message_type=None, enum_type=None, containing_type=None,
42 | is_extension=False, extension_scope=None,
43 | serialized_options=None, file=DESCRIPTOR),
44 | ],
45 | extensions=[
46 | ],
47 | nested_types=[],
48 | enum_types=[
49 | ],
50 | serialized_options=None,
51 | is_extendable=False,
52 | syntax='proto3',
53 | extension_ranges=[],
54 | oneofs=[
55 | ],
56 | serialized_start=28,
57 | serialized_end=75,
58 | )
59 |
60 |
61 | _ACCOUNTDETAILS = _descriptor.Descriptor(
62 | name='AccountDetails',
63 | full_name='spy.AccountDetails',
64 | filename=None,
65 | file=DESCRIPTOR,
66 | containing_type=None,
67 | fields=[
68 | _descriptor.FieldDescriptor(
69 | name='wxid', full_name='spy.AccountDetails.wxid', index=0,
70 | number=1, type=9, cpp_type=9, label=1,
71 | has_default_value=False, default_value=b"".decode('utf-8'),
72 | message_type=None, enum_type=None, containing_type=None,
73 | is_extension=False, extension_scope=None,
74 | serialized_options=None, file=DESCRIPTOR),
75 | _descriptor.FieldDescriptor(
76 | name='nickname', full_name='spy.AccountDetails.nickname', index=1,
77 | number=2, type=9, cpp_type=9, label=1,
78 | has_default_value=False, default_value=b"".decode('utf-8'),
79 | message_type=None, enum_type=None, containing_type=None,
80 | is_extension=False, extension_scope=None,
81 | serialized_options=None, file=DESCRIPTOR),
82 | _descriptor.FieldDescriptor(
83 | name='wechatid', full_name='spy.AccountDetails.wechatid', index=2,
84 | number=3, type=9, cpp_type=9, label=1,
85 | has_default_value=False, default_value=b"".decode('utf-8'),
86 | message_type=None, enum_type=None, containing_type=None,
87 | is_extension=False, extension_scope=None,
88 | serialized_options=None, file=DESCRIPTOR),
89 | _descriptor.FieldDescriptor(
90 | name='autograph', full_name='spy.AccountDetails.autograph', index=3,
91 | number=4, type=9, cpp_type=9, label=1,
92 | has_default_value=False, default_value=b"".decode('utf-8'),
93 | message_type=None, enum_type=None, containing_type=None,
94 | is_extension=False, extension_scope=None,
95 | serialized_options=None, file=DESCRIPTOR),
96 | _descriptor.FieldDescriptor(
97 | name='profilePhotoHD', full_name='spy.AccountDetails.profilePhotoHD', index=4,
98 | number=5, type=9, cpp_type=9, label=1,
99 | has_default_value=False, default_value=b"".decode('utf-8'),
100 | message_type=None, enum_type=None, containing_type=None,
101 | is_extension=False, extension_scope=None,
102 | serialized_options=None, file=DESCRIPTOR),
103 | _descriptor.FieldDescriptor(
104 | name='profilePhoto', full_name='spy.AccountDetails.profilePhoto', index=5,
105 | number=6, type=9, cpp_type=9, label=1,
106 | has_default_value=False, default_value=b"".decode('utf-8'),
107 | message_type=None, enum_type=None, containing_type=None,
108 | is_extension=False, extension_scope=None,
109 | serialized_options=None, file=DESCRIPTOR),
110 | _descriptor.FieldDescriptor(
111 | name='phone', full_name='spy.AccountDetails.phone', index=6,
112 | number=7, type=9, cpp_type=9, label=1,
113 | has_default_value=False, default_value=b"".decode('utf-8'),
114 | message_type=None, enum_type=None, containing_type=None,
115 | is_extension=False, extension_scope=None,
116 | serialized_options=None, file=DESCRIPTOR),
117 | _descriptor.FieldDescriptor(
118 | name='email', full_name='spy.AccountDetails.email', index=7,
119 | number=8, type=9, cpp_type=9, label=1,
120 | has_default_value=False, default_value=b"".decode('utf-8'),
121 | message_type=None, enum_type=None, containing_type=None,
122 | is_extension=False, extension_scope=None,
123 | serialized_options=None, file=DESCRIPTOR),
124 | _descriptor.FieldDescriptor(
125 | name='qq', full_name='spy.AccountDetails.qq', index=8,
126 | number=9, type=3, cpp_type=2, label=1,
127 | has_default_value=False, default_value=0,
128 | message_type=None, enum_type=None, containing_type=None,
129 | is_extension=False, extension_scope=None,
130 | serialized_options=None, file=DESCRIPTOR),
131 | _descriptor.FieldDescriptor(
132 | name='sex', full_name='spy.AccountDetails.sex', index=9,
133 | number=10, type=5, cpp_type=1, label=1,
134 | has_default_value=False, default_value=0,
135 | message_type=None, enum_type=None, containing_type=None,
136 | is_extension=False, extension_scope=None,
137 | serialized_options=None, file=DESCRIPTOR),
138 | _descriptor.FieldDescriptor(
139 | name='city', full_name='spy.AccountDetails.city', index=10,
140 | number=11, type=9, cpp_type=9, label=1,
141 | has_default_value=False, default_value=b"".decode('utf-8'),
142 | message_type=None, enum_type=None, containing_type=None,
143 | is_extension=False, extension_scope=None,
144 | serialized_options=None, file=DESCRIPTOR),
145 | _descriptor.FieldDescriptor(
146 | name='province', full_name='spy.AccountDetails.province', index=11,
147 | number=12, type=9, cpp_type=9, label=1,
148 | has_default_value=False, default_value=b"".decode('utf-8'),
149 | message_type=None, enum_type=None, containing_type=None,
150 | is_extension=False, extension_scope=None,
151 | serialized_options=None, file=DESCRIPTOR),
152 | _descriptor.FieldDescriptor(
153 | name='country', full_name='spy.AccountDetails.country', index=12,
154 | number=13, type=9, cpp_type=9, label=1,
155 | has_default_value=False, default_value=b"".decode('utf-8'),
156 | message_type=None, enum_type=None, containing_type=None,
157 | is_extension=False, extension_scope=None,
158 | serialized_options=None, file=DESCRIPTOR),
159 | ],
160 | extensions=[
161 | ],
162 | nested_types=[],
163 | enum_types=[
164 | ],
165 | serialized_options=None,
166 | is_extendable=False,
167 | syntax='proto3',
168 | extension_ranges=[],
169 | oneofs=[
170 | ],
171 | serialized_start=78,
172 | serialized_end=313,
173 | )
174 |
175 |
176 | _CONTACTS = _descriptor.Descriptor(
177 | name='Contacts',
178 | full_name='spy.Contacts',
179 | filename=None,
180 | file=DESCRIPTOR,
181 | containing_type=None,
182 | fields=[
183 | _descriptor.FieldDescriptor(
184 | name='contactDetails', full_name='spy.Contacts.contactDetails', index=0,
185 | number=1, type=11, cpp_type=10, label=3,
186 | has_default_value=False, default_value=[],
187 | message_type=None, enum_type=None, containing_type=None,
188 | is_extension=False, extension_scope=None,
189 | serialized_options=None, file=DESCRIPTOR),
190 | ],
191 | extensions=[
192 | ],
193 | nested_types=[],
194 | enum_types=[
195 | ],
196 | serialized_options=None,
197 | is_extendable=False,
198 | syntax='proto3',
199 | extension_ranges=[],
200 | oneofs=[
201 | ],
202 | serialized_start=315,
203 | serialized_end=369,
204 | )
205 |
206 |
207 | _TEXTMESSAGE = _descriptor.Descriptor(
208 | name='TextMessage',
209 | full_name='spy.TextMessage',
210 | filename=None,
211 | file=DESCRIPTOR,
212 | containing_type=None,
213 | fields=[
214 | _descriptor.FieldDescriptor(
215 | name='wxid', full_name='spy.TextMessage.wxid', index=0,
216 | number=1, type=9, cpp_type=9, label=1,
217 | has_default_value=False, default_value=b"".decode('utf-8'),
218 | message_type=None, enum_type=None, containing_type=None,
219 | is_extension=False, extension_scope=None,
220 | serialized_options=None, file=DESCRIPTOR),
221 | _descriptor.FieldDescriptor(
222 | name='wxidAt', full_name='spy.TextMessage.wxidAt', index=1,
223 | number=2, type=9, cpp_type=9, label=1,
224 | has_default_value=False, default_value=b"".decode('utf-8'),
225 | message_type=None, enum_type=None, containing_type=None,
226 | is_extension=False, extension_scope=None,
227 | serialized_options=None, file=DESCRIPTOR),
228 | _descriptor.FieldDescriptor(
229 | name='text', full_name='spy.TextMessage.text', index=2,
230 | number=3, type=9, cpp_type=9, label=1,
231 | has_default_value=False, default_value=b"".decode('utf-8'),
232 | message_type=None, enum_type=None, containing_type=None,
233 | is_extension=False, extension_scope=None,
234 | serialized_options=None, file=DESCRIPTOR),
235 | ],
236 | extensions=[
237 | ],
238 | nested_types=[],
239 | enum_types=[
240 | ],
241 | serialized_options=None,
242 | is_extendable=False,
243 | syntax='proto3',
244 | extension_ranges=[],
245 | oneofs=[
246 | ],
247 | serialized_start=371,
248 | serialized_end=428,
249 | )
250 |
251 |
252 | _FILEMESSAGE = _descriptor.Descriptor(
253 | name='FileMessage',
254 | full_name='spy.FileMessage',
255 | filename=None,
256 | file=DESCRIPTOR,
257 | containing_type=None,
258 | fields=[
259 | _descriptor.FieldDescriptor(
260 | name='wxid', full_name='spy.FileMessage.wxid', index=0,
261 | number=1, type=9, cpp_type=9, label=1,
262 | has_default_value=False, default_value=b"".decode('utf-8'),
263 | message_type=None, enum_type=None, containing_type=None,
264 | is_extension=False, extension_scope=None,
265 | serialized_options=None, file=DESCRIPTOR),
266 | _descriptor.FieldDescriptor(
267 | name='filePath', full_name='spy.FileMessage.filePath', index=1,
268 | number=2, type=9, cpp_type=9, label=1,
269 | has_default_value=False, default_value=b"".decode('utf-8'),
270 | message_type=None, enum_type=None, containing_type=None,
271 | is_extension=False, extension_scope=None,
272 | serialized_options=None, file=DESCRIPTOR),
273 | ],
274 | extensions=[
275 | ],
276 | nested_types=[],
277 | enum_types=[
278 | ],
279 | serialized_options=None,
280 | is_extendable=False,
281 | syntax='proto3',
282 | extension_ranges=[],
283 | oneofs=[
284 | ],
285 | serialized_start=430,
286 | serialized_end=475,
287 | )
288 |
289 |
290 | _XMLMESSAGE = _descriptor.Descriptor(
291 | name='XmlMessage',
292 | full_name='spy.XmlMessage',
293 | filename=None,
294 | file=DESCRIPTOR,
295 | containing_type=None,
296 | fields=[
297 | _descriptor.FieldDescriptor(
298 | name='wxid', full_name='spy.XmlMessage.wxid', index=0,
299 | number=1, type=9, cpp_type=9, label=1,
300 | has_default_value=False, default_value=b"".decode('utf-8'),
301 | message_type=None, enum_type=None, containing_type=None,
302 | is_extension=False, extension_scope=None,
303 | serialized_options=None, file=DESCRIPTOR),
304 | _descriptor.FieldDescriptor(
305 | name='title', full_name='spy.XmlMessage.title', index=1,
306 | number=2, type=9, cpp_type=9, label=1,
307 | has_default_value=False, default_value=b"".decode('utf-8'),
308 | message_type=None, enum_type=None, containing_type=None,
309 | is_extension=False, extension_scope=None,
310 | serialized_options=None, file=DESCRIPTOR),
311 | _descriptor.FieldDescriptor(
312 | name='desc', full_name='spy.XmlMessage.desc', index=2,
313 | number=3, type=9, cpp_type=9, label=1,
314 | has_default_value=False, default_value=b"".decode('utf-8'),
315 | message_type=None, enum_type=None, containing_type=None,
316 | is_extension=False, extension_scope=None,
317 | serialized_options=None, file=DESCRIPTOR),
318 | _descriptor.FieldDescriptor(
319 | name='appId', full_name='spy.XmlMessage.appId', index=3,
320 | number=4, type=9, cpp_type=9, label=1,
321 | has_default_value=False, default_value=b"".decode('utf-8'),
322 | message_type=None, enum_type=None, containing_type=None,
323 | is_extension=False, extension_scope=None,
324 | serialized_options=None, file=DESCRIPTOR),
325 | _descriptor.FieldDescriptor(
326 | name='route', full_name='spy.XmlMessage.route', index=4,
327 | number=5, type=9, cpp_type=9, label=1,
328 | has_default_value=False, default_value=b"".decode('utf-8'),
329 | message_type=None, enum_type=None, containing_type=None,
330 | is_extension=False, extension_scope=None,
331 | serialized_options=None, file=DESCRIPTOR),
332 | _descriptor.FieldDescriptor(
333 | name='url', full_name='spy.XmlMessage.url', index=5,
334 | number=6, type=9, cpp_type=9, label=1,
335 | has_default_value=False, default_value=b"".decode('utf-8'),
336 | message_type=None, enum_type=None, containing_type=None,
337 | is_extension=False, extension_scope=None,
338 | serialized_options=None, file=DESCRIPTOR),
339 | _descriptor.FieldDescriptor(
340 | name='imagePath', full_name='spy.XmlMessage.imagePath', index=6,
341 | number=7, type=9, cpp_type=9, label=1,
342 | has_default_value=False, default_value=b"".decode('utf-8'),
343 | message_type=None, enum_type=None, containing_type=None,
344 | is_extension=False, extension_scope=None,
345 | serialized_options=None, file=DESCRIPTOR),
346 | _descriptor.FieldDescriptor(
347 | name='username', full_name='spy.XmlMessage.username', index=7,
348 | number=8, type=9, cpp_type=9, label=1,
349 | has_default_value=False, default_value=b"".decode('utf-8'),
350 | message_type=None, enum_type=None, containing_type=None,
351 | is_extension=False, extension_scope=None,
352 | serialized_options=None, file=DESCRIPTOR),
353 | _descriptor.FieldDescriptor(
354 | name='weappiconurl', full_name='spy.XmlMessage.weappiconurl', index=8,
355 | number=9, type=9, cpp_type=9, label=1,
356 | has_default_value=False, default_value=b"".decode('utf-8'),
357 | message_type=None, enum_type=None, containing_type=None,
358 | is_extension=False, extension_scope=None,
359 | serialized_options=None, file=DESCRIPTOR),
360 | _descriptor.FieldDescriptor(
361 | name='appname', full_name='spy.XmlMessage.appname', index=9,
362 | number=10, type=9, cpp_type=9, label=1,
363 | has_default_value=False, default_value=b"".decode('utf-8'),
364 | message_type=None, enum_type=None, containing_type=None,
365 | is_extension=False, extension_scope=None,
366 | serialized_options=None, file=DESCRIPTOR),
367 | ],
368 | extensions=[
369 | ],
370 | nested_types=[],
371 | enum_types=[
372 | ],
373 | serialized_options=None,
374 | is_extendable=False,
375 | syntax='proto3',
376 | extension_ranges=[],
377 | oneofs=[
378 | ],
379 | serialized_start=478,
380 | serialized_end=652,
381 | )
382 |
383 |
384 | _CONTACTAPPLICATION = _descriptor.Descriptor(
385 | name='ContactApplication',
386 | full_name='spy.ContactApplication',
387 | filename=None,
388 | file=DESCRIPTOR,
389 | containing_type=None,
390 | fields=[
391 | _descriptor.FieldDescriptor(
392 | name='encryptusername', full_name='spy.ContactApplication.encryptusername', index=0,
393 | number=1, type=9, cpp_type=9, label=1,
394 | has_default_value=False, default_value=b"".decode('utf-8'),
395 | message_type=None, enum_type=None, containing_type=None,
396 | is_extension=False, extension_scope=None,
397 | serialized_options=None, file=DESCRIPTOR),
398 | _descriptor.FieldDescriptor(
399 | name='ticket', full_name='spy.ContactApplication.ticket', index=1,
400 | number=2, type=9, cpp_type=9, label=1,
401 | has_default_value=False, default_value=b"".decode('utf-8'),
402 | message_type=None, enum_type=None, containing_type=None,
403 | is_extension=False, extension_scope=None,
404 | serialized_options=None, file=DESCRIPTOR),
405 | ],
406 | extensions=[
407 | ],
408 | nested_types=[],
409 | enum_types=[
410 | ],
411 | serialized_options=None,
412 | is_extendable=False,
413 | syntax='proto3',
414 | extension_ranges=[],
415 | oneofs=[
416 | ],
417 | serialized_start=654,
418 | serialized_end=715,
419 | )
420 |
421 |
422 | _RESPONSE = _descriptor.Descriptor(
423 | name='Response',
424 | full_name='spy.Response',
425 | filename=None,
426 | file=DESCRIPTOR,
427 | containing_type=None,
428 | fields=[
429 | _descriptor.FieldDescriptor(
430 | name='type', full_name='spy.Response.type', index=0,
431 | number=1, type=5, cpp_type=1, label=1,
432 | has_default_value=False, default_value=0,
433 | message_type=None, enum_type=None, containing_type=None,
434 | is_extension=False, extension_scope=None,
435 | serialized_options=None, file=DESCRIPTOR),
436 | _descriptor.FieldDescriptor(
437 | name='bytes', full_name='spy.Response.bytes', index=1,
438 | number=2, type=12, cpp_type=9, label=1,
439 | has_default_value=False, default_value=b"",
440 | message_type=None, enum_type=None, containing_type=None,
441 | is_extension=False, extension_scope=None,
442 | serialized_options=None, file=DESCRIPTOR),
443 | _descriptor.FieldDescriptor(
444 | name='pid', full_name='spy.Response.pid', index=2,
445 | number=3, type=5, cpp_type=1, label=1,
446 | has_default_value=False, default_value=0,
447 | message_type=None, enum_type=None, containing_type=None,
448 | is_extension=False, extension_scope=None,
449 | serialized_options=None, file=DESCRIPTOR),
450 | _descriptor.FieldDescriptor(
451 | name='port', full_name='spy.Response.port', index=3,
452 | number=4, type=5, cpp_type=1, label=1,
453 | has_default_value=False, default_value=0,
454 | message_type=None, enum_type=None, containing_type=None,
455 | is_extension=False, extension_scope=None,
456 | serialized_options=None, file=DESCRIPTOR),
457 | _descriptor.FieldDescriptor(
458 | name='id', full_name='spy.Response.id', index=4,
459 | number=5, type=9, cpp_type=9, label=1,
460 | has_default_value=False, default_value=b"".decode('utf-8'),
461 | message_type=None, enum_type=None, containing_type=None,
462 | is_extension=False, extension_scope=None,
463 | serialized_options=None, file=DESCRIPTOR),
464 | _descriptor.FieldDescriptor(
465 | name='code', full_name='spy.Response.code', index=5,
466 | number=6, type=5, cpp_type=1, label=1,
467 | has_default_value=False, default_value=0,
468 | message_type=None, enum_type=None, containing_type=None,
469 | is_extension=False, extension_scope=None,
470 | serialized_options=None, file=DESCRIPTOR),
471 | _descriptor.FieldDescriptor(
472 | name='message', full_name='spy.Response.message', index=6,
473 | number=7, type=9, cpp_type=9, label=1,
474 | has_default_value=False, default_value=b"".decode('utf-8'),
475 | message_type=None, enum_type=None, containing_type=None,
476 | is_extension=False, extension_scope=None,
477 | serialized_options=None, file=DESCRIPTOR),
478 | ],
479 | extensions=[
480 | ],
481 | nested_types=[],
482 | enum_types=[
483 | ],
484 | serialized_options=None,
485 | is_extendable=False,
486 | syntax='proto3',
487 | extension_ranges=[],
488 | oneofs=[
489 | ],
490 | serialized_start=717,
491 | serialized_end=826,
492 | )
493 |
494 |
495 | _REQUEST = _descriptor.Descriptor(
496 | name='Request',
497 | full_name='spy.Request',
498 | filename=None,
499 | file=DESCRIPTOR,
500 | containing_type=None,
501 | fields=[
502 | _descriptor.FieldDescriptor(
503 | name='type', full_name='spy.Request.type', index=0,
504 | number=1, type=5, cpp_type=1, label=1,
505 | has_default_value=False, default_value=0,
506 | message_type=None, enum_type=None, containing_type=None,
507 | is_extension=False, extension_scope=None,
508 | serialized_options=None, file=DESCRIPTOR),
509 | _descriptor.FieldDescriptor(
510 | name='bytes', full_name='spy.Request.bytes', index=1,
511 | number=2, type=12, cpp_type=9, label=1,
512 | has_default_value=False, default_value=b"",
513 | message_type=None, enum_type=None, containing_type=None,
514 | is_extension=False, extension_scope=None,
515 | serialized_options=None, file=DESCRIPTOR),
516 | _descriptor.FieldDescriptor(
517 | name='id', full_name='spy.Request.id', index=2,
518 | number=3, type=9, cpp_type=9, label=1,
519 | has_default_value=False, default_value=b"".decode('utf-8'),
520 | message_type=None, enum_type=None, containing_type=None,
521 | is_extension=False, extension_scope=None,
522 | serialized_options=None, file=DESCRIPTOR),
523 | ],
524 | extensions=[
525 | ],
526 | nested_types=[],
527 | enum_types=[
528 | ],
529 | serialized_options=None,
530 | is_extendable=False,
531 | syntax='proto3',
532 | extension_ranges=[],
533 | oneofs=[
534 | ],
535 | serialized_start=828,
536 | serialized_end=878,
537 | )
538 |
539 |
540 | _CREATEGROUPCALLBACK = _descriptor.Descriptor(
541 | name='CreateGroupCallback',
542 | full_name='spy.CreateGroupCallback',
543 | filename=None,
544 | file=DESCRIPTOR,
545 | containing_type=None,
546 | fields=[
547 | _descriptor.FieldDescriptor(
548 | name='wxid', full_name='spy.CreateGroupCallback.wxid', index=0,
549 | number=1, type=11, cpp_type=10, label=1,
550 | has_default_value=False, default_value=None,
551 | message_type=None, enum_type=None, containing_type=None,
552 | is_extension=False, extension_scope=None,
553 | serialized_options=None, file=DESCRIPTOR),
554 | _descriptor.FieldDescriptor(
555 | name='memberData', full_name='spy.CreateGroupCallback.memberData', index=1,
556 | number=2, type=11, cpp_type=10, label=3,
557 | has_default_value=False, default_value=[],
558 | message_type=None, enum_type=None, containing_type=None,
559 | is_extension=False, extension_scope=None,
560 | serialized_options=None, file=DESCRIPTOR),
561 | ],
562 | extensions=[
563 | ],
564 | nested_types=[],
565 | enum_types=[
566 | ],
567 | serialized_options=None,
568 | is_extendable=False,
569 | syntax='proto3',
570 | extension_ranges=[],
571 | oneofs=[
572 | ],
573 | serialized_start=880,
574 | serialized_end=980,
575 | )
576 |
577 |
578 | _GROUPMEMBERDETAILS = _descriptor.Descriptor(
579 | name='GroupMemberDetails',
580 | full_name='spy.GroupMemberDetails',
581 | filename=None,
582 | file=DESCRIPTOR,
583 | containing_type=None,
584 | fields=[
585 | _descriptor.FieldDescriptor(
586 | name='wxid', full_name='spy.GroupMemberDetails.wxid', index=0,
587 | number=1, type=9, cpp_type=9, label=1,
588 | has_default_value=False, default_value=b"".decode('utf-8'),
589 | message_type=None, enum_type=None, containing_type=None,
590 | is_extension=False, extension_scope=None,
591 | serialized_options=None, file=DESCRIPTOR),
592 | _descriptor.FieldDescriptor(
593 | name='detailsCount', full_name='spy.GroupMemberDetails.detailsCount', index=1,
594 | number=2, type=5, cpp_type=1, label=1,
595 | has_default_value=False, default_value=0,
596 | message_type=None, enum_type=None, containing_type=None,
597 | is_extension=False, extension_scope=None,
598 | serialized_options=None, file=DESCRIPTOR),
599 | _descriptor.FieldDescriptor(
600 | name='groupMemberDetails', full_name='spy.GroupMemberDetails.groupMemberDetails', index=2,
601 | number=3, type=11, cpp_type=10, label=3,
602 | has_default_value=False, default_value=[],
603 | message_type=None, enum_type=None, containing_type=None,
604 | is_extension=False, extension_scope=None,
605 | serialized_options=None, file=DESCRIPTOR),
606 | ],
607 | extensions=[
608 | ],
609 | nested_types=[],
610 | enum_types=[
611 | ],
612 | serialized_options=None,
613 | is_extendable=False,
614 | syntax='proto3',
615 | extension_ranges=[],
616 | oneofs=[
617 | ],
618 | serialized_start=982,
619 | serialized_end=1090,
620 | )
621 |
622 |
623 | _GROUPMEMBEREVENT = _descriptor.Descriptor(
624 | name='GroupMemberEvent',
625 | full_name='spy.GroupMemberEvent',
626 | filename=None,
627 | file=DESCRIPTOR,
628 | containing_type=None,
629 | fields=[
630 | _descriptor.FieldDescriptor(
631 | name='wxid', full_name='spy.GroupMemberEvent.wxid', index=0,
632 | number=1, type=9, cpp_type=9, label=1,
633 | has_default_value=False, default_value=b"".decode('utf-8'),
634 | message_type=None, enum_type=None, containing_type=None,
635 | is_extension=False, extension_scope=None,
636 | serialized_options=None, file=DESCRIPTOR),
637 | _descriptor.FieldDescriptor(
638 | name='wxidJoin', full_name='spy.GroupMemberEvent.wxidJoin', index=1,
639 | number=2, type=9, cpp_type=9, label=3,
640 | has_default_value=False, default_value=[],
641 | message_type=None, enum_type=None, containing_type=None,
642 | is_extension=False, extension_scope=None,
643 | serialized_options=None, file=DESCRIPTOR),
644 | _descriptor.FieldDescriptor(
645 | name='wxidLeave', full_name='spy.GroupMemberEvent.wxidLeave', index=2,
646 | number=3, type=9, cpp_type=9, label=3,
647 | has_default_value=False, default_value=[],
648 | message_type=None, enum_type=None, containing_type=None,
649 | is_extension=False, extension_scope=None,
650 | serialized_options=None, file=DESCRIPTOR),
651 | ],
652 | extensions=[
653 | ],
654 | nested_types=[],
655 | enum_types=[
656 | ],
657 | serialized_options=None,
658 | is_extendable=False,
659 | syntax='proto3',
660 | extension_ranges=[],
661 | oneofs=[
662 | ],
663 | serialized_start=1092,
664 | serialized_end=1161,
665 | )
666 |
667 |
668 | _LOGINQRCODE = _descriptor.Descriptor(
669 | name='LoginQRCode',
670 | full_name='spy.LoginQRCode',
671 | filename=None,
672 | file=DESCRIPTOR,
673 | containing_type=None,
674 | fields=[
675 | _descriptor.FieldDescriptor(
676 | name='qrcodeSize', full_name='spy.LoginQRCode.qrcodeSize', index=0,
677 | number=1, type=5, cpp_type=1, label=1,
678 | has_default_value=False, default_value=0,
679 | message_type=None, enum_type=None, containing_type=None,
680 | is_extension=False, extension_scope=None,
681 | serialized_options=None, file=DESCRIPTOR),
682 | _descriptor.FieldDescriptor(
683 | name='qrcodeBytes', full_name='spy.LoginQRCode.qrcodeBytes', index=1,
684 | number=2, type=12, cpp_type=9, label=1,
685 | has_default_value=False, default_value=b"",
686 | message_type=None, enum_type=None, containing_type=None,
687 | is_extension=False, extension_scope=None,
688 | serialized_options=None, file=DESCRIPTOR),
689 | ],
690 | extensions=[
691 | ],
692 | nested_types=[],
693 | enum_types=[
694 | ],
695 | serialized_options=None,
696 | is_extendable=False,
697 | syntax='proto3',
698 | extension_ranges=[],
699 | oneofs=[
700 | ],
701 | serialized_start=1163,
702 | serialized_end=1217,
703 | )
704 |
705 |
706 | _GROUPENTERURL = _descriptor.Descriptor(
707 | name='GroupEnterUrl',
708 | full_name='spy.GroupEnterUrl',
709 | filename=None,
710 | file=DESCRIPTOR,
711 | containing_type=None,
712 | fields=[
713 | _descriptor.FieldDescriptor(
714 | name='url', full_name='spy.GroupEnterUrl.url', index=0,
715 | number=2, type=9, cpp_type=9, label=1,
716 | has_default_value=False, default_value=b"".decode('utf-8'),
717 | message_type=None, enum_type=None, containing_type=None,
718 | is_extension=False, extension_scope=None,
719 | serialized_options=None, file=DESCRIPTOR),
720 | ],
721 | extensions=[
722 | ],
723 | nested_types=[],
724 | enum_types=[
725 | ],
726 | serialized_options=None,
727 | is_extendable=False,
728 | syntax='proto3',
729 | extension_ranges=[],
730 | oneofs=[
731 | ],
732 | serialized_start=1219,
733 | serialized_end=1247,
734 | )
735 |
736 | _CHATMESSAGE.fields_by_name['message'].message_type = wx__pb2._CHATMESSAGE
737 | _CONTACTS.fields_by_name['contactDetails'].message_type = wx__pb2._CONTACTDETAILS
738 | _CREATEGROUPCALLBACK.fields_by_name['wxid'].message_type = wx__pb2._WECHATSTRING
739 | _CREATEGROUPCALLBACK.fields_by_name['memberData'].message_type = wx__pb2._CREATEGROUPMEMBERDATA
740 | _GROUPMEMBERDETAILS.fields_by_name['groupMemberDetails'].message_type = wx__pb2._GROUPMEMBERDETAILS
741 | DESCRIPTOR.message_types_by_name['ChatMessage'] = _CHATMESSAGE
742 | DESCRIPTOR.message_types_by_name['AccountDetails'] = _ACCOUNTDETAILS
743 | DESCRIPTOR.message_types_by_name['Contacts'] = _CONTACTS
744 | DESCRIPTOR.message_types_by_name['TextMessage'] = _TEXTMESSAGE
745 | DESCRIPTOR.message_types_by_name['FileMessage'] = _FILEMESSAGE
746 | DESCRIPTOR.message_types_by_name['XmlMessage'] = _XMLMESSAGE
747 | DESCRIPTOR.message_types_by_name['ContactApplication'] = _CONTACTAPPLICATION
748 | DESCRIPTOR.message_types_by_name['Response'] = _RESPONSE
749 | DESCRIPTOR.message_types_by_name['Request'] = _REQUEST
750 | DESCRIPTOR.message_types_by_name['CreateGroupCallback'] = _CREATEGROUPCALLBACK
751 | DESCRIPTOR.message_types_by_name['GroupMemberDetails'] = _GROUPMEMBERDETAILS
752 | DESCRIPTOR.message_types_by_name['GroupMemberEvent'] = _GROUPMEMBEREVENT
753 | DESCRIPTOR.message_types_by_name['LoginQRCode'] = _LOGINQRCODE
754 | DESCRIPTOR.message_types_by_name['GroupEnterUrl'] = _GROUPENTERURL
755 | _sym_db.RegisterFileDescriptor(DESCRIPTOR)
756 |
757 | ChatMessage = _reflection.GeneratedProtocolMessageType('ChatMessage', (_message.Message,), {
758 | 'DESCRIPTOR' : _CHATMESSAGE,
759 | '__module__' : 'spy_pb2'
760 | # @@protoc_insertion_point(class_scope:spy.ChatMessage)
761 | })
762 | _sym_db.RegisterMessage(ChatMessage)
763 |
764 | AccountDetails = _reflection.GeneratedProtocolMessageType('AccountDetails', (_message.Message,), {
765 | 'DESCRIPTOR' : _ACCOUNTDETAILS,
766 | '__module__' : 'spy_pb2'
767 | # @@protoc_insertion_point(class_scope:spy.AccountDetails)
768 | })
769 | _sym_db.RegisterMessage(AccountDetails)
770 |
771 | Contacts = _reflection.GeneratedProtocolMessageType('Contacts', (_message.Message,), {
772 | 'DESCRIPTOR' : _CONTACTS,
773 | '__module__' : 'spy_pb2'
774 | # @@protoc_insertion_point(class_scope:spy.Contacts)
775 | })
776 | _sym_db.RegisterMessage(Contacts)
777 |
778 | TextMessage = _reflection.GeneratedProtocolMessageType('TextMessage', (_message.Message,), {
779 | 'DESCRIPTOR' : _TEXTMESSAGE,
780 | '__module__' : 'spy_pb2'
781 | # @@protoc_insertion_point(class_scope:spy.TextMessage)
782 | })
783 | _sym_db.RegisterMessage(TextMessage)
784 |
785 | FileMessage = _reflection.GeneratedProtocolMessageType('FileMessage', (_message.Message,), {
786 | 'DESCRIPTOR' : _FILEMESSAGE,
787 | '__module__' : 'spy_pb2'
788 | # @@protoc_insertion_point(class_scope:spy.FileMessage)
789 | })
790 | _sym_db.RegisterMessage(FileMessage)
791 |
792 | XmlMessage = _reflection.GeneratedProtocolMessageType('XmlMessage', (_message.Message,), {
793 | 'DESCRIPTOR' : _XMLMESSAGE,
794 | '__module__' : 'spy_pb2'
795 | # @@protoc_insertion_point(class_scope:spy.XmlMessage)
796 | })
797 | _sym_db.RegisterMessage(XmlMessage)
798 |
799 | ContactApplication = _reflection.GeneratedProtocolMessageType('ContactApplication', (_message.Message,), {
800 | 'DESCRIPTOR' : _CONTACTAPPLICATION,
801 | '__module__' : 'spy_pb2'
802 | # @@protoc_insertion_point(class_scope:spy.ContactApplication)
803 | })
804 | _sym_db.RegisterMessage(ContactApplication)
805 |
806 | Response = _reflection.GeneratedProtocolMessageType('Response', (_message.Message,), {
807 | 'DESCRIPTOR' : _RESPONSE,
808 | '__module__' : 'spy_pb2'
809 | # @@protoc_insertion_point(class_scope:spy.Response)
810 | })
811 | _sym_db.RegisterMessage(Response)
812 |
813 | Request = _reflection.GeneratedProtocolMessageType('Request', (_message.Message,), {
814 | 'DESCRIPTOR' : _REQUEST,
815 | '__module__' : 'spy_pb2'
816 | # @@protoc_insertion_point(class_scope:spy.Request)
817 | })
818 | _sym_db.RegisterMessage(Request)
819 |
820 | CreateGroupCallback = _reflection.GeneratedProtocolMessageType('CreateGroupCallback', (_message.Message,), {
821 | 'DESCRIPTOR' : _CREATEGROUPCALLBACK,
822 | '__module__' : 'spy_pb2'
823 | # @@protoc_insertion_point(class_scope:spy.CreateGroupCallback)
824 | })
825 | _sym_db.RegisterMessage(CreateGroupCallback)
826 |
827 | GroupMemberDetails = _reflection.GeneratedProtocolMessageType('GroupMemberDetails', (_message.Message,), {
828 | 'DESCRIPTOR' : _GROUPMEMBERDETAILS,
829 | '__module__' : 'spy_pb2'
830 | # @@protoc_insertion_point(class_scope:spy.GroupMemberDetails)
831 | })
832 | _sym_db.RegisterMessage(GroupMemberDetails)
833 |
834 | GroupMemberEvent = _reflection.GeneratedProtocolMessageType('GroupMemberEvent', (_message.Message,), {
835 | 'DESCRIPTOR' : _GROUPMEMBEREVENT,
836 | '__module__' : 'spy_pb2'
837 | # @@protoc_insertion_point(class_scope:spy.GroupMemberEvent)
838 | })
839 | _sym_db.RegisterMessage(GroupMemberEvent)
840 |
841 | LoginQRCode = _reflection.GeneratedProtocolMessageType('LoginQRCode', (_message.Message,), {
842 | 'DESCRIPTOR' : _LOGINQRCODE,
843 | '__module__' : 'spy_pb2'
844 | # @@protoc_insertion_point(class_scope:spy.LoginQRCode)
845 | })
846 | _sym_db.RegisterMessage(LoginQRCode)
847 |
848 | GroupEnterUrl = _reflection.GeneratedProtocolMessageType('GroupEnterUrl', (_message.Message,), {
849 | 'DESCRIPTOR' : _GROUPENTERURL,
850 | '__module__' : 'spy_pb2'
851 | # @@protoc_insertion_point(class_scope:spy.GroupEnterUrl)
852 | })
853 | _sym_db.RegisterMessage(GroupEnterUrl)
854 |
855 |
856 | # @@protoc_insertion_point(module_scope)
857 |
--------------------------------------------------------------------------------
/PyWeChatSpy/proto/wx_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: wx.proto
4 |
5 | from google.protobuf import descriptor as _descriptor
6 | from google.protobuf import message as _message
7 | from google.protobuf import reflection as _reflection
8 | from google.protobuf import symbol_database as _symbol_database
9 | # @@protoc_insertion_point(imports)
10 |
11 | _sym_db = _symbol_database.Default()
12 |
13 |
14 |
15 |
16 | DESCRIPTOR = _descriptor.FileDescriptor(
17 | name='wx.proto',
18 | package='wx',
19 | syntax='proto3',
20 | serialized_options=None,
21 | serialized_pb=b'\n\x08wx.proto\x12\x02wx\"\x1b\n\x0cWeChatString\x12\x0b\n\x03str\x18\x01 \x01(\t\"\xbc\x02\n\x0f\x41\x63\x63ountDetails1\x12\x1e\n\x04wxid\x18\x02 \x01(\x0b\x32\x10.wx.WeChatString\x12\"\n\x08nickname\x18\x03 \x01(\x0b\x32\x10.wx.WeChatString\x12\n\n\x02QQ\x18\x04 \x01(\x03\x12\x1f\n\x05\x65mail\x18\x05 \x01(\x0b\x32\x10.wx.WeChatString\x12\x1f\n\x05phone\x18\x06 \x01(\x0b\x32\x10.wx.WeChatString\x12\x10\n\x08unknown7\x18\x07 \x01(\x05\x12\x10\n\x08unknown8\x18\x08 \x01(\x05\x12\x10\n\x08unknown9\x18\t \x01(\x0c\x12\x0b\n\x03sex\x18\n \x01(\x05\x12\x10\n\x08province\x18\x0b \x01(\t\x12\x0c\n\x04\x63ity\x18\x0c \x01(\t\x12\x11\n\tautograph\x18\r \x01(\t\x12\x10\n\x08wechatId\x18\x1b \x01(\t\x12\x0f\n\x07\x63ountry\x18& \x01(\t\"8\n\rWeChatMoments\x12\x0c\n\x04\x66lag\x18\x01 \x01(\x05\x12\x19\n\x11momentsBackground\x18\x02 \x01(\t\"i\n\x0f\x41\x63\x63ountDetails2\x12(\n\rwechatMoments\x18\x01 \x01(\x0b\x32\x11.wx.WeChatMoments\x12\x16\n\x0eprofilePhotoHD\x18\t \x01(\t\x12\x14\n\x0cprofilePhoto\x18\n \x01(\t\"\x82\x01\n\x12\x41\x63\x63ountDetailsData\x12\x10\n\x08unknown1\x18\x01 \x01(\x0c\x12,\n\x0f\x61\x63\x63ountDetails1\x18\x02 \x01(\x0b\x32\x13.wx.AccountDetails1\x12,\n\x0f\x61\x63\x63ountDetails2\x18\x03 \x01(\x0b\x32\x13.wx.AccountDetails2\":\n\rMessageDetail\x12\x13\n\x0bmessageSize\x18\x01 \x01(\x05\x12\x14\n\x0cmessageBytes\x18\x02 \x01(\x0c\"H\n\x07Message\x12\x13\n\x0bmessageType\x18\x01 \x01(\x05\x12(\n\rmessageDetail\x18\x02 \x01(\x0b\x32\x11.wx.MessageDetail\"A\n\x0bMessageList\x12\x14\n\x0cmessageCount\x18\x01 \x01(\x05\x12\x1c\n\x07message\x18\x02 \x03(\x0b\x32\x0b.wx.Message\"E\n\x0bMessageData\x12\x10\n\x08unknown1\x18\x01 \x01(\x05\x12$\n\x0bmessageList\x18\x02 \x01(\x0b\x32\x0f.wx.MessageList\"6\n\rImageOverview\x12\x11\n\timageSize\x18\x01 \x01(\x05\x12\x12\n\nimageBytes\x18\x02 \x01(\x0c\"\x93\x02\n\x0b\x43hatMessage\x12\"\n\x08wxidFrom\x18\x02 \x01(\x0b\x32\x10.wx.WeChatString\x12 \n\x06wxidTo\x18\x03 \x01(\x0b\x32\x10.wx.WeChatString\x12\x0c\n\x04type\x18\x04 \x01(\x05\x12!\n\x07\x63ontent\x18\x05 \x01(\x0b\x32\x10.wx.WeChatString\x12\x10\n\x08unknown6\x18\x06 \x01(\x05\x12\x10\n\x08unknown7\x18\x07 \x01(\x05\x12(\n\rimageOverview\x18\x08 \x01(\x0b\x32\x11.wx.ImageOverview\x12\x11\n\ttimestamp\x18\t \x01(\x03\x12\x0c\n\x04head\x18\n \x01(\t\x12\x10\n\x08overview\x18\x0b \x01(\t\x12\x0c\n\x04\x66ile\x18\x0e \x01(\t\"-\n\x0bGroupMember\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\x10\n\x08nickname\x18\x02 \x01(\t\"\x82\x01\n\x0fGroupMemberList\x12\x13\n\x0bmemberCount\x18\x01 \x01(\x05\x12$\n\x0bgroupMember\x18\x02 \x03(\x0b\x32\x0f.wx.GroupMember\x12\x10\n\x08unknown1\x18\x03 \x01(\x05\x12\x10\n\x08unknown2\x18\x04 \x01(\t\x12\x10\n\x08unknown3\x18\x05 \x01(\x05\"C\n\x0c\x43ontactPhone\x12\x12\n\nphoneCount\x18\x01 \x01(\x05\x12\x1f\n\x05phone\x18\x02 \x03(\x0b\x32\x10.wx.WeChatString\"\xc1\x05\n\x0e\x43ontactDetails\x12\x1e\n\x04wxid\x18\x01 \x01(\x0b\x32\x10.wx.WeChatString\x12\"\n\x08nickname\x18\x02 \x01(\x0b\x32\x10.wx.WeChatString\x12\x31\n\x17nicknamePinyinUppercase\x18\x03 \x01(\x0b\x32\x10.wx.WeChatString\x12(\n\x0enicknamePinyin\x18\x04 \x01(\x0b\x32\x10.wx.WeChatString\x12\x0b\n\x03sex\x18\x05 \x01(\x05\x12 \n\x06remark\x18\n \x01(\x0b\x32\x10.wx.WeChatString\x12/\n\x15remarkPinyinUppercase\x18\x0b \x01(\x0b\x32\x10.wx.WeChatString\x12&\n\x0cremarkPinyin\x18\x0c \x01(\x0b\x32\x10.wx.WeChatString\x12\x10\n\x08province\x18\x13 \x01(\t\x12\x0c\n\x04\x63ity\x18\x14 \x01(\t\x12\x11\n\tautograph\x18\x15 \x01(\t\x12\x10\n\x08wechatId\x18\x1e \x01(\t\x12\x16\n\x0egroupOwnerWxid\x18\x1f \x01(\t\x12(\n\rweChatMoments\x18% \x03(\x0b\x32\x11.wx.WeChatMoments\x12\x0f\n\x07\x63ountry\x18& \x01(\t\x12\x16\n\x0eprofilePhotoHD\x18\' \x01(\t\x12\x14\n\x0cprofilePhoto\x18( \x01(\t\x12\x11\n\tbrandList\x18) \x01(\t\x12\x0b\n\x03md5\x18, \x01(\t\x12\x17\n\x0f\x65ncryptusername\x18- \x01(\t\x12,\n\x0fgroupMemberList\x18\x39 \x01(\x0b\x32\x13.wx.GroupMemberList\x12\x13\n\x0b\x64\x65scription\x18; \x01(\t\x12\r\n\x05tagId\x18= \x01(\t\x12&\n\x0c\x63ontactPhone\x18> \x01(\x0b\x32\x10.wx.ContactPhone\x12\r\n\x05wxid2\x18G \x01(\t\"@\n\x12\x43ontactDetailsData\x12*\n\x0e\x63ontactDetails\x18\x03 \x01(\x0b\x32\x12.wx.ContactDetails\"7\n\x15\x43reateGroupMemberData\x12\x1e\n\x04wxid\x18\x01 \x01(\x0b\x32\x10.wx.WeChatString\"\x8e\x01\n\x12GroupMemberDetails\x12\x0c\n\x04wxid\x18\x01 \x01(\t\x12\x10\n\x08nickname\x18\x02 \x01(\t\x12\x15\n\rgroupNickname\x18\x03 \x01(\t\x12\x16\n\x0eprofilePhotoHD\x18\x04 \x01(\t\x12\x14\n\x0cprofilePhoto\x18\x05 \x01(\t\x12\x13\n\x0binviterWxid\x18\x07 \x01(\t\"b\n\x16GroupMemberDetailsList\x12\x14\n\x0c\x64\x65tailsCount\x18\x01 \x01(\x05\x12\x32\n\x12groupMemberDetails\x18\x02 \x03(\x0b\x32\x16.wx.GroupMemberDetails\"k\n\x1aGroupMemberDetailsListData\x12\x11\n\tgroupWxid\x18\x02 \x01(\t\x12:\n\x16groupMemberDetailsList\x18\x04 \x01(\x0b\x32\x1a.wx.GroupMemberDetailsList\"6\n\x0bLoginQRCode\x12\x12\n\nqrcodeSize\x18\x01 \x01(\x05\x12\x13\n\x0bqrcodeBytes\x18\x02 \x01(\x0c\"7\n\x0fLoginQRCodeData\x12$\n\x0bloginQRCode\x18\x02 \x01(\x0b\x32\x0f.wx.LoginQRCodeb\x06proto3'
22 | )
23 |
24 |
25 |
26 |
27 | _WECHATSTRING = _descriptor.Descriptor(
28 | name='WeChatString',
29 | full_name='wx.WeChatString',
30 | filename=None,
31 | file=DESCRIPTOR,
32 | containing_type=None,
33 | fields=[
34 | _descriptor.FieldDescriptor(
35 | name='str', full_name='wx.WeChatString.str', index=0,
36 | number=1, type=9, cpp_type=9, label=1,
37 | has_default_value=False, default_value=b"".decode('utf-8'),
38 | message_type=None, enum_type=None, containing_type=None,
39 | is_extension=False, extension_scope=None,
40 | serialized_options=None, file=DESCRIPTOR),
41 | ],
42 | extensions=[
43 | ],
44 | nested_types=[],
45 | enum_types=[
46 | ],
47 | serialized_options=None,
48 | is_extendable=False,
49 | syntax='proto3',
50 | extension_ranges=[],
51 | oneofs=[
52 | ],
53 | serialized_start=16,
54 | serialized_end=43,
55 | )
56 |
57 |
58 | _ACCOUNTDETAILS1 = _descriptor.Descriptor(
59 | name='AccountDetails1',
60 | full_name='wx.AccountDetails1',
61 | filename=None,
62 | file=DESCRIPTOR,
63 | containing_type=None,
64 | fields=[
65 | _descriptor.FieldDescriptor(
66 | name='wxid', full_name='wx.AccountDetails1.wxid', index=0,
67 | number=2, type=11, cpp_type=10, label=1,
68 | has_default_value=False, default_value=None,
69 | message_type=None, enum_type=None, containing_type=None,
70 | is_extension=False, extension_scope=None,
71 | serialized_options=None, file=DESCRIPTOR),
72 | _descriptor.FieldDescriptor(
73 | name='nickname', full_name='wx.AccountDetails1.nickname', index=1,
74 | number=3, type=11, cpp_type=10, label=1,
75 | has_default_value=False, default_value=None,
76 | message_type=None, enum_type=None, containing_type=None,
77 | is_extension=False, extension_scope=None,
78 | serialized_options=None, file=DESCRIPTOR),
79 | _descriptor.FieldDescriptor(
80 | name='QQ', full_name='wx.AccountDetails1.QQ', index=2,
81 | number=4, type=3, cpp_type=2, label=1,
82 | has_default_value=False, default_value=0,
83 | message_type=None, enum_type=None, containing_type=None,
84 | is_extension=False, extension_scope=None,
85 | serialized_options=None, file=DESCRIPTOR),
86 | _descriptor.FieldDescriptor(
87 | name='email', full_name='wx.AccountDetails1.email', index=3,
88 | number=5, type=11, cpp_type=10, label=1,
89 | has_default_value=False, default_value=None,
90 | message_type=None, enum_type=None, containing_type=None,
91 | is_extension=False, extension_scope=None,
92 | serialized_options=None, file=DESCRIPTOR),
93 | _descriptor.FieldDescriptor(
94 | name='phone', full_name='wx.AccountDetails1.phone', index=4,
95 | number=6, type=11, cpp_type=10, label=1,
96 | has_default_value=False, default_value=None,
97 | message_type=None, enum_type=None, containing_type=None,
98 | is_extension=False, extension_scope=None,
99 | serialized_options=None, file=DESCRIPTOR),
100 | _descriptor.FieldDescriptor(
101 | name='unknown7', full_name='wx.AccountDetails1.unknown7', index=5,
102 | number=7, type=5, cpp_type=1, label=1,
103 | has_default_value=False, default_value=0,
104 | message_type=None, enum_type=None, containing_type=None,
105 | is_extension=False, extension_scope=None,
106 | serialized_options=None, file=DESCRIPTOR),
107 | _descriptor.FieldDescriptor(
108 | name='unknown8', full_name='wx.AccountDetails1.unknown8', index=6,
109 | number=8, type=5, cpp_type=1, label=1,
110 | has_default_value=False, default_value=0,
111 | message_type=None, enum_type=None, containing_type=None,
112 | is_extension=False, extension_scope=None,
113 | serialized_options=None, file=DESCRIPTOR),
114 | _descriptor.FieldDescriptor(
115 | name='unknown9', full_name='wx.AccountDetails1.unknown9', index=7,
116 | number=9, type=12, cpp_type=9, label=1,
117 | has_default_value=False, default_value=b"",
118 | message_type=None, enum_type=None, containing_type=None,
119 | is_extension=False, extension_scope=None,
120 | serialized_options=None, file=DESCRIPTOR),
121 | _descriptor.FieldDescriptor(
122 | name='sex', full_name='wx.AccountDetails1.sex', index=8,
123 | number=10, type=5, cpp_type=1, label=1,
124 | has_default_value=False, default_value=0,
125 | message_type=None, enum_type=None, containing_type=None,
126 | is_extension=False, extension_scope=None,
127 | serialized_options=None, file=DESCRIPTOR),
128 | _descriptor.FieldDescriptor(
129 | name='province', full_name='wx.AccountDetails1.province', index=9,
130 | number=11, type=9, cpp_type=9, label=1,
131 | has_default_value=False, default_value=b"".decode('utf-8'),
132 | message_type=None, enum_type=None, containing_type=None,
133 | is_extension=False, extension_scope=None,
134 | serialized_options=None, file=DESCRIPTOR),
135 | _descriptor.FieldDescriptor(
136 | name='city', full_name='wx.AccountDetails1.city', index=10,
137 | number=12, type=9, cpp_type=9, label=1,
138 | has_default_value=False, default_value=b"".decode('utf-8'),
139 | message_type=None, enum_type=None, containing_type=None,
140 | is_extension=False, extension_scope=None,
141 | serialized_options=None, file=DESCRIPTOR),
142 | _descriptor.FieldDescriptor(
143 | name='autograph', full_name='wx.AccountDetails1.autograph', index=11,
144 | number=13, type=9, cpp_type=9, label=1,
145 | has_default_value=False, default_value=b"".decode('utf-8'),
146 | message_type=None, enum_type=None, containing_type=None,
147 | is_extension=False, extension_scope=None,
148 | serialized_options=None, file=DESCRIPTOR),
149 | _descriptor.FieldDescriptor(
150 | name='wechatId', full_name='wx.AccountDetails1.wechatId', index=12,
151 | number=27, type=9, cpp_type=9, label=1,
152 | has_default_value=False, default_value=b"".decode('utf-8'),
153 | message_type=None, enum_type=None, containing_type=None,
154 | is_extension=False, extension_scope=None,
155 | serialized_options=None, file=DESCRIPTOR),
156 | _descriptor.FieldDescriptor(
157 | name='country', full_name='wx.AccountDetails1.country', index=13,
158 | number=38, type=9, cpp_type=9, label=1,
159 | has_default_value=False, default_value=b"".decode('utf-8'),
160 | message_type=None, enum_type=None, containing_type=None,
161 | is_extension=False, extension_scope=None,
162 | serialized_options=None, file=DESCRIPTOR),
163 | ],
164 | extensions=[
165 | ],
166 | nested_types=[],
167 | enum_types=[
168 | ],
169 | serialized_options=None,
170 | is_extendable=False,
171 | syntax='proto3',
172 | extension_ranges=[],
173 | oneofs=[
174 | ],
175 | serialized_start=46,
176 | serialized_end=362,
177 | )
178 |
179 |
180 | _WECHATMOMENTS = _descriptor.Descriptor(
181 | name='WeChatMoments',
182 | full_name='wx.WeChatMoments',
183 | filename=None,
184 | file=DESCRIPTOR,
185 | containing_type=None,
186 | fields=[
187 | _descriptor.FieldDescriptor(
188 | name='flag', full_name='wx.WeChatMoments.flag', index=0,
189 | number=1, type=5, cpp_type=1, label=1,
190 | has_default_value=False, default_value=0,
191 | message_type=None, enum_type=None, containing_type=None,
192 | is_extension=False, extension_scope=None,
193 | serialized_options=None, file=DESCRIPTOR),
194 | _descriptor.FieldDescriptor(
195 | name='momentsBackground', full_name='wx.WeChatMoments.momentsBackground', index=1,
196 | number=2, type=9, cpp_type=9, label=1,
197 | has_default_value=False, default_value=b"".decode('utf-8'),
198 | message_type=None, enum_type=None, containing_type=None,
199 | is_extension=False, extension_scope=None,
200 | serialized_options=None, file=DESCRIPTOR),
201 | ],
202 | extensions=[
203 | ],
204 | nested_types=[],
205 | enum_types=[
206 | ],
207 | serialized_options=None,
208 | is_extendable=False,
209 | syntax='proto3',
210 | extension_ranges=[],
211 | oneofs=[
212 | ],
213 | serialized_start=364,
214 | serialized_end=420,
215 | )
216 |
217 |
218 | _ACCOUNTDETAILS2 = _descriptor.Descriptor(
219 | name='AccountDetails2',
220 | full_name='wx.AccountDetails2',
221 | filename=None,
222 | file=DESCRIPTOR,
223 | containing_type=None,
224 | fields=[
225 | _descriptor.FieldDescriptor(
226 | name='wechatMoments', full_name='wx.AccountDetails2.wechatMoments', index=0,
227 | number=1, type=11, cpp_type=10, label=1,
228 | has_default_value=False, default_value=None,
229 | message_type=None, enum_type=None, containing_type=None,
230 | is_extension=False, extension_scope=None,
231 | serialized_options=None, file=DESCRIPTOR),
232 | _descriptor.FieldDescriptor(
233 | name='profilePhotoHD', full_name='wx.AccountDetails2.profilePhotoHD', index=1,
234 | number=9, type=9, cpp_type=9, label=1,
235 | has_default_value=False, default_value=b"".decode('utf-8'),
236 | message_type=None, enum_type=None, containing_type=None,
237 | is_extension=False, extension_scope=None,
238 | serialized_options=None, file=DESCRIPTOR),
239 | _descriptor.FieldDescriptor(
240 | name='profilePhoto', full_name='wx.AccountDetails2.profilePhoto', index=2,
241 | number=10, type=9, cpp_type=9, label=1,
242 | has_default_value=False, default_value=b"".decode('utf-8'),
243 | message_type=None, enum_type=None, containing_type=None,
244 | is_extension=False, extension_scope=None,
245 | serialized_options=None, file=DESCRIPTOR),
246 | ],
247 | extensions=[
248 | ],
249 | nested_types=[],
250 | enum_types=[
251 | ],
252 | serialized_options=None,
253 | is_extendable=False,
254 | syntax='proto3',
255 | extension_ranges=[],
256 | oneofs=[
257 | ],
258 | serialized_start=422,
259 | serialized_end=527,
260 | )
261 |
262 |
263 | _ACCOUNTDETAILSDATA = _descriptor.Descriptor(
264 | name='AccountDetailsData',
265 | full_name='wx.AccountDetailsData',
266 | filename=None,
267 | file=DESCRIPTOR,
268 | containing_type=None,
269 | fields=[
270 | _descriptor.FieldDescriptor(
271 | name='unknown1', full_name='wx.AccountDetailsData.unknown1', index=0,
272 | number=1, type=12, cpp_type=9, label=1,
273 | has_default_value=False, default_value=b"",
274 | message_type=None, enum_type=None, containing_type=None,
275 | is_extension=False, extension_scope=None,
276 | serialized_options=None, file=DESCRIPTOR),
277 | _descriptor.FieldDescriptor(
278 | name='accountDetails1', full_name='wx.AccountDetailsData.accountDetails1', index=1,
279 | number=2, type=11, cpp_type=10, label=1,
280 | has_default_value=False, default_value=None,
281 | message_type=None, enum_type=None, containing_type=None,
282 | is_extension=False, extension_scope=None,
283 | serialized_options=None, file=DESCRIPTOR),
284 | _descriptor.FieldDescriptor(
285 | name='accountDetails2', full_name='wx.AccountDetailsData.accountDetails2', index=2,
286 | number=3, type=11, cpp_type=10, label=1,
287 | has_default_value=False, default_value=None,
288 | message_type=None, enum_type=None, containing_type=None,
289 | is_extension=False, extension_scope=None,
290 | serialized_options=None, file=DESCRIPTOR),
291 | ],
292 | extensions=[
293 | ],
294 | nested_types=[],
295 | enum_types=[
296 | ],
297 | serialized_options=None,
298 | is_extendable=False,
299 | syntax='proto3',
300 | extension_ranges=[],
301 | oneofs=[
302 | ],
303 | serialized_start=530,
304 | serialized_end=660,
305 | )
306 |
307 |
308 | _MESSAGEDETAIL = _descriptor.Descriptor(
309 | name='MessageDetail',
310 | full_name='wx.MessageDetail',
311 | filename=None,
312 | file=DESCRIPTOR,
313 | containing_type=None,
314 | fields=[
315 | _descriptor.FieldDescriptor(
316 | name='messageSize', full_name='wx.MessageDetail.messageSize', index=0,
317 | number=1, type=5, cpp_type=1, label=1,
318 | has_default_value=False, default_value=0,
319 | message_type=None, enum_type=None, containing_type=None,
320 | is_extension=False, extension_scope=None,
321 | serialized_options=None, file=DESCRIPTOR),
322 | _descriptor.FieldDescriptor(
323 | name='messageBytes', full_name='wx.MessageDetail.messageBytes', index=1,
324 | number=2, type=12, cpp_type=9, label=1,
325 | has_default_value=False, default_value=b"",
326 | message_type=None, enum_type=None, containing_type=None,
327 | is_extension=False, extension_scope=None,
328 | serialized_options=None, file=DESCRIPTOR),
329 | ],
330 | extensions=[
331 | ],
332 | nested_types=[],
333 | enum_types=[
334 | ],
335 | serialized_options=None,
336 | is_extendable=False,
337 | syntax='proto3',
338 | extension_ranges=[],
339 | oneofs=[
340 | ],
341 | serialized_start=662,
342 | serialized_end=720,
343 | )
344 |
345 |
346 | _MESSAGE = _descriptor.Descriptor(
347 | name='Message',
348 | full_name='wx.Message',
349 | filename=None,
350 | file=DESCRIPTOR,
351 | containing_type=None,
352 | fields=[
353 | _descriptor.FieldDescriptor(
354 | name='messageType', full_name='wx.Message.messageType', index=0,
355 | number=1, type=5, cpp_type=1, label=1,
356 | has_default_value=False, default_value=0,
357 | message_type=None, enum_type=None, containing_type=None,
358 | is_extension=False, extension_scope=None,
359 | serialized_options=None, file=DESCRIPTOR),
360 | _descriptor.FieldDescriptor(
361 | name='messageDetail', full_name='wx.Message.messageDetail', index=1,
362 | number=2, type=11, cpp_type=10, label=1,
363 | has_default_value=False, default_value=None,
364 | message_type=None, enum_type=None, containing_type=None,
365 | is_extension=False, extension_scope=None,
366 | serialized_options=None, file=DESCRIPTOR),
367 | ],
368 | extensions=[
369 | ],
370 | nested_types=[],
371 | enum_types=[
372 | ],
373 | serialized_options=None,
374 | is_extendable=False,
375 | syntax='proto3',
376 | extension_ranges=[],
377 | oneofs=[
378 | ],
379 | serialized_start=722,
380 | serialized_end=794,
381 | )
382 |
383 |
384 | _MESSAGELIST = _descriptor.Descriptor(
385 | name='MessageList',
386 | full_name='wx.MessageList',
387 | filename=None,
388 | file=DESCRIPTOR,
389 | containing_type=None,
390 | fields=[
391 | _descriptor.FieldDescriptor(
392 | name='messageCount', full_name='wx.MessageList.messageCount', index=0,
393 | number=1, type=5, cpp_type=1, label=1,
394 | has_default_value=False, default_value=0,
395 | message_type=None, enum_type=None, containing_type=None,
396 | is_extension=False, extension_scope=None,
397 | serialized_options=None, file=DESCRIPTOR),
398 | _descriptor.FieldDescriptor(
399 | name='message', full_name='wx.MessageList.message', index=1,
400 | number=2, type=11, cpp_type=10, label=3,
401 | has_default_value=False, default_value=[],
402 | message_type=None, enum_type=None, containing_type=None,
403 | is_extension=False, extension_scope=None,
404 | serialized_options=None, file=DESCRIPTOR),
405 | ],
406 | extensions=[
407 | ],
408 | nested_types=[],
409 | enum_types=[
410 | ],
411 | serialized_options=None,
412 | is_extendable=False,
413 | syntax='proto3',
414 | extension_ranges=[],
415 | oneofs=[
416 | ],
417 | serialized_start=796,
418 | serialized_end=861,
419 | )
420 |
421 |
422 | _MESSAGEDATA = _descriptor.Descriptor(
423 | name='MessageData',
424 | full_name='wx.MessageData',
425 | filename=None,
426 | file=DESCRIPTOR,
427 | containing_type=None,
428 | fields=[
429 | _descriptor.FieldDescriptor(
430 | name='unknown1', full_name='wx.MessageData.unknown1', index=0,
431 | number=1, type=5, cpp_type=1, label=1,
432 | has_default_value=False, default_value=0,
433 | message_type=None, enum_type=None, containing_type=None,
434 | is_extension=False, extension_scope=None,
435 | serialized_options=None, file=DESCRIPTOR),
436 | _descriptor.FieldDescriptor(
437 | name='messageList', full_name='wx.MessageData.messageList', index=1,
438 | number=2, type=11, cpp_type=10, label=1,
439 | has_default_value=False, default_value=None,
440 | message_type=None, enum_type=None, containing_type=None,
441 | is_extension=False, extension_scope=None,
442 | serialized_options=None, file=DESCRIPTOR),
443 | ],
444 | extensions=[
445 | ],
446 | nested_types=[],
447 | enum_types=[
448 | ],
449 | serialized_options=None,
450 | is_extendable=False,
451 | syntax='proto3',
452 | extension_ranges=[],
453 | oneofs=[
454 | ],
455 | serialized_start=863,
456 | serialized_end=932,
457 | )
458 |
459 |
460 | _IMAGEOVERVIEW = _descriptor.Descriptor(
461 | name='ImageOverview',
462 | full_name='wx.ImageOverview',
463 | filename=None,
464 | file=DESCRIPTOR,
465 | containing_type=None,
466 | fields=[
467 | _descriptor.FieldDescriptor(
468 | name='imageSize', full_name='wx.ImageOverview.imageSize', index=0,
469 | number=1, type=5, cpp_type=1, label=1,
470 | has_default_value=False, default_value=0,
471 | message_type=None, enum_type=None, containing_type=None,
472 | is_extension=False, extension_scope=None,
473 | serialized_options=None, file=DESCRIPTOR),
474 | _descriptor.FieldDescriptor(
475 | name='imageBytes', full_name='wx.ImageOverview.imageBytes', index=1,
476 | number=2, type=12, cpp_type=9, label=1,
477 | has_default_value=False, default_value=b"",
478 | message_type=None, enum_type=None, containing_type=None,
479 | is_extension=False, extension_scope=None,
480 | serialized_options=None, file=DESCRIPTOR),
481 | ],
482 | extensions=[
483 | ],
484 | nested_types=[],
485 | enum_types=[
486 | ],
487 | serialized_options=None,
488 | is_extendable=False,
489 | syntax='proto3',
490 | extension_ranges=[],
491 | oneofs=[
492 | ],
493 | serialized_start=934,
494 | serialized_end=988,
495 | )
496 |
497 |
498 | _CHATMESSAGE = _descriptor.Descriptor(
499 | name='ChatMessage',
500 | full_name='wx.ChatMessage',
501 | filename=None,
502 | file=DESCRIPTOR,
503 | containing_type=None,
504 | fields=[
505 | _descriptor.FieldDescriptor(
506 | name='wxidFrom', full_name='wx.ChatMessage.wxidFrom', index=0,
507 | number=2, type=11, cpp_type=10, label=1,
508 | has_default_value=False, default_value=None,
509 | message_type=None, enum_type=None, containing_type=None,
510 | is_extension=False, extension_scope=None,
511 | serialized_options=None, file=DESCRIPTOR),
512 | _descriptor.FieldDescriptor(
513 | name='wxidTo', full_name='wx.ChatMessage.wxidTo', index=1,
514 | number=3, type=11, cpp_type=10, label=1,
515 | has_default_value=False, default_value=None,
516 | message_type=None, enum_type=None, containing_type=None,
517 | is_extension=False, extension_scope=None,
518 | serialized_options=None, file=DESCRIPTOR),
519 | _descriptor.FieldDescriptor(
520 | name='type', full_name='wx.ChatMessage.type', index=2,
521 | number=4, type=5, cpp_type=1, label=1,
522 | has_default_value=False, default_value=0,
523 | message_type=None, enum_type=None, containing_type=None,
524 | is_extension=False, extension_scope=None,
525 | serialized_options=None, file=DESCRIPTOR),
526 | _descriptor.FieldDescriptor(
527 | name='content', full_name='wx.ChatMessage.content', index=3,
528 | number=5, type=11, cpp_type=10, label=1,
529 | has_default_value=False, default_value=None,
530 | message_type=None, enum_type=None, containing_type=None,
531 | is_extension=False, extension_scope=None,
532 | serialized_options=None, file=DESCRIPTOR),
533 | _descriptor.FieldDescriptor(
534 | name='unknown6', full_name='wx.ChatMessage.unknown6', index=4,
535 | number=6, type=5, cpp_type=1, label=1,
536 | has_default_value=False, default_value=0,
537 | message_type=None, enum_type=None, containing_type=None,
538 | is_extension=False, extension_scope=None,
539 | serialized_options=None, file=DESCRIPTOR),
540 | _descriptor.FieldDescriptor(
541 | name='unknown7', full_name='wx.ChatMessage.unknown7', index=5,
542 | number=7, type=5, cpp_type=1, label=1,
543 | has_default_value=False, default_value=0,
544 | message_type=None, enum_type=None, containing_type=None,
545 | is_extension=False, extension_scope=None,
546 | serialized_options=None, file=DESCRIPTOR),
547 | _descriptor.FieldDescriptor(
548 | name='imageOverview', full_name='wx.ChatMessage.imageOverview', index=6,
549 | number=8, type=11, cpp_type=10, label=1,
550 | has_default_value=False, default_value=None,
551 | message_type=None, enum_type=None, containing_type=None,
552 | is_extension=False, extension_scope=None,
553 | serialized_options=None, file=DESCRIPTOR),
554 | _descriptor.FieldDescriptor(
555 | name='timestamp', full_name='wx.ChatMessage.timestamp', index=7,
556 | number=9, type=3, cpp_type=2, label=1,
557 | has_default_value=False, default_value=0,
558 | message_type=None, enum_type=None, containing_type=None,
559 | is_extension=False, extension_scope=None,
560 | serialized_options=None, file=DESCRIPTOR),
561 | _descriptor.FieldDescriptor(
562 | name='head', full_name='wx.ChatMessage.head', index=8,
563 | number=10, type=9, cpp_type=9, label=1,
564 | has_default_value=False, default_value=b"".decode('utf-8'),
565 | message_type=None, enum_type=None, containing_type=None,
566 | is_extension=False, extension_scope=None,
567 | serialized_options=None, file=DESCRIPTOR),
568 | _descriptor.FieldDescriptor(
569 | name='overview', full_name='wx.ChatMessage.overview', index=9,
570 | number=11, type=9, cpp_type=9, label=1,
571 | has_default_value=False, default_value=b"".decode('utf-8'),
572 | message_type=None, enum_type=None, containing_type=None,
573 | is_extension=False, extension_scope=None,
574 | serialized_options=None, file=DESCRIPTOR),
575 | _descriptor.FieldDescriptor(
576 | name='file', full_name='wx.ChatMessage.file', index=10,
577 | number=14, type=9, cpp_type=9, label=1,
578 | has_default_value=False, default_value=b"".decode('utf-8'),
579 | message_type=None, enum_type=None, containing_type=None,
580 | is_extension=False, extension_scope=None,
581 | serialized_options=None, file=DESCRIPTOR),
582 | ],
583 | extensions=[
584 | ],
585 | nested_types=[],
586 | enum_types=[
587 | ],
588 | serialized_options=None,
589 | is_extendable=False,
590 | syntax='proto3',
591 | extension_ranges=[],
592 | oneofs=[
593 | ],
594 | serialized_start=991,
595 | serialized_end=1266,
596 | )
597 |
598 |
599 | _GROUPMEMBER = _descriptor.Descriptor(
600 | name='GroupMember',
601 | full_name='wx.GroupMember',
602 | filename=None,
603 | file=DESCRIPTOR,
604 | containing_type=None,
605 | fields=[
606 | _descriptor.FieldDescriptor(
607 | name='wxid', full_name='wx.GroupMember.wxid', index=0,
608 | number=1, type=9, cpp_type=9, label=1,
609 | has_default_value=False, default_value=b"".decode('utf-8'),
610 | message_type=None, enum_type=None, containing_type=None,
611 | is_extension=False, extension_scope=None,
612 | serialized_options=None, file=DESCRIPTOR),
613 | _descriptor.FieldDescriptor(
614 | name='nickname', full_name='wx.GroupMember.nickname', index=1,
615 | number=2, type=9, cpp_type=9, label=1,
616 | has_default_value=False, default_value=b"".decode('utf-8'),
617 | message_type=None, enum_type=None, containing_type=None,
618 | is_extension=False, extension_scope=None,
619 | serialized_options=None, file=DESCRIPTOR),
620 | ],
621 | extensions=[
622 | ],
623 | nested_types=[],
624 | enum_types=[
625 | ],
626 | serialized_options=None,
627 | is_extendable=False,
628 | syntax='proto3',
629 | extension_ranges=[],
630 | oneofs=[
631 | ],
632 | serialized_start=1268,
633 | serialized_end=1313,
634 | )
635 |
636 |
637 | _GROUPMEMBERLIST = _descriptor.Descriptor(
638 | name='GroupMemberList',
639 | full_name='wx.GroupMemberList',
640 | filename=None,
641 | file=DESCRIPTOR,
642 | containing_type=None,
643 | fields=[
644 | _descriptor.FieldDescriptor(
645 | name='memberCount', full_name='wx.GroupMemberList.memberCount', index=0,
646 | number=1, type=5, cpp_type=1, label=1,
647 | has_default_value=False, default_value=0,
648 | message_type=None, enum_type=None, containing_type=None,
649 | is_extension=False, extension_scope=None,
650 | serialized_options=None, file=DESCRIPTOR),
651 | _descriptor.FieldDescriptor(
652 | name='groupMember', full_name='wx.GroupMemberList.groupMember', index=1,
653 | number=2, type=11, cpp_type=10, label=3,
654 | has_default_value=False, default_value=[],
655 | message_type=None, enum_type=None, containing_type=None,
656 | is_extension=False, extension_scope=None,
657 | serialized_options=None, file=DESCRIPTOR),
658 | _descriptor.FieldDescriptor(
659 | name='unknown1', full_name='wx.GroupMemberList.unknown1', index=2,
660 | number=3, type=5, cpp_type=1, label=1,
661 | has_default_value=False, default_value=0,
662 | message_type=None, enum_type=None, containing_type=None,
663 | is_extension=False, extension_scope=None,
664 | serialized_options=None, file=DESCRIPTOR),
665 | _descriptor.FieldDescriptor(
666 | name='unknown2', full_name='wx.GroupMemberList.unknown2', index=3,
667 | number=4, type=9, cpp_type=9, label=1,
668 | has_default_value=False, default_value=b"".decode('utf-8'),
669 | message_type=None, enum_type=None, containing_type=None,
670 | is_extension=False, extension_scope=None,
671 | serialized_options=None, file=DESCRIPTOR),
672 | _descriptor.FieldDescriptor(
673 | name='unknown3', full_name='wx.GroupMemberList.unknown3', index=4,
674 | number=5, type=5, cpp_type=1, label=1,
675 | has_default_value=False, default_value=0,
676 | message_type=None, enum_type=None, containing_type=None,
677 | is_extension=False, extension_scope=None,
678 | serialized_options=None, file=DESCRIPTOR),
679 | ],
680 | extensions=[
681 | ],
682 | nested_types=[],
683 | enum_types=[
684 | ],
685 | serialized_options=None,
686 | is_extendable=False,
687 | syntax='proto3',
688 | extension_ranges=[],
689 | oneofs=[
690 | ],
691 | serialized_start=1316,
692 | serialized_end=1446,
693 | )
694 |
695 |
696 | _CONTACTPHONE = _descriptor.Descriptor(
697 | name='ContactPhone',
698 | full_name='wx.ContactPhone',
699 | filename=None,
700 | file=DESCRIPTOR,
701 | containing_type=None,
702 | fields=[
703 | _descriptor.FieldDescriptor(
704 | name='phoneCount', full_name='wx.ContactPhone.phoneCount', index=0,
705 | number=1, type=5, cpp_type=1, label=1,
706 | has_default_value=False, default_value=0,
707 | message_type=None, enum_type=None, containing_type=None,
708 | is_extension=False, extension_scope=None,
709 | serialized_options=None, file=DESCRIPTOR),
710 | _descriptor.FieldDescriptor(
711 | name='phone', full_name='wx.ContactPhone.phone', index=1,
712 | number=2, type=11, cpp_type=10, label=3,
713 | has_default_value=False, default_value=[],
714 | message_type=None, enum_type=None, containing_type=None,
715 | is_extension=False, extension_scope=None,
716 | serialized_options=None, file=DESCRIPTOR),
717 | ],
718 | extensions=[
719 | ],
720 | nested_types=[],
721 | enum_types=[
722 | ],
723 | serialized_options=None,
724 | is_extendable=False,
725 | syntax='proto3',
726 | extension_ranges=[],
727 | oneofs=[
728 | ],
729 | serialized_start=1448,
730 | serialized_end=1515,
731 | )
732 |
733 |
734 | _CONTACTDETAILS = _descriptor.Descriptor(
735 | name='ContactDetails',
736 | full_name='wx.ContactDetails',
737 | filename=None,
738 | file=DESCRIPTOR,
739 | containing_type=None,
740 | fields=[
741 | _descriptor.FieldDescriptor(
742 | name='wxid', full_name='wx.ContactDetails.wxid', index=0,
743 | number=1, type=11, cpp_type=10, label=1,
744 | has_default_value=False, default_value=None,
745 | message_type=None, enum_type=None, containing_type=None,
746 | is_extension=False, extension_scope=None,
747 | serialized_options=None, file=DESCRIPTOR),
748 | _descriptor.FieldDescriptor(
749 | name='nickname', full_name='wx.ContactDetails.nickname', index=1,
750 | number=2, type=11, cpp_type=10, label=1,
751 | has_default_value=False, default_value=None,
752 | message_type=None, enum_type=None, containing_type=None,
753 | is_extension=False, extension_scope=None,
754 | serialized_options=None, file=DESCRIPTOR),
755 | _descriptor.FieldDescriptor(
756 | name='nicknamePinyinUppercase', full_name='wx.ContactDetails.nicknamePinyinUppercase', index=2,
757 | number=3, type=11, cpp_type=10, label=1,
758 | has_default_value=False, default_value=None,
759 | message_type=None, enum_type=None, containing_type=None,
760 | is_extension=False, extension_scope=None,
761 | serialized_options=None, file=DESCRIPTOR),
762 | _descriptor.FieldDescriptor(
763 | name='nicknamePinyin', full_name='wx.ContactDetails.nicknamePinyin', index=3,
764 | number=4, type=11, cpp_type=10, label=1,
765 | has_default_value=False, default_value=None,
766 | message_type=None, enum_type=None, containing_type=None,
767 | is_extension=False, extension_scope=None,
768 | serialized_options=None, file=DESCRIPTOR),
769 | _descriptor.FieldDescriptor(
770 | name='sex', full_name='wx.ContactDetails.sex', index=4,
771 | number=5, type=5, cpp_type=1, label=1,
772 | has_default_value=False, default_value=0,
773 | message_type=None, enum_type=None, containing_type=None,
774 | is_extension=False, extension_scope=None,
775 | serialized_options=None, file=DESCRIPTOR),
776 | _descriptor.FieldDescriptor(
777 | name='remark', full_name='wx.ContactDetails.remark', index=5,
778 | number=10, type=11, cpp_type=10, label=1,
779 | has_default_value=False, default_value=None,
780 | message_type=None, enum_type=None, containing_type=None,
781 | is_extension=False, extension_scope=None,
782 | serialized_options=None, file=DESCRIPTOR),
783 | _descriptor.FieldDescriptor(
784 | name='remarkPinyinUppercase', full_name='wx.ContactDetails.remarkPinyinUppercase', index=6,
785 | number=11, type=11, cpp_type=10, label=1,
786 | has_default_value=False, default_value=None,
787 | message_type=None, enum_type=None, containing_type=None,
788 | is_extension=False, extension_scope=None,
789 | serialized_options=None, file=DESCRIPTOR),
790 | _descriptor.FieldDescriptor(
791 | name='remarkPinyin', full_name='wx.ContactDetails.remarkPinyin', index=7,
792 | number=12, type=11, cpp_type=10, label=1,
793 | has_default_value=False, default_value=None,
794 | message_type=None, enum_type=None, containing_type=None,
795 | is_extension=False, extension_scope=None,
796 | serialized_options=None, file=DESCRIPTOR),
797 | _descriptor.FieldDescriptor(
798 | name='province', full_name='wx.ContactDetails.province', index=8,
799 | number=19, type=9, cpp_type=9, label=1,
800 | has_default_value=False, default_value=b"".decode('utf-8'),
801 | message_type=None, enum_type=None, containing_type=None,
802 | is_extension=False, extension_scope=None,
803 | serialized_options=None, file=DESCRIPTOR),
804 | _descriptor.FieldDescriptor(
805 | name='city', full_name='wx.ContactDetails.city', index=9,
806 | number=20, type=9, cpp_type=9, label=1,
807 | has_default_value=False, default_value=b"".decode('utf-8'),
808 | message_type=None, enum_type=None, containing_type=None,
809 | is_extension=False, extension_scope=None,
810 | serialized_options=None, file=DESCRIPTOR),
811 | _descriptor.FieldDescriptor(
812 | name='autograph', full_name='wx.ContactDetails.autograph', index=10,
813 | number=21, type=9, cpp_type=9, label=1,
814 | has_default_value=False, default_value=b"".decode('utf-8'),
815 | message_type=None, enum_type=None, containing_type=None,
816 | is_extension=False, extension_scope=None,
817 | serialized_options=None, file=DESCRIPTOR),
818 | _descriptor.FieldDescriptor(
819 | name='wechatId', full_name='wx.ContactDetails.wechatId', index=11,
820 | number=30, type=9, cpp_type=9, label=1,
821 | has_default_value=False, default_value=b"".decode('utf-8'),
822 | message_type=None, enum_type=None, containing_type=None,
823 | is_extension=False, extension_scope=None,
824 | serialized_options=None, file=DESCRIPTOR),
825 | _descriptor.FieldDescriptor(
826 | name='groupOwnerWxid', full_name='wx.ContactDetails.groupOwnerWxid', index=12,
827 | number=31, type=9, cpp_type=9, label=1,
828 | has_default_value=False, default_value=b"".decode('utf-8'),
829 | message_type=None, enum_type=None, containing_type=None,
830 | is_extension=False, extension_scope=None,
831 | serialized_options=None, file=DESCRIPTOR),
832 | _descriptor.FieldDescriptor(
833 | name='weChatMoments', full_name='wx.ContactDetails.weChatMoments', index=13,
834 | number=37, type=11, cpp_type=10, label=3,
835 | has_default_value=False, default_value=[],
836 | message_type=None, enum_type=None, containing_type=None,
837 | is_extension=False, extension_scope=None,
838 | serialized_options=None, file=DESCRIPTOR),
839 | _descriptor.FieldDescriptor(
840 | name='country', full_name='wx.ContactDetails.country', index=14,
841 | number=38, type=9, cpp_type=9, label=1,
842 | has_default_value=False, default_value=b"".decode('utf-8'),
843 | message_type=None, enum_type=None, containing_type=None,
844 | is_extension=False, extension_scope=None,
845 | serialized_options=None, file=DESCRIPTOR),
846 | _descriptor.FieldDescriptor(
847 | name='profilePhotoHD', full_name='wx.ContactDetails.profilePhotoHD', index=15,
848 | number=39, type=9, cpp_type=9, label=1,
849 | has_default_value=False, default_value=b"".decode('utf-8'),
850 | message_type=None, enum_type=None, containing_type=None,
851 | is_extension=False, extension_scope=None,
852 | serialized_options=None, file=DESCRIPTOR),
853 | _descriptor.FieldDescriptor(
854 | name='profilePhoto', full_name='wx.ContactDetails.profilePhoto', index=16,
855 | number=40, type=9, cpp_type=9, label=1,
856 | has_default_value=False, default_value=b"".decode('utf-8'),
857 | message_type=None, enum_type=None, containing_type=None,
858 | is_extension=False, extension_scope=None,
859 | serialized_options=None, file=DESCRIPTOR),
860 | _descriptor.FieldDescriptor(
861 | name='brandList', full_name='wx.ContactDetails.brandList', index=17,
862 | number=41, type=9, cpp_type=9, label=1,
863 | has_default_value=False, default_value=b"".decode('utf-8'),
864 | message_type=None, enum_type=None, containing_type=None,
865 | is_extension=False, extension_scope=None,
866 | serialized_options=None, file=DESCRIPTOR),
867 | _descriptor.FieldDescriptor(
868 | name='md5', full_name='wx.ContactDetails.md5', index=18,
869 | number=44, type=9, cpp_type=9, label=1,
870 | has_default_value=False, default_value=b"".decode('utf-8'),
871 | message_type=None, enum_type=None, containing_type=None,
872 | is_extension=False, extension_scope=None,
873 | serialized_options=None, file=DESCRIPTOR),
874 | _descriptor.FieldDescriptor(
875 | name='encryptusername', full_name='wx.ContactDetails.encryptusername', index=19,
876 | number=45, type=9, cpp_type=9, label=1,
877 | has_default_value=False, default_value=b"".decode('utf-8'),
878 | message_type=None, enum_type=None, containing_type=None,
879 | is_extension=False, extension_scope=None,
880 | serialized_options=None, file=DESCRIPTOR),
881 | _descriptor.FieldDescriptor(
882 | name='groupMemberList', full_name='wx.ContactDetails.groupMemberList', index=20,
883 | number=57, type=11, cpp_type=10, label=1,
884 | has_default_value=False, default_value=None,
885 | message_type=None, enum_type=None, containing_type=None,
886 | is_extension=False, extension_scope=None,
887 | serialized_options=None, file=DESCRIPTOR),
888 | _descriptor.FieldDescriptor(
889 | name='description', full_name='wx.ContactDetails.description', index=21,
890 | number=59, type=9, cpp_type=9, label=1,
891 | has_default_value=False, default_value=b"".decode('utf-8'),
892 | message_type=None, enum_type=None, containing_type=None,
893 | is_extension=False, extension_scope=None,
894 | serialized_options=None, file=DESCRIPTOR),
895 | _descriptor.FieldDescriptor(
896 | name='tagId', full_name='wx.ContactDetails.tagId', index=22,
897 | number=61, type=9, cpp_type=9, label=1,
898 | has_default_value=False, default_value=b"".decode('utf-8'),
899 | message_type=None, enum_type=None, containing_type=None,
900 | is_extension=False, extension_scope=None,
901 | serialized_options=None, file=DESCRIPTOR),
902 | _descriptor.FieldDescriptor(
903 | name='contactPhone', full_name='wx.ContactDetails.contactPhone', index=23,
904 | number=62, type=11, cpp_type=10, label=1,
905 | has_default_value=False, default_value=None,
906 | message_type=None, enum_type=None, containing_type=None,
907 | is_extension=False, extension_scope=None,
908 | serialized_options=None, file=DESCRIPTOR),
909 | _descriptor.FieldDescriptor(
910 | name='wxid2', full_name='wx.ContactDetails.wxid2', index=24,
911 | number=71, type=9, cpp_type=9, label=1,
912 | has_default_value=False, default_value=b"".decode('utf-8'),
913 | message_type=None, enum_type=None, containing_type=None,
914 | is_extension=False, extension_scope=None,
915 | serialized_options=None, file=DESCRIPTOR),
916 | ],
917 | extensions=[
918 | ],
919 | nested_types=[],
920 | enum_types=[
921 | ],
922 | serialized_options=None,
923 | is_extendable=False,
924 | syntax='proto3',
925 | extension_ranges=[],
926 | oneofs=[
927 | ],
928 | serialized_start=1518,
929 | serialized_end=2223,
930 | )
931 |
932 |
933 | _CONTACTDETAILSDATA = _descriptor.Descriptor(
934 | name='ContactDetailsData',
935 | full_name='wx.ContactDetailsData',
936 | filename=None,
937 | file=DESCRIPTOR,
938 | containing_type=None,
939 | fields=[
940 | _descriptor.FieldDescriptor(
941 | name='contactDetails', full_name='wx.ContactDetailsData.contactDetails', index=0,
942 | number=3, type=11, cpp_type=10, label=1,
943 | has_default_value=False, default_value=None,
944 | message_type=None, enum_type=None, containing_type=None,
945 | is_extension=False, extension_scope=None,
946 | serialized_options=None, file=DESCRIPTOR),
947 | ],
948 | extensions=[
949 | ],
950 | nested_types=[],
951 | enum_types=[
952 | ],
953 | serialized_options=None,
954 | is_extendable=False,
955 | syntax='proto3',
956 | extension_ranges=[],
957 | oneofs=[
958 | ],
959 | serialized_start=2225,
960 | serialized_end=2289,
961 | )
962 |
963 |
964 | _CREATEGROUPMEMBERDATA = _descriptor.Descriptor(
965 | name='CreateGroupMemberData',
966 | full_name='wx.CreateGroupMemberData',
967 | filename=None,
968 | file=DESCRIPTOR,
969 | containing_type=None,
970 | fields=[
971 | _descriptor.FieldDescriptor(
972 | name='wxid', full_name='wx.CreateGroupMemberData.wxid', index=0,
973 | number=1, type=11, cpp_type=10, label=1,
974 | has_default_value=False, default_value=None,
975 | message_type=None, enum_type=None, containing_type=None,
976 | is_extension=False, extension_scope=None,
977 | serialized_options=None, file=DESCRIPTOR),
978 | ],
979 | extensions=[
980 | ],
981 | nested_types=[],
982 | enum_types=[
983 | ],
984 | serialized_options=None,
985 | is_extendable=False,
986 | syntax='proto3',
987 | extension_ranges=[],
988 | oneofs=[
989 | ],
990 | serialized_start=2291,
991 | serialized_end=2346,
992 | )
993 |
994 |
995 | _GROUPMEMBERDETAILS = _descriptor.Descriptor(
996 | name='GroupMemberDetails',
997 | full_name='wx.GroupMemberDetails',
998 | filename=None,
999 | file=DESCRIPTOR,
1000 | containing_type=None,
1001 | fields=[
1002 | _descriptor.FieldDescriptor(
1003 | name='wxid', full_name='wx.GroupMemberDetails.wxid', index=0,
1004 | number=1, type=9, cpp_type=9, label=1,
1005 | has_default_value=False, default_value=b"".decode('utf-8'),
1006 | message_type=None, enum_type=None, containing_type=None,
1007 | is_extension=False, extension_scope=None,
1008 | serialized_options=None, file=DESCRIPTOR),
1009 | _descriptor.FieldDescriptor(
1010 | name='nickname', full_name='wx.GroupMemberDetails.nickname', index=1,
1011 | number=2, type=9, cpp_type=9, label=1,
1012 | has_default_value=False, default_value=b"".decode('utf-8'),
1013 | message_type=None, enum_type=None, containing_type=None,
1014 | is_extension=False, extension_scope=None,
1015 | serialized_options=None, file=DESCRIPTOR),
1016 | _descriptor.FieldDescriptor(
1017 | name='groupNickname', full_name='wx.GroupMemberDetails.groupNickname', index=2,
1018 | number=3, type=9, cpp_type=9, label=1,
1019 | has_default_value=False, default_value=b"".decode('utf-8'),
1020 | message_type=None, enum_type=None, containing_type=None,
1021 | is_extension=False, extension_scope=None,
1022 | serialized_options=None, file=DESCRIPTOR),
1023 | _descriptor.FieldDescriptor(
1024 | name='profilePhotoHD', full_name='wx.GroupMemberDetails.profilePhotoHD', index=3,
1025 | number=4, type=9, cpp_type=9, label=1,
1026 | has_default_value=False, default_value=b"".decode('utf-8'),
1027 | message_type=None, enum_type=None, containing_type=None,
1028 | is_extension=False, extension_scope=None,
1029 | serialized_options=None, file=DESCRIPTOR),
1030 | _descriptor.FieldDescriptor(
1031 | name='profilePhoto', full_name='wx.GroupMemberDetails.profilePhoto', index=4,
1032 | number=5, type=9, cpp_type=9, label=1,
1033 | has_default_value=False, default_value=b"".decode('utf-8'),
1034 | message_type=None, enum_type=None, containing_type=None,
1035 | is_extension=False, extension_scope=None,
1036 | serialized_options=None, file=DESCRIPTOR),
1037 | _descriptor.FieldDescriptor(
1038 | name='inviterWxid', full_name='wx.GroupMemberDetails.inviterWxid', index=5,
1039 | number=7, type=9, cpp_type=9, label=1,
1040 | has_default_value=False, default_value=b"".decode('utf-8'),
1041 | message_type=None, enum_type=None, containing_type=None,
1042 | is_extension=False, extension_scope=None,
1043 | serialized_options=None, file=DESCRIPTOR),
1044 | ],
1045 | extensions=[
1046 | ],
1047 | nested_types=[],
1048 | enum_types=[
1049 | ],
1050 | serialized_options=None,
1051 | is_extendable=False,
1052 | syntax='proto3',
1053 | extension_ranges=[],
1054 | oneofs=[
1055 | ],
1056 | serialized_start=2349,
1057 | serialized_end=2491,
1058 | )
1059 |
1060 |
1061 | _GROUPMEMBERDETAILSLIST = _descriptor.Descriptor(
1062 | name='GroupMemberDetailsList',
1063 | full_name='wx.GroupMemberDetailsList',
1064 | filename=None,
1065 | file=DESCRIPTOR,
1066 | containing_type=None,
1067 | fields=[
1068 | _descriptor.FieldDescriptor(
1069 | name='detailsCount', full_name='wx.GroupMemberDetailsList.detailsCount', index=0,
1070 | number=1, type=5, cpp_type=1, label=1,
1071 | has_default_value=False, default_value=0,
1072 | message_type=None, enum_type=None, containing_type=None,
1073 | is_extension=False, extension_scope=None,
1074 | serialized_options=None, file=DESCRIPTOR),
1075 | _descriptor.FieldDescriptor(
1076 | name='groupMemberDetails', full_name='wx.GroupMemberDetailsList.groupMemberDetails', index=1,
1077 | number=2, type=11, cpp_type=10, label=3,
1078 | has_default_value=False, default_value=[],
1079 | message_type=None, enum_type=None, containing_type=None,
1080 | is_extension=False, extension_scope=None,
1081 | serialized_options=None, file=DESCRIPTOR),
1082 | ],
1083 | extensions=[
1084 | ],
1085 | nested_types=[],
1086 | enum_types=[
1087 | ],
1088 | serialized_options=None,
1089 | is_extendable=False,
1090 | syntax='proto3',
1091 | extension_ranges=[],
1092 | oneofs=[
1093 | ],
1094 | serialized_start=2493,
1095 | serialized_end=2591,
1096 | )
1097 |
1098 |
1099 | _GROUPMEMBERDETAILSLISTDATA = _descriptor.Descriptor(
1100 | name='GroupMemberDetailsListData',
1101 | full_name='wx.GroupMemberDetailsListData',
1102 | filename=None,
1103 | file=DESCRIPTOR,
1104 | containing_type=None,
1105 | fields=[
1106 | _descriptor.FieldDescriptor(
1107 | name='groupWxid', full_name='wx.GroupMemberDetailsListData.groupWxid', index=0,
1108 | number=2, type=9, cpp_type=9, label=1,
1109 | has_default_value=False, default_value=b"".decode('utf-8'),
1110 | message_type=None, enum_type=None, containing_type=None,
1111 | is_extension=False, extension_scope=None,
1112 | serialized_options=None, file=DESCRIPTOR),
1113 | _descriptor.FieldDescriptor(
1114 | name='groupMemberDetailsList', full_name='wx.GroupMemberDetailsListData.groupMemberDetailsList', index=1,
1115 | number=4, type=11, cpp_type=10, label=1,
1116 | has_default_value=False, default_value=None,
1117 | message_type=None, enum_type=None, containing_type=None,
1118 | is_extension=False, extension_scope=None,
1119 | serialized_options=None, file=DESCRIPTOR),
1120 | ],
1121 | extensions=[
1122 | ],
1123 | nested_types=[],
1124 | enum_types=[
1125 | ],
1126 | serialized_options=None,
1127 | is_extendable=False,
1128 | syntax='proto3',
1129 | extension_ranges=[],
1130 | oneofs=[
1131 | ],
1132 | serialized_start=2593,
1133 | serialized_end=2700,
1134 | )
1135 |
1136 |
1137 | _LOGINQRCODE = _descriptor.Descriptor(
1138 | name='LoginQRCode',
1139 | full_name='wx.LoginQRCode',
1140 | filename=None,
1141 | file=DESCRIPTOR,
1142 | containing_type=None,
1143 | fields=[
1144 | _descriptor.FieldDescriptor(
1145 | name='qrcodeSize', full_name='wx.LoginQRCode.qrcodeSize', index=0,
1146 | number=1, type=5, cpp_type=1, label=1,
1147 | has_default_value=False, default_value=0,
1148 | message_type=None, enum_type=None, containing_type=None,
1149 | is_extension=False, extension_scope=None,
1150 | serialized_options=None, file=DESCRIPTOR),
1151 | _descriptor.FieldDescriptor(
1152 | name='qrcodeBytes', full_name='wx.LoginQRCode.qrcodeBytes', index=1,
1153 | number=2, type=12, cpp_type=9, label=1,
1154 | has_default_value=False, default_value=b"",
1155 | message_type=None, enum_type=None, containing_type=None,
1156 | is_extension=False, extension_scope=None,
1157 | serialized_options=None, file=DESCRIPTOR),
1158 | ],
1159 | extensions=[
1160 | ],
1161 | nested_types=[],
1162 | enum_types=[
1163 | ],
1164 | serialized_options=None,
1165 | is_extendable=False,
1166 | syntax='proto3',
1167 | extension_ranges=[],
1168 | oneofs=[
1169 | ],
1170 | serialized_start=2702,
1171 | serialized_end=2756,
1172 | )
1173 |
1174 |
1175 | _LOGINQRCODEDATA = _descriptor.Descriptor(
1176 | name='LoginQRCodeData',
1177 | full_name='wx.LoginQRCodeData',
1178 | filename=None,
1179 | file=DESCRIPTOR,
1180 | containing_type=None,
1181 | fields=[
1182 | _descriptor.FieldDescriptor(
1183 | name='loginQRCode', full_name='wx.LoginQRCodeData.loginQRCode', index=0,
1184 | number=2, type=11, cpp_type=10, label=1,
1185 | has_default_value=False, default_value=None,
1186 | message_type=None, enum_type=None, containing_type=None,
1187 | is_extension=False, extension_scope=None,
1188 | serialized_options=None, file=DESCRIPTOR),
1189 | ],
1190 | extensions=[
1191 | ],
1192 | nested_types=[],
1193 | enum_types=[
1194 | ],
1195 | serialized_options=None,
1196 | is_extendable=False,
1197 | syntax='proto3',
1198 | extension_ranges=[],
1199 | oneofs=[
1200 | ],
1201 | serialized_start=2758,
1202 | serialized_end=2813,
1203 | )
1204 |
1205 | _ACCOUNTDETAILS1.fields_by_name['wxid'].message_type = _WECHATSTRING
1206 | _ACCOUNTDETAILS1.fields_by_name['nickname'].message_type = _WECHATSTRING
1207 | _ACCOUNTDETAILS1.fields_by_name['email'].message_type = _WECHATSTRING
1208 | _ACCOUNTDETAILS1.fields_by_name['phone'].message_type = _WECHATSTRING
1209 | _ACCOUNTDETAILS2.fields_by_name['wechatMoments'].message_type = _WECHATMOMENTS
1210 | _ACCOUNTDETAILSDATA.fields_by_name['accountDetails1'].message_type = _ACCOUNTDETAILS1
1211 | _ACCOUNTDETAILSDATA.fields_by_name['accountDetails2'].message_type = _ACCOUNTDETAILS2
1212 | _MESSAGE.fields_by_name['messageDetail'].message_type = _MESSAGEDETAIL
1213 | _MESSAGELIST.fields_by_name['message'].message_type = _MESSAGE
1214 | _MESSAGEDATA.fields_by_name['messageList'].message_type = _MESSAGELIST
1215 | _CHATMESSAGE.fields_by_name['wxidFrom'].message_type = _WECHATSTRING
1216 | _CHATMESSAGE.fields_by_name['wxidTo'].message_type = _WECHATSTRING
1217 | _CHATMESSAGE.fields_by_name['content'].message_type = _WECHATSTRING
1218 | _CHATMESSAGE.fields_by_name['imageOverview'].message_type = _IMAGEOVERVIEW
1219 | _GROUPMEMBERLIST.fields_by_name['groupMember'].message_type = _GROUPMEMBER
1220 | _CONTACTPHONE.fields_by_name['phone'].message_type = _WECHATSTRING
1221 | _CONTACTDETAILS.fields_by_name['wxid'].message_type = _WECHATSTRING
1222 | _CONTACTDETAILS.fields_by_name['nickname'].message_type = _WECHATSTRING
1223 | _CONTACTDETAILS.fields_by_name['nicknamePinyinUppercase'].message_type = _WECHATSTRING
1224 | _CONTACTDETAILS.fields_by_name['nicknamePinyin'].message_type = _WECHATSTRING
1225 | _CONTACTDETAILS.fields_by_name['remark'].message_type = _WECHATSTRING
1226 | _CONTACTDETAILS.fields_by_name['remarkPinyinUppercase'].message_type = _WECHATSTRING
1227 | _CONTACTDETAILS.fields_by_name['remarkPinyin'].message_type = _WECHATSTRING
1228 | _CONTACTDETAILS.fields_by_name['weChatMoments'].message_type = _WECHATMOMENTS
1229 | _CONTACTDETAILS.fields_by_name['groupMemberList'].message_type = _GROUPMEMBERLIST
1230 | _CONTACTDETAILS.fields_by_name['contactPhone'].message_type = _CONTACTPHONE
1231 | _CONTACTDETAILSDATA.fields_by_name['contactDetails'].message_type = _CONTACTDETAILS
1232 | _CREATEGROUPMEMBERDATA.fields_by_name['wxid'].message_type = _WECHATSTRING
1233 | _GROUPMEMBERDETAILSLIST.fields_by_name['groupMemberDetails'].message_type = _GROUPMEMBERDETAILS
1234 | _GROUPMEMBERDETAILSLISTDATA.fields_by_name['groupMemberDetailsList'].message_type = _GROUPMEMBERDETAILSLIST
1235 | _LOGINQRCODEDATA.fields_by_name['loginQRCode'].message_type = _LOGINQRCODE
1236 | DESCRIPTOR.message_types_by_name['WeChatString'] = _WECHATSTRING
1237 | DESCRIPTOR.message_types_by_name['AccountDetails1'] = _ACCOUNTDETAILS1
1238 | DESCRIPTOR.message_types_by_name['WeChatMoments'] = _WECHATMOMENTS
1239 | DESCRIPTOR.message_types_by_name['AccountDetails2'] = _ACCOUNTDETAILS2
1240 | DESCRIPTOR.message_types_by_name['AccountDetailsData'] = _ACCOUNTDETAILSDATA
1241 | DESCRIPTOR.message_types_by_name['MessageDetail'] = _MESSAGEDETAIL
1242 | DESCRIPTOR.message_types_by_name['Message'] = _MESSAGE
1243 | DESCRIPTOR.message_types_by_name['MessageList'] = _MESSAGELIST
1244 | DESCRIPTOR.message_types_by_name['MessageData'] = _MESSAGEDATA
1245 | DESCRIPTOR.message_types_by_name['ImageOverview'] = _IMAGEOVERVIEW
1246 | DESCRIPTOR.message_types_by_name['ChatMessage'] = _CHATMESSAGE
1247 | DESCRIPTOR.message_types_by_name['GroupMember'] = _GROUPMEMBER
1248 | DESCRIPTOR.message_types_by_name['GroupMemberList'] = _GROUPMEMBERLIST
1249 | DESCRIPTOR.message_types_by_name['ContactPhone'] = _CONTACTPHONE
1250 | DESCRIPTOR.message_types_by_name['ContactDetails'] = _CONTACTDETAILS
1251 | DESCRIPTOR.message_types_by_name['ContactDetailsData'] = _CONTACTDETAILSDATA
1252 | DESCRIPTOR.message_types_by_name['CreateGroupMemberData'] = _CREATEGROUPMEMBERDATA
1253 | DESCRIPTOR.message_types_by_name['GroupMemberDetails'] = _GROUPMEMBERDETAILS
1254 | DESCRIPTOR.message_types_by_name['GroupMemberDetailsList'] = _GROUPMEMBERDETAILSLIST
1255 | DESCRIPTOR.message_types_by_name['GroupMemberDetailsListData'] = _GROUPMEMBERDETAILSLISTDATA
1256 | DESCRIPTOR.message_types_by_name['LoginQRCode'] = _LOGINQRCODE
1257 | DESCRIPTOR.message_types_by_name['LoginQRCodeData'] = _LOGINQRCODEDATA
1258 | _sym_db.RegisterFileDescriptor(DESCRIPTOR)
1259 |
1260 | WeChatString = _reflection.GeneratedProtocolMessageType('WeChatString', (_message.Message,), {
1261 | 'DESCRIPTOR' : _WECHATSTRING,
1262 | '__module__' : 'wx_pb2'
1263 | # @@protoc_insertion_point(class_scope:wx.WeChatString)
1264 | })
1265 | _sym_db.RegisterMessage(WeChatString)
1266 |
1267 | AccountDetails1 = _reflection.GeneratedProtocolMessageType('AccountDetails1', (_message.Message,), {
1268 | 'DESCRIPTOR' : _ACCOUNTDETAILS1,
1269 | '__module__' : 'wx_pb2'
1270 | # @@protoc_insertion_point(class_scope:wx.AccountDetails1)
1271 | })
1272 | _sym_db.RegisterMessage(AccountDetails1)
1273 |
1274 | WeChatMoments = _reflection.GeneratedProtocolMessageType('WeChatMoments', (_message.Message,), {
1275 | 'DESCRIPTOR' : _WECHATMOMENTS,
1276 | '__module__' : 'wx_pb2'
1277 | # @@protoc_insertion_point(class_scope:wx.WeChatMoments)
1278 | })
1279 | _sym_db.RegisterMessage(WeChatMoments)
1280 |
1281 | AccountDetails2 = _reflection.GeneratedProtocolMessageType('AccountDetails2', (_message.Message,), {
1282 | 'DESCRIPTOR' : _ACCOUNTDETAILS2,
1283 | '__module__' : 'wx_pb2'
1284 | # @@protoc_insertion_point(class_scope:wx.AccountDetails2)
1285 | })
1286 | _sym_db.RegisterMessage(AccountDetails2)
1287 |
1288 | AccountDetailsData = _reflection.GeneratedProtocolMessageType('AccountDetailsData', (_message.Message,), {
1289 | 'DESCRIPTOR' : _ACCOUNTDETAILSDATA,
1290 | '__module__' : 'wx_pb2'
1291 | # @@protoc_insertion_point(class_scope:wx.AccountDetailsData)
1292 | })
1293 | _sym_db.RegisterMessage(AccountDetailsData)
1294 |
1295 | MessageDetail = _reflection.GeneratedProtocolMessageType('MessageDetail', (_message.Message,), {
1296 | 'DESCRIPTOR' : _MESSAGEDETAIL,
1297 | '__module__' : 'wx_pb2'
1298 | # @@protoc_insertion_point(class_scope:wx.MessageDetail)
1299 | })
1300 | _sym_db.RegisterMessage(MessageDetail)
1301 |
1302 | Message = _reflection.GeneratedProtocolMessageType('Message', (_message.Message,), {
1303 | 'DESCRIPTOR' : _MESSAGE,
1304 | '__module__' : 'wx_pb2'
1305 | # @@protoc_insertion_point(class_scope:wx.Message)
1306 | })
1307 | _sym_db.RegisterMessage(Message)
1308 |
1309 | MessageList = _reflection.GeneratedProtocolMessageType('MessageList', (_message.Message,), {
1310 | 'DESCRIPTOR' : _MESSAGELIST,
1311 | '__module__' : 'wx_pb2'
1312 | # @@protoc_insertion_point(class_scope:wx.MessageList)
1313 | })
1314 | _sym_db.RegisterMessage(MessageList)
1315 |
1316 | MessageData = _reflection.GeneratedProtocolMessageType('MessageData', (_message.Message,), {
1317 | 'DESCRIPTOR' : _MESSAGEDATA,
1318 | '__module__' : 'wx_pb2'
1319 | # @@protoc_insertion_point(class_scope:wx.MessageData)
1320 | })
1321 | _sym_db.RegisterMessage(MessageData)
1322 |
1323 | ImageOverview = _reflection.GeneratedProtocolMessageType('ImageOverview', (_message.Message,), {
1324 | 'DESCRIPTOR' : _IMAGEOVERVIEW,
1325 | '__module__' : 'wx_pb2'
1326 | # @@protoc_insertion_point(class_scope:wx.ImageOverview)
1327 | })
1328 | _sym_db.RegisterMessage(ImageOverview)
1329 |
1330 | ChatMessage = _reflection.GeneratedProtocolMessageType('ChatMessage', (_message.Message,), {
1331 | 'DESCRIPTOR' : _CHATMESSAGE,
1332 | '__module__' : 'wx_pb2'
1333 | # @@protoc_insertion_point(class_scope:wx.ChatMessage)
1334 | })
1335 | _sym_db.RegisterMessage(ChatMessage)
1336 |
1337 | GroupMember = _reflection.GeneratedProtocolMessageType('GroupMember', (_message.Message,), {
1338 | 'DESCRIPTOR' : _GROUPMEMBER,
1339 | '__module__' : 'wx_pb2'
1340 | # @@protoc_insertion_point(class_scope:wx.GroupMember)
1341 | })
1342 | _sym_db.RegisterMessage(GroupMember)
1343 |
1344 | GroupMemberList = _reflection.GeneratedProtocolMessageType('GroupMemberList', (_message.Message,), {
1345 | 'DESCRIPTOR' : _GROUPMEMBERLIST,
1346 | '__module__' : 'wx_pb2'
1347 | # @@protoc_insertion_point(class_scope:wx.GroupMemberList)
1348 | })
1349 | _sym_db.RegisterMessage(GroupMemberList)
1350 |
1351 | ContactPhone = _reflection.GeneratedProtocolMessageType('ContactPhone', (_message.Message,), {
1352 | 'DESCRIPTOR' : _CONTACTPHONE,
1353 | '__module__' : 'wx_pb2'
1354 | # @@protoc_insertion_point(class_scope:wx.ContactPhone)
1355 | })
1356 | _sym_db.RegisterMessage(ContactPhone)
1357 |
1358 | ContactDetails = _reflection.GeneratedProtocolMessageType('ContactDetails', (_message.Message,), {
1359 | 'DESCRIPTOR' : _CONTACTDETAILS,
1360 | '__module__' : 'wx_pb2'
1361 | # @@protoc_insertion_point(class_scope:wx.ContactDetails)
1362 | })
1363 | _sym_db.RegisterMessage(ContactDetails)
1364 |
1365 | ContactDetailsData = _reflection.GeneratedProtocolMessageType('ContactDetailsData', (_message.Message,), {
1366 | 'DESCRIPTOR' : _CONTACTDETAILSDATA,
1367 | '__module__' : 'wx_pb2'
1368 | # @@protoc_insertion_point(class_scope:wx.ContactDetailsData)
1369 | })
1370 | _sym_db.RegisterMessage(ContactDetailsData)
1371 |
1372 | CreateGroupMemberData = _reflection.GeneratedProtocolMessageType('CreateGroupMemberData', (_message.Message,), {
1373 | 'DESCRIPTOR' : _CREATEGROUPMEMBERDATA,
1374 | '__module__' : 'wx_pb2'
1375 | # @@protoc_insertion_point(class_scope:wx.CreateGroupMemberData)
1376 | })
1377 | _sym_db.RegisterMessage(CreateGroupMemberData)
1378 |
1379 | GroupMemberDetails = _reflection.GeneratedProtocolMessageType('GroupMemberDetails', (_message.Message,), {
1380 | 'DESCRIPTOR' : _GROUPMEMBERDETAILS,
1381 | '__module__' : 'wx_pb2'
1382 | # @@protoc_insertion_point(class_scope:wx.GroupMemberDetails)
1383 | })
1384 | _sym_db.RegisterMessage(GroupMemberDetails)
1385 |
1386 | GroupMemberDetailsList = _reflection.GeneratedProtocolMessageType('GroupMemberDetailsList', (_message.Message,), {
1387 | 'DESCRIPTOR' : _GROUPMEMBERDETAILSLIST,
1388 | '__module__' : 'wx_pb2'
1389 | # @@protoc_insertion_point(class_scope:wx.GroupMemberDetailsList)
1390 | })
1391 | _sym_db.RegisterMessage(GroupMemberDetailsList)
1392 |
1393 | GroupMemberDetailsListData = _reflection.GeneratedProtocolMessageType('GroupMemberDetailsListData', (_message.Message,), {
1394 | 'DESCRIPTOR' : _GROUPMEMBERDETAILSLISTDATA,
1395 | '__module__' : 'wx_pb2'
1396 | # @@protoc_insertion_point(class_scope:wx.GroupMemberDetailsListData)
1397 | })
1398 | _sym_db.RegisterMessage(GroupMemberDetailsListData)
1399 |
1400 | LoginQRCode = _reflection.GeneratedProtocolMessageType('LoginQRCode', (_message.Message,), {
1401 | 'DESCRIPTOR' : _LOGINQRCODE,
1402 | '__module__' : 'wx_pb2'
1403 | # @@protoc_insertion_point(class_scope:wx.LoginQRCode)
1404 | })
1405 | _sym_db.RegisterMessage(LoginQRCode)
1406 |
1407 | LoginQRCodeData = _reflection.GeneratedProtocolMessageType('LoginQRCodeData', (_message.Message,), {
1408 | 'DESCRIPTOR' : _LOGINQRCODEDATA,
1409 | '__module__' : 'wx_pb2'
1410 | # @@protoc_insertion_point(class_scope:wx.LoginQRCodeData)
1411 | })
1412 | _sym_db.RegisterMessage(LoginQRCodeData)
1413 |
1414 |
1415 | # @@protoc_insertion_point(module_scope)
1416 |
--------------------------------------------------------------------------------
/PyWeChatSpy/service/API.md:
--------------------------------------------------------------------------------
1 | # SpyService接口文档
2 |
3 | ## 1. 打开微信
4 | ### 1.1 功能描述
5 | 唤起微信客户端并返回微信客户端标识port
6 | ### 1.2 请求说明
7 | > 请求方式:GET
8 | 请求URL :[/open_wechat]()
9 |
10 | ### 1.3 请求参数
11 | 无
12 | ### 1.4 返回结果
13 | ```json
14 | {
15 | "code": 1,
16 | "port": 50866
17 | }
18 | ```
19 | ### 1.5 返回参数
20 | 字段 |字段类型 |字段说明
21 | ------------|-----------|-----------
22 | code |int |状态码
23 | port |int |微信客户端标识
24 | ### 1.6 状态码
25 | 状态码 |说明
26 | ------------|-----------
27 | 1 |成功
28 | 0 |失败
29 | ---
30 | ## 2. 获取登录二维码
31 | ### 2.1 功能描述
32 | 获取微信登录二维码供用户扫码登录
33 | ### 2.2 请求说明
34 | > 请求方式:GET
35 | 请求URL :[/get_login_qrcode/\]()
36 |
37 | ### 2.3 请求参数
38 | 字段 |字段类型 |字段说明
39 | ------------|-----------|-----------
40 | port |int |微信客户端标识
41 | ### 2.4 返回结果
42 | ```json
43 | {
44 | "code": 1,
45 | "qrcode": "iVBORw0KGgoAAAANSUhEUgAAALkAAAC5CAYAAAB0rZ5cAAAOg0lEQVR4Ae3BwZHsypJDwQMa1UHqL0e0QJhZB2sRxma925+W7gLCH5FENJLCTUnEl0kKTRLRSAoDSUQjKTRJxE2Swk1JxICk8EectvnLbPOX2WbCNnfZ5km2+Tbb/BUHGxuvdrCx8WoHGxuvdvJBVfFtay2eVFXcJSkMJBFNVdFJCk0Svk1SGLDNv1BVfNtai+7kM/F94VniJtv8gmhshyvxZbb548T3heZgY+PVDjY2Xu1gY+PVToYkhZuSiJuqirskhSaJeJCk0CShkxRusk0nKTRJeNJai05SaJKImySFm5KIgZMh2/wj4ibbfJttPhCN7fAg23wgnhUa2zzJNt92sLHxagcbG692sLHxaid/nKTQJBE3SQpNEu6qKiaqiom1Fl1VsXHbyR9nmyfZ5gNxn5gRM+FKbNx1sLHxagcbG692sLHxaif/gySFgSTcJSk0SUQjKQwkEY2k0CShkxS+LIl4qZP/QbYZEjfZZsI2d9nmA9HYDht3HWxsvNrBxsarHWxsvNrJUFXxl1UV3yYpNEno1lp0kkJjm05SaGwzUVVMrLXoJIXGNt9WVXzbyZz428SX2eYDcRUa20zY5hfETGhs84+ILzvY2Hi1g42NVzvY2Hi1kw8khS+zzV1VRScpNElEIyk0ScRAVdFJCk0SurUWXVXRrbXoqopurcWEpNAkoVtr0VUV3VqLuySFL7NNd/KBbf440dgOA7b5BdHYDlfiKlyJq3AlrsKAbT4QV+FKXIWbbPMvHGxsvNrBxsarHWxsvNpZVfxlVcVdkkKThImqopMUGtt0kkJjm05SaJLQSQqNbTpJobHNk6qKiarirzgB8beJm2zzgZgRje0wYJsJ23wgGtthwDb/ATEj/oiDjY1XO9jYeLWDjY1XO/kFSaFJIgYkhSaJuKmq6NZadJJCk0QMVBUTay0mqoq7qoqJtRZ3SQoDScSApHBTEtFICgMnv2Cbu2zzMHEVGtv8gpgJM+I+MRNuss2TbPMk20wcbGy82sHGxqsdbGy82skvVBV3VRVPkhSaJDxJUmiSiIGqopMUBmwzISk0SegkhSYJ3VqLCUlhIAn/wsnviPvEg2zzgXiQbX5BNLbDg2zzgWhshytxFQZsMyT+gYONjVc72Nh4tYONjVc7JYWBJOImSWEgiWgkhQHbTEgKTRLxoKqikxSaJHRrLbqq4klVxURVcddai05SaJKIAUmhSUK31qI7bfNttrnLNk+yzX9ANLbDlbgKV+JZYkbcFxrb3GWbD8RVaA42Nl7tYGPj1Q42Nl7t5BckhSaJaKqKCUmhsU1XVXRrLSaqiglJobHNt1UVE5JCk4ROUhhIIh5UVXRrLTpJoUkimqpioqroTn7BNkNiwHaYEVdhRgzY5h8RA7b5QDS2w78hrkJjmyExI5qDjY1XO9jYeLWDjY1XO3mYpNAkEY2k0NjmrqpiQlIYSMKEpNAkETdJCk0SMSApNLZ5kqTQJBGNpNAk4V84eZhtJmzzMDFgmyExYDs8yDZ32ebbbDNhmw/EP3CwsfFqBxsbr3awsfFqJx9UFRNVxYSk0CThSZLCQBK6tRadpNAkEU1V0UkKTRI6SaFJwkRV0a216KqKbq3FXVXFXZJCk0Q0kkKTRDSSwsDJZ2JGDNgOV+JBthkSV6GxzZBobIcr0dgOV2JGXIUrcRXuEzfZZsI2E7aZONjYeLWDjY1XO9jYeLWTIUnhJtt0ksKDbNNVFZ2k0CThSVVFJyk0tukkhZuS0EkKjW06SaFJIgYkhcY2XVXRSQpNEjpJoUlCt9aiOxmyzZNs8x8Qje1wJZ4lGtthwDa/IBrbYcA2d9lmSDS2w5VobIcrcRWag42NVzvY2Hi1g42NVzsZqir+irUW3yYpDCQRf1hV0a21eFJVMSEpNEmYqCo6SaFJQncyJ/6O8GW2eQlxFZ4lBmyHKzEjGtvhSjQHGxuvdrCx8WoHGxuvdlYVnaTQJBGNpNAkEQOSQpNENJJCY5uuqvgXJIUB23RVxcRai66q6CSFgSQ8SVIYSMKEpDCQhIkTEI3tMGCbu2wzYZsh8Q/Y5hfETLgSje0wIx5kmyExYJshMXCwsfFqBxsbr3awsfFqp6TQ2GaiqugkhYEkdJJCY5uuqugkhSaJGJAUGtvcVVV0ay3uqiomqopurUUnKQwkEY2k0NjmLkmhsc1dkkJz2uYXRGM7zIjGdpgRje1wk20eJq7CfWJGXIXGNnfZ5km2eZJtuoONjVc72Nh4tYONjVc7q4oJSaFJIgaqik5SaJIwISk0tpmoKibWWnRVxYSk0CRhQlIYSCIGqopurcW3VRUTVUW31mJCUmhs052AGLAd7hON7XAlBmyH+8RMuBIDtsOVGLDNw8RV+D4xI67CgG0mDjY2Xu1gY+PVDjY2Xu2UFJokYkBSaJIwUVV0ksKAbbqqopMUmiSikRSaJHSSQpNEPKiq6NZadJLCTUno1lpMVBV3SQoDSejWWnRVRbfWojttc5dtPhAzorEd7hON7TBgmw9EYzt8n7gKjW1+QVyFGXGTbYbEVbgSV6E52Nh4tYONjVc72Nh4tZMPJIUmCd1ai05SaJKIRlJobNNVFU+SFBrbTFQVnaTQJOEuSaFJQrfWoqsqJiSFxjadpPAg29xVVXSSQpOE7uQD23wgrkJjmwnbDIkH2eYXRGM7XImbbPOBuApXYsB2GLDNHyIa2+FKNAcbG692sLHxagcbG692VhV3VRUTkkKThG6tRScpDCQRA1VFt9ZiQlJokjAhKQzYZqKqmJAUGtt0VcWT1lp0VcVdkkJjm05SaE5A3CcGbIcrcRUa2zxMXIUB23wgBmzzMDFgmyHxrHAlbrLNhG26g42NVzvY2Hi1g42NVzslhYEkopEUmiRiQFJobNNVFXdVFRNVxV2SwoBtuqqiW2vRSQoDScRNkkKTRDSSQpNEDEgKN9nmrtM2d9nmLtsMifvEjLjJNr8grkJjm2+zzYRt7rLNv3CwsfFqBxsbr3awsfFqZ1XRrbW4S1JobNNVFd1ai2+TFJok4kFVRbfWopMUmiR0ay3uqiq6tRZdVXGXpNDYpqsqurUWXVUxsdZi4gTEVbjJNkPiKnyZbf4D4io0tvlAXIX7xFW4EjfZZkhchSsxEwYONjZe7WBj49UONjZeTUBokvCBuAo3SaKzTffz80OXRAxICk0SOklM2Gbi5+eHLglD4io0ay26n58fJpLwgWgkhSYJE2stuqoSV+FKzIRmrUV32uYDMSNush0GbHOXbT4Qje3wINt8IO4TV6GxzZAYsM0HYibMiPvEVWgONjZe7WBj49UONjZe7awqJiSFgSRioKro1lp0VUUnKTRJxICk0Nimqyom1lp0VUUnKTRJxICk0CShW2txl6TQJKGTFJokYkBSaJKIRlJokoibTkAM2OZh4ipcicZ2uMk2Q2ImXInGdrjJNh+Iq3CTbT4Qje1wk20mbPOkg42NVzvY2Hi1g42NVzslhSaJaKqKbq1FJynclIROUmhs00kKTRK6tRYTkkKTRDRVRScpNLbpJIWBJHSSQpOEbq3Fk6qKTlJoktCttZioKjpJoUkiBk7bDImr0NjmF0RjOwzY5gNxFQZsMyQa22HANkOisR2uxFV4lmhshytxFWZEYzvcdLCx8WoHGxuvdrCx8WpnVdFJCk0S0VQVE2stuqqikxQa23RVxZOqim6txZOqim6tRVdVTFQVd0kKjW06SWHANp2k0NjmrqrirhMQje0wI2bClWhshxnxLHEVniWuwpWYETfZZsI2d9nmYeKmg42NVzvY2Hi1g42NVzslhcY2naRwUxI6SaFJwpMkhcY2E1VFJykMJGGiqugkhSaJaCSFAdt0VcVday2eJCk8KAndaZsJ2/yCaGyHK/Eg2/yCaGyHGTEjGtthwDa/IO4LD7LNw0RzsLHxagcbG692sLHxasr/4/vEVbgSjaRwUxK6tRbdz88PXRJxFZq1Fl1ViUZSaJKIq9BIorNNV1V0ay26qhKNpDBgm66quGutRVdVTKy16H5+fuhOQPwbYsA2vyCuQmObIXEVBmwzJBrbYUZchQHb/IK4L1yJmdDYpjvY2Hi1g42NVzvY2Hi1U1L4I5KIpqro1lp0VcVEVdGttZiQFJokdJJCk4ROUmiSiKaq+LaqoltrcZek0CQRN0kKjW0mTtv8ceIqXIkZcRUGbPOBaGyHK9HYDjPi+8RVuMk2T7LNXQcbG692sLHxagcbG6928kFV8W1rLb5NUhhIwpOqik5SaJIwISkMJBFNVTEhKTRJ6NZaTFQV31ZVTJx8Jr4vfJlthsSzRGM7XIkB2/yCGLDNB+IqzIjvEwMHGxuvdrCx8WoHGxuvdjIkKdyURHyZpNDYZkJSaJKIpqroJIUmiRiQFJokoqkq7pIUBpJwl6Rwk206SaFJQicpNElEczJkm7/MNnfZZkg0tsNNthkSN9lmSNxkmyfZ5gPR2A4DBxsbr3awsfFqBxsbr3byx0kKTRLuWmvRVRV3VRWdpNDY5tskhSYJd0kKjW0mqopurcVEVdFJCo1tOkmhOfnjbPOBuC9ciftEYzv8A7b5QNxkm18QV2FGNLbDgG26g42NVzvY2Hi1g42NVzv546qKCUlhIAkTkkKTRDSSQpOEuySFm5IwISkMJOFJVUW31uKuqqJba9Gd/H1iwDZDYsA2E7b5QNxkO9wnBmwzJJ4lrsJ94io0Bxsbr3awsfFqBxsbr3YyVFX8FZJCY5u7JIXGNndJCgNJxE1VRScpDNhmQlIYSCJuqio6SaFJwkRV0Z3MiT/CNk+yzZNs8x8Qje3wINv8B0RjO1yJGdEcbGy82sHGxqsdbGy82skHksKX2ebbqoonSQpNErq1Fl1VMVFVdGstJqqKb1tr0UkKD0rChKQwcPKBbV5CPMg2H4ircCVmxFWYEd8XGts8TAzYZuJgY+PVDjY2Xu1gY+PV/g8/WblifiTBwQAAAABJRU5ErkJggg=="
46 | }
47 | ```
48 | ### 2.5 返回参数
49 | 字段 |字段类型 |字段说明
50 | ------------|-----------|-----------
51 | code |int |状态码
52 | qrcode |string |登录二维码base64编码字符串
53 | ### 2.6 状态码
54 | 状态码 |说明
55 | ------------|-----------
56 | 0 |获取二维码超时
57 | -1 |port错误
58 | 1 |成功
59 | ---
60 | ## 3. 登出微信
61 | ### 3.1 功能描述
62 | 用户主动退出PC微信客户端登录
63 | ### 3.2 请求说明
64 | > 请求方式:GET
65 | 请求URL :[/user_logout/\]()
66 |
67 | ### 3.3 请求参数
68 | 字段 |字段类型 |字段说明
69 | ------------|-----------|-----------
70 | port |int |微信客户端标识
71 | ### 3.4 返回结果
72 | ```json
73 | {
74 | "code": 1
75 | }
76 | ```
77 | ### 3.5 返回参数
78 | 字段 |字段类型 |字段说明
79 | ------------|-----------|-----------
80 | code |int |状态码
81 | ### 3.6 状态码
82 | 状态码 |说明
83 | ------------|-----------
84 | 0 |失败
85 | -1 |port错误
86 | 1 |成功
87 | ---
88 | ## 4. 关闭微信客户端
89 | ### 4.1 功能描述
90 | 用户关闭服务器上的微信客户端
91 | ### 4.2 请求说明
92 | > 请求方式:GET
93 | 请求URL :[/close_wechat/\]()
94 |
95 | ### 4.3 请求参数
96 | 字段 |字段类型 |字段说明
97 | ------------|-----------|-----------
98 | port |int |微信客户端标识
99 | ### 4.4 返回结果
100 | ```json
101 | {
102 | "code": 1
103 | }
104 | ```
105 | ### 4.5 返回参数
106 | 字段 |字段类型 |字段说明
107 | ------------|-----------|-----------
108 | code |int |状态码
109 | ### 4.6 状态码
110 | 状态码 |说明
111 | ------------|-----------
112 | 0 |失败
113 | -1 |port错误
114 | 1 |成功
115 | ---
116 | ## 5. 获取微信登录状态
117 | ### 5.1 功能描述
118 | 获取微信登录状态
119 | ### 5.2 请求说明
120 | > 请求方式:GET
121 | 请求URL :[/get_login_status/\]()
122 |
123 | ### 5.3 请求参数
124 | 字段 |字段类型 |字段说明
125 | ------------|-----------|-----------
126 | port |int |微信客户端标识
127 | ### 5.4 返回结果
128 | ```json
129 | {
130 | "code": 1,
131 | "status": "0"
132 | }
133 | ```
134 | ### 5.5 返回参数
135 | 字段 |字段类型 |字段说明
136 | ------------|-----------|-----------
137 | code |int |状态码
138 | status |string |登录状态 "0":未登录/'1":登录
139 | ### 5.6 状态码
140 | 状态码 |说明
141 | ------------|-----------
142 | 0 |获取二维码超时
143 | -1 |port错误
144 | 1 |成功
145 | ---
146 | ## 6. 获取登录信息
147 | ### 6.1 功能描述
148 | 获取用户当前登录微信账号基本信息
149 | ### 6.2 请求说明
150 | > 请求方式:GET
151 | 请求URL :[/get_login_info/\]()
152 |
153 | ### 6.3 请求参数
154 | 字段 |字段类型 |字段说明
155 | ------------|-----------|-----------
156 | port |int |微信客户端标识
157 | ### 6.4 返回结果
158 | ```json
159 | {
160 | "code": 1,
161 | "wxid": "",
162 | "nickname":"",
163 | "wechatid":"",
164 | "profile_photo_hd":"",
165 | "profile_photo":"",
166 | "phone":"",
167 | "sex":""
168 | }
169 | ```
170 | ### 6.5 返回参数
171 | 字段 |字段类型 |字段说明
172 | ------------|-----------|-----------
173 | code |int |状态码
174 | wxid |string |微信唯一标识
175 | nickname |string |昵称
176 | wechatid |string |微信号
177 | profile_photo_hd |string |高清头像url
178 | profile_photo |string |头像url
179 | phone |string |手机号
180 | sex |string |性别
181 | ### 6.6 状态码
182 | 状态码 |说明
183 | ------------|-----------
184 | 0 |获取登录信息超时
185 | -1 |port错误
186 | 1 |成功
187 | ---
188 | ## 7. 获取联系人列表
189 | ### 7.1 功能描述
190 | 获取微信联系人列表,包括好友与群
191 | ### 7.2 请求说明
192 | > 请求方式:GET
193 | 请求URL :[/get_contact_list/\]()
194 |
195 | ### 7.3 请求参数
196 | 字段 |字段类型 |字段说明
197 | ------------|-----------|-----------
198 | port |int |微信客户端标识
199 | ### 7.4 返回结果
200 | ```json
201 | {
202 | "code": 1,
203 | "contacts": [{"wxid":"", "nickname":"", "remark":""},.....]
204 | }
205 | ```
206 | ### 7.5 返回参数
207 | 字段 |字段类型 |字段说明
208 | ------------|-----------|-----------
209 | code |int |状态码
210 | contacts |list |联系人列表
211 |
212 | 字段 |字段类型 |字段说明
213 | ------------|-----------|-----------
214 | wxid |string |联系人微信唯一标识
215 | nickname |string |联系人昵称
216 | remark |string |联系人备注
217 |
218 | ### 7.6 状态码
219 | 状态码 |说明
220 | ------------|-----------
221 | 0 |获取联系人列表超时
222 | -1 |port错误
223 | 1 |成功
224 | ---
225 | ## 8. 获取联系人详情
226 | ### 8.1 功能描述
227 | 获取联系人、群成员详情或获取群成员列表
228 | ### 8.2 请求说明
229 | > 请求方式:POST(json)
230 | 请求URL :[/get_contact_details/\]()
231 |
232 | ### 8.3 请求参数
233 | 字段 |字段类型 |字段说明
234 | ------------|-----------|-----------
235 | port |int |微信客户端标识
236 | wxid |string |联系人唯一标识
237 | ### 8.4 返回结果
238 | ```json
239 | {
240 | "code": 1,
241 | "wxid": "",
242 | "nickname":"",
243 | "remark":"",
244 | "profile_photo:"",
245 | "is_group":False,
246 | "group_owner":"",
247 | "group_member_count":0,
248 | "group_members":[{"wxid":"", "nickname":""},......]
249 | }
250 | ```
251 | ### 8.5 返回参数
252 | 字段 |字段类型 |字段说明
253 | ------------|-----------|-----------
254 | code |int |状态码
255 | wxid |string |联系人唯一标识
256 | nickname |string |联系人昵称
257 | remark |string |联系人备注
258 | profile_photo |string |联系人头像
259 | is_group |bool |该联系人是否为群聊
260 | group_owner |string |群主
261 | group_member_count |int |群成员数量
262 | group_members |list |群成员列表
263 |
264 | 字段 |字段类型 |字段说明
265 | ------------|-----------|-----------
266 | wxid |string |群成员微信唯一标识
267 | nickname |string |群成员微信昵称
268 | ### 8.6 状态码
269 | 状态码 |说明
270 | ------------|-----------
271 | 0 |获取联系人详情超时
272 | -1 |port错误
273 | -2 |请求参数提交模式错误,应当以json提交
274 | -3 |请求参数缺失
275 | 1 |成功
276 | ---
277 | ## 9. 发送文本
278 | ### 9.1 功能描述
279 | 发送文本消息给指定联系人
280 | ### 9.2 请求说明
281 | > 请求方式:POST(json)
282 | 请求URL :[/send_text/\]()
283 |
284 | ### 9.3 请求参数
285 | 字段 |字段类型 |字段说明
286 | ------------|-----------|-----------
287 | port |int |微信客户端标识
288 | wxid |string |消息接收方唯一标识
289 | text |string |消息内容
290 | at_wxid |string |消息需@提醒人唯一标识
291 | ### 9.4 返回结果
292 | ```json
293 | {
294 | "code": 1
295 | }
296 | ```
297 | ### 9.5 返回参数
298 | 字段 |字段类型 |字段说明
299 | ------------|-----------|-----------
300 | code |int |状态码
301 | ### 9.6 状态码
302 | 状态码 |说明
303 | ------------|-----------
304 | 0 |失败
305 | -1 |port错误
306 | -2 |请求参数提交模式错误,应当以json提交
307 | -3 |请求参数缺失
308 | 1 |成功
309 | ---
310 | ## 10. 发送文件
311 | ### 10.1 功能描述
312 | 发送文件、图片消息
313 | ### 10.2 请求说明
314 | > 请求方式:POST(form)
315 | 请求URL :[/send_file/\]()
316 |
317 | ### 10.3 请求参数
318 | 字段 |字段类型 |字段说明
319 | ------------|-----------|-----------
320 | port |int |微信客户端标识
321 | wxid |string |消息接收方唯一标识
322 | file |file |文件
323 | ### 10.4 返回结果
324 | ```json
325 | {
326 | "code": 1
327 | }
328 | ```
329 | ### 10.5 返回参数
330 | 字段 |字段类型 |字段说明
331 | ------------|-----------|-----------
332 | code |int |状态码
333 | ### 10.6 状态码
334 | 状态码 |说明
335 | ------------|-----------
336 | 0 |失败
337 | -1 |port错误
338 | -4 |请求参数提交模式错误,应当以表单提交
339 | -3 |请求参数缺失
340 | 1 |成功
341 | ---
342 | ## 11. 发布群公告
343 | ### 11.1 功能描述
344 | 发布群公告
345 | ### 11.2 请求说明
346 | > 请求方式:POST(json)
347 | 请求URL :[/send_announcement/\]()
348 |
349 | ### 11.3 请求参数
350 | 字段 |字段类型 |字段说明
351 | ------------|-----------|-----------
352 | port |int |微信客户端标识
353 | wxid |string |群唯一标识
354 | text |string |群公告内容
355 | ### 11.4 返回结果
356 | ```json
357 | {
358 | "code": 1
359 | }
360 | ```
361 | ### 11.5 返回参数
362 | 字段 |字段类型 |字段说明
363 | ------------|-----------|-----------
364 | code |int |状态码
365 | ### 11.6 状态码
366 | 状态码 |说明
367 | ------------|-----------
368 | 0 |失败
369 | -1 |port错误
370 | -2 |请求参数提交模式错误,应当以json提交
371 | -3 |请求参数缺失
372 | 1 |成功
373 | ---
374 | ## 12. 接收好友请求
375 | ### 12.1 功能描述
376 | 通过新联系人好友验证
377 | ### 12.2 请求说明
378 | > 请求方式:POST(json)
379 | 请求URL :[/verify_new_contact/\]()
380 |
381 | ### 12.3 请求参数
382 | 字段 |字段类型 |字段说明
383 | ------------|-----------|-----------
384 | port |int |微信客户端标识
385 | encryptusername |string |好友验证参数1
386 | ticket |string |好友验证参数2
387 | ### 12.4 返回结果
388 | ```json
389 | {
390 | "code": 1
391 | }
392 | ```
393 | ### 12.5 返回参数
394 | 字段 |字段类型 |字段说明
395 | ------------|-----------|-----------
396 | code |int |状态码
397 | ### 12.6 状态码
398 | 状态码 |说明
399 | ------------|-----------
400 | 0 |失败
401 | -1 |port错误
402 | -2 |请求参数提交模式错误,应当以json提交
403 | -3 |请求参数缺失
404 | 1 |成功
405 | ---
406 | ## 13. 设置联系人备注
407 | ### 13.1 功能描述
408 | 设置、修改联系人备注
409 | ### 13.2 请求说明
410 | > 请求方式:POST(json)
411 | 请求URL :[/set_remark/\]()
412 |
413 | ### 13.3 请求参数
414 | 字段 |字段类型 |字段说明
415 | ------------|-----------|-----------
416 | port |int |微信客户端标识
417 | wxid |string |联系人唯一标识
418 | remark |string |备注
419 | ### 13.4 返回结果
420 | ```json
421 | {
422 | "code": 1
423 | }
424 | ```
425 | ### 13.5 返回参数
426 | 字段 |字段类型 |字段说明
427 | ------------|-----------|-----------
428 | code |int |状态码
429 | ### 13.6 状态码
430 | 状态码 |说明
431 | ------------|-----------
432 | 0 |失败
433 | -1 |port错误
434 | -2 |请求参数提交模式错误,应当以json提交
435 | -3 |请求参数缺失
436 | 1 |成功
437 | ---
438 | ## 14. 分享群聊
439 | ### 14.1 功能描述
440 | 发送群聊邀请链接给指定好友
441 | ### 14.2 请求说明
442 | > 请求方式:POST(json)
443 | 请求URL :[/share_chatroom/\]()
444 |
445 | ### 14.3 请求参数
446 | 字段 |字段类型 |字段说明
447 | ------------|-----------|-----------
448 | port |int |微信客户端标识
449 | wxid |string |好友唯一标识
450 | group_wxid |string |群聊唯一标识
451 | ### 14.4 返回结果
452 | ```json
453 | {
454 | "code": 1
455 | }
456 | ```
457 | ### 14.5 返回参数
458 | 字段 |字段类型 |字段说明
459 | ------------|-----------|-----------
460 | code |int |状态码
461 | ### 14.6 状态码
462 | 状态码 |说明
463 | ------------|-----------
464 | 0 |失败
465 | -1 |port错误
466 | -2 |请求参数提交模式错误,应当以json提交
467 | -3 |请求参数缺失
468 | 1 |成功
469 | ---
470 | ## 15. 移除群成员
471 | ### 15.1 功能描述
472 | 从群聊中将指定群成员移出该群
473 | ### 15.2 请求说明
474 | > 请求方式:POST(json)
475 | 请求URL :[/remove_chatroom_member/\]()
476 |
477 | ### 15.3 请求参数
478 | 字段 |字段类型 |字段说明
479 | ------------|-----------|-----------
480 | port |int |微信客户端标识
481 | group_wxid |string |群聊唯一标识
482 | wxid |string |群成员唯一标识
483 | ### 15.4 返回结果
484 | ```json
485 | {
486 | "code": 1
487 | }
488 | ```
489 | ### 15.5 返回参数
490 | 字段 |字段类型 |字段说明
491 | ------------|-----------|-----------
492 | code |int |状态码
493 | ### 15.6 状态码
494 | 状态码 |说明
495 | ------------|-----------
496 | 0 |失败
497 | -1 |port错误
498 | -2 |请求参数提交模式错误,应当以json提交
499 | -3 |请求参数缺失
500 | 1 |成功
501 | ---
502 | ## 16. 移除联系人
503 | ### 16.1 功能描述
504 | 删除指定好友
505 | ### 16.2 请求说明
506 | > 请求方式:POST(json)
507 | 请求URL :[/remove_contact/\]()
508 |
509 | ### 16.3 请求参数
510 | 字段 |字段类型 |字段说明
511 | ------------|-----------|-----------
512 | port |int |微信客户端标识
513 | wxid |string |好友唯一标识
514 | ### 16.4 返回结果
515 | ```json
516 | {
517 | "code": 1
518 | }
519 | ```
520 | ### 16.5 返回参数
521 | 字段 |字段类型 |字段说明
522 | ------------|-----------|-----------
523 | code |int |状态码
524 | ### 16.6 状态码
525 | 状态码 |说明
526 | ------------|-----------
527 | 0 |失败
528 | -1 |port错误
529 | -2 |请求参数提交模式错误,应当以json提交
530 | -3 |请求参数缺失
531 | 1 |成功
532 | ---
533 | ## 17. 发送小程序
534 | ### 17.1 功能描述
535 | 发送小程序给指定联系人
536 | ### 17.2 请求说明
537 | > 请求方式:POST(form)
538 | 请求URL :[/send_mini_program/\]()
539 |
540 | ### 17.3 请求参数
541 | 字段 |字段类型 |字段说明
542 | ------------|-----------|-----------
543 | port |int |微信客户端标识
544 | wxid |string |联系人唯一标识
545 | title |string |小程序标题
546 | app_id |string |小程序id
547 | route |string |小程序路由
548 | username |string |小程序用户名
549 | weappiconurl|string |小程序图标url
550 | appname |string |小程序名称
551 | ### 17.4 返回结果
552 | ```json
553 | {
554 | "code": 1
555 | }
556 | ```
557 | ### 17.5 返回参数
558 | 字段 |字段类型 |字段说明
559 | ------------|-----------|-----------
560 | code |int |状态码
561 | ### 17.6 状态码
562 | 状态码 |说明
563 | ------------|-----------
564 | 0 |失败
565 | -1 |port错误
566 | -4 |请求参数提交模式错误,应当以表单提交
567 | -3 |请求参数缺失
568 | 1 |成功
569 | ---
570 | ## 18. 发送链接卡片
571 | ### 18.1 功能描述
572 | 发送链接卡片给指定联系人
573 | ### 18.2 请求说明
574 | > 请求方式:POST(form)
575 | 请求URL :[/send_link_card/\]()
576 |
577 | ### 18.3 请求参数
578 | 字段 |字段类型 |字段说明
579 | ------------|-----------|-----------
580 | port |int |微信客户端标识
581 | wxid |string |联系人唯一标识
582 | title |string |链接卡片标题
583 | desc |string |链接卡片描述
584 | url |string |链接卡片链接
585 | app_id |string |链接卡片id
586 | ### 18.4 返回结果
587 | ```json
588 | {
589 | "code": 1
590 | }
591 | ```
592 | ### 18.5 返回参数
593 | 字段 |字段类型 |字段说明
594 | ------------|-----------|-----------
595 | code |int |状态码
596 | ### 18.6 状态码
597 | 状态码 |说明
598 | ------------|-----------
599 | 0 |失败
600 | -1 |port错误
601 | -4 |请求参数提交模式错误,应当以表单提交
602 | -3 |请求参数缺失
603 | 1 |成功
604 | ---
605 | ## 19. 解密图片
606 | ### 19.1 功能描述
607 | 将接收到的图片解密成jpg格式
608 | ### 19.2 请求说明
609 | > 请求方式:POST(json)
610 | 请求URL :[/decrypt_image/\]()
611 |
612 | ### 19.3 请求参数
613 | 字段 |字段类型 |字段说明
614 | ------------|-----------|-----------
615 | port |int |微信客户端标识
616 | filename |string |图片加密文件名称
617 | ### 19.4 返回结果
618 | 解密后图片bytes
619 | ### 19.5 返回参数
620 |
621 | ### 19.6 状态码
622 |
623 | ---
624 | ## 20. 新建群聊
625 | ### 20.1 功能描述
626 | 创建一个新的群聊
627 | ### 20.2 请求说明
628 | > 请求方式:POST(json)
629 | 请求URL :[/create_chatroom/\]()
630 |
631 | ### 20.3 请求参数
632 | 字段 |字段类型 |字段说明
633 | ------------|-----------|-----------
634 | port |int |微信客户端标识
635 | wxids |string |联系人wxid合集字符串 ","分隔
636 | ### 20.4 返回结果
637 | ```json
638 | {
639 | "code": 1,
640 | "wxid": ""
641 | }
642 | ```
643 | ### 20.5 返回参数
644 | 字段 |字段类型 |字段说明
645 | ------------|-----------|-----------
646 | code |int |状态码
647 | wxid |string |新群聊唯一标识
648 | ### 20.6 状态码
649 | 状态码 |说明
650 | ------------|-----------
651 | 0 |失败
652 | -1 |port错误
653 | -2 |请求参数提交模式错误,应当以json提交
654 | -3 |请求参数缺失
655 | 1 |成功
656 | ---
657 | ## 21. 设置群聊名称
658 | ### 21.1 功能描述
659 | 设置、修改群聊名称
660 | ### 21.2 请求说明
661 | > 请求方式:POST(json)
662 | 请求URL :[/set_chatroom_name/\]()
663 |
664 | ### 21.3 请求参数
665 | 字段 |字段类型 |字段说明
666 | ------------|-----------|-----------
667 | port |int |微信客户端标识
668 | wxid |string |群聊唯一标识
669 | name |string |群聊名称
670 | ### 21.4 返回结果
671 | ```json
672 | {
673 | "code": 1
674 | }
675 | ```
676 | ### 21.5 返回参数
677 | 字段 |字段类型 |字段说明
678 | ------------|-----------|-----------
679 | code |int |状态码
680 | ### 21.6 状态码
681 | 状态码 |说明
682 | ------------|-----------
683 | 0 |失败
684 | -1 |port错误
685 | -2 |请求参数提交模式错误,应当以json提交
686 | -3 |请求参数缺失
687 | 1 |成功
688 | ---
--------------------------------------------------------------------------------
/PyWeChatSpy/service/__init__.py:
--------------------------------------------------------------------------------
1 | from .app import *
2 |
--------------------------------------------------------------------------------
/PyWeChatSpy/service/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask
2 | from ..spy import WeChatSpy
3 | from queue import Queue
4 | from threading import Thread
5 | from ..proto.spy_pb2 import Response, ChatMessage
6 | from ..command import *
7 | from .config import MESSAGE_CALLBACK
8 | import requests
9 |
10 |
11 | class SpyService(Flask):
12 | def __init__(self, import_name,
13 | static_url_path=None,
14 | static_folder="static",
15 | static_host=None,
16 | host_matching=False,
17 | subdomain_matching=False,
18 | template_folder="templates",
19 | instance_path=None,
20 | instance_relative_config=False,
21 | root_path=None,
22 | key=None):
23 | self.last_client_count = 0
24 | self.response_queue = Queue()
25 | self.client2pid = dict()
26 | self.client2wxid = dict()
27 | self.client2login = dict()
28 | self.client2user_logout = dict()
29 | self.client2response = dict()
30 | self.__chat_message = []
31 | self.spy = WeChatSpy(response_queue=self.response_queue, key=key)
32 | super().__init__(import_name,
33 | static_url_path=static_url_path,
34 | static_folder=static_folder,
35 | static_host=static_host,
36 | host_matching=host_matching,
37 | subdomain_matching=subdomain_matching,
38 | template_folder=template_folder,
39 | instance_path=instance_path,
40 | instance_relative_config=instance_relative_config,
41 | root_path=root_path)
42 | t = Thread(target=self.parse)
43 | t.setDaemon(True)
44 | t.start()
45 |
46 | def parse(self):
47 | while True:
48 | data = self.response_queue.get()
49 | if data.type == WECHAT_CONNECTED:
50 | self.client2pid[data.port] = data.pid
51 | self.client2login[data.port] = "0"
52 | elif data.type == WECHAT_DISCONNECT:
53 | self.last_client_count -= 1
54 | elif data.type == WECHAT_LOGIN:
55 | self.client2login[data.port] = "1"
56 | elif data.type == WECHAT_LOGOUT:
57 | self.client2login[data.port] = "0"
58 | elif data.type == CHAT_MESSAGE:
59 | self.__chat_message.append(data)
60 | elif data.type != HEART_BEAT:
61 | if data.type == GET_LOGIN_QRCODE and data.code:
62 | continue
63 | elif data.type == GET_CONTACTS_LIST and data.code:
64 | continue
65 | elif data.type == SEND_TEXT and data.code:
66 | continue
67 | elif data.type == SEND_FILE and data.code:
68 | continue
69 | elif data.type == SEND_MINI_PROGRAM and data.code:
70 | continue
71 | elif data.type == SEND_LINK_CARD and data.code:
72 | continue
73 | elif data.type == CREATE_CHATROOM and data.code:
74 | continue
75 | self.client2response[data.id] = data
76 |
77 | def push_message(self):
78 | while True:
79 | message_data: Response = self.__chat_message.pop()
80 | message_port = message_data.port
81 | chat_message = ChatMessage()
82 | chat_message.ParseFromString(message_data.bytes)
83 | post_data = {
84 | "port": message_port,
85 | "messages": []
86 | }
87 | for message in chat_message.message:
88 | _from = message.wxidFrom.str # 消息发送方
89 | _from_group_member = ""
90 | if _from.endswith("@chatroom"): # 群聊消息
91 | _from_group_member = message.content.str.split(':\n', 1)[0] # 群内发言人
92 | content = message.content.str.split(':\n', 1)[-1] # 群聊消息内容
93 | _file = message.file
94 | post_data["messages"].append({
95 | "type": message.type,
96 | "from": _from,
97 | "to": message.wxidTo.str,
98 | "from_group_member": _from_group_member,
99 | "content": message.content.str,
100 | "timestamp": message.timestamp,
101 | "file": _file
102 | })
103 | try:
104 | requests.post(MESSAGE_CALLBACK, json=post_data)
105 | except Exception as e:
106 | print(e)
107 |
--------------------------------------------------------------------------------
/PyWeChatSpy/service/config.py:
--------------------------------------------------------------------------------
1 | MESSAGE_CALLBACK = ""
2 |
--------------------------------------------------------------------------------
/PyWeChatSpy/spy.py:
--------------------------------------------------------------------------------
1 | import os
2 | from socket import socket, AF_INET, SOCK_STREAM
3 | from threading import Thread
4 | import logging
5 | from .proto import spy_pb2
6 | from .command import *
7 | import subprocess
8 | from queue import Queue
9 | from uuid import uuid4
10 | import sys
11 |
12 |
13 | if not sys.version >= "3.8":
14 | logging.error("微信版本过低,请使用Python3.8.x或更高版本")
15 | exit()
16 |
17 |
18 | class WeChatSpy:
19 | def __init__(self, response_queue=None, key: str = None, logger: logging.Logger = None):
20 | # 付费key
21 | self.__key = key
22 | # 日志模块
23 | if isinstance(logger, logging.Logger):
24 | # 使用自定义logger
25 | self.logger = logger
26 | else:
27 | # 使用默认logger
28 | self.logger = logging.getLogger(__file__)
29 | formatter = logging.Formatter('%(asctime)s [%(threadName)s] %(levelname)s: %(message)s')
30 | sh = logging.StreamHandler()
31 | sh.setFormatter(formatter)
32 | sh.setLevel(logging.DEBUG)
33 | self.logger.addHandler(sh)
34 | self.logger.setLevel(logging.DEBUG)
35 | # response存放队列
36 | if isinstance(response_queue, Queue):
37 | self.__response_queue = response_queue
38 | else:
39 | raise Exception("response_queue must be Queue")
40 | self.pids = []
41 | self.port2client = dict()
42 | host = "127.0.0.1"
43 | port = 9527
44 | self.__socket_server = socket(AF_INET, SOCK_STREAM)
45 | self.__socket_server.bind((host, port))
46 | self.__socket_server.listen(1)
47 | t_start_server = Thread(target=self.__start_server)
48 | t_start_server.daemon = True
49 | t_start_server.name = "spy"
50 | t_start_server.start()
51 | current_path = os.path.split(os.path.abspath(__file__))[0]
52 | helper_path = os.path.join(current_path, "SpyK.exe")
53 | if not os.path.exists(helper_path):
54 | self.logger.error("请检查文件 SpyK.exe 是否被误删")
55 | sys.exit()
56 | subprocess.Popen(f"{helper_path} 3.0")
57 |
58 | def __start_server(self):
59 | while True:
60 | socket_client, client_address = self.__socket_server.accept()
61 | self.port2client[client_address[1]] = socket_client
62 | self.logger.debug(f"A WeChat process from {client_address} successfully connected")
63 | if self.__key:
64 | self.set_commercial(self.__key, port=client_address[1])
65 | t_socket_client_receive = Thread(target=self.receive, args=(socket_client, client_address))
66 | t_socket_client_receive.name = f"wechat {client_address}"
67 | t_socket_client_receive.daemon = True
68 | t_socket_client_receive.start()
69 |
70 | def receive(self, socket_client: socket, client_address: tuple):
71 | recv_bytes = b""
72 | data_size = 0
73 | while True:
74 | try:
75 | _bytes = socket_client.recv(4096)
76 | except Exception as e:
77 | self.port2client.pop(client_address[1])
78 | response = spy_pb2.Response()
79 | response.type = WECHAT_DISCONNECT
80 | response.port = client_address[1]
81 | self.__response_queue.put(response)
82 | return self.logger.warning(f"The WeChat process has disconnected: {e}")
83 | recv_bytes += _bytes
84 | while True:
85 | if not data_size:
86 | if len(recv_bytes) > 3:
87 | data_size = int.from_bytes(recv_bytes[:4], "little")
88 | else:
89 | break
90 | elif data_size <= len(recv_bytes) - 4:
91 | response = spy_pb2.Response()
92 | response.ParseFromString(recv_bytes[4: data_size + 4])
93 | response.port = client_address[1]
94 | self.__response_queue.put(response)
95 | recv_bytes = recv_bytes[data_size + 4:]
96 | data_size = 0
97 | else:
98 | break
99 |
100 | def __send(self, request: spy_pb2.Request, port: int = 0, _id: str = None):
101 | if not port and self.port2client:
102 | socket_client: socket = list(self.port2client.values())[0]
103 | elif not (socket_client := self.port2client.get(port)):
104 | self.logger.error(f"Failure to find socket client by port:{port}")
105 | return False
106 | request.id = _id or uuid4().__str__()
107 | data = request.SerializeToString()
108 | data_length_bytes = int.to_bytes(len(data), length=4, byteorder="little")
109 | try:
110 | socket_client.send(data_length_bytes + data)
111 | return True
112 | except Exception as e:
113 | self.logger.warning(f"The WeChat process {port} has disconnected: {e}")
114 | return False
115 |
116 | def run(self, wechat: str):
117 | sp = subprocess.Popen(wechat)
118 | self.pids.append(sp.pid)
119 | return sp.pid
120 |
121 | def set_commercial(self, key: str, port: int = 0, _id: str = None):
122 | request = spy_pb2.Request()
123 | request.type = PROFESSIONAL_KEY
124 | request.bytes = bytes(key, encoding="utf8")
125 | return self.__send(request, port, _id)
126 |
127 | def get_account_details(self, port: int = 0, _id: str = None):
128 | request = spy_pb2.Request()
129 | request.type = GET_ACCOUNT_DETAILS
130 | return self.__send(request, port, _id)
131 |
132 | def get_contacts(self, port: int = 0, _id: str = None):
133 | request = spy_pb2.Request()
134 | request.type = GET_CONTACTS_LIST
135 | return self.__send(request, port, _id)
136 |
137 | def get_contact_details(self, wxid: str, port: int = 0, _id: str = None):
138 | request = spy_pb2.Request()
139 | request.type = GET_CONTACT_DETAILS
140 | request.bytes = bytes(wxid, encoding="utf8")
141 | return self.__send(request, port, _id)
142 |
143 | def send_text(self, wxid: str, text: str, at_wxid: str = "", port: int = 0, _id: str = None):
144 | if not wxid.endswith("chatroom"):
145 | at_wxid = ""
146 | request = spy_pb2.Request()
147 | request.type = SEND_TEXT
148 | text_message = spy_pb2.TextMessage()
149 | text_message.wxid = wxid
150 | text_message.wxidAt = at_wxid
151 | text_message.text = text
152 | request.bytes = text_message.SerializeToString()
153 | return self.__send(request, port, _id)
154 |
155 | def send_file(self, wxid: str, file_path: str, port: int = 0, _id: str = None):
156 | if not os.path.exists(file_path):
157 | self.logger.error(f"File Not Found {file_path}")
158 | return False
159 | if len(file_path.split("\\")) > 8:
160 | self.logger.error(f"File path is too long: {file_path}")
161 | return False
162 | request = spy_pb2.Request()
163 | request.type = SEND_FILE
164 | file_message = spy_pb2.FileMessage()
165 | file_message.wxid = wxid
166 | file_message.filePath = file_path
167 | request.bytes = file_message.SerializeToString()
168 | return self.__send(request, port, _id)
169 |
170 | def user_logout(self, port: int = 0, _id: str = None):
171 | request = spy_pb2.Request()
172 | request.type = USER_LOGOUT
173 | return self.__send(request, port, _id)
174 |
175 | def accept_new_contact(self, encryptusername: str, ticket: str, port: int = 0, _id: str = None):
176 | request = spy_pb2.Request()
177 | request.type = ACCEPT_NEW_CONTACT
178 | application = spy_pb2.ContactApplication()
179 | application.encryptusername = encryptusername
180 | application.ticket = ticket
181 | request.bytes = application.SerializeToString()
182 | return self.__send(request, port, _id)
183 |
184 | def send_announcement(self, wxid: str, content: str, port: int = 0, _id: str = None):
185 | if not wxid.endswith("chatroom"):
186 | return self.logger.warning("Can only send announcements to chatrooms")
187 | request = spy_pb2.Request()
188 | request.type = SEND_ANNOUNCEMENT
189 | text_message = spy_pb2.TextMessage()
190 | text_message.wxid = wxid
191 | text_message.text = content
192 | request.bytes = text_message.SerializeToString()
193 | return self.__send(request, port, _id)
194 |
195 | def create_chatroom(self, wxid: str, port: int = 0, _id: str = None):
196 | if len(wxid.split(",")) < 2:
197 | return self.logger.warning("This function requires at least two wxids separated by ','")
198 | request = spy_pb2.Request()
199 | request.type = CREATE_CHATROOM
200 | request.bytes = bytes(wxid, encoding="utf8")
201 | return self.__send(request, port, _id)
202 |
203 | def share_chatroom(self, chatroom_wxid: str, wxid: str, port: int = 0, _id: str = None):
204 | request = spy_pb2.Request()
205 | request.type = SHARE_CHATROOM
206 | text_message = spy_pb2.TextMessage()
207 | text_message.wxid = wxid
208 | text_message.text = chatroom_wxid
209 | request.bytes = text_message.SerializeToString()
210 | return self.__send(request, port, _id)
211 |
212 | def remove_chatroom_member(self, chatroom_wxid: str, wxid: str, port: int = 0, _id: str = None):
213 | request = spy_pb2.Request()
214 | request.type = REMOVE_CHATROOM_MEMBER
215 | text_message = spy_pb2.TextMessage()
216 | text_message.wxid = wxid
217 | text_message.text = chatroom_wxid
218 | request.bytes = text_message.SerializeToString()
219 | return self.__send(request, port, _id)
220 |
221 | def remove_contact(self, wxid: str, port: int = 0, _id: str = None):
222 | request = spy_pb2.Request()
223 | request.type = REMOVE_CONTACT
224 | request.bytes = bytes(wxid, encoding="utf8")
225 | return self.__send(request, port, _id)
226 |
227 | def send_mini_program(self, wxid: str, title: str, image_path: str, route: str, app_id: str,
228 | username: str, weappiconurl: str, appname: str, port: int = 0, _id: str = None):
229 | if not os.path.exists(image_path):
230 | self.logger.error(f"Image Not Found {image_path}")
231 | return False
232 | request = spy_pb2.Request()
233 | request.type = SEND_MINI_PROGRAM
234 | xml = spy_pb2.XmlMessage()
235 | xml.wxid = wxid
236 | xml.title = title
237 | xml.appId = app_id
238 | xml.imagePath = image_path
239 | xml.route = route
240 | xml.username = username
241 | xml.weappiconurl = weappiconurl
242 | xml.appname = appname
243 | request.bytes = xml.SerializeToString()
244 | return self.__send(request, port, _id)
245 |
246 | def send_link_card(self, wxid: str, title: str, desc: str, app_id: str,
247 | url: str, image_path: str, port: int = 0, _id: str = None):
248 | if not os.path.exists(image_path):
249 | self.logger.error(f"Image Not Found {image_path}")
250 | return False
251 | request = spy_pb2.Request()
252 | request.type = SEND_LINK_CARD
253 | xml = spy_pb2.XmlMessage()
254 | xml.wxid = wxid
255 | xml.title = title
256 | xml.desc = desc
257 | xml.url = url
258 | xml.appId = app_id
259 | xml.imagePath = image_path
260 | request.bytes = xml.SerializeToString()
261 | return self.__send(request, port, _id)
262 |
263 | def add_contact(self, wxid: str, chatroom_wxid: str = "", greeting: str = "",
264 | add_type: int = 0, port: int = 0, _id: str = None):
265 | # TODO:
266 | request = spy_pb2.Request()
267 | request.cmd = add_type
268 | request.param1 = wxid
269 | if add_type == 1 and not chatroom_wxid:
270 | return
271 | request.param2 = chatroom_wxid
272 | request.param3 = greeting
273 | return self.__send(request, port, _id)
274 |
275 | def get_contact_status(self, wxid: str, port: int = 0, _id: str = None):
276 | request = spy_pb2.Request()
277 | request.type = GET_CONTACT_STATUS
278 | request.bytes = bytes(wxid, encoding="utf8")
279 | return self.__send(request, port, _id)
280 |
281 | def set_chatroom_name(self, wxid: str, name: str, port: int = 0, _id: str = None):
282 | request = spy_pb2.Request()
283 | request.type = SET_CHATROOM_NAME
284 | text_message = spy_pb2.TextMessage()
285 | text_message.wxid = wxid
286 | text_message.text = name
287 | request.bytes = text_message.SerializeToString()
288 | return self.__send(request, port, _id)
289 |
290 | def get_login_qrcode(self, port: int = 0, _id: str = None):
291 | request = spy_pb2.Request()
292 | request.type = GET_LOGIN_QRCODE
293 | return self.__send(request, port, _id)
294 |
295 | def set_remark(self, wxid: str, remark: str, port: int = 0, _id: str = None):
296 | request = spy_pb2.Request()
297 | request.type = SET_REMARK
298 | text_message = spy_pb2.TextMessage()
299 | text_message.wxid = wxid
300 | text_message.text = remark
301 | request.bytes = text_message.SerializeToString()
302 | return self.__send(request, port, _id)
303 |
304 | def get_group_enter_url(self, wxid: str, url: str, port: int = 0, _id: str = None):
305 | request = spy_pb2.Request()
306 | request.type = GET_GROUP_ENTER_URL
307 | text_message = spy_pb2.TextMessage()
308 | text_message.wxid = wxid
309 | text_message.text = url
310 | request.bytes = text_message.SerializeToString()
311 | return self.__send(request, port, _id)
312 |
313 | def decrypt_image(self, source_file: str, target_file: str, port: int = 0, _id: str = None):
314 | if not os.path.exists(source_file):
315 | self.logger.error(f"File Not Found {source_file}")
316 | return False
317 | request = spy_pb2.Request()
318 | request.type = DECRYPT_IMAGE
319 | file_message = spy_pb2.FileMessage()
320 | file_message.wxid = source_file
321 | file_message.filePath = target_file
322 | request.bytes = file_message.SerializeToString()
323 | return self.__send(request, port, _id)
324 |
325 | def send_card(self, wxid: str, card_wxid: str, card_nickname: str, port: int = 0, _id: str = None):
326 | request = spy_pb2.Request()
327 | request.type = SEND_CARD
328 | xml = spy_pb2.XmlMessage()
329 | xml.wxid = wxid
330 | xml.title = card_nickname
331 | xml.username = card_wxid
332 | request.bytes = xml.SerializeToString()
333 | return self.__send(request, port, _id)
334 |
--------------------------------------------------------------------------------
/PyWeChatSpy/ui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/PyWeChatSpy/ui/__init__.py
--------------------------------------------------------------------------------
/PyWeChatSpy/ui/profilephotos/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/PyWeChatSpy/ui/profilephotos/default.png
--------------------------------------------------------------------------------
/PyWeChatSpy/ui/ui.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import (
2 | QApplication,
3 | QWidget,
4 | QHBoxLayout,
5 | QVBoxLayout,
6 | QDesktopWidget,
7 | QPushButton,
8 | QLabel,
9 | QTabWidget,
10 | QMenu, QAction, QTextEdit, QFileDialog, QListWidget, QListWidgetItem, QCheckBox, QMainWindow, QGridLayout, QSplitter)
11 | from PyQt5.QtGui import QPixmap, QCursor
12 | from PyQt5.QtCore import QSize, QThread, pyqtSignal, Qt, QPoint
13 | from lxml import etree
14 | import requests
15 | import sys
16 | from queue import Queue
17 | from time import sleep
18 | from threading import Thread
19 | import os
20 | import re
21 | from PyWeChatSpy import WeChatSpy
22 | import qdarkstyle
23 | from PyWeChatSpy.proto.spy_pb2 import Response, AccountDetails, Contacts
24 | from PyWeChatSpy.command import WECHAT_CONNECTED, WECHAT_LOGIN, WECHAT_LOGOUT, ACCOUNT_DETAILS, CONTACTS_LIST
25 |
26 |
27 | my_response_queue = Queue()
28 | key = None
29 | if os.path.exists("key.txt"):
30 | with open("key.txt", "r") as rf:
31 | key = rf.read()
32 | print("key:", key)
33 | spy = WeChatSpy(response_queue=my_response_queue, key=key)
34 | contact_filter = ("qmessage", "qqmail", "tmessage", "medianote", "floatbottle", "fmessage")
35 | root_dir = os.path.dirname(__file__)
36 | profile_photo_dir = os.path.join(root_dir, "profilephotos")
37 |
38 |
39 | class MsgThread(QThread):
40 | signal = pyqtSignal(Response)
41 |
42 | def __init__(self):
43 | super().__init__()
44 |
45 | def run(self):
46 | while True:
47 | msg = my_response_queue.get()
48 | self.signal.emit(msg)
49 |
50 |
51 | class SendTextEdit(QTextEdit):
52 | def __init__(self, parent):
53 | super().__init__()
54 | self.parent = parent
55 |
56 | def keyPressEvent(self, event):
57 | QTextEdit.keyPressEvent(self, event)
58 | if event.key() == Qt.Key_Return:
59 | if QApplication.keyboardModifiers() == Qt.ControlModifier:
60 | self.append("")
61 | else:
62 | self.parent.send_msg()
63 |
64 |
65 | class SpyUI(QMainWindow):
66 | def __init__(self):
67 | super().__init__()
68 | fg = self.frameGeometry()
69 | center = QDesktopWidget().availableGeometry().center()
70 | fg.moveCenter(center)
71 | self.resize(858, 608)
72 | self.move(fg.topLeft())
73 | self.setWindowTitle("PyWeChatSpyUI Beta 1.3.3")
74 | self.setWindowOpacity(0.7) # 设置窗口透明度
75 | # self.layout_main = QHBoxLayout(self)
76 | # self.layout_left = QVBoxLayout(self)
77 | # self.layout_middle = QVBoxLayout(self)
78 | # self.layout_right = QVBoxLayout(self)
79 | # self.layout_main.addLayout(self.layout_left)
80 | # self.layout_main.addLayout(self.layout_middle)
81 | # self.layout_main.addLayout(self.layout_right)
82 | self._init_ui()
83 | self.main_layout.setSpacing(0)
84 | self.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
85 | self.profile_photos = {}
86 | self.contacts = {}
87 |
88 | def _init_ui(self):
89 | # 主窗体
90 | # 创建窗口主部件
91 | self.main_widget = QWidget()
92 | # 创建主部件的网格布局
93 | self.main_layout = QGridLayout()
94 | # 设置窗口主部件布局为网格布局
95 | self.main_widget.setLayout(self.main_layout)
96 | # 创建左侧部件
97 | self.left_widget = QWidget()
98 | self.left_widget.setObjectName('left_widget')
99 | # 创建左侧部件的网格布局层
100 | self.left_layout = QGridLayout()
101 | # 设置左侧部件布局为网格
102 | self.left_widget.setLayout(self.left_layout)
103 | # 创建中间部件
104 | self.middle_widget = QWidget()
105 | self.middle_widget.setObjectName("middle_widget")
106 | self.middle_layout = QGridLayout()
107 | self.middle_widget.setLayout(self.middle_layout)
108 | # 创建右侧部件
109 | self.right_widget = QWidget()
110 | self.right_widget.setObjectName('right_widget')
111 | self.right_layout = QGridLayout()
112 | self.right_widget.setLayout(self.right_layout)
113 |
114 | # 左侧部件在第0行第0列,占12行1列
115 | self.main_layout.addWidget(self.left_widget, 0, 0, 12, 1)
116 | # 中间部件在第0行第6列,占12行4列
117 | self.main_layout.addWidget(self.middle_widget, 0, 2, 12, 4)
118 | # 右侧部件在第0行第6列,占12行7列
119 | self.main_layout.addWidget(self.right_widget, 0, 5, 12, 7)
120 | # 设置窗口主部件
121 | self.setCentralWidget(self.main_widget)
122 | self.single_query = QPushButton("打开微信")
123 | self.single_query.clicked.connect(self.open_wechat)
124 | self.left_layout.addWidget(self.single_query, 0, 0, 1, 1)
125 | # self.middle_label = QLabel("预测天气情况绘图展示区1")
126 | # self.middle_layout.addWidget(self.middle_label, 0, 3, 12, 4)
127 | self.message_TE = SendTextEdit(self)
128 | self.right_layout.addWidget(self.message_TE, 0, 0, 1, 7)
129 | # self.right_label = QLabel("预测天气情况绘图展示区2")
130 | # self.right_layout.addWidget(self.right_label, 0, 6, 1, 7)
131 | msg_thread = MsgThread()
132 | msg_thread.signal.connect(self.parse)
133 | msg_thread.start()
134 | self.show()
135 |
136 | def parse(self, data: Response):
137 | if data.type == WECHAT_CONNECTED: # 微信接入
138 | print(f"微信客户端已接入 port:{data.port}")
139 | x = self.profile_photos.__len__() // 3
140 | y = self.profile_photos.__len__() % 3
141 | profile_photo_label = QLabel(self)
142 | default_profile_photo = QPixmap(os.path.join(profile_photo_dir, "default.png")).scaled(32, 32)
143 | profile_photo_label.setPixmap(default_profile_photo)
144 | self.profile_photos[data.port] = profile_photo_label
145 | self.middle_layout.addWidget(profile_photo_label, x, y, 1, 1)
146 | elif data.type == WECHAT_LOGIN:
147 | spy.get_account_details(data.port)
148 | elif data.type == ACCOUNT_DETAILS:
149 | account_details = AccountDetails()
150 | account_details.ParseFromString(data.bytes)
151 | profile_photo_url = account_details.profilePhoto
152 | profile_photo_path = os.path.join(profile_photo_dir, f"{account_details.wxid}.jpg")
153 | resp = requests.get(profile_photo_url)
154 | with open(profile_photo_path, "wb") as wf:
155 | wf.write(resp.content)
156 | profile_photo = QPixmap(profile_photo_path).scaled(32, 32)
157 | self.profile_photos[data.port].setPixmap(profile_photo)
158 | spy.get_contacts(data.port)
159 | elif data.type == CONTACTS_LIST:
160 | contacts = Contacts()
161 | contacts.ParseFromString(data.bytes)
162 | self.contacts[data.port] = contacts
163 |
164 | def open_wechat(self):
165 | pid = spy.run(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
166 |
167 | def send_msg(self):
168 | content_html = self.message_TE.toHtml()
169 | content_html = re.sub("", "", content_html)
170 | content_html = re.sub("", "", content_html)
171 | content_html = re.sub("", "", content_html)
172 | content_html = re.sub("", "", content_html)
173 | content_etree = etree.HTML(content_html)
174 | lines = content_etree.xpath("//p")
175 | msg_list = []
176 | text_list = []
177 | for line in lines:
178 | if line.xpath("*"):
179 | file_path = line.xpath("img/@src")
180 | if file_path:
181 | file_path = file_path[0]
182 | if text_list:
183 | msg_list.append((5, "\n".join(text_list)))
184 | text_list.clear()
185 | msg_list.append((6, file_path))
186 | text = line.xpath("text()")
187 | if text:
188 | text_list.append(text[0])
189 | else:
190 | if text_list:
191 | msg_list.append((5, "\n".join(text_list)))
192 | text_list.clear()
193 |
194 | def _send():
195 | for port, contacts in self.contacts.values():
196 | for contact in contacts.contactDetails:
197 | if contact.wxid.str not in contact_filter:
198 | for msg in msg_list:
199 | if msg[0] == 5:
200 | self.spy.send_text(contact.wxid.str, msg[1], port=port)
201 | # elif msg[0] == 6:
202 | # self.spy.send_file(wxid, msg[1])
203 | sleep(3)
204 | t = Thread(target=_send)
205 | t.daemon = True
206 | t.start()
207 | self.message_TE.clear()
208 |
209 |
210 | if __name__ == '__main__':
211 | app = QApplication(sys.argv)
212 | spy_ui = SpyUI()
213 | sys.exit(app.exec_())
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PyWeChatSpy
2 | help people make better use of WeChatForPC
3 |
4 | 相关文章:[硬核WeChatBot](https://zhuanlan.zhihu.com/p/118674498)
5 |
6 | ## 支持微信版本
7 | ### 3.0.0.57
8 | 微信客户端下载:[https://pan.baidu.com/s/1FIHQ4BCkpTSC-7QHk13LHw](https://pan.baidu.com/s/1FIHQ4BCkpTSC-7QHk13LHw) 提取码: v2n3
9 |
10 | ## 功能列表
11 | ### 基础功能
12 | * 推送聊天消息 CHAT_MESSAGE
13 | * 回调结构 [ChatMessage](#ChatMessage)
14 | * 获取登录账号信息 get_account_details
15 | * 回调结构 [AccountDetails](#AccountDetails)
16 | * 发送文本 send_text
17 | * 入参
18 | * wxid 文本消息接收方wxid
19 | * text 文本内容
20 | * at_wxid 需要被@的wxid(仅限群聊) at几个人,文本里就需要出现几个'@'符号 `spy.send_text('xxxx@chatroom', '@0000 @1111 Hello World', 'wxid_xxxx,wxid_yyyy')`
21 | * 发送文件、图片 send_file
22 | * 入参
23 | * wxid 文件接收方wxid
24 | * file_path 文件路径
25 | * 解密微信图片文件 decrypt_image(微信的图片下载到本地是加密的,需要使用此方法解密后方能看到图片原始内容)
26 | * 入参
27 | * source_file 带解密图片文件
28 | * target_file 解密后图片保存路径
29 | ### 高级功能
30 | * 获取联系人列表 get_contacts(获取所有联系人,包括好友与群,不活跃的群可能无法获取)
31 | * 回调类型 CONTACTS_LIST
32 | * 回调结构 [Contacts](#Contacts)
33 | * 获取联系人详情、群成员列表 get_contact_details
34 | * 入参
35 | * 联系人wxid
36 | * 回调类型 CONTACT_DETAILS
37 | * 回调结构 [Contacts](#Contacts)
38 | * 发送群公告 send_announcement
39 | * 入参
40 | * wxid 群wxid
41 | * content 公告内容
42 | * 自动通过好友请求 accept_new_contact
43 | * 入参
44 | * encryptusername 好友请求Xml消息结构体同名字段值
45 | * ticket 好友请求Xml消息结构体同名字段值
46 | * 设置联系人备注 set_remark
47 | * 入参
48 | * wxid 联系人wxid
49 | * remark 备注内容
50 | * 分享群聊 share_chatroom
51 | * 入参
52 | * chatroom_wxid 待分享群聊wxid
53 | * wxid 联系人wxid
54 | * 移除群成员 remove_chatroom_member
55 | * 入参
56 | * chatroom_wxid 待移除成员群聊wxid
57 | * wxid 待移除群聊成员wxid
58 | * 移除联系人 remove_contact
59 | * 入参
60 | * wxid 待移除联系人wxid
61 | * 发送小程序 send_mini_program
62 | * 入参
63 | * wxid 接收方wxid
64 | * title 小程序标题
65 | * image_path 小程序封面
66 | * route 小程序跳转路由,抓包小程序消息获取pagepath或自行生成
67 | * app_id 小程序AppId
68 | * username 小程序源Id
69 | * weappiconurl 小程序图标url
70 | * appname 小程序名称
71 | * 发送链接卡片 send_link_card
72 | * 入参
73 | * wxid 接收方wxid
74 | * title 卡片标题
75 | * desc 卡片描述
76 | * app_id 卡片AppId
77 | * url 卡片跳转url
78 | * image_path 卡片封面图片路径
79 | * 创建群聊 create_chatroom
80 | * 入参
81 | * wxid 创建群聊拉取的联系人wxid,不包括自己,至少连个,英文逗号分隔
82 | * 回调结构 [CreateGroupCallback](#CreateGroupCallback)
83 | * 设置群名称 set_chatroom_name
84 | * 入参
85 | * wxid 待改名群聊wxid
86 | * name 群聊名称
87 | * 推送群成员详情 GROUP_MEMBER_DETAILS
88 | * 回调结构 [GroupMemberDetails](#GroupMemberDetails)
89 | * 推送群成员变动(进群&退群) GROUP_MEMBER_EVENT
90 | * 回调结构 [GroupMemberEvent](#GroupMemberEvent)
91 | * 获取登录二维码 get_login_qrcode
92 | * 回调结构 [LoginQRCode](#LoginQRCode)
93 | * 发送个人名片 send_card
94 | * 入参
95 | * wxid 名片接收wxid
96 | * card_wxid 名片wxid
97 | * card_nickname 名片显示昵称
98 |
99 | ## 数据结构
100 | ### 登录信息 AccountDetails `account_details = spy_pb2.AccountDetails()`
101 | * wxid 登录账号wxid `account_details.wxid`
102 | * nickname 登录账号昵称 `account_details.nickname`
103 | * wechatid 登录账号微信号 `account_details.wechatid`
104 | * autograph 登录账号签名 `account_details.autograph`
105 | * profilePhotoHD 登录账号高清头像 `account_details.profilePhotoHD`
106 | * profilePhoto 登录账号头像 `account_details.profilePhoto`
107 | * phone 登录账号绑定手机号 `account_details.phone`
108 | * email 登录账号绑定邮箱 `account_details.email`
109 | * qq 登录账号绑定QQ `account_details.qq`
110 | * sex 登录账号性别 1男/2女 `account_details.sex`
111 | * city 登录账号所在城市 `account_details.city`
112 | * province 登录账号所在省份 `account_details.province`
113 | * country 登录账号所在国家 `account_details.country`
114 |
115 | ### Contacts 联系人列表 `contacts_list = spy_pb2.Contacts()`
116 | * contactDetails 联系人详情(可遍历) `for contact in contacts_list.contactDetails`
117 | * wxid 联系人wxid结构 `contact.wxid`
118 | * str 联系人wxid `contact.wxid.str`
119 | * nickname 联系人昵称结构 `contact.nickname`
120 | * str 联系人昵称 `contact.nickname.str`
121 | * sex 联系人性别 1男/2女 `contact.sex`
122 | * remark 联系人备注结构 `contact.remark`
123 | * str 联系人备注 `contact.remark.str`
124 | * wechatId 联系人微信号 `contact.wechatId`
125 | * groupOwnerWxid 群主wxid(如果联系人是群聊 wxid以"@chatroom"结尾) `cotact.groupOwnerWxid`
126 | * profilePhotoHD 联系人高清头像 `cotact.profilePhotoHD`
127 | * profilePhoto 联系人头像 `contact.profilePhoto`
128 | * groupMemberList 群成员列表(如果联系人是群聊 wxid以"@chatroom"结尾) `contact.groupMemberList`
129 | * memberCount 群成员数量 `contact.groupMemberList.memberCount`
130 | * groupMember 群成员信息(可遍历) `for member in contacts_list.contactDetails.groupMemberList.groupMember`
131 | * wxid 群成员wxid `member.wxid`
132 | * nickname 群成员昵称 `member.nickname`
133 |
134 | ### ChatMessage 微信消息 `chat_message = spy_pb2.ChatMessage()`
135 | * message 微信消息(可遍历) `for message in chat_message.message`
136 | * wxidFrom 消息发送方wxid结构 `message.wxidFrom`
137 | * str 消息发送方wxid `message.wxidFrom.str`
138 | * wxidTo 消息接收方wxid结构 `message.wxidTo`
139 | * str 消息接收方 `message.wxidTo.str`
140 | * type 消息类型 1文本3图片43视频49Xml37好友请求10000系统消息... `message.type`
141 | * content 消息内容结构 `message.content`
142 | * str 消息内容 `message.content.str`
143 | * timestamp 消息时间戳 `message.timestamp`
144 | * head 消息头 `message.head`
145 | * file 消息附带文件(图片、视频等) `message.file`
146 |
147 | ### GroupMemberDetails 群成员详情 `group_member_details = spy_pb2.GroupMemberDetails()`
148 | * wxid 群wxid `group_member_details.wxid`
149 | * detailsCount 详情数量(非群成员数量) `group_member_details.detailsCount`
150 | * groupMemberDetails 群成员详情(可遍历) `for member_details in group_member_details.groupMemberDetails`
151 | * wxid 群成员wxid `member_details.wxid`
152 | * nickname 群成员昵称 `member_details.nickname`
153 | * groupNickname 群成员群内昵称 `member_details.groupNickname`
154 | * profilePhotoHD 群成员高清头像 `member_details.profilePhotoHD`
155 | * profilePhoto 群成员头像 `member_details.profilePhoto`
156 | * inviterWxid 群成员邀请人wxid `member_details.inviterWxid`
157 |
158 | ### GroupMemberEvent 群成员变动事件 `group_member_event = spy_pb2.GroupMemberEvent()`
159 | * wxid 群wxid `group_member_event.wxid`
160 | * wxidJoin 进群wxid(可遍历) `for _join in group_member_event.wxidJoin`
161 | * wxidLeave 退群wxid(可遍历) `for _leave in group_member_event.wxidLeave`
162 |
163 | ### CreateGroupCallback 创建群聊回调 `callback = spy_pb2.CreateGroupCallback()`
164 | * wxid 群聊wxid结构 `callback.wxid`
165 | * str 群聊wxid `callback.wxid.str`
166 |
167 | ### LoginQRCode 登录二维码 `qrcode = spy_pb2.LoginQRCode()`
168 | * qrcodeSize 二维码大小 `qrcode.qrcodeSize`
169 | * qrcodeBytes 二维码数据 `qrcode.qrcodeBytes`
170 |
171 | ## 例子
172 | ### 一、本地运行
173 | 示例代码见[example.py](https://github.com/veikai/PyWeChatSpy/blob/master/example.py)
174 |
175 | ### 二、HTTP调用服务端
176 | 示例代码见
177 | [service_example.py](https://github.com/veikai/PyWeChatSpy/blob/master/service_example.py)
178 | 和
179 | [client_example.py](https://github.com/veikai/PyWeChatSpy/blob/master/client_example.py)
180 |
181 | ### 三、远程过程调用(RPC)
182 | 起作用的有4个额外文件:
183 | * example_rpc_server.py
184 | * example_rpc_client.py
185 | * rpc_server_tools.py
186 | * rpc_client_tools.py
187 |
188 | 使用方法:
189 | 1. 运行服务端 [example_rpc_server.py](https://github.com/veikai/PyWeChatSpy/blob/master/example_rpc_server.py) 启动微信
190 | 2. 运行客户端 [example_rpc_client.py](https://github.com/veikai/PyWeChatSpy/blob/master/example_rpc_client.py) 接收并处理消息
191 |
192 | *注意:例子中,客户端和服务端在一台机子上,所以监听的ip是127.0.0.1,如果将客户端放到其他机器,请填写实际服务端对应的ip,出现端口冲突的话也可以灵活更改端口,并配置对应服务器防火墙放行*
193 |
194 | ### 四、其他例子
195 |
196 | __待补充,欢迎大家贡献!__
--------------------------------------------------------------------------------
/UI.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import (
2 | QApplication,
3 | QWidget,
4 | QHBoxLayout,
5 | QVBoxLayout,
6 | QDesktopWidget,
7 | QPushButton,
8 | QLabel,
9 | QTabWidget,
10 | QMenu, QAction, QTextEdit, QFileDialog, QListWidget, QListWidgetItem, QCheckBox)
11 | from PyQt5.QtGui import QPixmap, QCursor
12 | from PyQt5.QtCore import QSize, QThread, pyqtSignal, Qt, QPoint
13 | from PyWeChatSpy import WeChatSpy
14 | from lxml import etree
15 | import requests
16 | import sys
17 | from queue import Queue
18 | from time import sleep
19 | from threading import Thread
20 | import os
21 | import re
22 |
23 |
24 | FRIEND_LIST = []
25 | GROUP_LIST = []
26 | OFFICE_LIST = []
27 | cb_contact_list = []
28 | contact_need_details = []
29 | current_row = 0
30 | msg_queue = Queue()
31 | wxid_contact = {}
32 | contact_filter = ("qmessage", "qqmail", "tmessage", "medianote", "floatbottle", "fmessage")
33 | key = "18d421169d93611a5584affac335e690"
34 | if os.path.exists("key"):
35 | with open("key", "r") as rf:
36 | key = rf.read()
37 |
38 |
39 | def parser(data: dict):
40 | msg_queue.put(data)
41 |
42 |
43 | class MsgThread(QThread):
44 | signal = pyqtSignal(dict)
45 |
46 | def __init__(self):
47 | super().__init__()
48 |
49 | def run(self):
50 | while True:
51 | if not msg_queue.empty():
52 | msg = msg_queue.get()
53 | self.signal.emit(msg)
54 | else:
55 | sleep(0.1)
56 |
57 |
58 | def download_image(url: str, output: str):
59 | resp = requests.get(url)
60 | if resp.status_code == 200:
61 | with open(output, "wb") as wf:
62 | wf.write(resp.content)
63 | return True
64 | return False
65 |
66 |
67 | class ContactWidget(QWidget):
68 | def __init__(self, contact: dict, select_changed: classmethod):
69 | super().__init__()
70 | layout = QHBoxLayout(self)
71 | checkbox_contact = QCheckBox()
72 | checkbox_contact.__setattr__("wxid", contact["wxid"])
73 | checkbox_contact.setFixedSize(20, 20)
74 | checkbox_contact.stateChanged[int].connect(select_changed)
75 | cb_contact_list.append(checkbox_contact)
76 | layout.addWidget(checkbox_contact)
77 | label_profilephoto = QLabel(self)
78 | label_profilephoto.setFixedSize(32, 32)
79 | profilephoto_path = "profilephotos/default.jpg"
80 | if os.path.exists(f"profilephotos/{contact['wxid']}.jpg"):
81 | profilephoto_path = f"profilephotos/{contact['wxid']}.jpg"
82 | default_profilephoto = QPixmap(profilephoto_path).scaled(32, 32)
83 | label_profilephoto.setPixmap(default_profilephoto)
84 | layout.addWidget(label_profilephoto)
85 | label_nickname = QLabel(self)
86 | nickname = contact["nickname"]
87 | if remark := contact.get("remark"):
88 | nickname = f"{nickname}({remark})"
89 | if count := contact.get("member_count"):
90 | nickname = f"{nickname}[{count}]"
91 | label_nickname.setText(nickname)
92 | layout.addWidget(label_nickname)
93 |
94 |
95 | class ContactSearchWidget(QWidget):
96 | def __init__(self, contact: dict):
97 | super().__init__()
98 | layout = QHBoxLayout(self)
99 | label_profilephoto = QLabel(self)
100 | label_profilephoto.setFixedSize(32, 32)
101 | profilephoto_path = "profilephotos/default.jpg"
102 | if os.path.exists(f"profilephotos/{contact['wxid']}.jpg"):
103 | profilephoto_path = f"profilephotos/{contact['wxid']}.jpg"
104 | default_profilephoto = QPixmap(profilephoto_path).scaled(32, 32)
105 | label_profilephoto.setPixmap(default_profilephoto)
106 | layout.addWidget(label_profilephoto)
107 | label_nickname = QLabel(self)
108 | nickname = contact["nickname"]
109 | if remark := contact.get("remark"):
110 | nickname = f"{nickname}({remark})"
111 | if count := contact.get("member_count"):
112 | nickname = f"{nickname}[{count}]"
113 | label_nickname.setText(nickname)
114 | layout.addWidget(label_nickname)
115 |
116 |
117 | class MessageWidget(QWidget):
118 | def __init__(self, message: dict):
119 | super().__init__()
120 | layout_main = QHBoxLayout(self)
121 | layout_side = QVBoxLayout(self)
122 | label_content = QLabel(self)
123 | label_content.setWordWrap(True)
124 | label_content.adjustSize()
125 | label_content.setFixedWidth(300)
126 | label_speaker = QLabel(self)
127 | if message["self"]:
128 | layout_main.setAlignment(Qt.AlignRight)
129 | label_content.setAlignment(Qt.AlignRight)
130 | label_speaker.setAlignment(Qt.AlignRight)
131 | else:
132 | layout_main.setAlignment(Qt.AlignLeft)
133 | label_content.setAlignment(Qt.AlignLeft)
134 | label_speaker.setAlignment(Qt.AlignLeft)
135 | label_profilephoto = QLabel(self)
136 | label_profilephoto.setFixedSize(32, 32)
137 | profilephoto_path = "profilephotos/default.jpg"
138 | if os.path.exists(f"profilephotos/{message['wxid1']}.jpg"):
139 | profilephoto_path = f"profilephotos/{message['wxid1']}.jpg"
140 | default_profilephoto = QPixmap(profilephoto_path).scaled(32, 32)
141 | label_profilephoto.setPixmap(default_profilephoto)
142 | speaker = ""
143 | wxid1 = message["wxid1"]
144 | if contact := wxid_contact.get(wxid1):
145 | speaker = contact["nickname"]
146 | if remark := contact.get("remark"):
147 | speaker = f"{speaker}({remark})"
148 | label_speaker.setText(speaker)
149 | layout_side.addWidget(label_speaker)
150 | if message["msg_type"] == 1:
151 | label_content.setText(message["content"])
152 | elif message["msg_type"] == 3:
153 | label_content.setText("图片消息,请在手机上查看")
154 | elif message["msg_type"] == 43:
155 | if message.get("content"):
156 | label_content.setText("不支持的消息类型,请在手机上查看")
157 | else:
158 | label_content.setText("视频消息,请在手机上查看")
159 | elif message["msg_type"] == 47:
160 | label_content.setText("表情包消息,请在手机上查看")
161 | elif message["msg_type"] == 49:
162 | label_content.setText("小程序或其他分享消息,请在手机上查看")
163 | else:
164 | label_content.setText("不支持的消息类型,请在手机上查看")
165 | layout_side.addWidget(label_content)
166 | if message["self"]:
167 | layout_main.addLayout(layout_side)
168 | layout_main.addWidget(label_profilephoto)
169 | else:
170 | layout_main.addWidget(label_profilephoto)
171 | layout_main.addLayout(layout_side)
172 |
173 |
174 | class SettingWidget(QWidget):
175 | def __init__(self, parent):
176 | super().__init__()
177 | self.setWindowTitle("设置")
178 | self.parent = parent
179 | self.tab_widget = QTabWidget(self)
180 | self.tab_widget.setTabPosition(QTabWidget.West)
181 | self.tab_widget.setFixedSize(300, 200)
182 | self.tab_common = QListWidget(self)
183 | self.tab_widget.addTab(self.tab_common, "通用")
184 | item = QListWidgetItem()
185 | item.setSizeHint(QSize(200, 50))
186 | self.cb_auto_accept = QCheckBox("自动通过好友请求")
187 | self.tab_common.addItem(item)
188 | self.tab_common.setItemWidget(item, self.cb_auto_accept)
189 |
190 |
191 | class SendTextEdit(QTextEdit):
192 | def __init__(self, parent):
193 | super().__init__()
194 | self.parent = parent
195 |
196 | def keyPressEvent(self, event):
197 | QTextEdit.keyPressEvent(self, event)
198 | if event.key() == Qt.Key_Return:
199 | if QApplication.keyboardModifiers() == Qt.ControlModifier:
200 | self.append("")
201 | else:
202 | self.parent.send_msg()
203 |
204 |
205 | class SpyUI(QWidget):
206 | def __init__(self):
207 | super().__init__()
208 | self.layout_main = QHBoxLayout(self)
209 | self.setting_widget = SettingWidget(self)
210 | self.wxid = ""
211 | self.init_ui()
212 |
213 | def init_ui(self):
214 | fg = self.frameGeometry()
215 | center = QDesktopWidget().availableGeometry().center()
216 | fg.moveCenter(center)
217 | # 设置窗体
218 | self.setting_widget.resize(300, 200)
219 | self.setting_widget.move(fg.topLeft())
220 | self.setting_widget.hide()
221 | # 主窗体
222 | self.resize(858, 608)
223 | self.move(fg.topLeft())
224 | self.setWindowTitle("PyWeChatSpyUI Beta 1.3.3")
225 | self.show()
226 |
227 |
228 | if __name__ == '__main__':
229 | app = QApplication(sys.argv)
230 | spy = SpyUI()
231 | sys.exit(app.exec_())
232 |
--------------------------------------------------------------------------------
/client_example.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import base64
3 | import time
4 | import os
5 |
6 |
7 | i = 0
8 | a = time.time()
9 | resp = requests.get("http://localhost:5000/open_wechat").json()
10 | print(i, resp, time.time() - a)
11 | port = resp['port']
12 | i += 1
13 | time.sleep(1)
14 | input() # 等待手动登录
15 | post_data = {
16 | "wxid": "filehelper",
17 | "text": "1111"
18 | }
19 | resp = requests.post(f"http://localhost:5000/send_text/{port}", json=post_data).json()
20 | print(resp)
21 | # resp = requests.get(f"http://localhost:5000/get_login_qrcode/{port}").json()
22 | # print(resp)
23 | # input()
24 | # resp = requests.get(f"http://localhost:5000/get_login_info/{port}").json()
25 | # print(resp)
26 | # input()
27 | # resp = requests.get(f"http://localhost:5000/get_contact_list/{port}").json()
28 | # print(resp)
29 | # input()
30 | # post_data = {"wxid": "17926000072@chatroom"}
31 | # resp = requests.post(f"http://localhost:5000/get_contact_details/{port}", json=post_data).json()
32 | # print(resp)
33 | input()
34 | url = f"http://localhost:5000/send_file/{port}"
35 | files = {'file': open(r'D:\18020891\Pictures\员工平台研发中心_智能应用开发部活动方案.docx', 'rb')}
36 | post_data = {
37 | "wxid": "filehelper"
38 | }
39 | resp = requests.post(url, data=post_data, files=files).json()
40 | print(resp)
--------------------------------------------------------------------------------
/example.py:
--------------------------------------------------------------------------------
1 | from PyWeChatSpy import WeChatSpy
2 | from PyWeChatSpy.command import *
3 | from lxml import etree
4 | import time
5 | import logging
6 | from logging.handlers import TimedRotatingFileHandler
7 | from PyWeChatSpy.proto import spy_pb2
8 | import os
9 | import shutil
10 | from queue import Queue
11 | from PyWeChatSpy.games.truth_or_dare import TruthOrDare
12 |
13 |
14 | logger = logging.getLogger(__file__)
15 | logger.setLevel(logging.DEBUG)
16 | formatter = logging.Formatter('%(asctime)s [%(threadName)s] %(levelname)s: %(message)s')
17 | sh = logging.StreamHandler()
18 | sh.setFormatter(formatter)
19 | sh.setLevel(logging.INFO)
20 | fh = TimedRotatingFileHandler("spy.log", when="midnight")
21 | fh.setFormatter(formatter)
22 | logger.addHandler(fh)
23 | logger.addHandler(sh)
24 |
25 |
26 | WECHAT_PROFILE = rf"C:\Users\{os.environ['USERNAME']}\Documents\WeChat Files"
27 | PATCH_PATH = rf"C:\Users\{os.environ['USERNAME']}\AppData\Roaming\Tencent\WeChat\patch"
28 | if not os.path.exists(WECHAT_PROFILE):
29 | logger.error("请先设置计算机用户名,并完善WECHAT_PROFILE和PATCH_PATH")
30 | exit()
31 | if os.path.isdir(PATCH_PATH):
32 | shutil.rmtree(PATCH_PATH)
33 | if not os.path.exists(PATCH_PATH):
34 | with open(PATCH_PATH, "a") as wf:
35 | wf.write("")
36 | my_response_queue = Queue()
37 | spy = WeChatSpy(response_queue=my_response_queue, key="ab28d8c4768ab3bc2ba86841313f6e32", logger=logger)
38 | tod = TruthOrDare(spy)
39 |
40 |
41 | def pop_response():
42 | while True:
43 | data = my_response_queue.get()
44 | handle_response(data)
45 |
46 |
47 | def handle_response(data):
48 | if data.type == PROFESSIONAL_KEY:
49 | if not data.code:
50 | logger.warning(data.message)
51 | elif data.type == WECHAT_CONNECTED: # 微信接入
52 | print(f"微信客户端已接入 port:{data.port}")
53 | time.sleep(1)
54 | # spy.get_login_qrcode() # 获取登录二维码
55 | elif data.type == HEART_BEAT: # 心跳
56 | pass
57 | elif data.type == WECHAT_LOGIN: # 微信登录
58 | print("微信登录")
59 | spy.get_account_details() # 获取登录账号详情
60 | elif data.type == WECHAT_LOGOUT: # 微信登出
61 | print("微信登出")
62 | elif data.type == CHAT_MESSAGE: # 微信消息
63 | chat_message = spy_pb2.ChatMessage()
64 | chat_message.ParseFromString(data.bytes)
65 | for message in chat_message.message:
66 | _type = message.type # 消息类型 1.文本|3.图片...自行探索
67 | _from = message.wxidFrom.str # 消息发送方
68 | _to = message.wxidTo.str # 消息接收方
69 | content = message.content.str # 消息内容
70 | _from_group_member = ""
71 | if _from.endswith("@chatroom"): # 群聊消息
72 | _from_group_member = message.content.str.split(':\n', 1)[0] # 群内发言人
73 | content = message.content.str.split(':\n', 1)[-1] # 群聊消息内容
74 | image_overview_size = message.imageOverview.imageSize # 图片缩略图大小
75 | image_overview_bytes = message.imageOverview.imageBytes # 图片缩略图数据
76 | # with open("img.jpg", "wb") as wf:
77 | # wf.write(image_overview_bytes)
78 | overview = message.overview # 消息缩略
79 | timestamp = message.timestamp # 消息时间戳
80 | if _type == 1: # 文本消息
81 | print(_from, _to, _from_group_member, content)
82 | if _to == "filehelper":
83 | spy.send_text("filehelper", "Hello PyWeChatSpy3.0\n" + content)
84 | time.sleep(2)
85 | spy.send_file("filehelper", r"D:\18020891\Pictures\b.jpg")
86 | elif _type == 3: # 图片消息
87 | file_path = message.file
88 | file_path = os.path.join(WECHAT_PROFILE, file_path)
89 | time.sleep(10)
90 | # spy.decrypt_image(file_path, "a.jpg")
91 | elif _type == 43: # 视频消息
92 | pass
93 | elif _type == 49: # XML报文消息
94 | print(_from, _to, message.file)
95 | xml = etree.XML(content)
96 | xml_type = xml.xpath("/msg/appmsg/type/text()")[0]
97 | if xml_type == "5":
98 | xml_title = xml.xpath("/msg/appmsg/title/text()")[0]
99 | print(xml_title)
100 | if xml_title == "邀请你加入群聊":
101 | url = xml.xpath("/msg/appmsg/url/text()")[0]
102 | print(url)
103 | time.sleep(1)
104 | spy.get_group_enter_url(_from, url)
105 | elif _type == 37: # 好友申请
106 | print("新的好友申请")
107 | obj = etree.XML(message.content.str)
108 | encryptusername, ticket = obj.xpath("/msg/@encryptusername")[0], obj.xpath("/msg/@ticket")[0]
109 | spy.accept_new_contact(encryptusername, ticket) # 接收好友请求
110 | elif data.type == ACCOUNT_DETAILS: # 登录账号详情
111 | if data.code:
112 | account_details = spy_pb2.AccountDetails()
113 | account_details.ParseFromString(data.bytes)
114 | print(account_details)
115 | spy.get_contacts() # 获取联系人列表
116 | else:
117 | logger.warning(data.message)
118 | elif data.type == CONTACTS_LIST: # 联系人列表
119 | if data.code:
120 | contacts_list = spy_pb2.Contacts()
121 | contacts_list.ParseFromString(data.bytes)
122 | for contact in contacts_list.contactDetails: # 遍历联系人列表
123 | wxid = contact.wxid.str # 联系人wxid
124 | nickname = contact.nickname.str # 联系人昵称
125 | remark = contact.remark.str # 联系人备注
126 | print(wxid, nickname, remark)
127 | # spy.get_contact_details("20646587964@chatroom") # 获取群聊详情
128 | else:
129 | logger.error(data.message)
130 | elif data.type == CONTACT_DETAILS:
131 | if data.code:
132 | contact_details_list = spy_pb2.Contacts()
133 | contact_details_list.ParseFromString(data.bytes)
134 | for contact_details in contact_details_list.contactDetails: # 遍历联系人详情
135 | wxid = contact_details.wxid.str # 联系人wxid
136 | nickname = contact_details.nickname.str # 联系人昵称
137 | remark = contact_details.remark.str # 联系人备注
138 | if wxid.endswith("chatroom"): # 判断是否为群聊
139 | group_member_list = contact_details.groupMemberList # 群成员列表
140 | member_count = group_member_list.memberCount # 群成员数量
141 | for group_member in group_member_list.groupMember: # 遍历群成员
142 | member_wxid = group_member.wxid # 群成员wxid
143 | member_nickname = group_member.nickname # 群成员昵称
144 | # print(member_wxid, member_nickname)
145 | pass
146 | else:
147 | logger.error(data.message)
148 | elif data.type == GET_CONTACTS_LIST and not data.code:
149 | logger.error(data.message)
150 | elif data.type == CREATE_GROUP_CALLBACK: # 创建群聊回调
151 | callback = spy_pb2.CreateGroupCallback()
152 | callback.ParseFromString(data.bytes)
153 | print(callback)
154 | elif data.type == GROUP_MEMBER_DETAILS: # 群成员详情
155 | group_member_details = spy_pb2.GroupMemberDetails()
156 | group_member_details.ParseFromString(data.bytes)
157 | # print(group_member_details)
158 | elif data.type == GROUP_MEMBER_EVENT: # 群成员进出事件
159 | group_member_event = spy_pb2.GroupMemberEvent()
160 | group_member_event.ParseFromString(data.bytes)
161 | # print(group_member_event)
162 | elif data.type == LOGIN_QRCODE: # 登录二维码
163 | qrcode = spy_pb2.LoginQRCode()
164 | qrcode.ParseFromString(data.bytes)
165 | with open("qrcode.png", "wb") as _wf:
166 | _wf.write(qrcode.qrcodeBytes)
167 | elif data.type == GROUP_ENTER_URL: # 进群链接
168 | group_enter_url = spy_pb2.GroupEnterUrl()
169 | group_enter_url.ParseFromString(data.bytes)
170 | print(group_enter_url)
171 | # 进群直接post请求链接
172 | # try:
173 | # requests.post(group_enter_url.url)
174 | # except requests.exceptions.InvalidSchema:
175 | # pass
176 | # except Exception as e:
177 | # logger.error(f"进群失败:{e}")
178 | elif data.type == SEND_TEXT_CALLBACK:
179 | print("发送文本回调")
180 | print(data)
181 | print(data.code)
182 | elif data.type == SEND_XML_CALLBACK:
183 | print("发送xml回调")
184 | print(data)
185 | print(data.code)
186 | elif data.type == SEND_IMAGE_CALLBACK:
187 | print("发送图片回调")
188 | print(data)
189 | print(data.code)
190 | else:
191 | print(data)
192 |
193 |
194 | if __name__ == '__main__':
195 | pid = spy.run(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
196 | pop_response()
197 |
--------------------------------------------------------------------------------
/example_rpc_client.py:
--------------------------------------------------------------------------------
1 | import re
2 | import os
3 | from lxml import etree
4 | import time
5 | from PyWeChatSpy.command import *
6 | from PyWeChatSpy.proto import spy_pb2
7 | from threading import Thread
8 | from google.protobuf.descriptor import FieldDescriptor as FD
9 | from rpc_client_tools import *
10 | import logging
11 | from queue import Queue
12 | contact_list = []
13 | chatroom_list = []
14 |
15 | my_response_queue = Queue()
16 | logger = logging.getLogger(__file__)
17 | logger.setLevel(logging.DEBUG)
18 | formatter = logging.Formatter('%(asctime)s [%(threadName)s] %(levelname)s: %(message)s')
19 | sh = logging.StreamHandler()
20 | sh.setFormatter(formatter)
21 | sh.setLevel(logging.INFO)
22 | logger.addHandler(sh)
23 |
24 | def handle_response():
25 | while True:
26 | data = my_response_queue.get()
27 | data = dict2pb(spy_pb2.Response, data)
28 | if data.type == PROFESSIONAL_KEY:
29 | if not data.code:
30 | logger.warning(data.message)
31 | elif data.type == WECHAT_CONNECTED: # 微信接入
32 | print(f"微信客户端已接入 port:{data.port}")
33 | time.sleep(1)
34 | # spy.get_login_qrcode() # 获取登录二维码
35 | elif data.type == HEART_BEAT: # 心跳
36 | pass
37 | elif data.type == WECHAT_LOGIN: # 微信登录
38 | print("微信登录")
39 | spy.get_account_details() # 获取登录账号详情
40 | elif data.type == WECHAT_LOGOUT: # 微信登出
41 | print("微信登出")
42 | elif data.type == CHAT_MESSAGE: # 微信消息
43 | chat_message = spy_pb2.ChatMessage()
44 | chat_message.ParseFromString(data.bytes)
45 | for message in chat_message.message:
46 | _type = message.type # 消息类型 1.文本|3.图片...自行探索
47 | _from = message.wxidFrom.str # 消息发送方
48 | _to = message.wxidTo.str # 消息接收方
49 | content = message.content.str # 消息内容
50 | _from_group_member = ""
51 | if _from.endswith("@chatroom"): # 群聊消息
52 | _from_group_member = message.content.str.split(':\n', 1)[0] # 群内发言人
53 | content = message.content.str.split(':\n', 1)[-1] # 群聊消息内容
54 | image_overview_size = message.imageOverview.imageSize # 图片缩略图大小
55 | image_overview_bytes = message.imageOverview.imageBytes # 图片缩略图数据
56 | # with open("img.jpg", "wb") as wf:
57 | # wf.write(image_overview_bytes)
58 | overview = message.overview # 消息缩略
59 | timestamp = message.timestamp # 消息时间戳
60 | if _type == 1: # 文本消息
61 | print(_from, _to, _from_group_member, content)
62 | if _to == "filehelper":
63 | spy.send_text("filehelper", "Hello PyWeChatSpy3.0\n" + content)
64 | elif _type == 3: # 图片消息
65 | break
66 | # file_path = message.file
67 | # file_path = os.path.join(WECHAT_PROFILE, file_path)
68 | # time.sleep(10)
69 | # spy.decrypt_image(file_path, "a.jpg")
70 | elif _type == 43: # 视频消息
71 | pass
72 | elif _type == 49: # XML报文消息
73 | print(_from, _to, message.file)
74 | xml = etree.XML(content)
75 | xml_type = xml.xpath("/msg/appmsg/type/text()")[0]
76 | if xml_type == "5":
77 | xml_title = xml.xpath("/msg/appmsg/title/text()")[0]
78 | print(xml_title)
79 | if xml_title == "邀请你加入群聊":
80 | url = xml.xpath("/msg/appmsg/url/text()")[0]
81 | print(url)
82 | time.sleep(1)
83 | spy.get_group_enter_url(_from, url)
84 | elif _type == 37: # 好友申请
85 | print("新的好友申请")
86 | obj = etree.XML(message.content.str)
87 | encryptusername, ticket = obj.xpath("/msg/@encryptusername")[0], obj.xpath("/msg/@ticket")[0]
88 | spy.accept_new_contact(encryptusername, ticket) # 接收好友请求
89 | elif data.type == ACCOUNT_DETAILS: # 登录账号详情
90 | if data.code:
91 | account_details = spy_pb2.AccountDetails()
92 | account_details.ParseFromString(data.bytes)
93 | print(account_details)
94 | spy.get_contacts() # 获取联系人列表
95 | else:
96 | logger.warning(data.message)
97 | elif data.type == CONTACTS_LIST: # 联系人列表
98 | if data.code:
99 | contacts_list = spy_pb2.Contacts()
100 | contacts_list.ParseFromString(data.bytes)
101 | for contact in contacts_list.contactDetails: # 遍历联系人列表
102 | wxid = contact.wxid.str # 联系人wxid
103 | nickname = contact.nickname.str # 联系人昵称
104 | remark = contact.remark.str # 联系人备注
105 | print(wxid, nickname, remark)
106 | if wxid.endswith("chatroom"): # 群聊
107 | groups.append(wxid)
108 | # spy.get_contact_details("20646587964@chatroom") # 获取群聊详情
109 | else:
110 | logger.error(data.message)
111 | elif data.type == CONTACT_DETAILS:
112 | if data.code:
113 | contact_details_list = spy_pb2.Contacts()
114 | contact_details_list.ParseFromString(data.bytes)
115 | for contact_details in contact_details_list.contactDetails: # 遍历联系人详情
116 | wxid = contact_details.wxid.str # 联系人wxid
117 | nickname = contact_details.nickname.str # 联系人昵称
118 | remark = contact_details.remark.str # 联系人备注
119 | if wxid.endswith("chatroom"): # 判断是否为群聊
120 | group_member_list = contact_details.groupMemberList # 群成员列表
121 | member_count = group_member_list.memberCount # 群成员数量
122 | for group_member in group_member_list.groupMember: # 遍历群成员
123 | member_wxid = group_member.wxid # 群成员wxid
124 | member_nickname = group_member.nickname # 群成员昵称
125 | # print(member_wxid, member_nickname)
126 | pass
127 | else:
128 | logger.error(data.message)
129 | elif data.type == GET_CONTACTS_LIST and not data.code:
130 | logger.error(data.message)
131 | elif data.type == CREATE_GROUP_CALLBACK: # 创建群聊回调
132 | callback = spy_pb2.CreateGroupCallback()
133 | callback.ParseFromString(data.bytes)
134 | print(callback)
135 | elif data.type == GROUP_MEMBER_DETAILS: # 群成员详情
136 | group_member_details = spy_pb2.GroupMemberDetails()
137 | group_member_details.ParseFromString(data.bytes)
138 | # print(group_member_details)
139 | elif data.type == GROUP_MEMBER_EVENT: # 群成员进出事件
140 | group_member_event = spy_pb2.GroupMemberEvent()
141 | group_member_event.ParseFromString(data.bytes)
142 | # print(group_member_event)
143 | elif data.type == LOGIN_QRCODE: # 登录二维码
144 | qrcode = spy_pb2.LoginQRCode()
145 | qrcode.ParseFromString(data.bytes)
146 | with open("qrcode.png", "wb") as _wf:
147 | _wf.write(qrcode.qrcodeBytes)
148 | elif data.type == GROUP_ENTER_URL: # 进群链接
149 | group_enter_url = spy_pb2.GroupEnterUrl()
150 | group_enter_url.ParseFromString(data.bytes)
151 | print(group_enter_url)
152 | # 进群直接post请求链接
153 | # try:
154 | # requests.post(group_enter_url.url)
155 | # except requests.exceptions.InvalidSchema:
156 | # pass
157 | # except Exception as e:
158 | # logger.error(f"进群失败:{e}")
159 | else:
160 | print(data)
161 |
162 | # dict格式转pb
163 | def dict2pb(cls, adict, strict=False):
164 | """
165 | Takes a class representing the ProtoBuf Message and fills it with data from
166 | the dict.
167 | """
168 | obj = cls()
169 | for field in obj.DESCRIPTOR.fields:
170 | if not field.label == field.LABEL_REQUIRED:
171 | continue
172 | if field.has_default_value:
173 | continue
174 | if not field.name in adict:
175 | # raise ConvertException('Field "%s" missing from descriptor dictionary.' % field.name)
176 | print('Field "%s" missing from descriptor dictionary.' % field.name)
177 |
178 | if strict:
179 | field_names = set([field.name for field in obj.DESCRIPTOR.fields])
180 | for key in adict.keys():
181 | if key not in field_names:
182 | # raise ConvertException('Key "%s" can not be mapped to field in %s class.' % (key, type(obj)))
183 | print('Key "%s" can not be mapped to field in %s class.' % (key, type(obj)))
184 |
185 | for field in obj.DESCRIPTOR.fields:
186 | if not field.name in adict and not field.has_default_value:
187 | continue
188 | cur_value = adict[field.name] if field.name in adict else field.default_value
189 | msg_type = field.message_type
190 | if field.label == FD.LABEL_REPEATED:
191 | if field.type == FD.TYPE_MESSAGE:
192 | for sub_dict in cur_value:
193 | item = getattr(obj, field.name).add()
194 | item.CopyFrom(dict2pb(msg_type._concrete_class, sub_dict))
195 | else:
196 | map(getattr(obj, field.name).append, cur_value)
197 | else:
198 | if field.type == FD.TYPE_MESSAGE:
199 | value = dict2pb(msg_type._concrete_class, cur_value)
200 | getattr(obj, field.name).CopyFrom(value)
201 | else:
202 | setattr(obj, field.name, cur_value)
203 | return obj
204 |
205 | # 服务端推送消息的ip和端口
206 | msg_server_address = "tcp://127.0.0.1:5557"
207 |
208 | def accept_data(my_queue):
209 | puller = context.socket(zmq.PULL)
210 | puller.connect(msg_server_address)
211 | while True:
212 | # 接收服务端推送的消息
213 | data = puller.recv_pyobj()
214 | # 存到队列里
215 | my_queue.put(data)
216 |
217 | # 启动线程接收来自服务端的消息
218 | t = Thread(target=accept_data, args=(my_response_queue, ))
219 | t.start()
220 |
221 | # 从队列里获取消息并处理,再通过rpc调用服务端
222 | spy = RPCProxy()
223 | handle_response()
--------------------------------------------------------------------------------
/example_rpc_server.py:
--------------------------------------------------------------------------------
1 | from PyWeChatSpy import WeChatSpy
2 | import logging
3 | from rpc_server_tools import *
4 | from queue import Queue
5 | import zmq
6 | import time
7 | from google.protobuf.descriptor import FieldDescriptor as FD
8 |
9 | my_response_queue = Queue()
10 | logger = logging.getLogger(__file__)
11 | logger.setLevel(logging.DEBUG)
12 | formatter = logging.Formatter('%(asctime)s [%(threadName)s] %(levelname)s: %(message)s')
13 | sh = logging.StreamHandler()
14 | sh.setFormatter(formatter)
15 | sh.setLevel(logging.INFO)
16 | logger.addHandler(sh)
17 |
18 | contact_list = []
19 | chatroom_list = []
20 |
21 | # pb格式转dict
22 | def pb2dict(obj):
23 | """
24 | Takes a ProtoBuf Message obj and convertes it to a dict.
25 | """
26 | try:
27 | adict = {}
28 | if not obj.IsInitialized():
29 | return None
30 | for field in obj.DESCRIPTOR.fields:
31 | if not getattr(obj, field.name):
32 | continue
33 | if not field.label == FD.LABEL_REPEATED:
34 | if not field.type == FD.TYPE_MESSAGE:
35 | adict[field.name] = getattr(obj, field.name)
36 | else:
37 | value = pb2dict(getattr(obj, field.name))
38 | if value:
39 | adict[field.name] = value
40 | else:
41 | if field.type == FD.TYPE_MESSAGE:
42 | adict[field.name] = [pb2dict(v) for v in getattr(obj, field.name)]
43 | else:
44 | adict[field.name] = [v for v in getattr(obj, field.name)]
45 | return adict
46 | except Exception as e:
47 | print(e)
48 | return obj
49 |
50 | context = zmq.Context()
51 | # 服务端绑定推送消息的端口
52 | msg_bind_address = "tcp://*:5557"
53 |
54 | def data_forward():
55 | # socket不能定义在线程外!
56 | pusher = context.socket(zmq.PUSH)
57 | pusher.bind(msg_bind_address)
58 | while True:
59 | data = my_response_queue.get()
60 | # 将消息转换成dict格式
61 | data = pb2dict(data)
62 | pusher.send_pyobj(data)
63 |
64 |
65 | if __name__ == '__main__':
66 | spy = WeChatSpy(response_queue=my_response_queue, key="7d30e1a7903a5a4de12a792ed24ae5ea", logger=logger)
67 | pid = spy.run(r"D:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
68 | # 注册远程调用的函数, 自己按需增加
69 | rpc_handler = RPCHandler()
70 | rpc_handler.register_function(spy.send_text)
71 | rpc_handler.register_function(spy.get_contacts)
72 | rpc_handler.register_function(spy.decrypt_image)
73 | # 转发消息到客户端
74 | data_forward()
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/images/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/1.jpg
--------------------------------------------------------------------------------
/images/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/2.jpg
--------------------------------------------------------------------------------
/images/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/3.jpg
--------------------------------------------------------------------------------
/images/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/4.jpg
--------------------------------------------------------------------------------
/images/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/5.jpg
--------------------------------------------------------------------------------
/images/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/6.jpg
--------------------------------------------------------------------------------
/images/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/7.jpg
--------------------------------------------------------------------------------
/images/bqstz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/bqstz.jpg
--------------------------------------------------------------------------------
/images/e.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veikai/PyWeChatSpy/1ff551d310aef1b5425365279c3ca4a351572e10/images/e.gif
--------------------------------------------------------------------------------
/pai1pai.py:
--------------------------------------------------------------------------------
1 | from PyWeChatSpy import WeChatSpy
2 | from PyWeChatSpy.command import *
3 | from PyWeChatSpy.proto import spy_pb2
4 | import random
5 | import re
6 | from queue import Queue
7 |
8 | my_response_queue = Queue()
9 |
10 |
11 | def parse():
12 | while True:
13 | data = my_response_queue.get()
14 | if data.type == CHAT_MESSAGE: # 判断是微信消息数据
15 | chat_message = spy_pb2.ChatMessage()
16 | chat_message.ParseFromString(data.bytes)
17 | for message in chat_message.message: # 遍历微信消息
18 | _type = message.type # 消息类型 1.文本|3.图片...自行探索
19 | _from = message.wxidFrom.str # 消息发送方
20 | _to = message.wxidTo.str # 消息接收方
21 | content = message.content.str # 消息内容
22 | print(_type, _from, _to, content)
23 | if _type == 10000: # 判断是微信拍一拍系统提示
24 | # 因为微信系统消息很多 因此需要用正则匹配消息内容进一步过滤拍一拍提示
25 | m = re.search('".*" 拍了拍我', content)
26 | if m: # 搜索到了匹配的字符串 判断为拍一拍
27 | image_path = f"images/{random.randint(1, 7)}.jpg" # 随机选一张回复用的图片
28 | spy.send_file(_from, image_path) # 发送图片
29 |
30 |
31 | if __name__ == '__main__':
32 | spy = WeChatSpy(response_queue=my_response_queue)
33 | spy.run(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
34 | parse()
35 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | protobuf==3.11.3
2 | Flask==1.1.2
3 | lxml
4 | zmq
5 | pywin32
--------------------------------------------------------------------------------
/rpc_client_tools.py:
--------------------------------------------------------------------------------
1 | import zmq
2 | import pickle
3 |
4 | context = zmq.Context()
5 | # 服务端远程过程调用的ip和端口
6 | rpc_server_address = "tcp://127.0.0.1:5558"
7 |
8 | # RPC服务代理类
9 | class RPCProxy:
10 | def __getattr__(self, name):
11 | def do_rpc(*args, **kwargs):
12 | tmp_socket = context.socket(zmq.REQ)
13 | tmp_socket.connect(rpc_server_address)
14 | tmp_socket.send(pickle.dumps((name, args, kwargs)))
15 | result = tmp_socket.recv_json()
16 | return result
17 | return do_rpc
18 |
19 |
20 |
--------------------------------------------------------------------------------
/rpc_server_tools.py:
--------------------------------------------------------------------------------
1 | import zmq
2 | from threading import Thread
3 | import pickle
4 | context = zmq.Context()
5 |
6 | # 远程过程调用的绑定端口
7 | rpc_bind_address = "tcp://*:5558"
8 |
9 | # RPC服务处理类
10 | class RPCHandler:
11 | def __init__(self):
12 | self._functions = {}
13 | # 创建上下文对象
14 | t2 = Thread(target=self.rpc_server, args=())
15 | # t2.daemon = True
16 | t2.start()
17 |
18 | def register_function(self, func):
19 | self._functions[func.__name__] = func
20 |
21 | def handle_connection(self, data):
22 | # print(data)
23 | func_name, args, kwargs = pickle.loads(data)
24 | print(func_name, args, kwargs)
25 | result = self._functions[func_name](*args, **kwargs)
26 | return result
27 |
28 |
29 |
30 | def rpc_server(self):
31 | # socket不能定义在线程外!
32 | self.reply_socket = context.socket(zmq.REP)
33 | self.reply_socket.bind(rpc_bind_address)
34 | while True:
35 | data = self.reply_socket.recv()
36 | result = None
37 | try:
38 | result = self.handle_connection(data)
39 | except Exception as e:
40 | print(e)
41 | finally:
42 | self.reply_socket.send_json({"result": result})
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/service_example.py:
--------------------------------------------------------------------------------
1 | from PyWeChatSpy.service import SpyService, GET_CONTACTS_LIST, GET_LOGIN_QRCODE, GET_CONTACT_DETAILS
2 | from flask.json import jsonify
3 | from flask import request, send_from_directory
4 | from functools import wraps
5 | from time import sleep
6 | from PyWeChatSpy.proto import spy_pb2
7 | from flask_cors import CORS
8 | from uuid import uuid4
9 | import base64
10 | import os
11 |
12 |
13 | app = SpyService(__name__, key="18d421169d93611a5584affac335e690")
14 | app.config['UPLOAD_FOLDER'] = r"D:\cache"
15 | WECHAT_PROFILE = r"C:\Users\administrator\Documents\WeChat Files"
16 | CORS(app, supports_credentials=True) # 允许跨域
17 |
18 |
19 | def verify_port(fun):
20 | @wraps(fun)
21 | def wrap(port):
22 | if not port and app.spy.port2client:
23 | port = list(app.spy.port2client.keys())[0]
24 | if port:
25 | _id = uuid4().__str__()
26 | return fun(port, _id)
27 | else:
28 | return jsonify({"code": 0, "msg": "port not found"})
29 | return wrap
30 |
31 |
32 | def verify_json(*args):
33 | def decorator(fun):
34 | @wraps(fun)
35 | def wrap(port, _id):
36 | if not request.json:
37 | return jsonify({"code": 0, "msg": "json error"})
38 | for param in args:
39 | if not request.json.get(param):
40 | return jsonify({"code": 0, "msg": "parameters error"})
41 | return fun(port, _id)
42 | return wrap
43 | return decorator
44 |
45 |
46 | @app.route('/open_wechat')
47 | def open_wechat():
48 | app.spy.run(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
49 | i = 0
50 | while i < 20:
51 | if app.spy.port2client.keys().__len__() > app.last_client_count:
52 | app.last_client_count = app.spy.port2client.keys().__len__()
53 | return jsonify({"code": 1, "port": list(app.spy.port2client.keys())[-1]})
54 | i += 1
55 | sleep(0.5)
56 | return jsonify({"code": 0, "msg": "wechat not found"})
57 |
58 |
59 | @app.route('/get_login_qrcode/')
60 | @verify_port
61 | def get_login_qrcode(port, _id):
62 | app.spy.get_login_qrcode(port, _id)
63 | for i in range(20):
64 | if app.client2response.get(_id):
65 | data = app.client2response.pop(_id)
66 | if data.type == GET_LOGIN_QRCODE and not data.code:
67 | return jsonify({"code": 0, "msg": "GET_LOGIN_QRCODE is not available"})
68 | qrcode_data = spy_pb2.LoginQRCode()
69 | qrcode_data.ParseFromString(data.bytes)
70 | base64_data = base64.b64encode(qrcode_data.qrcodeBytes)
71 | return jsonify({"code": 1, "qrcode": base64_data.decode()})
72 | sleep(0.5)
73 | return jsonify({"code": 0, "msg": "login qrcode not found"})
74 |
75 |
76 | @app.route("/user_logout/")
77 | @verify_port
78 | def user_logout(port, _id):
79 | app.spy.user_logout(port, _id)
80 | for i in range(20):
81 | if app.client2user_logout.get(port) is not None:
82 | code = app.client2user_logout.pop(port)
83 | return jsonify({"code": code})
84 | sleep(0.5)
85 | return jsonify({"code": 0})
86 |
87 |
88 | @app.route("/close_wechat/")
89 | @verify_port
90 | def close_wechat(port, _id):
91 | if pid := app.client2pid.get(port):
92 | app.client2pid.pop(port)
93 | os.system(f"taskkill /pid {pid}")
94 | app.last_client_count -= 1
95 | return jsonify({"code": 1})
96 | return jsonify({"code": 0})
97 |
98 |
99 | if __name__ == '__main__':
100 | app.run()
101 |
--------------------------------------------------------------------------------
/ui_example.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtWidgets import QApplication
2 | from PyWeChatSpy.ui.ui import SpyUI
3 | import sys
4 |
5 |
6 | if __name__ == '__main__':
7 | app = QApplication(sys.argv)
8 | spy_ui = SpyUI()
9 | sys.exit(app.exec_())
--------------------------------------------------------------------------------