本文由網友投稿
作者:且聽風吟
原文標題:基於 FlaUI 自動化+chatGPT 實現微信自動回覆
原文連結:https://blog.csdn.net/ftfmatlab/article/details/132589169
1. 先看效果圖
取得微信好友列表

自動問答效果

2. 本文實現功能
本次主要介紹如何實現自動回覆:
將檔案傳輸助手置頂,模擬滑鼠點擊檔案傳輸助手;
一直重新整理會話列表,有新的訊息就需要回覆內容;
當重新整理到新的訊息時,模擬滑鼠點擊到對應的會話人,此時判斷是群聊還是人,如果是群聊則不回覆。
取得訊息後轉發給 chatGPT,同時等待 chatGPT 回覆內容。
取得 chatGPT 的內容後將內容輸入到微信聊天框,並模擬滑鼠點擊傳送按鈕。
模擬滑鼠點擊檔案傳輸助手,等待其他訊息。。。。
3. 功能程式碼
3.1. 取得聊天訊息並傳送
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. 自動回覆
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. 其他程式碼
/// <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();
//取得微信視窗自動化操作物件
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. 擴充方法
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);
}
}
註:ChatAchieve 是 IChat 的實作,是對 chatGPT 的實作
public interface IChat
{
Action<string> RequestContent { get; set; }
void RequestGPT(string content);
}
作者懶,不願意將程式碼放倉庫,原始碼直接丟站長了,大家需要直接點擊下載:https://img1.dotnet9.com/2023/08/WeChat.Automation.zip
技術交流新增 QQ 群:771992300
或掃站長微信(codewf,備註「加群」)加入微信技術交流群:
