浏览代码

feat: 命令汉化

kotoyuuko 1 周之前
父节点
当前提交
e3e4cd2260

+ 15 - 28
src/command/handlers/bookEvent.ts

@@ -22,13 +22,13 @@ export async function handleBookEvent(ctx: Context, env: Env): Promise<void> {
       // Get user credentials from KV storage
       const telegramUserId = ctx.from?.id.toString();
       if (!telegramUserId) {
-        await ctx.reply("Could not identify your Telegram user ID.");
+        await ctx.reply("无法获取你的 Telegram 用户身份");
         return;
       }
       
       const storedCredentials = await env.COSMOE_CREDENTIALS.get(telegramUserId);
       if (!storedCredentials) {
-        await ctx.reply("You need to login first using /login username password before booking events.");
+        await ctx.reply("请先使用 /login 命令登录后再进行预约");
         return;
       }
       
@@ -41,7 +41,7 @@ export async function handleBookEvent(ctx: Context, env: Env): Promise<void> {
       // Fetch event details to get time slots
       const eventResult = await cosmoeClient.getEventDetail(eventId);
       if (eventResult.code !== 200) {
-        await ctx.reply(`Event not found: ${eventResult.msg || 'Unknown error'}`);
+        await ctx.reply(`获取活动详情时出错: ${eventResult.msg || '未知错误'}`);
         return;
       }
       
@@ -51,14 +51,14 @@ export async function handleBookEvent(ctx: Context, env: Env): Promise<void> {
       const sortedSlots = [...event.slots].sort((a, b) => a.range.localeCompare(b.range));
       
       if (slotIndex < 0 || slotIndex >= sortedSlots.length) {
-        await ctx.reply(`Invalid slot number. Valid range is 0-${sortedSlots.length - 1}.`);
+        await ctx.reply(`无效的时间段编号,有效范围是 0 ~ ${sortedSlots.length - 1}`);
         return;
       }
       
       const selectedSlot = sortedSlots[slotIndex];
       
       if (selectedSlot.remaining <= 0) {
-        await ctx.reply(`Sorry, the selected slot (${selectedSlot.range}) is fully booked. No spots left.`);
+        await ctx.reply(`非常遗憾,你选中的时间段 (${selectedSlot.range}) 已满,没有空位了`);
         return;
       }
       
@@ -92,36 +92,23 @@ export async function handleBookEvent(ctx: Context, env: Env): Promise<void> {
         // Extract final price and booking ID from the response data if available
         const finalPrice = bookingResult.data?.final_price || selectedSlot.price;
         const bookingId = bookingResult.data?.id;
-        let successMessage = `Successfully booked event ${event.name} for slot ${selectedSlot.range}!`;
-        successMessage += `\nFinal Price: ¥${finalPrice}`;
+      
+        let successMessage = `成功预约活动 *${event.name}*,时间段 *${selectedSlot.range}*`;
+        successMessage += `\n*最终价格*  ¥${finalPrice}`;
         if (bookingId) {
-          successMessage += `\nBooking ID: ${bookingId}`;
+          successMessage += `\n*预约编号*  ${bookingId}`;
         }
         if (couponCode) {
-          successMessage += ` \n\(Used coupon: ${couponCode}\)`;
+          successMessage += ` \n*使用优惠码*  ${couponCode}`;
         }
-        await ctx.reply(successMessage);
+        await ctx.reply(successMessage, { parse_mode: "Markdown" });
       } else {
-        let errorMessage = `Booking failed: ${bookingResult.msg || 'Unknown error'}`;
-        if (couponCode) {
-          // Retry without coupon in case the coupon caused the failure
-          const retryResult = await cosmoeClient.bookEvent({
-            event_id: eventId,
-            time_slot: selectedSlot.range,
-          });
-          
-          if (retryResult.code === 200) {
-            await ctx.reply(`Successfully booked event ${event.name} for slot ${selectedSlot.range}! \(Original attempt failed with coupon, succeeded without coupon\)`);
-          } else {
-            await ctx.reply(errorMessage);
-          }
-        } else {
-          await ctx.reply(errorMessage);
-        }
+        let errorMessage = `预约失败: ${bookingResult.msg || '未知错误'}`;
+        await ctx.reply(errorMessage);
       }
     }
   } catch (error) {
-    console.error("Error handling booking request:", error);
-    await ctx.reply("An error occurred while processing your booking request. Please try again.");
+      console.error("Error handling booking request:", error);
+      await ctx.reply("处理预约请求时出错,请稍后再试")
   }
 }

