开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 373|回复: 6
收起左侧

[易语言] Python源码转易语言实现钉钉stream机qi人(求助)

[复制链接]
结帖率:0% (0/2)
发表于 2025-8-18 16:53:02 | 显示全部楼层 |阅读模式   重庆市重庆市
150精币
# !/usr/bin/env python

import argparse
import logging
from dingtalk_stream import AckMessage
import dingtalk_stream
from alibabacloud_dingtalk.oauth2_1_0.client import Client as dingtalkoauth2_1_0Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dingtalk.oauth2_1_0 import models as dingtalkoauth_2__1__0_models
from alibabacloud_dingtalk.robot_1_0.client import Client as dingtalkrobot_1_0Client
from alibabacloud_dingtalk.robot_1_0 import models as dingtalkrobot__1__0_models
from alibabacloud_tea_util import models as util_models
import time

_token_cache = {"token": None, "expire": 0}

def setup_logger():
    logger = logging.getLogger()
    handler = logging.StreamHandler()
    handler.setFormatter(
        logging.Formatter('%(asctime)s %(name)-8s %(levelname)-8s %(message)s [%(filename)s:%(lineno)d]'))
    logger.addHandler(handler)
    logger.setLevel(logging.INFO)
    return logger


def define_options():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--client_id', dest='client_id', required=True,
        help='app_key or suite_key from https://open-dev.digntalk.com'
    )
    parser.add_argument(
        '--client_secret', dest='client_secret', required=True,
        help='app_secret or suite_secret from https://open-dev.digntalk.com'
    )
    parser.add_argument(
        '--robot_code', dest='robot_code', required=True,
        help='robot_code from https://open-dev.dingtalk.com'
    )
    options = parser.parse_args()
    return options


def get_token(options):
    """
    使用钉钉SDK获取access_token,带本地缓存,2小时有效,提前200秒刷新。
    :param options: 命令行参数对象,包含 client_id, client_secret
    :return: access_token字符串,获取失败返回None
    """
    now = time.time()
    if _token_cache["token"] and now < _token_cache["expire"]:
        return _token_cache["token"]
    config = open_api_models.Config()
    config.protocol = 'https'
    config.region_id = 'central'
    client = dingtalkoauth2_1_0Client(config)
    get_access_token_request = dingtalkoauth_2__1__0_models.GetAccessTokenRequest(
        app_key=options.client_id,
        app_secret=options.client_secret
    )
    try:
        response = client.get_access_token(get_access_token_request)
        token = getattr(response.body, "access_token", None)
        expire_in = getattr(response.body, "expire_in", 7200)
        if token:
            _token_cache["token"] = token
            _token_cache["expire"] = now + expire_in - 200  # 提前200秒刷新
        return token
    except Exception as err:
        print(f"获取token失败: {err}")
        return None


def send_robot_group_message(access_token, open_conversation_id, options):
    """
    使用钉钉SDK发送群消息
    :param access_token: 已获取的 access_token
    :param open_conversation_id: 群会话ID
    :param options: 命令行参数对象,包含 robot_code
    :return: 发送结果或 None
    """
    robot_code = options.robot_code
    msg_param = '{"content":"python-getting-start say:hello"}'
    msg_key = 'sampleText'
    config = open_api_models.Config()
    config.protocol = 'https'
    config.region_id = 'central'
    client = dingtalkrobot_1_0Client(config)
    org_group_send_headers = dingtalkrobot__1__0_models.OrgGroupSendHeaders()
    org_group_send_headers.x_acs_dingtalk_access_token = access_token
    org_group_send_request = dingtalkrobot__1__0_models.OrgGroupSendRequest(
        msg_param=msg_param,
        msg_key=msg_key,
        open_conversation_id=open_conversation_id,
        robot_code=robot_code
    )
    try:
        response = client.org_group_send_with_options(
            org_group_send_request,
            org_group_send_headers,
            util_models.RuntimeOptions()
        )
        print("消息发送成功,返回:", response)
        return response
    except Exception as err:
        print(f"发送群消息失败: {err}")
        return None


class EchoTextHandler(dingtalk_stream.ChatbotHandler):
    def __init__(self, logger: logging.Logger = None, options=None):
        super(dingtalk_stream.ChatbotHandler, self).__init__()
        self.logger = logger
        self.options = options

    async def process(self, callback: dingtalk_stream.CallbackMessage):
        incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
        open_conversation_id = incoming_message.conversation_id
        access_token = get_token(self.options)
        if access_token:
            send_robot_group_message(access_token, open_conversation_id, self.options)
        else:
            print("access_token 获取失败")
        return AckMessage.STATUS_OK, 'OK'


