วิธีที่ผมใช้ตั้งเวลาโพสต์ Bluesky โดยไม่ต้องใช้ SaaS

ผมตั้งเวลาโพสต์ Bluesky วันละ 3 โพสต์ โดยใช้ GitHub Actions และไฟล์ JSONL ผมไม่ได้ใช้บริการตั้งเวลาภายนอกเลย

ระบบนี้ทำงานโดยใช้ไฟล์เพียงไฟล์เดียวคือ: content/bluesky-queue.jsonl

แต่ละบรรทัดในไฟล์นี้คือ JSON object

  • บรรทัดที่ยังไม่ได้โพสต์จะมีเพียงข้อความเท่านั้น
  • บรรทัดที่โพสต์แล้วจะมี timestamp และ post URI รวมอยู่ด้วย

สคริปต์จะอ่านไฟล์จากบนลงล่าง โดยจะหาบรรทัดแรกที่ไม่มี timestamp แล้วทำการโพสต์ จากนั้นจึงอัปเดตบรรทัดนั้น

ทำไมผมถึงใช้ JSONL แทนที่จะใช้ฐานข้อมูล:

  • ง่ายต่อการติดตามการเปลี่ยนแปลงใน Git
  • งาน CI ใดๆ ก็สามารถเพิ่มบรรทัดใหม่ต่อท้ายไฟล์ได้
  • ช่วยให้การตั้งค่าเรียบง่ายและไม่มีค่าใช้จ่าย

การจัดการข้อกำหนดของ Bluesky API

Bluesky ต้องการ "facets" สำหรับลิงก์และแฮชแท็ก คุณไม่สามารถส่งแค่ข้อความไปเฉยๆ ได้ แต่ต้องระบุตำแหน่งไบต์ (byte positions) ที่แน่นอนสำหรับองค์ประกอบเหล่านี้

ผมใช้สคริปต์ในการคำนวณตำแหน่งเหล่านี้ โดยใช้ TextEncoder เพื่อหาค่า UTF-8 byte offsets วิธีนี้จะช่วยป้องกันข้อผิดพลาดเมื่อมีการใช้ emoji เพราะจำนวนตัวอักษรและจำนวนไบต์นั้นไม่เท่ากัน

การเพิ่มประสิทธิภาพ GitHub Actions

GitHub Actions มักจะทำงานล่าช้าหากคุณตั้งเวลาทำงานไว้ที่ต้นชั่วโมงพอดี เพื่อแก้ปัญหานี้ ผมจึงใช้การตั้งเวลาแบบเลี่ยงนาที (off-minute offset) แทนที่จะเป็น 00:00 ผมจะใช้ 23:37 แทน ซึ่งช่วยลดความล่าช้าได้

นอกจากนี้ ผมยังเพิ่มการหน่วงเวลาแบบสุ่มระหว่าง 0 ถึง 5 นาทีก่อนการโพสต์ เพื่อให้รูปแบบการโพสต์ดูเหมือนมนุษย์มากขึ้น และหลีกเลี่ยงการใช้เวลาที่แม่นยำแบบเครื่องจักร ซึ่งอัลกอริทึมบางตัวอาจจะลดความสำคัญลง

การป้องกันการเกิด Infinite Loops

เมื่อสคริปต์อัปเดตคิว มันจะทำการ commit การเปลี่ยนแปลงกลับไปยัง repository ซึ่งอาจไปกระตุ้นให้ workflow ทำงานซ้ำอีกครั้ง

ผมแก้ปัญหานี้ด้วยการใช้ commit message guard:

  • สคริปต์จะเพิ่ม [skip bluesky-queue] ลงใน commit message
  • workflow จะตรวจสอบหาแท็กนี้
  • หากพบแท็กนี้ workflow ก็จะไม่ทำงาน

ระบบนี้เป็นส่วนหนึ่งของการทดลองระยะยาวกับเว็บไซต์ที่คัดสรรเนื้อหาโดย AI มันมีความคล่องตัว (lean) ราคาถูก และเชื่อถือได้

Source: https://dev.to/morinaga/how-i-schedule-three-daily-bluesky-posts-from-a-jsonl-queue-without-an-external-service-mno