รายการเนื้อหาตามลิงก์ที่แชร์ (Content Link)
ภาพรวม
Content Link คือลิงก์ที่แอดมินสร้างขึ้นใน CMS โดยฝังตัวกรองไว้ล่วงหน้า ได้แก่ หมวดหมู่ หมวดหมู่ย่อย ช่วงวันที่ และ audience จากนั้นนำไปแปะใน rich menu หรือส่งในแชท เมื่อผู้ใช้เปิดลิงก์ ระบบจะแสดงหน้ารายการบทความที่ถูกกรองไว้เรียบร้อยแล้ว โดยฝั่ง client ไม่ต้องส่งพารามิเตอร์ตัวกรองใด ๆ มาเลย
นอกจากนี้ endpoint ยังทำหน้าที่นับ click_count ของลิงก์ เพื่อให้ CMS นำไปแสดงเป็นสถิติ
Business Flow
GET /api/public-content/links/:token/contents (rate limit 10/60s)
Query parameter ที่รับ ได้แก่ search (sanitize + ตรวจ pattern + ยาวไม่เกิน 100 ตัวอักษร เช่นเดียวกับหน้ารายการทั่วไป), page ค่าระหว่าง 1–100 และ limit ค่าระหว่าง 1–50
- ค้นหาแถว
content_linkที่ active ด้วย token — ไม่พบตอบ 404Content link not found or inactive validateLineOa(link.lineOaId)— OA ต้อง active มิฉะนั้นตอบ 404Invalid or inactive channel- หา audience ของผู้ใช้แบบ best-effort — หากมี header
x-liff-tokenจะ verify แต่ความล้มเหลวทุกกรณีจะถูกกลืนไว้แล้วทำงานต่อโดยไม่กรอง audience ซึ่งเป็น graceful degrade ไม่ใช่การปฏิเสธ - เรียก
IncrementClickCount(link.id)เพื่อนับคลิกก่อนดึงข้อมูล - ค่าเริ่มต้นคือ
page=1และlimit=10โดยskipที่เกิน 500 จะตอบ 400Page number exceeds maximum allowed - ประกอบตัวกรองจาก ค่าที่ฝังอยู่ในลิงก์ ไม่ใช่จาก query ได้แก่
categoryId,subcategoryId(ขยายเป็นลูกหลานทั้งหมด) และpublishedDateFrom/publishedDateToซึ่ง format เป็นรูปแบบ2006-01-02T15:04:05.000Z - บันได audience 3 ชั้น ตัดสินตามลำดับนี้
- หากลิงก์มี
audience_idsที่ไม่ว่าง จะกรองด้วย audience ของลิงก์ - มิฉะนั้น หากผู้ใช้มี audience จะกรองด้วย audience ของผู้ใช้
- มิฉะนั้นใช้
ApplyPublicOnlyคือแสดงเฉพาะบทความที่ไม่จำกัด audience
- หากลิงก์มี
- ค่า
searchจาก query ยังใช้ได้ โดยทำงานร่วมกับตัวกรองของลิงก์ - Hydrate translations และข้อมูลอ้างอิงหมวดหมู่ด้วย helper ชุดเดียวกับหน้ารายการทั่วไป
- ตอบกลับ
{linkInfo, data, total, page, limit, totalPages}โดยlinkInfoประกอบด้วยname,descriptionและข้อมูลหมวดหมู่/หมวดหมู่ย่อยซึ่ง resolve จาก id แบบไม่กรองเงื่อนไขเพิ่ม
ไฟล์และฟังก์ชันหลัก
| รายการ | ค่า |
|---|---|
| Route | GET /api/public-content/links/:token/contents (rate limit 10/60s) |
| Handler | internal/publiccontent/handler.go → (*Handler).GetContentsByLinkToken |
| Service | internal/publiccontent/service.go → (*Service).GetContentsByLinkToken |
| DTO | byLinkDTO รับ search, page, limit |
| Repository | internal/contentlink/repository.go → FindActiveByToken, IncrementClickCount |
| Entity | internal/contentlink/entity.go → ContentLink (audience_ids, category_id, subcategory_id, published_date_from, published_date_to, click_count) |
| Filter | internal/contentpage.ListFilter (LinkAudienceIDs, UserAudienceIDs, ApplyPublicOnly, SubcategoryIDs) |
| Response | ByLinkResponse และ linkInfo |
จุดเชื่อมต่อกับ Service อื่น
- ฐานข้อมูล — ตาราง
content_link,content_page,content_page_translation,content_category,content_subcategory,line_oaและline_user(สำหรับ audience) - LIFF authentication — เรียก
VerifyAndGetLineUserแบบ best-effort - ฟีเจอร์ที่เกี่ยวข้อง — ใช้ repository และ helper ร่วมกับ public content listing และเป็นปลายทางของ menu item ชนิด content link ผ่านค่า
contentLinkToken,contentLinkBehaviorและcontentLinkDisplayStyleในเมนูสาธารณะ - client-web — ตรงกับฟีเจอร์
content-link-listing