Giter Club home page Giter Club logo

donbarbos / telegram-bot-template Goto Github PK

View Code? Open in Web Editor NEW
228.0 6.0 44.0 4.02 MB

πŸ€– Template for telegram bot using postgres, pgbouncer, redis, docker, amplitude, prometheus, grafana, CI

License: GNU Lesser General Public License v3.0

Dockerfile 1.23% Python 67.25% CSS 0.81% JavaScript 5.55% HTML 24.53% Mako 0.63%
telegram-bot python aiogram-bot-template docker-compose postgresql aiogram docker poetry redis telegram telegram-bot-template telegrambot template telegram-bot-example database pydantic ruff sqlalchemy analytics metrics

telegram-bot-template's Introduction

Telegram bot template

Best way to create a scalable telegram bot with analytics

GitHub tag (latest SemVer) Linters Status Docker Build Status Python License Code style

✨ Features

πŸš€ How to Use

🐳 Running in Docker (recommended method)

  • configure environment variables in .env file

  • start services

    docker compose up -d --build

πŸ’» Running on Local Machine

  • install dependencies using Poetry

    poetry install
  • start the necessary services (at least the database and redis)

  • configure environment variables in .env file

  • start telegram bot

    poetry run python -m bot
  • start admin panel

    poetry run gunicorn -c admin/gunicorn_conf.py
  • make migrations

    poetry run alembic upgrade head

🌍 Environment variables

to launch the bot you only need a token bot, database and redis settings, everything else can be left out

name description
BOT_TOKEN Telegram bot API token
RATE_LIMIT Maximum number of requests allowed per minute for rate limiting
DEBUG Enable or disable debugging mode (e.g., True or False)
USE_WEBHOOK Flag to indicate whether the bot should use a webhook for updates (e.g., True or False)
WEBHOOK_BASE_URL Base URL for the webhook
WEBHOOK_PATH Path to receive updates from Telegram
WEBHOOK_SECRET Secret key for securing the webhook communication
WEBHOOK_HOST Hostname or IP address for the main application
WEBHOOK_PORT Port number for the main application
ADMIN_HOST Hostname or IP address for the admin panel
ADMIN_PORT Port number for the admin panel
DEFAULT_ADMIN_EMAIL Default email for the admin user
DEFAULT_ADMIN_PASSWORD Default password for the admin user
SECURITY_PASSWORD_HASH Hashing algorithm for user passwords (e.g., bcrypt)
SECURITY_PASSWORD_SALT Salt value for user password hashing
DB_HOST Hostname or IP address of the PostgreSQL database
DB_PORT Port number for the PostgreSQL database
DB_USER Username for authenticating with the PostgreSQL database
DB_PASS Password for authenticating with the PostgreSQL database
DB_NAME Name of the PostgreSQL database
REDIS_HOST Hostname or IP address of the Redis database
REDIS_PORT Port number for the Redis database
REDIS_PASS Password for authenticating with the Redis database
SENTRY_DSN Sentry DSN (Data Source Name) for error tracking
AMPLITUDE_API_KEY API key for Amplitude analytics
POSTHOG_API_KEY API key for PostHog analytics
PROMETHEUS_PORT Port number for the Prometheus monitoring system
GRAFANA_PORT Port number for the Grafana monitoring and visualization platform
GRAFANA_ADMIN_USER Admin username for accessing Grafana
GRAFANA_ADMIN_PASSWORD Admin password for accessing Grafana

πŸ“‚ Project Folder Structure

