七夏 发表于 2024-7-24 18:08:54

discuz论坛新帖推送到钉钉群教程

前言:本教程适用于热爱折腾的小伙伴,没有基础的朋友可能看不太懂,但不影响你使用!
因为是本站自用,所以没有做成插件,发出来一是留作记录,二是供大家研究一下,欢迎指正不足!



注意,所有操作基于默认程序(数据库),如果你的程序(数据库)有改动,请自行适配。

实现步骤

1. 设置数据库触发器

在发布新帖子时,使用MySQL触发器将新帖子的相关信息插入到 notification_queue 表中。
在数据库中执行下面的代码:
CREATE TABLE IF NOT EXISTS notification_queue (
    id INT AUTO_INCREMENT PRIMARY KEY,
    tid INT,
    subject VARCHAR(255),
    author VARCHAR(100),
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

DELIMITER //

CREATE TRIGGER trg_new_post_notification
AFTER INSERT ON pre_forum_thread
FOR EACH ROW
BEGIN
    INSERT INTO notification_queue (tid, subject, author)
    VALUES (NEW.tid, NEW.subject, NEW.author);
END;
//

DELIMITER ;

数据库触发器 (trg_new_post_notification):在每次向 pre_forum_thread 表中插入新帖子时触发,将帖子的 tid、subject 和 author 插入到 notification_queue 表中。

2. 编写消息队列消费者的PHP脚本

编写PHP脚本作为消息队列的消费者,从 notification_queue 表中读取待处理的通知,并发送到钉钉群组。
创建一个PHP文件,并填入下方代码:
<?php
// 连接MySQL和Redis
$mysql_host = 'localhost';
$mysql_user = '你的数据库用户名';
$mysql_password = '你的数据库密码';
$mysql_database = '你的数据库名';
$redis_host = 'localhost';
$redis_port = 6379;

try {
    $pdo = new PDO("mysql:host=$mysql_host;dbname=$mysql_database", $mysql_user, $mysql_password);
    $redis = new Redis();
    $redis->connect($redis_host, $redis_port);

    // 持续监听通知队列
    while (true) {
      // 从MySQL中获取待处理的通知
      $stmt = $pdo->query("SELECT * FROM notification_queue");
      while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            // 构建通知消息
            $message = "新帖发布:{$row['subject']}\n";
            $message .= "作者: {$row['author']}\n";
            $message .= "发布时间: {$row['create_time']}\n";
            $message .= "查看链接: http://yourforum.com/viewthread.php?tid={$row['tid']}";

            // 发送通知到钉钉
            send_dingtalk_notification($message);

            // 从队列中删除已处理的通知
            $pdo->exec("DELETE FROM notification_queue WHERE id = {$row['id']}");
      }

      // 休眠一段时间,避免持续轮询
      usleep(100000); // 0.1秒
    }
} catch (PDOException $e) {
    die("错误: " . $e->getMessage());
}

// 发送通知到钉钉的函数
function send_dingtalk_notification($message) {
    // 替换为你的钉钉机器人Webhook地址和加签密钥
    $webhook = 'https://oapi.dingtalk.com/robot/send?access_token=你的access_token';
    $secret = '你的加签密钥';

    // 构建消息内容
    $data = array(
      'msgtype' => 'text',
      'text' => array('content' => $message)
    );

    // 转换数据为JSON格式
    $data_string = json_encode($data);

    // 计算时间戳和加签
    $timestamp = time() * 1000;
    $sign = urlencode(base64_encode(hash_hmac('sha256', $timestamp . "\n" . $secret, $secret, true)));

    // 构建最终的URL,包含时间戳和加签
    $url = "$webhook&timestamp=$timestamp&sign=$sign";

    // 发送HTTP POST请求到钉钉
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $response = curl_exec($ch);
    curl_close($ch);

    // 可选:记录或处理来自钉钉的响应
    // error_log("钉钉响应: " . $response);
}
?>

PHP消费者脚本:这个脚本使用无限循环来持续监听 notification_queue 表。在每次循环中,它从表中读取待处理的通知,构建包含帖子标题、作者、发布时间和查看链接的消息,然后通过Curl发送HTTP POST请求将消息发送到钉钉群组,并删除已处理的通知记录。

3. 创建定时任务

虽然采用了持续监听,可以保证实时推送,但一段时间内没有新内容就会休眠,所以需要定时任务来唤醒。
设置间隔访问上方的PHP文件即可。

通过以上步骤,你可以实现在发布新帖子时实时通知到钉钉群组,并且通知内容包含了帖子的关键信息。这种方法能有效地将业务逻辑和通知发送过程分离,同时保持系统的高效性和资源优化。

SanS三石 发表于 2024-7-25 10:04:34

真正要分开的两个人,连“分手”二字都是多余的,因为殊途同归。—— 来自:荷包蛋部落(HBD0.CN)已读乱回
页: [1]
查看完整版本: discuz论坛新帖推送到钉钉群教程