+ 22 - 21
src/command/handlers/cancel.ts

@@ -21,13 +21,13 @@ export async function handleCancelCommand(ctx: Context, env: Env): Promise<void>
       // Get user credentials from KV storage
       const telegramUserId = ctx.from?.id.toString();
       if (!telegramUserId) {
-        await ctx.reply("Could not identify your Telegram user ID.");
+        await ctx.reply("无法获取你的 Telegram 用户身份");
         return;
       }
       
       const storedCredentials = await env.COSMOE_CREDENTIALS.get(telegramUserId);
       if (!storedCredentials) {
-        await ctx.reply("You need to login first using /login username password before canceling bookings.");
+        await ctx.reply("请先使用 /login 命令登录后再取消预约");
         return;
       }
       
@@ -38,7 +38,7 @@ export async function handleCancelCommand(ctx: Context, env: Env): Promise<void>
       cosmoeClient.setCredentials(credentialsObj.user_id, credentialsObj.token);
       
       if (!cosmoeClient.isAuthenticated()) {
-        await ctx.reply("❌ Invalid credentials. Please try logging in again with /login.");
+        await ctx.reply("无效的凭证,请尝试使用 /login 命令重新登录");
         return;
       }
       
@@ -46,39 +46,40 @@ export async function handleCancelCommand(ctx: Context, env: Env): Promise<void>
       const bookingsResult = await cosmoeClient.getMyBookings();
       
       if (bookingsResult.code !== 200 || !bookingsResult.data) {
-        await ctx.reply("❌ Could not retrieve booking details. Cannot proceed with cancellation.");
+        await ctx.reply("无法获取预约详情");
         return;
       }
       
       const booking = bookingsResult.data.find(b => b.id === bookingId);
       
       if (!booking) {
-        await ctx.reply(`❌ Booking ID ${bookingId} not found.`);
+        await ctx.reply(`预约 ID ${bookingId} 未找到`);
         return;
       }
       
       // Create confirmation keyboard
       const confirmationKeyboard = new InlineKeyboard()
-        .text('✅ Confirm Cancellation', `confirm_cancel_${bookingId}`)
+        .text('确认', `confirm_cancel_${bookingId}`)
         .row()
-        .text('❌ Cancel', 'cancel_action');
+        .text('取消', 'cancel_action');
       
       // Send confirmation message with inline keyboard
       await ctx.reply(
-        `Are you sure you want to cancel this booking?\n\n` +
-        `Event: ${booking.event_name}\n` +
-        `Date: ${booking.booking_date}\n` +
-        `Time: ${booking.time_slot}\n` +
-        `Status: ${booking.status}\n\n` +
-        `⚠️ This action cannot be undone.`,
+        `确认取消此预约?\n\n` +
+        `*活动*  ${booking.event_name}\n` +
+        `*日期*  ${booking.booking_date}\n` +
+        `*时间*  ${booking.time_slot}\n` +
+        `*状态*  ${booking.status}\n\n` +
+        `⚠️ 此操作无法撤销!`,
         {
+          parse_mode: "Markdown",
           reply_markup: confirmationKeyboard,
         }
       );
     }
   } catch (error) {
     console.error("Error handling cancel request:", error);
-    await ctx.reply("An error occurred while preparing the cancellation request. Please try again.");
+    await ctx.reply("处理取消预约请求时出错,请稍后再试");
   }
 }
 
