Files
2meet-data-optimizer/includes/notifications/class-tmdo-discord-notifier.php
T
wpdev 76c01e44df refactor: 全部 128 個生產檔加入 declare(strict_types=1)(PR-H)
對齊 A v3.2.0。型別強制會把隱式轉換變成 TypeError,所以一次全檔加入
並跑完整測試(unit 451 / integration 398 全綠,無迴歸)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
2026-07-31 06:13:33 +08:00

79 lines
2.0 KiB
PHP

<?php
/**
* TMDO_Discord_Notifier — Discord webhook channel (v2.5.0 M15).
*
* Settings: wpdo_discord_enabled, wpdo_discord_webhook,
* wpdo_discord_throttle_hours, wpdo_discord_severity.
*
* @package WP_Data_Optimizer
*/
declare(strict_types=1);
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Discord channel.
*/
class TMDO_Discord_Notifier extends TMDO_Abstract_Notifier {
/**
* Channel identifier used as option key prefix.
*
* @return string
*/
public static function channel_id(): string {
return 'discord';
}
/**
* Build Discord-specific context (webhook URL).
*
* @return array|null Null if webhook URL is missing or invalid.
*/
public static function build_context(): ?array {
$url = class_exists( 'TMDO_Crypto' )
? TMDO_Crypto::get_option( 'wpdo_discord_webhook' )
: (string) get_option( 'wpdo_discord_webhook', '' );
if ( '' === $url || strpos( $url, 'https://discord.com/api/webhooks/' ) !== 0 ) {
return null;
}
return array( 'webhook_url' => $url );
}
/**
* Send alert via Discord webhook.
*
* @param string $subject Alert subject / title.
* @param string $body Alert body text.
* @param array $context Channel context (webhook_url).
* @return bool True on HTTP 2xx response.
*/
public static function actually_send( string $subject, string $body, array $context ): bool {
$url = (string) ( $context['webhook_url'] ?? '' );
if ( '' === $url ) {
return false;
}
// Discord max content length = 2000 chars.
$content = "**{$subject}**\n```\n" . substr( $body, 0, 1800 ) . "\n```";
$payload = wp_json_encode( array( 'content' => $content ) );
$resp = wp_remote_post(
$url,
array(
'headers' => array( 'Content-Type' => 'application/json' ),
'body' => $payload,
'timeout' => 5,
'blocking' => true,
)
);
if ( is_wp_error( $resp ) ) {
return false;
}
$code = (int) wp_remote_retrieve_response_code( $resp );
// Discord returns 204 on success.
return $code >= 200 && $code < 300;
}
}