@@ -41,4 +43,4 @@ function Header({ walletId, onConnectWallet, onLogout }) {
);
}
-export default Header;
\ No newline at end of file
+export default Header;
diff --git a/frontend/src/components/header/header.css b/frontend/src/components/header/header.css
index 7a52eed4..4de09e6d 100644
--- a/frontend/src/components/header/header.css
+++ b/frontend/src/components/header/header.css
@@ -64,6 +64,8 @@ nav {
.wallet-section {
position: absolute;
right: 10px;
+ display: flex;
+ gap: 10px;
}
.nav-items a {
From ebe84e51f8ab0bf5f9df7907aa30b88b376a328b Mon Sep 17 00:00:00 2001
From: Teri-anric <2005ahi2005@gmail.com>
Date: Sat, 26 Oct 2024 18:00:06 +0000
Subject: [PATCH 06/19] add telegram db
---
web_app/api/serializers/telegram.py | 16 +++
web_app/db/acrud.py | 177 ++++++++++++++++++++++++++++
web_app/db/models.py | 28 ++++-
3 files changed, 219 insertions(+), 2 deletions(-)
create mode 100644 web_app/api/serializers/telegram.py
create mode 100644 web_app/db/acrud.py
diff --git a/web_app/api/serializers/telegram.py b/web_app/api/serializers/telegram.py
new file mode 100644
index 00000000..e6cd896c
--- /dev/null
+++ b/web_app/api/serializers/telegram.py
@@ -0,0 +1,16 @@
+from pydantic import BaseModel
+
+
+class TelegramUserCreate(BaseModel):
+ telegram_id: str
+ username: str | None
+ first_name: str | None
+ last_name: str | None
+ photo_url: str | None
+
+ wallet_id: str | None
+
+
+class TelegramUserAuth(BaseModel):
+ raw: str | dict
+ is_webapp: bool
diff --git a/web_app/db/acrud.py b/web_app/db/acrud.py
new file mode 100644
index 00000000..dccda975
--- /dev/null
+++ b/web_app/db/acrud.py
@@ -0,0 +1,177 @@
+import logging
+import uuid
+from typing import Type, TypeVar
+from uuid import UUID
+
+from sqlalchemy import update
+from sqlalchemy.exc import SQLAlchemyError
+from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
+from sqlalchemy.future import select
+from sqlalchemy.orm import sessionmaker
+
+from web_app.db.database import SQLALCHEMY_DATABASE_URL
+from web_app.db.models import Base, Position, Status, TelegramUser, User
+
+logger = logging.getLogger(__name__)
+ModelType = TypeVar("ModelType", bound=Base) # type: ignore
+
+
+class AsyncDBConnector:
+ """
+ Provides asynchronous database connection and operations management using SQLAlchemy
+ in a FastAPI application context.
+ """
+
+ def __init__(self, db_url: str = SQLALCHEMY_DATABASE_URL):
+ """
+ Initialize the database connection and session factory.
+ :param db_url: str = None
+ """
+ self.engine = create_async_engine(db_url)
+ self.async_session = sessionmaker(
+ self.engine, class_=AsyncSession, expire_on_commit=False
+ )
+
+ async def write_to_db(self, obj: ModelType = None) -> ModelType:
+ """
+ Writes an object to the database asynchronously. Rolls back the transaction if there's an error.
+ :param obj: ModelType = None
+ :raise SQLAlchemyError: If the database operation fails.
+ :return: ModelType - the updated object
+ """
+ async with self.async_session() as session:
+ async with session.begin():
+ try:
+ session.add(obj)
+ await session.commit()
+ await session.refresh(obj)
+ return obj
+ except SQLAlchemyError as e:
+ await session.rollback()
+ raise e
+
+ async def get_object(
+ self, model: Type[ModelType] = None, obj_id: uuid = None
+ ) -> ModelType | None:
+ """
+ Retrieves an object by its ID from the database asynchronously.
+ :param: model: type[Base] = None
+ :param: obj_id: uuid = None
+ :return: Base | None
+ """
+ async with self.async_session() as session:
+ result = await session.execute(select(model).filter(model.id == obj_id))
+ return result.scalar_one_or_none()
+
+ async def get_object_by_field(
+ self, model: Type[ModelType] = None, field: str = None, value: str = None
+ ) -> ModelType | None:
+ """
+ Retrieves an object by a specified field from the database asynchronously.
+ :param model: type[Base] = None
+ :param field: str = None
+ :param value: str = None
+ :return: Base | None
+ """
+ async with self.async_session() as session:
+ result = await session.execute(
+ select(model).filter(getattr(model, field) == value)
+ )
+ return result.scalar_one_or_none()
+
+ async def delete_object(
+ self, model: Type[ModelType] = None, obj_id: uuid = None
+ ) -> None:
+ """
+ Delete an object by its ID from the database asynchronously. Rolls back if the operation fails.
+ :param model: type[Base] = None
+ :param obj_id: uuid = None
+ :return: None
+ :raise SQLAlchemyError: If the database operation fails
+ """
+ async with self.async_session() as session:
+ async with session.begin():
+ try:
+ obj = await session.execute(
+ select(model).filter(model.id == obj_id)
+ )
+ obj = obj.scalar_one_or_none()
+ if obj:
+ await session.delete(obj)
+ await session.commit()
+ except SQLAlchemyError as e:
+ await session.rollback()
+ raise e
+
+
+class AsyncTelegramUserDBConnector(AsyncDBConnector):
+ """
+ Provides asynchronous database connection and operations management for the TelegramUser model.
+ """
+
+ async def get_user_by_telegram_id(self, telegram_id: str) -> TelegramUser | None:
+ """
+ Retrieves a TelegramUser by their Telegram ID asynchronously.
+ :param telegram_id: str
+ :return: TelegramUser | None
+ """
+ return await self.get_object_by_field(TelegramUser, "telegram_id", telegram_id)
+
+ async def get_wallet_id_by_telegram_id(self, telegram_id: str) -> str | None:
+ """
+ Retrieves the wallet ID of a TelegramUser by their Telegram ID asynchronously.
+ :param telegram_id: str
+ :return: str | None
+ """
+ user = await self.get_user_by_telegram_id(telegram_id)
+ return user.wallet_id if user else None
+
+ async def create_telegram_user(self, user_data: dict) -> TelegramUser:
+ """
+ Creates a new TelegramUser in the database asynchronously.
+ :param user_data: dict
+ :return: TelegramUser
+ """
+ telegram_user = TelegramUser(**user_data)
+ return await self.write_to_db(telegram_user)
+
+ async def update_telegram_user(self, telegram_id: str, user_data: dict) -> None:
+ """
+ Updates a TelegramUser in the database asynchronously.
+ :param telegram_id: str
+ :param user_data: dict
+ :return: None
+ """
+ async with self.get_session() as session:
+ stmt = (
+ update(TelegramUser)
+ .where(TelegramUser.telegram_id == telegram_id)
+ .values(**user_data)
+ )
+ await session.execute(stmt)
+ await session.commit()
+
+ async def save_or_update_user(self, user_data: dict) -> TelegramUser:
+ """
+ Saves a new TelegramUser or updates an existing one asynchronously.
+ :param user_data: dict
+ :return: TelegramUser
+ """
+ telegram_id = user_data.get("telegram_id")
+ existing_user = await self.get_user_by_telegram_id(telegram_id)
+
+ if existing_user:
+ await self.update_telegram_user(telegram_id, user_data)
+ return await self.get_user_by_telegram_id(telegram_id)
+ else:
+ return await self.create_telegram_user(user_data)
+
+ async def delete_telegram_user(self, telegram_id: str) -> None:
+ """
+ Deletes a TelegramUser from the database asynchronously.
+ :param telegram_id: str
+ :return: None
+ """
+ user = await self.get_user_by_telegram_id(telegram_id)
+ if user:
+ await self.delete_from_db(user)
diff --git a/web_app/db/models.py b/web_app/db/models.py
index c5ca96e0..b2216b79 100644
--- a/web_app/db/models.py
+++ b/web_app/db/models.py
@@ -1,8 +1,11 @@
+from enum import Enum as PyEnum
from uuid import uuid4
+
+from sqlalchemy import (Boolean, Column, DateTime, Enum, ForeignKey, Integer,
+ String)
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
-from sqlalchemy import Column, String, Boolean, Integer, ForeignKey, DateTime, Enum
-from enum import Enum as PyEnum
+
from web_app.db.database import Base
@@ -51,3 +54,24 @@ class Position(Base):
nullable=True,
default="pending",
)
+
+
+class TelegramUser(Base):
+ """
+ SQLAlchemy model for the telegram_user table.
+ """
+
+ __tablename__ = "telegram_user"
+
+ id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
+ telegram_id = Column(String, nullable=False, unique=True, index=True)
+ username = Column(String, nullable=True)
+ first_name = Column(String, nullable=True)
+ last_name = Column(String, nullable=True)
+ wallet_id = Column(String, ForeignKey("user.wallet_id"), nullable=True)
+ photo_url = Column(String, nullable=True)
+
+ created_at = Column(DateTime, nullable=False, default=func.now())
+ updated_at = Column(
+ DateTime, nullable=False, default=func.now(), onupdate=func.now()
+ )
From 753f2545576422353157d73739eddccdd141b409 Mon Sep 17 00:00:00 2001
From: Teri-anric <2005ahi2005@gmail.com>
Date: Sat, 26 Oct 2024 18:00:41 +0000
Subject: [PATCH 07/19] add tg auth api
---
web_app/api/telegram.py | 69 ++++++++++++++++++++++++++++++++++++---
web_app/telegram/utils.py | 23 +++++++++++++
2 files changed, 87 insertions(+), 5 deletions(-)
diff --git a/web_app/api/telegram.py b/web_app/api/telegram.py
index ce616cba..46635a82 100644
--- a/web_app/api/telegram.py
+++ b/web_app/api/telegram.py
@@ -1,16 +1,23 @@
from typing import Literal
from aiogram.types import Update
-from fastapi import APIRouter, Request
+from aiogram.utils.web_app import check_webapp_signature
+from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import StreamingResponse
+from pydantic import BaseModel
+from web_app.api.serializers.telegram import (TelegramUserAuth,
+ TelegramUserCreate)
+from web_app.db.acrud import AsyncTelegramUserDBConnector
from web_app.db.crud import DBConnector
-from web_app.telegram import bot, dp
-from web_app.telegram.utils import build_response_writer
+from web_app.telegram import TELEGRAM_TOKEN, bot, dp
+from web_app.telegram.utils import (build_response_writer,
+ check_telegram_authorization)
# Create a FastAPI router for handling Telegram webhook requests
-router = APIRouter(include_in_schema=False)
+router = APIRouter()
db_connector = DBConnector()
+adb_telegram_user = AsyncTelegramUserDBConnector()
@router.get("/api/webhook/telegram")
@@ -32,7 +39,7 @@ async def set_telegram_webhook(request: Request) -> Literal["ok"]:
return "ok"
-@router.post("/api/webhook/telegram")
+@router.post("/api/webhook/telegram", include_in_schema=False)
async def telegram_webhook(update: Update):
"""
Handle incoming updates from Telegram.
@@ -50,3 +57,55 @@ async def telegram_webhook(update: Update):
return StreamingResponse(
build_response_writer(bot, result), media_type="multipart/form-data"
)
+
+
+@router.post(
+ "/api/telegram/save-user",
+ tags=["Telegram Operations"],
+ summary="Save or update Telegram user information",
+)
+async def save_telegram_user(user: TelegramUserCreate):
+ """
+ Save or update Telegram user information in the database.
+
+ ### Parameters:
+ - **user**: TelegramUserCreate object containing user information
+
+ ### Returns:
+ A dictionary with a success message
+ """
+ try:
+ await adb_telegram_user.save_or_update_user(user.model_dump())
+ return {"message": "Telegram user saved successfully"}
+ except Exception as e:
+ raise HTTPException(
+ status_code=500, detail=f"Error saving Telegram user: {str(e)}"
+ )
+
+
+@router.get(
+ "/api/telegram/get-wallet-id/{telegram_id}",
+ tags=["Telegram Operations"],
+ summary="Get wallet ID for a Telegram user",
+)
+async def get_wallet_id(telegram_auth: TelegramUserAuth, telegram_id: str):
+ """
+ Retrieve the wallet ID associated with a Telegram user.
+
+ ### Parameters:
+ - **telegram_auth**: Telegram authorization data or webapp init data
+ - **telegram_id**: Telegram user ID
+
+ ### Returns:
+ A dictionary containing the wallet ID or None if not found
+ """
+ if telegram_auth.is_webapp:
+ is_valid = check_webapp_signature(TELEGRAM_TOKEN, telegram_auth.raw)
+ else:
+ is_valid = check_telegram_authorization(TELEGRAM_TOKEN, telegram_auth.raw)
+
+ if is_valid:
+ return HTTPException(400, "Telegram auth data is invalid.")
+
+ wallet_id = await adb_telegram_user.get_wallet_id_by_telegram_id(telegram_id)
+ return {"wallet_id": wallet_id}
diff --git a/web_app/telegram/utils.py b/web_app/telegram/utils.py
index b0b3c7ea..0239393e 100644
--- a/web_app/telegram/utils.py
+++ b/web_app/telegram/utils.py
@@ -1,4 +1,7 @@
+import hashlib
+import hmac
import secrets
+import time
from typing import Dict, Optional
from aiogram import Bot
@@ -8,6 +11,26 @@
from aiohttp import MultipartWriter
+def check_telegram_authorization(token: str, auth_data: dict):
+ check_hash = auth_data.pop("hash")
+ data_check_arr = [f"{key}={value}" for key, value in auth_data.items()]
+ data_check_arr.sort()
+ data_check_string = "\n".join(data_check_arr)
+
+ secret_key = hashlib.sha256(token.encode()).digest()
+ hash_value = hmac.new(
+ secret_key, data_check_string.encode(), hashlib.sha256
+ ).hexdigest()
+
+ if hash_value != check_hash:
+ raise Exception("Data is NOT from Telegram")
+
+ if (int(time.time()) - auth_data["auth_date"]) > 86400:
+ raise Exception("Data is outdated")
+
+ return auth_data
+
+
def build_response_writer(
bot: Bot, result: Optional[TelegramMethod[TelegramType]]
) -> MultipartWriter:
From 4ef5ea13075474164de38ee41ccf55b4d09c16bc Mon Sep 17 00:00:00 2001
From: Teri-anric <2005ahi2005@gmail.com>
Date: Sat, 26 Oct 2024 18:01:28 +0000
Subject: [PATCH 08/19] add frontend wallet save(on telegram auth)
---
frontend/src/App.jsx | 67 +++++++++++++++++++++++-----------
frontend/src/utils/telegram.js | 33 +++++++++++++++++
2 files changed, 78 insertions(+), 22 deletions(-)
create mode 100644 frontend/src/utils/telegram.js
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index e8f7ab63..0212b3f2 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -7,6 +7,7 @@ import SpotnetApp from './pages/spotnet/spotnet_app/SpotnetApp';
import Login from "./pages/Login";
import Form from "./pages/forms/Form";
import { connectWallet, logout } from './utils/wallet';
+import { saveTelegramUser } from './utils/telegram';
function App() {
const [walletId, setWalletId] = useState(localStorage.getItem('wallet_id'));
@@ -15,13 +16,35 @@ function App() {
const navigate = useNavigate();
useEffect(() => {
- if (walletId) {
- localStorage.setItem('wallet_id', walletId);
- } else {
+ if (tgUser) {
+ saveTelegramUser(tgUser, walletId)
+ .then(() => console.log('Telegram user saved successfully'))
+ .catch(error => console.error('Error saving Telegram user:', error));
+ }
+ if (!walletId) {
localStorage.removeItem('wallet_id');
+ return;
}
+ localStorage.setItem('wallet_id', walletId);
}, [walletId]);
+ useEffect(() => {
+ if (!tgUser) {
+ localStorage.removeItem('tg_user');
+ return
+ }
+ if (!walletId) {
+ getTelegramUserWalletId(tgUser.id)
+ .then(fetchedWalletId => {
+ if (fetchedWalletId) {
+ setWalletId(fetchedWalletId);
+ }
+ })
+ .catch(error => console.error('Error fetching wallet ID:', error));
+ localStorage.setItem('tg_user', JSON.stringify(tgUser));
+ }
+ }, [tgUser, walletId])
+
const handleConnectWallet = async () => {
try {
setError(null);
@@ -42,25 +65,25 @@ function App() {
};
return (
-
-
-
- {error && {error}
}
-
- }
- />
- : }
- />
- } />
- } />
-
-
-
-
+
+
+
+ {error && {error}
}
+
+ }
+ />
+ : }
+ />
+ } />
+ } />
+
+
+
+
);
}
diff --git a/frontend/src/utils/telegram.js b/frontend/src/utils/telegram.js
new file mode 100644
index 00000000..47dcf831
--- /dev/null
+++ b/frontend/src/utils/telegram.js
@@ -0,0 +1,33 @@
+import axios from 'axios';
+
+const API_BASE_URL = process.env.REACT_APP_API_BASE_URL || 'http://localhost:8000';
+
+export const saveTelegramUser = async (telegramUser, walletId) => {
+ try {
+ const response = await axios.post(`${API_BASE_URL}/api/telegram/save-user`, {
+ telegram_id: telegramUser.id,
+ username: telegramUser.username,
+ first_name: telegramUser.first_name,
+ last_name: telegramUser.last_name,
+ photo_url: telegramUser.photo_url,
+ wallet_id: walletId
+ });
+ return response.data;
+ } catch (error) {
+ console.error('Error saving Telegram user:', error);
+ throw error;
+ }
+};
+
+export const getTelegramUserWalletId = async (tg_user) => {
+ try {
+ const response = await axios.post(`${API_BASE_URL}/api/telegram/get-wallet-id/${tg_user.id}`, {
+ raw: window.Telegram.initData || tg_user,
+ is_webapp: !!window.Telegram.initData
+ });
+ return response.data.wallet_id;
+ } catch (error) {
+ console.error('Error getting wallet ID for Telegram user:', error);
+ throw error;
+ }
+};
\ No newline at end of file
From 693ec03d159badc00d5535d35256de0ea2d83114 Mon Sep 17 00:00:00 2001
From: Teri-anric <2005ahi2005@gmail.com>
Date: Sat, 26 Oct 2024 18:05:03 +0000
Subject: [PATCH 09/19] add not set telegram token warning
---
web_app/telegram/__init__.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/web_app/telegram/__init__.py b/web_app/telegram/__init__.py
index 660ab0b9..b3a55840 100644
--- a/web_app/telegram/__init__.py
+++ b/web_app/telegram/__init__.py
@@ -1,15 +1,22 @@
from aiogram import Bot, Dispatcher
+import logging
from .config import TELEGRAM_TOKEN
from .handlers import cmd_router
+# Set up logging
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
# Initialize the Telegram bot (None for the ability to run without a bot token)
bot: Bot = None
if TELEGRAM_TOKEN:
# Create a Bot instance using the provided token
bot = Bot(TELEGRAM_TOKEN)
+else:
+ logger.warning("Telegram token is not set. Telegram bot functionality will be limited.")
# Create a Dispatcher for handling updates
dp = Dispatcher()
# Include command routers for handling specific commands
-dp.include_routers(cmd_router)
+dp.include_routers(cmd_router)
\ No newline at end of file
From 84f0345a829e0ac14b1366554af8ae51b8aa50ca Mon Sep 17 00:00:00 2001
From: Teri-anric <2005ahi2005@gmail.com>
Date: Sat, 26 Oct 2024 18:17:48 +0000
Subject: [PATCH 10/19] uncommitted changes
---
web_app/db/models.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/web_app/db/models.py b/web_app/db/models.py
index 545b2b71..0ccc7a1f 100644
--- a/web_app/db/models.py
+++ b/web_app/db/models.py
@@ -1,7 +1,16 @@
from uuid import uuid4
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
-from sqlalchemy import Column, String, Boolean, Integer, ForeignKey, DateTime, Enum
+from sqlalchemy import (
+ DECIMAL,
+ Column,
+ String,
+ Boolean,
+ Integer,
+ ForeignKey,
+ DateTime,
+ Enum,
+)
from enum import Enum as PyEnum
from web_app.db.database import Base
From 2ccb644b6bdf8d49b419585abab55342a90d4960 Mon Sep 17 00:00:00 2001
From: Teri-anric <2005ahi2005@gmail.com>
Date: Sat, 26 Oct 2024 18:51:26 +0000
Subject: [PATCH 11/19] add docstring
---
.../src/components/Telegram/TelegramLogin.jsx | 2 +-
web_app/telegram/README.md | 50 ++++++++++++++++++
web_app/telegram/__init__.py | 5 ++
web_app/telegram/__main__.py | 5 ++
web_app/telegram/assets/image.png | Bin 0 -> 53137 bytes
web_app/telegram/config.py | 5 ++
web_app/telegram/handlers/__init__.py | 5 ++
web_app/telegram/handlers/command.py | 5 ++
web_app/telegram/markups.py | 5 ++
web_app/telegram/texts.py | 5 ++
web_app/telegram/utils.py | 5 ++
11 files changed, 91 insertions(+), 1 deletion(-)
create mode 100644 web_app/telegram/README.md
create mode 100644 web_app/telegram/assets/image.png
diff --git a/frontend/src/components/Telegram/TelegramLogin.jsx b/frontend/src/components/Telegram/TelegramLogin.jsx
index b18784fd..01262a37 100644
--- a/frontend/src/components/Telegram/TelegramLogin.jsx
+++ b/frontend/src/components/Telegram/TelegramLogin.jsx
@@ -18,7 +18,7 @@ const TelegramLogin = ({ user, onLogin }) => {
const handleLogin = () => {
window.Telegram.Login.auth({
- bot_id: "BOT_ID",
+ bot_id: process.env.REACT_APP_BOT_ID,
request_access: 'write'
}, onLogin)
};
diff --git a/web_app/telegram/README.md b/web_app/telegram/README.md
new file mode 100644
index 00000000..340d3d57
--- /dev/null
+++ b/web_app/telegram/README.md
@@ -0,0 +1,50 @@
+# Telegram Bot Setup
+
+This document provides instructions on how to set up and run the Telegram bot, as well as how to configure webhooks.
+
+## Prerequisites
+- A Telegram bot token (create a bot using [BotFather](https://core.telegram.org/bots#botfather))
+
+## Setting Up the Environment
+
+2. **Create a `.env` file in the root directory and add your environment variables:**
+ ```env
+ TELEGRAM_TOKEN=
+ TELEGRAM_WEBAPP_URL=
+ REACT_APP_BOT_ID=
+ ```
+ Note: You can obtain the bot ID directly from your Telegram bot token in the format `bot_id:secret`.
+
+## Running the Bot
+
+To run the bot, execute the following command:
+ ```bash
+ python -m web_app.telegram
+ ```
+
+
+## Setting Up Webhooks
+
+To set the webhook for your Telegram bot, follow these steps:
+
+1. Start your FastAPI application (make sure it's accessible from the internet).
+2. Call the following endpoint to set the webhook:
+ ```http
+ GET /api/webhook/telegram
+ ```
+ This will set the webhook URL to the current request URL.
+
+3. Ensure that your server is publicly accessible so that Telegram can send updates to your webhook.
+
+## Additional Configuration In [BotFather](https://core.telegram.org/bots#botfather)
+
+- **Domain:** You need to set a domain for the bot to work properly with the Telegram widget login(frontend).
+- **Photo** You need to upload your site's logo, as it will be displayed when users log in through the Telegram login widget![alt text](./assets/image.png)
+- **Configure MiniApp URL:** This is optional but recommended for better integration.
+
+## Notes
+
+- Make sure your server is running and accessible to Telegram for the webhook to function correctly.
+- You can test the bot by sending the `/start` command after setting up the webhook.
+
+For any issues or further assistance, please refer to the documentation or contact support.
\ No newline at end of file
diff --git a/web_app/telegram/__init__.py b/web_app/telegram/__init__.py
index b3a55840..f0e1c113 100644
--- a/web_app/telegram/__init__.py
+++ b/web_app/telegram/__init__.py
@@ -1,3 +1,8 @@
+"""
+This module initializes the Telegram bot and sets up the dispatcher for handling updates.
+
+It imports necessary components from the aiogram library and configures logging.
+"""
from aiogram import Bot, Dispatcher
import logging
diff --git a/web_app/telegram/__main__.py b/web_app/telegram/__main__.py
index b9c4540d..ec43f67b 100644
--- a/web_app/telegram/__main__.py
+++ b/web_app/telegram/__main__.py
@@ -1,3 +1,8 @@
+"""
+This module serves as the entry point for the Telegram bot application.
+It initializes the bot and starts polling for updates.
+This module is made for testing purposes.
+"""
from web_app.db.crud import DBConnector
from . import bot, dp
diff --git a/web_app/telegram/assets/image.png b/web_app/telegram/assets/image.png
new file mode 100644
index 0000000000000000000000000000000000000000..dfd53a33a11c2d3effadb8bbce4ead6ad651d9a6
GIT binary patch
literal 53137
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
z