ใช้ Next.js และ TypeScript
หน้าเว็บพัฒนาด้วย Next.js และ TypeScript แยก API เป็น NestJS เพื่อรับ webhook ส่งข้อความ และจัดการข้อมูล
เว็บจัดการบทสนทนาของ LINE Official Account
รับข้อความจากผู้ใช้ LINE เลือกห้องแชทแล้วตอบกลับในนาม Test Bot พร้อมอัปเดตข้อความและสถานะอ่านแบบ realtime
โจทย์คือสร้างเว็บแชทที่เชื่อมกับ LINE Official Account โดยเว็บนี้เป็นหน้าจอของผู้ดูแล OA ผู้ใช้ส่งข้อความหา Test Bot ผ่าน LINE แล้วผู้ดูแลเลือกผู้ใช้และตอบกลับผ่านเว็บ
หน้าเว็บพัฒนาด้วย Next.js และ TypeScript แยก API เป็น NestJS เพื่อรับ webhook ส่งข้อความ และจัดการข้อมูล
LINE ส่ง message event มายัง webhook ระบบบันทึกผู้ส่งและข้อความลง PostgreSQL แล้วส่ง Socket event ให้เว็บแสดงข้อความทันที
แสดงรายชื่อและประวัติแชทแยกตามผู้ใช้ เมื่อผู้ดูแลกดส่ง API จะเรียก LINE Messaging API ในนาม Test Bot แล้วบันทึกข้อความที่ส่งสำเร็จ
โค้ดอยู่ใน GitHub repository ที่ลิงก์ด้านบน ส่วน hosting โจทย์เดิมระบุ Vercel แต่แผนของโปรเจกต์นี้เปลี่ยนเป็น DigitalOcean สำหรับ Web, API และฐานข้อมูล
ผลลัพธ์คือผู้ดูแลเห็นว่าใครส่งข้อความมา เลือกห้องเพื่ออ่านและตอบกลับได้ พร้อมสถานะเพิ่มเพื่อนหรือบล็อก OA และจำนวนข้อความที่ยังไม่อ่าน
ค้นหาผู้ใช้และดูสถานะเพิ่มเพื่อนหรือบล็อก OA ปิดพิมพ์และส่งให้ผู้ใช้ที่บล็อกแล้ว
แยกห้องตาม User ดูประวัติ รับและส่งข้อความ แสดงข้อความล่าสุดทันทีเมื่อเปิดห้อง
บันทึก unread รายผู้ใช้และ readAt รายข้อความ พร้อมยอดรวมใน sidebar เป็นสถานะอ่านร่วมของผู้ดูแลเว็บ
Socket connection เดียวต่อแท็บ อัปเดต React Query cache ข้ามหน้าโดยไม่ล้างข้อมูลระหว่างโหลดใหม่เบื้องหลัง
apps/web เป็น Next.js ส่วน apps/api เป็น NestJS แยก package, dependencies และ Prettier ของแต่ละแอป รันด้วย Bun
ข้อมูลหลักอยู่ในตาราง line_users และ messages ใช้ UUID ภายใน ส่วน ID ของ LINE เก็บแยกไว้ใน lineUserId / lineMessageId
LINE → Webhook → บันทึก DB → Socket → อัปเดต cache และเว็บ
เว็บ → API → LINE → บันทึก DB → Socket → อัปเดต cache และเว็บ
ข้อความขารับใช้ timestamp จาก LINE ขาส่งใช้เวลาเครื่องก่อนเรียก LINE API นาฬิกาเครื่อง API ต้องตรงกับเวลามาตรฐานเพื่อเรียงข้อความข้ามฝั่งได้ถูกต้อง
ความสัมพันธ์ของ Sequelize model ใช้ UUID ภายในเป็น Primary Key และ Foreign Key ส่วน ID จาก LINE เก็บแยกไว้
กำลังวาด diagram…
| 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 ที่เหลือ |