# aardio 范例: 微信 iLink 机器人



```aardio
import win.ui;
/*DSG{{*/
var winform = win.form(text="微信 iLink 机器人";right=800;bottom=620)
winform.add(
logEdit={cls="edit";left=16;top=46;right=780;bottom=490;edge=1;multiline=1;readonly=1;vscroll=1;z=2};
plusQrCode={cls="plus";left=17;top=50;right=778;bottom=486;bgcolor=0xFFFFFF;repeat="scale";z=5};
replyEdit={cls="edit";text='\uD83E\uDD16 已收到: ';left=16;top=505;right=620;bottom=535;edge=1;z=3};
sendBtn={cls="button";text="更新回复内容";left=630;top=503;right=780;bottom=535;z=4};
statusText={cls="static";text="准备连接...";left=16;top=12;right=780;bottom=36;font=LOGFONT(h=-14);z=1}
)
/*}}*/

winform.updateStatus = function(statusText){
	winform.logEdit.print(statusText);	
	winform.statusText.text = statusText
}

/*
在工作线程里可以用 web.rest.iLinkClient.login 登录比较方便。
创建微信扫码登录对话框: https://www.aardio.com/zh-cn/docs/examples/Web/REST/iLink/login.html
*/
import qrencode.bitmap;
winform.showQr = function(qrcodeUrl){
	var qrBmp = qrencode.bitmap(qrcodeUrl)
	winform.plusQrCode.setBackground(qrBmp.copyBitmap(winform.plusQrCode.width));
	winform.plusQrCode.show();
}

winform.updateStatus ("正在初始化微信 iLink 客户端...");

// 启动消息监听线程
thread.invoke(
	function(winform){
		import web.rest.iLinkClient;
		var bot = web.rest.iLinkClient(
			// 可选指定 Bot token 持久化路径
			tokenPath = io.appData("aardio\std\web\rest\ilink_token.bin")
		);
		 
		var login = function(){
			winform.updateStatus("正在获取登录二维码...");
				
			var qrRes, err = bot.getQrCode();
			
			if(!qrRes[["qrcode_img_content"]]){
				winform.updateStatus("❌ 获取二维码失败: " + (err || "未知错误"));
				return;
			}
			
			winform.updateStatus("⏳ 等待微信扫码连接 ...");
			
			winform.showQr(qrRes.qrcode_url);
			var res, err = bot.waitQrCodeStatus(null, 120, 2000);
			winform.plusQrCode.show(false);
			
			if(!res){
				winform.updateStatus("❌ 登录失败: " + (err || "超时"));
				return;
			}
			
			if(res.bot_token){
				return true; 
			}			
		}
		
		if(!bot.getAuthToken()){
			if(!login()) return;
		}
		
		winform.updateStatus("✅ 机器人已上线，正在监听微信消息 ...");
		winform.logEdit.print("💡 先声明，我不是 OpenClaw ...");
		winform.logEdit.print("💡 用微信给我人发一条消息，我将自动回复。");
	
		// 消息监听循环
		while(true){
			var updateRes, err, errCode = bot.getUpdates();
			
			if(updateRes && updateRes.msgs){
				for i, fromMsg in updateRes.msgs {
					var textContent = fromMsg[["item_list"]][[1]][["text_item"]][["text"]];
					
					if(textContent){
						winform.updateStatus("📩 [" + fromMsg.from_user_id + "]: " + textContent);
						
						// 从界面读取最新的回复内容
						var replyPrefix = winform.replyEdit.text || "🤖 已收到: ";
						
						//回复内容支持 Markdown 语法，同一个 fromMsg 可以多次回复
						var ret, sendErr, sendCode = bot.sendMessage(fromMsg, replyPrefix ++ textContent);
					
						if(ret){
							winform.logEdit.print("✅ 回复成功 → " + textContent);
						}
						else {
							winform.logEdit.print("❌ 回复失败: " + (sendErr || "") + " (错误码: " + sendCode + ")");
						}
					}
				}
			}
			elseif(!updateRes){
				// errCode < 0 是腾讯业务错误，> 0 是 HTTP 客户端错误
				if(errCode && errCode < 0){
					winform.logEdit.print("⚠️ 业务错误: " + (err || "") + " (" + errCode + ")，3秒后重试...");
				
					if(errCode == -14){
						if(!login()) return;
					}
				}
				elseif(errCode){
					winform.logEdit.print("⚠️ 网络错误: " + (err || "") + " (" + errCode + ")，3秒后重试...");
				}
				
				//没必要等太久，微信轮询默认会阻塞等待
				thread.delay(1000);
			}
		}
	}, winform
);

// 更新自定义回复内容
winform.sendBtn.oncommand = function(){
	var text = string.trim(winform.replyEdit.text);
	if(#text){
		winform.logEdit.print("✅ 回复前缀已更新为: " + text + "（收到消息时将以此前缀自动回复）");
	}
	else {
		winform.logEdit.print("⚠️ 回复内容不能为空");
	}
};

winform.show();
win.loopMessage();

```

