# API для запуска стратегий продвижения

## Обзор

Данный документ описывает API для управления credentials социальных сетей и запуска маркетинговых стратегий с автоматической публикацией постов.

## Базовый URL

```
http://your-server:port/api
```

## Аутентификация

Все endpoints требуют JWT токен в заголовке `Authorization`:

```
Authorization: Bearer <your-jwt-token>
```

## Управление Credentials социальных сетей

### 1. Сохранение/обновление credentials

Сохраняет или обновляет credentials для указанной платформы. Credentials автоматически шифруются перед сохранением.

**Endpoint:** `POST /api/social-media/credentials`

**Headers:**

```
Authorization: Bearer <token>
Content-Type: application/json
```

**Request Body:**

```json
{
  "platform": "facebook",
  "credentials": "your-facebook-access-token"
}
```

**Параметры:**

- `platform` (string, required) - Название платформы (например: "facebook", "instagram")
- `credentials` (string, required) - Access token или другие credentials для платформы

**Response 200 OK:**

```json
{
  "success": true,
  "message": "Credentials успешно сохранены для платформы facebook",
  "data": {
    "platform": "facebook",
    "hasCredentials": true,
    "createdAt": "2024-01-15T10:30:00",
    "updatedAt": "2024-01-15T10:30:00"
  }
}
```

**Response 400 Bad Request:**

```json
{
  "success": false,
  "message": "Ошибка валидации",
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Platform is required",
    "details": {
      "platform": "Platform is required"
    }
  }
}
```

**Response 401 Unauthorized:**

```json
{
  "success": false,
  "message": "Не авторизован",
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Требуется аутентификация. Пожалуйста, предоставьте валидный JWT токен."
  }
}
```

**Пример запроса (JavaScript):**

```javascript
const saveCredentials = async (platform, accessToken) => {
  const response = await fetch('/api/social-media/credentials', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${jwtToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      platform: platform,
      credentials: accessToken,
    }),
  });

  const data = await response.json();
  return data;
};

// Использование
await saveCredentials('facebook', 'EAABwzLix...');
```

---

### 2. Получение информации о credentials

Проверяет наличие credentials для указанной платформы.

**Endpoint:** `GET /api/social-media/credentials/{platform}`

**Headers:**

```
Authorization: Bearer <token>
```

**Path Parameters:**

- `platform` (string) - Название платформы

**Response 200 OK:**

```json
{
  "success": true,
  "message": "Операция выполнена успешно",
  "data": {
    "platform": "facebook",
    "hasCredentials": true
  }
}
```

**Пример запроса:**

