SaaS 없이 Bluesky 게시물을 예약하는 방법
저는 GitHub Actions와 JSONL 파일을 사용하여 매일 세 개의 Bluesky 게시물을 예약합니다. 외부 예약 서비스를 사용하지 않습니다.
이 시스템은 content/bluesky-queue.jsonl이라는 단일 파일을 사용하여 작동합니다.
이 파일의 각 줄은 JSON 객체입니다.
- 게시되지 않은 줄은 텍스트만 포함합니다.
- 게시된 줄에는 타임스탬프와 게시물 URI가 포함됩니다.
스크립트는 파일을 위에서 아래로 읽습니다. 타임스탬프가 없는 첫 번째 줄을 찾아 게시한 다음, 해당 줄을 업데이트합니다.
데이터베이스 대신 JSONL을 사용하는 이유:
- Git에서 변경 사항을 추적하기 쉽습니다.
- 어떤 CI 작업이든 파일에 새 줄을 추가할 수 있습니다.
- 설정을 단순하고 비용 없이 유지할 수 있습니다.
Bluesky API 요구 사항 처리
Bluesky는 링크와 해시태그를 위해 "facets"를 요구합니다. 단순히 텍스트만 보낼 수는 없습니다. 이러한 요소에 대한 정확한 바이트 위치를 제공해야 합니다.
저는 이러한 위치를 계산하기 위해 스크립트를 사용합니다. UTF-8 바이트 오프셋을 얻기 위해 TextEncoder를 사용합니다. 이렇게 하면 이모지를 사용할 때 발생하는 오류를 방지할 수 있습니다. 문자와 바이트는 서로 다르기 때문입니다.
GitHub Actions 최적화
정각에 작업을 예약하면 GitHub Actions가 늦게 실행되는 경우가 많습니다. 이를 해결하기 위해 저는 분 단위 오프셋을 사용합니다. 00:00 대신 23:37을 사용합니다. 이렇게 하면 지연을 줄일 수 있습니다.
또한 게시하기 전에 0분에서 5분 사이의 무작위 지연 시간을 추가합니다. 이는 게시 패턴을 더 사람처럼 보이게 만듭니다. 일부 알고리즘이 기피하는 정확한 기계적 타이밍을 피할 수 있습니다.
무한 루프 방지
스크립트가 큐를 업데이트할 때 변경 사항을 저장소에 다시 커밋합니다. 이로 인해 워크플로우가 다시 트리거될 수 있습니다.
저는 커밋 메시지 가드(guard)로 이 문제를 해결합니다:
- 스크립트는 커밋 메시지에
[skip bluesky-queue]를 추가합니다. - 워크플로우는 이 태그를 확인합니다.
- 태그가 존재하면 워크플로우는 실행되지 않습니다.
이 시스템은 AI 큐레이션 사이트를 활용한 장기 실험의 일부입니다. 가볍고, 저렴하며, 신뢰할 수 있는 상태를 유지합니다.
