وبهوکها
قابلیتهای Zealy را با اتصالهای وبهوک تقویت کنید.
توسط louis, Fredrika, benjamin

در این صفحه
وبهوک Zealy هنگام رخ دادن یکی از نُه رویداد جامعه، از جمله پیوستن عضو، موفق یا ناموفق بودن ثبت یک کوئست، شروع یک اسپرینت و مسدود شدن کاربر، یک درخواست HTTP POST به نشانی اینترنتی که انتخاب میکنید ارسال میکند. هر محموله شامل شناسه رویداد، نوع، دادهها، برچسب زمان میلیثانیهای و رمزی است که اصالت درخواست را اثبات میکند.
مبانی
Zealy ارائه میدهد وبهوکها را که به شما امکان میدهد هر زمان دادهای ایجاد یا بهروزرسانی شود، اعلانهای فشاری HTTP دریافت کنید. این امکان به شما اجازه میدهد یکپارچهسازیهایی روی Zealy بسازید. میتوانید ساختهای CI را راهاندازی کنید، محاسباتی روی دادههای کوئست انجام دهید یا در شرایط خاص پیام بفرستید – هر چه بخواهید.
برای راهاندازی وبهوکهای خود به Settings > Integrations > Zapier & Webhooks بروید.
وبهوک چگونه کار میکند؟
ارسال وبهوک بهسادگی یک HTTP POST درخواست است که به URL انتخابی شما ارسال میشود. این ارسال بهطور خودکار توسط Linear هنگام بهروزرسانی دادهها فعال میشود. برای نمونهای از دادههای موجود در payload، به اینجا مراجعه کنید payload وبهوک.
مصرفکننده وبهوک شما یک endpoint ساده HTTP است. باید شرایط زیر را برآورده کند:
- در یک URL عمومی HTTPS و غیر localhost در دسترس باشد
- به ارسال وبهوک Zealy (درخواست HTTP POST) با یک
HTTP 200پاسخ ("OK") پاسخ دهد
اگر تحویل ناموفق باشد (یعنی سرور در دسترس نباشد، پاسخ بیش از ۵ ثانیه طول بکشد، بدنهٔ پاسخ بزرگتر از ۵۰۰۰ بایت باشد یا با کد وضعیت HTTP غیر از ۲۰۰ پاسخ دهد)، ارسال ۱۵ بار دوباره تلاش میشود. در اینجا از تأخیر عقبنشینی نمایی استفاده میشود: تلاش پس از حدود ۱۰ دقیقه، سپس ۳۰ دقیقه و به همین ترتیب تکرار میشود. اگر URL وبهوک همچنان پاسخگو نباشد، ممکن است وبهوک توسط Zealy غیرفعال شود و باید دوباره بهصورت دستی فعال شود.
برای اطمینان از اینکه یک وبهوک POST واقعاً توسط Zealy ایجاد شده است، یک رمز تصادفی تولید میکنیم که به بدنهٔ درخواست در فیلد secret پیوست میشود.
برای اطلاعات بیشتر دربارهٔ وبهوکها، منابع خوبی وجود دارد:
- RequestBin: وبهوکها – راهنمای جامع
- requestbin.com ابزار عالی برای آزمایش وبهوکها است
- راهنمای توسعهدهندگان GitHub: وبهوکها
از آن برای چه کاری میتوانم استفاده کنم؟
- یکپارچهسازی با Zapier
- خودکارسازی پاداشهای سفارشی
- اطلاعرسانی کوئستهای در انتظار بررسی در Telegram
و خیلی چیزهای دیگر!
شروع کار با وبهوکهای Zealy
- رویدادهایی را که میخواهید پایش کنید مشخص کنید.
- یک تابع endpoint وبهوک برای دریافت درخواستهای POST دادههای رویداد توسعه دهید.
- endpoint خود را در Zealy با استفاده از داشبورد Webhooks در Settings > Integrations > Zapier & Webhooks ثبت کنید.
- endpoint وبهوک خود را ایمن کنید.
ساخت یک مصرفکننده ساده وبهوک
میتوانید استفاده از چیزی مانند Netlify Functions را در نظر بگیرید که روشی ساده برای استقرار endpointهای ساده HTTP(S) فراهم میکند: https://www.netlify.com/blog/2018/09/13/how-to-run-express.js-apps-with-netlify-functions/.
// server.js
//
// Use this sample code to handle webhook events in your integration.
//
// 1) Paste this code into a new file (server.js)
//
// 2) Install dependencies
// npm install express
//
// 3) Run the server on http://localhost:4242
// node server.js
// The library needs to be configured with your account's secret key.
// Ensure the key is kept out of any version control system you might be using.
const express = require('express');
const app = express();
// This is your Zealy webhook secret for testing your endpoint locally.
const endpointSecret = '5888a6800dbac634e52d8504f097e064';
app.post('/webhook', express.raw({ type: 'application/json' }), (request, response) => {
const payload = req.body;
// Does createdAt make more sense than time?
const { id, type, data, time, secret } = payload;
if (secret === endpointSecret) {
// Do something neat with the data received!
}
// Return a 200 response to acknowledge receipt of the event
response.send();
});
app.listen(4242, () => console.log('Running on port 4242'));پیکربندی در تنظیمات
وبهوک و رویدادهایی را که باید پایش کند در Settings > Integrations > Webhooks تنظیم کنید.
محتوای Webhook
محتوای HTTP وبهوک شامل اطلاعاتی هم در هدرهای HTTP و هم در بدنه درخواست خواهد بود.
محتوا با هدرهای HTTP زیر ارسال میشود:
User-Agent: Zealy-Webhook
Content-Type: application/json; charset=utf-8
{
id: string // unique ID for this event (UUID v4)
type: "JOINED_COMMUNITY" | "LEFT_COMMUNITY" | "QUEST_SUCCEEDED" | "QUEST_CLAIMED" | "QUEST_FAILED" | "QUEST_CLAIM_STATUS_UPDATED" | "SPRINT_STARTED" | "SPRINT_ENDED" | "USER_BANNED", // event type
data: EventData, // event data, see below
time: number, // timestamp, in milliseconds
secret: string, // secret generated when you created your webhook, used for checking origin
}فیلد EventData برای هر رویداد:
// JOINED_COMMUNITY
type JoinedCommunityEventData = {
community: WebhookCommunityPayload;
user: WebhookUserPayload;
};
// LEFT_COMMUNITY
type LeftCommunityEventData = {
community: WebhookCommunityPayload;
user: WebhookUserPayload;
};
// QUEST_SUCCEEDED
type QuestSucceededEventData = {
community: WebhookCommunityPayload;
user: WebhookUserPayload;
quest: WebhookQuestPayload;
taskInputs?: Array<{
taskId: string, // task ID (uuid v4)
taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
input: WebhookQuestTaskInputPayload,
}>;
status: 'success';
};
// QUEST_CLAIMED
type QuestClaimedEventData = {
community: WebhookCommunityPayload;
user: WebhookUserPayload;
quest: WebhookQuestPayload;
taskInputs?: Array<{
taskId: string, // task ID (uuid v4)
taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
input: WebhookQuestTaskInputPayload,
}>;
};
// QUEST_FAILED
type QuestFailedEventData = {
community: WebhookCommunityPayload;
user: WebhookUserPayload;
quest: WebhookQuestPayload;
taskInputs?: Array<{
taskId: string, // task ID (uuid v4)
taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
input: WebhookQuestTaskInputPayload,
}>;
};
// QUEST_CLAIM_STATUS_UPDATED
type QuestClaimStatusUpdatedEventData = {
community: WebhookCommunityPayload;
user: WebhookUserPayload;
quest: WebhookQuestPayload;
taskInputs?: Array<{
taskId: string, // task ID (uuid v4)
taskType: 'number' | 'date' | 'api' | 'text' | 'discord' | 'url' | 'telegram' | 'quiz' | 'invites' | 'visitLink' | 'file' | 'poll' | 'opinion' | 'twitterFollow' | 'twitterSpace' | 'tweetReact' | 'tweet',
input: WebhookQuestTaskInputPayload,
}>;
status: 'success' | 'pending' | 'failed';
};
// SPRINT_STARTED
type SprintStartedEventData = {
community: WebhookCommunityPayload;
sprint: WebhookSprintPayload;
};
// SPRINT_ENDED
type SprintEndedEventData = {
community: WebhookCommunityPayload;
sprint: WebhookSprintPayload;
};
// USER_BANNED
type UserBannedEventData = {
community: WebhookCommunityPayload;
user: WebhookUserPayload;
};موجودیتهای مشترک:
type WebhookCommunityPayload = {
id: string; // community ID (uuid V4)
name: string; // community name
subdomain: string; // community subdomain
blockchain: string;
discord: string | null; // discord URI of the community, e.g., https://discord.gg/zealy
twitter: string | null; // twitter handle of the community, e.g., zealy_io
website: string | null; // website URI of the community
};type WebhookUserPayload = {
id: string; // user ID (uuid V4)
name: string | null; // user display name
twitter: {
id: string; // user twitter ID
username: string | null; // user twitter handle
} | null;
discord: {
id: string; // user discord ID
handle: string | null; // user discord handle
} | null;
email: string | null; // user email
addresses: Dict<string>; // key/value dictionary for wallets
verifiedAddresses: Dict<string>; // key/value dictionary for all users verified wallets
};type WebhookQuestPayload = {
id: string; // quest ID (uuid V4)
name: string; // quest display name
categoryId: string; // category ID (uuid V4)
categoryName: string | null; // category display name
xp: number | null; // XP reward
published: boolean | null; // true if quest is published, false otherwise
autoValidate: boolean | null;
tasks: TaskPayload[];
lastReviewerId: string; // user ID (uuid V4)
};type WebhookQuestTaskInputPayload =
| { } // for task type 'visitLink', 'invites', 'discord', 'telegram', 'twitterFollow', 'twitterSpace'
| { value: string } // for task type 'text', 'date', 'url', 'opinion'
| { value: number } // for task type 'number'
| { values: string[] } // for task type 'poll', 'quiz'
| { fileUrls: string[] } // for task type 'fileUrls'
| { tweetId?: string } // for task type 'tweetReact', 'tweet'
| { requestId: string, statusCode: number } // for task type 'api'type WebhookSprintPayload = {
id: string; // sprint ID (uuid V4)
startingAt: ISOString; // sprint starting date - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
endingAt: ISOString; // sprint ending date
};امنسازی وبهوکها
با ایجاد یک وبهوک، یک رمز تصادفی ساخته میشود که میتوانید با آن تأیید کنید درخواست از وبهوکهای Zealy میآید. رمز را از گوشه بالا سمت راست پنل بازرسی وبهوک کپی کنید و تأیید کنید که رمز تنظیمشده در بدنه درخواست POST یکسان است.
در صورت افشای رمز، میتوانید آن را از همان صفحه دوباره تولید کنید.

آزمایش webhookها
از پنل بررسی webhook میتوانید بهصورت دستی یک رویداد آزمایشی را فعال کنید. روی دکمه در بالا سمت راست کلیک کنید و «Send test event» را انتخاب کنید. میتوانید یک نوع رویداد را از میان انواع رویدادهای پایششده انتخاب کنید. یک رویداد با دادههای ساختگی فعال میشود و وضعیت نمایش داده میشود.
اشکالزدایی
اگر از صفحه Webhooks روی webhook کلیک کنید، میتوانید گزارشهای همه رویدادهای گذشتهای را که webhook فعال کرده است ببینید. با فیلتر کردن بر اساس وضعیت میتوانید از گزارشها برای اشکالزدایی در صورت بروز مشکل استفاده کنید. برای هر رویداد، پیام خطای دریافتی و درخواست ارسالشده را میبینید.
همچنین میتوانید هر رویدادی را از این صفحه دوباره امتحان کنید.