@@ -92,13 +93,13 @@ export async function handleCancelConfirmation(ctx: Context, env: Env, action: s
       // Get user credentials from KV storage
       const telegramUserId = ctx.from?.id.toString();
       if (!telegramUserId) {
-        await ctx.editMessageText("Could not identify your Telegram user ID.");
+        await ctx.editMessageText("无法获取你的 Telegram 用户身份");
         return;
       }
       
       const storedCredentials = await env.COSMOE_CREDENTIALS.get(telegramUserId);
       if (!storedCredentials) {
-        await ctx.editMessageText("You need to login first using /login username password before canceling bookings.");
+        await ctx.editMessageText("请先使用 /login 命令登录后再取消预约");
         return;
       }
       
@@ -109,7 +110,7 @@ export async function handleCancelConfirmation(ctx: Context, env: Env, action: s
       cosmoeClient.setCredentials(credentialsObj.user_id, credentialsObj.token);
       
       if (!cosmoeClient.isAuthenticated()) {
-        await ctx.editMessageText("❌ Invalid credentials. Please try logging in again with /login.");
+        await ctx.editMessageText("无效的凭证,请尝试使用 /login 命令重新登录");
         return;
       }
       
@@ -117,15 +118,15 @@ export async function handleCancelConfirmation(ctx: Context, env: Env, action: s
       const cancelResult = await cosmoeClient.cancelBooking(bookingId);
       
       if (cancelResult.code === 200) {
-        await ctx.editMessageText(`✅ Successfully canceled booking ID: ${bookingId}`);
+        await ctx.editMessageText(`成功取消预约 ID: ${bookingId}`);
       } else {
-        await ctx.editMessageText(`❌ Failed to cancel booking: ${cancelResult.msg || 'Unknown error'}`);
+        await ctx.editMessageText(`取消预约 ID: ${bookingId} 失败: ${cancelResult.msg || '未知错误'}`);
       }
     } else if (action === 'cancel_action') {
-      await ctx.editMessageText('Cancellation has been canceled.');
+      await ctx.editMessageText('操作已取消');
     }
   } catch (error) {
     console.error("Error handling cancel confirmation:", error);
-    await ctx.editMessageText("An error occurred while processing your cancellation. Please try again.");
+    await ctx.editMessageText("处理取消预约请求时出错,请稍后再试");
   }
 }

+ 3 - 3
src/command/handlers/eventDetails.ts

