diff --git a/README.md b/README.md index 163b917..6e8becb 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,39 @@ # OLGram -Конструктор ботов обратной связи в Telegram +[@olgram](https://t.me/olgrambot) - конструктор ботов обратной связи в Telegram [![Static Analysis Status](https://github.com/civsocit/olgram/workflows/Linter/badge.svg)](https://github.com/civsocit/olgram/actions?workflow=Linter) [![Deploy Status](https://github.com/civsocit/olgram/workflows/Deploy/badge.svg)](https://github.com/civsocit/olgram/actions?workflow=Deploy) +![Logo](media/logo1_big.png) +## Возможности и преимущества Olgram Bot + +* **Общение с клиентами**. После подключения бота, вы сможете общаться с вашими пользователями бота через диалог с ботом, либо подключенный отдельно чат, где может находиться ваш колл-центр. +* **Все типы сообщений**. Livegram боты поддерживают все типы сообщений — текст, фото, видео, голосовые сообщения и стикеры. +* **Open-source**. В отличие от известного проекта Livegram код нашего конструктора полностью открыт. +* **Self-hosted**. Вы можете развернуть свой собственный конструктор, если не доверяете нашему. +* **Безопасность**. В отличие от Livegram, мы не храним сообщения, которые вы отправляете в бот. А наши сервера располагаются в Германии, что делает проект неподконтрольным российским властям. + + +По любым вопросам, связанным с Olgram, пишите в наш бот обратной связи @civsocit_feedback_bot + +### Для разработчиков: сборка и запуск проекта + +Вам потребуется собственный VPS или любой хост со статическим адресом или доменом. +* Создайте файл .env и заполните его по образцу example.env. Вам нужно заполнить переменные: +** BOT_TOKEN - токен нового бота, получить у @botfather +** POSTGRES_PASSWORD - любой случайный пароль +** WEBHOOK_HOST - IP адрес или доменное имя сервера, на котором запускается проект +* Сохраните файл docker-compose.yaml и соберите его: +``` +sudo docker-compose up -d +``` + +В docker-compose.yaml минимальная конфигурация. Для использования в серьёзных проектах мы советуем: +* Приобрести домен и настроить его на свой хост +* Наладить реверс-прокси и автоматическое обновление сертификатов - например, с помощью [Traefik](https://github.com/traefik/traefik) +* Скрыть IP сервера с помощью [Cloudflire](https://www.cloudflare.com), чтобы пользователи ботов не могли найти IP адрес +хоста по Webhook бота. + +Пример более сложной конфигурации есть в файле docker-compose-full.yaml diff --git a/docker-compose-full.yaml b/docker-compose-full.yaml new file mode 100644 index 0000000..111bc16 --- /dev/null +++ b/docker-compose-full.yaml @@ -0,0 +1,81 @@ +version: '3' +services: + postgres: + image: postgres + restart: unless-stopped + env_file: + - release.env + volumes: + - database:/var/lib/postgresql/data + networks: + - traefik + redis: + image: 'bitnami/redis:latest' + restart: unless-stopped + environment: + - ALLOW_EMPTY_PASSWORD=yes + volumes: + - redis-db:/bitnami/redis/data + env_file: + - release.env + networks: + - traefik + olgram: + image: ghcr.io/civsocit/olgram/bot:stable + restart: unless-stopped + networks: + - traefik + labels: + - 'com.centurylinklabs.watchtower.enable="true"' + - "traefik.enable=true" + - "traefik.http.routers.static.rule=Host(`bot.civsoc.com`)" + - "traefik.http.routers.static.tls=true" + - "traefik.http.routers.static.tls.certresolver=le" + - "traefik.http.routers.static.entrypoints=websecure" + - "traefik.docker.network=traefik" + env_file: + - release.env + depends_on: + - postgres + - redis + watchtower: + image: containrrr/watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./config.json:/config.json + command: --interval 30 + networks: + - traefik + traefik: + image: traefik:v2.4 + container_name: olgram_traefik + restart: unless-stopped + ports: + - "80:80" + - "443:443" + networks: + - traefik + volumes: + - /etc/localtime:/etc/localtime:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./acme:/acme + command: + - --entrypoints.web.address=:80 + - --entrypoints.websecure.address=:443 + - --providers.docker=true + - --providers.docker.endpoint=unix:///var/run/docker.sock + - --providers.docker.exposedByDefault=false + - --providers.docker.network=traefik + - --certificatesresolvers.le.acme.email=feedback@civsoc.com + - --certificatesresolvers.le.acme.storage=/acme/acme.json + - --certificatesresolvers.le.acme.tlschallenge=false + - --certificatesresolvers.le.acme.httpchallenge=true + - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web + +volumes: + database: + redis-db: + +networks: + traefik: + driver: bridge diff --git a/docker-compose.yaml b/docker-compose.yaml index c8de0c1..47b17ff 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -7,8 +7,6 @@ services: - .env volumes: - database:/var/lib/postgresql/data - networks: - - default redis: image: 'bitnami/redis:latest' restart: unless-stopped @@ -18,13 +16,9 @@ services: - redis-db:/bitnami/redis/data env_file: - .env - networks: - - default olgram: image: ghcr.io/civsocit/olgram/bot:stable restart: unless-stopped - networks: - - default env_file: - .env volumes: @@ -39,7 +33,3 @@ volumes: database: redis-db: olgram-cert: - -networks: - default: - driver: bridge diff --git a/media/logo1_big.png b/media/logo1_big.png new file mode 100644 index 0000000..8a9441d Binary files /dev/null and b/media/logo1_big.png differ diff --git a/olgram/settings.py b/olgram/settings.py index ca0fba5..d280482 100644 --- a/olgram/settings.py +++ b/olgram/settings.py @@ -67,6 +67,10 @@ class ServerSettings(AbstractSettings): def public_path(cls) -> str: return "/cert/public.pem" + @classmethod + def append_text(cls) -> str: + return "\n\nЭтот бот создан с помощью @OlgramBot" + class BotSettings(AbstractSettings): @classmethod diff --git a/server/custom.py b/server/custom.py index b58323e..0068a03 100644 --- a/server/custom.py +++ b/server/custom.py @@ -32,7 +32,7 @@ async def message_handler(message, *args, **kwargs): if message.text and message.text.startswith("/start"): # На команду start нужно ответить, не пересылая сообщение никуда return SendMessage(chat_id=message.chat.id, - text=bot.start_text) + text=bot.start_text + ServerSettings.append_text()) super_chat_id = await bot.super_chat_id()