# VH Posting System - Описание системы

**Версия:** 1.0
**Дата:** 2026-01-07
**Совместимость:** PHP 7.2+
**Хостинг:** reg.ru (shared hosting)

---

## Общее описание

VH Posting System — веб-приложение для работы с изображениями Flickr. Позволяет конвертировать ссылки в различные форматы для публикации на форумах, блогах и социальных сетях, а также напрямую публиковать в Telegram-каналы.

---

## Структура проекта

```
VH_posting_system/
├── index.php              # Главная страница (требует авторизации)
├── login.php              # Страница входа
├── setup.php              # Первоначальная настройка (создание админа)
├── api.php                # API эндпоинты для AJAX-запросов
├── config.php             # Конфигурация (API ключи) - НЕ в git
├── config.example.php     # Пример конфигурации
├── auth_config.php        # Данные пользователей - НЕ в git, создаётся автоматически
├── .htaccess              # Настройки Apache
├── .gitignore             # Исключения для git
│
├── classes/               # PHP классы
│   ├── Auth.php           # Система авторизации
│   ├── FlickrAPI.php      # Клиент Flickr API
│   ├── FlickrParser.php   # Парсер ссылок Flickr
│   ├── FormatGenerator.php # Генератор форматов вывода
│   └── TelegramBot.php    # Клиент Telegram Bot API
│
├── css/
│   └── style.css          # Стили интерфейса
│
├── js/
│   └── app.js             # Фронтенд логика
│
└── templates/             # (зарезервировано для шаблонов)
```

---

## Функциональные модули

### 1. Link Converter (Конвертер ссылок)

**Назначение:** Преобразование ссылок Flickr в различные форматы.

**Поддерживаемые входные форматы:**
- Страница фото: `https://www.flickr.com/photos/username/12345678901/`
- Короткая ссылка: `https://flic.kr/p/ABC123`
- Прямая ссылка: `https://live.staticflickr.com/65535/12345678901_abcdef1234_b.jpg`

**Форматы вывода:**

| Ключ | Название | Шаблон | Применение |
|------|----------|--------|------------|
| `bbcode` | BBCode | `[img]{url}[/img]` | Форумы phpBB, vBulletin, IPB |
| `bbcode_linked` | BBCode (clickable) | `[url={original}][img]{url}[/img][/url]` | Кликабельные превью |
| `html` | HTML | `<img src="{url}" alt="{title}">` | Веб-сайты |
| `html_linked` | HTML (clickable) | `<a href="{original}"><img...></a>` | Кликабельные изображения |
| `html_figure` | HTML Figure | `<figure>...</figure>` | Семантическая разметка |
| `markdown` | Markdown | `![{title}]({url})` | GitHub, Reddit |
| `markdown_linked` | Markdown (clickable) | `[![...](...)]({original})` | Кликабельные в Markdown |
| `url_only` | URL only | `{url}` | Просто ссылка |
| `url_list` | URL list (comma) | `{url}, {url}...` | Списки через запятую |

**Размеры изображений:**

| Размер | Суффикс | Размер (px) |
|--------|---------|-------------|
| Square | `_s` | 75×75 |
| LargeSquare | `_q` | 150×150 |
| Thumbnail | `_t` | 100 |
| Small | `_m` | 240 |
| Small320 | `_n` | 320 |
| Medium | (нет) | 500 |
| Medium640 | `_z` | 640 |
| Medium800 | `_c` | 800 |
| Large | `_b` | 1024 |
| Large1600 | `_h` | 1600 |
| Large2048 | `_k` | 2048 |
| Original | `_o` | Оригинал |

---

### 2. Flickr Gallery (Галерея Flickr)

**Назначение:** Просмотр и выбор фотографий из аккаунта Flickr.

**Возможности:**
- Просмотр всех фотографий пользователя
- Просмотр по альбомам (photosets)
- Поиск по названию/описанию
- Множественный выбор галочками
- Пагинация (50 фото на страницу)
- Превью в виде сетки

**Требует:** Flickr API Key + User ID

---

### 3. Telegram Post (Публикация в Telegram)

**Назначение:** Отправка фотографий и текста в Telegram-каналы.

**Возможности:**
- Отправка одной фотографии с подписью
- Отправка альбома (2-10 фото)
- Автоматическое разбиение больших альбомов (>10 фото)
- Выбор формата текста (HTML, Markdown, plain)
- Публикация в несколько каналов

**Ограничения Telegram:**
- Максимум 10 фото в одном альбоме
- Подпись только у первого фото в альбоме
- Бот должен быть администратором канала

---

### 4. Settings (Настройки)

**Возможности:**
- Проверка статуса подключения к Flickr API
- Проверка статуса Telegram бота
- Управление списком каналов
- Смена пароля пользователя

---

## Классы PHP

### Auth.php — Система авторизации

```php
class Auth {
    // Создание пользователя
    createUser($username, $password): bool

    // Смена пароля
    changePassword($username, $oldPassword, $newPassword): bool

    // Вход в систему
    login($username, $password, $ip): array

    // Запуск сессии
    startSession($username, $token): void

    // Проверка авторизации
    isAuthenticated($timeout = 3600): bool

    // Выход
    logout(): void

    // Текущий пользователь
    getCurrentUser(): ?string

    // Есть ли пользователи
    hasUsers(): bool

    // IP клиента
    static getClientIP(): string
}
```

**Безопасность:**
- Хеширование: Argon2ID (fallback на bcrypt)
- Защита от брутфорса: 5 попыток, блокировка 15 минут
- Таймаут сессии: 1 час
- Регенерация session ID при входе

---

