Skip to main content

Quick reply

ภาพรวม​

Quick reply คือชุดปุ่ม (chips) ที่ขึ้นเหนือช่องพิมพ์ข้อความบน LINE เมื่อผู้ใช้ได้รับข้อความจาก OA ผู้ดูแลสร้าง "ชุด quick reply" ไว้เป็นรายการกลางในเมนูนี้ แล้วให้เมนูอื่นมาเลือกใช้ซ้ำได้ ไม่ต้องตั้งปุ่มใหม่ทุกครั้งที่สร้างข้อความ

จุดสำคัญที่ต้องรู้ก่อนเริ่มคือ การอ้างอิงเป็นแบบอ้างอิงสด ไม่ใช่การคัดลอก — ข้อความที่ผูกชุด quick reply ไว้จะเก็บแค่ id ของชุดนั้น ไม่ได้ก็อปปี้ปุ่มไปเก็บไว้ในตัวเอง แก้ปุ่มที่นี่ครั้งเดียวจึงเปลี่ยนทุกข้อความที่อ้างอิงชุดนี้อยู่ทันที (ตรงตามคำอธิบายในฟอร์มว่า "การแก้ไขที่นี่จะอัปเดตทุกข้อความที่ใช้งานอยู่") และในทางกลับกัน การปิดใช้งานชุดหนึ่งก็ทำให้ปุ่มหายไปจากทุกข้อความที่ผูกไว้พร้อมกัน

อีกจุดที่ต้องรู้คือ ชุด quick reply ใช้ได้กับ Rich message เท่านั้น — ไม่ใช่กับ Template message แม้หน้าเว็บจะมีข้อความบางส่วนที่พูดถึง Template message อยู่ (ดูหัวข้อ รายละเอียดสำคัญ)

บทบาทที่ใช้งาน — ทีมคอนเทนต์และทีมที่ดูแลแชทของ LINE OA ที่เตรียมปุ่มตอบกลับไว้ให้ข้อความต่าง ๆ เรียกใช้ (โมดูลนี้ ไม่มี ModuleGate บังคับที่ backend ต่างจาก Rich message และ Auto-response message — ดูหัวข้อ สิทธิ์การเข้าถึง)

เส้นทางผู้ใช้งาน​

1. ดูรายการชุด quick reply​

เปิดเมนู ข้อความตอบกลับด่วน หน้ารายการเป็นตารางเดียว (ไม่มีแท็บ) เรียงจากใหม่ไปเก่าตามวันที่สร้าง คอลัมน์มี ลำดับ / ชื่อ / รายการ (จำนวนปุ่มในชุด) / สถานะ / การดำเนินการ ตัวกรองมี 2 ช่อง — ค้นหาจากชื่อ และเลือกสถานะ ค่าตัวกรองถูกจดจำไว้ใน sessionStorage

คอลัมน์ สถานะ เป็นสวิตช์ที่กดสลับได้จากหน้ารายการโดยตรง ไม่ต้องเข้าฟอร์ม แต่การกดปิดชุดที่ถูกใช้งานอยู่จะไม่ผ่านทันที (ดูขั้นตอนที่ 4)

