custom-gift-send


Namecustom-gift-send JSON
Version 3.0.0 PyPI version JSON
download
home_pagehttps://symphonious-kringle-d43f01.netlify.app/
SummaryУлучшенный асинхронный Python-модуль для Telegram Bot API с повышенной безопасностью, аналитикой и новыми функциями.
upload_time2025-07-17 20:44:59
maintainerNone
docs_urlNone
authorNsvl
requires_python>=3.8
licenseNone
keywords telegram bot api stars gift premium checklist business account circuitbreaker security analytics rate-limiting webhook
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Custom Gift Send - Улучшенный Асинхронный Telegram Bot API SDK 🎁✨🔒⚡

**custom-gift-send v3.0.0** — мощный, масштабируемый и безопасный асинхронный Python SDK для Telegram Bot API v9.1. Разработан для профессиональной работы с подарками, Telegram Stars, бизнес-ботами, мини-приложениями и автоматизацией рассылок.

## 🚀 Что нового в v3.0.0

### 📇 Архитектурные изменения

* **Полный переход к SDK-подходу**: все функции инкапсулированы в `CustomGiftSend`
* **Поддержка событий**: `on_event`, `on_sent`, `on_error`, `on_retry`
* **Расширяемая архитектура**: внедрение интерфейсов, DI, и `SecurityManagerV2`

### 🔒 Надежность и безопасность

* **Advanced SecurityConfig**: контроль доступа, сигнатуры, IP-фильтры, шифрование данных
* **Circuit Breaker & Retry Strategy**: восстановление после сбоев
* **Контроль лимитов**: `RateLimiter` с `RetryAfter`

### ⚖️ Масштабируемость и производительность

* **Async HTTP Pooling**: повторное использование соединений через `aiohttp`
* **SmartCache v2**: кэш с TTL, статистикой попаданий и автоочисткой
* **Batch Processing**: отправка подарков и сообщений партиями, с прогрессом и throttle

### 📊 Мониторинг и аналитика

* **Prometheus & JSON Metrics**: готовый экспорт
* **Health Check API**: `detailed_health_check()` с оценкой всех слоёв
* **Аналитика ошибок и производительности**: перцентили, throughput, детализация по методам

### 🌐 Новые функции

* `send_gift_at()` — отложенная отправка
* `batch_send_gifts()`, `bulk_send_message()` — массовые операции
* `upload_file_chunked()` / `download_file_chunked()`
* `get_cache_statistics()`, `clear_all_caches()`

## 📦 Установка

```bash
pip install custom-gift-send>=3.0.0
```

### Дополнительно:

```bash
pip install custom-gift-send[dev]       # Для разработки
pip install custom-gift-send[monitoring] # Метрики
pip install custom-gift-send[docs]      # Документация
```

## 🔧 Быстрый старт

```python
import asyncio
from custom_gift_send import CustomGiftSend, GiftAlias, SecurityConfig

async def main():
    bot = CustomGiftSend(
        token="ВАШ_ТОКЕН",
        security_config=SecurityConfig(
            enable_request_signing=True,
            enable_smart_caching=True,
            connection_pool_size=20,
            enable_metrics_export=True
        )
    )
    async with bot:
        await bot.send_simple_gift(chat_id=123456, gift_id=GiftAlias.PREMIUM_1_MONTH)

if __name__ == '__main__':
    asyncio.run(main())
```

## 🎯 Основные возможности

### 🎁 Работа с подарками

```python
# Простая отправка подарка
await bot.send_simple_gift(
    chat_id=123456,
    gift_id=GiftAlias.PREMIUM_3_MONTHS
)

# Отложенная отправка
await bot.send_gift_at(
    chat_id=123456,
    gift_id="premium_1_month",
    send_at=datetime.now() + timedelta(hours=1)
)

# Массовая отправка подарков
operations = [
    {"chat_id": 123456, "gift_id": GiftAlias.PREMIUM_1_MONTH},
    {"chat_id": 789012, "gift_id": GiftAlias.STAR_PACK_5}
]
results = await bot.batch_send_gifts(operations, max_concurrent=5)
```

### ⭐ Telegram Stars

```python
# Проверка баланса Stars
balance = await bot.get_star_balance()
print(f"Баланс Stars: {balance}")

# Возврат платежа
await bot.refund_star_payment(
    user_id=123456,
    telegram_payment_charge_id="charge_id"
)

# Получение состояния вывода средств
withdrawal_state = await bot.get_revenue_withdrawal_state()
```

### 📨 Массовые рассылки

```python
# Массовая отправка сообщений
chat_ids = [123456, 789012, 345678]
results = await bot.bulk_send_message(
    chat_ids=chat_ids,
    text="Привет! Это массовая рассылка",
    delay=0.1  # Задержка между отправками
)

# Отправка с прогрессом
async def progress_callback(sent, total):
    print(f"Отправлено: {sent}/{total}")

await bot.bulk_send_message_with_progress(
    chat_ids=chat_ids,
    text="Сообщение с прогрессом",
    progress_callback=progress_callback
)
```

