配置钉钉机器人推送阿里云站内信消息

158 阅读5分钟

1. 配置钉钉机器人推送阿里云站内信消息(消息经AI提炼)

将阿里云上的故障、风险、变更类消息通过AI提炼优化后将消息由钉钉机器人推送到钉钉。

2. 方案设定

image.png

3. 配置流程

3.1. 前提条件

  • Python版本在3.8及以上。
  • 服务器能否访问公网。

3.2. 百炼大模型配置

  1. 创建智能体应用

image.png 2. Prompt配置如下内容

# 角色
你是一名专业的文本关键信息提取专家,专门处理HTML格式的文本,并从中提取出关键信息。你需要根据不同的内容类型(如云上实例订购、产品推广广告、风险通知等),提取并总结相关信息。

## 技能
### 技能 1: 提取云上实例操作信息
- **任务**:从HTML文本中提取关于云上实例订购、续费、退订、变更等信息。如果实例ID超过5个,多余的实例省略。
  - 提取具体的操作信息(如订购、续费、退订、变更)。
  - 提取所有的实例ID,若超过30个,则多余的省略。(如未出现具体实例ID,请忽略,不要出现“原文中未提供具体的实例ID信息”等字样。)
  - 提取受影响的时间范围。(如未明确时间,请忽略,不要出现“时间未具体说明”等字样。)

### 技能 2: 提取风险和运维事件信息
- **任务**:从HTML文本中提取关于云上实例的风险、版本升级、计划运维事件、主动运维事件等信息。
  - 提取具体的风险信息。
  - 提取所有的实例ID,若超过30个,则多余的省略。(如未出现具体实例ID,请忽略,不要出现“原文中未提供具体的实例ID信息”等字样。)
  - 提取事件的发生或计划发生时间。(如未明确时间,请忽略,不要出现“时间未具体说明”等字样。)
  - 如有文档链接请输出,如未提供则忽略。

## 工具
- 你可以调用HTML解析工具来帮助你从HTML文本中提取关键信息。

## 限制
- 文本内容要简洁明了,避免冗余信息。
- 如果原文中没有建议客户执行的动作,不要给出建议;如果原文中有建议,确保在提取的信息中体现。
- 只提取关键信息,不进行额外的解释或扩展。
- 确保提取的信息准确无误,与原文保持一致。
- 不要说明本次任务做的是什么工作,直接输出内容。
- 不要给建议行动。
- 输出文本不需要类似"### 续费成功信息"的标题,直接给内容。
- 如果出现省略的信息,提示去控制台查具体信息。

4. 获取DASHSCOPE_API_KEY(后面配置需要使用)

image.png

3.3. Linux配置

本文以Alibaba Cloud Linux 3.2104 LTS 64位为例。

说明:Python3.8及以上版本请忽略步骤1-4。

  1. 更新Python版本

yum install python3.11 -y

  1. 设置Python命令默认使用Python3.11

alternatives --config python (输入python3.11的序列号)回车

  1. 验证版本

python --version

image.png 4. 更新pip版本

curl bootstrap.pypa.io/get-pip.py -o get-pip.py

python get-pip.py

  1. 安装依赖SDK

pip install requests alibabacloud-msccommonquery20210407 alibabacloud-tea-openapi dashscope

  1. 上传Python脚本文件(例如:上传至/data/)
import os
import json
import requests
from datetime import datetime, timedelta
from alibabacloud_msccommonquery20210407.client import (
    Client as MscCommonQuery20210407Client,
)
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_msccommonquery20210407 import (
    models as msc_common_query_20210407_models,
)
from http import HTTPStatus
from dashscope import Application
import hashlib
import hmac
import time
import base64
import urllib.parse

# 机器人配置加签则使用此版本