2. สร้างชุด quick reply ใหม่​

  1. กดปุ่ม สร้างข้อความตอบกลับด่วน เข้าสู่ฟอร์มสองฝั่ง (ซ้ายกรอกข้อมูล ขวาดูตัวอย่าง chips)
  2. กรอกชื่อ — บังคับกรอก ไม่เกิน 255 ตัวอักษร
  3. เพิ่มปุ่มทีละรายการ — สูงสุด 13 ปุ่ม (ตรงกับเพดานของ LINE เอง) ตัวนับ n/13 แสดงอยู่มุมขวาของหัวข้อรายการ และปุ่ม เพิ่มรายการ จะถูกปิดเมื่อครบ 13
  4. เลือกชนิดปุ่มจาก 6 แบบ — ข้อความ, URI / ลิงก์, ตัวเลือกวันที่/เวลา, กล้อง, คลังภาพ, ตำแหน่งที่ตั้ง
    • ข้อความ — กรอกข้อความที่จะถูกส่งเข้าแชทแทนผู้ใช้เมื่อกดปุ่ม ช่องนี้เป็น autocomplete ที่ดึง keyword ของกฎที่ เปิดใช้งานอยู่ ในเมนู Auto-response message มาแนะนำ เพราะข้อความที่ปุ่มส่งกลับเข้าแชทจะไปกระตุ้นกฎตอบกลับอัตโนมัติได้จริง (เป็นคำแนะนำอย่างเดียว พิมพ์ค่าอื่นได้)
    • URI / ลิงก์ — ช่องเดียว มี placeholder บอกรูปแบบที่รับ https://... หรือ tel:... หรือ line://...
    • ตัวเลือกวันที่/เวลา — กรอกข้อมูล postback, เลือกโหมด (วันที่ / เวลา / วันที่และเวลา — ค่าเริ่มต้นคือวันที่และเวลา) และกำหนดค่าเริ่มต้น / ค่าต่ำสุด / ค่าสูงสุด ได้ (ไม่บังคับ)
    • กล้อง / คลังภาพ / ตำแหน่งที่ตั้ง — ไม่มีฟิลด์เพิ่มเติม ระบบขึ้นข้อความกำกับว่า "LINE จะเปิดกล้อง/ตัวเลือกตำแหน่งโดยตรงเมื่อแตะ"
  5. ทุกปุ่มต้องมี ป้ายชื่อ (label) ที่แสดงบน chip — ไม่เกิน 20 ตัวอักษร (ช่องกรอกมีตัวนับและตัดที่ 20 ให้เลย)
  6. จัดลำดับปุ่ม — ปุ่มลูกศรขึ้น/ลงในแต่ละการ์ด (ลูกศรขึ้นถูกปิดที่รายการแรก ลูกศรลงถูกปิดที่รายการสุดท้าย) ลำดับในฟอร์มคือลำดับที่ผู้ใช้ LINE จะเห็นจริง
  7. ดูตัวอย่าง chips แบบเรียลไทม์ ที่การ์ด "ตัวอย่างชิป" คอลัมน์ขวา ซึ่งตรึงตำแหน่งไว้ (Affix) ให้เห็นตลอดขณะเลื่อนแก้ไข
  8. เปิด/ปิดสวิตช์ สถานะ (ค่าเริ่มต้นเมื่อสร้างใหม่คือเปิดใช้งาน) แล้วกดบันทึก ระบบพากลับหน้ารายการ

การเปลี่ยนชนิดของปุ่มที่กรอกไว้แล้ว ระบบจะ ล้างฟิลด์เฉพาะชนิดทั้งหมดให้ใหม่ เก็บไว้แค่ป้ายชื่อ เพื่อไม่ให้ฟิลด์ของชนิดเก่าค้างติดไปกับชนิดใหม่ ซึ่ง backend จะปฏิเสธ (ดูหัวข้อรายละเอียดสำคัญ)

3. นำไปใช้ในเมนูอื่น​

  1. เปิดฟอร์มของ Rich message จะมีช่องเลือกชุด quick reply ที่โหลดเฉพาะชุดที่ เปิดใช้งานอยู่ (ดึงมาครั้งเดียว 100 รายการ ไม่แบ่งหน้า) พร้อมตัวเลือก "ไม่มี" อยู่บนสุด
  2. เลือกชุดแล้ว ระบบแสดง ป้ายชื่อของทุกปุ่มเป็น tag ใต้ช่องเลือกทันทีเพื่อยืนยันว่าเลือกถูกชุด และแสดง chips ในหน้าจอตัวอย่างแชทของข้อความนั้นด้วย
  3. หากข้อความนั้นอ้างอิงชุดที่ถูก ปิดใช้งาน ไปแล้ว ระบบจะดึงชุดนั้นมาแสดงเป็นตัวเลือกเพิ่มพร้อมป้าย "ปิดใช้งาน" และขึ้นคำเตือนว่า "จะไม่มีการส่งชิป" — ถ้าชุดนั้นถูก ลบ ไปแล้ว จะแสดงเป็น "ข้อความตอบกลับด่วนที่ไม่พร้อมใช้งาน" พร้อมคำเตือนให้เลือกรายการอื่น (ออกแบบไว้เพื่อไม่ให้หน้าเว็บโชว์ uuid เปล่า ๆ)

4. ปิดหรือลบชุดที่ถูกใช้งานอยู่​