```javascript
const checkCredentials = async (platform) => {
  const response = await fetch(`/api/social-media/credentials/${platform}`, {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${jwtToken}`,
    },
  });

  const data = await response.json();
  return data.data.hasCredentials;
};
```

---

### 3. Получение списка всех credentials

Возвращает список всех платформ, для которых у пользователя настроены credentials.

**Endpoint:** `GET /api/social-media/credentials`

**Headers:**

```
Authorization: Bearer <token>
```

**Response 200 OK:**

```json
{
  "success": true,
  "message": "Операция выполнена успешно",
  "data": [
    {
      "platform": "facebook",
      "hasCredentials": true,
      "createdAt": "2024-01-15T10:30:00",
      "updatedAt": "2024-01-15T10:30:00"
    }
  ]
}
```

**Пример запроса:**

```javascript
const getAllCredentials = async () => {
  const response = await fetch('/api/social-media/credentials', {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${jwtToken}`,
    },
  });

  const data = await response.json();
  return data.data;
};
```

---

### 4. Удаление credentials

Удаляет credentials для указанной платформы.

**Endpoint:** `DELETE /api/social-media/credentials/{platform}`

**Headers:**

```
Authorization: Bearer <token>
```

**Path Parameters:**

- `platform` (string) - Название платформы

**Response 200 OK:**

```json
{
  "success": true,
  "message": "Credentials для платформы facebook успешно удалены",
  "data": null
}
```

**Response 404 Not Found:**

```json
{
  "success": false,
  "message": "Credentials не найдены",
  "error": {
    "code": "NOT_FOUND",
    "message": "Credentials для платформы facebook не найдены"
  }
}
```

**Пример запроса:**

```javascript
const deleteCredentials = async (platform) => {
  const response = await fetch(`/api/social-media/credentials/${platform}`, {
    method: 'DELETE',
    headers: {
      Authorization: `Bearer ${jwtToken}`,
    },
  });

  const data = await response.json();
  return data;
};
```

---

## Запуск стратегии продвижения

### Запуск стратегии

Запускает выполнение маркетинговой стратегии. Система автоматически создает задачи публикации из календаря постов стратегии и добавляет их в очередь для выполнения.

**Endpoint:** `POST /api/marketing/analysis/strategy/{strategyId}/start`

**Headers:**

```
Authorization: Bearer <token>
Content-Type: application/json
```

**Path Parameters:**

- `strategyId` (string) - ID стратегии для запуска

**Request Body (опционально):**

```json
{}
```

**Response 200 OK:**

```json
{
  "success": true,
  "message": "Стратегия успешно запущена",
  "data": {
    "strategyId": "67890abcdef",
    "tasksCreated": 12,
    "platforms": ["facebook", "instagram"],
    "message": "Стратегия успешно запущена. Создано задач: 12"
  }
}
```

**Response 400 Bad Request (стратегия не завершена):**

```json
{
  "success": false,
  "message": "Стратегия не готова к запуску",
  "error": {
    "code": "INVALID_STATUS",
    "message": "Стратегия еще не завершена. Статус: processing"
  }
}
```

**Response 400 Bad Request (нет credentials):**

```json
{
  "success": false,
  "message": "Не удалось запустить стратегию",
  "error": {
    "code": "MISSING_CREDENTIALS",
    "message": "Credentials not found for platform: facebook. Please configure credentials first."
  }
}
```

**Response 404 Not Found:**

```json
{
  "success": false,
  "message": "Стратегия не найдена",
  "error": {
    "code": "NOT_FOUND",
    "message": "Стратегия с указанным ID не найдена"
  }
}
```

**Response 403 Forbidden:**

```json
{
  "success": false,
  "message": "Доступ запрещен",
  "error": {
    "code": "FORBIDDEN",
    "message": "У вас нет доступа к этой стратегии"
  }
}
```

**Пример запроса:**

```javascript
const startStrategy = async (strategyId) => {
  const response = await fetch(
    `/api/marketing/analysis/strategy/${strategyId}/start`,
    {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${jwtToken}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({}),
    }
  );

  const data = await response.json();

  if (data.success) {
    console.log(`Создано задач: ${data.data.tasksCreated}`);
    console.log(`Платформы: ${data.data.platforms.join(', ')}`);
  } else {
    console.error('Ошибка:', data.error.message);
  }

  return data;
};
```

---

## Полный пример использования

### Шаг 1: Настройка credentials для Facebook

```javascript
// Сохраняем Facebook Access Token
const facebookToken = 'EAABwzLix...'; // Получить из Facebook Developer Console

const result = await saveCredentials('facebook', facebookToken);
if (result.success) {
  console.log('Facebook credentials сохранены');
}
```

### Шаг 2: Получение стратегии

```javascript
// Получаем список стратегий пользователя
const response = await fetch('/api/marketing/analysis/strategy/my', {
  headers: {
    Authorization: `Bearer ${jwtToken}`,
  },
});

const data = await response.json();
const strategies = data.data;

// Выбираем завершенную стратегию
const completedStrategy = strategies.find((s) => s.status === 'completed');
```

### Шаг 3: Запуск стратегии

```javascript
if (completedStrategy) {
  // Проверяем наличие credentials для платформ стратегии
  const platforms = completedStrategy.priorityPlatforms || [];

  for (const platform of platforms) {
    const hasCreds = await checkCredentials(platform);
    if (!hasCreds) {
      console.warn(`Необходимо настроить credentials для ${platform}`);
      // Показать пользователю форму для ввода credentials
    }
  }

  // Запускаем стратегию
  const startResult = await startStrategy(completedStrategy.strategyId);

  if (startResult.success) {
    console.log(
      `Стратегия запущена! Создано ${startResult.data.tasksCreated} задач`
    );
    // Показать уведомление пользователю
  }
}
```

---

## Обработка ошибок

### Типичные ошибки и их обработка

1. **UNAUTHORIZED (401)**

   - Причина: Невалидный или отсутствующий JWT токен
   - Решение: Обновить токен или перенаправить на страницу входа

2. **VALIDATION_ERROR (400)**

   - Причина: Невалидные данные в запросе
   - Решение: Проверить обязательные поля и их формат

3. **MISSING_CREDENTIALS (400)**

   - Причина: Не настроены credentials для платформы
   - Решение: Предложить пользователю настроить credentials

4. **INVALID_STATUS (400)**

   - Причина: Стратегия еще не завершена
   - Решение: Дождаться завершения генерации стратегии

5. **NOT_FOUND (404)**

   - Причина: Стратегия или credentials не найдены
   - Решение: Проверить правильность ID

6. **FORBIDDEN (403)**
   - Причина: Пользователь не имеет доступа к ресурсу
   - Решение: Проверить права доступа

### Пример обработки ошибок

```javascript
const handleApiError = (error) => {
  switch (error.code) {
    case 'UNAUTHORIZED':
      // Перенаправить на страницу входа
      window.location.href = '/login';
      break;

    case 'MISSING_CREDENTIALS':
      // Показать модальное окно для настройки credentials
      showCredentialsModal(error.message);
      break;

    case 'INVALID_STATUS':
      // Показать сообщение о том, что стратегия еще не готова
      showNotification(
        'Стратегия еще не завершена. Пожалуйста, подождите.',
        'warning'
      );
      break;

    case 'VALIDATION_ERROR':
      // Показать ошибки валидации
      showValidationErrors(error.details);
      break;

    default:
      showNotification('Произошла ошибка. Попробуйте позже.', 'error');
  }
};

// Использование
try {
  const result = await startStrategy(strategyId);
  if (!result.success) {
    handleApiError(result.error);
  }
} catch (error) {
  console.error('Network error:', error);
  showNotification('Ошибка сети. Проверьте подключение.', 'error');
}
```

---

## Статусы задач публикации

После запуска стратегии создаются задачи со следующими статусами:

- `pending` - Задача ожидает выполнения (дата публикации еще не наступила)
- `processing` - Задача выполняется в данный момент
- `completed` - Задача успешно выполнена
- `failed` - Задача не выполнена из-за ошибки

**Примечание:** Задачи с датой публикации в прошлом выполняются сразу после создания.

---

## Планировщик задач

Система автоматически проверяет очередь задач каждую минуту и выполняет задачи, у которых наступило время публикации.

- Планировщик включен по умолчанию
- Можно отключить через настройку `posting.scheduler.enabled=false`
- Задачи выполняются асинхронно

---

## Поддерживаемые платформы

На данный момент поддерживается:

- **Facebook** - через Facebook Graph API v18.0

В будущем планируется поддержка:

- Instagram
- LinkedIn
- Telegram
- TikTok
- YouTube

---

## Получение Facebook Access Token

Для получения Facebook Access Token:

1. Перейдите на [Facebook Developers](https://developers.facebook.com/)
2. Создайте приложение
3. Добавьте продукт "Facebook Login"
4. Настройте OAuth и получите Access Token
5. Используйте полученный токен в API

**Важно:**

- Access Token имеет срок действия
- Для долгосрочного использования рекомендуется использовать Long-Lived Token
- Токен должен иметь разрешения `pages_manage_posts` для публикации

---

## Примеры React компонентов

### Компонент для настройки credentials

```jsx
import React, { useState } from 'react';

const CredentialsForm = ({ platform, onSave }) => {
  const [token, setToken] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    setError(null);

    try {
      const response = await fetch('/api/social-media/credentials', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${jwtToken}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          platform: platform,
          credentials: token,
        }),
      });

      const data = await response.json();

      if (data.success) {
        onSave();
        setToken('');
      } else {
        setError(data.error.message);
      }
    } catch (err) {
      setError('Ошибка сети');
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Access Token для {platform}:</label>
        <input
          type='text'
          value={token}
          onChange={(e) => setToken(e.target.value)}
          required
        />
      </div>
      {error && <div className='error'>{error}</div>}
      <button type='submit' disabled={loading}>
        {loading ? 'Сохранение...' : 'Сохранить'}
      </button>
    </form>
  );
};

export default CredentialsForm;
```

### Компонент для запуска стратегии

```jsx
import React, { useState } from 'react';

const StartStrategyButton = ({ strategyId, onStart }) => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const handleStart = async () => {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch(
        `/api/marketing/analysis/strategy/${strategyId}/start`,
        {
          method: 'POST',
          headers: {
            Authorization: `Bearer ${jwtToken}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({}),
        }
      );

      const data = await response.json();

      if (data.success) {
        onStart(data.data);
      } else {
        setError(data.error.message);
      }
    } catch (err) {
      setError('Ошибка сети');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <button onClick={handleStart} disabled={loading}>
        {loading ? 'Запуск...' : 'Запустить стратегию'}
      </button>
      {error && <div className='error'>{error}</div>}
    </div>
  );
};

export default StartStrategyButton;
```

---

## Часто задаваемые вопросы

### Q: Как часто проверяются задачи на выполнение?

A: Планировщик проверяет очередь каждую минуту.

### Q: Что происходит, если credentials истекли?

A: Задача получит статус `failed` с сообщением об ошибке. Необходимо обновить credentials и перезапустить стратегию.

### Q: Можно ли отменить выполнение стратегии?

A: На данный момент нет, но можно удалить credentials для платформы, что предотвратит выполнение будущих задач.

### Q: Как узнать статус выполнения задач?

A: Статусы задач можно получить через API (будет добавлено в будущих версиях).

### Q: Поддерживается ли публикация с изображениями?

A: На данный момент поддерживается только текстовая публикация. Поддержка изображений планируется в будущем.

---

## Версионирование API

Текущая версия: **v1**

Все endpoints могут изменяться в будущих версиях. При изменении API будет указана новая версия.

---

## Поддержка

При возникновении проблем:

1. Проверьте логи в консоли браузера
2. Убедитесь, что JWT токен валиден
3. Проверьте формат запросов согласно документации
4. Обратитесь к разработчикам с описанием проблемы
