(1)监听QQ消息自动回复-QQ自动化(.Net)

整理 | 小耕家的喵大仙

出品 | CSDN(ID:lichao19897314)

Q Q | 978124155

关于项目背景和微信自动化学习介绍

因为前面写了很多关于微信自动化的文章,网上有一位网友说他是做CAD培训行业的,有时候除了微信对接客户还需要通过QQ来做日常的回复工作,因为很多回复是重复性,他想实现监听QQ消息并自动回复文字内容和文件的功能。该篇博客记录了实现QQ自动回复的整体实现逻辑和技术细节。

如果有兴趣的朋友可以看下我微信自动化的文章!因为底层实现和微信自动化同根同源,感兴趣的点个赞关注支持下原创。

(1)C#开启探索微信自动化之路-微信UI自动化

(2)C#创建微信窗体自动化实例-微信UI自动化

(3)C#针对系统热键管理-微信UI自动化

(4)C#采集微信通讯录和联系人-微信UI自动化

(5)C#实现针对微信窗体鼠标静默点击-微信UI自动化

(6)C#搜索微信通讯录联系人-微信UI自动化

(7)C#实现微信消息群发-微信UI自动化

(8)C#监控微信进程运行状态-微信UI自动化

(9)C#监控微信网络连接状态-微信UI自动化

(11)C#实现微信窗体尺寸跟随调整-微信UI自动化

(12)C#采集微信聊天记录及历史消息-微信UI自动化

(13)C#实现自动回复微信消息-微信UI自动化

(14)C#针对微信界面元素截图操作-微信UI自动化

(15)C#实现对微信窗体的行为管控-微信UI自动化

(16)C#实现微信多开-微信UI自动化

(17)C#实现微信聊天文件接收及下载-微信UI自动化

(18)C#采集微信群成员信息-微信UI自动化(.Net)

(19)C#添加微信好友(可批量添加)--微信UI自动化(.Net)

QQ版本以及软件功能效果

采用的QQ版本为当前最新版本QQ👇

QQ监听消息并自动回复的效果视频呈现

实时监听最新消息并根据消息内容给指定联系人做回复(包括回复文本和文件)

(1)实时监控QQ主面板的消息,判断是否有新消息推送过来。

(2)如果有新消息推送并且消息发送人在您需要自动回复好友列表中,则会根据您自己定义的业务规则进行自动回复。

技术实现思路和示例代码

找到QQ主窗体句柄和QQ进程ID,通过QQ进程ID构建UIA3Automation的自动化测试实例。构建针对QQ自动化测试实例成功后,我们创建一个后台监听任务,监听QQ主窗体的消息面板。监听任务判断消息面板中的UI对象中的内容是否有修改,如果有修改则判断为新消息。因为本次程序是针对特定群和特定联系人的自动回复,所以需要将特定群或者联系人的聊天窗口平铺打开。请像如下打开需要监听的联系人聊天窗口,当然也可以实现自动打开。通过监听任务获取到的新消息内容和消息发送人,通过UI自动化实例对象找到与对应联系人的聊天窗口。找到对应的聊天窗口的编辑框和发送按钮的UI对象实例。通过监听到的消息内容产生我们自己需要回复的智能化业务内容,并通过剪贴版本的方式复制到聊天窗口的编辑框中,执行发送按钮的点击事件,完成发送,并将新消息内容设为以处理。

核心示例代码

加载QQ主窗体并构建自动化测试实例

public bool Load()

{

int weChatID = 0;

IntPtr hwnd = FindWindow(null, "QQ");

if (hwnd != IntPtr.Zero)

{

GetWindowThreadProcessId(hwnd, out weChatID);

}

else

{

return false;

}

application = FlaUI.Core.Application.Attach(weChatID);

automation = new UIA3Automation();

Window = application.GetMainWindow(automation);

var windowSource = application.GetAllTopLevelWindows(automation);

if (Window == null)

return false;

startPanel = string.Format("/Pane[{0}]", Window.FindAllChildren().Length-1);

return true;

}

监控实例对象

using FlaUI.WinForm.UIAuto.Business.WX.Task.Base;

using FlaUI.WinForm.UIAuto.Model;

using OnlineRetailers.Extension.Page.UIAuto;

using OnlineRetailers.Extension.Page.UIAuto.Log;

using OnlineRetailers.Extension.Page.UIAuto.Model;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace FlaUI.WinForm.UIAuto.Business.WX.Task

