Linework Developers
AR
احصل على الوصول

دليل · comments:write

الرد على التعليقات

روبوت صغير يتحقق من التعليقات على أحدث منشوراتك ويجيب عن الجديدة منها، دون أن يجيب مرتين أبدًا.

نطاقات الصلاحية: posts:read وcomments:write (اختياري: likes:write).

نقاط النهاية#

نقطة النهايةالاستخدام
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. ردّ#

للرد على تعليق محدّد، مرّر معرّفه في 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 إعجاب لكل حساب.
  • لا تردّ إلا حيث يكون الرد مفيدًا. لا تنشر النص نفسه مرارًا وتكرارًا، ولا تعلّق على منشورات أشخاص لم يتفاعلوا معك قط.
  • عندما لا يكون الروبوت متأكدًا، فليلتزم الصمت وليترك شخصًا يجيب.