### 📁 Работа с файлами

```python
# Загрузка больших файлов по частям
file_id = await bot.upload_file_chunked(
    file_path="large_video.mp4",
    chunk_size=1024*1024  # 1MB chunks
)

# Скачивание файлов по частям
await bot.download_file_chunked(
    file_path="path/to/file",
    output_path="downloaded_file.mp4",
    chunk_size=1024*1024
)
```

### 📊 Мониторинг и аналитика

```python
# Получение аналитики
analytics = bot.get_analytics()
print(f"Успешных запросов: {analytics['requests_success']}")
print(f"Среднее время ответа: {analytics['average_response_time']:.2f}s")

# Детальная проверка здоровья
health = await bot.detailed_health_check()
print(f"Общий статус: {health['overall_status']}")

# Экспорт метрик для Prometheus
prometheus_metrics = await bot.export_metrics(format='prometheus')
print(prometheus_metrics)

# Статистика кэша
cache_stats = await bot.get_cache_statistics()
print(f"Попаданий в кэш: {cache_stats['total_hits']}")
```

## 🔄 Основные методы SDK

| Метод                         | Назначение                     |
| ----------------------------- | ------------------------------ |
| `send_gift()`                 | Отправка подарка по ID         |
| `send_simple_gift()`          | Упрощённая отправка по enum    |
| `send_gift_at()`              | Отложенная отправка            |
| `gift_premium_subscription()` | Premium подписка               |
| `bulk_send_message()`         | Массовая рассылка              |
| `upload_file_chunked()`       | Загрузка по частям             |
| `export_metrics()`            | Метрики Prometheus или JSON    |
| `detailed_health_check()`     | Проверка состояния компонентов |
| `get_star_balance()`          | Баланс Stars                   |
| `get_cache_statistics()`      | Метрики кэша                   |

## 🔧 Конфигурация

### SecurityConfig

```python
from custom_gift_send import SecurityConfig

security_config = SecurityConfig(
    # Основные настройки
    max_request_size=50 * 1024 * 1024,  # 50MB
    rate_limit_requests=30,
    rate_limit_window=60,
    
    # Безопасность
    enable_request_signing=True,
    encrypt_sensitive_data=True,
    allowed_ips={"192.168.1.0/24", "10.0.0.0/8"},
    
    # Производительность
    connection_pool_size=100,
    max_concurrent_requests=50,
    enable_smart_caching=True,
    
    # Мониторинг
    enable_metrics_export=True,
    enable_detailed_logging=True
)

bot = CustomGiftSend(token="YOUR_TOKEN", security_config=security_config)
```

## 📈 Метрики и мониторинг

### Prometheus метрики

* `telegram_requests_total` - Общее количество запросов
* `telegram_requests_success_total` - Успешные запросы
* `telegram_requests_failed_total` - Неудачные запросы
* `telegram_cache_hits_total` - Попадания в кэш
* `telegram_cache_misses_total` - Промахи кэша
* `telegram_request_duration_seconds` - Время выполнения запросов
* `telegram_gifts_sent_total` - Отправленные подарки
* `telegram_messages_sent_total` - Отправленные сообщения

### Grafana Dashboard

```json
{
  "dashboard": {
    "title": "Custom Gift Send Metrics",
    "panels": [
      {
        "title": "Request Rate",
        "targets": [
          {
            "expr": "rate(telegram_requests_total[5m])"
          }
        ]
      },
      {
        "title": "Success Rate",
        "targets": [
          {
            "expr": "rate(telegram_requests_success_total[5m]) / rate(telegram_requests_total[5m]) * 100"
          }
        ]
      }
    ]
  }
}
```

## 🎭 Система событий

```python
from custom_gift_send import EventType, EventHandler, Event

class CustomEventHandler(EventHandler):
    async def handle(self, event: Event):
        if event.event_type == EventType.GIFT_SENT:
            print(f"Подарок отправлен: {event.data}")
        elif event.event_type == EventType.ERROR_OCCURRED:
            print(f"Ошибка: {event.data}")

# Добавление обработчика
handler = CustomEventHandler()
bot.add_event_handler(EventType.GIFT_SENT, handler)
bot.add_event_handler(EventType.ERROR_OCCURRED, handler)

# Использование декораторов
@bot.on_event(EventType.MESSAGE_SENT)
async def on_message_sent(event: Event):
    print(f"Сообщение отправлено в чат {event.data['chat_id']}")

@bot.on_error
async def on_error(event: Event):
    print(f"Произошла ошибка: {event.data['error']}")
```

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

### Отправка подарков с обработкой ошибок

```python
async def send_gift_safely(bot, chat_id, gift_id):
    try:
        message = await bot.send_simple_gift(chat_id, gift_id)
        print(f"Подарок отправлен: {message.message_id}")
        return True
    except TelegramForbiddenError:
        print(f"Бот заблокирован пользователем {chat_id}")
        return False
    except TelegramTooManyRequestsError as e:
        print(f"Превышен лимит запросов, ждем {e.retry_after} секунд")
        await asyncio.sleep(e.retry_after)
        return await send_gift_safely(bot, chat_id, gift_id)
    except Exception as e:
        print(f"Неожиданная ошибка: {e}")
        return False
```