class MessageProcessor:
    def __init__(self, include_keywords=None, exclude_keywords=None):
        self.include_keywords = include_keywords or []
        self.exclude_keywords = exclude_keywords or []

    @staticmethod
    def send_msg_dd(msg):
        yesterday = datetime.now() - timedelta(days=1)
        yesterday_str = yesterday.strftime("%Y-%m-%d")

        prefix = f"**昨日事件通知({yesterday_str})**\n"

        access_token = os.getenv("DINGTALK_ACCESS_TOKEN")  # 机器人access_token
        secret = os.getenv("DINGTALK_ROBOT_SECRET")  # 加签秘钥

        timestamp = str(int(time.time() * 1000))
        sign = MessageProcessor.generate_sign(timestamp, secret)

        url = f"https://oapi.dingtalk.com/robot/send?access_token={access_token}&timestamp={timestamp}&sign={sign}"

        markdown_text = f"{prefix}\n{msg}"

        payload = {
            "msgtype": "markdown",
            "markdown": {
                "title": "阿里云事件通知",
                "text": markdown_text,
            },
            "at": {"isAtAll": True},
        }

        json_payload = json.dumps(payload)

        headers = {"Content-Type": "application/json"}

        response = requests.post(url, headers=headers, data=json_payload)

        print(response.status_code)
        print(response.text)

        return response.status_code

    @staticmethod
    def generate_sign(timestamp, secret):
        string_to_sign = f"{timestamp}\n{secret}"
        hmac_code = hmac.new(
            secret.encode("utf-8"),
            string_to_sign.encode("utf-8"),
            digestmod=hashlib.sha256,
        ).digest()

        # Base64编码并URL编码
        sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))

        return sign

    def message_optimize(self, content):
        response = Application.call(
            api_key=os.getenv("DASHSCOPE_API_KEY"),
            app_id=os.getenv("DASHSCOPE_API_ID"),
            prompt=content,
        )

        if response.status_code != HTTPStatus.OK:
            print(f"request_id={response.request_id}")
            print(f"code={response.status_code}")
            print(f"message={response.message}")
            print(
                f"请参考文档:https://help.aliyun.com/zh/model-studio/developer-reference/error-code"
            )
        else:
            text = getattr(response.output, "text", None)  # 安全访问属性
            if text is not None:
                self.send_msg_dd(text)

        return text

    def list_messages(
        self,
        start_timestamp,
        end_timestamp,
        channel_type="pmsg",
        page_no=1,
        page_size=50,
    ):
        access_key_id = os.environ["ALIBABA_CLOUD_ACCESS_KEY_ID"]
        access_key_secret = os.environ["ALIBABA_CLOUD_ACCESS_KEY_SECRET"]
        pop_domain = "msccommonquery.aliyuncs.com"

        config = open_api_models.Config(
            access_key_id=access_key_id,
            access_key_secret=access_key_secret,
        )

        config.endpoint = pop_domain
        client = MscCommonQuery20210407Client(config)
        request = msc_common_query_20210407_models.ListMessagesRequest()
        request.channel_type = channel_type
        request.start_timestamp = start_timestamp
        request.end_timestamp = end_timestamp
        request.page_no = page_no
        request.page_size = page_size

        try:
            response = client.list_messages(request)

            message_data = response.body.data

            # for i in message_data:
            #     if any(keyword.lower() in i.content.lower() for keyword in self.include_keywords):
            #         if not any(keyword.lower() in i.content.lower() for keyword in self.exclude_keywords):
            #             self.message_optimize(i.content)
            for i in message_data:
                content_includes_keyword = any(
                    keyword.lower() in i.content.lower()
                    for keyword in self.include_keywords
                )
                title_includes_keyword = any(
                    keyword.lower() in i.title.lower()
                    for keyword in self.include_keywords
                )

                content_excludes_keyword = any(
                    keyword.lower() in i.content.lower()
                    for keyword in self.exclude_keywords
                )
                title_excludes_keyword = any(
                    keyword.lower() in i.title.lower()
                    for keyword in self.exclude_keywords
                )

                # 如果content或title包含include关键字,并且都不包含exclude关键字,则进行优化处理
                if (content_includes_keyword or title_includes_keyword) and not (
                    content_excludes_keyword or title_excludes_keyword
                ):
                    self.message_optimize(i.content)

        except Exception as error:
            print(error)


if __name__ == "__main__":
    processor = MessageProcessor(
        include_keywords=[
            "变更",
            "运维",
            "风险",
            "切换",
            "宕机",
            "崩溃",
            "升级",
            "受损",
        ],
        exclude_keywords=[
            "ram用户",
            "带宽变更",
            "性价比",
            "开通",
            "新购",
            "续费",
            "提醒",
        ],
    )

    now = datetime.now()
    yesterday = now - timedelta(days=1)

    start_of_yesterday = datetime(
        yesterday.year, yesterday.month, yesterday.day, 0, 0, 0
    )
    start_timestamp = int(start_of_yesterday.timestamp())

    end_of_yesterday = datetime(now.year, now.month, now.day, 0, 0, 0)
    end_timestamp = int(end_of_yesterday.timestamp())

    processor.list_messages(start_timestamp, end_timestamp)
    # processor.list_messages(1735574400, 1735660800)

7. 创建shell脚本文件

touch /data/run.sh

#!/bin/bash
#RAM账号AK/SK
export ALIBABA_CLOUD_ACCESS_KEY_ID='your_access_key_id_here'
export ALIBABA_CLOUD_ACCESS_KEY_SECRET='your_access_key_secret_here'
#百炼大模型key及应用id
export DASHSCOPE_API_KEY='your_dashscope_api_key_here'
export DASHSCOPE_API_ID='your_dashscope_api_id'
#钉钉机器人token及加签密钥
export DINGTALK_ACCESS_TOKEN='your_dingtalk_access_token'
export DINGTALK_ROBOT_SECRET='your_dingtalk_robot_secret'

# 调用 Python 脚本
date +"%Y-%m-%d %H:%M:%S" >> /data/logfile.log 2>&1
/usr/bin/python /data/message_notice.py >> /data/logfile.log 2>&1

8. 配置定时任务定时执行

crontab -e

0 9 * * * /data/run.sh >> /data/logfile.log 2>&1