Перейти до змісту

Черга з таблиці контенту

Таблиця — природне місце планувати контент з іншими людьми: по рядку на пост, стовпці для файлу, тексту, куди й коли. Цей рецепт читає таку таблицю й перетворює кожен рядок на queued пост. Він написаний для n8n, бо саме там більшість тримає такі потоки, з тими самими викликами у вигляді скрипта наприкінці. Стовпець файлу містить публічний https-URL (посилання на спільний диск, обʼєкт S3), тож кроком завантаження є POST /media/from-url, і жодні байти не проходять через робочий процес.

  • Платний тариф і ключ API зі write, збережений як credential Header Auth у n8n — імʼя Authorization, значення Bearer ds_live_xxxxxxxxxxxxxxxxxxxx — ніколи в тілі вузла.
  • Таблиця або CSV зі стовпцями file_url, text, title, accounts (id акаунтів через |, з GET /accounts), when (локальний час, 2026-09-29T18:00, читається в часовому поясі workspace), status (порожній, доки не готово).
  • n8n із вузлом Google Sheets або файл CSV.
Google Sheets: Read rows (status is empty)
→ HTTP Request: POST /media/from-url → mediaId
→ Wait 20 s → HTTP Request: GET /media/{{mediaId}} → loop until status = ready
→ HTTP Request: POST /posts/plan → stop the row if ok = false
→ HTTP Request: POST /posts (confirm: true) → post ids
→ Google Sheets: Update row (status = queued, post_ids)
  1. Прочитати рядки. Вузол Google Sheets, операція Get many rows, фільтр status порожній.

  2. Імпортувати файл. Вузол HTTP Request, POST https://api.dropslate.top/v1/media/from-url, credential Header Auth, тіло JSON:

    { "url": "{{ $json.file_url }}", "filename": "{{ $json.file_url.split('/').pop() }}" }

    Відповідь — { "mediaId": "med_…", "status": "processing" }.

  3. Дочекатися ready. Вузол Wait на 20 секунд, потім HTTP Request GET https://api.dropslate.top/v1/media/{{ $('Import').item.json.mediaId }}, потім вузол IF на {{ $json.status === 'ready' }}, що повертається до вузла Wait, коли false. Статус failed завершує рядок із failReason, записаним у таблицю.

  4. Спланувати. HTTP Request POST https://api.dropslate.top/v1/posts/plan, тіло:

    {
    "targets": { "accountIds": {{ JSON.stringify($('Read rows').item.json.accounts.split('|')) }} },
    "mediaIds": ["{{ $('Import').item.json.mediaId }}"],
    "title": "{{ $('Read rows').item.json.title }}",
    "text": "{{ $('Read rows').item.json.text }}",
    "when": { "publishAt": "{{ $('Read rows').item.json.when }}", "timezone": "Europe/Kiev" }
    }

    Вузол IF на {{ $json.ok }}: false спрямовує рядок на оновлення таблиці зі status = check і {{ $json.table }} у стовпці приміток — людина читає, який акаунт і чому.

  5. Створити. Те саме тіло плюс "confirm": true у POST https://api.dropslate.top/v1/posts. У відповіді є posts[]; запишіть {{ $json.posts.map(p => p.id).join('|') }} і status = queued назад у рядок.

Поставте Batching на вузлах плану і створення на один елемент на секунду: workspace дозволяє 60 POST /posts на годину, і таблиця зі 100 рядків інакше впреться в rate_limited на 61-му — повтор при невдачі у вузлі із заголовком Retry-After розбереться з рештою.

Terminal window
export KEY="ds_live_xxxxxxxxxxxxxxxxxxxx"; export API="https://api.dropslate.top/v1"; AUTH="Authorization: Bearer $KEY"
tail -n +2 posts.csv | while IFS=, read -r file_url text title accounts when; do
MEDIA=$(curl -s -X POST "$API/media/from-url" -H "$AUTH" -H "Content-Type: application/json" -d "{\"url\":\"$file_url\"}" | jq -r .mediaId)
until [ "$(curl -s "$API/media/$MEDIA" -H "$AUTH" | jq -r .status)" = "ready" ]; do sleep 10; done
BODY=$(jq -n --arg a "$accounts" --arg m "$MEDIA" --arg t "$text" --arg ti "$title" --arg w "$when" \
'{targets:{accountIds:($a|split("|"))}, mediaIds:[$m], text:$t, title:$ti, when:{publishAt:$w, timezone:"Europe/Kiev"}}')
PLAN=$(curl -s -X POST "$API/posts/plan" -H "$AUTH" -H "Content-Type: application/json" -d "$BODY")
[ "$(echo "$PLAN" | jq -r .ok)" = "true" ] || { echo "$PLAN" | jq -r .table; continue; }
curl -s -X POST "$API/posts" -H "$AUTH" -H "Content-Type: application/json" -d "$(echo "$BODY" | jq '.+{confirm:true}')" | jq -r '.posts[].statusLine'
done

Кожен рядок зі status = queued має пост у Календарі на свій when; GET /posts?status=queued перелічує їх із тим самим statusLine. Рядки з позначкою check — ті, які людині треба виправити — зазвичай текст понад ліміт мережі або файл, який тип контенту не приймає.

  • Стовпці тексту на мережу. Додайте text_threads, text_facebook і кладіть їх в overrides, коли не порожні.
  • Стовпець групи замість id акаунтів: "targets": {"groupId": "{{ $json.group }}"}.
  • Make або Zapier. Ті самі пʼять HTTP-викликів; Make і Zapier показують назви модуля й дії.