发送webhook到飞书机器人

发送webhook到飞书机器人

发送webhook到飞书机器人

参考链接 自定义机器人使用指南

创建自定义机器人

  1. 邀请自定义机器人进群。
  2. 获取签名校验
    在 安全设置 区域,选择 签名校验。

获取自定义机器人的 webhook 地址
机器人对应的 webhook 地址 格式如下:
https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx
请妥善保存好此 webhook 地址,不要公布在 Gitlab、博客等可公开查阅的网站上,避免地址泄露后被恶意调用发送垃圾消息。

在这里插入图片描述

设置自定义机器人的头像、名称与描述,并点击 添加。

在这里插入图片描述

在 群机器人 界面点击 添加机器人。在 添加机器人 对话框,找到并点击 自定义机器人。

在这里插入图片描述

在右侧 设置 界面,点击 群机器人。

在这里插入图片描述

进入目标群组,在群组右上角点击更多按钮,并点击 设置。

在这里插入图片描述

选择签名校验后,系统已默认提供了一个秘钥。你也可以点击 重置,更换秘钥。

在这里插入图片描述

使用java发送http post到自定义机器人

  1. 计算签名校验,参考官方文档的SignDemo.java,自定义一个签名函数
privatestaticStringgenSign(String secret,long timestamp)throwsNoSuchAlgorithmException,InvalidKeyException{//把timestamp+"\n"+密钥当做签名字符串String stringToSign = timestamp +"\n"+ secret;//使用HmacSHA256算法计算签名Mac mac =Mac.getInstance("HmacSHA256"); mac.init(newSecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8),"HmacSHA256"));byte[] signData = mac.doFinal(newbyte[]{});returnnewString(Base64.encodeBase64(signData));}
  1. 计算时间戳
    需要注意的是,时间戳是以秒为单位的,并且要配置时区,不可直接使用System.currentTimeMillis()/1000来计算秒值
long seconds =LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
  1. 创建富文本消息
    参考官方文档 发送富文本消息
    • 创建一个content对象
privatestaticJSONObjectcreateOuterContent(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("post",createPostJsonObject(title, message, detail, startTime, endTime));return result;}privatestaticJSONObjectcreatePostJsonObject(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("zh_cn",createZhCNJsonObject(title, message, detail, startTime, endTime));return result;}privatestaticJSONObjectcreateZhCNJsonObject(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("title", title); result.put("content",createContentList(message, detail, startTime, endTime));return result;}privatestaticJSONArraycreateContentList(String message,String detail,String startTime,String endTime){JSONArray result =newJSONArray();JSONArray item1 =newJSONArray(); item1.add(createInnerHeadContent("message")); item1.add(createInnerTextContent(message)); result.add(item1);JSONArray item2 =newJSONArray(); item2.add(createInnerHeadContent("detail")); item2.add(createInnerTextContent(detail)); result.add(item2);JSONArray item3 =newJSONArray(); item3.add(createInnerHeadContent("startTime")); item3.add(createInnerTextContent(startTime)); result.add(item3);JSONArray item4 =newJSONArray(); item4.add(createInnerHeadContent("endTime")); item4.add(createInnerTextContent(endTime)); result.add(item4);return result;}privatestaticJSONObjectcreateInnerHeadContent(String tag){JSONObject result =newJSONObject(); result.put("tag","text"); result.put("text", tag+": ");return result;}privatestaticJSONObjectcreateInnerTextContent(String text){JSONObject result =newJSONObject(); result.put("tag","text"); result.put("text", text);return result;}
  • 再创建完整的json对象

完整代码如下

java版本

publicclassFeishuWebhook{privatestaticfinalLogger logger =LoggerFactory.getLogger(FeishuWebhook.class);publicstaticfinalStringDEFAULT_DATETIME_FORMATTER_STR="yyyy-MM-dd HH:mm:ss";publicstaticfinalDateTimeFormatterDEFAULT_DATETIME_FORMATTER=DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMATTER_STR);publicstaticvoidsend(String url,String secret,AlertDO alertDO){ logger.info("FeishuWebhook.send, url:{}, alertDO={}", url, alertDO);JSONObject requestBody =createRequestBody(secret, alertDO); logger.info("requestBody:{}", requestBody);JSONObject result =HttpUtils.postForJsonObject(url,null,null, requestBody); logger.info("result:{}", result);}privatestaticStringgenSign(String secret,long timestamp)throwsNoSuchAlgorithmException,InvalidKeyException{//把timestamp+"\n"+密钥当做签名字符串String stringToSign = timestamp +"\n"+ secret;//使用HmacSHA256算法计算签名Mac mac =Mac.getInstance("HmacSHA256"); mac.init(newSecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8),"HmacSHA256"));byte[] signData = mac.doFinal(newbyte[]{});returnnewString(Base64.encodeBase64(signData));}privatestaticJSONObjectcreateRequestBody(String secret,AlertDO alertDO){JSONObject requestBody =newJSONObject();long seconds =LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond(); logger.info("seconds:{}", seconds);// int seconds = 1734515343;try{String sign =genSign(secret, seconds); requestBody.put("timestamp", seconds); requestBody.put("sign", sign); requestBody.put("msg_type","post");String title ="通知";String message = alertDO.getMessage();String detail = alertDO.getDetail();String startTime =DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.ofInstant(alertDO.getStartTime().toInstant(),ZoneId.systemDefault()));String endTime =DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.ofInstant(alertDO.getEndTime().toInstant(),ZoneId.systemDefault())); requestBody.put("content",createOuterContent(title, message, detail, startTime, endTime));}catch(Exception e){ e.printStackTrace();}return requestBody;}privatestaticJSONObjectcreateOuterContent(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("post",createPostJsonObject(title, message, detail, startTime, endTime));return result;}privatestaticJSONObjectcreatePostJsonObject(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("zh_cn",createZhCNJsonObject(title, message, detail, startTime, endTime));return result;}privatestaticJSONObjectcreateZhCNJsonObject(String title,String message,String detail,String startTime,String endTime){JSONObject result =newJSONObject(); result.put("title", title); result.put("content",createContentList(message, detail, startTime, endTime));return result;}privatestaticJSONArraycreateContentList(String message,String detail,String startTime,String endTime){JSONArray result =newJSONArray();JSONArray item1 =newJSONArray(); item1.add(createInnerHeadContent("message")); item1.add(createInnerTextContent(message)); result.add(item1);JSONArray item2 =newJSONArray(); item2.add(createInnerHeadContent("detail")); item2.add(createInnerTextContent(detail)); result.add(item2);JSONArray item3 =newJSONArray(); item3.add(createInnerHeadContent("startTime")); item3.add(createInnerTextContent(startTime)); result.add(item3);JSONArray item4 =newJSONArray(); item4.add(createInnerHeadContent("endTime")); item4.add(createInnerTextContent(endTime)); result.add(item4);return result;}privatestaticJSONObjectcreateInnerHeadContent(String tag){JSONObject result =newJSONObject(); result.put("tag","text"); result.put("text", tag+": ");return result;}privatestaticJSONObjectcreateInnerTextContent(String text){JSONObject result =newJSONObject(); result.put("tag","text"); result.put("text", text);return result;}}

python版本
FeishuBotHypertextWithSecret.py

import base64 import hashlib import hmac from datetime import datetime import requests WEBHOOK_URL ="https://open.feishu.cn/open-apis/bot/v2/hook/xx" WEBHOOK_SECRET ="ssssssss"classLarkBot:def__init__(self, secret:str)->None:ifnot secret:raise ValueError("invalid secret key") self.secret = secret defgen_sign(self, timestamp:int)->str: string_to_sign ='{}\n{}'.format(timestamp, self.secret) hmac_code = hmac.new( string_to_sign.encode("utf-8"), digestmod=hashlib.sha256 ).digest() sign = base64.b64encode(hmac_code).decode('utf-8')return sign defsend(self)->None: timestamp =int(datetime.now().timestamp()) sign = self.gen_sign(timestamp) params ={"timestamp": timestamp,"sign": sign,"msg_type":"post","content":{"post":{"zh_cn":{"title":"项目更新通知","content":[[{"tag":"text","text":"项目有更新: "},{"tag":"a","text":"请查看","href":"http://www.example.com/"},{"tag":"at","user_id":"ou_18eac8********17ad4f02e8bbbb"}]]}}}} resp = requests.post(url=WEBHOOK_URL, json=params) resp.raise_for_status() result = resp.json()if result.get("code")and result["code"]!=0:print(result["msg"])returnprint("消息发送成功")defmain(): bot = LarkBot(secret=WEBHOOK_SECRET) bot.send()if __name__ =='__main__': main()

LarkBotWithoutSecret.py

from datetime import datetime import requests WEBHOOK_URL ="https://open.feishu.cn/open-apis/bot/v2/hook/sss"classLarkBot:defsend(self, content:str)->None: timestamp =int(datetime.now().timestamp()) params ={"timestamp": timestamp,"msg_type":"text","content":{"text": content},} resp = requests.post(url=WEBHOOK_URL, json=params) resp.raise_for_status() result = resp.json()if result.get("code")and result["code"]!=0:print(result["msg"])returnprint("消息发送成功")defmain(): bot = LarkBot() bot.send(content="我是一只高级鸽子!")if __name__ =='__main__': main()

Read more

当 Vibe Coding 遇上汽车 PID 开发:AIGC 重构嵌入式创意落地范式

当 Vibe Coding 遇上汽车 PID 开发:AIGC 重构嵌入式创意落地范式

在汽车定速巡航 PID 参数调试的传统开发流程中,开发者往往陷入 “公式推导→代码敲写→硬件烧录→实车测试” 的低效循环 —— 哪怕只是微调一个比例系数,都要经历数小时的代码修改、环境适配和实车验证,创意被繁琐的技术细节层层束缚。而当我以 Vibe Coding(AIGC 驱动的沉浸式编码)为核心,借助 TRAE 工具完成「汽车定速巡航 PID 参数调优可视化」项目(GitHub 仓库:https://github.com/LQY-hh/PID_Vibe_Coding)时,真切感受到了 AIGC 为嵌入式开发带来的创造性变革:它不是简单的 “代码生成工具”,而是让开发者从 “代码的执行者” 彻底回归为 “创意的设计者”,重构了嵌入式开发的创作逻辑。 一、从 “细节纠缠” 到

Copilot认证后强制使用GPT-4o模型的底层逻辑与开发者应对策略

最近在深度使用GitHub Copilot时,发现一个挺有意思的现象:一旦完成企业认证或订阅升级,Copilot的后端模型似乎就被“锁定”为GPT-4o了。对于习惯了根据任务类型灵活切换模型(比如用GPT-4处理复杂推理,用GPT-3.5处理轻量补全)的开发者来说,这多少有点不便。今天就来聊聊这背后的技术逻辑,以及我们作为开发者可以有哪些应对策略。 先看一组直观的数据对比。我在本地简单模拟了两种模型对同一段代码补全请求的响应情况: # 模拟请求日志 import time # GPT-4 (假设调用) start = time.time() # ... 模拟API调用 gpt4_latency = 320 # 毫秒 gpt4_tokens = 1250 # GPT-4o (实际Copilot认证后调用) gpt4o_latency = 280 # 毫秒 gpt4o_tokens = 1180 print(f"GPT-4 响应延迟: {gpt4_latency}ms,

实战指南:Stable Diffusion模型部署问题排查与性能调优

实战指南:Stable Diffusion模型部署问题排查与性能调优 【免费下载链接】stable-diffusionA latent text-to-image diffusion model 项目地址: https://gitcode.com/gh_mirrors/st/stable-diffusion 在将Stable Diffusion模型投入生产环境时,技术团队常常面临显存溢出、推理速度慢、生成质量不稳定等实际问题。本文基于实际部署经验,提供一套完整的故障排查与性能优化方案。 显存不足的快速解决方案 当遇到CUDA out of memory错误时,首先需要分析显存占用情况。通过以下命令可以实时监控显存使用: nvidia-smi -l 1 显存优化策略 降低批次大小:将默认的--n_samples 4调整为--n_samples 1,可减少约75%的显存占用。 调整图像分辨率:使用--H 384 --W 384替代默认的512×512,显存需求降低约40%

PyCharm+GitHub Copilot零成本配置手册:学生认证/2FA/汉化疑难一次解决

PyCharm + GitHub Copilot 零成本配置手册:从学生认证到流畅编码的全链路实战 作为一名学生开发者,你是否曾羡慕那些能流畅使用AI编程助手的同行,却苦于复杂的认证流程、网络环境的掣肘,或是面对英文界面时的些许不适?将前沿的AI工具无缝融入日常开发工作流,本应是一个提升效率的愉悦过程,而非充满障碍的挑战。今天,我们就来彻底解决这些问题,打造一套专为学生群体设计、开箱即用的PyCharm与GitHub Copilot生产力解决方案。这套方案不仅会手把手带你完成从学生身份验证到IDE集成的每一步,更会聚焦于国内用户常见的“水土不服”问题,提供稳定的替代方案和优化技巧,让你真正零成本、零门槛地拥抱AI辅助编程。 1. 基石构建:GitHub学生认证与账户安全加固 在享受任何福利之前,一个经过验证且安全的GitHub账户是首要前提。学生认证是获取GitHub Copilot Pro免费使用权的钥匙,而双重身份验证(2FA)则是守护这把钥匙的保险箱。 1.1 高效通过GitHub学生认证 学生认证的核心在于向GitHub证明你当前的在读身份。整个过程需要细心,但绝非