iT邦幫忙

0

Day 5:驗證並解析日期與時間輸入

  • 分享至 

  • xImage
  •  

一、今天的學習目標
延續昨天取得 /add 指令中 title、date、time 三個輸入值的功能,今天開始處理使用者輸入的日期與時間的格式是否有符合要求。我希望使用者在輸入日期與時間時只要輸入數字就好,然後系統會自己轉成可用的格式。
因此今天主要是圍繞在新增輸入格式驗證、字串切割,以及錯誤訊息的處理。

二、程式碼修改與問題處理
今天我想先替 /add 指令加入日期與時間的格式驗證。因為我希望使用者輸入日期時直接輸入 20260903,時間則輸入 1830,不需要自己加入 - 或 :,再由程式幫忙整理成後續比較好使用的格式。
因此我先分別替日期與時間建立格式規則。日期必須是 8 位數,時間必須是 4 位數。當格式不符合時,就直接回覆錯誤訊息並停止這次指令的執行,避免錯誤資料繼續往後處理。因此在修改了index.js裏面/add的部分。

if (interaction.commandName === 'add') {
    const title = interaction.options.getString('title');
    const date = interaction.options.getString('date');
    const time = interaction.options.getString('time');

    const dateRegex = /^\d{8}$/;
    const timeRegex = /^\d{4}$/;

    if (!dateRegex.test(date)) {
        await interaction.reply(
            '日期格式錯誤,請輸入 8 位數日期,例如 20260903'
        );
        return;
    }

    if (!timeRegex.test(time)) {
        await interaction.reply(
            '時間格式錯誤,請輸入 4 位數時間,例如 1830'
        );
        return;
    }

    const year = date.slice(0, 4);
    const month = date.slice(4, 6);
    const day = date.slice(6, 8);

    const hour = time.slice(0, 2);
    const minute = time.slice(2, 4);

    const formattedDate = `${year}-${month}-${day}`;
    const formattedTime = `${hour}:${minute}`;

    await interaction.reply(
        `行程名稱:${title}\n日期:${formattedDate}\n時間:${formattedTime}`
    );
}

我先在 /add 指令中取得使用者輸入的 title、date 和 time。接著我希望日期可以直接輸入像 20260903 這樣的 8 位數字,時間則輸入像 1830 這樣的 4 位數字,再由程式自行拆解並整理格式。
因此我先使用 Regex 檢查日期是否為 8 位數、時間是否為 4 位數。如果格式錯誤,就使用 interaction.reply() 回覆提示訊息,並利用 return 停止這次指令。格式正確的話,再使用 slice() 把日期拆成年、月、日,把時間拆成時、分,最後重新組合成 YYYY-MM-DD 與 HH:mm 的格式。

但後來發現,假如同時date跟time出現錯誤時,他只會顯示date格式錯誤。
https://ithelp.ithome.com.tw/upload/images/20260929/20184393716DMUSXHa.png
https://ithelp.ithome.com.tw/upload/images/20260929/20184393PeAF3vzNgD.png
我希望使用者在兩個欄位格式都輸入錯誤時能即時發現錯誤,而不是修改完一個後送出又發現另一個有問題。
因此我修改了處理錯誤格式那邊的邏輯。原本是在偵測到第一個錯誤後就會直接回覆並使用 return 結束程式,現在則先建立一個 errors 陣列,用來暫時儲存所有檢查到的錯誤訊息。這樣就可以等所有欄位都檢查完後一起回傳。

const errors = [];

      if (!dateRegex.test(date)) {
        errors.push("日期格式錯誤,請輸入 8 位數日期,例如 20260903");
      }

      if (!timeRegex.test(time)) {
        errors.push("時間格式錯誤,請輸入 4 位數時間,例如 1830");
      }

      if (errors.length > 0) {
        await interaction.reply(errors.join("\n"));
        return;
      }

三、今天修改檔案的完整程式碼
index.js

require("dotenv").config();

const { Client, Events, GatewayIntentBits } = require("discord.js");

const token = process.env.DISCORD_TOKEN;

if (!token) {
  console.error("錯誤:.env 裡還沒有設定 DISCORD_TOKEN");
  console.error("請先到 Discord Developer Portal 複製 Bot Token,然後在 .env 加上:");
  console.error("DISCORD_TOKEN=你的BotToken");
  process.exit(1);
}

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds
  ]
});

client.once(Events.ClientReady, () => {
  console.log(`Bot 已登入:${client.user.tag}`);
});

client.on(Events.InteractionCreate, async (interaction) => {
  try {
    if (!interaction.isChatInputCommand()) return;

    if (interaction.commandName === "ping") {
      await interaction.reply("Pong!");
      return;
    }

    if (interaction.commandName === "add") {
      const title = interaction.options.getString("title");
      const date = interaction.options.getString("date");
      const time = interaction.options.getString("time");

      const dateRegex = /^\d{8}$/;
      const timeRegex = /^\d{4}$/;
      const errors = [];

      if (!dateRegex.test(date)) {
        errors.push("日期格式錯誤,請輸入 8 位數日期,例如 20260903");
      }

      if (!timeRegex.test(time)) {
        errors.push("時間格式錯誤,請輸入 4 位數時間,例如 1830");
      }

      if (errors.length > 0) {
        await interaction.reply(errors.join("\n"));
        return;
      }

      const year = date.slice(0, 4);
      const month = date.slice(4, 6);
      const day = date.slice(6, 8);

      const hour = time.slice(0, 2);
      const minute = time.slice(2, 4);

      const formattedDate = `${year}-${month}-${day}`;
      const formattedTime = `${hour}:${minute}`;

      await interaction.reply(
        `行程名稱:${title}\n日期:${formattedDate}\n時間:${formattedTime}`
      );
    }
  } catch (error) {
    console.error("處理指令時發生錯誤:");
    console.error(error);

    const errorMessage = "程式發生錯誤,請看終端機錯誤訊息。";

    if (interaction.replied || interaction.deferred) {
      await interaction.followUp(errorMessage);
    } else {
      await interaction.reply(errorMessage);
    }
  }
});

client.login(token).catch((error) => {
  console.error("Bot 登入失敗,請檢查 Token 或網路連線。");
  console.error(error.message);
  process.exit(1);
});

*提醒邦友,使用第三方服務/API 時,請務必評估資安風險與隱私保護
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言