.
β”œβ”€β”€ admin # Source code for admin panel
β”‚Β Β  β”œβ”€β”€ __init__.py
β”‚Β Β  β”œβ”€β”€ app.py # Main application module for the admin panel
β”‚Β Β  β”œβ”€β”€ config.py # Configuration module for the admin panel
β”‚Β Β  β”œβ”€β”€ Dockerfile # Dockerfile for admin panel
β”‚Β Β  β”œβ”€β”€ gunicorn_conf.py # Gunicorn configuration file for serving admin panel
β”‚Β Β  β”œβ”€β”€ static # Folder for static assets
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ css/
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ fonts/
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ img/
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ js/
β”‚Β Β  β”‚Β Β  └── plugins/
β”‚Β Β  β”œβ”€β”€ templates # HTML templates for the admin panel
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ admin/
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ index.html
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ my_master.html
β”‚Β Β  β”‚Β Β  └── security/
β”‚Β Β  └── views # Custom View modules for handling web requests
β”‚Β Β      β”œβ”€β”€ __init__.py
β”‚Β Β      └── users.py
β”‚
β”œβ”€β”€ bot # Source code for Telegram Bot
β”‚Β Β  β”œβ”€β”€ __init__.py
β”‚Β Β  β”œβ”€β”€ __main__.py # Main entry point to launch the bot
β”‚Β Β  β”œβ”€β”€ analytics/ # Interaction with analytics services (e.g., Amplitude or Google Analytics)
β”‚Β Β  β”œβ”€β”€ cache/ # Logic for using Redis cache
β”‚Β Β  β”œβ”€β”€ core/ # Settings for application and other core components
β”‚Β Β  β”œβ”€β”€ database/ # Database functions and SQLAlchemy Models
β”‚Β Β  β”œβ”€β”€ filters/ # Filters for processing incoming messages or updates
β”‚Β Β  β”œβ”€β”€ handlers/ # Handlers for processing user commands and interactions
β”‚Β Β  β”œβ”€β”€ keyboards # Modules for creating custom keyboards
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ default_commands.py # Default command keyboards
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ __init__.py
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ inline/ # Inline keyboards
β”‚Β Β  β”‚Β Β  └── reply/ # Reply keyboards
β”‚Β Β  β”œβ”€β”€ locales/ # Localization files for supporting multiple languages
β”‚Β Β  β”œβ”€β”€ middlewares/ # Middleware modules for processing incoming updates
β”‚Β Β  β”œβ”€β”€ services/ # Business logic for application
β”‚Β Β  └── utils/ # Utility functions and helper modules
β”‚
β”œβ”€β”€ migrations # Database Migrations managed by Alembic
β”‚Β Β  β”œβ”€β”€ env.py # Environment setup for Alembic
β”‚Β Β  β”œβ”€β”€ __init__.py
β”‚Β Β  β”œβ”€β”€ README
β”‚Β Β  β”œβ”€β”€ script.py.mako # Script template for generating migrations
β”‚Β Β  └── versions/ # Folder containing individual migration scripts
β”‚
β”œβ”€β”€ configs # Config folder for Monitoring (Prometheus, Node-exporter and Grafana)
β”‚Β Β  β”œβ”€β”€ grafana # Configuration files for Grafana
β”‚Β Β  β”‚Β Β  └── datasource.yml
β”‚Β Β  └── prometheus # Configuration files for Prometheus
β”‚Β Β      └── prometheus.yml
β”‚
β”œβ”€β”€ alembic.ini # Configuration file for migrations
β”œβ”€β”€ docker-compose.yml # Docker Compose configuration file for orchestrating containers
β”œβ”€β”€ Dockerfile # Dockerfile for Telegram Bot
β”œβ”€β”€ LICENSE.md # License file for the project
β”œβ”€β”€ poetry.lock # Lock file for Poetry dependency management
β”œβ”€β”€ pyproject.toml # Configuration file for Python projects, including build tools, dependencies, and metadata
└── README.md # Documentation

πŸ”§ Tech Stack

  • sqlalchemy β€” object-relational mapping (ORM) library that provides a set of high-level API for interacting with relational databases
  • asyncpg β€” asynchronous PostgreSQL database client library
  • aiogram β€” asynchronous framework for Telegram Bot API
  • flask-admin β€” simple and extensible administrative interface framework
  • loguru β€” third party library for logging in Python
  • poetry β€” development workflow
  • docker β€” to automate deployment
  • postgres β€” powerful, open source object-relational database system
  • pgbouncer β€” connection pooler for PostgreSQL database
  • redis β€” in-memory data structure store used as a cache and FSM
  • prometheus β€” time series database for collecting metrics from various systems
  • grafana β€” visualization and analysis from various sources, including Prometheus

πŸ‘· Contributing

First off, thanks for taking the time to contribute! Contributions are what makes the open-source community such an amazing place to learn, inspire, and create. Any contributions you make will benefit everybody else and are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork this repository
  2. Create a branch
  3. Commit your changes
  4. Push your commits to the branch
  5. Submit a pull request

πŸ“ License

Distributed under the LGPL-3.0 license. See LICENSE for more information.

πŸ“’ Contact

donbarbos: [email protected]

telegram-bot-template's People

Contributors

aoulaa avatar dependabot[bot] avatar donbarbos avatar maxktz avatar realaashil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

telegram-bot-template's Issues

Feature: Automatic database backups