@@ -16,8 +16,8 @@ export async function handleEventDetails(ctx: Context): Promise<void> {
       if (result.code === 200) {
         const event = result.data;
         let message = `*${event.name}*\n`;
-        message += `*日期* ${event.event_date}\n\n`;
-        message += `*时间段*\n`;
+        message += `📅 *日期* ${event.event_date}\n\n`;
+        message += `*时间段*\n`;
         
         if (event.slots && event.slots.length > 0) {
           // Check if today is the event day or before the event day (Beijing time)
@@ -47,7 +47,7 @@ export async function handleEventDetails(ctx: Context): Promise<void> {
           message += "没有可预约的时间段\n";
         }
         
-        message += `\n*封面图* ${event.cover_image_url}`;
+        message += `\n🖼️ *封面图* ${event.cover_image_url}`;
         
         await ctx.reply(message, { parse_mode: "Markdown" });
       } else {

+ 15 - 17
src/command/handlers/history.ts

@@ -6,14 +6,14 @@ export async function handleHistoryCommand(ctx: Context, env: any) {
     // Get user ID from context
     const userId = ctx.from?.id;
     if (!userId) {
-      await ctx.reply("❌ Unable to identify your account. Please try again.");
+      await ctx.reply("无法获取你的 Telegram 用户身份");
       return;
     }
 
     // Retrieve stored credentials for this user
     const credentials = await env.COSMOE_CREDENTIALS.get(userId.toString());
     if (!credentials) {
-      await ctx.reply("⚠️ You need to log in first. Please use /login command.");
+      await ctx.reply("请先使用 /login 命令登录");
       return;
     }
 
@@ -24,7 +24,7 @@ export async function handleHistoryCommand(ctx: Context, env: any) {
     cosmoeClient.setCredentials(credentialsObj.user_id, credentialsObj.token);
     
     if (!cosmoeClient.isAuthenticated()) {
-      await ctx.reply("❌ Invalid credentials. Please try logging in again with /login.");
+      await ctx.reply("无效的凭证,请尝试使用 /login 命令重新登录");
       return;
     }
 
@@ -32,37 +32,36 @@ export async function handleHistoryCommand(ctx: Context, env: any) {
     const bookingsResult = await cosmoeClient.getMyBookings();
     
     if (bookingsResult.code !== 200 || !bookingsResult.data) {
-      await ctx.reply("📋 No booking history found or failed to retrieve history.");
+      await ctx.reply("获取预约记录失败");
       return;
     }
 
     const bookings = bookingsResult.data;
 
     if (bookings.length === 0) {
-      await ctx.reply("📋 Your booking history is empty.");
+      await ctx.reply("你的预约记录为空");
       return;
     }
 
     // Format and send booking history
-    let historyMessage = `📖 *Your Booking History*\n\n`;
+    let historyMessage = `*预约记录*\n\n`;
     
     // Sort bookings by booking_date in descending order (most recent first) and take only the latest 10
     const sortedBookings = [...bookings]
       .sort((a, b) => new Date(b.booking_date).getTime() - new Date(a.booking_date).getTime())
-      .slice(0, 10);
+      .slice(0, 8);
 
     for (let i = 0; i < sortedBookings.length; i++) {
       const booking = sortedBookings[i];
           
-      historyMessage += `*${i + 1}. ${booking.event_name}*\n`;
-      historyMessage += `📅 Date: ${booking.booking_date}\n`;
-      historyMessage += `⏰ Time: ${booking.time_slot}\n`;
-      historyMessage += `💰 Price: ¥${booking.final_price}\n`;
-      historyMessage += `💳 Status: ${booking.status}\n`;
-      historyMessage += `🗓️ Created: ${booking.created_at}\n`;
+      historyMessage += `*[${booking.id}] ${booking.event_name}*\n`;
+      historyMessage += `📅 *日期*  ${booking.booking_date}\n`;
+      historyMessage += `⏰ *时间*  ${booking.time_slot}\n`;
+      historyMessage += `💰 *价格*  ¥${booking.final_price}\n`;
+      historyMessage += `💳 *状态*  ${booking.status}\n`;
           
       if (booking.notes_by_user) {
-        historyMessage += `📝 Note: ${booking.notes_by_user}\n`;
+        historyMessage += `📝 *备注*  ${booking.notes_by_user}\n`;
       }
           
       // Add cancel link for bookings that are not completed and have a future booking date (Beijing time)
@@ -86,10 +85,9 @@ export async function handleHistoryCommand(ctx: Context, env: any) {
       const beijingBookingDate = new Date(bookingDateTime.getTime() + beijingOffset);
             
       if (booking.status !== '已完成' && booking.status !== '已取消' && beijingBookingDate >= beijingTime) {
-        historyMessage += `🔗 Cancel: /cancel\\_${booking.id}\n`;
+        historyMessage += `🔗 *取消*  /cancel\\_${booking.id}\n`;
       }
           
-      historyMessage += `💳 Order ID: ${booking.payment_order_id}\n`;
       historyMessage += `\n`;
     }
 
@@ -104,6 +102,6 @@ export async function handleHistoryCommand(ctx: Context, env: any) {
     });
   } catch (error) {
     console.error('Error in handleHistoryCommand:', error);
-    await ctx.reply("❌ An error occurred while retrieving your booking history. Please try again later.");
+    await ctx.reply("获取预约记录时出错,请稍后再试");
   }
 }

+ 4 - 4
src/command/handlers/logout.ts

@@ -12,23 +12,23 @@ export async function handleLogoutCommand(ctx: Context, env: Env): Promise<void>
     // Get user ID from context
     const userId = ctx.from?.id;
     if (!userId) {
-      await ctx.reply("❌ Unable to identify your account. Please try again.");
+      await ctx.reply("无法获取你的 Telegram 用户身份");
       return;
     }
 
     // Check if credentials exist for this user
     const credentials = await env.COSMOE_CREDENTIALS.get(userId.toString());
     if (!credentials) {
-      await ctx.reply("⚠️ You are not logged in. No credentials to clear.");
+      await ctx.reply("请先使用 /login 命令登录");
       return;
     }
 
     // Delete the stored credentials
     await env.COSMOE_CREDENTIALS.delete(userId.toString());
 
-    await ctx.reply("✅ Successfully logged out. Your account information has been cleared from our system.");
+    await ctx.reply("成功登出,你的账户信息已从系统中清除");
   } catch (error) {
     console.error("Error handling logout request:", error);
-    await ctx.reply("❌ An error occurred while logging out. Please try again.");
+    await ctx.reply("登出时出错,请稍后再试");
   }
 }

+ 1 - 1
src/command/handlers/start.ts

@@ -2,5 +2,5 @@ import { Context } from "grammy";
 import { CosmoeClient } from "../../client/cosmoe";
 
 export async function handleStartCommand(ctx: Context): Promise<void> {
-  await ctx.reply("Welcome to CosMoe Bot! Available commands:\n/events - See latest events\n/login - Log in to your account\n/logout - Log out and clear your account information\n/history - View your booking history");
+  await ctx.reply("欢迎使用 甜奈摄影会 Telegram 机器人!\n\n可用命令:\n/events - 查看最新活动\n/login - 登录账户\n/logout - 登出并清除账户信息\n/history - 查看预约历史");
 }