C#监听QQ消息自动回复-QQ自动化

整理 | 小耕家的喵大仙

出品 | CSDN(ID:lichao19897314)

Q Q | 978124155

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

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

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

(1)微信UI自动化-篇章开启(C#)

(2)微信UI自动化-微信窗体管理(C#)

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

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

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

(6)微信UI自动化-搜索指定联系人(C#)

(7)微信UI自动化-自动发送消息给指定联系人(C#)(.Net)

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

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

(10)微信UI自动化-跟随微信窗口移动(C#)

(11)微信UI自动化-微信窗口跟随主窗体移动(C#)

(12)PC端微信自动化测试-C#采集微信聊天记录

(13)PC端微信自动化UI-C#监听微信消息自动回复

(14)微信自动化测试-针对微信控件元素截图操作

(15)微信自动化测试-针对微信主窗体的行为控制

(16)微信自动化测试-C#控制微信多开

  • QQ版本以及软件功能效果

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

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

QQ监听消息自动回复

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

  • 技术实现思路和示例代码 

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

核心示例代码 

加载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<QQRealMsgEntity> historyMessageSource { get;   set; }

        /// <summary>
        /// 自动回复内容
        /// </summary>
        public string ReplyMessage { get; set; }

        /// <summary>
        /// 自动回复文件的文件路径
        /// </summary>
        public string FilePath { get; set; }

        /// <summary>
        /// 需要自动回复的用户
        /// </summary>
        public List<string> 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<QQRealMsgEntity>();
                    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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/372032.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

druid配置wall导致无法批量sql

1、现象 2、原配置 spring:autoconfigure:exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfiguredatasource:druid:stat-view-servlet:enabled: trueloginUsername: ***loginPassword: ***allow:web-stat-filter:enabled: truedynamic:druid: #…

kakfa系统架构

消息队列Kafka系统架构 Q:什么是Kafka&#xff1f; A&#xff1a;Kafka是由Apache软件基金会开发的一个开源流处理平台&#xff0c;由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息引擎、消息队列服务&#xff0c;它可以处理消费者规模的网站中的所有动作流数据。…

【GameFramework框架】三、快速启动

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录&#xff1a; https://blog.csdn.net/q7…

python常用pandas函数nlargest / nsmallest及其手动实现

目录 pandas库 Series和DataFrame nlargest和nsmallest 用法示例 代替方法 手动实现 模拟代码 pandas库 是Python中一个非常强大的数据处理库&#xff0c;提供了高效的数据分析方法和数据结构。它特别适用于处理具有关系型数据或带标签数据的情况&#xff0c;同时在时间…

动态库是怎么被加载的?

目录 1.动态库是如何被加载的&#xff1f; 2.那么虚拟地址和物理地址是如何映射的呢&#xff1f; 3.那么动态库的地址怎么来&#xff1f; 1.动态库是如何被加载的&#xff1f; 下面这个就是正常的进程是如何从磁盘中读取信息编译的&#xff1a; 而动态库就存储在共享区段&am…

Android简单支持项目符号的EditText

一、背景及样式效果 因项目需要&#xff0c;需要文本编辑时&#xff0c;支持项目符号&#xff08;无序列表&#xff09;尝试了BulletSpan&#xff0c;但不是很理想&#xff0c;并且考虑到影响老版本回显等因素&#xff0c;最终决定自定义一个BulletEditText。 先看效果&…

新春营销不间断,AI 整活更省心

新年、春节历来都是营销的大热节点&#xff0c;各种好物集、年货节、送礼清单比比皆是。这些新鲜玩法的背后是大量的品牌内容「弹药库」。 然而&#xff0c;品牌想在竞争激烈的新春季刷满存在感&#xff0c;并非易事。一方面&#xff0c;节日期间&#xff0c;消费者对于内容的审…

交叉验证之KFold和StratifiedKFold的使用(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

云计算、Docker、K8S问题

1 云计算 云计算作为一种新兴技术&#xff0c;已经在现代社会中得到了广泛应用。它以其高效、灵活和可扩展特性&#xff0c;成为了许多企业和组织在数据处理和存储方面的首选方案。 1.1 什么是云计算&#xff1f;它有哪些特点&#xff1f; 云计算是一种通过网络提供计算资源…

项目02《游戏-06-开发》Unity3D

基于 项目02《游戏-05-开发》Unity3D &#xff0c; 接下来做 背包系统的 存储框架 &#xff0c; 首先了解静态数据 与 动态数据&#xff0c;静态代表不变的数据&#xff0c;比如下图武器Icon&#xff0c; 其中&#xff0c;武器的名称&#xff0c;描述&#xff…

全网第一篇把Nacos配置中心客户端讲明白的

入口 我们依旧拿ConfigExample作为入口 public class ConfigExample {public static void main(String[] args) throws NacosException, InterruptedException {String serverAddr "localhost";String dataId "test";String group "DEFAULT_GROU…

搭建frp

1.frp 是什么&#xff1f; frp 是一款高性能的反向代理应用&#xff0c;专注于内网穿透。它支持多种协议&#xff0c;包括 TCP、UDP、HTTP、HTTPS 等&#xff0c;并且具备 P2P 通信功能。使用 frp&#xff0c;您可以安全、便捷地将内网服务暴露到公网&#xff0c;通过拥有公网…

解决nvrtc: error: invalid value for --gpu-architecture (-arch)

问题描述 在使用pytorch3d的时候&#xff0c;可以正常的import&#xff0c;但是在执行错误的使用就会报&#xff0c;nvrtc: error: invalid value for --gpu-architecture (-arch)&#xff0c;的错误&#xff0c;图片如下&#xff1a; 我的环境是&#xff1a; 显卡&#xff1…

精细管理药厂设备,制药机械设备管理平台系统助力生产提效

制药行业的复杂性要求对药品的品质和安全性进行严格控制&#xff0c;而这离不开高效管理各类机械设备。然而&#xff0c;随着制药企业规模的不断扩大和技术的迅猛进步&#xff0c;如何有效管理这些设备成为一个亟待解决的问题。在这一挑战面前&#xff0c;PreMaint制药机械设备…

Antd+React+react-resizable实现表格拖拽功能

1、先看效果 2、环境准备 "dependencies": {"antd": "^5.4.0","react-resizable": "^3.0.4",},"devDependencies": {"types/react": "^18.0.33","types/react-resizable": "^…

前端面试题——Vue的双向绑定

前言 双向绑定机制是Vue中最重要的机制之一&#xff0c;甚至可以说是Vue框架的根基&#xff0c;它将数据与视图模板相分离&#xff0c;使得数据处理和页面渲染更为高效&#xff0c;同时它也是前端面试题中的常客&#xff0c;接下来让我们来了解什么是双向绑定以及其实现原理。…

Python的包安装工具——pip命令大全

对于大多数使用Python的人来说&#xff0c;一定知道pip这个包安装工具&#xff0c;但是对pip可能还不是很了解&#xff0c;今天作者给大家介绍一下pip的命令&#xff0c;以方便灵活使用pip。 一、pip工具使用方法 pip的语法如下&#xff1a; pip [options] 式中&#xff1a…

InverseMatrix3D

InverseMatrixVT3D: An Efficient Projection Matrix-Based Approach for 3D Occupancy Prediction https://github.com/DanielMing123/InverseMatrixVT3D InverseMatrix3D过程总结如下&#xff1a; 1. 用2D backbone提取N个视角的多尺度图像特征&#xff0c;表示如下&#xf…

机器学习聚类算法

聚类算法是一种无监督学习方法&#xff0c;用于将数据集中的样本划分为多个簇&#xff0c;使得同一簇内的样本相似度较高&#xff0c;而不同簇之间的样本相似度较低。在数据分析中&#xff0c;聚类算法可以帮助我们发现数据的内在结构和规律&#xff0c;从而为进一步的数据分析…

Centos 内存和硬盘占用情况以及top作用

目录 只查看内存使用情况&#xff1a; 内存使用排序取前5个&#xff1a; 硬盘占用情况 定位占用空间最大目录 top查看cpu及内存使用信息 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&…