Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
被猫吃掉的鱼Z
ComWeChatRobot
提交
d4546759
C
ComWeChatRobot
项目概览
被猫吃掉的鱼Z
/
ComWeChatRobot
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ComWeChatRobot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
d4546759
编写于
8月 02, 2022
作者:
J
Jack Li
提交者:
GitHub
8月 02, 2022
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #69 from amchii/feat/message-event
添加使用微信PID注册消息事件功能, 避免多客户端时不必要的消息广播
上级
569c5948
448d0c8a
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
150 addition
and
47 deletion
+150
-47
CWeChatRobot/RobotEvent.cpp
CWeChatRobot/RobotEvent.cpp
+13
-2
CWeChatRobot/RobotEvent.h
CWeChatRobot/RobotEvent.h
+2
-3
CWeChatRobot/WeChatRobotCOM.idl
CWeChatRobot/WeChatRobotCOM.idl
+2
-1
CWeChatRobot/WeChatRobotCOM_i.h
CWeChatRobot/WeChatRobotCOM_i.h
+18
-2
CWeChatRobot/WeChatRobotCOM_p.c
CWeChatRobot/WeChatRobotCOM_p.c
+73
-18
CWeChatRobot/_IRobotEventEvents_CP.h
CWeChatRobot/_IRobotEventEvents_CP.h
+32
-15
DWeChatRobot/ReceiveMessage.cpp
DWeChatRobot/ReceiveMessage.cpp
+1
-1
DWeChatRobot/comclient.cpp
DWeChatRobot/comclient.cpp
+3
-2
DWeChatRobot/comclient.h
DWeChatRobot/comclient.h
+1
-1
Python/test.py
Python/test.py
+1
-1
Python/wxRobot.py
Python/wxRobot.py
+4
-1
Release/CWeChatRobot.exe
Release/CWeChatRobot.exe
+0
-0
Release/DWeChatRobot.dll
Release/DWeChatRobot.dll
+0
-0
未找到文件。
CWeChatRobot/RobotEvent.cpp
浏览文件 @
d4546759
...
...
@@ -8,14 +8,14 @@
// CRobotEvent
STDMETHODIMP
CRobotEvent
::
CPostMessage
(
int
msgtype
,
VARIANT
*
msg
,
int
*
__result
)
STDMETHODIMP
CRobotEvent
::
CPostMessage
(
DWORD
pid
,
int
msgtype
,
VARIANT
*
msg
,
int
*
__result
)
{
// TODO: 在此处添加实现代码
// 将收到的消息广播给所有用户
switch
(
msgtype
)
{
case
WX_MESSAGE
:
{
Fire_OnGetMessageEvent
(
msg
);
Fire_OnGetMessageEvent
(
pid
,
msg
);
break
;
}
case
WX_LOG_MESSAGE
:{
...
...
@@ -27,3 +27,14 @@ STDMETHODIMP CRobotEvent::CPostMessage(int msgtype,VARIANT* msg, int* __result)
*
__result
=
0
;
return
S_OK
;
}
/**
* \param pid 微信PID
* \param cookie Cookie
*/
STDMETHODIMP
CRobotEvent
::
CRegisterWxPidWithCookie
(
DWORD
pid
,
DWORD
cookie
,
int
*
__result
)
{
WxPidToEventCookie
[
pid
].
insert
(
cookie
);
*
__result
=
0
;
return
S_OK
;
}
CWeChatRobot/RobotEvent.h
浏览文件 @
d4546759
...
...
@@ -9,10 +9,8 @@
#include "_IRobotEventEvents_CP.h"
using
namespace
ATL
;
// CRobotEvent
class
ATL_NO_VTABLE
CRobotEvent
:
...
...
@@ -56,7 +54,8 @@ public:
STDMETHOD
(
CPostMessage
)(
int
msgtype
,
VARIANT
*
msg
,
int
*
__result
);
STDMETHOD
(
CPostMessage
)(
DWORD
pid
,
int
msgtype
,
VARIANT
*
msg
,
int
*
__result
);
STDMETHOD
(
CRegisterWxPidWithCookie
)(
DWORD
pid
,
DWORD
cookie
,
int
*
__result
);
};
OBJECT_ENTRY_AUTO
(
__uuidof
(
RobotEvent
),
CRobotEvent
)
CWeChatRobot/WeChatRobotCOM.idl
浏览文件 @
d4546759
...
...
@@ -68,7 +68,8 @@ interface IWeChatRobot : IDispatch
]
interface
IRobotEvent
:
IDispatch
{
[
id
(
1
),
helpstring
(
"用于微信主动推送消息"
)
]
HRESULT
CPostMessage
(
[
in
]
int
msgtype
,
[
in
]
VARIANT
*
msg
,
[
out
,
retval
]
int
*
__result
)
;
[
id
(
1
),
helpstring
(
"用于微信主动推送消息"
)
]
HRESULT
CPostMessage
(
[
in
]
DWORD
pid
,
[
in
]
int
msgtype
,
[
in
]
VARIANT
*
msg
,
[
out
,
retval
]
int
*
__result
)
;
[
id
(
2
),
helpstring
(
"用于微信主动推送消息"
)
]
HRESULT
CRegisterWxPidWithCookie
(
[
in
]
DWORD
pid
,
[
in
]
DWORD
cookie
,
[
out
,
retval
]
int
*
__result
)
;
}
;
[
uuid
(
721
abb35
-
141
a
-
4
aa2
-
94
f2
-
762
e2833fa6c
),
...
...
CWeChatRobot/WeChatRobotCOM_i.h
浏览文件 @
d4546759
...
...
@@ -843,10 +843,16 @@ EXTERN_C const IID IID_IRobotEvent;
{
public:
virtual
/* [helpstring][id] */
HRESULT
STDMETHODCALLTYPE
CPostMessage
(
/* [in] */
DWORD
pid
,
/* [in] */
int
msgtype
,
/* [in] */
VARIANT
*
msg
,
/* [retval][out] */
int
*
__result
)
=
0
;
virtual
/* [helpstring][id] */
HRESULT
STDMETHODCALLTYPE
CRegisterWxPidWithCookie
(
/* [in] */
DWORD
pid
,
/* [in] */
DWORD
cookie
,
/* [retval][out] */
int
*
__result
)
=
0
;
};
...
...
@@ -907,10 +913,17 @@ EXTERN_C const IID IID_IRobotEvent;
/* [helpstring][id] */
HRESULT
(
STDMETHODCALLTYPE
*
CPostMessage
)(
IRobotEvent
*
This
,
/* [in] */
DWORD
pid
,
/* [in] */
int
msgtype
,
/* [in] */
VARIANT
*
msg
,
/* [retval][out] */
int
*
__result
);
/* [helpstring][id] */
HRESULT
(
STDMETHODCALLTYPE
*
CRegisterWxPidWithCookie
)(
IRobotEvent
*
This
,
/* [in] */
DWORD
pid
,
/* [in] */
DWORD
cookie
,
/* [retval][out] */
int
*
__result
);
END_INTERFACE
}
IRobotEventVtbl
;
...
...
@@ -947,8 +960,11 @@ EXTERN_C const IID IID_IRobotEvent;
(
(
This
)
->
lpVtbl
->
Invoke
(
This
,
dispIdMember
,
riid
,
lcid
,
wFlags
,
pDispParams
,
pVarResult
,
pExcepInfo
,
puArgErr
)
)
#define IRobotEvent_CPostMessage(This,msgtype,msg,__result) \
(
(
This
)
->
lpVtbl
->
CPostMessage
(
This
,
msgtype
,
msg
,
__result
)
)
#define IRobotEvent_CPostMessage(This,pid,msgtype,msg,__result) \
(
(
This
)
->
lpVtbl
->
CPostMessage
(
This
,
pid
,
msgtype
,
msg
,
__result
)
)
#define IRobotEvent_CRegisterWxPidWithCookie(This,pid,cookie,__result) \
(
(
This
)
->
lpVtbl
->
CRegisterWxPidWithCookie
(
This
,
pid
,
cookie
,
__result
)
)
#endif
/* COBJMACROS */
...
...
CWeChatRobot/WeChatRobotCOM_p.c
浏览文件 @
d4546759
...
...
@@ -49,7 +49,7 @@
#include "WeChatRobotCOM_i.h"
#define TYPE_FORMAT_STRING_SIZE 1239
#define PROC_FORMAT_STRING_SIZE 21
25
#define PROC_FORMAT_STRING_SIZE 21
79
#define EXPR_FORMAT_STRING_SIZE 1
#define TRANSMIT_AS_TABLE_SIZE 0
#define WIRE_MARSHAL_TABLE_SIZE 2
...
...
@@ -2019,44 +2019,96 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor
0x6c
,
/* Old Flags: object, Oi2 */
/* 2078 */
NdrFcLong
(
0x0
),
/* 0 */
/* 2082 */
NdrFcShort
(
0x7
),
/* 7 */
/* 2084 */
NdrFcShort
(
0x1
4
),
/* x86 Stack size/offset = 20
*/
/* 2086 */
NdrFcShort
(
0x
8
),
/* 8
*/
/* 2084 */
NdrFcShort
(
0x1
8
),
/* x86 Stack size/offset = 24
*/
/* 2086 */
NdrFcShort
(
0x
10
),
/* 16
*/
/* 2088 */
NdrFcShort
(
0x24
),
/* 36 */
/* 2090 */
0x46
,
/* Oi2 Flags: clt must size, has return, has ext, */
0x
4
,
/* 4
*/
0x
5
,
/* 5
*/
/* 2092 */
0x8
,
/* 8 */
0x45
,
/* Ext Flags: new corr desc, srv corr check, has range on conformance */
/* 2094 */
NdrFcShort
(
0x0
),
/* 0 */
/* 2096 */
NdrFcShort
(
0x1
),
/* 1 */
/* 2098 */
NdrFcShort
(
0x0
),
/* 0 */
/* Parameter
msgtype
*/
/* Parameter
pid
*/
/* 2100 */
NdrFcShort
(
0x48
),
/* Flags: in, base type, */
/* 2102 */
NdrFcShort
(
0x4
),
/* x86 Stack size/offset = 4 */
/* 2104 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* Parameter msg */
/* Parameter msg
type
*/
/* 2106 */
NdrFcShort
(
0x
10b
),
/* Flags: must size, must free, in, simple ref
, */
/* 2106 */
NdrFcShort
(
0x
48
),
/* Flags: in, base type
, */
/* 2108 */
NdrFcShort
(
0x8
),
/* x86 Stack size/offset = 8 */
/* 2110 */
NdrFcShort
(
0x4cc
),
/* Type Offset=1228 */
/* 2110 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* Parameter
__result
*/
/* Parameter
msg
*/
/* 2112 */
NdrFcShort
(
0x
2150
),
/* Flags: out, base type, simple ref, srv alloc size=8
*/
/* 2112 */
NdrFcShort
(
0x
10b
),
/* Flags: must size, must free, in, simple ref,
*/
/* 2114 */
NdrFcShort
(
0xc
),
/* x86 Stack size/offset = 12 */
/* 2116 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* 2116 */
NdrFcShort
(
0x4cc
),
/* Type Offset=1228 */
/*
Return value
*/
/*
Parameter __result
*/
/* 2118 */
NdrFcShort
(
0x
70
),
/* Flags: out, return, base type,
*/
/* 2118 */
NdrFcShort
(
0x
2150
),
/* Flags: out, base type, simple ref, srv alloc size=8
*/
/* 2120 */
NdrFcShort
(
0x10
),
/* x86 Stack size/offset = 16 */
/* 2122 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* Return value */
/* 2124 */
NdrFcShort
(
0x70
),
/* Flags: out, return, base type, */
/* 2126 */
NdrFcShort
(
0x14
),
/* x86 Stack size/offset = 20 */
/* 2128 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* Procedure CRegisterWxPidWithCookie */
/* 2130 */
0x33
,
/* FC_AUTO_HANDLE */
0x6c
,
/* Old Flags: object, Oi2 */
/* 2132 */
NdrFcLong
(
0x0
),
/* 0 */
/* 2136 */
NdrFcShort
(
0x8
),
/* 8 */
/* 2138 */
NdrFcShort
(
0x14
),
/* x86 Stack size/offset = 20 */
/* 2140 */
NdrFcShort
(
0x10
),
/* 16 */
/* 2142 */
NdrFcShort
(
0x24
),
/* 36 */
/* 2144 */
0x44
,
/* Oi2 Flags: has return, has ext, */
0x4
,
/* 4 */
/* 2146 */
0x8
,
/* 8 */
0x41
,
/* Ext Flags: new corr desc, has range on conformance */
/* 2148 */
NdrFcShort
(
0x0
),
/* 0 */
/* 2150 */
NdrFcShort
(
0x0
),
/* 0 */
/* 2152 */
NdrFcShort
(
0x0
),
/* 0 */
/* Parameter pid */
/* 2154 */
NdrFcShort
(
0x48
),
/* Flags: in, base type, */
/* 2156 */
NdrFcShort
(
0x4
),
/* x86 Stack size/offset = 4 */
/* 2158 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* Parameter cookie */
/* 2160 */
NdrFcShort
(
0x48
),
/* Flags: in, base type, */
/* 2162 */
NdrFcShort
(
0x8
),
/* x86 Stack size/offset = 8 */
/* 2164 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* Parameter __result */
/* 2166 */
NdrFcShort
(
0x2150
),
/* Flags: out, base type, simple ref, srv alloc size=8 */
/* 2168 */
NdrFcShort
(
0xc
),
/* x86 Stack size/offset = 12 */
/* 2170 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
/* Return value */
/* 2172 */
NdrFcShort
(
0x70
),
/* Flags: out, return, base type, */
/* 2174 */
NdrFcShort
(
0x10
),
/* x86 Stack size/offset = 16 */
/* 2176 */
0x8
,
/* FC_LONG */
0x0
,
/* 0 */
0x0
}
};
...
...
@@ -3093,7 +3145,8 @@ static const unsigned short IRobotEvent_FormatStringOffsetTable[] =
(
unsigned
short
)
-
1
,
(
unsigned
short
)
-
1
,
(
unsigned
short
)
-
1
,
2076
2076
,
2130
};
static
const
MIDL_STUBLESS_PROXY_INFO
IRobotEvent_ProxyInfo
=
...
...
@@ -3117,7 +3170,7 @@ static const MIDL_SERVER_INFO IRobotEvent_ServerInfo =
0
,
0
,
0
};
CINTERFACE_PROXY_VTABLE
(
8
)
_IRobotEventProxyVtbl
=
CINTERFACE_PROXY_VTABLE
(
9
)
_IRobotEventProxyVtbl
=
{
&
IRobotEvent_ProxyInfo
,
&
IID_IRobotEvent
,
...
...
@@ -3128,7 +3181,8 @@ CINTERFACE_PROXY_VTABLE(8) _IRobotEventProxyVtbl =
0
/* IDispatch::GetTypeInfo */
,
0
/* IDispatch::GetIDsOfNames */
,
0
/* IDispatch_Invoke_Proxy */
,
(
void
*
)
(
INT_PTR
)
-
1
/* IRobotEvent::CPostMessage */
(
void
*
)
(
INT_PTR
)
-
1
/* IRobotEvent::CPostMessage */
,
(
void
*
)
(
INT_PTR
)
-
1
/* IRobotEvent::CRegisterWxPidWithCookie */
};
...
...
@@ -3138,6 +3192,7 @@ static const PRPC_STUB_FUNCTION IRobotEvent_table[] =
STUB_FORWARDING_FUNCTION
,
STUB_FORWARDING_FUNCTION
,
STUB_FORWARDING_FUNCTION
,
NdrStubCall2
,
NdrStubCall2
};
...
...
@@ -3145,7 +3200,7 @@ CInterfaceStubVtbl _IRobotEventStubVtbl =
{
&
IID_IRobotEvent
,
&
IRobotEvent_ServerInfo
,
8
,
9
,
&
IRobotEvent_table
[
-
3
],
CStdStubBuffer_DELEGATING_METHODS
};
...
...
CWeChatRobot/_IRobotEventEvents_CP.h
浏览文件 @
d4546759
#
pragma
once
#include <map>
#include <set>
/**
* 微信PID与客户端事件ConnectionPoint的cookie的映射,客户端使用自己关心的微信PID和cookie进行注册,
* 服务端根据PID向订阅该PID的客户端发起事件调用
*/
map
<
DWORD
,
set
<
DWORD
>>
WxPidToEventCookie
;
template
<
class
T
>
class
CProxy_IRobotEventEvents
:
public
ATL
::
IConnectionPointImpl
<
T
,
&
__uuidof
(
_IRobotEventEvents
)
>
{
public:
HRESULT
Fire_OnGetMessageEvent
(
VARIANT
*
msg
)
HRESULT
Fire_OnGetMessageEvent
(
DWORD
pid
,
VARIANT
*
msg
)
{
HRESULT
hr
=
S_OK
;
T
*
pThis
=
static_cast
<
T
*>
(
this
);
int
cConnections
=
m_vec
.
GetSize
();
for
(
int
iConnection
=
0
;
iConnection
<
cConnections
;
iConnection
++
)
if
(
WxPidToEventCookie
.
count
(
pid
)
==
0
)
{
return
hr
;
}
const
set
<
DWORD
>
cookies
=
WxPidToEventCookie
[
pid
];
for
(
DWORD
cookie
:
cookies
)
{
pThis
->
Lock
();
CComPtr
<
IUnknown
>
punkConnection
=
m_vec
.
GetAt
(
iConnection
);
ATL
::
CComPtr
<
IUnknown
>
punkConnection
=
this
->
m_vec
.
GetUnknown
(
cookie
);
pThis
->
Unlock
();
IDispatch
*
pConnection
=
static_cast
<
IDispatch
*>
(
punkConnection
.
p
);
if
(
pConnection
)
if
(
punkConnection
)
{
/*CComVariant avarParams[1]
;
avarParams[0] = msg;
avarParams[0].vt = msg->vt;*/
CComVariant
varResult
;
IDispatch
*
pConnection
=
static_cast
<
IDispatch
*>
(
punkConnection
.
p
)
;
if
(
pConnection
)
{
ATL
::
CComVariant
varResult
;
DISPPARAMS
params
=
{
msg
,
NULL
,
1
,
0
};
hr
=
pConnection
->
Invoke
(
1
,
IID_NULL
,
LOCALE_USER_DEFAULT
,
DISPATCH_METHOD
,
&
params
,
&
varResult
,
NULL
,
NULL
);
DISPPARAMS
params
=
{
msg
,
nullptr
,
1
,
0
};
hr
=
pConnection
->
Invoke
(
1
,
IID_NULL
,
LOCALE_USER_DEFAULT
,
DISPATCH_METHOD
,
&
params
,
&
varResult
,
nullptr
,
nullptr
);
}
else
{
WxPidToEventCookie
[
pid
].
erase
(
cookie
);
}
}
else
{
WxPidToEventCookie
[
pid
].
erase
(
cookie
);
}
}
return
hr
;
...
...
DWeChatRobot/ReceiveMessage.cpp
浏览文件 @
d4546759
...
...
@@ -203,7 +203,7 @@ static void dealMessage(DWORD messageAddr) {
VARIANT
vsaValue
;
vsaValue
.
vt
=
VT_ARRAY
|
VT_VARIANT
;
V_ARRAY
(
&
vsaValue
)
=
psaValue
;
PostComMessage
(
WX_MESSAGE
,
&
vsaValue
);
PostComMessage
(
message
->
pid
,
WX_MESSAGE
,
&
vsaValue
);
#endif
HANDLE
hThread
=
CreateThread
(
NULL
,
0
,
(
LPTHREAD_START_ROUTINE
)
SendSocketMessage
,
message
,
NULL
,
0
);
if
(
hThread
)
{
...
...
DWeChatRobot/comclient.cpp
浏览文件 @
d4546759
...
...
@@ -33,8 +33,9 @@ public:
}
};
BOOL
PostComMessage
(
int
msgtype
,
VARIANT
*
msg
)
{
BOOL
PostComMessage
(
DWORD
pid
,
int
msgtype
,
VARIANT
*
msg
)
{
HRESULT
hr
=
S_OK
;
hr
=
CoInitializeEx
(
0
,
COINIT_APARTMENTTHREADED
);
if
(
FAILED
(
hr
))
return
false
;
...
...
@@ -50,7 +51,7 @@ BOOL PostComMessage(int msgtype,VARIANT* msg) {
AtlAdvise(spRobotEvent, sinkptr, __uuidof(_IRobotEventEvents), &cookies);
*/
int
__result
=
0
;
spRobotEvent
->
CPostMessage
(
msgtype
,
msg
,
&
__result
);
spRobotEvent
->
CPostMessage
(
pid
,
msgtype
,
msg
,
&
__result
);
}
else
{
return
false
;
...
...
DWeChatRobot/comclient.h
浏览文件 @
d4546759
...
...
@@ -6,4 +6,4 @@
#define WX_MESSAGE 1
#define WX_LOG_MESSAGE 2
BOOL
PostComMessage
(
int
msgtype
,
VARIANT
*
msg
);
\ No newline at end of file
BOOL
PostComMessage
(
DWORD
pid
,
int
msgtype
,
VARIANT
*
msg
);
\ No newline at end of file
Python/test.py
浏览文件 @
d4546759
...
...
@@ -88,5 +88,5 @@ if __name__ == '__main__':
wx
=
WeChatRobot
(
pid_list
[
0
])
wx
.
StartService
()
wx
.
StartReceiveMessage
()
wxRobot
.
register_msg_event
()
wxRobot
.
register_msg_event
(
wx
.
pid
)
wx
.
StopService
()
Python/wxRobot.py
浏览文件 @
d4546759
...
...
@@ -1060,12 +1060,14 @@ def start_wechat() -> 'WeChatRobot' or None:
return
None
def
register_msg_event
(
event_sink
:
'WeChatEventSink'
or
None
=
None
)
->
None
:
def
register_msg_event
(
wx_pid
:
int
,
event_sink
:
'WeChatEventSink'
or
None
=
None
)
->
None
:
"""
通过COM组件连接点接收消息,真正的回调
只会收到wx_pid对应的微信消息
Parameters
----------
wx_pid: 微信PID
event_sink : object, optional
回调的实现类,该类要继承`WeChatEventSink`类或实现其中的方法.
...
...
@@ -1080,6 +1082,7 @@ def register_msg_event(event_sink: 'WeChatEventSink' or None = None) -> None:
sink
=
event_sink
or
WeChatEventSink
()
connection_point
=
GetEvents
(
event
,
sink
)
assert
connection_point
is
not
None
event
.
CRegisterWxPidWithCookie
(
wx_pid
,
connection_point
.
cookie
)
while
True
:
try
:
PumpEvents
(
2
)
...
...
Release/CWeChatRobot.exe
浏览文件 @
d4546759
无法预览此类型文件
Release/DWeChatRobot.dll
浏览文件 @
d4546759
无法预览此类型文件
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录