分享NodeRed TTS,傳送訊息照片整合 2026/3版

2024/10分享第一篇Telegram開始到現在已經過去很久也改版過很多次
今天將目前能用的設定方式統一整合起來

一 安裝需要的整合以及服務

1.1 安裝通知軟體

Synology Chat設定方式請參考下方連結
[分享] Synology Chat設定
取得Telgram相關ID請參考下列之前的分享文章
[分享]Telegram 機器人創建token ID 以及群組創建ID 取得方法
因之前改版已經取消yaml設定方式
所以上面的舊文章只要創建好Telegram並取得Token以及ID即可
或者直接看下面內容是目前版本的設定方式
到系統 整合 搜尋Telegram



進去後選擇Telegram bot

依照內容先到botfather去新增機器人
便可以取得api token

輸入後便可以按傳送創建

沒問題的話就可以看到新建好的機器人了

至於怎麼創建群組跟取得群組ID請參考舊文章

再來就可以新增群組的ID

直接新增允許的聊天室ID

你創建好的機器人都會列出 選你的群組是屬於哪個機器人
我這邊沒有創群組所以是直接丟給機器人用的就是機器人的ID


也可以依照說明取得chat_id
注意 跟機器人的聊天ID是正數 如果是群組的會是負數
輸入後傳送即可
便可新增完成


可以看到群組或者是直接跟機器人聊天的ID是有差別的
在使用上要特別注意

1.2 安裝TTS軟體

因我都是用Edge 所以下面都是用Edge TTS來說明
Edge安裝可以參考我之前寫的舊文
Edge TTS Node-Red 亂數語音+亂數訊息分享

裝完這些就可以開始來設定了
如果都已經安裝可以直接跳過

二 NodeRed設定

因前段時間Telegram配合HA的更新改版一直在改發送的格式
相信各位應該都有收到通知

而我之前發放通知Flow都是個別處理導致要改的地方會一大堆

現在把格式統一整合到2個Function來處理
第1個Function負責處理要傳送格式
看是要傳送純文字,還是圖片, 還有TTS是否播放, 正常音量設定, 夜間時段音量設定。
第2個處理要傳送的格式內容

前Function 內容
請依照格式設定好相關內容


// ===== 0. Speaker 清單 =====
// 格式:entity_id / 白天音量 / 深夜音量
// 如果有多顆直接複製貼上修改 Speaker? 增加上去
//var Speaker? = {
//    entity_id: "實體ID", // 喇叭位置
//    normal_vol: 0.7,
//    nite_vol: 0.3
//};

// 自動組合 AllSpeakers
// 依照你的喇叭數量添加修改
var SpeakerMap = {
    Speaker1,
//    Speaker2,
//    Speaker3,
//    Speaker4,
//    Speaker5
};

// 此段不需動
var AllSpeakers = Object.values(SpeakerMap).filter(s =>
    s &&
    typeof s.entity_id === "string" &&
    s.entity_id.trim() !== ""
);

// ===== 0-1. Telegram 設定 =====
// 沒填實體資料為空有多組照格式加上即可
var Telegram1 = "notify.telegram_bot_你的實體ID";
var Telegram2 = "";
var Telegram3 = "";

// 判斷喇叭數量不需動
var Telegram_Entity_List = [Telegram1, Telegram2, Telegram3]
    .filter(v => typeof v === "string" && v.trim() !== "");

// ===== 0-2. 深夜時段設定 =====
// 例如 23:00 ~ 06:59 算深夜
var night_start_hour = 23;
var night_end_hour = 7;

// ===== 1. 設定抓取時間格式 =====
const now = new Date();
const pad = (num, len = 2) => num.toString().padStart(len, "0");

