Вебхуки
Розширте можливості Zealy за допомогою підключень вебхуків.
Автор louis, Fredrika, benjamin

На цій сторінці
Вебхук Zealy надсилає HTTP POST на вибрану вами URL-адресу, коли відбувається одна з дев'яти подій спільноти, серед яких приєднання учасника, успішне або невдале подання квесту, початок спринту та блокування користувача. Кожне корисне навантаження містить ідентифікатор події, тип, дані, мітку часу в мілісекундах і секрет, який підтверджує справжність запиту.
Основи
Zealy надає вебхуки , які дозволяють отримувати HTTP push-сповіщення щоразу, коли дані створюються або оновлюються. Це дозволяє створювати інтеграції на основі Zealy. Ви можете запускати CI-збірки, виконувати обчислення на основі даних квестів або надсилати повідомлення за певних умов – що завгодно.
Будь ласка, перейдіть до Settings > Integrations > Zapier & Webhooks, щоб налаштувати вебхуки.
Як працює вебхук?
Push вебхука — це просто HTTP POST запит, надісланий на вибрану вами URL-адресу. Push автоматично запускається Linear, коли дані оновлюються. Приклад того, які дані містить корисне навантаження, див. Корисне навантаження вебхука.
Ваш споживач вебхука — це простий HTTP-ендпоінт. Він повинен відповідати таким умовам:
- Він доступний за загальнодоступною HTTPS-адресою, не localhost
- Він відповідатиме на push вебхука Zealy (HTTP POST-запит) відповіддю
HTTP 200("OK")
Якщо доставка не вдається (тобто сервер недоступний, відповідь тривала довше 5 секунд, тіло відповіді було більше 5000 байт або відповідь мала HTTP-статус, відмінний від 200), push повторюватиметься 15 разів. Тут використовується експоненційна затримка: спроба повторюється приблизно через 10 хвилин, потім через 30 хвилин і так далі. Якщо URL-адреса вебхука продовжує бути недоступною, вебхук може бути вимкнений Zealy, і його потрібно буде знову ввімкнути вручну.
Щоб переконатися, що вебхук POST справді створений Zealy, ми генеруємо випадковий секрет, який буде додано до тіла запиту в полі secret .
Додаткову інформацію про вебхуки можна знайти в кількох хороших джерелах:
- RequestBin: Webhooks – The Definitive Guide
- requestbin.com — чудовий інструмент для тестування вебхуків
- GitHub Developer Guide: Webhooks
Для чого я можу це використовувати?
- Інтеграція з Zapier
- Автоматизація користувацьких винагород
- Сповіщення про квести, що очікують перевірки, у Telegram
І багато-багато іншого!
Початок роботи з вебхуками Zealy
- Визначте, які події ви хочете відстежувати.
- Розробіть функцію ендпоінта вебхука для отримання POST-запитів з даними подій.
- Зареєструйте свій ендпоінт у Zealy за допомогою панелі вебхуків у Settings > Integrations > Zapier & Webhooks.
- Захистіть свій ендпоінт вебхука.
Створення простого споживача вебхука
Можливо, варто розглянути використання чогось на кшталт Netlify Functions, що забезпечує простий спосіб розгортання простих 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.
Корисне навантаження вебхука
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-запиту, збігається.
Якщо секрет став відомий, ви можете повторно згенерувати його на тій самій сторінці.

Тестування вебхуків
З панелі перевірки вебхука ви можете вручну запустити тестову подію. Натисніть кнопку у верхньому правому куті та виберіть «Send test event». Ви зможете вибрати тип події серед відстежуваних типів подій. Подія буде запущена з фіктивними даними, а статус відображено.
Налагодження
Ви можете переглянути журнали всіх минулих подій, запущених вебхуком, якщо натиснете на вебхук на сторінці Webhooks. Фільтруючи за статусом, ви можете використовувати журнали для налагодження, якщо щось пішло не так. Для кожної події ви можете побачити отримане повідомлення про помилку та надісланий запит.
Ви також можете повторити будь-яку подію з цієї сторінки.
