PROJECT OVERVIEW

LINE Desk

เว็บจัดการบทสนทนาของ LINE Official Account

รับข้อความจากผู้ใช้ LINE เลือกห้องแชทแล้วตอบกลับในนาม Test Bot พร้อมอัปเดตข้อความและสถานะอ่านแบบ realtime

THE ASSIGNMENT

การแก้โจทย์

โจทย์คือสร้างเว็บแชทที่เชื่อมกับ LINE Official Account โดยเว็บนี้เป็นหน้าจอของผู้ดูแล OA ผู้ใช้ส่งข้อความหา Test Bot ผ่าน LINE แล้วผู้ดูแลเลือกผู้ใช้และตอบกลับผ่านเว็บ

ใช้ Next.js และ TypeScript

หน้าเว็บพัฒนาด้วย Next.js และ TypeScript แยก API เป็น NestJS เพื่อรับ webhook ส่งข้อความ และจัดการข้อมูล

รับข้อความจาก LINE

LINE ส่ง message event มายัง webhook ระบบบันทึกผู้ส่งและข้อความลง PostgreSQL แล้วส่ง Socket event ให้เว็บแสดงข้อความทันที

เลือกผู้ใช้และส่งข้อความกลับ

แสดงรายชื่อและประวัติแชทแยกตามผู้ใช้ เมื่อผู้ดูแลกดส่ง API จะเรียก LINE Messaging API ในนาม Test Bot แล้วบันทึกข้อความที่ส่งสำเร็จ

ส่งมอบและเผยแพร่

โค้ดอยู่ใน GitHub repository ที่ลิงก์ด้านบน ส่วน hosting โจทย์เดิมระบุ Vercel แต่แผนของโปรเจกต์นี้เปลี่ยนเป็น DigitalOcean สำหรับ Web, API และฐานข้อมูล

ผลลัพธ์คือผู้ดูแลเห็นว่าใครส่งข้อความมา เลือกห้องเพื่ออ่านและตอบกลับได้ พร้อมสถานะเพิ่มเพื่อนหรือบล็อก OA และจำนวนข้อความที่ยังไม่อ่าน

01 / TRY IT

ทดลองใช้งาน

  1. เพิ่มเพื่อน Test Bot

    ค้นหา @641heypb บน LINE หรือสแกน QR ด้านล่าง

    QR เพิ่มเพื่อน Test Bot @641heypb
  2. ส่งข้อความจาก LINE

    ข้อความจะเข้า API ผ่าน webhook แล้วเก็บในฐานข้อมูล

  3. เปิดเมนู Chat แล้วเลือกผู้ใช้

    อ่านข้อความและพิมพ์ตอบกลับ จากนั้นตรวจข้อความตอบบน LINE

02 / FEATURES

สิ่งที่ระบบทำได้

Users

ค้นหาผู้ใช้และดูสถานะเพิ่มเพื่อนหรือบล็อก OA ปิดพิมพ์และส่งให้ผู้ใช้ที่บล็อกแล้ว

Chat

แยกห้องตาม User ดูประวัติ รับและส่งข้อความ แสดงข้อความล่าสุดทันทีเมื่อเปิดห้อง

Unread

บันทึก unread รายผู้ใช้และ readAt รายข้อความ พร้อมยอดรวมใน sidebar เป็นสถานะอ่านร่วมของผู้ดูแลเว็บ

Realtime & cache

Socket connection เดียวต่อแท็บ อัปเดต React Query cache ข้ามหน้าโดยไม่ล้างข้อมูลระหว่างโหลดใหม่เบื้องหลัง

03 / ARCHITECTURE

โครงสร้างและเทคโนโลยี

Next.jsTypeScriptNestJSPostgreSQLSequelizeSocket.IOReact Queryshadcn/uiBun

apps/web เป็น Next.js ส่วน apps/api เป็น NestJS แยก package, dependencies และ Prettier ของแต่ละแอป รันด้วย Bun

ข้อมูลหลักอยู่ในตาราง line_users และ messages ใช้ UUID ภายใน ส่วน ID ของ LINE เก็บแยกไว้ใน lineUserId / lineMessageId

04 / MESSAGE FLOW

ข้อความเดินทางอย่างไร

รับเข้า

LINE → Webhook → บันทึก DB → Socket → อัปเดต cache และเว็บ

ส่งออก

เว็บ → API → LINE → บันทึก DB → Socket → อัปเดต cache และเว็บ

ข้อความขารับใช้ timestamp จาก LINE ขาส่งใช้เวลาเครื่องก่อนเรียก LINE API นาฬิกาเครื่อง API ต้องตรงกับเวลามาตรฐานเพื่อเรียงข้อความข้ามฝั่งได้ถูกต้อง

05 / UML & SEQUENCE

โครงสร้างข้อมูลและลำดับการทำงาน

ความสัมพันธ์ของ Sequelize model ใช้ UUID ภายในเป็น Primary Key และ Foreign Key ส่วน ID จาก LINE เก็บแยกไว้

กำลังวาด diagram…

06 / API

API ที่ใช้

Endpointหน้าที่
POST /api/webhookรับ event follow, unfollow และ message จาก LINE พร้อมตรวจ signature
GET /api/line-usersรายชื่อผู้ใช้ ค้นหาและกรองสถานะ ไม่มี pagination ผู้ใช้ที่บล็อก OA อยู่ท้ายรายการ
GET /api/conversationsรายการแชท JOIN ข้อความล่าสุด เรียงตาม lastMessageTime ถ้าไม่มีใช้เวลาสร้าง User
GET /api/messages?lineUserId=...ประวัติข้อความเฉพาะห้อง เรียงเก่าไปใหม่
POST /api/messagesส่งข้อความด้วย LINE User ID หลังสำเร็จจึงบันทึก DB และส่ง Socket
POST /api/conversations/:lineUserId/readอ่านเฉพาะ Message ID ที่ระบุ แล้วคำนวณ unread ที่เหลือ
07 / BEHAVIOR

รายละเอียดที่ควรรู้

  • เข้า /chat จะเห็น empty state ก่อน เลือกห้องจึงโหลดประวัติ เปลี่ยนห้องจะเรียก API ใหม่โดยใช้ cache แสดงระหว่างรอถ้ามี
  • ขณะรับหรือส่งข้อความใช้ Socket อัปเดต cache ส่วน follow/unfollow และ reconnect โหลดข้อมูลใหม่เบื้องหลัง
  • ทำเครื่องหมายอ่านเมื่อห้องเปิดในแท็บที่มองเห็นและมีโฟกัส ไม่ใช่สถานะอ่านในแอป LINE
  • ข้อความส่งผ่านเว็บนี้ถูกเก็บในระบบ ข้อความส่งจากแอป LINE OA โดยตรงไม่ได้เข้ามาเป็นประวัติในเว็บนี้