File: //proc/thread-self/cwd/fm_send_messages_to_dc.php
<?php
// 將 DISCORD_BOT_TOKEN 設為環境變數,避免把 Token 寫死在檔案裡
$token = 'MTQyODY1NTAyMzQxOTgxODAxNQ.GVhBDQ.m64Lv0GtJ5I6WfKzSLoeSEJ8yvt44zukEX7iME';
if (!$token) {
http_response_code(500);
echo json_encode(['error' => 'Missing DISCORD_BOT_TOKEN env var']);
exit;
}
// 參數
$user_id = isset($_GET['user_id']) ? trim($_GET['user_id']) : '';
$message = isset($_GET['message']) ? trim($_GET['message']) : '';
if ($message === '') {
http_response_code(400);
echo json_encode(['error' => 'message 不能為空']);
exit;
}
if (mb_strlen($message) > 2000) {
http_response_code(400);
echo json_encode(['error' => 'message 超過 2000 字元限制']);
exit;
}
function discord_post_json($url, $token, $payload) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_HTTPHEADER => [
'Authorization: Bot ' . $token,
'Content-Type: application/json',
'User-Agent: YSNETBot (https://ysnet.com.tw, 1.0)'
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true, // 連同 header 一起回傳
]);
$raw = curl_exec($ch);
if ($raw === false) {
$err = curl_error($ch);
curl_close($ch);
return [0, [], ['error' => $err]];
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headerStr = substr($raw, 0, $headerSize);
$bodyStr = substr($raw, $headerSize);
curl_close($ch);
// 解析 headers
$headers = [];
foreach (explode("\r\n", $headerStr) as $line) {
if (strpos($line, ':') !== false) {
[$k, $v] = explode(':', $line, 2);
$headers[trim($k)] = trim($v);
}
}
$body = json_decode($bodyStr, true);
if ($body === null && $bodyStr !== '') {
$body = ['raw' => $bodyStr]; // 非 JSON 時保底
}
return [$status, $headers, $body];
}
$api = 'https://discord.com/api/v10';
// 1) 建立 DM channel
list($s1, $h1, $b1) = discord_post_json($api . '/users/@me/channels', $token, [
'recipient_id' => $user_id
]);
if ($s1 !== 200) {
http_response_code($s1 ?: 500);
echo json_encode([
'step' => 'create_dm_channel',
'status' => $s1,
'rate_limit_remaining' => $h1['X-RateLimit-Remaining'] ?? null,
'retry_after' => $h1['Retry-After'] ?? null,
'error' => $b1['message'] ?? ($b1['error'] ?? 'unknown'),
'code' => $b1['code'] ?? null,
'hint' => ($s1 === 403)
? '對方可能關閉了來自伺服器成員的私訊,或與 Bot 不在同一伺服器。'
: null
], JSON_UNESCAPED_UNICODE);
exit;
}
$channel_id = $b1['id'] ?? null;
if (!$channel_id) {
http_response_code(500);
echo json_encode(['error' => '無法取得 channel_id', 'resp' => $b1], JSON_UNESCAPED_UNICODE);
exit;
}
// 2) 在該 channel 發送訊息
list($s2, $h2, $b2) = discord_post_json($api . '/channels/' . $channel_id . '/messages', $token, [
'content' => $message
]);
if (!in_array($s2, [200, 201])) {
http_response_code($s2 ?: 500);
echo json_encode([
'step' => 'send_message',
'status' => $s2,
'rate_limit_remaining' => $h2['X-RateLimit-Remaining'] ?? null,
'retry_after' => $h2['Retry-After'] ?? null,
'error' => $b2['message'] ?? 'unknown',
'code' => $b2['code'] ?? null
], JSON_UNESCAPED_UNICODE);
exit;
}
echo json_encode([
'ok' => true,
'channel_id' => $channel_id,
'message_id' => $b2['id'] ?? null
], JSON_UNESCAPED_UNICODE);
?>