├── README.md ├── dll ├── MsgIPC.pro ├── dllmain.cpp ├── message.cpp ├── message.h ├── precompiled.h ├── qq_definition.cpp ├── qq_definition.h ├── websocket_client.cpp └── websocket_client.h ├── doc └── screenshot.png └── python ├── form.ui ├── requirements.txt ├── serve.py ├── serve_with_pyside.py ├── serve_with_pyside_nogui.py ├── serve_without_pyside.py └── ui_form.py /README.md: -------------------------------------------------------------------------------- 1 | MsgIPC是通过Hook的方式截取QQ消息并通过zeromq发布的一款dll插件,项目相关代码仅供学习参考。 2 | 3 | ## 说明 4 | 5 | QQ版本:8.2(17724) 6 | 7 | python目录下nogui.py为非pyside2即可运行。 8 | 9 | ### 注意: 10 | 新版QQ确保关闭QQProtect进程(QQ_SecurityCheck_Patch_v12.1(for_v9.2.x).exe),`KernelUtil.dll`中`CheckVideoMsg`导出符号是否一致。 11 | 12 | `dev` 分支将zeromq替换成websocket方便功能扩展。 13 | 14 | - 支持断线重连。 15 | - 添加GetSelfUin接口获取自身QQ号使用案例。 16 | 17 | ## 截图 18 | ![screenshot](https://raw.githubusercontent.com/bstaint/MsgIPC/dev/doc/screenshot.png) 19 | 20 | ## C++ dll 21 | 22 | pro文件中引用第三方pri文件参考: 23 | [https://github.com/bstaint/3rdparty](https://github.com/bstaint/3rdparty) 24 | 25 | #### requires 26 | 27 | - minhook 28 | - spdlog 29 | - websocketpp 30 | - concurrentqueue ([https://github.com/cameron314/concurrentqueue](https://github.com/cameron314/concurrentqueue)) 31 | 32 | ## Python Client 33 | 34 | #### requires 35 | 36 | - PySide2 37 | - websockets 38 | - asyncio 39 | -------------------------------------------------------------------------------- /dll/MsgIPC.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | CONFIG += c++11 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | dllmain.cpp \ 8 | message.cpp \ 9 | qq_definition.cpp \ 10 | websocket_client.cpp 11 | 12 | HEADERS += \ 13 | message.h \ 14 | precompiled.h \ 15 | qq_definition.h \ 16 | websocket_client.h 17 | 18 | PRECOMPILED_HEADER = precompiled.h 19 | 20 | LIBS += -luser32 21 | 22 | include (E:/3rdParty/boost.pri) 23 | include (E:/3rdParty/3rdparty.pri) 24 | 25 | add_deps(debug/spdlog) 26 | add_deps(debug/minhook) 27 | add_deps(net/websocketpp) 28 | add_deps(general/concurrentqueue) 29 | -------------------------------------------------------------------------------- /dll/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "precompiled.h" 2 | #include "qq_definition.h" 3 | #include "message.h" 4 | #include "websocket_client.h" 5 | 6 | using namespace msgipc; 7 | 8 | std::shared_ptr sink(nullptr); 9 | std::shared_ptr logger(nullptr); 10 | 11 | moodycamel::BlockingConcurrentQueue kQueue; 12 | 13 | // 如果groupUin = 0 则为私聊 14 | void __cdecl MyCheckVideoMsg(int a, unsigned long senderUin, /*unsigned long unknown, */unsigned long groupUin, unsigned long * msg) 15 | { 16 | static std::wstring_convert> conv; 17 | 18 | wchar_t * nickname = NULL; 19 | wchar_t * text = NULL; 20 | // 获取消息时间 21 | // __int64 timestamp = GetMsgTime(msg); 22 | GetNickname(&nickname, senderUin); 23 | GetMsgAbstract(&text, msg); 24 | 25 | spdlog::info("senderUin: {0:x}, groupUin: {1:x}", senderUin, groupUin); 26 | kQueue.enqueue(new MessageChat(senderUin, 27 | groupUin, 28 | conv.to_bytes(nickname), 29 | conv.to_bytes(text))); 30 | 31 | CheckVideoMsg(a, senderUin/*, unknown*/, groupUin, msg); 32 | } 33 | 34 | void OnMessageCallback(const String& text) 35 | { 36 | Property item; 37 | try { 38 | item = MessageLoad(text); 39 | 40 | switch (item.get("errno")) { 41 | case MSG_SELFUIN: 42 | kQueue.enqueue(new Message(MSG_SELFUIN, std::to_string(GetSelfUin()))); 43 | break; 44 | case MSG_TEST: 45 | spdlog::info("This is a test command\n"); 46 | break; 47 | default: 48 | spdlog::error("unknown message"); 49 | break; 50 | } 51 | } catch (...) { 52 | spdlog::error("can't parser message."); 53 | } 54 | } 55 | 56 | DWORD WINAPI WebSocketProc(HMODULE hModule) 57 | { 58 | kClient.setConnectStr("ws://192.168.10.1:5678"); 59 | kClient.setTimeout(10000); 60 | kClient.setCallback(OnMessageCallback); 61 | kClient.connect(); 62 | return 0; 63 | } 64 | 65 | DWORD WINAPI RecvMsgProc(HMODULE hModule) 66 | { 67 | Message* message = nullptr; 68 | while(1) 69 | { 70 | kQueue.wait_dequeue(message); 71 | if (message == nullptr) 72 | { 73 | spdlog::warn("message ptr should not empty"); 74 | continue; 75 | } 76 | 77 | String s = MessageDump(message); 78 | if(kClient.is_connected()) 79 | kClient.send(s); 80 | 81 | delete message; 82 | message = nullptr; 83 | } 84 | return 0; 85 | } 86 | 87 | BOOL SetHook(LPVOID pTarget, LPVOID pDest, LPVOID pOld) 88 | { 89 | MH_STATUS ret = MH_OK; 90 | 91 | spdlog::info("SetHook begin, pTarget: {}", pTarget); 92 | ret = MH_CreateHook(pTarget, pDest, reinterpret_cast(pOld)); 93 | if (ret != MH_OK) 94 | { 95 | spdlog::error("MH_CreateHook failed, MH_STATUS: {}", MH_StatusToString(ret)); 96 | return FALSE; 97 | } 98 | 99 | if ((ret = MH_EnableHook((LPVOID)pTarget)) != MH_OK) 100 | { 101 | spdlog::error("MH_CreateHook failed, MH_STATUS: {}", MH_StatusToString(ret)); 102 | return FALSE; 103 | } 104 | 105 | return TRUE; 106 | } 107 | 108 | BOOL UnHook(LPVOID pTarget) 109 | { 110 | if (MH_DisableHook(pTarget) != MH_OK) 111 | return FALSE; 112 | 113 | if(MH_Uninitialize() != MH_OK) 114 | return FALSE; 115 | 116 | return TRUE; 117 | } 118 | 119 | BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID lpReserved) 120 | { 121 | switch (reason) 122 | { 123 | case DLL_PROCESS_ATTACH: 124 | { 125 | DisableThreadLibraryCalls(hInst); 126 | // 设置日志默认输出 127 | sink = std::make_shared(); 128 | logger = std::make_shared("MsgIPC", sink); 129 | spdlog::set_default_logger(logger); 130 | 131 | // 初始化minhook并hook 132 | MH_Initialize(); 133 | if(!InitQQPtr()) return FALSE; 134 | 135 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WebSocketProc, NULL, 0, NULL); 136 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RecvMsgProc, NULL, 0, NULL); 137 | 138 | if(SetHook((LPVOID)CheckVideoMsgPtr, &MyCheckVideoMsg, &CheckVideoMsg)) 139 | spdlog::info("SetHook OK."); 140 | } 141 | break; 142 | case DLL_PROCESS_DETACH: 143 | { 144 | // TODO: DLL Detach Crash. 145 | if(UnHook((LPVOID)CheckVideoMsgPtr)) 146 | spdlog::info("UnHook OK."); 147 | 148 | MH_Uninitialize(); 149 | } 150 | break; 151 | case DLL_THREAD_ATTACH: 152 | break; 153 | case DLL_THREAD_DETACH: 154 | break; 155 | } 156 | return TRUE; 157 | } 158 | -------------------------------------------------------------------------------- /dll/message.cpp: -------------------------------------------------------------------------------- 1 | #include "message.h" 2 | 3 | using namespace boost::property_tree; 4 | 5 | namespace msgipc { 6 | 7 | Property MessageLoad(const String& text) 8 | { 9 | std::istringstream iss; 10 | iss.str(text); 11 | 12 | Property item; 13 | json_parser::read_json(iss, item); 14 | 15 | return item; 16 | } 17 | 18 | String MessageDump(Message *message) 19 | { 20 | Property item; 21 | std::stringstream is; 22 | 23 | item.put("errno", message->err()); 24 | message->fill(item); 25 | write_json(is, item); 26 | 27 | return is.str(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /dll/message.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGE_H 2 | #define MESSAGE_H 3 | 4 | #include "precompiled.h" 5 | 6 | namespace msgipc { 7 | 8 | enum err { 9 | MSG_UNKNOWN = -1, 10 | MSG_ERROR = 0, 11 | MSG_OK = 1, 12 | MSG_SELFUIN, 13 | MSG_CHAT, 14 | MSG_TEST 15 | }; 16 | 17 | class Message 18 | { 19 | protected: 20 | uint8_t errno_; 21 | String message_; 22 | 23 | public: 24 | Message() : errno_(MSG_UNKNOWN), message_("") {} 25 | Message(const uint8_t err, const String& message) : 26 | errno_(err), message_(message) {} 27 | 28 | uint8_t err() const { return errno_; } 29 | virtual void fill(Property& item) { item.put("message", message_); } 30 | 31 | virtual ~Message() {} 32 | }; 33 | 34 | class MessageChat : public Message 35 | { 36 | uint32_t sender_; 37 | uint32_t group_; 38 | String nickname_; 39 | 40 | public: 41 | MessageChat() : Message(), sender_(0), group_(0), nickname_("") {} 42 | MessageChat(uint32_t sender, uint32_t group, 43 | const String& nickname, const String& message) : 44 | Message(MSG_CHAT, message), 45 | sender_(sender), group_(group), nickname_(nickname) {} 46 | 47 | void fill(Property& item) 48 | { 49 | Property subitem; 50 | subitem.put("sender", sender_); 51 | subitem.put("group", group_); 52 | subitem.put("nickname", nickname_); 53 | subitem.put("text", message_); 54 | 55 | item.push_back(std::make_pair("message", subitem)); 56 | } 57 | }; 58 | 59 | Property MessageLoad(const String &text); 60 | String MessageDump(Message *message); 61 | 62 | } 63 | 64 | #endif // MESSAGE_H 65 | -------------------------------------------------------------------------------- /dll/precompiled.h: -------------------------------------------------------------------------------- 1 | #ifndef PRECOMPILED_H 2 | #define PRECOMPILED_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace msgipc 19 | { 20 | typedef std::string String; 21 | typedef boost::property_tree::ptree Property; 22 | } 23 | 24 | #endif // PRECOMPILED_H 25 | -------------------------------------------------------------------------------- /dll/qq_definition.cpp: -------------------------------------------------------------------------------- 1 | #include "qq_definition.h" 2 | 3 | ULONG_PTR CheckVideoMsgPtr = NULL; 4 | CheckVideoMsg_t CheckVideoMsg = nullptr; 5 | GetMsgTime_t GetMsgTime = nullptr; 6 | GetMsgAbstract_t GetMsgAbstract = nullptr; 7 | GetNickname_t GetNickname = nullptr; 8 | GetSelfUin_t GetSelfUin = nullptr; 9 | 10 | bool InitQQPtr() 11 | { 12 | HMODULE hModule = GetModuleHandleA("KernelUtil"); 13 | 14 | GetMsgTime = (GetMsgTime_t)GetProcAddress(hModule, GetMsgTime_Symbol); 15 | GetMsgAbstract = (GetMsgAbstract_t)GetProcAddress(hModule, GetMsgAbstract_Symbol); 16 | GetNickname = (GetNickname_t)GetProcAddress(hModule, GetNickname_Symbol); 17 | GetSelfUin = (GetSelfUin_t)GetProcAddress(hModule, GetSelfUin_Symbol); 18 | 19 | CheckVideoMsgPtr = (ULONG_PTR)GetProcAddress(hModule, CheckVideoMsg_Symbol); 20 | CheckVideoMsg = (CheckVideoMsg_t)CheckVideoMsgPtr; 21 | 22 | if(GetMsgTime && CheckVideoMsg && GetMsgAbstract && GetNickname) 23 | return true; 24 | 25 | spdlog::error("InitQQPtr failed!"); 26 | spdlog::info("GetMsgTime: {0:x}, CheckVideoMsg: {1:x}, GetMsgAbstract: {2:x}, GetNickname: {3:x}", 27 | (ULONG_PTR)GetMsgTime, 28 | (ULONG_PTR)CheckVideoMsg, 29 | (ULONG_PTR)GetMsgAbstract, 30 | (ULONG_PTR)GetNickname); 31 | return false; 32 | } 33 | -------------------------------------------------------------------------------- /dll/qq_definition.h: -------------------------------------------------------------------------------- 1 | #ifndef QQ_DEFINITION_H 2 | #define QQ_DEFINITION_H 3 | 4 | #include "precompiled.h" 5 | 6 | // 8.2 7 | #define CheckVideoMsg_Symbol "?CheckVideoMsg@Msg@Util@@YAXHKKPAUITXMsgPack@@@Z" 8 | // 9.2.3 (26595) 9 | //#define CheckVideoMsg_Symbol "?CheckVideoMsg@Msg@Util@@YAXHKKKPAUITXMsgPack@@@Z" 10 | #define GetMsgAbstract_Symbol "?GetMsgAbstract@Msg@Util@@YA?AVCTXStringW@@PAUITXMsgPack@@@Z" 11 | #define GetMsgTime_Symbol "?GetMsgTime@Msg@Util@@YA_JPAUITXMsgPack@@@Z" 12 | #define GetMsgDumpString_Symbol "?GetMsgDumpString@Msg@Util@@YA?AVCTXStringW@@PAUITXMsgPack@@@Z" 13 | #define GetNickname_Symbol "?GetNickname@Contact@Util@@YA?AVCTXStringW@@K@Z" 14 | #define GetSelfUin_Symbol "?GetSelfUin@Contact@Util@@YAKXZ" 15 | 16 | //void __cdecl Util::Msg::CheckVideoMsg(int,unsigned long,unsigned long,struct ITXMsgPack *) 17 | typedef void (__cdecl* CheckVideoMsg_t)(int, unsigned long, unsigned long, unsigned long *); 18 | //typedef void (__cdecl* CheckVideoMsg_t)(int, unsigned long, unsigned long, unsigned long, unsigned long *); 19 | //__int64 __cdecl Util::Msg::GetMsgTime(struct ITXMsgPack *) 20 | typedef __int64 (__cdecl* GetMsgTime_t)(unsigned long *); 21 | //class CTXStringW __cdecl Util::Msg::GetMsgAbstract(struct ITXMsgPack *) 22 | typedef void (__cdecl* GetMsgAbstract_t)(void *, unsigned long *); 23 | //class CTXStringW __cdecl Util::Contact::GetNickname(unsigned long) 24 | typedef void (__cdecl* GetNickname_t)(void *, unsigned long); 25 | 26 | typedef unsigned long (__cdecl* GetSelfUin_t)(void); 27 | 28 | // 初始化Hook函数指针 29 | bool InitQQPtr(); 30 | 31 | extern ULONG_PTR CheckVideoMsgPtr; 32 | // 33 | extern CheckVideoMsg_t CheckVideoMsg; 34 | // 获取消息时间 35 | extern GetMsgTime_t GetMsgTime; 36 | // 获取消息内容 37 | extern GetMsgAbstract_t GetMsgAbstract; 38 | // 通过QQ获取昵称 39 | extern GetNickname_t GetNickname; 40 | 41 | extern GetSelfUin_t GetSelfUin; 42 | 43 | #endif // QQ_DEFINITION_H 44 | -------------------------------------------------------------------------------- /dll/websocket_client.cpp: -------------------------------------------------------------------------------- 1 | #include "websocket_client.h" 2 | #include "precompiled.h" 3 | 4 | using std::bind; 5 | using std::placeholders::_1; 6 | using std::placeholders::_2; 7 | 8 | namespace msgipc 9 | { 10 | 11 | Client kClient; 12 | 13 | void OnClose(asio_client*, websocketpp::connection_hdl) { 14 | Sleep(kClient.timeout()); 15 | 16 | spdlog::info("retry connecting..."); 17 | kClient.connect(); 18 | } 19 | 20 | void OnMessage(asio_client*, websocketpp::connection_hdl, message_ptr msg) { 21 | if (kClient.callback()) 22 | kClient.callback()(msg->get_payload()); 23 | } 24 | 25 | Client::Client(const String& connect_str) : 26 | connected_(nullptr), 27 | callback_(nullptr), 28 | timeout_(3000), 29 | connect_str_(connect_str) 30 | { 31 | client_.clear_access_channels(websocketpp::log::alevel::all); 32 | client_.init_asio(); 33 | client_.set_message_handler(bind(&OnMessage, &client_, ::_1, ::_2)); 34 | client_.set_fail_handler(bind(&OnClose, &client_, ::_1)); 35 | client_.set_close_handler(bind(&OnClose, &client_, ::_1)); 36 | } 37 | 38 | void Client::connect() 39 | { 40 | spdlog::info("connecting..."); 41 | websocketpp::lib::error_code ec; 42 | connected_ = client_.get_connection(connect_str_.c_str(), ec); 43 | if (ec) { 44 | spdlog::error("could not create connection because: {}", ec.message()); 45 | return; 46 | } 47 | 48 | client_.connect(connected_); 49 | client_.run(); 50 | } 51 | 52 | void Client::close() 53 | { 54 | if(is_connected()) 55 | { 56 | websocketpp::close::status::value val{}; 57 | connected_->close(val, ""); 58 | spdlog::info("connected close."); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /dll/websocket_client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include "precompiled.h" 5 | 6 | namespace msgipc 7 | { 8 | 9 | typedef websocketpp::client asio_client; 10 | typedef websocketpp::config::asio_client::message_type::ptr message_ptr; 11 | 12 | typedef std::function MessageCallback; 13 | 14 | class Client 15 | { 16 | String connect_str_; 17 | asio_client client_; 18 | asio_client::connection_ptr connected_; 19 | MessageCallback callback_; 20 | uint32_t timeout_; 21 | 22 | public: 23 | Client(const String &connect_str=""); 24 | void connect(); 25 | bool is_connected() 26 | { 27 | return connected_ != nullptr && connected_->get_state() == websocketpp::session::state::open; 28 | } 29 | void send(const String& text) 30 | { 31 | client_.send(connected_, text, websocketpp::frame::opcode::text); 32 | } 33 | void close(); 34 | 35 | void setTimeout(const uint32_t &timeout) { timeout_ = timeout; } 36 | void setCallback(MessageCallback cb) { callback_ = cb; } 37 | void setConnectStr(const String &connect_str) { connect_str_ = connect_str; } 38 | 39 | uint32_t timeout() const { return timeout_; } 40 | MessageCallback callback() const { return callback_; } 41 | }; 42 | 43 | extern Client kClient; 44 | 45 | } 46 | #endif // CLIENT_H 47 | -------------------------------------------------------------------------------- /doc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bstaint/MsgIPC/0be5128a25d66bbfc5ed3b6a9799ecd1ef0dd53b/doc/screenshot.png -------------------------------------------------------------------------------- /python/form.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Form 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | GetSelfUin 26 | 27 | 28 | 29 | 30 | 31 | 32 | Action2 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /python/requirements.txt: -------------------------------------------------------------------------------- 1 | websockets==9.1 2 | -------------------------------------------------------------------------------- /python/serve.py: -------------------------------------------------------------------------------- 1 | import json 2 | from PySide2.QtCore import QObject, Signal 3 | from PySide2.QtWebSockets import QWebSocket, QWebSocketServer 4 | from PySide2.QtNetwork import QHostAddress 5 | 6 | class Serve(QObject): 7 | 8 | closed = Signal() 9 | recv = Signal(str) 10 | 11 | def __init__(self): 12 | super(Serve, self).__init__() 13 | self.client = None 14 | self.server = QWebSocketServer("Echo Server", QWebSocketServer.NonSecureMode) 15 | self.server.listen(QHostAddress.Any, 5678) 16 | self.server.newConnection.connect(self.onNewConnection) 17 | self.server.closed.connect(self.closed) 18 | 19 | def onNewConnection(self): 20 | if not self.client: 21 | self.client = self.server.nextPendingConnection() 22 | self.client.textMessageReceived.connect(self.recv) 23 | 24 | def proessTextMessage(self, message): 25 | self.recv.emit(message) 26 | 27 | def send(self, text): 28 | if self.client: 29 | self.client.sendTextMessage(text) 30 | -------------------------------------------------------------------------------- /python/serve_with_pyside.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | from PySide2.QtWidgets import QApplication, QWidget, QMessageBox 4 | from PySide2.QtCore import QFile 5 | from ui_form import Ui_Form 6 | from serve import Serve 7 | from enum import Enum, unique 8 | 9 | @unique 10 | class Message(Enum): 11 | UNKNOWN = -1 12 | ERROR = 0 13 | OK = 1 14 | SELFUIN = 2 15 | CHAT = 3 16 | TEST = 4 17 | 18 | class MainWindow(QWidget): 19 | def __init__(self): 20 | super(MainWindow, self).__init__() 21 | self.ui = Ui_Form() 22 | self.ui.setupUi(self) 23 | self.ui.pushButton.clicked.connect(self.pushButton1Clicked) 24 | self.ui.pushButton_2.clicked.connect(self.pushButton2Clicked) 25 | self.serve = Serve() 26 | self.serve.recv.connect(self.recvText) 27 | 28 | def pushButton1Clicked(self): 29 | self.serve.send(json.dumps({'errno': Message.PSELFUIN.value })) 30 | 31 | def pushButton2Clicked(self): 32 | self.serve.send(json.dumps({'errno': Message.PTEST.value })) 33 | # error message 34 | self.serve.send(json.dumps({'type': Message.PTEST.value })) 35 | 36 | def recvText(self, text): 37 | try: 38 | obj = json.loads(text) 39 | except json.decoder.JSONDecodeError: 40 | return 41 | 42 | errno = int(obj['errno']) 43 | if errno == Message.CHAT.value: 44 | self.ui.listWidget.addItem( 45 | 'group:{group} {nickname}({sender}): {text}'.format(**obj['message']) 46 | ) 47 | elif errno == Message.SELFUIN.value: 48 | QMessageBox.information(self, 'test', obj['message']) 49 | 50 | 51 | if __name__ == "__main__": 52 | app = QApplication(sys.argv) 53 | 54 | window = MainWindow() 55 | window.show() 56 | 57 | sys.exit(app.exec_()) 58 | -------------------------------------------------------------------------------- /python/serve_with_pyside_nogui.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from serve import Serve 3 | from PySide2.QtCore import QCoreApplication 4 | 5 | def recv(text): 6 | print(text) 7 | 8 | if __name__ == '__main__': 9 | app = QCoreApplication(sys.argv) 10 | s = Serve() 11 | s.recv.connect(recv) 12 | sys.exit(app.exec_()) 13 | -------------------------------------------------------------------------------- /python/serve_without_pyside.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import websockets 3 | 4 | async def recv_msg(websocket): 5 | while True: 6 | text = await websocket.recv() 7 | print(text) 8 | 9 | async def main_logic(websocket, path): 10 | await recv_msg(websocket) 11 | 12 | start_server = websockets.serve(main_logic, '127.0.0.1', 5678) 13 | asyncio.get_event_loop().run_until_complete(start_server) 14 | asyncio.get_event_loop().run_forever() 15 | -------------------------------------------------------------------------------- /python/ui_form.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file '.\MsgIPC\form.ui', 4 | # licensing of '.\MsgIPC\form.ui' applies. 5 | # 6 | # Created: Thu Jan 23 21:51:19 2020 7 | # by: pyside2-uic running on PySide2 5.13.1 8 | # 9 | # WARNING! All changes made in this file will be lost! 10 | 11 | from PySide2 import QtCore, QtGui, QtWidgets 12 | 13 | class Ui_Form(object): 14 | def setupUi(self, Form): 15 | Form.setObjectName("Form") 16 | Form.resize(400, 300) 17 | self.verticalLayout = QtWidgets.QVBoxLayout(Form) 18 | self.verticalLayout.setObjectName("verticalLayout") 19 | self.listWidget = QtWidgets.QListWidget(Form) 20 | self.listWidget.setObjectName("listWidget") 21 | self.verticalLayout.addWidget(self.listWidget) 22 | self.horizontalLayout = QtWidgets.QHBoxLayout() 23 | self.horizontalLayout.setObjectName("horizontalLayout") 24 | self.pushButton = QtWidgets.QPushButton(Form) 25 | self.pushButton.setObjectName("pushButton") 26 | self.horizontalLayout.addWidget(self.pushButton) 27 | self.pushButton_2 = QtWidgets.QPushButton(Form) 28 | self.pushButton_2.setObjectName("pushButton_2") 29 | self.horizontalLayout.addWidget(self.pushButton_2) 30 | self.verticalLayout.addLayout(self.horizontalLayout) 31 | 32 | self.retranslateUi(Form) 33 | QtCore.QMetaObject.connectSlotsByName(Form) 34 | 35 | def retranslateUi(self, Form): 36 | Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) 37 | self.pushButton.setText(QtWidgets.QApplication.translate("Form", "GetSelfUin", None, -1)) 38 | self.pushButton_2.setText(QtWidgets.QApplication.translate("Form", "Action2", None, -1)) 39 | 40 | --------------------------------------------------------------------------------