def main():
    logger = setup_logger()
    options = define_options()
    credential = dingtalk_stream.Credential(options.client_id, options.client_secret)
    client = dingtalk_stream.DingTalkStreamClient(credential)
    client.register_callback_handler(
        dingtalk_stream.chatbot.ChatbotMessage.TOPIC,
        EchoTextHandler(logger, options)
    )
    client.start_forever()


if __name__ == '__main__':
    main()


有大佬可以转的吗


回答提醒:如果本帖被关闭无法回复,您有更好的答案帮助楼主解决,请发表至 源码区 可获得加分喔。
友情提醒:本版被采纳的主题可在 申请荣誉值 页面申请荣誉值,获得 1点 荣誉值,荣誉值可兑换荣誉会员、终身vip用户组。
快捷通道:申请荣誉值
结帖率:98% (84/86)

签到天数: 8 天

发表于 2025-8-18 17:19:03 | 显示全部楼层   湖南省长沙市
  
窗口程序集名保 留  保 留备 注
程序集1   
变量名类 型数组备 注
token_cache文本型2[0]为token,[1]为过期时间
logger日志类  
client_id文本型  
client_secret文本型  
robot_code文本型  

子程序名返回值类型公开备 注
_启动子程序整数型 本子程序在程序启动后最先执行
变量名类 型静态数组备 注
命令行参数文本型0
i整数型 
参数名文本型 
参数值文本型 
' 初始化日志
logger.初始化 ()
logger.设置日志级别 (日志级别_信息)
' 解析命令行参数
命令行参数 = 取命令行参数 ()
计次循环首 (取数组成员数 (命令行参数), i)
如果真 (取文本左边 (命令行参数 [i], 2) = "--")
参数名 = 取文本中间 (命令行参数 [i], 3, 取文本长度 (命令行参数 [i]) - 2)
如果真 (i < 取数组成员数 (命令行参数))
参数值 = 命令行参数 [i + 1]
如果 (参数名 = "client_id")
client_id = 参数值
.否则如果 (参数名 = "client_secret")
client_secret = 参数值
.否则如果 (参数名 = "robot_code")
robot_code = 参数值
logger.写日志 (日志级别_警告, "未知参数: " + 参数名)


计次循环尾 ()
' 检查必要参数
如果 (client_id = "" client_secret = "" robot_code = "")
logger.写日志 (日志级别_错误, "缺少必要参数,请提供client_id、client_secret和robot_code")
返回 (1)

' 初始化token缓存
token_cache [1] = "0"
' 启动钉钉消息监听(这里使用模拟,实际需要根据钉钉stream协议实现)
logger.写日志 (日志级别_信息, "钉钉机qi人程序启动成功")
模拟消息监听 ()
返回 (0)
子程序名返回值类型公开备 注
模拟消息监听  
' 注意:这里只是模拟消息监听,实际需要根据钉钉stream协议实现WebSocket连接
变量名类 型静态数组备 注
模拟会话ID文本型 
模拟会话ID = "模拟群会话ID_123456"
logger.写日志 (日志级别_信息, "开始监听消息...")
' 模拟接收到消息
计次循环首 (5, )
处理接收到的消息 (模拟会话ID)
延迟 (5000)
计次循环尾 ()
子程序名返回值类型公开备 注
处理接收到的消息  
参数名类 型参考可空数组备 注
open_conversation_id文本型
变量名类 型静态数组备 注
access_token文本型 
logger.写日志 (日志级别_信息, "收到消息,会话ID: " + open_conversation_id)
access_token = 获取Token ()
如果 (access_token ≠ "")
发送机qi人群消息 (access_token, open_conversation_id)
logger.写日志 (日志级别_错误, "获取access_token失败")

子程序名返回值类型公开备 注
获取Token文本型 
变量名类 型静态数组备 注
现在时间整数型 
过期时间整数型 
响应文本文本型 
json解析类_json解析 
状态码整数型 
token文本型 
过期时间秒整数型 
' 检查缓存
现在时间 = 取现行时间戳 ()
过期时间 = 到整数 (token_cache [1])
如果 (token_cache [0] ≠ "" 现在时间 < 过期时间)
返回 (token_cache [0])

' 缓存失效,重新获取
logger.写日志 (日志级别_信息, "获取新的access_token...")
响应文本 = 网页_访问S ("https://api.dingtalk.com/v1.0/oauth2/accessToken", , "grant_type=client_credentials&client_id=" + 编码_URL编码 (client_id) + "&client_secret=" + 编码_URL编码 (client_secret), , , 状态码)
如果 (状态码 ≠ 200)
logger.写日志 (日志级别_错误, "获取token失败,状态码: " + 到文本 (状态码) + ",响应: " + 响应文本)
返回 ("")

json解析.解析 (响应文本)
token = json解析.取属性值 (“accessToken”)
过期时间秒 = 到整数 (json解析.取属性值 (“expireIn”))
如果 (token ≠ "")
' 提前200秒刷新
token_cache [0] = token
token_cache [1]到文本 (现在时间 + 过期时间秒 - 200)
logger.写日志 (日志级别_信息, "获取access_token成功")
返回 (token)
logger.写日志 (日志级别_错误, "解析token失败,响应: " + 响应文本)
返回 ("")

子程序名返回值类型公开备 注
发送机qi人群消息  
参数名类 型参考可空数组备 注
access_token文本型
open_conversation_id文本型
变量名类 型静态数组备 注
响应文本文本型 
状态码整数型 
请求头文本型 
请求数据文本型 
json解析类_json解析 
logger.写日志 (日志级别_信息, "发送群消息到会话: " + open_conversation_id)
' 构建请求头
请求头 = "Content-Type: application/json" + #换行符 + "x-acs-dingtalk-access-token: " + access_token
' 构建请求数据
json解析.清空 ()
json解析.添加键值对 (“msgParam”, “{"content":"易语言机qi人 say:hello"}”)
json解析.添加键值对 (“msgKey”, “sampleText”)
json解析.添加键值对 (“openConversationId”, open_conversation_id)
json解析.添加键值对 (“robotCode”, robot_code)
请求数据 = json解析.转换为文本 ()
' 发送请求
响应文本 = 网页_访问S (“https://api.dingtalk.com/v1.0/robot/groupMessages/send”, 1, 请求数据, 请求头, , 状态码)
如果 (状态码 = 200)
logger.写日志 (日志级别_信息, "消息发送成功,响应: " + 响应文本)
logger.写日志 (日志级别_错误, "消息发送失败,状态码: " + 到文本 (状态码) + ",响应: " + 响应文本)

窗口程序集名保 留  保 留备 注
日志类   
变量名类 型数组备 注
日志级别整数型  

子程序名返回值类型公开备 注
初始化  
日志级别 = 日志级别_信息
子程序名返回值类型公开备 注
设置日志级别  
参数名类 型参考可空数组备 注
级别整数型
日志级别 = 级别
子程序名返回值类型公开备 注
写日志  
参数名类 型参考可空数组备 注
级别整数型
内容文本型
变量名类 型静态数组备 注
时间字符串文本型 
级别字符串文本型 
如果 (级别 > 日志级别)
返回

时间字符串 = 取时间字符串 (取现行时间 (), #日期时间格式 )
判断 (级别 = 日志级别_调试)
级别字符串 = "DEBUG"
判断 (级别 = 日志级别_信息)
级别字符串 = "INFO"
判断 (级别 = 日志级别_警告)
级别字符串 = "WARNING"
判断 (级别 = 日志级别_错误)
级别字符串 = "ERROR"
判断 (级别 = 日志级别_致命)
级别字符串 = "FATAL"
级别字符串 = "UNKNOWN"

输出调试文本 (时间字符串 + " [" + 级别字符串 + "] " + 内容)
常量名称常量值公 开备 注
日志级别_调试0 
日志级别_信息1 
日志级别_警告2 
日志级别_错误3 
日志级别_致命4 



i支持库列表   支持库注释   
internet互联网支持库
dp1数据操作支持库一
eJSON(未知支持库)

回复

使用道具 举报

结帖率:50% (1/2)
发表于 2025-8-18 17:45:04 | 显示全部楼层   河北省张家口市
  
子程序名返回值类型公开备 注
_启动子程序整数型 
日志初始化 ()
启动线程 (&主逻辑, , )
返回 (0)
' ================== 日志初始化 ==================
子程序名返回值类型公开备 注
日志初始化  
输出调试文本 (“[INFO] 日志系统已初始化”)
' ================== 主逻辑 ==================
子程序名返回值类型公开备 注
主逻辑  
变量名类 型静态数组备 注
client_id文本型 
client_secret文本型 
robot_code文本型 
access_token文本型 
' 替换为你的钉钉开放平台凭证
client_id = “your_client_id”
client_secret = “your_client_secret”
robot_code = “your_robot_code”
判断循环首 ()  ' 保持长连接
access_token = 获取Token (client_id, client_secret)
如果 (access_token ≠ “”)
输出调试文本 (“[INFO] 获取Token成功: ” + access_token)
' 模拟接收消息并回复(实际需对接钉钉Stream API)
发送群消息 (access_token, “test_conversation_id”, robot_code, “易语言机qi人说:你好!”)
输出调试文本 (“[ERROR] 获取Token失败”)

延迟 (5000)  ' 5秒轮询一次
判断循环尾 ()
' ================== 获取Token ==================
子程序名返回值类型公开备 注
获取Token文本型 
参数名类 型参考可空数组备 注
client_id文本型
client_secret文本型
变量名类 型静态数组备 注
当前时间整数型 
请求地址文本型 
提交数据文本型 
协议头文本型 
返回文本文本型 
HTTP响应整数型 
token文本型 
当前时间 = 取启动时间 () ÷ 1000  ' 转换为秒
' 检查缓存是否有效
如果 (_token缓存 ≠ “” 当前时间 < _token过期时间)
返回 (_token缓存)


请求地址 = “https://api.dingtalk.com/v1.0/oauth2/accessToken”
提交数据 = “{”clientId“:”” + client_id + “”,”clientSecret“:”” + client_secret + “”}”
协议头 = “Content-Type: application/json”
HTTP响应 = 网页_访问 (请求地址, 1, 提交数据, , , 协议头, , , , , , , )
返回文本 = 编码_Utf8到Ansi (HTTP响应)
token = 文本_取出中间文本 (返回文本, “access_token””:”“, ”””)
如果 (token ≠ “”)
_token缓存 = token
_token过期时间 = 当前时间 + 7000  ' 提前200秒刷新(7200-200)
返回 (token)
返回 (“”)


' ================== 发送群消息 ==================
子程序名返回值类型公开备 注
发送群消息逻辑型 
参数名类 型参考可空数组备 注
access_token文本型
open_conversation_id文本型
robot_code文本型
消息内容文本型
变量名类 型静态数组备 注
请求地址文本型 
提交数据文本型 
协议头文本型 
HTTP响应整数型 
返回文本文本型 
请求地址 = “https://api.dingtalk.com/v1.0/robot/groupMessages/send”
提交数据 = “{”msgParam“: ”{”content“:”” + 消息内容 + “”}“,”msgKey“:”sampleText“,”openConversationId“:”” + open_conversation_id + “”,”robotCode“:”” + robot_code + “”}”
协议头 = “Content-Type: application/json”#换行符“x-acs-dingtalk-access-token: ” + access_token
HTTP响应 = 网页_访问 (请求地址, 1, 提交数据, , , 协议头, , , , , , , )
返回文本 = 编码_Utf8到Ansi (HTTP响应)
输出调试文本 (“[DEBUG] 消息发送返回: ” + 返回文本)
返回 (寻找文本 (返回文本, “success”, , ) ≠ -1)


i支持库列表   支持库注释   
EThread多线程支持库
spec特殊功能支持库

回复

使用道具 举报

结帖率:0% (0/2)
 楼主| 发表于 2025-8-18 23:15:29 | 显示全部楼层   重庆市重庆市
huayuanderen 发表于 2025-8-18 17:45
[e=0].版本 2
.支持库 EThread
.支持库 spec

现在是回调不了群里@消息
回复

使用道具 举报

结帖率:50% (1/2)
发表于 2025-8-19 01:06:33 | 显示全部楼层   河北省张家口市
什么是不是你代码有问题啊 所以回调不了
回复

使用道具 举报

结帖率:0% (0/2)
 楼主| 发表于 2025-8-19 08:28:17 | 显示全部楼层   重庆市重庆市
huayuanderen 发表于 2025-8-19 01:06
什么是不是你代码有问题啊 所以回调不了

从官网下的实例,用PYthon 试了 可以用
回复

使用道具 举报

结帖率:50% (1/2)
发表于 2025-8-19 09:30:33 | 显示全部楼层   河北省张家口市
renjinyu 发表于 2025-8-19 08:28
从官网下的实例,用PYthon 试了 可以用

那不清除啊,没弄过钉钉
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

关闭

精易论坛 - 有你更精彩上一条 /2 下一条

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表