ทั้งสองการกระทำถูกป้องกันด้วยกลไกเดียวกันที่ backend แต่ผลลัพธ์ต่างกันคนละแบบ:

  • ปิดใช้งาน — ระบบเปิดกล่องเตือน "ปิดใช้งานข้อความตอบกลับด่วนนี้หรือไม่?" พร้อม รายชื่อ Rich message ทุกตัวที่อ้างอิงอยู่ และคำอธิบายว่า "ข้อความเหล่านี้จะยังคงส่งต่อไป แต่จะไม่มีชิปของข้อความตอบกลับด่วนนี้" กดปุ่ม ปิดใช้งานต่อไป เพื่อยืนยัน (ระบบยิงคำขอซ้ำโดยแนบธง force ให้อัตโนมัติ) ถ้ากดยกเลิก สวิตช์จะถูกดึงกลับไปตรงกับค่าที่เซิร์ฟเวอร์เก็บไว้จริง ไม่ค้างอยู่ที่ค่าที่กดไป
  • ลบ — กล่องขึ้นหัวข้อ "ข้อความตอบกลับด่วนนี้ยังถูกใช้งานอยู่" พร้อมรายชื่อผู้อ้างอิงเหมือนกัน แต่ ไม่มีปุ่มยืนยันให้ทำต่อ มีแค่ปุ่มปิด ต้องไปแก้ Rich message ที่อ้างอิงให้เลิกใช้ชุดนี้ก่อน

ในหน้าฟอร์มแก้ไข (ไม่ใช่หน้าสร้าง) ยังมีการ์ด "ใช้งานโดย" ที่คอลัมน์ขวา แสดงรายชื่อผู้อ้างอิงให้เห็นล่วงหน้า ก่อน ที่จะกดปิดหรือลบ — ดึงจาก endpoint แยกที่ให้ผลชุดเดียวกับที่กลไกป้องกันใช้

รายละเอียดสำคัญที่ตรวจสอบจากซอร์สโค้ดจริง​

