- Добавлена полная интеграция с Telegram Mini App (динамическая загрузка SDK) - Отдельный компактный дизайн для Telegram Mini App - Добавлен loader при инициализации (предотвращает мелькание SMS-авторизации) - Улучшена навигация: кнопки "Назад" и "К списку заявок" теперь сохраняют авторизацию - Telegram Mini App: кнопка "Выход" просто закрывает приложение - Telegram Mini App: заявки "В работе" скрыты из списка - Веб-версия: для заявок "В работе" добавлена кнопка "Просмотреть в Telegram" (ссылка на @klientprav_bot) - Telegram Mini App: кнопки действий в черновиках расположены вертикально - Веб-версия: убрано отображение номера телефона в приветствии - Исправлена проблема с возвратом к списку черновиков (не требует повторной SMS-авторизации) - Заблокировано удаление и редактирование заявок со статусом "В работе" - Добавлена документация по Telegram Mini App интеграции
321 lines
7.8 KiB
Markdown
321 lines
7.8 KiB
Markdown
# Пример Workflow для обработки рейсов с Base64 PDF
|
||
|
||
## Структура Workflow
|
||
|
||
```
|
||
HTTP Request (FlightAware)
|
||
↓
|
||
HTTP Request (FlightRadar24)
|
||
↓
|
||
Code: Process Flights Data ← N8N_CODE_PROCESS_FLIGHTS_DATA.js
|
||
↓
|
||
Code: Prepare PDF Request ← N8N_FLIGHTS_PDF_BASE64_COMPLETE.js
|
||
↓
|
||
HTTP Request (Convert to PDF) ← Внешний сервис конвертации
|
||
↓
|
||
Code: Extract Base64 PDF ← N8N_FLIGHTS_PDF_BASE64_FULL.js
|
||
↓
|
||
[Использование base64 PDF]
|
||
├─→ Save File
|
||
├─→ Send Email
|
||
├─→ Upload to S3
|
||
└─→ Return in API Response
|
||
```
|
||
|
||
## Детальная настройка нод
|
||
|
||
### 1. HTTP Request: FlightAware
|
||
- **Method:** GET/POST (в зависимости от API)
|
||
- **URL:** `https://flightaware.com/api/...`
|
||
- **Authentication:** По необходимости
|
||
|
||
### 2. HTTP Request: FlightRadar24
|
||
- **Method:** GET/POST (в зависимости от API)
|
||
- **URL:** `https://flightradar24.com/api/...`
|
||
- **Authentication:** По необходимости
|
||
|
||
### 3. Code: Process Flights Data
|
||
**Код:** Скопируйте из `N8N_CODE_PROCESS_FLIGHTS_DATA.js`
|
||
|
||
**Входные данные:**
|
||
- Два элемента из предыдущих HTTP Request нод
|
||
|
||
**Выходные данные:**
|
||
```json
|
||
{
|
||
"html": "<!DOCTYPE html>...",
|
||
"flights": [...],
|
||
"flights_count": 2,
|
||
"sources": {...},
|
||
"generated_at": "2026-01-14T..."
|
||
}
|
||
```
|
||
|
||
### 4. Code: Prepare PDF Request
|
||
**Код:** Скопируйте из `N8N_FLIGHTS_PDF_BASE64_COMPLETE.js`
|
||
|
||
**Настройка:**
|
||
- Замените `PDF_SERVICE_URL` на URL вашего сервиса
|
||
- Замените `PDF_API_KEY` на ваш API ключ
|
||
|
||
**Выходные данные:**
|
||
```json
|
||
{
|
||
"http_method": "POST",
|
||
"http_url": "https://api.htmlpdfapi.com/v1/pdf",
|
||
"http_headers": {...},
|
||
"http_body": "{...}",
|
||
"html_length": 12345,
|
||
"flights_count": 2
|
||
}
|
||
```
|
||
|
||
### 5. HTTP Request: Convert to PDF
|
||
**Настройка:**
|
||
- **Method:** `{{ $json.http_method }}`
|
||
- **URL:** `{{ $json.http_url }}`
|
||
- **Authentication:** По необходимости (через Headers)
|
||
- **Headers:**
|
||
```json
|
||
{{ $json.http_headers }}
|
||
```
|
||
- **Body:**
|
||
```json
|
||
{{ $json.http_body }}
|
||
```
|
||
- **Response Format:** `JSON` или `Binary` (зависит от сервиса)
|
||
|
||
**Пример для htmlpdfapi.com:**
|
||
```json
|
||
{
|
||
"method": "POST",
|
||
"url": "https://api.htmlpdfapi.com/v1/pdf",
|
||
"headers": {
|
||
"Content-Type": "application/json",
|
||
"Authorization": "Bearer YOUR_API_KEY"
|
||
},
|
||
"body": {
|
||
"html": "{{ $('Code: Process Flights Data').first().json.html }}",
|
||
"options": {
|
||
"format": "A4",
|
||
"printBackground": true
|
||
},
|
||
"base64": true
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6. Code: Extract Base64 PDF
|
||
**Код:** Скопируйте из `N8N_FLIGHTS_PDF_BASE64_FULL.js`
|
||
|
||
**Входные данные:**
|
||
- Ответ от HTTP Request ноды (JSON или Binary)
|
||
|
||
**Выходные данные:**
|
||
```json
|
||
{
|
||
"pdf_base64": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9MZW5ndGg...",
|
||
"pdf_size_bytes": 123456,
|
||
"pdf_size_mb": "0.12",
|
||
"success": true,
|
||
"source": "json_response"
|
||
}
|
||
```
|
||
|
||
## Использование base64 PDF
|
||
|
||
### Вариант A: Сохранение в файл
|
||
|
||
**Code Node:**
|
||
```javascript
|
||
const base64 = $('Code: Extract Base64 PDF').first().json.pdf_base64;
|
||
const filename = `flights-report-${new Date().toISOString().split('T')[0]}.pdf`;
|
||
|
||
// Конвертируем base64 в binary
|
||
const pdfBuffer = Buffer.from(base64, 'base64');
|
||
|
||
return [{
|
||
binary: {
|
||
data: pdfBuffer,
|
||
fileName: filename,
|
||
mimeType: 'application/pdf'
|
||
},
|
||
json: {
|
||
filename: filename,
|
||
size_bytes: pdfBuffer.length
|
||
}
|
||
}];
|
||
```
|
||
|
||
Затем используйте ноду **Write Binary File** или **Save to S3**.
|
||
|
||
### Вариант B: Отправка по Email
|
||
|
||
**Code Node:**
|
||
```javascript
|
||
const base64 = $('Code: Extract Base64 PDF').first().json.pdf_base64;
|
||
const pdfBuffer = Buffer.from(base64, 'base64');
|
||
|
||
return [{
|
||
json: {
|
||
to: 'recipient@example.com',
|
||
subject: 'Отчёт о рейсах',
|
||
text: 'Во вложении отчёт о рейсах.',
|
||
attachments: [{
|
||
filename: 'flights-report.pdf',
|
||
content: pdfBuffer,
|
||
contentType: 'application/pdf'
|
||
}]
|
||
}
|
||
}];
|
||
```
|
||
|
||
Затем используйте ноду **Email Send**.
|
||
|
||
### Вариант C: Возврат в API Response
|
||
|
||
**Code Node (перед Response нодой):**
|
||
```javascript
|
||
const base64 = $('Code: Extract Base64 PDF').first().json.pdf_base64;
|
||
const processedData = $('Code: Process Flights Data').first().json;
|
||
|
||
return [{
|
||
json: {
|
||
success: true,
|
||
flights_count: processedData.flights_count,
|
||
pdf_base64: base64,
|
||
pdf_size_mb: $('Code: Extract Base64 PDF').first().json.pdf_size_mb,
|
||
generated_at: processedData.generated_at
|
||
}
|
||
}];
|
||
```
|
||
|
||
### Вариант D: Загрузка в S3/Nextcloud
|
||
|
||
**Code Node:**
|
||
```javascript
|
||
const base64 = $('Code: Extract Base64 PDF').first().json.pdf_base64;
|
||
const pdfBuffer = Buffer.from(base64, 'base64');
|
||
const filename = `flights-report-${new Date().toISOString().split('T')[0]}.pdf`;
|
||
|
||
return [{
|
||
binary: {
|
||
data: pdfBuffer,
|
||
fileName: filename,
|
||
mimeType: 'application/pdf'
|
||
},
|
||
json: {
|
||
bucket: 'your-bucket',
|
||
key: `reports/${filename}`,
|
||
contentType: 'application/pdf'
|
||
}
|
||
}];
|
||
```
|
||
|
||
Затем используйте ноду **S3 Upload** или **Nextcloud Upload**.
|
||
|
||
## Альтернативные сервисы конвертации
|
||
|
||
### 1. htmlpdfapi.com
|
||
```javascript
|
||
{
|
||
"url": "https://api.htmlpdfapi.com/v1/pdf",
|
||
"method": "POST",
|
||
"headers": {
|
||
"Content-Type": "application/json",
|
||
"Authorization": "Bearer YOUR_API_KEY"
|
||
},
|
||
"body": {
|
||
"html": "{{ HTML }}",
|
||
"base64": true
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. pdfshift.io
|
||
```javascript
|
||
{
|
||
"url": "https://api.pdfshift.io/v3/convert/pdf",
|
||
"method": "POST",
|
||
"headers": {
|
||
"Content-Type": "application/json",
|
||
"Authorization": "Basic " + Buffer.from("api:YOUR_API_KEY").toString("base64")
|
||
},
|
||
"body": {
|
||
"source": "{{ HTML }}",
|
||
"format": "A4"
|
||
}
|
||
}
|
||
// Ответ содержит base64 в поле "pdf"
|
||
```
|
||
|
||
### 3. api2pdf.com
|
||
```javascript
|
||
{
|
||
"url": "https://v2.api2pdf.com/chrome/html",
|
||
"method": "POST",
|
||
"headers": {
|
||
"Authorization": "YOUR_API_KEY",
|
||
"Content-Type": "application/json"
|
||
},
|
||
"body": {
|
||
"html": "{{ HTML }}",
|
||
"inlinePdf": true,
|
||
"fileName": "flights-report.pdf"
|
||
}
|
||
}
|
||
// Ответ содержит base64 в поле "pdf"
|
||
```
|
||
|
||
### 4. Self-hosted: Gotenberg
|
||
```javascript
|
||
{
|
||
"url": "http://your-gotenberg-server:3000/forms/chromium/convert/html",
|
||
"method": "POST",
|
||
"headers": {
|
||
"Content-Type": "multipart/form-data"
|
||
},
|
||
"body": {
|
||
"files": [{
|
||
"name": "index.html",
|
||
"content": "{{ HTML }}"
|
||
}]
|
||
}
|
||
}
|
||
// Ответ - binary PDF, конвертируем в base64
|
||
```
|
||
|
||
## Отладка
|
||
|
||
### Проверка HTML
|
||
```javascript
|
||
const html = $('Code: Process Flights Data').first().json.html;
|
||
console.log('HTML length:', html.length);
|
||
console.log('HTML preview:', html.substring(0, 500));
|
||
```
|
||
|
||
### Проверка base64
|
||
```javascript
|
||
const base64 = $('Code: Extract Base64 PDF').first().json.pdf_base64;
|
||
console.log('Base64 length:', base64.length);
|
||
console.log('Base64 preview:', base64.substring(0, 100));
|
||
```
|
||
|
||
### Проверка размера PDF
|
||
```javascript
|
||
const data = $('Code: Extract Base64 PDF').first().json;
|
||
console.log('PDF size:', data.pdf_size_mb, 'MB');
|
||
console.log('PDF size bytes:', data.pdf_size_bytes);
|
||
```
|
||
|
||
## Обработка ошибок
|
||
|
||
Добавьте IF Node после HTTP Request для проверки успешности:
|
||
|
||
```javascript
|
||
// IF Node: Check PDF Conversion Success
|
||
{{ $json.success === true }}
|
||
```
|
||
|
||
Если ошибка - отправьте уведомление или сохраните HTML для ручной конвертации.
|