mirror of
https://github.com/Balshgit/gpt_chat_bot.git
synced 2025-09-11 22:30:41 +03:00
move handlers to separate files
This commit is contained in:
parent
1ecf95631d
commit
315284fc38
@ -4,50 +4,45 @@ from asyncio import Queue, sleep
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from fastapi import Request, Response
|
from fastapi import Request, Response
|
||||||
from telegram import Update
|
from telegram import Update
|
||||||
from telegram.ext import Application, CommandHandler, ContextTypes
|
from telegram.ext import Application
|
||||||
|
|
||||||
|
from app.core.utils import logger
|
||||||
from settings.config import AppSettings
|
from settings.config import AppSettings
|
||||||
|
|
||||||
|
|
||||||
class BotApplication:
|
class BotApplication:
|
||||||
def __init__(self, settings: AppSettings) -> None:
|
def __init__(
|
||||||
self.application: Application = ( # type: ignore
|
self,
|
||||||
|
settings: AppSettings,
|
||||||
|
handlers: list[Any],
|
||||||
|
application: Application | None = None, # type: ignore[type-arg]
|
||||||
|
) -> None:
|
||||||
|
self.application: Application = application or ( # type: ignore
|
||||||
Application.builder().token(token=settings.TELEGRAM_API_TOKEN).build()
|
Application.builder().token(token=settings.TELEGRAM_API_TOKEN).build()
|
||||||
)
|
)
|
||||||
self.add_handlers()
|
self.handlers = handlers
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.start_with_webhook = settings.START_WITH_WEBHOOK
|
self.start_with_webhook = settings.START_WITH_WEBHOOK
|
||||||
|
self._add_handlers()
|
||||||
|
|
||||||
async def set_webhook(self) -> None:
|
async def set_webhook(self) -> None:
|
||||||
await self.application.initialize()
|
await self.application.initialize()
|
||||||
await self.application.bot.set_webhook(url=self.webhook_url)
|
await self.application.bot.set_webhook(url=self.webhook_url)
|
||||||
|
logger.info('webhook is set')
|
||||||
|
|
||||||
async def delete_webhook(self) -> None:
|
async def delete_webhook(self) -> None:
|
||||||
await self.application.bot.delete_webhook()
|
await self.application.bot.delete_webhook()
|
||||||
|
logger.info('webhook has been deleted')
|
||||||
@staticmethod
|
|
||||||
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
|
||||||
"""Send a message when the command /help is issued."""
|
|
||||||
|
|
||||||
if update.message:
|
|
||||||
await asyncio.sleep(10)
|
|
||||||
await update.message.reply_text(
|
|
||||||
"Help!",
|
|
||||||
disable_notification=True,
|
|
||||||
api_kwargs={"text": "Hello World"},
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def add_handlers(self) -> None:
|
|
||||||
self.application.add_handler(CommandHandler("help", self.help_command))
|
|
||||||
|
|
||||||
async def polling(self) -> None:
|
async def polling(self) -> None:
|
||||||
await self.application.initialize()
|
await self.application.initialize()
|
||||||
await self.application.start()
|
await self.application.start()
|
||||||
await self.application.updater.start_polling() # type: ignore
|
await self.application.updater.start_polling() # type: ignore
|
||||||
|
logger.info("bot started in polling mode")
|
||||||
|
|
||||||
async def shutdown(self) -> None:
|
async def shutdown(self) -> None:
|
||||||
await self.application.updater.shutdown() # type: ignore
|
await self.application.updater.shutdown() # type: ignore
|
||||||
@ -56,6 +51,10 @@ class BotApplication:
|
|||||||
def webhook_url(self) -> str:
|
def webhook_url(self) -> str:
|
||||||
return os.path.join(self.settings.DOMAIN.strip("/"), self.settings.bot_webhook_url.strip("/"))
|
return os.path.join(self.settings.DOMAIN.strip("/"), self.settings.bot_webhook_url.strip("/"))
|
||||||
|
|
||||||
|
def _add_handlers(self) -> None:
|
||||||
|
for handler in self.handlers:
|
||||||
|
self.application.add_handler(handler)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class BotQueue:
|
class BotQueue:
|
||||||
|
14
app/core/commands.py
Normal file
14
app/core/commands.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from telegram import Update
|
||||||
|
from telegram.ext import ContextTypes
|
||||||
|
|
||||||
|
|
||||||
|
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||||
|
"""Send a message when the command /help is issued."""
|
||||||
|
|
||||||
|
if update.message:
|
||||||
|
await update.message.reply_text(
|
||||||
|
"Help!",
|
||||||
|
disable_notification=True,
|
||||||
|
api_kwargs={"text": "Hello World"},
|
||||||
|
)
|
||||||
|
return None
|
20
app/core/handlers.py
Normal file
20
app/core/handlers.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from telegram.ext import CommandHandler
|
||||||
|
|
||||||
|
from app.core.commands import help_command
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CommandHandlers:
|
||||||
|
handlers: list[Any] = field(default_factory=list[Any])
|
||||||
|
|
||||||
|
def add_handler(self, handler: Any) -> None:
|
||||||
|
self.handlers.append(handler)
|
||||||
|
|
||||||
|
|
||||||
|
command_handlers = CommandHandlers()
|
||||||
|
|
||||||
|
|
||||||
|
command_handlers.add_handler(CommandHandler("help", help_command))
|
37
app/core/utils.py
Normal file
37
app/core/utils.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import sys
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from functools import lru_cache, wraps
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from loguru import logger as loguru_logger
|
||||||
|
|
||||||
|
logger = loguru_logger
|
||||||
|
|
||||||
|
logger.remove()
|
||||||
|
logger.add(
|
||||||
|
sink=sys.stdout,
|
||||||
|
colorize=True,
|
||||||
|
level='DEBUG',
|
||||||
|
format="<cyan>{time:DD.MM.YYYY HH:mm:ss}</cyan> | <level>{level}</level> | <magenta>{message}</magenta>",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def timed_cache(**timedelta_kwargs: Any) -> Any:
|
||||||
|
def _wrapper(func: Any) -> Any:
|
||||||
|
update_delta = timedelta(**timedelta_kwargs)
|
||||||
|
next_update = datetime.utcnow() + update_delta
|
||||||
|
# Apply @lru_cache to f with no cache size limit
|
||||||
|
cached_func = lru_cache(None)(func)
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
def _wrapped(*args: Any, **kwargs: Any) -> Any:
|
||||||
|
nonlocal next_update
|
||||||
|
now = datetime.utcnow()
|
||||||
|
if now >= next_update:
|
||||||
|
cached_func.cache_clear()
|
||||||
|
next_update = now + update_delta
|
||||||
|
return cached_func(*args, **kwargs)
|
||||||
|
|
||||||
|
return _wrapped
|
||||||
|
|
||||||
|
return _wrapper
|
13
app/main.py
13
app/main.py
@ -1,23 +1,14 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.responses import UJSONResponse
|
from fastapi.responses import UJSONResponse
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from app.core.bot import BotApplication, BotQueue
|
from app.core.bot import BotApplication, BotQueue
|
||||||
|
from app.core.handlers import command_handlers
|
||||||
from app.routers import api_router
|
from app.routers import api_router
|
||||||
from settings.config import AppSettings, get_settings
|
from settings.config import AppSettings, get_settings
|
||||||
|
|
||||||
logger.remove()
|
|
||||||
logger.add(
|
|
||||||
sink=sys.stdout,
|
|
||||||
colorize=True,
|
|
||||||
level="DEBUG",
|
|
||||||
format="<cyan>{time:DD.MM.YYYY HH:mm:ss}</cyan> | <level>{level}</level> | <magenta>{message}</magenta>",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Application:
|
class Application:
|
||||||
def __init__(self, settings: AppSettings, bot_app: BotApplication) -> None:
|
def __init__(self, settings: AppSettings, bot_app: BotApplication) -> None:
|
||||||
@ -60,7 +51,7 @@ class Application:
|
|||||||
|
|
||||||
def create_app(settings: AppSettings | None = None) -> FastAPI:
|
def create_app(settings: AppSettings | None = None) -> FastAPI:
|
||||||
settings = settings or get_settings()
|
settings = settings or get_settings()
|
||||||
bot_app = BotApplication(settings=settings)
|
bot_app = BotApplication(settings=settings, handlers=command_handlers.handlers)
|
||||||
|
|
||||||
return Application(settings=settings, bot_app=bot_app).fastapi_app
|
return Application(settings=settings, bot_app=bot_app).fastapi_app
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ from telegram import Bot, User
|
|||||||
from telegram.ext import Application, ApplicationBuilder, Defaults, ExtBot
|
from telegram.ext import Application, ApplicationBuilder, Defaults, ExtBot
|
||||||
|
|
||||||
from app.core.bot import BotApplication
|
from app.core.bot import BotApplication
|
||||||
|
from app.core.handlers import command_handlers
|
||||||
from app.main import Application as AppApplication
|
from app.main import Application as AppApplication
|
||||||
from settings.config import AppSettings, get_settings
|
from settings.config import AppSettings, get_settings
|
||||||
from tests.integration.bot.networking import NonchalantHttpxRequest
|
from tests.integration.bot.networking import NonchalantHttpxRequest
|
||||||
@ -119,27 +120,41 @@ def bot_info() -> dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="session")
|
@pytest_asyncio.fixture(scope="session")
|
||||||
async def bot(bot_info: dict[str, Any]) -> AsyncGenerator[PytestExtBot, None]:
|
async def bot_application(bot_info: dict[str, Any]) -> AsyncGenerator[Any, None]:
|
||||||
|
# We build a new bot each time so that we use `app` in a context manager without problems
|
||||||
|
application = ApplicationBuilder().bot(make_bot(bot_info)).application_class(PytestApplication).build()
|
||||||
|
yield application
|
||||||
|
if application.running:
|
||||||
|
await application.stop()
|
||||||
|
await application.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest_asyncio.fixture(scope="session")
|
||||||
|
async def bot(bot_info: dict[str, Any], bot_application: Any) -> AsyncGenerator[PytestExtBot, None]:
|
||||||
"""Makes an ExtBot instance with the given bot_info"""
|
"""Makes an ExtBot instance with the given bot_info"""
|
||||||
async with make_bot(bot_info) as _bot:
|
async with make_bot(bot_info) as _bot:
|
||||||
|
_bot.application = bot_application
|
||||||
yield _bot
|
yield _bot
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def one_time_bot(bot_info: dict[str, Any]) -> PytestExtBot:
|
def one_time_bot(bot_info: dict[str, Any], bot_application: Any) -> PytestExtBot:
|
||||||
"""A function scoped bot since the session bot would shutdown when `async with app` finishes"""
|
"""A function scoped bot since the session bot would shutdown when `async with app` finishes"""
|
||||||
return make_bot(bot_info)
|
bot = make_bot(bot_info)
|
||||||
|
bot.application = bot_application
|
||||||
|
return bot
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="session")
|
@pytest_asyncio.fixture(scope="session")
|
||||||
async def cdc_bot(bot_info: dict[str, Any]) -> AsyncGenerator[PytestExtBot, None]:
|
async def cdc_bot(bot_info: dict[str, Any], bot_application: Any) -> AsyncGenerator[PytestExtBot, None]:
|
||||||
"""Makes an ExtBot instance with the given bot_info that uses arbitrary callback_data"""
|
"""Makes an ExtBot instance with the given bot_info that uses arbitrary callback_data"""
|
||||||
async with make_bot(bot_info, arbitrary_callback_data=True) as _bot:
|
async with make_bot(bot_info, arbitrary_callback_data=True) as _bot:
|
||||||
|
_bot.application = bot_application
|
||||||
yield _bot
|
yield _bot
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="session")
|
@pytest_asyncio.fixture(scope="session")
|
||||||
async def raw_bot(bot_info: dict[str, Any]) -> AsyncGenerator[PytestBot, None]:
|
async def raw_bot(bot_info: dict[str, Any], bot_application: Any) -> AsyncGenerator[PytestBot, None]:
|
||||||
"""Makes an regular Bot instance with the given bot_info"""
|
"""Makes an regular Bot instance with the given bot_info"""
|
||||||
async with PytestBot(
|
async with PytestBot(
|
||||||
bot_info["token"],
|
bot_info["token"],
|
||||||
@ -147,6 +162,7 @@ async def raw_bot(bot_info: dict[str, Any]) -> AsyncGenerator[PytestBot, None]:
|
|||||||
request=NonchalantHttpxRequest(8),
|
request=NonchalantHttpxRequest(8),
|
||||||
get_updates_request=NonchalantHttpxRequest(1),
|
get_updates_request=NonchalantHttpxRequest(1),
|
||||||
) as _bot:
|
) as _bot:
|
||||||
|
_bot.application = bot_application
|
||||||
yield _bot
|
yield _bot
|
||||||
|
|
||||||
|
|
||||||
@ -207,22 +223,15 @@ def provider_token(bot_info: dict[str, Any]) -> str:
|
|||||||
return bot_info["payment_provider_token"]
|
return bot_info["payment_provider_token"]
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="session")
|
|
||||||
async def bot_application(bot_info: dict[str, Any]) -> AsyncGenerator[Any, None]:
|
|
||||||
# We build a new bot each time so that we use `app` in a context manager without problems
|
|
||||||
application = ApplicationBuilder().bot(make_bot(bot_info)).application_class(PytestApplication).build()
|
|
||||||
yield application
|
|
||||||
if application.running:
|
|
||||||
await application.stop()
|
|
||||||
await application.shutdown()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="session")
|
@pytest_asyncio.fixture(scope="session")
|
||||||
async def main_application(
|
async def main_application(
|
||||||
bot_application: PytestApplication, test_settings: AppSettings
|
bot_application: PytestApplication, test_settings: AppSettings
|
||||||
) -> AsyncGenerator[FastAPI, None]:
|
) -> AsyncGenerator[FastAPI, None]:
|
||||||
bot_app = BotApplication(settings=test_settings)
|
bot_app = BotApplication(
|
||||||
bot_app.application = bot_application
|
application=bot_application,
|
||||||
|
settings=test_settings,
|
||||||
|
handlers=command_handlers.handlers,
|
||||||
|
)
|
||||||
fast_api_app = AppApplication(settings=test_settings, bot_app=bot_app).fastapi_app
|
fast_api_app = AppApplication(settings=test_settings, bot_app=bot_app).fastapi_app
|
||||||
yield fast_api_app
|
yield fast_api_app
|
||||||
|
|
||||||
|
@ -4,91 +4,69 @@ from asyncio import AbstractEventLoop
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from assertpy import assert_that
|
||||||
|
from faker import Faker
|
||||||
from httpx import AsyncClient
|
from httpx import AsyncClient
|
||||||
|
|
||||||
from app.core.bot import BotApplication, BotQueue
|
from app.core.bot import BotApplication, BotQueue
|
||||||
from app.main import Application
|
from app.main import Application
|
||||||
from tests.integration.bot.networking import MockedRequest
|
from tests.integration.bot.networking import MockedRequest
|
||||||
|
from tests.integration.factories.bot import (
|
||||||
|
BotChatFactory,
|
||||||
|
BotEntitleFactory,
|
||||||
|
BotUserFactory,
|
||||||
|
)
|
||||||
|
|
||||||
pytestmark = [
|
pytestmark = [
|
||||||
pytest.mark.asyncio,
|
pytest.mark.asyncio,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
faker = Faker()
|
||||||
|
|
||||||
|
|
||||||
async def test_bot_updates(rest_client: AsyncClient) -> None:
|
async def test_bot_updates(rest_client: AsyncClient) -> None:
|
||||||
response = await rest_client.get("/api/healthcheck")
|
response = await rest_client.get("/api/healthcheck")
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
async def test_bot_webhook_endpoint(
|
async def test_bot_webhook_endpoint(
|
||||||
rest_client: AsyncClient,
|
rest_client: AsyncClient,
|
||||||
|
main_application: Application,
|
||||||
) -> None:
|
) -> None:
|
||||||
response = await rest_client.post(
|
bot_update = create_bot_update()
|
||||||
url="/api/123456789:AABBCCDDEEFFaabbccddeeff-1234567890",
|
response = await rest_client.post(url="/api/123456789:AABBCCDDEEFFaabbccddeeff-1234567890", json=bot_update)
|
||||||
json={
|
|
||||||
"update_id": 957250703,
|
|
||||||
"message": {
|
|
||||||
"message_id": 417070387,
|
|
||||||
"from": {
|
|
||||||
"id": 1000,
|
|
||||||
"is_bot": "false",
|
|
||||||
"first_name": "William",
|
|
||||||
"last_name": "Dalton",
|
|
||||||
"username": "bolshakovfortunat",
|
|
||||||
"language_code": "ru",
|
|
||||||
},
|
|
||||||
"chat": {
|
|
||||||
"id": 1,
|
|
||||||
"first_name": "Gabrielle",
|
|
||||||
"last_name": "Smith",
|
|
||||||
"username": "arefi_2019",
|
|
||||||
"type": "private",
|
|
||||||
},
|
|
||||||
"date": time.time(),
|
|
||||||
"text": "/chatid",
|
|
||||||
"entities": [{"type": "bot_command", "offset": 0, "length": 7}],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
assert response.status_code == 202
|
assert response.status_code == 202
|
||||||
|
update = await main_application.state._state["queue"].queue.get() # type: ignore[attr-defined]
|
||||||
|
update = update.to_dict()
|
||||||
|
assert update["update_id"] == bot_update["update_id"]
|
||||||
|
assert_that(update["message"]).is_equal_to(
|
||||||
|
bot_update["message"], include=["from", "entities", "message_id", "text"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_bot_queue(
|
async def test_bot_queue(
|
||||||
bot: BotApplication,
|
bot: BotApplication,
|
||||||
bot_application: Any,
|
|
||||||
main_application: Application,
|
|
||||||
event_loop: AbstractEventLoop,
|
event_loop: AbstractEventLoop,
|
||||||
) -> None:
|
) -> None:
|
||||||
bot.application = bot_application
|
|
||||||
bot_queue = BotQueue(bot_app=bot)
|
bot_queue = BotQueue(bot_app=bot)
|
||||||
event_loop.create_task(bot_queue.get_updates_from_queue())
|
event_loop.create_task(bot_queue.get_updates_from_queue())
|
||||||
mocked_request = MockedRequest(
|
bot_update = create_bot_update()
|
||||||
{
|
mocked_request = MockedRequest(bot_update)
|
||||||
"update_id": 957250703,
|
|
||||||
"message": {
|
|
||||||
"message_id": 417070387,
|
|
||||||
"from": {
|
|
||||||
"id": 1000,
|
|
||||||
"is_bot": "false",
|
|
||||||
"first_name": "William",
|
|
||||||
"last_name": "Dalton",
|
|
||||||
"username": "bolshakovfortunat",
|
|
||||||
"language_code": "ru",
|
|
||||||
},
|
|
||||||
"chat": {
|
|
||||||
"id": 1,
|
|
||||||
"first_name": "Gabrielle",
|
|
||||||
"last_name": "Smith",
|
|
||||||
"username": "arefi_2019",
|
|
||||||
"type": "private",
|
|
||||||
},
|
|
||||||
"date": time.time(),
|
|
||||||
"text": "/chatid",
|
|
||||||
"entities": [{"type": "bot_command", "offset": 0, "length": 7}],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
await bot_queue.put_updates_on_queue(mocked_request) # type: ignore
|
await bot_queue.put_updates_on_queue(mocked_request) # type: ignore
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
assert bot_queue.queue.empty()
|
assert bot_queue.queue.empty()
|
||||||
|
|
||||||
|
|
||||||
|
def create_bot_update() -> dict[str, Any]:
|
||||||
|
bot_update: dict[str, Any] = {}
|
||||||
|
bot_update["update_id"] = faker.random_int(min=10**8, max=10**9 - 1)
|
||||||
|
bot_update["message"] = {
|
||||||
|
"message_id": faker.random_int(min=10**8, max=10**9 - 1),
|
||||||
|
"from": BotUserFactory()._asdict(),
|
||||||
|
"chat": BotChatFactory()._asdict(),
|
||||||
|
"date": time.time(),
|
||||||
|
"text": "/chatid",
|
||||||
|
"entities": [BotEntitleFactory()],
|
||||||
|
}
|
||||||
|
return bot_update
|
||||||
|
@ -1,35 +1,14 @@
|
|||||||
import string
|
import string
|
||||||
import time
|
|
||||||
|
|
||||||
import factory
|
import factory
|
||||||
from faker import Faker
|
from faker import Faker
|
||||||
|
|
||||||
from tests.integration.factories.models import Chat, User
|
from tests.integration.factories.models import Chat, User
|
||||||
|
|
||||||
data = {
|
|
||||||
"update_id": 957250703,
|
|
||||||
"message": {
|
|
||||||
"message_id": 417070387,
|
|
||||||
"from": {
|
|
||||||
"id": 1000,
|
|
||||||
"is_bot": "false",
|
|
||||||
"first_name": "William",
|
|
||||||
"last_name": "Dalton",
|
|
||||||
"username": "bolshakovfortunat",
|
|
||||||
"language_code": "ru",
|
|
||||||
},
|
|
||||||
"chat": {"id": 1, "first_name": "Gabrielle", "last_name": "Smith", "username": "arefi_2019", "type": "private"},
|
|
||||||
"date": time.time(),
|
|
||||||
"text": "/chatid",
|
|
||||||
"entities": [{"type": "bot_command", "offset": 0, "length": 7}],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
faker = Faker("ru_RU")
|
faker = Faker("ru_RU")
|
||||||
|
|
||||||
|
|
||||||
class UserFactory(factory.Factory):
|
class BotUserFactory(factory.Factory):
|
||||||
id = factory.Sequence(lambda n: 1000 + n)
|
id = factory.Sequence(lambda n: 1000 + n)
|
||||||
is_bot = False
|
is_bot = False
|
||||||
first_name = factory.Faker("first_name")
|
first_name = factory.Faker("first_name")
|
||||||
@ -41,7 +20,7 @@ class UserFactory(factory.Factory):
|
|||||||
model = User
|
model = User
|
||||||
|
|
||||||
|
|
||||||
class ChatFactory(factory.Factory):
|
class BotChatFactory(factory.Factory):
|
||||||
id = factory.Sequence(lambda n: 1 + n)
|
id = factory.Sequence(lambda n: 1 + n)
|
||||||
first_name = factory.Faker("first_name")
|
first_name = factory.Faker("first_name")
|
||||||
last_name = factory.Faker("last_name")
|
last_name = factory.Faker("last_name")
|
||||||
@ -70,3 +49,9 @@ class BotInfoFactory(factory.DictFactory):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
exclude = ("channel_name", "fake_username")
|
exclude = ("channel_name", "fake_username")
|
||||||
|
|
||||||
|
|
||||||
|
class BotEntitleFactory(factory.DictFactory):
|
||||||
|
type = "bot_command"
|
||||||
|
offset = 0
|
||||||
|
length = 7
|
||||||
|
Loading…
x
Reference in New Issue
Block a user