This article was submitted by netizens
Author: Listen to the wind
Original title: Automatic WeChat reply based on FlaUI automation + chatGPT
Original link: https://www.example.com
1. Look at the renderings first
-
- Get WeChat friends list **

-
- Automatic question and answer effect **

2. This article implements functions
This time we mainly introduce how to achieve automatic reply:
Place the File Transfer Assistant at the top and simulate the mouse clicking on the File Transfer Assistant;
Keep refreshing the session list, and you need to reply to new messages;
When a new message is refreshed, the mouse is simulated to click on the corresponding conversation person. At this time, it is determined whether it is Group chats or people. If it is Group chats, no reply will be given.
Get the message and forward it to chatGPT, while waiting for chatGPT to reply.
After obtaining the content of chatGPT, enter the content into the WeChat chat box and simulate the mouse clicking on the send button.
Simulate the mouse clicking on the File Transfer Assistant, waiting for other messages...
3. function code
3.1. Get chat messages and send them
void GetChatInfo()
{
if (!IsInit)
{
return;
}
if (wxWindow == null)
{
return;
}
//wxWindow.FindAllDescendants(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.Button)).AsParallel().FirstOrDefault(s =>s!=null && s.Name == "聊天")?.Click(false);
wxWindow.FindFirstDescendant(cf => cf.ByName("聊天"))?.Click(false);
Task.Run(() =>
{
AutomationElement? assFirst = null;
object obj = new object();
while (true)
{
if (ChatListCancellationToken.IsCancellationRequested)
{
break;
}
try
{
DateTime dateTime3 = DateTime.Now;
var searchTextBox = wxWindow.FindFirstDescendant(cf => cf.ByName("会话")).AsListBoxItem();
if (searchTextBox != null)
{
var list = searchTextBox.FindAllChildren();
if (assFirst == null)
{
assFirst = list.AsParallel().FirstOrDefault(t => t != null && "文件传输助手".Equals(t.Name));// 并行查询---需要将文件传输助手置顶
assFirst?.Click();
continue;
}
Parallel.ForEach(list, item =>
{
if (item != null && !string.IsNullOrEmpty(item.Name) && !"折叠置顶聊天".Equals(item.Name)
&& !"腾讯新闻".Equals(item.Name) && !"群聊".Contains(item.Name))
{
DateTime t1= DateTime.Now;
var allText = item.FindAllByXPath(".//Text");// 定位元素的局部搜索: .//Text; 全局搜索: //*/Text
DateTime t2 = DateTime.Now;
Trace.WriteLine($"allText用时:{(t2 - t1).TotalMilliseconds}ms");
// 回复消息列表还未回复的
if (allText != null && allText.Length >= 4)
{
if (int.TryParse(allText[3].Name, out var count) && count > 0)
{
lock (obj)
{
var name = allText[0].Name;
var time = allText[1].Name;
var content = allText[2].Name;
if (wxWindow.Patterns.Window.PatternOrDefault != null)
{
//将微信窗体设置为默认焦点状态
wxWindow.Patterns.Window.Pattern.SetWindowVisualState(FlaUI.Core.Definitions.WindowVisualState.Normal);
}
item.Click();
DateTime t7= DateTime.Now;
var itemFirst = wxWindow.FindAllDescendants(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.Text)).AsParallel()
.FirstOrDefault(t =>t!=null && t.Parent.ControlType == ControlType.Pane && !t.IsOffscreen && t.Name.Trim().IsSpecificNumbers());
DateTime t8= DateTime.Now;
Trace.WriteLine($"itemFirst:{(t8 - t7).TotalMilliseconds}ms");
// 判断是否为群聊
if (itemFirst == null)
{
AutoGetMesg(content);
}
assFirst?.Click();
}
}
}
}
});
DateTime dateTime4 = DateTime.Now;
Trace.WriteLine($"任务888耗时:{(dateTime4 - dateTime3).TotalMilliseconds}ms");
}
else
{
Thread.Sleep(10);
continue;
}
//ScrollEvent(-700);
}
catch (Exception ex)
{
continue;
}
finally
{
//await Task.Delay(1);
}
}
}, ChatListCancellationToken);
}
3.2. automatic reply
IChat _chat;
private void AutoGetMesg(string txt)
{
if (_chat == null)
{
_chat = new ChatAchieve();
_chat.RequestContent = GetMessage;
}
Trace.WriteLine($"发送消息:{txt}");
_chat.RequestGPT(txt);
}
private FlaUI.Core.AutomationElements.TextBox _mesText;
public FlaUI.Core.AutomationElements.TextBox MesText
{
get
{
if (_mesText == null)
_mesText = wxWindow.FindFirstDescendant(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.Text)).AsTextBox();
return _mesText;
}
}
private AutomationElement? _btnSend;
public AutomationElement? btnSend
{
get
{
if (_btnSend == null)
{
_btnSend = wxWindow.FindFirstDescendant(cf => cf.ByName("sendBtn"));
//_btnSend = wxWindow.FindAllDescendants(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.Button)).FirstOrDefault(s => s.Name == "发送(S)");
}
return _btnSend;
}
}
const int _offSize = 300;
private void GetMessage(string mes)
{
SendMes(mes);
Trace.WriteLine($"回复:{mes}");
}
private void SendMes(string mes)
{
if (wxWindow.Patterns.Window.PatternOrDefault != null)
{
//将微信窗体设置为默认焦点状态
wxWindow.Patterns.Window.Pattern.SetWindowVisualState(FlaUI.Core.Definitions.WindowVisualState.Normal);
}
int tempLen = 0;
string txt = string.Empty;
try
{
if (!string.IsNullOrWhiteSpace(mes))
{
string[] lines = mes.Split(Environment.NewLine);
foreach (string line in lines)
{
tempLen += line.Length;
txt += line + Environment.NewLine;
if (tempLen > _offSize)
{
MesText.Text = txt;
btnSend?.Click();
tempLen = 0;
txt = string.Empty;
}
}
if (!string.IsNullOrWhiteSpace(txt))
{
MesText.Text = txt;
Thread.Sleep(3);
btnSend?.Click();
}
}
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
MesText.Text = txt;
btnSend?.Click();
}
}
3.3. other code
/// <summary>
/// 启动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
InitWechat();
}
private void FrmMain_Load(object sender, EventArgs e)
{
}
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
this.Dispose();
GC.Collect();
}
private CancellationToken FriendCancellationToken { get; set; }
private CancellationTokenSource FriendTokenSource { get; set; }
private CancellationToken ChatListCancellationToken { get; set; }
private CancellationTokenSource ChatListTokenSource { get; set; }
private CancellationToken GetFriendCancellationToken { get; set; }
private CancellationTokenSource GetFriendTokenSource { get; set; }
/// <summary>
/// 微信的进程ID
/// </summary>
private int ProcessId { get; set; }
/// <summary>
/// 微信窗体
/// </summary>
private Window wxWindow { get; set; }
private bool IsInit { get; set; }
/// <summary>
/// 获取
/// </summary>
void GetWxHandle()
{
var process = Process.GetProcessesByName("Wechat").FirstOrDefault();
if (process != null)
{
ProcessId = process.Id;
}
}
/// <summary>
/// 加载微信
/// </summary>
void InitWechat()
{
IsInit = true;
GetWxHandle();
GetFriendTokenSource = new CancellationTokenSource();
GetFriendCancellationToken = GetFriendTokenSource.Token;
ChatListTokenSource = new CancellationTokenSource();
ChatListCancellationToken = ChatListTokenSource.Token;
FriendTokenSource = new CancellationTokenSource();
FriendCancellationToken = FriendTokenSource.Token;
//根据微信进程ID绑定FLAUI
try
{
var application = FlaUI.Core.Application.Attach(ProcessId);
var automation = new UIA3Automation();
//获取微信window自动化操作对象
wxWindow = application.GetMainWindow(automation);
}
catch (Exception ex)
{
if (MessageBox.Show(ex.Message, "异常", MessageBoxButtons.OK, MessageBoxIcon.Error) == DialogResult.OK)
this.Close();
}
// 加载好友
IsListenCronyList = true;
// 加载聊天信息
GetChatInfo();
}
/// <summary>
/// 获取好友列表
/// </summary>
void GetFriends()
{
if (!IsInit)
{
return;
}
if (wxWindow == null)
{
return;
}
if (wxWindow.Patterns.Window.PatternOrDefault != null)
{
//将微信窗体设置为默认焦点状态
wxWindow.Patterns.Window.Pattern.SetWindowVisualState(FlaUI.Core.Definitions.WindowVisualState.Normal);
}
wxWindow.FindAllDescendants(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.Button)).AsParallel()
.FirstOrDefault(item => item != null && item.Name == "通讯录")?.Click(false);
string lastName = string.Empty;
var list = new List<AutomationElement>();
var sync = SynchronizationContext.Current;
Task.Run(async () =>
{
while (true)
{
if (GetFriendCancellationToken.IsCancellationRequested)
break;
var all = wxWindow.FindAllDescendants(x => x.ByControlType(FlaUI.Core.Definitions.ControlType.ListItem));
var allItem = all.AsParallel().Where(s => s != null && s.Parent != null && "联系人".Equals(s.Parent?.Name)).ToList();
foreach (var item in allItem)
{
if (!string.IsNullOrWhiteSpace(item.Name) && !listBox1.Items.Contains(item.Name.ToString()))
{
sync.Post(s =>
{
listBox1.Items.Add(s);
}, item.Name.ToString());
}
}
//ScrollEvent(-700);
await Task.Delay(1);
}
}, GetFriendCancellationToken);
}
/// <summary>
/// 监听好友列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnListenCronyList_Click(object sender, EventArgs e)
{
IsListenCronyList = !IsListenCronyList;
}
private bool _isListenCronyList = false;
public bool IsListenCronyList
{
set
{
if (_isListenCronyList == value)
return;
_isListenCronyList = value;
string txt = string.Empty;
if (value)
{
txt = "关闭监听好友列表";
GetFriends();
}
else
{
txt = "开启监听好友列表";
GetFriendTokenSource.Cancel();
}
btnListenCronyList.ExecBeginInvoke(() =>
{
btnListenCronyList.Text = txt;
});
}
get => this._isListenCronyList;
}
3.4. extension method
internal static class SystemEx
{
/// <summary>
/// 跨线程操作控件
/// </summary>
/// <param name="con"></param>
/// <param name="action"></param>
public static void ExecBeginInvoke(this Control con, Action action)
{
if (action == null) return;
if (con.InvokeRequired)
{
con.BeginInvoke(new Action(action));
}
else
{
action();
}
}
public static void ExecInvoke(this Control con, Action action)
{
if (action == null) return;
if (con.InvokeRequired)
{
con.Invoke(new Action(action));
}
else
{
action();
}
}
const string PARRERN = @"^\(\d+\)$";
public static bool IsSpecificNumbers(this string txt)
{
return Regex.IsMatch(txt, PARRERN);
}
}
-
- Note: ChatAchieve is an implementation of IChat, an implementation of chatGPT **
public interface IChat
{
Action<string> RequestContent { get; set; }
void RequestGPT(string content);
}
The author is lazy and unwilling to put the code in the warehouse. The source code is directly lost to the webmaster. You need to directly click to download it: https://www.example.com
Add QQ group for technical exchanges: 771992300
Or scan the webmaster's WeChat (codewf, note "add group ") to join the WeChat technical exchange group:
