Linework Developers
RU
Получить доступ

Руководство · comments:write

Ответы на комментарии

Небольшой бот, который проверяет комментарии к вашим последним постам и отвечает на новые, никогда не отвечая дважды.

Scopes: posts:read и comments:write (необязательно: likes:write).

Endpoint#

EndpointНазначение
GET /me/postsВаши последние посты.
GET /posts/{id}/commentsКомментарии к посту (с пагинацией).
POST /posts/{id}/commentsНаписать комментарий или ответ.
DELETE /comments/{id}Удалить свой комментарий или комментарий к своему посту.
POST /posts/{id}/likeПоставить лайк посту.

1. Прочитайте комментарии#

curl "https://api.linework.app/open/v1/posts/1043/comments?limit=100" \
  -H "Authorization: Bearer $LINEWORK_API_KEY"
{
  "data": [
    {
      "id": "88121",
      "text": "Where is this?",
      "author": { "id": "5512", "username": "giulia" },
      "createdAt": "2026-10-14T09:30:00.000Z"
    }
  ],
  "next_cursor": null
}

2. Ответьте#

Чтобы ответить на конкретный комментарий, передайте его id в поле parentId; без него комментарий будет добавлен к самому посту.

curl https://api.linework.app/open/v1/posts/1043/comments \
  -H "Authorization: Bearer $LINEWORK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Lake Como, from Varenna 😊", "parentId": "88121" }'

3. Соберите всё вместе#

Запоминайте, на какие комментарии вы уже ответили (здесь — в локальном файле), и пропускайте собственные комментарии.

import { readFile, writeFile } from "node:fs/promises";

const API = "https://api.linework.app/open/v1";
const headers = {
  Authorization: `Bearer ${process.env.LINEWORK_API_KEY}`,
  "Content-Type": "application/json",
};
const get = (p) => fetch(API + p, { headers }).then((r) => r.json());

const seen = new Set(JSON.parse(await readFile("seen.json", "utf8").catch(() => "[]")));
const me = await get("/me");
const posts = await get("/me/posts?limit=10");

for (const post of posts.data) {
  const comments = await get(`/posts/${post.id}/comments?limit=100`);
  for (const c of comments.data) {
    if (seen.has(c.id) || c.author.id === me.id) continue;
    const reply = answer(c.text);
    if (reply) {
      await fetch(`${API}/posts/${post.id}/comments`, {
        method: "POST",
        headers,
        body: JSON.stringify({ text: reply, parentId: c.id }),
      });
    }
    seen.add(c.id);
  }
}
await writeFile("seen.json", JSON.stringify([...seen]));

function answer(text) {
  if (/where|dove/i.test(text)) return "Lake Como, from Varenna 😊";
  return null; // no canned answer: leave it to a human
}
import json, os, re, requests

API = "https://api.linework.app/open/v1"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['LINEWORK_API_KEY']}"

try:
    seen = set(json.load(open("seen.json")))
except FileNotFoundError:
    seen = set()

def answer(text):
    if re.search(r"where|dove", text, re.I):
        return "Lake Como, from Varenna 😊"
    return None  # no canned answer: leave it to a human

me = s.get(API + "/me", timeout=30).json()
posts = s.get(API + "/me/posts", params={"limit": 10}, timeout=30).json()
for post in posts["data"]:
    comments = s.get(f"{API}/posts/{post['id']}/comments", params={"limit": 100}, timeout=30).json()
    for c in comments["data"]:
        if c["id"] in seen or c["author"]["id"] == me["id"]:
            continue
        reply = answer(c["text"])
        if reply:
            s.post(f"{API}/posts/{post['id']}/comments",
                   json={"text": reply, "parentId": c["id"]}, timeout=30)
        seen.add(c["id"])

json.dump(sorted(seen), open("seen.json", "w"))

Запускайте его каждые несколько минут (cron, задача по расписанию, serverless-таймер). Каждый запуск выполняет лишь несколько запросов — намного меньше лимита в 120 в минуту.

Правила для ботов, работающих с комментариями#

  • Дневная квота: 300 комментариев и 500 лайков на аккаунт.
  • Отвечайте только там, где ответ полезен. Не публикуйте один и тот же текст снова и снова и не комментируйте посты людей, которые никогда с вами не взаимодействовали.
  • Если бот не уверен, пусть промолчит и оставит ответ человеку.