ยืนยันจาก internal/modules/quickreply/{controller,service,dto,items}.go ของ line-management-cms-api-go และ internal/quickreply/attach.go ของ line-management-worker-go:

  • ชนิด postback ถูกปิดไว้ที่ backend อย่างจงใจ และปิดไม่ให้เลือกที่หน้าเว็บด้วย — items.go ตรวจเจอ type: "postback" แล้วปฏิเสธด้วย 400 "postback is not currently supported" ทันที คอมเมนต์ในโค้ดอธิบายเหตุผลไว้ตรง ๆ ว่ายังไม่มีตัวจัดการ postback แบบทั่วไป (webhook มีแค่ prefix เฉพาะทางที่ hardcode ไว้) ปุ่ม postback จึงจะ "ยิงแล้วไม่ไปไหน" — โค้ดตรวจสอบของ postback ถูกเก็บไว้ครบเพื่อเปิดใช้ทีหลัง ฝั่งหน้าเว็บก็ตัด postback ออกจากรายการตัวเลือกด้วยเหตุผลเดียวกัน แต่ยังเก็บค่า constant และหน้าจอกรอกฟิลด์ postback ไว้เพื่อรองรับข้อมูลเก่าที่มีอยู่แล้ว
  • URI เป็น allowlist ที่ไม่มีการตรวจซ้ำฝั่งหน้าเว็บเลย — backend รับเฉพาะ https://, tel: และ line:// เท่านั้น (เทียบแบบไม่สนตัวพิมพ์เล็กใหญ่) http:// ถูก ปฏิเสธตรง ๆ ไม่ได้อัปเกรดให้เป็น https ส่วนฝั่งหน้าเว็บตรวจแค่ว่า "ช่อง URI ไม่ว่าง" ไม่ได้ตรวจ scheme เลย — พิมพ์ http://... ลงไปจะผ่านการตรวจในฟอร์มทั้งหมดแล้วไปตกที่ 400 ตอนกดบันทึก
  • การตรวจ items เป็น "closed shape" — ฟิลด์แปลกปลอมถูกปฏิเสธ ไม่ใช่ถูกละเลย — แต่ละชนิดอนุญาตชุดคีย์ของตัวเองเท่านั้น (นอกจาก type และ label ที่ทุกชนิดมีได้) ถ้ามีคี่ที่ไม่เข้าพวกจะได้ 400 ระบุตำแหน่งเป็นราย index เช่น property items[2].uri should not exist เป็นเหตุผลว่าทำไมหน้าเว็บต้องล้างฟิลด์เฉพาะชนิดทิ้งทุกครั้งที่เปลี่ยนชนิดปุ่ม
  • เพดานความยาวหลายค่าบังคับที่ backend เท่านั้น — label 1-20 ตัวอักษร (นับเป็น rune จึงนับอักษรไทยถูกต้อง), ข้อความของชนิด message ไม่เกิน 300, URI ไม่เกิน 1000, ข้อมูล postback ของ datetimepicker ไม่เกิน 300, ค่าเริ่มต้น/ต่ำสุด/สูงสุด ไม่เกิน 100 ต่อช่อง ในจำนวนนี้หน้าเว็บบังคับให้จริงแค่ label (ผ่าน maxLength ของช่องกรอก) และชื่อชุด 255 — เพดาน 300 ของช่องข้อความไม่มีการเตือนใด ๆ ในฟอร์ม
  • กลไกป้องกันตอนปิดใช้งานยิงเฉพาะการเปลี่ยนสถานะ active → inactive เท่านั้น — โค้ดตรวจสามเงื่อนไขพร้อมกัน (เดิมเปิดอยู่ + จะเปลี่ยนเป็นปิด + ไม่ได้ส่ง force) และ สแกนฐานข้อมูลเฉพาะเมื่อสามเงื่อนไขนี้ครบ เพื่อไม่ให้การแก้ชื่อหรือแก้ปุ่มธรรมดาต้องเสียเวลาสแกนโดยไม่จำเป็น การแก้ไขอื่นทั้งหมด (ปิด→ปิด, →เปิด, หรือแก้ชื่อ/ปุ่มเฉย ๆ) ไม่ถูกป้องกันเลย ส่วนธง force เป็น ฟิลด์ที่มีอยู่แค่ในคำขอ ไม่ถูกบันทึกลงฐานข้อมูล (คอมเมนต์ระบุชัดว่าไม่เคยไปถึงคำสั่ง update)
  • การสแกนหาผู้อ้างอิงดูตาราง rich_message ตารางเดียว และเป็นการตัดสินใจโดยเจตนา — คอมเมนต์ใน service.go อธิบายว่า template_message ไม่มีคอลัมน์ quick_reply_id เลย เพราะเทมเพลตไม่มีเส้นทางส่งออก LINE ของตัวเอง (flex ของมันถูกส่งในฐานะรายการหนึ่งของ Rich message เท่านั้น) ปุ่ม quick reply ที่ผูกกับเทมเพลตจึงจะไม่ทำงานอยู่ดี — ทั้งที่ไฟล์ข้อความหน้าเว็บยังมีป้าย "ข้อความเทมเพลต" เตรียมไว้เป็นแหล่งอ้างอิงชนิดหนึ่ง (ค่าที่ backend ไม่เคยส่งกลับมา)
  • worker ปฏิบัติกับชุดที่ถูกปิด/ลบ เหมือนกับ "ไม่มีชุดเลย" ไม่ถือเป็นข้อผิดพลาด — ตอนส่งจริง worker อ่าน SELECT items FROM quick_reply WHERE id = ? AND status = 'active' AND deleted_date IS NULL ถ้าไม่เจอแถวจะคืนค่าว่างเงียบ ๆ แล้ว ส่งข้อความออกไปโดยไม่มี chips ไม่ทำให้การส่งล้มเหลว (คอมเมนต์ระบุว่าเป็นพฤติกรรมที่ตั้งใจ: การปิดสวิตช์ต้องหยุด chips เงียบ ๆ ห้ามทำให้ส่งข้อความไม่ออก) และ chips ถูกแนบกับบับเบิลสุดท้ายของชุดข้อความเท่านั้น — Rich message ที่มี 5 รายการจะมี chips โผล่หลังรายการที่ 5
  • ปุ่มเรียงลำดับตามคอลัมน์ "ชื่อ" ในหน้ารายการไม่ทำงานจริง — ตารางฝั่งหน้าเว็บตั้ง sorter: true ที่คอลัมน์ชื่อและส่ง order/orderBy ไปกับคำขอ แต่ List ของโมดูลนี้ ไม่อ่านค่าทั้งสองเลย บังคับ ORDER BY created_date DESC ตายตัวทุกครั้ง กดหัวคอลัมน์แล้วลูกศรเปลี่ยนแต่ลำดับข้อมูลไม่เปลี่ยน
  • ตาราง quick_reply ไม่มี hook ลบแบบนุ่มนวลของ gorm — entity ไม่ได้ประกาศ gorm.DeletedAt ไว้ ทุก query ในโมดูลนี้จึงต้องเขียน deleted_date IS NULL ด้วยมือทุกครั้ง และการลบคือการประทับ deleted_date (soft delete) ข้อมูลยังอยู่ในฐานข้อมูล

เมนูที่เกี่ยวข้องกันในเส้นทางนี้​

  • Rich message — ผู้อ้างอิงชุด quick reply เพียงเมนูเดียวที่มีอยู่จริงในระบบ และเป็นตารางเดียวที่กลไกป้องกันการปิด/ลบสแกนหา
  • Auto-response message — keyword ของกฎที่ เปิดใช้งานอยู่ ในเมนูนั้นจะโผล่เป็นคำแนะนำในช่องข้อความของปุ่มชนิด "ข้อความ" ที่นี่ เพราะข้อความที่ปุ่มส่งกลับเข้าแชทสามารถไปกระตุ้นกฎตอบกลับอัตโนมัติได้จริง
  • Campaign — ไม่ได้เลือกชุด quick reply เองโดยตรง แต่ปุ่มที่ผูกกับ Rich message จะติดไปกับแคมเปญโดยอัตโนมัติเมื่อส่งออก
  • Template message — ไม่ รองรับการผูกชุด quick reply (ไม่มีคอลัมน์รองรับที่ฐานข้อมูล) ถ้าต้องการปุ่มพร้อมเทมเพลต ต้องผูกที่ระดับ Rich message ที่ห่อเทมเพลตนั้นอยู่

จุดที่ควรระวัง​

  • แก้ปุ่มที่นี่คือแก้ข้อความที่กำลังใช้งานอยู่ทันที — ไม่มีเวอร์ชันหรือการอนุมัติคั่นกลาง ทุก Rich message ที่อ้างอิงชุดนี้จะส่งปุ่มชุดใหม่ตั้งแต่การส่งครั้งถัดไป การ์ด "ใช้งานโดย" ในฟอร์มแก้ไขคือที่เดียวที่บอกว่ากำลังจะกระทบข้อความใดบ้าง
  • พิมพ์ http:// ในช่อง URI จะผ่านฟอร์มแต่ไม่ผ่านการบันทึก — ฟอร์มไม่ตรวจ scheme เลย ข้อผิดพลาดจะโผล่เป็น 400 ตอนกดบันทึกเท่านั้น
  • ข้อความของปุ่มชนิด "ข้อความ" ยาวเกิน 300 ตัวอักษรจะบันทึกไม่ผ่าน โดยที่ช่องกรอกไม่มีตัวนับหรือคำเตือนใด ๆ ล่วงหน้า
  • ปิดชุดที่ถูกใช้งานอยู่ = ปุ่มหายเงียบ ๆ ไม่มีข้อผิดพลาดที่ไหน — ข้อความยังส่งออกปกติ แต่ chips ไม่มา ไม่มี log แจ้งเตือนฝั่งผู้ใช้ ถ้าผู้ใช้แจ้งว่า "ปุ่มหายไป" ให้เช็กสถานะของชุดที่ผูกไว้ก่อนอื่น
  • ปุ่มเกิน 13 รายการถูกตัดทิ้งที่ worker ด้วยอีกชั้น — ทั้งฟอร์มและ backend กันไว้ที่ 13 แล้ว แต่ถ้าข้อมูลเก่ามีเกิน worker จะตัดเอาแค่ 13 ตัวแรกไปส่ง ไม่ปฏิเสธการส่ง
  • การกดเรียงลำดับตามชื่อไม่มีผล — รายการเรียงตามวันที่สร้างใหม่สุดขึ้นก่อนอยู่เสมอ ใช้ช่องค้นหาชื่อแทนถ้ามีชุดจำนวนมาก

สิทธิ์การเข้าถึง (ตรวจสอบจากซอร์สโค้ดจริง)​

  • ฝั่งหน้าเว็บ — ทั้งหน้ารายการและหน้าฟอร์มถูกครอบด้วย PermissionGuard ตรวจ action VIEW ของ subject quick-reply
  • ฝั่งเซิร์ฟเวอร์ — โมดูลนี้ไม่มี ModuleGate ต่างจาก Rich message (ModuleGate(d, "rich-message")), Template message และ Auto-response message ที่มีบังคับใช้จริง ทั้ง 6 เส้นทางของ quick reply ผูกไว้กับ auth.CheckPolicies(...) เท่านั้น ซึ่ง คอมเมนต์บนหัวไฟล์ controller.go ระบุตรง ๆ ว่าเป็น no-op ในวันนี้ ("auth.CheckPolicies is a no-op today — see internal/modules/auth/policy.go — but the metadata is kept for when enforcement is switched on") ผลคือผู้ใช้ที่ล็อกอินสำเร็จเรียก API ของ quick reply ได้ทุกเส้นทางแม้ผู้ดูแลระดับแพลตฟอร์มจะไม่ได้เปิดโมดูลใดให้ก็ตาม
  • การกันข้อมูลข้ามองค์กรเป็นการบังคับจริงเพียงชั้นเดียวที่มี — ทุก query ผูก line_oa_id จาก context ของผู้เรียกไว้ตายตัว การเรียก id ของ OA อื่นให้ผล 404 "Quick reply not found" ไม่ใช่ 403 (จึงไม่รั่วข้อมูลว่า id นั้นมีอยู่จริงหรือไม่)
  • policy annotation ระดับการกระทำมีประกาศครบทั้ง readAll/create/read/update/delete แต่วิ่งผ่าน middleware ที่เป็น no-op เหมือนกับโมดูลอื่นส่วนใหญ่ในระบบ — เก็บไว้เป็น metadata สำหรับวันที่เปิดบังคับใช้จริง
  • ไม่มีเส้นทางลบแบบถาวร (hard delete) และไม่มีเส้นทางที่ต้องเป็น Super Admin ในโมดูลนี้

ไฟล์อ้างอิงจากซอร์สโค้ด​

Frontend (cms-web-2026)

  • src/app/quick-reply/page.tsx, src/app/quick-reply/form/page.tsx — จุดเข้าหน้ารายการและฟอร์ม พร้อม PermissionGuard
  • src/components/quick-reply/list/quick-reply.container.tsx — ตาราง, สวิตช์สถานะ, การจัดการ 409 ของทั้งการปิดใช้งานและการลบ
  • src/components/quick-reply/form/quick-reply-form.tsx, quick-reply-form.container.tsx — กฎตรวจสอบฝั่งหน้าเว็บ, การ์ด "ใช้งานโดย", การยิงซ้ำด้วยธง force
  • src/components/quick-reply/form/quick-reply-items-editor.tsx — เพดาน 13 ปุ่ม, การล้างฟิลด์เมื่อเปลี่ยนชนิด, การจัดลำดับ
  • src/components/quick-reply/form/enums/quick-reply-item.enum.ts — รายการชนิดปุ่มที่เลือกได้ (และเหตุผลที่ตัด postback ออก)
  • src/components/quick-reply/QuickReplyPicker.tsx — ช่องเลือกชุดที่เมนูอื่นเรียกใช้ พร้อมการจัดการชุดที่ถูกปิด/ลบ
  • src/components/common/auto-response-keyword-autocomplete.tsx — คำแนะนำ keyword จากเมนู Auto-response message
  • src/services/quick-reply.service.ts — endpoint ทั้งหมดที่หน้าเว็บเรียกใช้
  • messages/th/quick-reply.json, messages/en/quick-reply.json — ข้อความ UI ทั้งหมด

Backend (line-management-cms-api-go)

  • internal/modules/quickreply/controller.go — 6 เส้นทาง และคอมเมนต์ที่ระบุว่า policy เป็น no-op
  • internal/modules/quickreply/service.go — CRUD, การผูก line_oa_id, กลไกป้องกันการปิด/ลบ, การสแกน rich_message
  • internal/modules/quickreply/dto.go — กฎตรวจสอบ name / status / ธง force
  • internal/modules/quickreply/items.go — closed shape ของปุ่มแต่ละชนิด, allowlist ของ URI, การปิด postback

Worker (line-management-worker-go)

  • internal/quickreply/attach.go — การอ่านชุดเฉพาะที่ active, การแปลงเป็นรูปแบบของ LINE, การแนบ chips กับบับเบิลสุดท้าย

ดูรายละเอียดเชิงเทคนิคเพิ่มเติม (เวอร์ชันก่อนหน้าของทีมเอกสาร) ที่ ข้อความตอบกลับด่วน (Quick Reply)