C#实现钉钉自定义机器人消息推送

本文属于个人原创作品、个人总结,谢绝转载、抄袭。如果您有疑问或者希望沟通交流,可以联系QQ:865562060。

一、钉钉自定义机器人

钉钉自定义机器人官方文档地址

钉钉自定义机器人是在钉钉群中部署的机器人之一,可以通过自定义聊天内容实时通知群内用户。在开发工作中可以起到服务器安全提醒、部署提醒、操作提醒等作用。

获取自定义机器人webhook:

  • 在机器人管理页面选择“自定义”机器人,输入机器人名字并选择要发送消息的群。如果需要的话,可以为机器人设置一个头像。点击“完成添加”。
  • 点击“复制”按钮,即可获得这个机器人对应的Webhook地址,其格式如下

1

https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxx

使用自定义机器人:

  • 获取到Webhook地址后,用户可以使用任何方式向这个地址发起HTTP POST 请求,即可实现给该群组发送消息。注意,发起POST请求时,必须将字符集编码设置成UTF-8。

  • 当前自定义机器人支持文本(text)、连接(link)、markdown(markdown)三种消息类型,大家可以根据自己的使用场景选择合适的消息类型,达到最好的展示样式。具体的消息类型参考下一节内容。

  • 自定义机器人发送消息时,可以通过手机号码指定“被@人列表”。在“被@人列表”里面的人员,在收到该消息时,会有@消息提醒(免打扰会话仍然通知提醒,首屏出现“有人@你”)

二、C#实现钉钉自定义机器人的开发

以下代码源码地址为:https://github.com/Menyoupingxiaoguo/DDRobot。自定义类都在项目中,请自行下载。

如果我的代码对您有帮助,请给博主的github项目一个star,谢谢!

1、需要额外引入的dll

using Newtonsoft.Json;
using System.Configuration;

2、定义方法类,主要包含各种消息体的发送

    public class OapiRobot
    {
        public static string dd_host = ConfigurationManager.AppSettings["DDHost"];
        public static string RobotSendUrl = ConfigurationManager.AppSettings["RobotSendUrl"];

        /// <summary>
        /// 发送文本消息
        /// </summary>
        /// <param name="content">文本内容</param>
        /// <param name="atMobiles">@人员电话</param>
        /// <param name="isAtAll">是否@群所有成员</param>
        public static void OapiRobotText(string content, List<string> atMobiles, bool isAtAll)
        {
            TextModel tModel = new TextModel();
            tModel.at = new atText();
            tModel.text = new text();
            tModel.at.atMobiles = new List<string>();

            tModel.text.content = content;
            tModel.at.atMobiles.AddRange(atMobiles);
            tModel.at.isAtAll = isAtAll;
            tModel.msgtype = "text";

            string data = JsonConvert.SerializeObject(tModel);
            string json = Request(RobotSendUrl, data, "POST");
        }
        /// <summary>
        /// 发送Link消息
        /// </summary>
        /// <param name="title">消息标题</param>
        /// <param name="text">消息内容。如果太长只会部分展示</param>
        /// <param name="messageUrl">点击消息跳转的URL</param>
        /// <param name="picUrl">图片URL</param>
        public static void OapiRobotLink(string title, string text, string messageUrl, string picUrl)
        {
            LinkModel lModel = new LinkModel();
            lModel.link = new link();
            lModel.msgtype = "link";
            lModel.link.title = title;
            lModel.link.text = text;
            lModel.link.messageUrl = messageUrl;
            lModel.link.picUrl = picUrl;

            string data = JsonConvert.SerializeObject(lModel);
            string json = Request(RobotSendUrl, data, "POST");
        }
        /// <summary>
        /// 发送markdown类消息
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="text">消息主体</param>
        /// <param name="atMobiles">@人员电话</param>
        /// <param name="isAtAll">是否@群所有成员</param>
        public static void OapiRobotMarkDown(string title, string text, List<string> atMobiles, bool isAtAll)
        {
            MarkDownModel mdModel = new MarkDownModel();
            mdModel.at = new atMarkdown();
            mdModel.markdown = new markdown();
            mdModel.at.atMobiles = new List<string>();

            mdModel.markdown.title = title;
            mdModel.markdown.text = text;
            mdModel.at.atMobiles.AddRange(atMobiles);
            mdModel.at.isAtAll = isAtAll;
            mdModel.msgtype = "markdown";

            string data = JsonConvert.SerializeObject(mdModel);
            string json = Request(RobotSendUrl, data, "POST");
        }

        /// <summary>
        /// 发送整体跳转ActionCard类型
        /// </summary>
        /// <param name="title">首屏会话透出的展示内容</param>
        /// <param name="text">markdown格式的消息</param>
        /// <param name="singleTitle">单个按钮的方案。(设置此项和singleURL后btns无效。)</param>
        /// <param name="singleURL">点击singleTitle按钮触发的URL</param>
        /// <param name="btnOrientation">0-按钮竖直排列,1-按钮横向排列</param>
        /// <param name="hideAvatar">0-正常发消息者头像,1-隐藏发消息者头像</param>
        public static void OapiRobotActionCardOverall(string title, string text, string singleTitle, string singleURL, string btnOrientation, string hideAvatar)
        {
            ActionCardOverallModel acModel = new ActionCardOverallModel();
            acModel.actionCard = new actionCard();

            acModel.msgtype = "actionCard";
            acModel.actionCard.title = title;
            acModel.actionCard.text = text;
            acModel.actionCard.singleTitle = singleTitle;
            acModel.actionCard.singleURL = singleURL;
            if (!string.IsNullOrEmpty(btnOrientation))
                acModel.actionCard.btnOrientation = btnOrientation;
            else
                acModel.actionCard.btnOrientation = "0";
            if (!string.IsNullOrEmpty(hideAvatar))
                acModel.actionCard.hideAvatar = hideAvatar;
            else
                acModel.actionCard.hideAvatar = "0";

            string data = JsonConvert.SerializeObject(acModel);
            string json = Request(RobotSendUrl, data, "POST");
        }

        /// <summary>
        /// 发送独立跳转ActionCard类型
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        /// <param name="btns"></param>
        /// <param name="btnOrientation"></param>
        /// <param name="hideAvatar"></param>
        public static void OapiRobotActionCardSingle(string title, string text, string btns, string btnOrientation, string hideAvatar)
        {
            ActionCardSingleModel acModel = new ActionCardSingleModel();
            acModel.actionCard = new actionCardSingle();
            acModel.actionCard.btns = JsonConvert.DeserializeObject<List<btns>>(btns);
            acModel.msgtype = "actionCard";
            acModel.actionCard.title = title;
            acModel.actionCard.text = text;
            if (!string.IsNullOrEmpty(btnOrientation))
                acModel.actionCard.btnOrientation = btnOrientation;
            else
                acModel.actionCard.btnOrientation = "0";
            if (!string.IsNullOrEmpty(hideAvatar))
                acModel.actionCard.hideAvatar = hideAvatar;
            else
                acModel.actionCard.hideAvatar = "0";
            string data = JsonConvert.SerializeObject(acModel);
            string json = Request(RobotSendUrl, data, "POST");
        }
        /// <summary>
        /// 发送FeedCard类型
        /// </summary>
        public static void OapiRobotFeedCard()
        {
            FeedCardModel fcModel = new FeedCardModel();
            fcModel.msgtype = "feedCard";
            fcModel.feedCard = new feedCard();
            fcModel.feedCard.links = new List<links>();

            links model1 = new links();
            model1.title = "时代的火车向前开";
            model1.messageURL = "https://mp.weixin.qq.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI";
            model1.picURL = "https://www.dingtalk.com/";
            fcModel.feedCard.links.Add(model1);

            links model2 = new links();
            model2.title = "时代的火车向前开2";
            model2.messageURL = "https://mp.weixin.qq.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI";
            model2.picURL = "https://www.dingtalk.com/";
            fcModel.feedCard.links.Add(model2);

            string data = JsonConvert.SerializeObject(fcModel);
            string json = Request(RobotSendUrl, data, "POST");
        }
    }