{

public class UI_Real_Reply_Task : UI_QQ_Element_Base_Task

{

private List historyMessageSource { get; set; }

///

/// 自动回复内容

///

public string ReplyMessage { get; set; }

///

/// 自动回复文件的文件路径

///

public string FilePath { get; set; }

///

/// 需要自动回复的用户

///

public List ReplyUser { get; set; }

public override void Stop()

{

base.Stop();

}

public override void Start()

{

if (State == TaskState.Stop)

{

State = TaskState.Runing;

}

else

{

return;

}

Thread th = new Thread(new ThreadStart(() =>

{

while (State == TaskState.Runing)

{

var currentChatList = UI_QQ_Window.Current.Find("主窗体消息面板UI");

if (currentChatList == null || currentChatList.ControlType != FlaUI.Core.Definitions.ControlType.Pane)

{

Thread.Sleep(1000);

continue;

}

var source = currentChatList.FindAllChildren();

var tempMessageSource = new List();

source.ToList().ForEach(item =>

{

if (item.ControlType == FlaUI.Core.Definitions.ControlType.ListItem)

{

var buttonName = item .Name;

var lastMessage = item.Patterns.Value.PatternOrDefault?.Value;

var messageitem = new QQRealMsgEntity { UserName = buttonName, CurrentMessage = lastMessage };

tempMessageSource.Add(messageitem);

if (historyMessageSource != null)

{

var cnt = historyMessageSource.Count(s => s.UserName == messageitem.UserName && messageitem.CurrentMessage == s.CurrentMessage);

if (cnt == 0)

{

//有新消息

SetMessage(messageitem.UserName + "发送给新消息你:" + messageitem.CurrentMessage);

if (ReplyUser.Count(ss => ss.Contains(messageitem.UserName)) > 0 )

{

if (!string.IsNullOrEmpty(FilePath))

{

if (

!messageitem.CurrentMessage.Contains("对方已成功接收了你发送的离线文件")

&& !messageitem.CurrentMessage.Contains("[图片文件]")

&& !messageitem.CurrentMessage.Contains("已成功保存至文件助手"))//正对自己发送的图片文件不采取回复,有可能发送文件

{

if ( SendQQFile(messageitem.UserName, FilePath))

{

SetMessage("自动回复文本消息给" + messageitem.UserName + ":" + ReplyMessage);

//var fileName = System.IO.Path.GetFileName(FilePath);

}

}

}

if (!string.IsNullOrEmpty(ReplyMessage))

{

if ( SendQQText(messageitem.UserName, ReplyMessage))

{

SetMessage("自动回复文件消息给" + messageitem.UserName + ":" + ReplyMessage);

messageitem.CurrentMessage = ReplyMessage;

}

}

}

}

}

}

});

historyMessageSource = tempMessageSource;

Thread.Sleep(500);

}

}));

th.Start();

base.Start();

}

public bool SendQQText(string name, string message)

{

return SendQQMessage(name, new QQMessageEntity { Info = message, Type = QQMessageType.Text });

}

public bool SendQQFile(string name, string filePath) {

return SendQQMessage(name, new QQMessageEntity { Info = filePath, Type = QQMessageType.File });

}

public bool SendQQMessage(string name, QQMessageEntity message) {

//查找窗体

var currentChatWindow = UI_QQ_Window.Current.GetCurrentChatWindow(name);

if (currentChatWindow != null)

{

var SendInput = currentChatWindow.FindFirstByXPath("聊天窗体编辑框");// GetSendInput();

var SendButton = currentChatWindow.FindFirstByXPath("聊天窗体发送按钮");// GetSendInput();

if (SendInput == null)

{

SystemLog.Error("【" + name + "】窗体下未找到输入框,发送信息失败");

}

if (SendButton == null)

{

SystemLog.Error("【" + name + "】窗体下未找到发送按钮,发送信息失败");

}

currentChatWindow.Focus();

SetText(message, SendInput, false);

UI_QQ_Window.Current.ClickElement(SendButton, currentChatWindow);

SystemLog.Info("向【" + name + "】窗体发送信息" + message.Info + "成功");

return true;

}

else

{

SystemLog.Error("【" + name + "】窗体未找到,发送信息失败");

}

return false;

}

}

}

以上是核心组件及代码思路,因为代码关联类比较多,无法在本篇全部博客呈现!如果需要源码请加本人QQ 978124155