// date: yyyy-mm-dd_HH_MM_SS
const date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}_${pad(now.getMinutes())}_${pad(now.getSeconds())}`;

// date2: yyyy/mm/dd HH:MM:SS
const date2 = `${now.getFullYear()}/${pad(now.getMonth() + 1)}/${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;

// ===== 2. 隨機訊息內容 =====
var myArray = [
    //純文字訊息使用下方格式
    // "純文字訊息1",
    // "純文字訊息2"
    // 傳送的文字如果需要帶日期格式改用下列方式
    // `${date2}\n宿舍攝影機偵測到移動!`
];
var randomItem = myArray[Math.floor(Math.random() * myArray.length)];

// ===== 3. 隨機 TTS 語音 =====
var myVoice = [
//個人覺得edge tts好聽的語音,可依照自己喜好修改
    "zh-TW-HsiaoChenNeural",
    "zh-CN-XiaoxiaoNeural"
];
var randomVoice = myVoice[Math.floor(Math.random() * myVoice.length)];

// ===== 4. 這次通知設定 =====
var image_send = "no";   // 傳送照片 yes / no
var tts_send = "no";    // 使用TTS yes / no

// ===== 5. 圖片資料 =====
// 要用圖片就直接填完整路徑與網址
// 不用就留空字串
// var image_path = "";
// var image_url = "";
var image_path = `/config/www/image/snapshot_${date}.jpg`;
var image_url = `http://你的HAip:8123/local/image/snapshot_${date}.jpg`;

// ===== 6. TTS 設定 =====
// on = 全時 normal 音量
// nite = 深夜使用 nite_vol
// off = 深夜不播
var tts_night_mode = "on";

// tts_message 可和 message 不同
var tts_message = randomItem;

// 這裡可自由指定喇叭
// 全部播放:AllSpeakers
// 單顆播放:[Speaker1]
// 多顆指定:[Speaker1, Speaker2]
var tts_speakers = AllSpeakers;

// ===== 7. 若需要圖片,提供給 camera.snapshot / 舊流程相容用 =====
if (image_send === "yes" && image_path !== "") {
    msg.payload_snapshot = {
        filename: image_path
    };
}

// ===== 8. 統一輸出 notify 物件 =====
msg.notify = {
    message: randomItem,

    telegram_entity_list: Telegram_Entity_List,

    image_send: image_send,
    image_path: image_path,
    image_url: image_url,

    tts_send: tts_send,
    tts_voice: (tts_send === "yes") ? randomVoice : "",
    tts_speakers: (tts_send === "yes") ? tts_speakers : [],
    tts_night_mode: tts_night_mode,
    tts_message: (tts_send === "yes") ? tts_message : "",

    night_start_hour: night_start_hour,
    night_end_hour: night_end_hour
};

return msg;

後Function內容

// ===== 1. 讀取前面 Function 傳來的 notify 物件 =====
const notify = msg.notify || {};

const message = notify.message || "";
const telegram_entity_list = Array.isArray(notify.telegram_entity_list)
    ? notify.telegram_entity_list.filter(v => typeof v === "string" && v.trim() !== "")
    : [];

const image_send = notify.image_send || "no";
const image_path = notify.image_path || "";
const image_url = notify.image_url || "";

const tts_send = notify.tts_send || "no";
const tts_voice = notify.tts_voice || "";
const tts_speakers = Array.isArray(notify.tts_speakers) ? notify.tts_speakers : [];
const tts_night_mode = notify.tts_night_mode || "on";
const tts_message = notify.tts_message || message;

const night_start_hour = Number(notify.night_start_hour ?? 23);
const night_end_hour = Number(notify.night_end_hour ?? 7);

// ===== 2. 準備 5 個輸出 =====
let msg_telegram_photo = null;
let msg_telegram_text = null;
let msg_synology_chat = null;
let msg_set_volume = null;
let msg_tts = null;

// ===== 3. Telegram =====
// 多組 Telegram 會用 push 方式逐筆送出
if (telegram_entity_list.length > 0) {
    if (image_send === "yes" && image_path !== "") {
        let telegramPhotoMsgs = [];

        telegram_entity_list.forEach(id => {
            telegramPhotoMsgs.push({
                ...msg,
                payload_telegram_photo: {
                    entity_id: id,
                    file: image_path,
                    caption: message
                }
            });
        });

        if (telegramPhotoMsgs.length > 0) {
            msg_telegram_photo = telegramPhotoMsgs;
        }
    } else {
        let telegramTextMsgs = [];

        telegram_entity_list.forEach(id => {
            telegramTextMsgs.push({
                ...msg,
                payload_telegram_text: {
                    entity_id: id,
                    message: message
                }
            });
        });

        if (telegramTextMsgs.length > 0) {
            msg_telegram_text = telegramTextMsgs;
        }
    }
}

// ===== 4. Synology Chat =====
if (image_send === "yes" && image_url !== "") {
    msg_synology_chat = {
        ...msg,
        payload_synology_chat: {
            data: {
                file_url: image_url
            },
            message: message.replace(/%/g, "%25").replace(/&/g, "%26")
        }
    };
} else {
    msg_synology_chat = {
        ...msg,
        payload_synology_chat: {
            message: message
        }
    };
}

// ===== 5. TTS + 設定音量 =====
if (tts_send === "yes" && tts_speakers.length > 0) {
    const now = new Date();
    const hour = now.getHours();

    let isNight = false;

    if (night_start_hour > night_end_hour) {
        // 例如 23 -> 7,跨日
        isNight = (hour >= night_start_hour || hour < night_end_hour);
    } else if (night_start_hour < night_end_hour) {
        // 例如 1 -> 6,不跨日
        isNight = (hour >= night_start_hour && hour < night_end_hour);
    } else {
        // 相同代表整天都算夜間,通常不會這樣設
        isNight = true;
    }

    // off = 深夜不播
    if (!(tts_night_mode === "off" && isNight)) {

        // 5-1. 先產生多筆音量設定訊息
        let volumeMsgs = [];
        let ttsEntityList = [];

        tts_speakers.forEach(sp => {
            if (!sp || typeof sp.entity_id !== "string" || sp.entity_id.trim() === "") return;

            ttsEntityList.push(sp.entity_id);

            // 音量選擇邏輯
            let finalVol = null;

            if (isNight && tts_night_mode === "nite") {
                finalVol = sp.nite_vol;
            } else {
                finalVol = sp.normal_vol;
            }

            if (finalVol !== "" && finalVol !== null && finalVol !== undefined) {
                volumeMsgs.push({
                    ...msg,
                    payload_setvol: {
                        entity_id: sp.entity_id,
                        volume_level: Number(finalVol)
                    }
                });
            }
        });

        if (volumeMsgs.length > 0) {
            msg_set_volume = volumeMsgs;
        }

        // 5-2. 再產生 TTS 訊息(只會有一筆)
        if (ttsEntityList.length > 0) {
            msg_tts = {
                ...msg,
                payload_tts: {
                    media_player_entity_id: ttsEntityList,
                    message: tts_message,
                    cache: true,
                    options: {
                        volume: "+100%",
                        voice: tts_voice !== "" ? tts_voice : "zh-TW-HsiaoChenNeural",
                        pitch: "+0Hz",
                        rate: "+0%"
                    }
                }
            };
        }
    }
}

// ===== 6. 回傳 5 個輸出 =====
// Output 1: Telegram Photo(多筆)
// Output 2: Telegram Text(多筆)
// Output 3: Synology Chat
// Output 4: 設定音量(多筆)
// Output 5: TTS(單筆)
return [msg_telegram_photo, msg_telegram_text, msg_synology_chat, msg_set_volume, msg_tts];

相關節點設定
後Function因為有5個Output 所以輸出需要改成5

傳送Telegram圖片
Action 用 telegram_bot.send_photo
data 用 msg.payload_telegram_photo

傳送Telegram文字訊息
Action 用 notify.send_message
data 用 msg.payload_telegram_text

傳送Synology chat通知
Action 用 notify.synology_chat_bot
data 用 msg.payload_synology_chat

設定音量
Action 用 media_player.volume_set
data 用 msg.payload_setvol

設定TTS
Action 用 tts.speak
Target 需要選擇 Edge TTS
data 用 msg.payload_tts

這邊需要注意的是TTS前面有加一個延遲


主要是因為要先設定音量再去播放TTS所以要注意自己喇叭數量修改延遲的時間
我5顆喇叭設定1s 沒遇到問題
如果你比我多顆那就要注意觀察是否會造成音量還沒改就先播放了

以上為這次分享
個人認為還不是很完整
下版我將會針對傳送訊息的部分做修改
應該會納入HA Notify
傳送訊息的部分是否啟用
比如
是否啟用 Telegram 通知
是否啟用 Synology Chat 通知
是否啟用 HA Notify 通知
或者你有想要加的功能也可以留言
可以的話我會盡量加進來

本次都是透過 ChatGPT 一步一步弄出來的

新增 Ha Notify + iMessage 部分
並修改部分設定
新增 各類訊息是否傳送開關

iMessage傳送號碼設定及轉發關鍵詞

設定用Function

// ===== 0. 設定區 =====
// ===== 0-1. 通知 / 圖片 / TTS 設定 =====
// on = 啟用
// off = 停用
var Telegram = "on";
var Synology_Chat = "off";
var HA_Notify = "off";
var iMessage = "off";
var TTS = "off";

var image_send = "off";   // on / off

// ===== 0-2. 深夜時段設定 =====
// 例如 23:00 ~ 06:59 算深夜
var night_start_hour = 23;
var night_end_hour = 7;

// ===== 0-3. 播放時段設定 =====
// on = 全時 normal 音量
// nite = 深夜使用 nite_vol
// off = 深夜不播
var tts_night_mode = "on";

// ===== 0-4. Telegram 設定 =====
// 沒填實體資料為空,有多組照格式加上即可
var Telegram1 = "notify.telegram_bot_xxxxxxxxxx_xxxxxxxxx";
var Telegram2 = "";
var Telegram3 = "";

// 判斷實體數量不需動
var Telegram_Entity_List = [Telegram1, Telegram2, Telegram3]
    .filter(v => typeof v === "string" && v.trim() !== "");

// ===== 0-5. iMessage 設定 =====
// 直接填手機號碼即可,例如 09xxxxxxxx
var iMessage1 = "09xxxxxx";
var iMessage2 = "";
var iMessage3 = "";

// iMessage 關鍵字
// 實際送出時會變成:關鍵字 + 換行 + 訊息內容
var iMessage_Keyword = "HA通知";

// 判斷電話數量不需動
var iMessage_List = [iMessage1, iMessage2, iMessage3]
    .filter(v => typeof v === "string" && v.trim() !== "");

// ===== 0-6. Speaker 清單 =====
// 格式:entity_id / 白天音量 / 深夜音量
var Speaker1 = {
    entity_id: "media_player.你的喇叭1",
    normal_vol: 0.7,
    nite_vol: 0.3
};

//var Speaker2 = {
//    entity_id: "media_player.你的喇叭2",
//    normal_vol: 0.7,
//    nite_vol: 0.3
//};

//var Speaker3 = {
//    entity_id: "media_player.你的喇叭3",
//    normal_vol: 0.7,
//    nite_vol: 0.3
//};

//var Speaker4 = {
//    entity_id: "media_player.你的喇叭4",
//    normal_vol: 0.7,
//    nite_vol: 0.3
};

