179 lines
5.8 KiB
JavaScript
179 lines
5.8 KiB
JavaScript
|
const express = require('express');
|
|||
|
const bodyParser = require('body-parser');
|
|||
|
|
|||
|
const app = express();
|
|||
|
app.use(bodyParser.json());
|
|||
|
|
|||
|
// Адрес сервера данного приложения (для доступа из Интернета)
|
|||
|
const SERVER_URL = '';
|
|||
|
// Адрес сервера Loop
|
|||
|
const LOOP_URL = '';
|
|||
|
// Порт на котором будет слушать наш сервер
|
|||
|
const PORT = 4000;
|
|||
|
|
|||
|
// Описание первой формы
|
|||
|
const form1 = {
|
|||
|
title: 'Первая форма',
|
|||
|
icon: 'icon.png', // Иконку для каждой формы можно задать свою
|
|||
|
fields: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
name: 'message',
|
|||
|
modal_label: 'Тут какое-то поле',
|
|||
|
position: 1,
|
|||
|
is_required: true,
|
|||
|
},
|
|||
|
],
|
|||
|
submit: {
|
|||
|
// Куда отправлять запрос после нажатия кнопки "Отправить"
|
|||
|
path: '/second_modal',
|
|||
|
// Контекст для запроса
|
|||
|
expand: {
|
|||
|
// Запрашиваем данные пользователя который вызвал действие
|
|||
|
acting_user: "all",
|
|||
|
// запрашиваем канал в котором было вызвано действие
|
|||
|
channel: "all",
|
|||
|
}
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
// Описание второй формы
|
|||
|
const form2 = {
|
|||
|
title: 'Вторая форма',
|
|||
|
icon: 'icon.png',
|
|||
|
fields: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
name: 'message2',
|
|||
|
modal_label: 'Еще одно поле',
|
|||
|
position: 1,
|
|||
|
},
|
|||
|
],
|
|||
|
submit: {
|
|||
|
// Куда отправлять запрос после нажатия кнопки "Отправить"
|
|||
|
path: '/second_result',
|
|||
|
expand: {
|
|||
|
// Запрашиваем данные пользователя который вызвал действие
|
|||
|
acting_user: "all",
|
|||
|
// запрашиваем канал в котором было вызвано действие
|
|||
|
channel: "all",
|
|||
|
}
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
// Отправка сообщения в канал Loop
|
|||
|
const createPost = async (bot_access_token, channel_id, message) => {
|
|||
|
try {
|
|||
|
await fetch(`${LOOP_URL}/api/v4/posts`, {
|
|||
|
method: 'POST',
|
|||
|
headers: {
|
|||
|
Authorization: 'Bearer ' + bot_access_token,
|
|||
|
},
|
|||
|
body: JSON.stringify({
|
|||
|
channel_id,
|
|||
|
message,
|
|||
|
})
|
|||
|
});
|
|||
|
} catch (e) {
|
|||
|
console.error('Error when create post', e);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Обработчик результата первой формы
|
|||
|
app.post('/second_modal', (req, res) => {
|
|||
|
const context = req.body.context;
|
|||
|
|
|||
|
// Отправляем данные формы в канал
|
|||
|
createPost(
|
|||
|
context.bot_access_token,
|
|||
|
context.channel.id,
|
|||
|
'### Заполнена форма 1\n```json\n' + JSON.stringify(req.body.values, null, 2) + '\n```',
|
|||
|
);
|
|||
|
|
|||
|
// Отвечаем второй формой. Обязательно статус 200 (не 201 и тд)
|
|||
|
res.status(200).json({
|
|||
|
type: 'form',
|
|||
|
form: form2,
|
|||
|
})
|
|||
|
});
|
|||
|
|
|||
|
// Обработчик результата второй формы
|
|||
|
app.post('/second_result', (req, res) => {
|
|||
|
const context = req.body.context;
|
|||
|
|
|||
|
// Отправляем результат в канал
|
|||
|
createPost(
|
|||
|
context.bot_access_token,
|
|||
|
context.channel.id,
|
|||
|
'### Заполнена форма 2\n```json\n' + JSON.stringify(req.body.values, null, 2) + '\n```',
|
|||
|
);
|
|||
|
|
|||
|
// Отвечаем что все хорошо. Обязательно статус 200 (не 201 и тд)
|
|||
|
res.status(200).json({
|
|||
|
type: 'ok',
|
|||
|
});
|
|||
|
})
|
|||
|
|
|||
|
// Данный метод будет вызываться при открытии любого канала, любым пользователем
|
|||
|
// Отвечает за отрисовку кнопки в сайдбаре
|
|||
|
app.post('/bindings', (req, res) => {
|
|||
|
res.status(200).json({
|
|||
|
type: 'ok',
|
|||
|
data: [
|
|||
|
{
|
|||
|
// Место где показать кнопку
|
|||
|
location: '/channel_header',
|
|||
|
// Описание кнопки
|
|||
|
bindings: [
|
|||
|
{
|
|||
|
// идентификатор, который будет отправлен в запросе
|
|||
|
location: 'send-button',
|
|||
|
// Иконка кнопки
|
|||
|
icon: 'icon.png',
|
|||
|
// Подпись для кнопки
|
|||
|
label: 'Открыть форму',
|
|||
|
// Первая форма
|
|||
|
form: form1,
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
]
|
|||
|
})
|
|||
|
})
|
|||
|
|
|||
|
// Манифест для установки приложения
|
|||
|
app.get('/manifest.json', (req, res) => {
|
|||
|
res.json({
|
|||
|
app_id: 'ru.loop.dialog-sequence-example',
|
|||
|
version: '0.1.0',
|
|||
|
display_name: 'Loop Dialog Sequence Example',
|
|||
|
description: 'An app that opens modal dialogs sequentially',
|
|||
|
icon: 'icon.png',
|
|||
|
homepage_url: 'https://git.wilix.dev/loop/integration-examples',
|
|||
|
// Разрешения для приложения
|
|||
|
requested_permissions: [
|
|||
|
// разрешение, чтобы приложение могло писать от имени бота
|
|||
|
'act_as_bot',
|
|||
|
// разрешение, чтобы получать данные пользователя, который вызывает действия
|
|||
|
'act_as_user'
|
|||
|
],
|
|||
|
// Разрешения для установки кнопок или команд
|
|||
|
requested_locations: [
|
|||
|
// Устанавливает кнопку во всех каналах в сайдбаре или в заголовке канала
|
|||
|
// (расположение завит от того, включен ли сайдбар)
|
|||
|
'/channel_header'
|
|||
|
],
|
|||
|
app_type: 'http',
|
|||
|
http: {
|
|||
|
root_url: SERVER_URL
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
|
|||
|
// Сервим иконки из папки. Все иконки всегда будут искаться по пути /static
|
|||
|
app.use('/static', express.static('./static'));
|
|||
|
|
|||
|
app.listen(PORT, () => {
|
|||
|
console.log(`Server is running on port ${PORT}`);
|
|||
|
});
|