جميع الأدلة
الأدوات والإنتاجية

ملخص تقني يومي متعدد المصادر مع ترتيب AI وتوصيل Slack في n8n

سير n8n يسحب Hacker News و Dev.to و GitHub Trending بالتوازي كل صباح، يُلخص كل عنصر في جملة واحدة بالذكاء الاصطناعي، ثم يُرسل رسالة Slack بصيغة Block Kit بروابط قابلة للنقر. مُشغّل بجدول، يدمج ثلاثة أشكال بيانات، ويستخدم `gpt-5-mini` عبر الأرصدة المجانية.

16 دقيقة قراءة
٢٤ أبريل ٢٠٢٦
NerdLevelTech
2 مقالات مرتبطة
ملخص تقني يومي متعدد المصادر مع ترتيب AI وتوصيل Slack في n8n

{/* آخر تحديث: 2026-04-24 | بُني واستورد وحُفظ مباشرة على nerdleveltech.app.n8n.cloud | gpt-5-mini + أرصدة مجانية */}

12 عقدة، 3 مصادر بيانات متوازية، خطوة تلخيص AI واحدة، حمولة Slack Block Kit واحدة — وُصلت وحُفظت على n8n cloud. استورد، بدّل رابط Slack webhook العام (الخطوة 6)، وجدول. لقطات التنفيذ أدناه تعرض البيانات تتدفق عبر مُلخص AI.

