一、任务需求
此次的任务需求相对简单,思路也很清晰。就是从生产的库中读取数据,定时推送到钉钉群中用以消息通知,整个过程可以了解到如何自定义钉钉机器人、如何在Linux环境下部署python脚本并设置定时任务。
二、自定义钉钉机器人
1. 首先可以将相关人员建立一个钉钉群,人数要大于等于三人(不然还群聊个锤子...)
2. 点击右上角的群设置;
3. 点击智能群助手;
4. 点击添加机器人;
5. 点击添加机器人
6. 可以看到,钉钉可以添加的机器人的种类是很多的,包括代码托管的GitHub,gitlab,bug的追踪管理工具JIRA等等,这里我们选择自定义机器人。
7. 选择添加
8. 此时可以设置机器人的相关属性,包括机器人名字,安全设置等。
需要注意的是,这里的安全属性是必须选择的。
安全设置目前有3种方式:
(1)方式一,自定义关键词
最多可以设置10个关键词,消息中至少包含其中1个关键词才可以发送成功。
例如:添加了一个自定义关键词:监控报警
在你写的代码中,让这个机器人所发送的消息必须包含“监控报警”这个词,才能发送成功。否则会出现 keyword not in content。错误。
(2)方式二,加签
第一步,把timestamp+"\n"+密钥当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名(需要使用UTF-8字符集)。
参数 | 说明 |
timestamp | 当前时间戳,单位是毫秒,与请求调用时间误差不能超过1小时 |
secret | 密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 |
签名计算代码示例(Java)
Long timestamp = System.currentTimeMillis();
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
return URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");
签名计算代码示例(Python)
#python 2.7
import time
import hmac
import hashlib
import base64
import urllibtimestamp = long(round(time.time() * 1000))
secret = 'this is secret'
secret_enc = bytes(secret).encode('utf-8')
string_to_sign = '{}\n{}'.format(timestamp, secret)
string_to_sign_enc = bytes(string_to_sign).encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.quote_plus(base64.b64encode(hmac_code))
print(timestamp)
print(sign)
第二步,把 timestamp和第一步得到的签名值拼接到URL中。
参数 | 说明 |
timestamp | 第一步使用到的时间戳 |
sign | 第一步得到的签名值 |
https://oapi.dingtalk.com/robot/send?access_token=XXXXXX×tamp=XXX&sign=XXX
(3)方式三,IP地址(段)
设定后,只有来自IP地址范围内的请求才会被正常处理。支持两种设置方式:IP、IP段,暂不支持IPv6地址白名单,格式如下:
注意:安全设置的上述三种方式,需要至少设置其中一种,以进行安全保护。校验不通过的消息将会发送失败,错误如下:
// 消息内容中不包含任何关键词
{"errcode":310000,"errmsg":"keywords not in content"
}// timestamp 无效
{"errcode":310000,"errmsg":"invalid timestamp"
}// 签名不匹配
{"errcode":310000,"errmsg":"sign not match"
}// IP地址不在白名单
{"errcode":310000,"errmsg":"ip X.X.X.X not in whitelist"
}
详情参考说明文档:
https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq
9. 完成安全设置后,复制出机器人的Webhook地址,可用于向这个群发送消息,格式如下:
https://oapi.dingtalk.com/robot/send?access_token=XXXXXX
三、推送代码
单独推送的代码比较简单,如下。完整的GitHub代码见:GitHub代码
"""!/usr/bin/env python3.6-*- coding: utf-8 -*---------------------------------Description : 测试钉钉群机器人推送消息安全设置是必填项,例如自定义关键字:钉钉钉钉发送通知时,必须包含关键字 “钉钉”,不然会报 keyword not in content。--------------------------------@Time : 2020/2/9 18:34@File : dingding_push.py@Software: PyCharm--------------------------------@Author : lixj@contact : lixj_zj@163.com
"""import requests
import jsondef ding_push_message():# 构建请求头部header = {"Content-Type": "application/json","Charset": "UTF-8"}# 构建请求数据message = {"msgtype": "text","text": {"content": msg},"at": {"isAtAll": True}}# 对请求的数据进行json封装message_json = json.dumps(message)# 发送请求info = requests.post(url=web_url, data=message_json, headers=header)# 打印返回的结果print(info.text)if __name__ == "__main__":# 请求的URL,WebHook地址web_url = "https://oapi.dingtalk.com/robot/send?access_token=xxxx"# 构建请求数据msg = "钉钉,测试消息。。。"ding_push_message()
四、部署测试
脚本完成后在Linux环境下部署测试,此时将脚本存放于 /app/mom/demo路径下:
在Linux中设置定时任务,使用 #crontab -e 指令:
crontab -e
设置每分钟查询一次:
*/1 * * * * python /app/mom/demo/demo.py
保存退出等待一分钟后,在同目录下生成run_log.log 日志文件:
此时钉钉群接受到消息:
除了简单的发送消息通知外,钉钉机器人还可以发送更丰富的通知形式,如链接、文本、markdown类型等等,详情参考钉钉开发平台开发指南(https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq )。
问题集锦
1. 生成的日志文件需要指定具体生成的位置,否则会默认生成在 /root 路径下,在做测试时,在 /root 路径下生成了 test.txt 文件,并且是通过定时任务定时执行的结果。
具体原因是因为直接执行和通过任务执行,程序的执行环境不同。直接执行脚本,脚本执行环境是脚本所在的目录,而定时的脚本执行环境默认是root目录。
参考连接
https://www.cnblogs.com/imustun/p/9604722.html
http://www.coin163.com/it/x5906505031476308272
https://blog.csdn.net/wc1695040842/article/details/86419557