

经常使用钉钉的朋友应该不会陌生,利用钉钉机器人来进行消息的分发是再熟悉不过的了,那么就像大家熟知的一样,单单文本并不能满足我们的日常使用,同时图片的信息量也是我们文本无法比拟的,那么这时候就会蹦出一个老问题了,如何使用钉钉机器人发图片,首先你有自己的图床吧?
因为目前钉钉自定义机器人使用markdown发送图片时,不支持使用base64编码的方式,只支持使用网络路径的方式,如果你使用base64编码的方式,钉钉会将其原样输出,而不会转换成图片,所以你使用markdown发送图片时,需要使用网络图片,无法本地发送的本地文件。所以你搭建一个服务器做为图床,或者白嫖免费的图床,显然一个贵,一个不安全,那么如何两全其美呢?
今天给大家带来的是,钉钉发送图片”无图床“版本的解决方案,确切说是不止图片,刚好最近是客户提出了一个问题,使用目前指令的钉盘发送图片,钉钉有时候会显示出预览,有时又不会,所以造成了需要再点一次预览才行的情况,于是乎,去网络翻垃圾找到了对应的接口,尝试再尝试之后产生如下解决方案
图片发送演示

图片发送自由后,这次我们还可以实现音频、视频、文件的发送

既然展示完了,那我们来聊一聊指令的实现原理吧,这次能够实现各类文件的发送,主要是依托于钉钉的媒体文件,那么什么是媒体文件呢
答:媒体文件是钉钉提供的开放能力之一,可以在企业内部应用和第三方企业应用内的文件储存场景使用,而且媒体文件使用的空间是钉钉提供给钉钉组织的特定存储空间,不属于钉钉组织的钉盘空间,上传媒体文件,不占用钉钉组织的钉盘空间
!!需要注意的是虽然本功能媒体文件使用的空间没有大小限制,但是是有次数要求限制,每个钉钉组织每年可执行上传的次数上限为1万次
1)创建一个企业内部应用,然后给应用开通机器人的能力

2)复制应用的Client ID 和 Client Secret,以及RobotCode


3)获取应用访问凭证accessToken,上传媒体文件
这一块就是我们熟悉的发请求环节啦,详细内容见钉钉开放平台:
https://open.dingtalk.com/document/orgapp/upload-media-files
4)我们请求成功后,就可以获取到我们的媒体文件id了,使用它结合机器人发送群聊消息请求,就可以完成我们前面演示的效果啦
--注意事项:
1)使用钉钉的媒体文件,会有一部分文件类型和大小的限制,这里我们需要注意一下,具体如下:
2)使用钉钉机器人发群聊消息时,如果发送的是视频媒体,需要给一个视频封面,也就是我们需要一个图片的媒体id做为视频媒体的封面图
3)虽然会有一些大小的限制,但是足够支持我们自由发送图片,对于视频,音频或者文件超出了范围怎么办?这里推荐一下驿站老师封装的【钉钉云盘操作】,使用该指令就可以利用钉盘完成超出范围的大文件群聊消息发送啦
--使用:
我这边已经封装好了一个指令,有需要的企业用户可以找自己的技术支持要一下进行体验使用~

1)AppKey、AppSecret、RobotCode对应刚才保存的Client ID, Client Secret和RobotCode
2)群会话ID是我们机器人位于群聊的id,获取方式参考驿站老师封装的云盘文档中的群会话ID获取步骤
https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/gmubbci9u26qdf2x
不过需要注意一下,这里指令使用的群会话id是另一个,获取方法还是链接里面的,不过我们得到的会是这样的结果:

我们需要的是"openConversationId"填写到群会话id
3)文件类型根据需要选择,支持文件、图片、音频以及视频
4)上传视频文件的时候,需要一个图片做为视频的封面哦,不然会报错的
最后是我的源码分享环节,有能力的伙伴可以自行封装一下,如果这次的分享有帮到你,还请在评论区一键三连一下
,你的支持将会是我的动力,如果大家遇到什么问题,也欢迎大家在评论区互动
import json
import requests
import os
REQUEST_HEAD_DD = "https://api.dingtalk.com/v1.0"
REQUEST_OLDHEAD_DD = "https://oapi.dingtalk.com/"
IMAGE_TYPE = ["jpg", "gif", "png", "bmp"]
VOICE_TYPE = ["amr", "mp3", "wav"]
VIDEO_TYPE = ["mp4"]
FILE_TYPE = ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "zip", "pdf", "rar"]
class FileError(Exception):
def __init__(self, ErrorInfo):
super().__init__(self)
self.errorinfo = ErrorInfo
def __str__(self):
return self.errorinfo
class DD:
def __init__(self, robotKey, robotSecret, typeChoose, filePath):
self.robotKey = robotKey
self.robotSecret = robotSecret
self.typeChoose = typeChoose
self.filePath = filePath
def token(self):
try:
url = REQUEST_HEAD_DD + "/oauth2/accessToken"
headers = {"Content-Type": "application/json"}
body = {"appKey": self.robotKey, "appSecret": self.robotSecret}
token_Get = requests.post(url=url, headers=headers, json=body)
self.token_text = token_Get.json()['accessToken']
return 1
except Exception as e:
print("get token Error: " + str(e))
def media(self):
self.fileCheck()
self.token()
self.typeCheck()
url = REQUEST_OLDHEAD_DD + "media/upload"
payload = {'type': self.typeChoose}
files = {('media', (self.filename, open(self.filePath, 'rb'), self.suffix))}
params = {"access_token": self.token_text}
try:
respondResult = requests.post(url=url, data=payload, files=files, params=params)
media_id = respondResult.json()['media_id']
return media_id
except Exception as E:
print("Error Get mediaID")
def typeCheck(self):
(temp, filename) = os.path.split(self.filePath)
(name, suffix) = os.path.splitext(filename)
suffix = suffix.replace(".", "")
if self.typeChoose == "image":
if suffix in IMAGE_TYPE:
self.filename = filename
self.suffix = suffix
else:
raise FileError("Error Unsupported type \"" + suffix + "\"")
elif self.typeChoose == "voice":
if suffix in VOICE_TYPE:
self.filename = filename
self.suffix = suffix
else:
raise FileError("Error Unsupported type \"" + suffix + "\"")
elif self.typeChoose == "video":
if suffix in VIDEO_TYPE:
self.filename = filename
self.suffix = suffix
else:
raise FileError("Error Unsupported type \"" + suffix + "\"")
elif self.typeChoose == "file":
if suffix in FILE_TYPE:
self.filename = filename
self.suffix = suffix
else:
raise FileError("Error Unsupported type \"" + suffix + "\"")
def fileCheck(self):
if os.path.exists(self.filePath) is False:
raise FileError("Error Please Check FilePath")
def sendMessage(self, robotCode, chatid, mediaId, videoPicMediaId):
url = REQUEST_HEAD_DD + "/robot/groupMessages/send"
headers = {"Content-Type": "application/json", "x-acs-dingtalk-access-token": self.token_text}
body = {"robotCode": robotCode, "openConversationId": chatid}
if self.typeChoose == "image":
body["msgKey"] = "sampleMarkdown"
body["msgParam"] = "{\"text\":\"\"}"
elif self.typeChoose == "voice":
body["msgKey"] = "sampleAudio"
body["msgParam"] = json.dumps({"duration": "9999", "mediaId": mediaId})
elif self.typeChoose == "video":
body["msgKey"] = "sampleVideo"
body["msgParam"] = json.dumps({"duration": "9999",
"videoMediaId": mediaId,
"videoType": self.suffix,
"picMediaId": videoPicMediaId,
"height": "160",
"width": "90"
})
elif self.typeChoose == "file":
body["msgKey"] = "sampleFile"
body["msgParam"] = json.dumps({"mediaId": mediaId,
"fileName": self.filename,
"fileType": self.suffix})
body = json.dumps(body, indent=2, sort_keys=True)
try:
respond = requests.post(url=url, headers=headers, data=body)
except Exception as E:
print("send Error")
def send_picture(ddkey, ddSecret, Path, robotCode, chatid):
dd = DD(ddkey, ddSecret, "image", Path)
dd.sendMessage(robotCode, chatid, dd.media(), "")
def send_voice(ddkey, ddSecret, Path, robotCode, chatid):
dd = DD(ddkey, ddSecret, "voice", Path)
dd.sendMessage(robotCode, chatid, dd.media(), "")
def send_video(ddkey, ddSecret, videoPath, robotCode, chatid, picPath):
dd = DD(ddkey, ddSecret, "video", videoPath)
videoMedia = dd.media()
dd.filePath = picPath
dd.typeChoose = "image"
picMedia = dd.media()
dd.typeChoose = "video"
dd.sendMessage(robotCode, chatid, videoMedia, picMedia)
def send_file(ddkey, ddSecret, Path, robotCode, chatid):
dd = DD(ddkey, ddSecret, "file", Path)
dd.sendMessage(robotCode, chatid, dd.media(), "")
def robot_send(ddkey, ddSecret, robotCode, chatid, Path, type, videoPicPath):
if type == "图片":
send_picture(ddkey, ddSecret, Path, robotCode, chatid)
elif type == "音频":
send_voice(ddkey, ddSecret, Path, robotCode, chatid)
elif type == "视频":
if videoPicPath == "":
raise FileError("please give video pic")
send_video(ddkey, ddSecret, Path, robotCode, chatid, videoPicPath)
elif type == "文件":
send_file(ddkey, ddSecret, Path, robotCode, chatid)
//拿走使用的话,悄悄在评论区吱一声~
//author:monai 4/17