工作中会经常遇到监控告警相关问题,监控和告警的目的是要在事中及时发现问题并定位系统问题,那么当系统或平台出现问题了,如何及时暴露这些问题给对应的项目开发人员呢?
本文记录了在Python项目中利用飞书的自定义机器人webhook向飞书群推送文本及图片消息~
飞书群-设置-群机器人-添加机器人-自定义机器人;

复制webhook地址,webhook地址就是用来发送消息的接口;

参考:飞书官方开发文档
注:如想要@具体成员,则需要获取对方的user_id,可参考:获取user_id
class FeishuTalk:
# 机器人webhook
chatGPT_url = 'https://open.feishu.cn/open-apis/bot/v2/hook/XXX'
# 发送文本消息
def sendTextmessage(self, content):
url = self.chatGPT_url
headers = {
"Content-Type": "application/json; charset=utf-8",
}
payload_message = {
"msg_type": "text",
"content": {
# @ 单个用户 <at user_id="ou_xxx">名字</at>
"text": content + "<at user_id=\"bf888888\">test</at>"
# @ 所有人 <at user_id="all">所有人</at>
# "text": content + "<at user_id=\"all\">test</at>"
}
}
response = requests.post(url=url, data=json.dumps(payload_message), headers=headers)
return response.json
# 执行发送文本消息
content = "生活不止眼前的苟且,还有诗和远方!"
FeishuTalk().sendTextmessage(content)

富文本可以在一条消息中同时支持文字、At、图片、超链接等元素,可参考:富文本消息
对于需要换行展示的消息,可通过发送 富文本消息 进行实现,比如发送一个榜单消息
# 发送富文本消息
def sendFuTextmessage(self, content):
url = self.chatGPT_url
headers = {
"Content-Type": "application/json; charset=utf-8",
}
payload_message = {
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "微博头条热榜",
"content": content
}
}
}
}
response = requests.post(url=url, data=json.dumps(payload_message), headers=headers)
return response
# 微博头条榜单
def getHotBand(self):
url = "https://www.weibo.com/ajax/statuses/hot_band"
headers = {
"cookie": "XSRF-TOKEN=iuIb9M_gQ8D4FjMwUthqcink; SUB=_2AkMUpJdaf8NxqwJRmPEVz2Pib4V_zwrEieKi-GaBJRMxHRl-yT92qhALtRB6PyS5tbPLRbsCo0gfSwhlb8PLq3CnqnuA; SUBP=0033WrSXqPxfM72-Ws9jqgMF55529P9D9WFyRDSrne6a4e.bkQHJzd-.; WBPSESS=IawIaCISeX-46VmeRocrJ40RrQZ7YTNxKt6pB9xuTQ-WP-uhwIvsoHpBEQfU2CGlyGf32loDQLI6ykRbGvzNf_mvmCuvfYLwUPDbYHJizUdUKfKplkCi6sPas7wrz6ACVGt8HOr-w8hjNGpZtkeUtLcl0-BFnXMuSPDMToH7QlI=",
"x-xsrf-token": "iuIb9M_gQ8D4FjMwUthqcink"
}
response = requests.get(url=url, headers=headers).json()
bandList_all = []
index = 1
for item in response['data']['band_list']:
bandDict = {"tag": "text"}
bandList = []
bandDict.update({"text": "No." + str(index) + ":" + item['word']})
bandList.append(bandDict)
index += 1
bandList_all.append(bandList)
return bandList_all
# 发送富文本消息
content = FeishuTalk().getHotBand()
FeishuTalk().sendFuTextmessage(content)
# 注:富文本消息的content消息体格式如下
[
[
{
"tag": "text",
"text": "第一行 :"
}
],
[
{
"tag": "text",
"text": "第二行:"
}
]
]

发送图片要分为两步:第一步通过上传图片接口获取image_key,第二步将上传的图片发送到群。可参考:发送图片
登录【飞书开放平台-开发者后台】,查看app_id与app_secret,通过接口拿到 tenant_access_token,供上传图片接口使用。可参考:自建应用获取 tenant_access_token;

注:需要开通上传图片权限,入口:开发者后台-权限管理-检索【获取与上传图片或文件资源】;

上传图片获取 image_key ,可参考:上传图片获取image_key
class FeishuTalk:
# 应用凭证,获取方式查看上面的步骤
app_id = "cli_a37c6ffbdxxxxxxx"
app_secret = "mLstZkv0C4d1sxxxxxxxxxxxxxxx"
# 机器人webhook
chatGPT_url = 'https://open.feishu.cn/open-apis/bot/v2/hook/XXX'
def __init__(self):
# 获取tenant_access_token,供上传图片接口使用
url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
headers = {
"Content-Type": "application/json; charset=utf-8",
}
payload_data = {
"app_id": self.app_id,
"app_secret": self.app_secret
}
response = requests.post(url=url, data=json.dumps(payload_data), headers=headers).json()
self.token = response['tenant_access_token']
# 发送图片
def uploadImage(self, picturePath):
image_key_headers = {
'Authorization': 'Bearer ' + self.token,
}
# 上传图片获取image_key
get_image_key_url = "https://open.feishu.cn/open-apis/im/v1/images"
form = {'image_type': 'message',
'image': (open(picturePath, 'rb'))} # 需要替换具体的path
multi_form = MultipartEncoder(form)
image_key_headers['Content-Type'] = multi_form.content_type
response = requests.request("POST", get_image_key_url, headers=image_key_headers, data=multi_form).json()
# print(response.headers['X-Tt-Logid']) # for debug or oncall
image_key = response['data']['image_key']
print("image_key:", image_key)
# 发送图片
url = self.chatGPT_url
form = {'msg_type': 'image',
'content':
{"image_key": image_key}
}
headers = {
'Authorization': 'Bearer ' + self.token
}
response = requests.post(url=url, data=json.dumps(form), headers=headers)
return response.json()
# 发送图片消息
picturePath = "E:\PythonCodes\FeishuTalk\picLibs\1.jpg"
FeishuTalk().uploadImage(picturePath)

关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=
我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi