Skip to main content

การจัดการ Rich Menu

ภาพรวม​

Rich Menu คือเมนูรูปภาพที่แสดงอยู่ด้านล่างหน้าจอแชท LINE ระบบรองรับเมนูหลายประเภท (default, member, guest, custom) และสามารถผูกเมนูคนละแบบให้ผู้ใช้แต่ละคนได้

งานนี้เป็น consumer ที่รับคำสั่งเปลี่ยน ผูก และลบ rich menu แล้วไปเรียก LINE Rich Menu API จริง โดยใช้ queue เดียวคือ line_change_richmenu ซึ่งรองรับคำสั่งได้ 6 รูปแบบ แยกกันด้วยฟิลด์ type ใน payload

Business Flow​

Handler จะอ่านฟิลด์ type แล้วแตกไปยังสาขาการทำงานที่เกี่ยวข้อง

ค่า typeการทำงาน
memberchangeRichMenuFromWebhookId — กรณีผู้ใช้พิมพ์คำว่า "member" ในแชท ระบบจะ resolve OA จาก webhookId ค้นหา line_user เปลี่ยน user_type เป็น MEMBER แล้วผูก rich menu ประเภท member ให้ผู้ใช้รายนั้นผ่าน LINE API
setRichMenuMembersetRichMenuMemberByLineOaId — ผูก rich menu ประเภท member ให้สมาชิกทุกคนของ OA โดยทำงานเป็นชุด (chunk) และสร้าง CLS context ใหม่ต่อหนึ่ง message
setRichMenuMemberByLineUserIdผูก rich menu ให้ผู้ใช้ที่ระบุเป็นรายบุคคล
setRichMenuByTriggerRuleผูก rich menu ตามผลลัพธ์ของ trigger rule ซึ่งถูกสั่งมาจาก action switch_rich_menu
cronSetRichMenuCustomค้นหา rich menu ประเภท custom ที่มี status=active, complete_link_user=false และอยู่ในช่วงเวลา start_date <= now < end_date แล้วทยอยผูกให้สมาชิกกลุ่มเป้าหมาย เมื่อครบทุกคนจะ mark complete_link_user=true
deletedeleteRichMenu — unlink ผู้ใช้ทั้งหมด ลบ rich menu บน LINE แล้ว cascade สถานะไปยัง alias rich menu

หลักการที่ใช้ร่วมกันในทุกสาขา:

  • resolve channel_access_token ผ่าน LineOAResolver (คือ lineoa.Service ที่ทำหน้าที่ verify และ refresh token ให้) จากนั้นสร้าง LINE client แยกต่อ OA
  • การผูกผู้ใช้จำนวนมากจะถูกแบ่งเป็น chunk ด้วย chunkStrings เพื่อไม่ให้ยิง API รวดเดียว
  • ล้าง Redis cache ที่เกี่ยวข้องหลังการเปลี่ยนแปลงทุกครั้งด้วย delRedisAllCacheRelate
  • payload ที่ decode ไม่ได้จะคืน mq.Permanent เพื่อเข้า DLQ ทันที ส่วน type ที่ไม่รู้จักจะ return nil (ack เงียบ ๆ โดยไม่ retry)

ไฟล์และฟังก์ชันหลัก​

  • internal/richmenu/consumer.go — Consumer.HandleLineChangeRichMenu() ทำหน้าที่ dispatch ตามค่า type และ Register()
  • internal/richmenu/richmenu.go — Service, NewService(), enum typeOfRichMenuDefault/Member/Guest/Custom, chunkStrings(), delRedisAllCacheRelate()
  • internal/richmenu/service_methods.go — changeRichMenuFromWebhookId(), setRichMenuMemberByLineOaId(), setRichMenuMemberByLineUserId(), setRichMenuByTriggerRule(), deleteRichMenu()
  • internal/richmenu/service_cron.go — cronSetRichMenuCustom(), cronDeleteRichMenuCustom(), findRichMenuMemberLineUserIds(), cascadeStatusToAliasRichMenus()
  • internal/line/richmenu.go — LINE Rich Menu API client
  • cmd/worker/integration.go — จุด wiring ของ lineOaForRichMenu และ lineUserForRichMenu
  • Queue: line_change_richmenu (profile main)

จุดเชื่อมต่อกับ Service อื่น​

  • รับ job จาก: handler ของ line_webhook (กรณีผู้ใช้พิมพ์ "member"), cms-api-go โดเมน rich menu และ action executor ผ่าน action switch_rich_menu
  • ตารางที่เกี่ยวข้อง: rich_menu, rich_menu_action, rich_menu_archive, line_user (คอลัมน์ rich_menu_id และ user_type) และ line_oa
  • Redis: cache ของโดเมน rich menu โดยใช้ prefix ตามค่า MODULE_NAME
  • LINE API: create/delete rich menu, การ link ผ่าน POST /v2/bot/user/:userId/richmenu/:richMenuId, การ unlink และการจัดการ rich menu alias
  • สถิติการคลิกเมนูอยู่ในเอกสาร การคำนวณสถิติ Rich Menu