### Мониторинг производительности

```python
async def monitor_bot_performance(bot):
    while True:
        health = await bot.detailed_health_check()
        analytics = bot.get_analytics()
        
        print(f"Статус: {health['overall_status']}")
        print(f"Успешность: {analytics['success_rate']:.1f}%")
        print(f"Среднее время ответа: {analytics['average_response_time']:.2f}s")
        
        if analytics['success_rate'] < 95:
            print("⚠️ Низкая успешность запросов!")
        
        await asyncio.sleep(60)  # Проверка каждую минуту
```

### Работа с кэшем

```python
# Получение статистики кэша
cache_stats = await bot.get_cache_statistics()
print(f"Размер кэша подарков: {cache_stats['gifts_cache']['size']}")
print(f"Процент попаданий: {cache_stats['gifts_cache']['hit_rate']:.1f}%")

# Очистка всех кэшей
await bot.clear_all_caches()

# Принудительное обновление кэша
gifts = await bot.get_available_gifts(force_refresh=True)
balance = await bot.get_star_balance(force_refresh=True)
```

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

### Настройка безопасности

```python
security_config = SecurityConfig(
    # IP фильтрация
    allowed_ips={"192.168.1.0/24", "10.0.0.0/8"},
    
    # Подписи запросов
    enable_request_signing=True,
    webhook_secret_token="your_secret_token",
    
    # Шифрование
    encrypt_sensitive_data=True,
    
    # Лимиты
    max_request_size=50 * 1024 * 1024,
    max_concurrent_requests=100,
    rate_limit_requests=30,
    rate_limit_window=60
)
```

### Валидация webhook

```python
def validate_webhook_ip(data: dict) -> bool:
    # Проверка IP адреса webhook
    return True  # Ваша логика

def validate_webhook_signature(data: dict) -> bool:
    # Проверка подписи webhook
    return True  # Ваша логика

bot.add_webhook_validator(validate_webhook_ip)
bot.add_webhook_validator(validate_webhook_signature)
```

## 🔄 Graceful Shutdown

```python
import signal

async def main():
    bot = CustomGiftSend(token="YOUR_TOKEN")
    
    # Обработка сигналов для graceful shutdown
    def signal_handler(signum, frame):
        print("Получен сигнал завершения, закрываем бота...")
        asyncio.create_task(bot.close())
    
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    async with bot:
        # Ваш код здесь
        await bot.send_message(123456, "Бот запущен!")
        
        # Бесконечный цикл обработки обновлений
        async for update in bot.updates_stream():
            # Обработка обновлений
            pass

if __name__ == '__main__':
    asyncio.run(main())
```

## 📚 Документация и поддержка

* [GitHub](https://github.com/Nsvl/custom-gift-send)
* [Wiki](https://github.com/Nsvl/custom-gift-send/wiki)
* [Telegram канал](https://t.me/GifterChannel)

## 🤝 Вклад в проект

Мы приветствуем вклад в развитие проекта! Пожалуйста:

1. Форкните репозиторий
2. Создайте ветку для новой функции (`git checkout -b feature/amazing-feature`)
3. Зафиксируйте изменения (`git commit -m 'Add amazing feature'`)
4. Отправьте в ветку (`git push origin feature/amazing-feature`)
5. Откройте Pull Request

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

* Python 3.8+
* aiohttp >= 3.8.0
* pydantic >= 2.0.0
* cryptography >= 3.0.0
* cachetools >= 5.0.0
* pybreaker >= 1.0.0

## 🧪 Тестирование

```bash
# Установка зависимостей для разработки
pip install custom-gift-send[dev]

# Запуск тестов
pytest tests/

# Запуск с покрытием
pytest --cov=custom_gift_send tests/

# Линтинг
flake8 custom_gift_send/
black custom_gift_send/
mypy custom_gift_send/
```

## 📊 Бенчмарки

| Операция | Время выполнения | RPS |
|----------|------------------|-----|
| send_message | ~50ms | 1000+ |
| send_gift | ~100ms | 500+ |
| get_updates | ~30ms | 2000+ |
| bulk_send (100 msg) | ~5s | 20 batches/s |

## 🎉 Автор

Разработано [@Spikov](https://github.com/Nsvl) 

## 🌟 Лицензия

MIT License - см. файл [LICENSE](LICENSE) для подробностей.

            

Raw data

            {
    "_id": null,
    "home_page": "https://symphonious-kringle-d43f01.netlify.app/",
    "name": "custom-gift-send",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "telegram bot api stars gift premium checklist business account circuitbreaker security analytics rate-limiting webhook",
    "author": "Nsvl",
    "author_email": "huff-outer-siding@duck.com",
    "download_url": "https://files.pythonhosted.org/packages/e0/8f/51730518883633879edc93951548e6ea383a2c83f3a3a71f696194e37777/custom_gift_send-3.0.0.tar.gz",
    "platform": null,
    "description": "# Custom Gift Send - \u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u044b\u0439 \u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 Telegram Bot API SDK \ud83c\udf81\u2728\ud83d\udd12\u26a1\r\n\r\n**custom-gift-send v3.0.0** \u2014 \u043c\u043e\u0449\u043d\u044b\u0439, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 Python SDK \u0434\u043b\u044f Telegram Bot API v9.1. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0434\u0430\u0440\u043a\u0430\u043c\u0438, Telegram Stars, \u0431\u0438\u0437\u043d\u0435\u0441-\u0431\u043e\u0442\u0430\u043c\u0438, \u043c\u0438\u043d\u0438-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0440\u0430\u0441\u0441\u044b\u043b\u043e\u043a.\r\n\r\n## \ud83d\ude80 \u0427\u0442\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0432 v3.0.0\r\n\r\n### \ud83d\udcc7 \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\r\n\r\n* **\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043a SDK-\u043f\u043e\u0434\u0445\u043e\u0434\u0443**: \u0432\u0441\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432 `CustomGiftSend`\r\n* **\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439**: `on_event`, `on_sent`, `on_error`, `on_retry`\r\n* **\u0420\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430**: \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432, DI, \u0438 `SecurityManagerV2`\r\n\r\n### \ud83d\udd12 \u041d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\r\n\r\n* **Advanced SecurityConfig**: \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0430, \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b, IP-\u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\r\n* **Circuit Breaker & Retry Strategy**: \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0435\u0432\r\n* **\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043b\u0438\u043c\u0438\u0442\u043e\u0432**: `RateLimiter` \u0441 `RetryAfter`\r\n\r\n### \u2696\ufe0f \u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\r\n\r\n* **Async HTTP Pooling**: \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 `aiohttp`\r\n* **SmartCache v2**: \u043a\u044d\u0448 \u0441 TTL, \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u043e\u0439 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0439 \u0438 \u0430\u0432\u0442\u043e\u043e\u0447\u0438\u0441\u0442\u043a\u043e\u0439\r\n* **Batch Processing**: \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0434\u0430\u0440\u043a\u043e\u0432 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0442\u0438\u044f\u043c\u0438, \u0441 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u043e\u043c \u0438 throttle\r\n\r\n### \ud83d\udcca \u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\r\n\r\n* **Prometheus & JSON Metrics**: \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\r\n* **Health Check API**: `detailed_health_check()` \u0441 \u043e\u0446\u0435\u043d\u043a\u043e\u0439 \u0432\u0441\u0435\u0445 \u0441\u043b\u043e\u0451\u0432\r\n* **\u0410\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438**: \u043f\u0435\u0440\u0446\u0435\u043d\u0442\u0438\u043b\u0438, throughput, \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e \u043c\u0435\u0442\u043e\u0434\u0430\u043c\r\n\r\n### \ud83c\udf10 \u041d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438\r\n\r\n* `send_gift_at()` \u2014 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430\r\n* `batch_send_gifts()`, `bulk_send_message()` \u2014 \u043c\u0430\u0441\u0441\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438\r\n* `upload_file_chunked()` / `download_file_chunked()`\r\n* `get_cache_statistics()`, `clear_all_caches()`\r\n\r\n## \ud83d\udce6 \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\r\n\r\n```bash\r\npip install custom-gift-send>=3.0.0\r\n```\r\n\r\n### \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e:\r\n\r\n```bash\r\npip install custom-gift-send[dev]       # \u0414\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438\r\npip install custom-gift-send[monitoring] # \u041c\u0435\u0442\u0440\u0438\u043a\u0438\r\npip install custom-gift-send[docs]      # \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f\r\n```\r\n\r\n## \ud83d\udd27 \u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442\r\n\r\n```python\r\nimport asyncio\r\nfrom custom_gift_send import CustomGiftSend, GiftAlias, SecurityConfig\r\n\r\nasync def main():\r\n    bot = CustomGiftSend(\r\n        token=\"\u0412\u0410\u0428_\u0422\u041e\u041a\u0415\u041d\",\r\n        security_config=SecurityConfig(\r\n            enable_request_signing=True,\r\n            enable_smart_caching=True,\r\n            connection_pool_size=20,\r\n            enable_metrics_export=True\r\n        )\r\n    )\r\n    async with bot:\r\n        await bot.send_simple_gift(chat_id=123456, gift_id=GiftAlias.PREMIUM_1_MONTH)\r\n\r\nif __name__ == '__main__':\r\n    asyncio.run(main())\r\n```\r\n\r\n## \ud83c\udfaf \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\r\n\r\n### \ud83c\udf81 \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u043f\u043e\u0434\u0430\u0440\u043a\u0430\u043c\u0438\r\n\r\n```python\r\n# \u041f\u0440\u043e\u0441\u0442\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0434\u0430\u0440\u043a\u0430\r\nawait bot.send_simple_gift(\r\n    chat_id=123456,\r\n    gift_id=GiftAlias.PREMIUM_3_MONTHS\r\n)\r\n\r\n# \u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430\r\nawait bot.send_gift_at(\r\n    chat_id=123456,\r\n    gift_id=\"premium_1_month\",\r\n    send_at=datetime.now() + timedelta(hours=1)\r\n)\r\n\r\n# \u041c\u0430\u0441\u0441\u043e\u0432\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0434\u0430\u0440\u043a\u043e\u0432\r\noperations = [\r\n    {\"chat_id\": 123456, \"gift_id\": GiftAlias.PREMIUM_1_MONTH},\r\n    {\"chat_id\": 789012, \"gift_id\": GiftAlias.STAR_PACK_5}\r\n]\r\nresults = await bot.batch_send_gifts(operations, max_concurrent=5)\r\n```\r\n\r\n### \u2b50 Telegram Stars\r\n\r\n```python\r\n# \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0430 Stars\r\nbalance = await bot.get_star_balance()\r\nprint(f\"\u0411\u0430\u043b\u0430\u043d\u0441 Stars: {balance}\")\r\n\r\n# \u0412\u043e\u0437\u0432\u0440\u0430\u0442 \u043f\u043b\u0430\u0442\u0435\u0436\u0430\r\nawait bot.refund_star_payment(\r\n    user_id=123456,\r\n    telegram_payment_charge_id=\"charge_id\"\r\n)\r\n\r\n# \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\r\nwithdrawal_state = await bot.get_revenue_withdrawal_state()\r\n```\r\n\r\n### \ud83d\udce8 \u041c\u0430\u0441\u0441\u043e\u0432\u044b\u0435 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438\r\n\r\n```python\r\n# \u041c\u0430\u0441\u0441\u043e\u0432\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439\r\nchat_ids = [123456, 789012, 345678]\r\nresults = await bot.bulk_send_message(\r\n    chat_ids=chat_ids,\r\n    text=\"\u041f\u0440\u0438\u0432\u0435\u0442! \u042d\u0442\u043e \u043c\u0430\u0441\u0441\u043e\u0432\u0430\u044f \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0430\",\r\n    delay=0.1  # \u0417\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430\u043c\u0438\r\n)\r\n\r\n# \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u043e\u043c\r\nasync def progress_callback(sent, total):\r\n    print(f\"\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e: {sent}/{total}\")\r\n\r\nawait bot.bulk_send_message_with_progress(\r\n    chat_ids=chat_ids,\r\n    text=\"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u043e\u043c\",\r\n    progress_callback=progress_callback\r\n)\r\n```\r\n\r\n### \ud83d\udcc1 \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438\r\n\r\n```python\r\n# \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c\r\nfile_id = await bot.upload_file_chunked(\r\n    file_path=\"large_video.mp4\",\r\n    chunk_size=1024*1024  # 1MB chunks\r\n)\r\n\r\n# \u0421\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c\r\nawait bot.download_file_chunked(\r\n    file_path=\"path/to/file\",\r\n    output_path=\"downloaded_file.mp4\",\r\n    chunk_size=1024*1024\r\n)\r\n```\r\n\r\n### \ud83d\udcca \u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\r\n\r\n```python\r\n# \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438\r\nanalytics = bot.get_analytics()\r\nprint(f\"\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432: {analytics['requests_success']}\")\r\nprint(f\"\u0421\u0440\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0432\u0435\u0442\u0430: {analytics['average_response_time']:.2f}s\")\r\n\r\n# \u0414\u0435\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u044f\r\nhealth = await bot.detailed_health_check()\r\nprint(f\"\u041e\u0431\u0449\u0438\u0439 \u0441\u0442\u0430\u0442\u0443\u0441: {health['overall_status']}\")\r\n\r\n# \u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u043c\u0435\u0442\u0440\u0438\u043a \u0434\u043b\u044f Prometheus\r\nprometheus_metrics = await bot.export_metrics(format='prometheus')\r\nprint(prometheus_metrics)\r\n\r\n# \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043a\u044d\u0448\u0430\r\ncache_stats = await bot.get_cache_statistics()\r\nprint(f\"\u041f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0439 \u0432 \u043a\u044d\u0448: {cache_stats['total_hits']}\")\r\n```\r\n\r\n## \ud83d\udd04 \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b SDK\r\n\r\n| \u041c\u0435\u0442\u043e\u0434                         | \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435                     |\r\n| ----------------------------- | ------------------------------ |\r\n| `send_gift()`                 | \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0434\u0430\u0440\u043a\u0430 \u043f\u043e ID         |\r\n| `send_simple_gift()`          | \u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e enum    |\r\n| `send_gift_at()`              | \u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430            |\r\n| `gift_premium_subscription()` | Premium \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430               |\r\n| `bulk_send_message()`         | \u041c\u0430\u0441\u0441\u043e\u0432\u0430\u044f \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0430              |\r\n| `upload_file_chunked()`       | \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c             |\r\n| `export_metrics()`            | \u041c\u0435\u0442\u0440\u0438\u043a\u0438 Prometheus \u0438\u043b\u0438 JSON    |\r\n| `detailed_health_check()`     | \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 |\r\n| `get_star_balance()`          | \u0411\u0430\u043b\u0430\u043d\u0441 Stars                   |\r\n| `get_cache_statistics()`      | \u041c\u0435\u0442\u0440\u0438\u043a\u0438 \u043a\u044d\u0448\u0430                   |\r\n\r\n## \ud83d\udd27 \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\r\n\r\n### SecurityConfig\r\n\r\n```python\r\nfrom custom_gift_send import SecurityConfig\r\n\r\nsecurity_config = SecurityConfig(\r\n    # \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\r\n    max_request_size=50 * 1024 * 1024,  # 50MB\r\n    rate_limit_requests=30,\r\n    rate_limit_window=60,\r\n    \r\n    # \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\r\n    enable_request_signing=True,\r\n    encrypt_sensitive_data=True,\r\n    allowed_ips={\"192.168.1.0/24\", \"10.0.0.0/8\"},\r\n    \r\n    # \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\r\n    connection_pool_size=100,\r\n    max_concurrent_requests=50,\r\n    enable_smart_caching=True,\r\n    \r\n    # \u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\r\n    enable_metrics_export=True,\r\n    enable_detailed_logging=True\r\n)\r\n\r\nbot = CustomGiftSend(token=\"YOUR_TOKEN\", security_config=security_config)\r\n```\r\n\r\n## \ud83d\udcc8 \u041c\u0435\u0442\u0440\u0438\u043a\u0438 \u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\r\n\r\n### Prometheus \u043c\u0435\u0442\u0440\u0438\u043a\u0438\r\n\r\n* `telegram_requests_total` - \u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\r\n* `telegram_requests_success_total` - \u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b\r\n* `telegram_requests_failed_total` - \u041d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b\r\n* `telegram_cache_hits_total` - \u041f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043a\u044d\u0448\r\n* `telegram_cache_misses_total` - \u041f\u0440\u043e\u043c\u0430\u0445\u0438 \u043a\u044d\u0448\u0430\r\n* `telegram_request_duration_seconds` - \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\r\n* `telegram_gifts_sent_total` - \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u0430\u0440\u043a\u0438\r\n* `telegram_messages_sent_total` - \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\r\n\r\n### Grafana Dashboard\r\n\r\n```json\r\n{\r\n  \"dashboard\": {\r\n    \"title\": \"Custom Gift Send Metrics\",\r\n    \"panels\": [\r\n      {\r\n        \"title\": \"Request Rate\",\r\n        \"targets\": [\r\n          {\r\n            \"expr\": \"rate(telegram_requests_total[5m])\"\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"title\": \"Success Rate\",\r\n        \"targets\": [\r\n          {\r\n            \"expr\": \"rate(telegram_requests_success_total[5m]) / rate(telegram_requests_total[5m]) * 100\"\r\n          }\r\n        ]\r\n      }\r\n    ]\r\n  }\r\n}\r\n```\r\n\r\n## \ud83c\udfad \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439\r\n\r\n```python\r\nfrom custom_gift_send import EventType, EventHandler, Event\r\n\r\nclass CustomEventHandler(EventHandler):\r\n    async def handle(self, event: Event):\r\n        if event.event_type == EventType.GIFT_SENT:\r\n            print(f\"\u041f\u043e\u0434\u0430\u0440\u043e\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d: {event.data}\")\r\n        elif event.event_type == EventType.ERROR_OCCURRED:\r\n            print(f\"\u041e\u0448\u0438\u0431\u043a\u0430: {event.data}\")\r\n\r\n# \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\r\nhandler = CustomEventHandler()\r\nbot.add_event_handler(EventType.GIFT_SENT, handler)\r\nbot.add_event_handler(EventType.ERROR_OCCURRED, handler)\r\n\r\n# \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u043e\u0432\r\n@bot.on_event(EventType.MESSAGE_SENT)\r\nasync def on_message_sent(event: Event):\r\n    print(f\"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u0447\u0430\u0442 {event.data['chat_id']}\")\r\n\r\n@bot.on_error\r\nasync def on_error(event: Event):\r\n    print(f\"\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430: {event.data['error']}\")\r\n```\r\n\r\n## \u26a1 \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f\r\n\r\n### \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0434\u0430\u0440\u043a\u043e\u0432 \u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043e\u0448\u0438\u0431\u043e\u043a\r\n\r\n```python\r\nasync def send_gift_safely(bot, chat_id, gift_id):\r\n    try:\r\n        message = await bot.send_simple_gift(chat_id, gift_id)\r\n        print(f\"\u041f\u043e\u0434\u0430\u0440\u043e\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d: {message.message_id}\")\r\n        return True\r\n    except TelegramForbiddenError:\r\n        print(f\"\u0411\u043e\u0442 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c {chat_id}\")\r\n        return False\r\n    except TelegramTooManyRequestsError as e:\r\n        print(f\"\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d \u043b\u0438\u043c\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0436\u0434\u0435\u043c {e.retry_after} \u0441\u0435\u043a\u0443\u043d\u0434\")\r\n        await asyncio.sleep(e.retry_after)\r\n        return await send_gift_safely(bot, chat_id, gift_id)\r\n    except Exception as e:\r\n        print(f\"\u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430: {e}\")\r\n        return False\r\n```\r\n\r\n### \u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438\r\n\r\n```python\r\nasync def monitor_bot_performance(bot):\r\n    while True:\r\n        health = await bot.detailed_health_check()\r\n        analytics = bot.get_analytics()\r\n        \r\n        print(f\"\u0421\u0442\u0430\u0442\u0443\u0441: {health['overall_status']}\")\r\n        print(f\"\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0441\u0442\u044c: {analytics['success_rate']:.1f}%\")\r\n        print(f\"\u0421\u0440\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0432\u0435\u0442\u0430: {analytics['average_response_time']:.2f}s\")\r\n        \r\n        if analytics['success_rate'] < 95:\r\n            print(\"\u26a0\ufe0f \u041d\u0438\u0437\u043a\u0430\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432!\")\r\n        \r\n        await asyncio.sleep(60)  # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u043c\u0438\u043d\u0443\u0442\u0443\r\n```\r\n\r\n### \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u044d\u0448\u0435\u043c\r\n\r\n```python\r\n# \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043a\u044d\u0448\u0430\r\ncache_stats = await bot.get_cache_statistics()\r\nprint(f\"\u0420\u0430\u0437\u043c\u0435\u0440 \u043a\u044d\u0448\u0430 \u043f\u043e\u0434\u0430\u0440\u043a\u043e\u0432: {cache_stats['gifts_cache']['size']}\")\r\nprint(f\"\u041f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0439: {cache_stats['gifts_cache']['hit_rate']:.1f}%\")\r\n\r\n# \u041e\u0447\u0438\u0441\u0442\u043a\u0430 \u0432\u0441\u0435\u0445 \u043a\u044d\u0448\u0435\u0439\r\nawait bot.clear_all_caches()\r\n\r\n# \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u044d\u0448\u0430\r\ngifts = await bot.get_available_gifts(force_refresh=True)\r\nbalance = await bot.get_star_balance(force_refresh=True)\r\n```\r\n\r\n## \ud83d\udea7 \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\r\n\r\n### \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438\r\n\r\n```python\r\nsecurity_config = SecurityConfig(\r\n    # IP \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f\r\n    allowed_ips={\"192.168.1.0/24\", \"10.0.0.0/8\"},\r\n    \r\n    # \u041f\u043e\u0434\u043f\u0438\u0441\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\r\n    enable_request_signing=True,\r\n    webhook_secret_token=\"your_secret_token\",\r\n    \r\n    # \u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435\r\n    encrypt_sensitive_data=True,\r\n    \r\n    # \u041b\u0438\u043c\u0438\u0442\u044b\r\n    max_request_size=50 * 1024 * 1024,\r\n    max_concurrent_requests=100,\r\n    rate_limit_requests=30,\r\n    rate_limit_window=60\r\n)\r\n```\r\n\r\n### \u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f webhook\r\n\r\n```python\r\ndef validate_webhook_ip(data: dict) -> bool:\r\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 IP \u0430\u0434\u0440\u0435\u0441\u0430 webhook\r\n    return True  # \u0412\u0430\u0448\u0430 \u043b\u043e\u0433\u0438\u043a\u0430\r\n\r\ndef validate_webhook_signature(data: dict) -> bool:\r\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u0438 webhook\r\n    return True  # \u0412\u0430\u0448\u0430 \u043b\u043e\u0433\u0438\u043a\u0430\r\n\r\nbot.add_webhook_validator(validate_webhook_ip)\r\nbot.add_webhook_validator(validate_webhook_signature)\r\n```\r\n\r\n## \ud83d\udd04 Graceful Shutdown\r\n\r\n```python\r\nimport signal\r\n\r\nasync def main():\r\n    bot = CustomGiftSend(token=\"YOUR_TOKEN\")\r\n    \r\n    # \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432 \u0434\u043b\u044f graceful shutdown\r\n    def signal_handler(signum, frame):\r\n        print(\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0441\u0438\u0433\u043d\u0430\u043b \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f, \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0431\u043e\u0442\u0430...\")\r\n        asyncio.create_task(bot.close())\r\n    \r\n    signal.signal(signal.SIGINT, signal_handler)\r\n    signal.signal(signal.SIGTERM, signal_handler)\r\n    \r\n    async with bot:\r\n        # \u0412\u0430\u0448 \u043a\u043e\u0434 \u0437\u0434\u0435\u0441\u044c\r\n        await bot.send_message(123456, \"\u0411\u043e\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d!\")\r\n        \r\n        # \u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439\r\n        async for update in bot.updates_stream():\r\n            # \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439\r\n            pass\r\n\r\nif __name__ == '__main__':\r\n    asyncio.run(main())\r\n```\r\n\r\n## \ud83d\udcda \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430\r\n\r\n* [GitHub](https://github.com/Nsvl/custom-gift-send)\r\n* [Wiki](https://github.com/Nsvl/custom-gift-send/wiki)\r\n* [Telegram \u043a\u0430\u043d\u0430\u043b](https://t.me/GifterChannel)\r\n\r\n## \ud83e\udd1d \u0412\u043a\u043b\u0430\u0434 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\r\n\r\n\u041c\u044b \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u043c \u0432\u043a\u043b\u0430\u0434 \u0432 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430! \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430:\r\n\r\n1. \u0424\u043e\u0440\u043a\u043d\u0438\u0442\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439\r\n2. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0432\u0435\u0442\u043a\u0443 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (`git checkout -b feature/amazing-feature`)\r\n3. \u0417\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0439\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f (`git commit -m 'Add amazing feature'`)\r\n4. \u041e\u0442\u043f\u0440\u0430\u0432\u044c\u0442\u0435 \u0432 \u0432\u0435\u0442\u043a\u0443 (`git push origin feature/amazing-feature`)\r\n5. \u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 Pull Request\r\n\r\n## \ud83d\udccb \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\r\n\r\n* Python 3.8+\r\n* aiohttp >= 3.8.0\r\n* pydantic >= 2.0.0\r\n* cryptography >= 3.0.0\r\n* cachetools >= 5.0.0\r\n* pybreaker >= 1.0.0\r\n\r\n## \ud83e\uddea \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\r\n\r\n```bash\r\n# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438\r\npip install custom-gift-send[dev]\r\n\r\n# \u0417\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432\r\npytest tests/\r\n\r\n# \u0417\u0430\u043f\u0443\u0441\u043a \u0441 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435\u043c\r\npytest --cov=custom_gift_send tests/\r\n\r\n# \u041b\u0438\u043d\u0442\u0438\u043d\u0433\r\nflake8 custom_gift_send/\r\nblack custom_gift_send/\r\nmypy custom_gift_send/\r\n```\r\n\r\n## \ud83d\udcca \u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0438\r\n\r\n| \u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f | \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f | RPS |\r\n|----------|------------------|-----|\r\n| send_message | ~50ms | 1000+ |\r\n| send_gift | ~100ms | 500+ |\r\n| get_updates | ~30ms | 2000+ |\r\n| bulk_send (100 msg) | ~5s | 20 batches/s |\r\n\r\n## \ud83c\udf89 \u0410\u0432\u0442\u043e\u0440\r\n\r\n\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043e [@Spikov](https://github.com/Nsvl) \r\n\r\n## \ud83c\udf1f \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f\r\n\r\nMIT License - \u0441\u043c. \u0444\u0430\u0439\u043b [LICENSE](LICENSE) \u0434\u043b\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0435\u0439.\r\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u044b\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 Python-\u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f Telegram Bot API \u0441 \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u044e, \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u043e\u0439 \u0438 \u043d\u043e\u0432\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438.",
    "version": "3.0.0",
    "project_urls": {
        "Bug Reports": "https://github.com/Nsvl/custom-gift-send/issues",
        "Documentation": "https://github.com/Nsvl/custom-gift-send/wiki",
        "Homepage": "https://symphonious-kringle-d43f01.netlify.app/",
        "Source": "https://github.com/Nsvl/custom-gift-send",
        "Telegram Channel": "https://t.me/GifterChannel"
    },
    "split_keywords": [
        "telegram",
        "bot",
        "api",
        "stars",
        "gift",
        "premium",
        "checklist",
        "business",
        "account",
        "circuitbreaker",
        "security",
        "analytics",
        "rate-limiting",
        "webhook"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c26d51a713ed48b883ede3a419e450959cc724498a86ec8437ca4d57ea26117c",
                "md5": "5aae50573628262c8cd79f5068b662f2",
                "sha256": "264ed44309c92bf97f6a87360e80e0bbf43855ad0f8ee13f7cbcac18c8ae68f7"
            },
            "downloads": -1,
            "filename": "custom_gift_send-3.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "5aae50573628262c8cd79f5068b662f2",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 38309,
            "upload_time": "2025-07-17T20:44:57",
            "upload_time_iso_8601": "2025-07-17T20:44:57.826079Z",
            "url": "https://files.pythonhosted.org/packages/c2/6d/51a713ed48b883ede3a419e450959cc724498a86ec8437ca4d57ea26117c/custom_gift_send-3.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e08f51730518883633879edc93951548e6ea383a2c83f3a3a71f696194e37777",
                "md5": "560d4a353811705dc3e353da7d25113c",
                "sha256": "e751741404c9f9320ed2e230c2a646c569d3383de6b8eaf14c07eae1208bf67d"
            },
            "downloads": -1,
            "filename": "custom_gift_send-3.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "560d4a353811705dc3e353da7d25113c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 43348,
            "upload_time": "2025-07-17T20:44:59",
            "upload_time_iso_8601": "2025-07-17T20:44:59.867043Z",
            "url": "https://files.pythonhosted.org/packages/e0/8f/51730518883633879edc93951548e6ea383a2c83f3a3a71f696194e37777/custom_gift_send-3.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-17 20:44:59",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Nsvl",
    "github_project": "custom-gift-send",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "custom-gift-send"
}
        
Elapsed time: 0.46063s