釘釘自定義機器人&傳送釘釘訊息(C#版)
阿新 • • 發佈:2018-12-16
開發文件: 釘釘 自定義機器人 一、建立、設定釘釘機器人
- 建立機器人:釘釘群 ->群設定 -> 群機器人 如下圖所示
- 設定釘釘機器人資訊
二、傳送釘釘訊息 根據釘釘開發文件,當前釘釘機器人支援的訊息型別主要有三種:文字型別、link型別、markdown型別。本文主要介紹傳送“markdown型別”訊息。 事實上,釘釘機器人傳送訊息,就是傳送一次HTTP Post請求給webhook,資料最終都是json格式的,所以在通過機器人傳送訊息未成功時,可以檢查自己的webhook是否正確,json資料是否符合開發文件要求。 廢話不多說,直接開始。
- 編寫訊息型別類Model MarkDown:MarkDown型別 At:At DingDingMessage:釘釘訊息 DingDingResponse:訊息響應
/// <summary> /// 訊息型別 /// </summary> public class MarkDown { public MarkDown() { } public string title { set; get; }//標題 public string text { set; get; }//文字訊息 } /// <summary> /// At /// </summary> public class At { public At() { atMobiles = new List<string>(); } private List<string> _atMobiles;//@的手機號 private bool _isAtAll;//是否@所有人 /// <summary> /// @的聯絡人 /// </summary> public List<string> atMobiles { set { _atMobiles = value; } get { return _atMobiles; } } /// <summary> /// 是否@所有人 /// </summary> public bool isAtAll { set { _isAtAll = value; } get { return _isAtAll; } } } /// <summary> /// 釘釘訊息 /// </summary> public class DingDingMessage { public DingDingMessage() { this.at = new At(); this.text = new Text(); this.markdown = new MarkDown(); } public string msgtype { set; get; }//訊息型別 public Model.Text text { set; get; }//text型別 public Model.MarkDown markdown { set; get; }//markdown型別 public Model.At at { set; get; }//@ } /// <summary> /// 訊息響應 /// </summary> public class DingDingResponse { private string _msg; private string _code; /// <summary> /// 錯誤資訊 /// </summary> public string ErrMsg { set { _msg = value; } get { return _msg; } } /// <summary> /// 錯誤碼 /// </summary> public string ErrCode { set { _code = value; } get { return _code; } } }
- 編寫傳送釘釘訊息的方法
/// <summary> /// 建立測試任務、修改測試任務 /// 向釘釘群傳送訊息 /// </summary> /// <param name="task"></param> /// <param name="type"></param> public static Model.DingDingResponse Send_TestTaskMessageToDingDing(Model.Task task, string type) { StringBuilder msg = new StringBuilder(); Model.DingDingResponse response = new Model.DingDingResponse(); List<string> phoneList = new List<string>(); Model.DingDingMessage message = new Model.DingDingMessage(); message.msgtype = "markdown"; if (type.Equals("新建")) { message.markdown.title = "【測試任務分配】建立人:" + Utility.UserInfo.UserName; msg.Append("### 【測試任務分配】專案負責人:" + task.Project_Leader_Name + "\n"); } else if (type.Equals("修改")) { message.markdown.title = "【測試任務分配】修改人:" + Utility.UserInfo.UserName; msg.Append("### 【測試任務分配】專案負責人:" + task.Project_Leader_Name + "\n"); } else if (type.Equals("刪除")) { message.markdown.title = "【測試任務刪除】刪除人:" + Utility.UserInfo.UserName; msg.Append("### 【測試任務刪除】專案負責人:" + task.Project_Leader_Name + "\n"); msg.Append("* 任務名:" + task.TaskName + "\n"); msg.Append("* 刪除人:" + Utility.UserInfo.UserName + "\n"); msg.Append("* 建立時間:" + task.PublishTime.ToString() + "\n"); msg.Append("* 刪除時間:" + Utility.Common.GetSysTime().ToString() + "\n"); msg.Append("* 所屬機型專案:" + task.Project_Id.ToUpper() + "\n"); msg.Append("\n"); msg.Append("@所有人"); } if (type.Equals("新建") || type.Equals("修改")) { //@所有人與@某些人不能一起使用 message.at.isAtAll = false; } else if(type.Equals("刪除")) { message.at.isAtAll = true; } if (type.Equals("新建") || type.Equals("修改")) { msg.Append("* 任務名:" + task.TaskName + "\n"); msg.Append("* 測試機型:" + task.Project_Id.ToUpper() + "(" + task.PhoneType + ")\n"); msg.Append("* 測試周期:" + task.TestCycle + "天\n"); msg.Append("* 測試時間:" + task.StartTime.ToString("yyyy/MM/dd HH:mm") + " 至 " + task.EndTime.ToString("yyyy/MM/dd HH:mm") + "\n"); msg.Append("* 其他:請檢視OverseaPMS系統->個人任務\n"); //msg.Append("* 備註:" + task.BZ + "\n"); msg.Append("------\n"); msg.Append("------\n"); DataTable dt_allChildTasks = BLL.TestTask.ChildTask.Que_AllChildTasksByTaskId(task.TaskId).Tables[0]; if (dt_allChildTasks != null && dt_allChildTasks.Rows.Count > 0) { msg.Append("#### 測試模組安排如下:\n"); string phone = ""; for (int i = 0; i < dt_allChildTasks.Rows.Count; i++) { phone = dt_allChildTasks.Rows[i]["phone"].ToString(); //去除重複手機號 if (!phoneList.Contains("@" + phone)) { phoneList.Add("@" + phone); } msg.Append(" \n > (" + (i + 1) + ") " + dt_allChildTasks.Rows[i]["module_name"] + "," + dt_allChildTasks.Rows[i]["tester_name"] + ",測試要求:" + dt_allChildTasks.Rows[i]["requirement"]); //msg.Append("\n @" + phone); msg.Append("\n"); } msg.Append("\n"); if (phoneList.Count > 20) { for (int i = 0; i < 20; i++) { msg.Append(phoneList[i] + " "); phone = phoneList[i].Trim().Substring(1); message.at.atMobiles.Add(phone); } //刪除 phoneList.RemoveRange(0, 20); } else { for (int i = 0; i < phoneList.Count; i++) { msg.Append(phoneList[i] + " "); phone = phoneList[i].Trim().Substring(1); message.at.atMobiles.Add(phone); } //刪除 phoneList.Clear(); } msg.Append("\n"); } } //message.text.content = msg.ToString(); message.markdown.text = msg.ToString(); String textMsg = Utility.JsonHelper.SerializeObject(message);//Json將物件序列化 string webhook = Get_TestTaskWebhook(); //返回響應 string result = Utility.Common.PostDingDing(textMsg, webhook); response = Utility.JsonHelper.DeserializeJsonToObject<Model.DingDingResponse>(result); if (response.ErrCode.Equals("0")) { if (phoneList.Count > 0) { //將剩餘手機號分組,併發送訊息 response = Send_SplitOtherPhoneToDingDing(phoneList, task); } } //if (!response.ErrCode.Equals("0")) //{ // MessageBox.Show("釘釘請求異常!\n錯誤碼:" + response.ErrCode + ",錯誤資訊:" + response.ErrMsg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); //} return response; } /// <summary> /// 手機號列表分組,併發送到釘釘群 /// </summary> /// <param name="phoneList"></param> /// <returns></returns> public static Model.DingDingResponse Send_SplitOtherPhoneToDingDing(List<string> phoneList, Model.Task task=null) { Model.DingDingResponse response = new Model.DingDingResponse(); List<string> temp = new List<string>(); if (phoneList.Count > 20) { int count = Convert.ToInt32(Math.Ceiling(phoneList.Count / 20.0)); for (int i = 0; i < count; i++) { temp = phoneList.GetRange(1+(20*i), 20); response = Send_OtherPhoneToDingDing(temp,task); if (!response.ErrCode.Equals("0")) { return response; } } } else { response = Send_OtherPhoneToDingDing(phoneList,task); } return response; } /// <summary> /// 傳送手機號到釘釘群 /// </summary> /// <param name="phoneList"></param> /// <returns></returns> public static Model.DingDingResponse Send_OtherPhoneToDingDing(List<string> phoneList, Model.Task task=null) { StringBuilder msg = new StringBuilder(); Model.DingDingResponse response = new Model.DingDingResponse(); Model.DingDingMessage message = new Model.DingDingMessage(); message.msgtype = "markdown"; message.markdown.title = "【測試任務分配】任務名:" + task.TaskName; string phone = ""; for (int i = 0; i < phoneList.Count; i++) { msg.Append(phoneList[i] + " "); phone = phoneList[i].Trim().Substring(1); message.at.atMobiles.Add(phone); } message.markdown.text = msg.ToString(); String textMsg = Utility.JsonHelper.SerializeObject(message);//Json將物件序列化 string webhook = Get_TestTaskWebhook(); //返回響應 string result = Utility.Common.PostDingDing(textMsg, webhook); response = Utility.JsonHelper.DeserializeJsonToObject<Model.DingDingResponse>(result); return response; } /// <summary> /// 以Post方式傳送請求 /// </summary> /// <param name="apiurl">請求的URL</param> /// <param name="jsonString">請求的json引數</param> /// <param name="headers">請求頭的key-value字典</param> public static String PostDingDing(string jsonString, string apiurl = null, Dictionary<String, String> headers = null) { if (apiurl == null) { apiurl = WEB_HOOK;//機器人的webhook } WebRequest request = WebRequest.Create(@apiurl); request.Method = "POST"; request.ContentType = "application/json"; if (headers != null) { foreach (var keyValue in headers) { if (keyValue.Key == "Content-Type") { request.ContentType = keyValue.Value; continue; } request.Headers.Add(keyValue.Key, keyValue.Value); } } if (String.IsNullOrEmpty(jsonString)) { request.ContentLength = 0; } else { byte[] bs = Encoding.UTF8.GetBytes(jsonString); request.ContentLength = bs.Length; Stream newStream = request.GetRequestStream(); newStream.Write(bs, 0, bs.Length); newStream.Close(); } WebResponse response = request.GetResponse(); Stream stream = response.GetResponseStream(); Encoding encode = Encoding.UTF8; StreamReader reader = new StreamReader(stream, encode); string resultJson = reader.ReadToEnd(); return resultJson; }
效果圖: