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}`);
|
||
});
|