add to docker-compose.yml


  pgbackup:
    container_name: pgbackup
    image: prodrigestivill/postgres-backup-local
    restart: always
    volumes:
      - ./backup:/backups
    networks:
      - app
    depends_on:
      - postgres
    environment:
      - POSTGRES_HOST=postgres
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASS}
      - POSTGRES_EXTRA_OPTS=-Z9 --schema=public --blobs
      - SCHEDULE=@every 0h30m00s
      - BACKUP_KEEP_DAYS=7
      - BACKUP_KEEP_WEEKS=4
      - BACKUP_KEEP_MONTHS=6
      - HEALTHCHECK_PORT=81

start

docker-compose up -d pgbackup

output

docker logs 1fc25aaab5d9
2024/08/09 07:11:35 Running version: v0.0.10
2024/08/09 07:11:35 new cron: @every 0h30m00s
2024/08/09 09:11:35 272 cmd: /backup.sh
2024/08/09 09:11:35 272: Creating dump of bot_db database from postgres...
2024/08/09 09:11:35 272: Replacing daily backup /backups/daily/bot_db-20240809.sql.gz file this last backup...
2024/08/09 09:11:35 272: '/backups/daily/bot_db-20240809.sql.gz' => '/backups/last/bot_db-20240809-091135.sql.gz'
2024/08/09 09:11:35 272: Replacing weekly backup /backups/weekly/bot_db-202432.sql.gz file this last backup...
2024/08/09 09:11:35 272: '/backups/weekly/bot_db-202432.sql.gz' => '/backups/last/bot_db-20240809-091135.sql.gz'
2024/08/09 09:11:35 272: Replacing monthly backup /backups/monthly/bot_db-202408.sql.gz file this last backup...
2024/08/09 09:11:35 272: '/backups/monthly/bot_db-202408.sql.gz' => '/backups/last/bot_db-20240809-091135.sql.gz'
2024/08/09 09:11:35 272: Point last backup file to this last backup...
2024/08/09 09:11:35 272: '/backups/last/bot_db-latest.sql.gz' -> 'bot_db-20240809-091135.sql.gz'
2024/08/09 09:11:35 272: Point latest daily backup to this last backup...
2024/08/09 09:11:35 272: '/backups/daily/bot_db-latest.sql.gz' -> 'bot_db-20240809.sql.gz'
2024/08/09 09:11:35 272: Point latest weekly backup to this last backup...
2024/08/09 09:11:35 272: '/backups/weekly/bot_db-latest.sql.gz' -> 'bot_db-202432.sql.gz'
2024/08/09 09:11:35 272: Point latest monthly backup to this last backup...
2024/08/09 09:11:35 272: '/backups/monthly/bot_db-latest.sql.gz' -> 'bot_db-202408.sql.gz'
2024/08/09 09:11:35 272: Cleaning older files for bot_db database from postgres...
2024/08/09 09:11:35 272: SQL backup created successfully

Update docker-compose (or something)

It would be nice to add something like this to the dockerfile (docker-compose): alembic upgrade head
Or use may be 'prestart.sh' that could be mount.

Localization error in docker (container: bot)

2024-04-06 22:01:45 bot            | Traceback (most recent call last):
2024-04-06 22:01:45 bot            |   File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
2024-04-06 22:01:45 bot            |     return _run_code(code, main_globals, None,
2024-04-06 22:01:45 bot            |   File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
2024-04-06 22:01:45 bot            |     exec(code, run_globals)
2024-04-06 22:01:45 bot            |   File "/usr/src/app/bot/__main__.py", line 10, in <module>
2024-04-06 22:01:45 bot            |     from bot.core.loader import app, bot, dp
2024-04-06 22:01:45 bot            |   File "/usr/src/app/bot/core/loader.py", line 32, in <module>
2024-04-06 22:01:45 bot            |     i18n: I18n = I18n(path=LOCALES_DIR, default_locale="en", domain=I18N_DOMAIN)
2024-04-06 22:01:45 bot            |   File "/usr/local/lib/python3.10/site-packages/aiogram/utils/i18n/core.py", line 24, in __init__
2024-04-06 22:01:45 bot            |     self.locales = self.find_locales()
2024-04-06 22:01:45 bot            |   File "/usr/local/lib/python3.10/site-packages/aiogram/utils/i18n/core.py", line 73, in find_locales
2024-04-06 22:01:45 bot            |     raise RuntimeError(f"Found locale '{name}' but this language is not compiled!")
2024-04-06 22:01:45 bot            | RuntimeError: Found locale 'en' but this language is not compiled!
bot exited with code 1

System Information:

  • Operating System: Windows 11 version 23H2 (OS Build 22631.3374)
  • Docker Desktop version: 4.28.0 (139021)
  • Docker version: 25.0.3, build 4debf41

Error in creating migration

Since telegram is now growing in popularity, the Integer type used in the users table in id will no longer work.
As the record of this format: 10 digits in user id in telegram will cause an error in the database.

migrations\versions\2024-01-23_initial.py
def upgrade() -> None:\n
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "users",
        sa.Column("id", sa.BigInteger(), autoincrement=False, nullable=False),
        sa.Column("first_name", sa.String(), nullable=False),
        sa.Column("last_name", sa.String(), nullable=True),
        sa.Column("username", sa.String(), nullable=True),
        sa.Column("language_code", sa.String(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("TIMEZONE('utc', now())"), nullable=False),
        sa.Column("is_admin", sa.Boolean(), nullable=False),
        sa.Column("is_suspicious", sa.Boolean(), nullable=False),
        sa.Column("is_block", sa.Boolean(), nullable=False),
        sa.Column("is_premium", sa.Boolean(), nullable=False),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("id"),
    )
bot\database\models\user.py
# ruff: noqa: TCH001, TCH003, A003, F821
from __future__ import annotations

from sqlalchemy.orm import Mapped, mapped_column

from bot.database.models.base import Base, created_at, int_pk, big_int_pk


class UserModel(Base):
    __tablename__ = "users"

    id: Mapped[big_int_pk]
    first_name: Mapped[str]
    last_name: Mapped[str | None]
    username: Mapped[str | None]
    language_code: Mapped[str | None]
    referrer: Mapped[str | None]
    created_at: Mapped[created_at]

    is_admin: Mapped[bool] = mapped_column(default=False)
    is_suspicious: Mapped[bool] = mapped_column(default=False)
    is_block: Mapped[bool] = mapped_column(default=False)
    is_premium: Mapped[bool] = mapped_column(default=False)
bot\database\models\base.py
import datetime
from typing import Annotated

from sqlalchemy import text, BigInteger
from sqlalchemy.orm import DeclarativeBase, mapped_column

int_pk = Annotated[int, mapped_column(primary_key=True, unique=True, autoincrement=False)]
big_int_pk = Annotated[int, mapped_column(primary_key=True, unique=True, autoincrement=False, type_=BigInteger)]
created_at = Annotated[datetime.datetime, mapped_column(server_default=text("TIMEZONE('utc', now())"))]


class Base(DeclarativeBase):
    repr_cols_num: int = 3  # print first columns
    repr_cols: tuple = ()  # extra printed columns

    def __repr__(self) -> str:
        cols = [
            f"{col}={getattr(self, col)}"
            for idx, col in enumerate(self.__table__.columns.keys())
            if col in self.repr_cols or idx < self.repr_cols_num
        ]
        return f"<{self.__class__.__name__} {', '.join(cols)}>"

inline keyboard button problem

I have a problem with all the commands except the "/menu" and "/help" (see picture)
a full text description looks like this:
["

2024-07-03 22:23:07 2024-07-03 17:23:07.396 | INFO | bot.middlewares.logging:call:113 - received message | chat_type: private | user_id: ??? | text: /supports
2024-07-03 22:23:07 Cause exception while process update id=??? by bot id=???
2024-07-03 22:23:07 TelegramBadRequest: Telegram server says - Bad Request: can't parse inline keyboard button: Text buttons are unallowed in the inline keyboard
2024-07-03 22:23:07 File "/usr/local/lib/python3.10/site-packages/aiogram/fsm/middleware.py", line 42, in call
2024-07-03 22:23:07 return await handler(event, data)
2024-07-03 22:23:07 File "/usr/src/app/bot/middlewares/logging.py", line 165, in call
2024-07-03 22:23:07 return await handler(event, data)
2024-07-03 22:23:07 File "/usr/src/app/bot/middlewares/database.py", line 23, in call
2024-07-03 22:23:07 return await handler(event, data)

2024-07-03 22:23:07 File "/usr/local/lib/python3.10/site-packages/aiogram/dispatcher/event/telegram.py", line 121, in trigger
2024-07-03 22:23:07 return await wrapped_inner(event, kwargs)
2024-07-03 22:23:07 aiogram.exceptions.TelegramBadRequest: Telegram server says - Bad Request: can't parse inline keyboard button: Text buttons are unallowed in the inline keyboard
"]
how i make to fix it?
ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅_2024-07-03_222537132

try to change language

I tried to switch i18n to the Ukrainian language, but the bot does not want to translate the text

Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2024-05-27 Π² 16 26 06 Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2024-05-27 Π² 16 26 22 Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2024-05-27 Π² 16 26 54 Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2024-05-27 Π² 16 27 20

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.