### FlickrAPI.php — Клиент Flickr API

```php
class FlickrAPI {
    __construct($apiKey, $apiSecret, $userId = '')

    // Установить User ID
    setUserId($userId): void

    // Получить фотографии пользователя
    getPhotos($page = 1, $perPage = 50): array

    // Получить альбомы
    getPhotosets($page = 1, $perPage = 50): array

    // Фотографии из альбома
    getPhotosetPhotos($photosetId, $page, $perPage): array

    // Информация о фото
    getPhotoInfo($photoId): array

    // Доступные размеры фото
    getPhotoSizes($photoId): array

    // Поиск фотографий
    searchPhotos($query, $page, $perPage): array

    // Найти User ID по имени
    findUserByUsername($username): string
}
```

---

### FlickrParser.php — Парсер ссылок

```php
class FlickrParser {
    // Парсинг одной ссылки
    parse($url): ?array

    // Парсинг нескольких ссылок
    parseMultiple($input): array

    // Построение URL изображения
    buildImageUrl($photoInfo, $size = 'Large'): string

    // Доступные размеры
    getAvailableSizes(): array
}
```

---

### FormatGenerator.php — Генератор форматов

```php
class FormatGenerator {
    // Добавить кастомный формат
    addFormat($key, $name, $template, $separator, $description): void

    // Получить все форматы
    getFormats(): array

    // Сгенерировать для одного изображения
    generate($formatKey, $imageData): string

    // Сгенерировать для нескольких
    generateMultiple($formatKey, $images): string

    // Сгенерировать все форматы сразу
    generateAll($images): array
}
```

**Плейсхолдеры в шаблонах:**
- `{url}` — URL изображения выбранного размера
- `{original}` — URL оригинала
- `{title}` — Название фото
- `{description}` — Описание
- `{photo_id}` — ID фото
- `{width}`, `{height}` — Размеры

---

### TelegramBot.php — Клиент Telegram

```php
class TelegramBot {
    __construct($botToken)

    // Отправить текст
    sendMessage($chatId, $text, $parseMode, $disablePreview): array

    // Отправить фото
    sendPhoto($chatId, $photo, $caption, $parseMode): array

    // Отправить альбом
    sendMediaGroup($chatId, $photos, $caption, $parseMode): array

    // Умная публикация (авто-выбор метода)
    post($chatId, $photos, $text, $parseMode): array

    // Публикация в несколько каналов
    postToMultiple($chatIds, $photos, $text, $parseMode): array

    // Информация о боте
    getMe(): array

    // Информация о чате
    getChat($chatId): array

    // Проверка доступа к каналу
    validateChannel($chatId): array

    // Экранирование HTML
    static escapeHtml($text): string

    // Экранирование Markdown
    static escapeMarkdown($text): string
}
```

---

## API Endpoints (api.php)

| Action | Method | Параметры | Описание |
|--------|--------|-----------|----------|
| `convert` | POST | urls, size, format | Конвертация ссылок |
| `flickr_albums` | GET | — | Список альбомов |
| `flickr_photos` | GET | page, per_page, album_id, search | Список фото |
| `flickr_photo_sizes` | GET | photo_id | Размеры фото |
| `telegram_status` | GET | — | Статус бота |
| `telegram_channels` | GET | — | Список каналов |
| `telegram_post` | POST | channel_id, text, photos, parse_mode | Публикация |
| `change_password` | POST | current_password, new_password | Смена пароля |

---

## Конфигурация (config.php)

```php
return [
    'flickr' => [
        'api_key' => '',      // API ключ Flickr
        'api_secret' => '',   // API секрет
    ],
    'flickr_user_id' => '',   // ID пользователя (12345678@N00)

    'telegram' => [
        'bot_token' => '',    // Токен бота от @BotFather
        'channels' => [       // Список каналов
            ['id' => '@channel', 'name' => 'Название'],
        ],
    ],

    'default_size' => 'Large',

    'custom_formats' => [     // Кастомные форматы
        // 'key' => ['name' => '', 'template' => ''],
    ],
];
```

---

## Безопасность

### Защита файлов (.htaccess)
- Запрет листинга директорий
- Блокировка доступа к config.php, auth_config.php
- Блокировка прямого доступа к /classes/

### Защита авторизации
- Argon2ID/bcrypt хеширование
- Rate limiting (5 попыток / 15 минут блокировки)
- Session timeout (1 час)
- CSRF токены на формах
- Регенерация session ID

### Входные данные
- htmlspecialchars() для вывода
- Валидация URL при парсинге
- JSON-encode для API ответов

---

## Требования

### Сервер
- PHP 7.2+ (рекомендуется 7.4+)
- Расширения: curl, json, bcmath (для base58)
- Apache с mod_rewrite

### API ключи
- **Flickr:** https://www.flickr.com/services/apps/create/
- **Telegram:** @BotFather → /newbot

---

## Установка

1. Загрузить файлы на хостинг
2. Скопировать `config.example.php` → `config.php`
3. Заполнить API ключи в config.php
4. Открыть сайт → setup.php → создать админа
5. Войти через login.php

---

## Планируемые функции

- [ ] Drag & drop загрузка изображений
- [ ] История конвертаций
- [ ] Избранные форматы
- [ ] Темная тема
- [ ] Экспорт/импорт настроек
- [ ] Поддержка других фотохостингов (Imgur, etc.)

---

## Changelog

### v1.0 (2026-01-07)
- Начальная реализация
- Конвертер ссылок Flickr
- Интеграция с Flickr API
- Интеграция с Telegram Bot API
- Система авторизации
- Адаптация под PHP 7.2 (reg.ru)