//var Speaker5 = {
//    entity_id: "media_player.你的喇叭5",
//    normal_vol: 0.7,
//    nite_vol: 0.3
//};

// 如果有多顆直接複製貼上修改 Speaker? 增加上去
// var Speaker6 = {
//     entity_id: "media_player.你的喇叭6",
//     normal_vol: 0.7,
//     nite_vol: 0.3
// };

// ===== 自動組合 AllSpeakers =====
// 依照你的喇叭數量添加 / 刪除
// 注意最後一顆喇叭不要加 ,
var SpeakerMap = {
    Speaker1
//    Speaker2,
//    Speaker3,
//    Speaker4,
//    Speaker5
    // Speaker6
};

// 此段不需動
var AllSpeakers = Object.values(SpeakerMap).filter(s =>
    s &&
    typeof s.entity_id === "string" &&
    s.entity_id.trim() !== ""
);

// ===== 1. 設定抓取時間格式 =====
const now = new Date();
const pad = (num, len = 2) => num.toString().padStart(len, "0");

// date: yyyy-mm-dd_HH_MM_SS
const date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}_${pad(now.getMinutes())}_${pad(now.getSeconds())}`;

// date2: yyyy/mm/dd HH:MM:SS
const date2 = `${now.getFullYear()}/${pad(now.getMonth() + 1)}/${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;

// ===== 2. 隨機訊息內容 =====
var msgArray = [
    // 純文字訊息使用下方格式
    // "純文字訊息1",
    // "純文字訊息2"

    // 傳送的文字如果需要帶日期格式可改用下列方式
    // `${date2}\n攝影機偵測到移動!`

    "請在這裡填入你的訊息內容"
];

var randomMSG = msgArray[Math.floor(Math.random() * msgArray.length)];

// ===== 3. 隨機 TTS 語音 =====
// 個人覺得 Edge TTS 好聽的語音,可依自己喜好修改
var myVoice = [
    "zh-TW-HsiaoChenNeural",
    "zh-CN-XiaoxiaoNeural"
];
var randomVoice = myVoice[Math.floor(Math.random() * myVoice.length)];

// ===== 4. 圖片資料 =====
// 要用圖片就直接填完整路徑與網址
// 不用就留空字串
// var image_path = "";
// var image_url = "";
var image_path = `/config/www/image/snapshot_${date}.jpg`;
var image_url = `http://你的HA_IP:8123/local/image/snapshot_${date}.jpg`;

// ===== 5. TTS 內容 / 喇叭 =====
// tts_message 可和 message 不同
var tts_message = randomMSG;

// 這裡可自由指定喇叭
// 全部播放:AllSpeakers
// 單顆播放:[Speaker1]
// 多顆指定:[Speaker1, Speaker2]
var tts_speakers = AllSpeakers;

// ===== 6. 若需要圖片,提供給 camera.snapshot / 舊流程相容用 =====
if (image_send === "on" && image_path !== "") {
    msg.payload_snapshot = {
        filename: image_path
    };
}

// ===== 7. 統一輸出 notify 物件 =====
msg.notify = {
    message: randomMSG,

    telegram_send: Telegram,
    telegram_entity_list: Telegram_Entity_List,

    synology_chat_send: Synology_Chat,

    ha_notify_send: HA_Notify,

    imessage_send: iMessage,
    imessage_list: iMessage_List,
    imessage_keyword: iMessage_Keyword,

    image_send: image_send,
    image_path: image_path,
    image_url: image_url,

    tts_send: TTS,
    tts_voice: (TTS === "on") ? randomVoice : "",
    tts_speakers: (TTS === "on") ? tts_speakers : [],
    tts_night_mode: tts_night_mode,
    tts_message: (TTS === "on") ? tts_message : "",

    night_start_hour: night_start_hour,
    night_end_hour: night_end_hour
};

return msg;

處理發送Funcion


因多加了 iMessage , HA notify所以output要改成7個


Switch 節點設定

屬性設為 notifyimage_send
判斷是否傳送照片套用不同的 iMessage 格式

iMessage action節點設定差別在 傳送照片還是文字而已


傳送照片部分會再改 等我找出正確方式
應該會改成傳送url 而不是傳送檔案
主要是 iPhone 捷徑不支援傳送檔案到 Line

HA notfiy 的 action 節點要注意如果是多部手機 請在後面加上去同樣設定的 action
主要原因是 Action 只能固定 沒辦法從 Function 帶入參數

我沒在用HA Notify 所以不要問我怎麼查歷史訊息 這我真不會

設定輸出方式 Function 內容

// ===== 1. 讀取 notify =====
const notify = msg.notify || {};

const message = notify.message || "";

// ===== 通知開關 =====
const telegram_send = notify.telegram_send || "off";
const synology_chat_send = notify.synology_chat_send || "off";
const ha_notify_send = notify.ha_notify_send || "off";
const imessage_send = notify.imessage_send || "off";
const tts_send = notify.tts_send || "off";

// ===== 其他資料 =====
const telegram_entity_list = Array.isArray(notify.telegram_entity_list)
    ? notify.telegram_entity_list.filter(v => typeof v === "string" && v.trim() !== "")
    : [];

const imessage_list = Array.isArray(notify.imessage_list)
    ? notify.imessage_list.filter(v => typeof v === "string" && v.trim() !== "")
    : [];

const imessage_keyword = notify.imessage_keyword || "";

const image_send = notify.image_send || "off";
const image_path = notify.image_path || "";
const image_url = notify.image_url || "";

const tts_voice = notify.tts_voice || "";
const tts_speakers = Array.isArray(notify.tts_speakers) ? notify.tts_speakers : [];
const tts_night_mode = notify.tts_night_mode || "on";
const tts_message = notify.tts_message || message;

const night_start_hour = Number(notify.night_start_hour ?? 23);
const night_end_hour = Number(notify.night_end_hour ?? 7);

// ===== 2. 準備輸出 =====
let msg_telegram_photo = null;
let msg_telegram_text = null;
let msg_synology_chat = null;
let msg_set_volume = null;
let msg_tts = null;
let msg_imessage = null;
let msg_ha_notify = null;

// ===== 3. Telegram =====
if (telegram_send === "on" && telegram_entity_list.length > 0) {

    if (image_send === "on" && image_path !== "") {
        msg_telegram_photo = {
            ...msg,
            payload_telegram_photo: {
                entity_id: telegram_entity_list,
                file: image_path,
                caption: message
            }
        };
    } else {
        msg_telegram_text = {
            ...msg,
            payload_telegram_text: {
                entity_id: telegram_entity_list,
                message: message
            }
        };
    }
}

// ===== 4. Synology Chat =====
if (synology_chat_send === "on") {

    if (image_send === "on" && image_url !== "") {
        msg_synology_chat = {
            ...msg,
            payload_synology_chat: {
                data: {
                    file_url: image_url
                },
                message: message.replace(/%/g, "%25").replace(/&/g, "%26")
            }
        };
    } else {
        msg_synology_chat = {
            ...msg,
            payload_synology_chat: {
                message: message
            }
        };
    }
}

// ===== 5. TTS =====
if (tts_send === "on" && tts_speakers.length > 0) {

    const now = new Date();
    const hour = now.getHours();

    let isNight = false;

    if (night_start_hour > night_end_hour) {
        isNight = (hour >= night_start_hour || hour < night_end_hour);
    } else if (night_start_hour < night_end_hour) {
        isNight = (hour >= night_start_hour && hour < night_end_hour);
    } else {
        isNight = true;
    }

    if (!(tts_night_mode === "off" && isNight)) {

        let volumeMsgs = [];

        tts_speakers.forEach(sp => {
            if (!sp || typeof sp.entity_id !== "string" || sp.entity_id.trim() === "") return;

            const vol = (tts_night_mode === "nite" && isNight)
                ? sp.nite_vol
                : sp.normal_vol;

            if (vol !== undefined && vol !== null && vol !== "") {
                volumeMsgs.push({
                    ...msg,
                    payload_setvol: {
                        entity_id: sp.entity_id,
                        volume_level: Number(vol)
                    }
                });
            }
        });

        if (volumeMsgs.length > 0) {
            msg_set_volume = volumeMsgs;
        }

        msg_tts = {
            ...msg,
            payload_tts: {
                media_player_entity_id: tts_speakers
                    .filter(s => s && typeof s.entity_id === "string" && s.entity_id.trim() !== "")
                    .map(s => s.entity_id),
                message: tts_message,
                cache: true,
                options: {
                    volume: "+100%",
                    voice: tts_voice || "zh-TW-HsiaoChenNeural",
                    pitch: "+0Hz",
                    rate: "+0%"
                }
            }
        };
    }
}

// ===== 6. iMessage =====
if (imessage_send === "on" && imessage_list.length > 0) {

    function formatPhone(num) {
        num = String(num).replace(/\D/g, "");

        if (num.startsWith("0")) {
            return "+886" + num.slice(1);
        }

        if (num.startsWith("886")) {
            return "+" + num;
        }

        if (num.startsWith("9")) {
            return "+886" + num;
        }

        return "";
    }

    function toBase64(str) {
        return Buffer.from(String(str), "utf-8").toString("base64");
    }

    let targets = imessage_list
        .map(p => formatPhone(p))
        .filter(p => p !== "");

    let imessage_text = message;
    if (imessage_keyword !== "") {
        imessage_text = `${imessage_keyword}\n${message}`;
    }

    if (targets.length > 0) {
        msg_imessage = targets.map(phone => ({
            ...msg,
            payload_imessage: {
                phone: phone,
                message_b64: toBase64(imessage_text),
                image_send: image_send,
                image_url: image_url
            }
        }));
    }
}

// ===== 7. HA Notify(out7)=====
if (ha_notify_send === "on") {

    let payload = {
        message: message
    };

    if (image_send === "on" && image_url !== "") {
        payload.data = {
            image: image_url
        };
    }

    msg_ha_notify = {
        ...msg,
        payload_ha_notify: payload
    };
}

// ===== 8. 回傳 7 個輸出 =====
// 1 Telegram Photo
// 2 Telegram Text
// 3 Synology Chat
// 4 Volume
// 5 TTS
// 6 iMessage
// 7 HA Notify
return [
    msg_telegram_photo,
    msg_telegram_text,
    msg_synology_chat,
    msg_set_volume,
    msg_tts,
    msg_imessage,
    msg_ha_notify
];

以上為本次補充 有問題可以提出