3、发送消息测试

        static void Main(string[] args)
        {
            #region 1、发送Text消息
            OapiRobot.OapiRobotText("啦啦啦测试", new List<string> { "180********" }, false);
            #endregion

            #region 2、发送Link消息
            OapiRobot.OapiRobotLink("自定义机器人协议", "群机器人是钉钉群的高级扩展功能。群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步。例如:通过聚合GitHub,GitLab等源码管理服务,实现源码更新同步;通过聚合Trello,JIRA等项目协调服务,实现项目信息同步。不仅如此,群机器人支持Webhook协议的自定义接入,支持更多可能性,例如:你可将运维报警提醒通过自定义机器人聚合到钉钉群。",
                                    "https://open-doc.dingtalk.com/docs/doc.htm?spm=a219a.7629140.0.0.Rqyvqo&treeId=257&articleId=105735&docType=1","");
            #endregion

            #region 3、发送MarkDown消息
            //MarkDown语法学习可参照以下地址:https://www.jianshu.com/p/191d1e21f7ed 
            //图片地址必须写钉钉可以访问的外链地址
            OapiRobot.OapiRobotMarkDown("杭州天气", "#### 杭州天气  \n > 9度,@1825718XXXX 西北风1级,空气良89,相对温度73%\n\n > ![screenshot](http://i01.lw.aliimg.com/media/lALPBbCc1ZhJGIvNAkzNBLA_1200_588.png)\n  > ###### 10点20分发布 [天气](http://www.thinkpage.cn/)", new List<string> { "180********" }, false);
            #endregion;

            #region 4、发送整体跳转ActionCard类型
            OapiRobot.OapiRobotActionCardOverall("乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
                                                "![screenshot](@lADOpwk3K80C0M0FoA) \n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
                                                "阅读全文",
                                                "https://www.dingtalk.com/",
                                                "0",
                                                "0");
            #endregion

            #region 5、独立跳转ActionCard类型
            OapiRobot.OapiRobotActionCardSingle("乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
                                                "![screenshot](@lADOpwk3K80C0M0FoA) \n\n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
                                                "[{\"title\": \"内容不错\", \"actionURL\": \"https://www.dingtalk.com/\"}, {\"title\": \"不感兴趣\", \"actionURL\": \"https://www.dingtalk.com/\"}]",
                                                "0",
                                                "0");
            #endregion

            #region 6、FeedCard类型
            OapiRobot.OapiRobotFeedCard();
            #endregion
        }

4、实现效果

文本类型:

ææ¬æ¶æ¯

link类型:

linkæ¶æ¯

markdown类型:

markdownæ¶æ¯

 整体跳转ActionCard类型

image

独立跳转ActionCard类型:

image

 FeedCard类型:

image


版权声明:本文为qq_23009105原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。