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