⚠️ قبل التفعيل: عقدة Post to Slack Webhook تأتي برابط placeholder (https://hooks.slack.com/services/REPLACE/WITH/YOUR_WEBHOOK). أول تشغيل مجدول سيفشل بـ 404 إذا لم تستبدله. انظر الخطوة 6 لإجراء الاستبدال الدقيق.

ما الذي ستبنيه

سير n8n مُشغّل بجدول يومي:

  • يعمل كل صباح الساعة 8 (UTC افتراضياً، قابل للضبط)
  • يجلب أهم 5 عناصر بالتوازي من ثلاثة مصادر: صفحة Hacker News الأولى، أفضل مقالات Dev.to، مستودعات GitHub المُنشأة في آخر 48 ساعة مرتبة بالنجوم
  • يُطبّع كل شكل إلى كائن مشترك { source, title, url, score, summary_seed }
  • يستخدم Summarization Chain من LangChain لكتابة ملخص جملة واحدة لكل عنصر
  • يبني رسالة Slack Block Kit بأقسام مُجمّعة وروابط قابلة للنقر وفواصل
  • يُرسل POST إلى Slack Incoming Webhook — بدون OAuth
سير الملخص متعدد المصادر الكامل: Schedule ← 3 HTTP متوازية ← 3 عقد Normalize Code ← Merge ← Summarize Each ← Combine ← Format Slack Blocks ← Post to Slack

تخطَّ البناء — استورد السير


المتطلبات المسبقة

المتطلبالتفاصيل
حساب n8nتجربة مجانية 14 يوماً
أرصدة OpenAI100 مجانية تغطي شهور من التشغيلات اليومية
مساحة عمل Slackتحتاج صلاحيات admin لتثبيت Incoming Webhook
الوقتحوالي 20 دقيقة

الخطوة 1 — استيراد السير

أنشئ سير جديد، ألصق JSON على اللوحة الفارغة. يُحمل n8n 12 عقدة. يبدو هكذا:

Schedule ──┬─→ HN Fetch   ─→ Normalize HN
           ├─→ Dev.to     ─→ Normalize Dev.to    ──┐
           └─→ GitHub     ─→ Normalize GitHub    ──┼─→ Merge → Summarize Each → Combine → Format Slack → POST
                                                  ──┘

انقر نقراً مزدوجاً على OpenAI Chat Model، وتحقق من بيانات n8n المجانية و gpt-5-mini بدرجة حرارة 0.3 (منخفضة — نريد مخرجات جملة واحدة متسقة).


الخطوة 2 — فهم المصادر الثلاثة

المصدرنقطة النهايةالمصادقةيُعيد
Hacker Newshn.algolia.com/api/v1/search?tags=front_page&hitsPerPage=5بدونhits[] مع title و url و points
Dev.todev.to/api/articles?top=1&per_page=5بدونمصفوفة عادية مع title و url و positive_reactions_count
GitHubapi.github.com/search/repositories?q=created:>{date}&sort=stars&order=desc&per_page=5بدون (محدود)items[] مع full_name و html_url و stargazers_count و description

رابط GitHub يستخدم تعبير n8n: {{ $now.minus({days: 2}).toFormat('yyyy-MM-dd') }} — يبني سلسلة تاريخ لـ"قبل يومين" في وقت التشغيل لتحصل دائماً على أحدث المستودعات.


الخطوة 3 — تطبيع كل مصدر

ثلاث عقد Code تحول كل مصدر إلى نفس شكل الكائن. مثلاً Normalize HN:

const hits = $input.first().json.hits || [];
return hits.map(h => ({
  json: {
    source: 'Hacker News',
    title: h.title,
    url: h.url || `https://news.ycombinator.com/item?id=${h.objectID}`,
    score: h.points || 0,
    summary_seed: (h.story_text || '').slice(0, 400)
  }
}));

summary_seed يُعطي AI سياقاً للعناصر التي تفتقد لجسم URL (Show HN أو Ask HN). URL الاحتياطي (news.ycombinator.com/item?id=...) يضمن أن عناصر Ask HN لا تزال قابلة للنقر.

Normalize Dev.to يقرأ description إلى summary_seed. Normalize GitHub يقرأ description السطر الواحد للمستودع.

بعد هذه الخطوة، كل العناصر الـ 15 (5 × 3) لها بنية متطابقة — لا عقدة لاحقة تحتاج لمعرفة من أي مصدر جاءت.


الخطوة 4 — الدمج والتلخيص

عقدة Merge

مضبوطة على mode: append. تأخذ 3 تدفقات مدخلة (عقد Normalize الثلاث) وتُخرج قائمة مُجمعة واحدة من 15 عنصراً بترتيب المصدر.

Summarization Chain

السلسلة تشتغل مرة لكل عنصر. المطالبة مُدمجة في combineMapPrompt للعقدة:

⚠️ اختلاف نحوي مهم: مطالبة Summarization Chain تستخدم متغير قالب LangChain {text} وليس تعبيرات n8n {{ $json.x }}. السلسلة الافتراضية تُغذي محتوى كل عنصر مدخل تلقائياً كـ {text} في المطالبة. إذا احتجت الوصول لحقول أخرى ($json.title و $json.url)، أنظف حل هو استبدال Summarization Chain بـ Basic LLM Chain (chainLlm) — تلك العقدة تُبدل تعبيرات n8n مثل ما يفعل دليل 1. واجهنا هذا في اختبارنا الحقيقي: مع {{ $json.title }} حرفياً في مطالبة Summarization Chain، أعاد النموذج placeholders بأسلوب القوالب الخاصة به بدلاً من ملخص حقيقي. استخدم Basic LLM Chain إلا إذا احتجت تحديداً map-reduce على مستندات طويلة جداً.

Source: {{ $json.source }}
Title: {{ $json.title }}
URL: {{ $json.url }}
Score/engagement: {{ $json.score }}
Context: "{{ $json.summary_seed }}"

Write ONE crisp sentence (≤ 25 words) that tells a busy developer what this
is and why it matters TODAY. Lead with the concrete thing, not with "This
story is about...". If it is a GitHub repo, mention the language or primary
domain. No hedging.

كل عنصر يحصل على استدعاء API واحد إلى gpt-5-mini. التكلفة اليومية الإجمالية: ~0.005$ (أقل بكثير من 100 رصيد مجاني).

عرض تفاصيل عقدة Summarize Each بعد تنفيذ حقيقي: اللوحة اليسرى تعرض العناصر المدموجة من Hacker News و Dev.to و GitHub بحقول source و title و url و score و summary_seed، اللوحة اليمنى تعرض مخرجات الملخص بجملة واحدة من gpt-5-mini — دليل نجاح السلسلة

أعلاه: عقدة Summarize Each مفتوحة بعد تنفيذ حقيقي — اللوحة اليسرى المُدخل المدموج من المصادر الثلاثة، اللوحة اليمنى ملخصات الجملة الواحدة التي أنتجتها gpt-5-mini.

Combine Items

عقدة Code تُجمِّع العناصر المُلخصة حسب المصدر:

const bySource = {};
items.forEach(it => {
  const src = it.json.source || 'Other';
  bySource[src] = bySource[src] || [];
  bySource[src].push({
    summary: (it.json.output || it.json.response?.text || it.json.text || '').trim(),
    url: it.json.url,
    title: it.json.title,
    score: it.json.score
  });
});

الاحتياطي الثلاثي it.json.output || it.json.response?.text || it.json.text يتعامل مع أشكال مخرجات التلخيص لثلاث إصدارات n8n. احتفظ به — التكلفة مقارنة حرف واحد، والفائدة توافق مستقبلي.


الخطوة 5 — تنسيق Slack Block Kit

انقر نقراً مزدوجاً على Format Slack Blocks. عقدة Code تبني حمولة Block Kit الرسمية من Slack — JSON منظم يعرض كبطاقات غنية، ليس نصاً عادياً.

const blocks = [
  { type: 'header', text: { type: 'plain_text', text: `🧠 Daily Tech Digest — ${date}` } },
  { type: 'context', elements: [{ type: 'mrkdwn', text: `Merged from ${Object.keys(bySource).length} sources` }] },
  { type: 'divider' }
];
Object.entries(bySource).forEach(([src, items]) => {
  blocks.push({ type: 'section', text: { type: 'mrkdwn', text: `*${src}*` } });
  items.forEach(i => {
    const scoreStr = i.score ? ` _(${i.score})_` : '';
    blocks.push({ type: 'section', text: { type: 'mrkdwn', text: `• <${i.url}|${i.title}>${scoreStr}\n${i.summary}` } });
  });
  blocks.push({ type: 'divider' });
});

النتيجة: رأس قسم بالخط العريض لكل مصدر، كل عنصر على سطر خاص به بعنوان قابل للنقر وملخص AI أسفله. النقاط تُعرض بالخط المائل _(312)_.

لماذا Block Kit مقابل النص العادي؟ رسائل النص العادي تقطع العناوين عند الروابط الطويلة ولا تُعرض قابلة للنقر. صيغة <url|text> في Block Kit تُعطيك تسميات روابط قابلة للنقر وتجميع وفواصل وتذييلات سياق.


الخطوة 6 — توصيل Slack Webhook

6أ. إنشاء webhook في Slack

  1. افتح Slack في متصفح ← اضغط اسم مساحة العمل أعلى اليسار ← Settings & administrationManage apps
  2. ابحث "Incoming Webhooks"Add to Slack
  3. اختر القناة التي تريد نشر الملخص عليها (مثلاً #ai-digest)
  4. اضغط Add Incoming WebHooks integration — Slack يُعطيك رابطاً مثل https://hooks.slack.com/services/T01.../B02.../abc123
  5. انسخ الرابط

6ب. اللصق في السير

انقر نقراً مزدوجاً على Post to Slack Webhook في n8n. استبدل placeholder الـ URL:

https://hooks.slack.com/services/REPLACE/WITH/YOUR_WEBHOOK

…برابط webhook الحقيقي. احفظ السير.

6ج. اختبره

اضغط Execute workflow على اللوحة. السير يشتغل عبر العقد الـ 12 وينشر على قناة Slack. إذا كان كل شيء صحيحاً، تحصل على رسالة غنية تبدو كنشرة مُنسقة — المصادر مفصولة، الروابط قابلة للنقر، ملخصات AI تحت كل عنصر.

إذا لم تصل رسالة Slack:

  • افتح سجل التنفيذ ← اضغط عقدة Post to Slack Webhook ← افحص رمز استجابة HTTP. 200 = نجاح. 400 = JSON تالف (عادة حقل text احتياطي مفقود).
  • تحقق من القناة التي تم تثبيت webhook عليها — لا يمكنك إعادة توجيه webhook بدون تثبيت واحد جديد.

التوسعات: البريد و Teams و Discord والتخصيص

البريد الإلكتروني بدلاً من Slack

استبدل Post to Slack Webhook بعقدة Gmail (تحتاج OAuth لحساب Google). اعمل خريطة:

  • To ← بريدك الإلكتروني
  • Subject🧠 Daily Tech Digest — {{ $json.text }}
  • Body (HTML) ← حوّل blocks من Slack إلى HTML بعقدة Code صغيرة قبل هذه الخطوة

Microsoft Teams

Teams يقبل Adaptive Cards بدلاً من Block Kit. أنشئ عقدة Code جديدة تُترجم كائن bySource إلى JSON بتنسيق Adaptive Card (المخطط هنا). أرسل POST إلى رابط webhook الوارد لقناة Teams.

Discord

Discord يقبل webhooks لكن بشكل مختلف — مصفوفة embeds مع title و description و url و fields. سهل الترجمة من bySource.

التخصيص بتفضيلات المستخدم

أضف عقدة Read From Database قبل الجلب. استعلم عن جدول { user_id, topics[], min_score, slack_webhook } ووزع لكل مستخدم. كل مستخدم يحصل على ملخص مُصفى لمواضيعه مع webhook شخصي.

ضبط المصادر لكل يوم

أضف عقدة Switch بعد Schedule توجه إلى مجموعات fetch مختلفة حسب يوم الأسبوع. الإثنين = Hacker News + Dev.to؛ الجمعة = GitHub Trending + Product Hunt. يُبقي الملخص طازجاً.


ما التالي

ادمج هذا مع يوتيوب إلى تدوينة AI لتحويل مستودع GitHub لليوم إلى مقال شرح كامل، أو مع إثراء العملاء المحتملين بالـAI لتحديد الشركات المُوظِّفة من منشورات Dev.to وتوليد outreach.

شارك هذا الدليل

الأسئلة الشائعة

كل مصدر يعيد شكل استجابة مختلف: HN يُعيد `hits[]` من Algolia، Dev.to يُعيد مصفوفة عادية، GitHub يُعيد `items[]`. تطبيع ثلاثة أشكال في عقدة Code واحدة يصبح spaghetti. ثلاثة أزواج Fetch → Normalize تعطيك معالجة أخطاء لكل مصدر، وإعادة محاولة لكل مصدر، وتصحيح أنظف عندما تنكسر واجهة واحدة. عقدة Merge تخيطها معاً.

مقالات ذات صلة

نشرة أسبوعية مجانية

ابقَ على مسار النيرد

بريد واحد أسبوعياً — دورات، مقالات معمّقة، أدوات، وتجارب ذكاء اصطناعي.

بدون إزعاج. إلغاء الاشتراك في أي وقت.