├── core ├── __init__.py ├── asgi.py ├── wsgi.py ├── urls.py └── settings.py ├── robot ├── __init__.py ├── management │ ├── __init__.py │ └── commands │ │ └── runbot.py ├── migrations │ ├── __init__.py │ ├── 0004_delete_permission.py │ ├── 0002_alter_telegramuser_username.py │ ├── 0003_alter_permission_name.py │ └── 0001_initial.py ├── handlers │ ├── groups │ │ └── __init__.py │ ├── errors │ │ ├── __init__.py │ │ └── error_handler.py │ ├── __init__.py │ └── users │ │ ├── __init__.py │ │ ├── echo.py │ │ ├── help.py │ │ ├── midjourney.py │ │ ├── cancel.py │ │ ├── start.py │ │ ├── example.py │ │ ├── contact.py │ │ └── create.py ├── utils │ ├── db_api │ │ └── __init__.py │ ├── misc │ │ ├── __init__.py │ │ ├── logging.py │ │ └── throttling.py │ ├── __init__.py │ ├── set_bot_commands.py │ └── notify_admins.py ├── keyboards │ ├── inline │ │ └── __init__.py │ ├── __init__.py │ └── default │ │ ├── __init__.py │ │ └── user_register.py ├── media │ └── example │ │ ├── hire.jpg │ │ ├── example_1.jpg │ │ ├── example_2.jpg │ │ ├── example_3.jpg │ │ └── nav-brend.jpg ├── states │ ├── __init__.py │ ├── create_image.py │ ├── admin_message.py │ └── user_register.py ├── apps.py ├── middlewares │ ├── __init__.py │ └── throttling.py ├── admin.py └── models.py ├── requirements.txt ├── loader.py ├── .env.template ├── README.md ├── manage.py ├── const_texts.py └── .gitignore /core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /robot/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /robot/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /robot/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /robot/handlers/groups/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /robot/utils/db_api/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /robot/keyboards/inline/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /robot/handlers/errors/__init__.py: -------------------------------------------------------------------------------- 1 | from . import error_handler 2 | -------------------------------------------------------------------------------- /robot/keyboards/__init__.py: -------------------------------------------------------------------------------- 1 | from . import default 2 | from . import inline 3 | -------------------------------------------------------------------------------- /robot/keyboards/default/__init__.py: -------------------------------------------------------------------------------- 1 | from .user_register import make_buttons 2 | -------------------------------------------------------------------------------- /robot/utils/misc/__init__.py: -------------------------------------------------------------------------------- 1 | from .throttling import rate_limit 2 | from . import logging 3 | -------------------------------------------------------------------------------- /robot/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import errors 2 | from . import users 3 | from . import groups 4 | -------------------------------------------------------------------------------- /robot/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from . import db_api 2 | from . import misc 3 | from .notify_admins import on_startup_notify 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiogram==2.23.1 2 | Django==4.1.4 3 | environs==9.5.0 4 | replicate==0.4.0 5 | Pillow==9.4.0 6 | psycopg2==2.9.5 -------------------------------------------------------------------------------- /robot/media/example/hire.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bekmuxtorov/midjourney-telegram-bot/HEAD/robot/media/example/hire.jpg -------------------------------------------------------------------------------- /robot/media/example/example_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bekmuxtorov/midjourney-telegram-bot/HEAD/robot/media/example/example_1.jpg -------------------------------------------------------------------------------- /robot/media/example/example_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bekmuxtorov/midjourney-telegram-bot/HEAD/robot/media/example/example_2.jpg -------------------------------------------------------------------------------- /robot/media/example/example_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bekmuxtorov/midjourney-telegram-bot/HEAD/robot/media/example/example_3.jpg -------------------------------------------------------------------------------- /robot/media/example/nav-brend.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bekmuxtorov/midjourney-telegram-bot/HEAD/robot/media/example/nav-brend.jpg -------------------------------------------------------------------------------- /robot/states/__init__.py: -------------------------------------------------------------------------------- 1 | from .user_register import UserRegister 2 | from .create_image import CreateImage 3 | from .admin_message import Contact 4 | -------------------------------------------------------------------------------- /robot/states/create_image.py: -------------------------------------------------------------------------------- 1 | from aiogram.dispatcher.filters.state import StatesGroup, State 2 | 3 | 4 | class CreateImage(StatesGroup): 5 | create_image = State() 6 | -------------------------------------------------------------------------------- /robot/states/admin_message.py: -------------------------------------------------------------------------------- 1 | from aiogram.dispatcher.filters.state import StatesGroup, State 2 | 3 | 4 | class Contact(StatesGroup): 5 | admin_message = State() 6 | send_admin = State() 7 | -------------------------------------------------------------------------------- /robot/utils/misc/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | logging.basicConfig( 4 | format=u'%(filename)s [LINE:%(lineno)d] #%(levelname)-8s [%(asctime)s] %(message)s', 5 | level=logging.INFO, 6 | ) 7 | -------------------------------------------------------------------------------- /robot/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class RobotConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'robot' 7 | verbose_name = 'Telegram bot' 8 | -------------------------------------------------------------------------------- /robot/handlers/users/__init__.py: -------------------------------------------------------------------------------- 1 | from . import help 2 | from . import start 3 | from . import create 4 | from . import example 5 | from . import midjourney 6 | from . import contact 7 | from . import cancel 8 | from . import echo 9 | -------------------------------------------------------------------------------- /robot/middlewares/__init__.py: -------------------------------------------------------------------------------- 1 | from aiogram import Dispatcher 2 | 3 | from loader import dp 4 | from .throttling import ThrottlingMiddleware 5 | 6 | 7 | if __name__ == "middlewares": 8 | dp.middleware.setup(ThrottlingMiddleware()) 9 | -------------------------------------------------------------------------------- /robot/handlers/users/echo.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | 3 | from loader import dp 4 | 5 | 6 | # Echo bot 7 | @dp.message_handler(state=None) 8 | async def bot_echo(message: types.Message): 9 | await message.answer(message.text) 10 | -------------------------------------------------------------------------------- /robot/states/user_register.py: -------------------------------------------------------------------------------- 1 | from aiogram.dispatcher.filters.state import StatesGroup, State 2 | 3 | 4 | class UserRegister(StatesGroup): 5 | username = State() 6 | first_name = State() 7 | last_name = State() 8 | password = State() 9 | -------------------------------------------------------------------------------- /loader.py: -------------------------------------------------------------------------------- 1 | from aiogram import Bot, Dispatcher, types 2 | from aiogram.contrib.fsm_storage.memory import MemoryStorage 3 | from django.conf import settings 4 | 5 | 6 | bot = Bot(token=settings.BOT_TOKEN, parse_mode=types.ParseMode.HTML) 7 | storage = MemoryStorage() 8 | dp = Dispatcher(bot, storage=storage) 9 | -------------------------------------------------------------------------------- /robot/utils/set_bot_commands.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | 3 | 4 | async def set_default_commands(dp): 5 | await dp.bot.set_my_commands( 6 | [ 7 | types.BotCommand("start", "Botni ishga tushurish"), 8 | types.BotCommand("help", "Yordam"), 9 | ] 10 | ) 11 | -------------------------------------------------------------------------------- /.env.template: -------------------------------------------------------------------------------- 1 | SECRET_KEY=django-insecure 2 | DEBUG=True 3 | ALLOWED_HOSTS=localhost,127.0.0.1 4 | 5 | BOT_TOKEN=527407998:AAEhQD8PPUw 6 | ADMINS_LIST=51256566641 7 | 8 | REPLICATE_API_TOKEN= 9 | 10 | DB_TYPE=postgres 11 | DB_NAME=your_db_name 12 | DB_USER=your_db_user 13 | DB_PASSWORD=your_password 14 | DB_HOST=localhost 15 | DB_PORT=5432 -------------------------------------------------------------------------------- /robot/utils/notify_admins.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from aiogram import Dispatcher 4 | 5 | from django.conf import settings 6 | 7 | 8 | async def on_startup_notify(dp: Dispatcher): 9 | for admin in settings.ADMINS_LIST: 10 | try: 11 | await dp.bot.send_message(admin, "Bot ishga tushirildi") 12 | 13 | except Exception as err: 14 | logging.exception(err) 15 | -------------------------------------------------------------------------------- /robot/migrations/0004_delete_permission.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.4 on 2023-03-26 17:13 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('robot', '0003_alter_permission_name'), 10 | ] 11 | 12 | operations = [ 13 | migrations.DeleteModel( 14 | name='Permission', 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /robot/handlers/users/help.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | from aiogram.dispatcher.filters.builtin import CommandHelp 3 | 4 | from loader import dp 5 | 6 | 7 | @dp.message_handler(CommandHelp()) 8 | async def bot_help(message: types.Message): 9 | text = ("Buyruqlar: ", 10 | "/start - Botni ishga tushirish", 11 | "/help - Yordam") 12 | 13 | await message.answer("\n".join(text)) 14 | -------------------------------------------------------------------------------- /robot/utils/misc/throttling.py: -------------------------------------------------------------------------------- 1 | def rate_limit(limit: int, key=None): 2 | """ 3 | Decorator for configuring rate limit and key in different functions. 4 | 5 | :param limit: 6 | :param key: 7 | :return: 8 | """ 9 | 10 | def decorator(func): 11 | setattr(func, 'throttling_rate_limit', limit) 12 | if key: 13 | setattr(func, 'throttling_key', key) 14 | return func 15 | 16 | return decorator 17 | -------------------------------------------------------------------------------- /core/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for core project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /core/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for core project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /robot/keyboards/default/user_register.py: -------------------------------------------------------------------------------- 1 | from aiogram.types import ReplyKeyboardMarkup, KeyboardButton 2 | from const_texts import c_cancel 3 | 4 | 5 | def make_buttons(words: list, row_width: int = 1) -> ReplyKeyboardMarkup: 6 | buttons_group = ReplyKeyboardMarkup( 7 | row_width=row_width, resize_keyboard=True) 8 | for word in words: 9 | if word is not None: 10 | buttons_group.insert(KeyboardButton(text=word)) 11 | return buttons_group 12 | -------------------------------------------------------------------------------- /robot/handlers/users/midjourney.py: -------------------------------------------------------------------------------- 1 | import replicate 2 | from environs import Env 3 | 4 | env = Env() 5 | env.read_env() 6 | 7 | # Set the REPLICATE_API_TOKEN environment variable 8 | REPLICATE_API_TOKEN = env.str("REPLICATE_API_TOKEN") 9 | model = replicate.models.get("tstramer/midjourney-diffusion") 10 | version = model.versions.get( 11 | "436b051ebd8f68d23e83d22de5e198e0995357afef113768c20f0b6fcef23c8b") 12 | 13 | 14 | def draw_picture(input: str, version: str = version) -> str: 15 | return version.predict(prompt=input) 16 | -------------------------------------------------------------------------------- /robot/migrations/0002_alter_telegramuser_username.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.4 on 2023-01-13 12:56 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('robot', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='telegramuser', 15 | name='username', 16 | field=models.CharField(blank=True, default='Nomalum', max_length=40, null=True, verbose_name='Username'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /robot/migrations/0003_alter_permission_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.4 on 2023-03-26 00:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('robot', '0002_alter_telegramuser_username'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='permission', 15 | name='name', 16 | field=models.CharField(choices=[('midjourney', 'Midjourney'), ('googletrans', 'Googletrans')], max_length=100, verbose_name='API nomi'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /robot/handlers/users/cancel.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | from aiogram.dispatcher import FSMContext 3 | 4 | from robot.keyboards.default import make_buttons 5 | from const_texts import c_create, c_example, c_contact, c_cancel 6 | from loader import dp 7 | 8 | 9 | # Echo bot 10 | @dp.message_handler(text=c_cancel, state='*') 11 | async def bot_start(message: types.Message, state: FSMContext): 12 | await state.finish() 13 | await message.answer( 14 | text="Yaxshi. Ortga qaytamiz.", 15 | reply_markup=make_buttons( 16 | words=[c_create, c_example, c_contact], 17 | row_width=2 18 | ) 19 | ) 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Django + Aiogram 2 | 3 | ## 1. Create virtualenv and activate 4 | 5 | ```sh 6 | python3 -m virtualenv venv 7 | source venv/bin/activate 8 | ``` 9 | 10 | ## 2. Install required packages 11 | 12 | ```sh 13 | pip install -r requirements.txt 14 | ``` 15 | 16 | ## 3. Create ```.env``` file using env template file and fill it 17 | 18 | ```sh 19 | cp .env.template .env 20 | ``` 21 | 22 | ## 4. Run django project 23 | 24 | - Migrations 25 | 26 | ```sh 27 | python manage.py migrate 28 | ``` 29 | 30 | - Run server 31 | 32 | ```sh 33 | python manage.py runserver 34 | ``` 35 | 36 | ## 5. Run aiogram project 37 | 38 | ```sh 39 | python manage.py runbot 40 | ``` 41 | -------------------------------------------------------------------------------- /robot/management/commands/runbot.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand, CommandError 2 | 3 | from aiogram import executor 4 | 5 | from loader import dp 6 | 7 | from robot.middlewares import * 8 | from robot.handlers import * 9 | 10 | from robot.utils.notify_admins import on_startup_notify 11 | from robot.utils.set_bot_commands import set_default_commands 12 | 13 | 14 | async def on_startup(dispatcher): 15 | await set_default_commands(dispatcher) 16 | await on_startup_notify(dispatcher) 17 | 18 | 19 | class Command(BaseCommand): 20 | help = 'RUN COMMAND: python manage.py runbot' 21 | 22 | def handle(self, *args, **options): 23 | executor.start_polling(dp, on_startup=on_startup) 24 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /robot/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import TelegramUser, Example, Request, Message 3 | 4 | 5 | class TelegramUserAdmin(admin.ModelAdmin): 6 | list_display = ['id', 'full_name', 'get_username', 7 | 'tg_id', 'request_all_count'] 8 | search_fields = ['full_name'] 9 | 10 | 11 | class ExampleAdmin(admin.ModelAdmin): 12 | list_display = ['id', 'description', 'create_date'] 13 | ordering = ['-create_date'] 14 | 15 | 16 | class RequestAdmin(admin.ModelAdmin): 17 | list_display = ['id', 'user', 'get_date'] 18 | search_fields = ['user'] 19 | 20 | 21 | class MessageAdmin(admin.ModelAdmin): 22 | list_display = ['id', 'user', 'get_username', 23 | 'get_date', 'get_message'] 24 | search_fields = ['user'] 25 | 26 | 27 | admin.site.register(TelegramUser, TelegramUserAdmin) 28 | admin.site.register(Example, ExampleAdmin) 29 | admin.site.register(Request, RequestAdmin) 30 | admin.site.register(Message, MessageAdmin) 31 | -------------------------------------------------------------------------------- /core/urls.py: -------------------------------------------------------------------------------- 1 | """core URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from django.conf import settings 19 | from django.conf.urls.static import static 20 | 21 | urlpatterns = [ 22 | path('admin/', admin.site.urls), 23 | ] 24 | 25 | urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 26 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 27 | -------------------------------------------------------------------------------- /robot/handlers/users/start.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from asgiref.sync import sync_to_async 4 | from robot.models import TelegramUser 5 | 6 | from aiogram import types 7 | from aiogram.dispatcher.filters.builtin import CommandStart 8 | 9 | from loader import dp, bot 10 | from const_texts import c_get_hello, c_about_us, c_create, c_example, c_contact 11 | from robot.keyboards.default import make_buttons 12 | 13 | 14 | @dp.message_handler(CommandStart()) 15 | async def bot_start(message: types.Message): 16 | telegram_user, _ = await TelegramUser.objects.aget_or_create( 17 | full_name=message.from_user.full_name, 18 | username=message.from_user.username, 19 | tg_id=message.from_user.id, 20 | chat_id=message.chat.id, 21 | ) 22 | logging.info("New user") 23 | chat_id = message.from_user.id 24 | await bot.send_animation( 25 | chat_id=chat_id, 26 | animation="https://t.me/sinovuchun4101/15", 27 | caption=c_get_hello(message.from_user.full_name), 28 | reply_markup=make_buttons( 29 | words=[c_create, c_example, c_contact], 30 | row_width=2 31 | ) 32 | ) 33 | -------------------------------------------------------------------------------- /robot/handlers/users/example.py: -------------------------------------------------------------------------------- 1 | from asgiref.sync import sync_to_async 2 | from aiogram import types 3 | from aiogram.types.input_file import InputFile 4 | 5 | from loader import dp, bot 6 | from const_texts import c_example, c_example_get_caption, c_create, c_contact, c_null_base 7 | from robot.models import Example 8 | from robot.keyboards.default import make_buttons 9 | 10 | 11 | def get_image(image_url): 12 | return InputFile(path_or_bytesio=image_url) 13 | 14 | 15 | @dp.message_handler(text=c_example) 16 | async def bot_echo(message: types.Message): 17 | try: 18 | chat_id = message.from_user.id 19 | example_photos = await sync_to_async(list)(Example.objects.all()) 20 | for indx, example_photo in enumerate(example_photos, start=1): 21 | await bot.send_photo( 22 | chat_id=chat_id, 23 | photo=get_image(example_photo.image.path), 24 | caption=c_example_get_caption(example_photo.description, indx), 25 | reply_markup=make_buttons( 26 | words=[c_create, c_example, c_contact], 27 | row_width=2 28 | ) 29 | ) 30 | 31 | except Exception: 32 | print('='*5 + c_null_base + '='*5) 33 | await message.answer(text=c_null_base) 34 | -------------------------------------------------------------------------------- /const_texts.py: -------------------------------------------------------------------------------- 1 | def c_get_hello(full_name: str) -> str: 2 | return f"Assalomu alaykum, {full_name.title()}\nBu Midjorneydan to'g'ridan-to'g'ri telegramda mavjud bo'lgan bot!\n\n" \ 3 | "🔥Endi siz messenjerdan chiqmasdan matn tavsifiga muvofiq istalgan tasvirni yaratishingiz mumkin!\n\n"\ 4 | "Namunalarni ko'rish uchun bosing👇" 5 | 6 | 7 | def c_example_get_caption(description: str, indx: int = 0) -> str: 8 | if indx != 0: 9 | return f'{indx} - namuna \n\n' \ 10 | f"Tavsif: {description}" 11 | else: 12 | return f"\n\nTavsif: {description}\n\n👉@midjourney_imagebot" 13 | 14 | 15 | c_create_description = 'Marhamat tassavuringizdagi suratni so\'zlar yordamida bayon qilib bering. \n\n🖋Matnni kiriting...' 16 | c_null_base = 'Bizda hali namunalar mavjud emas.' 17 | c_example = 'Namunalar🏞' 18 | c_create = 'Yaratish🤖' 19 | c_contact = '📑Bog\'lanish' 20 | c_about_us = "Biz haqimizda 👁️" 21 | c_error_words = '🛠Botda texnik ishlar olib borilmoqda. Birozdan keyin qayta urinib ko\'ring.\n\nKeltirilgan noqulayliklar uchun uzr so\'raymiz!' 22 | c_block_words = '24 soatda 4 marta so\'rov jo\'natishingiz mumkin. \n\nSizni so\'rovingiz limitdan oshdi. 24 soatdan keyin qayta urinib ko\'ring' 23 | c_contact_message = "📥Marhamat murojaatingizni yo'llang:" 24 | c_cancel = '🔙Ortga', 25 | c_create_image = '🖍Rasm chizilmoqda...' 26 | c_send_admin_succsess = '✔Murojjat muaffaqiyatli jo\'natildi, Tez orada javob qaytariladi.' 27 | -------------------------------------------------------------------------------- /robot/middlewares/throttling.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from aiogram import types, Dispatcher 4 | from aiogram.dispatcher import DEFAULT_RATE_LIMIT 5 | from aiogram.dispatcher.handler import CancelHandler, current_handler 6 | from aiogram.dispatcher.middlewares import BaseMiddleware 7 | from aiogram.utils.exceptions import Throttled 8 | 9 | 10 | class ThrottlingMiddleware(BaseMiddleware): 11 | """ 12 | Simple middleware 13 | """ 14 | 15 | def __init__(self, limit=DEFAULT_RATE_LIMIT, key_prefix='antiflood_'): 16 | self.rate_limit = limit 17 | self.prefix = key_prefix 18 | super(ThrottlingMiddleware, self).__init__() 19 | 20 | async def on_process_message(self, message: types.Message, data: dict): 21 | handler = current_handler.get() 22 | dispatcher = Dispatcher.get_current() 23 | if handler: 24 | limit = getattr(handler, "throttling_rate_limit", self.rate_limit) 25 | key = getattr(handler, "throttling_key", f"{self.prefix}_{handler.__name__}") 26 | else: 27 | limit = self.rate_limit 28 | key = f"{self.prefix}_message" 29 | try: 30 | await dispatcher.throttle(key, rate=limit) 31 | except Throttled as t: 32 | await self.message_throttled(message, t) 33 | raise CancelHandler() 34 | 35 | async def message_throttled(self, message: types.Message, throttled: Throttled): 36 | if throttled.exceeded_count <= 2: 37 | await message.reply("Too many requests!") 38 | -------------------------------------------------------------------------------- /robot/handlers/users/contact.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | from aiogram.dispatcher import FSMContext 3 | 4 | from const_texts import c_contact, c_contact_message, c_cancel, c_send_admin_succsess 5 | from loader import dp, bot 6 | 7 | from robot.states.admin_message import Contact 8 | from robot.keyboards.default import make_buttons 9 | from robot.models import Message, TelegramUser 10 | from core.settings import ADMINS_LIST 11 | 12 | 13 | # Echo bot 14 | 15 | 16 | @dp.message_handler(text=c_contact) 17 | async def bot_help(message: types.Message): 18 | await message.answer( 19 | text=c_contact_message 20 | ) 21 | await Contact.admin_message.set() 22 | 23 | 24 | @dp.message_handler(state=Contact.admin_message) 25 | async def bot_help(message: types.Message, state: FSMContext): 26 | admin_message = message.text 27 | full_name = message.from_user.full_name 28 | user_id = message.from_user.id 29 | user_name = message.from_user.username 30 | user = await TelegramUser.objects.aget(tg_id=user_id) 31 | 32 | admin_full_message = f"Ismi: {full_name}\n" \ 33 | f"User ID: {user_id}\n" \ 34 | f"Username: {user_name}\n\n" \ 35 | f"Xabar: {admin_message}" 36 | 37 | for admin in ADMINS_LIST: 38 | await bot.send_message( 39 | chat_id=admin, 40 | text=admin_full_message 41 | ) 42 | 43 | await bot.send_message( 44 | chat_id=user_id, 45 | text=c_send_admin_succsess, 46 | reply_markup=make_buttons(c_cancel) 47 | ) 48 | await Message.objects.acreate( 49 | user=user, 50 | message=admin_message 51 | ) 52 | 53 | await state.finish() 54 | -------------------------------------------------------------------------------- /robot/handlers/users/create.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | from aiogram.dispatcher import FSMContext 3 | 4 | from asgiref.sync import sync_to_async 5 | from .midjourney import draw_picture 6 | from loader import dp, bot 7 | from const_texts import c_create, c_example, c_contact, c_create_description, c_create_image, c_example_get_caption, c_block_words 8 | from robot.states import CreateImage 9 | from robot.keyboards.default import make_buttons 10 | 11 | from robot.models import TelegramUser, Request 12 | 13 | from datetime import datetime, timezone 14 | 15 | 16 | @dp.message_handler(text=c_create) 17 | async def bot_echo(message: types.Message): 18 | await CreateImage.create_image.set() 19 | await message.answer(text=c_create_description) 20 | 21 | 22 | @dp.message_handler(state=CreateImage.create_image) 23 | async def bot_echo(message: types.Message, state: FSMContext): 24 | user = await TelegramUser.objects.aget(tg_id=message.from_user.id) 25 | 26 | input = message.text.lower().strip() 27 | 28 | request_count = await Request.objects.filter(user=user).acount() 29 | if request_count <= 4: 30 | await message.answer( 31 | text=c_create_image 32 | ) 33 | result = draw_picture( 34 | input=input 35 | )[0] 36 | await bot.send_photo( 37 | chat_id=message.from_user.id, 38 | photo=result, 39 | caption=c_example_get_caption(input), 40 | reply_markup=make_buttons( 41 | words=[c_create, c_example, c_contact], 42 | row_width=2 43 | ) 44 | ) 45 | await state.finish() 46 | await sync_to_async(user.set_request_count)() 47 | await Request.objects.acreate(user=user) 48 | 49 | else: 50 | result = None 51 | await message.answer( 52 | text=c_block_words 53 | ) 54 | await state.finish() 55 | return 56 | -------------------------------------------------------------------------------- /robot/handlers/errors/error_handler.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from aiogram.utils.exceptions import (Unauthorized, InvalidQueryID, TelegramAPIError, 3 | CantDemoteChatCreator, MessageNotModified, MessageToDeleteNotFound, 4 | MessageTextIsEmpty, RetryAfter, 5 | CantParseEntities, MessageCantBeDeleted) 6 | 7 | 8 | from loader import dp 9 | 10 | 11 | @dp.errors_handler() 12 | async def errors_handler(update, exception): 13 | """ 14 | Exceptions handler. Catches all exceptions within task factory tasks. 15 | :param dispatcher: 16 | :param update: 17 | :param exception: 18 | :return: stdout logging 19 | """ 20 | 21 | if isinstance(exception, CantDemoteChatCreator): 22 | logging.exception("Can't demote chat creator") 23 | return True 24 | 25 | if isinstance(exception, MessageNotModified): 26 | logging.exception('Message is not modified') 27 | return True 28 | if isinstance(exception, MessageCantBeDeleted): 29 | logging.exception('Message cant be deleted') 30 | return True 31 | 32 | if isinstance(exception, MessageToDeleteNotFound): 33 | logging.exception('Message to delete not found') 34 | return True 35 | 36 | if isinstance(exception, MessageTextIsEmpty): 37 | logging.exception('MessageTextIsEmpty') 38 | return True 39 | 40 | if isinstance(exception, Unauthorized): 41 | logging.exception(f'Unauthorized: {exception}') 42 | return True 43 | 44 | if isinstance(exception, InvalidQueryID): 45 | logging.exception(f'InvalidQueryID: {exception} \nUpdate: {update}') 46 | return True 47 | 48 | if isinstance(exception, TelegramAPIError): 49 | logging.exception(f'TelegramAPIError: {exception} \nUpdate: {update}') 50 | return True 51 | if isinstance(exception, RetryAfter): 52 | logging.exception(f'RetryAfter: {exception} \nUpdate: {update}') 53 | return True 54 | if isinstance(exception, CantParseEntities): 55 | logging.exception(f'CantParseEntities: {exception} \nUpdate: {update}') 56 | return True 57 | 58 | logging.exception(f'Update: {update} \n{exception}') 59 | -------------------------------------------------------------------------------- /robot/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.4 on 2023-01-11 10:56 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='Example', 17 | fields=[ 18 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('description', models.TextField(verbose_name='Rasm haqida batafsil')), 20 | ('image', models.ImageField(upload_to='example/', verbose_name='Namuna rasm')), 21 | ('create_date', models.DateTimeField(auto_now_add=True)), 22 | ], 23 | options={ 24 | 'verbose_name': 'Example photo', 25 | 'verbose_name_plural': 'Example photos', 26 | }, 27 | ), 28 | migrations.CreateModel( 29 | name='Permission', 30 | fields=[ 31 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 32 | ('name', models.CharField(max_length=100, verbose_name='Ruhsat nomi')), 33 | ('permission_status', models.BooleanField(choices=[(True, 'Ishga tushirish'), (False, "To'xtatish")], default=True, verbose_name='Xolat')), 34 | ], 35 | ), 36 | migrations.CreateModel( 37 | name='TelegramUser', 38 | fields=[ 39 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 40 | ('full_name', models.CharField(max_length=100, verbose_name='Ismi va familiya')), 41 | ('username', models.CharField(blank=True, max_length=40, null=True, verbose_name='Username')), 42 | ('tg_id', models.CharField(max_length=20, verbose_name='Telegram id')), 43 | ('chat_id', models.CharField(max_length=20, verbose_name='Chat id')), 44 | ('request_all_count', models.IntegerField(default=0, verbose_name="Umumiy so'rovlar soni")), 45 | ], 46 | ), 47 | migrations.CreateModel( 48 | name='Request', 49 | fields=[ 50 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 51 | ('create_add', models.DateTimeField(auto_now_add=True)), 52 | ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='robot.telegramuser', verbose_name='User')), 53 | ], 54 | ), 55 | migrations.CreateModel( 56 | name='Message', 57 | fields=[ 58 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 59 | ('message', models.TextField(blank=True, null=True, verbose_name='Xabar')), 60 | ('create_add', models.DateTimeField(auto_now_add=True)), 61 | ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='robot.telegramuser', verbose_name='User')), 62 | ], 63 | ), 64 | ] 65 | -------------------------------------------------------------------------------- /robot/models.py: -------------------------------------------------------------------------------- 1 | import datetime as dt 2 | from django.utils.html import mark_safe 3 | from django.db import models 4 | from django.contrib.auth import get_user_model 5 | from asgiref.sync import sync_to_async 6 | 7 | API_NAME = ( 8 | ('midjourney', 'Midjourney'), 9 | ('googletrans', 'Googletrans') 10 | ) 11 | 12 | 13 | class TelegramUser(models.Model): 14 | full_name = models.CharField( 15 | max_length=100, 16 | verbose_name='Ismi va familiya' 17 | ) 18 | 19 | username = models.CharField( 20 | max_length=40, 21 | verbose_name='Username', 22 | null=True, 23 | blank=True, 24 | default='Nomalum' 25 | ) 26 | 27 | tg_id = models.CharField( 28 | max_length=20, 29 | verbose_name='Telegram id' 30 | ) 31 | 32 | chat_id = models.CharField( 33 | max_length=20, 34 | verbose_name='Chat id' 35 | ) 36 | 37 | request_all_count = models.IntegerField( 38 | verbose_name='Umumiy so\'rovlar soni', 39 | default=0 40 | ) 41 | 42 | def set_request_count(self): 43 | self.request_all_count += 1 44 | self.save() 45 | 46 | def __str__(self) -> str: 47 | return self.full_name 48 | 49 | def get_user(self): 50 | return self.user 51 | 52 | def set_user(self, user): 53 | self.user = user 54 | self.save() 55 | 56 | def get_username(self): 57 | return mark_safe(f"@{self.username}") 58 | 59 | 60 | class Example(models.Model): 61 | description = models.TextField( 62 | verbose_name="Rasm haqida batafsil" 63 | ) 64 | 65 | image = models.ImageField( 66 | upload_to='example/', 67 | verbose_name="Namuna rasm" 68 | ) 69 | 70 | create_date = models.DateTimeField( 71 | auto_now_add=True 72 | ) 73 | 74 | def __str__(self): 75 | return self.description 76 | 77 | class Meta: 78 | verbose_name = 'Example photo' 79 | verbose_name_plural = 'Example photos' 80 | 81 | 82 | class Request(models.Model): 83 | user = models.ForeignKey( 84 | to=TelegramUser, 85 | on_delete=models.SET_NULL, 86 | verbose_name='User', 87 | null=True, 88 | blank=True 89 | ) 90 | 91 | create_add = models.DateTimeField( 92 | auto_now_add=True, 93 | ) 94 | 95 | def get_date(self): 96 | return self.create_add.strftime("%H:%M:%S, %d/%m/%Y") 97 | 98 | 99 | class Message(models.Model): 100 | user = models.ForeignKey( 101 | to=TelegramUser, 102 | on_delete=models.SET_NULL, 103 | verbose_name='User', 104 | null=True, 105 | blank=True 106 | ) 107 | 108 | message = models.TextField( 109 | verbose_name='Xabar', 110 | blank=True, 111 | null=True 112 | ) 113 | 114 | create_add = models.DateTimeField( 115 | auto_now_add=True 116 | ) 117 | 118 | def __str__(self): 119 | return f'{self.user} || {self.id} message' 120 | 121 | def get_message(self): 122 | return self.message[:100] 123 | 124 | def get_date(self): 125 | return self.create_add.strftime("%H:%M:%S, %d/%m/%Y") 126 | 127 | def get_username(self): 128 | return self.user.username 129 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | .idea/ -------------------------------------------------------------------------------- /core/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for core project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.1.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | from environs import Env 15 | 16 | env = Env() 17 | env.read_env() 18 | 19 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 20 | BASE_DIR = Path(__file__).resolve().parent.parent 21 | 22 | 23 | # Quick-start development settings - unsuitable for production 24 | # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ 25 | 26 | # SECURITY WARNING: keep the secret key used in production secret! 27 | SECRET_KEY = env.str('SECRET_KEY') 28 | 29 | # SECURITY WARNING: don't run with debug turned on in production! 30 | DEBUG = env.bool('DEBUG', False) 31 | ALLOWED_HOSTS = env.list('ALLOWED_HOSTS') 32 | 33 | 34 | # Application definition 35 | 36 | INSTALLED_APPS = [ 37 | 'django.contrib.admin', 38 | 'django.contrib.auth', 39 | 'django.contrib.contenttypes', 40 | 'django.contrib.sessions', 41 | 'django.contrib.messages', 42 | 'django.contrib.staticfiles', 43 | 'robot.apps.RobotConfig', 44 | ] 45 | 46 | MIDDLEWARE = [ 47 | 'django.middleware.security.SecurityMiddleware', 48 | 'django.contrib.sessions.middleware.SessionMiddleware', 49 | 'django.middleware.common.CommonMiddleware', 50 | 'django.middleware.csrf.CsrfViewMiddleware', 51 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 52 | 'django.contrib.messages.middleware.MessageMiddleware', 53 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 54 | ] 55 | 56 | ROOT_URLCONF = 'core.urls' 57 | 58 | TEMPLATES = [ 59 | { 60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 61 | 'DIRS': [], 62 | 'APP_DIRS': True, 63 | 'OPTIONS': { 64 | 'context_processors': [ 65 | 'django.template.context_processors.debug', 66 | 'django.template.context_processors.request', 67 | 'django.contrib.auth.context_processors.auth', 68 | 'django.contrib.messages.context_processors.messages', 69 | ], 70 | }, 71 | }, 72 | ] 73 | 74 | WSGI_APPLICATION = 'core.wsgi.application' 75 | 76 | 77 | # Database 78 | # https://docs.djangoproject.com/en/4.1/ref/settings/#databases 79 | 80 | DATABASES = { 81 | 'default': { 82 | 'ENGINE': 'django.db.backends.postgresql_psycopg2', 83 | 'NAME': env("DB_NAME"), 84 | 'USER': env("DB_USER"), 85 | 'PASSWORD': env("DB_PASSWORD"), 86 | 'HOST': env("DB_HOST"), 87 | 'POST': env("DB_PORT"), 88 | } if env("DB_TYPE") == 'postgres' else { 89 | 'ENGINE': 'django.db.backends.sqlite3', 90 | 'NAME': BASE_DIR / 'db.sqlite3', 91 | } 92 | } 93 | 94 | 95 | # Password validation 96 | # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators 97 | 98 | AUTH_PASSWORD_VALIDATORS = [ 99 | { 100 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 101 | }, 102 | { 103 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 104 | }, 105 | { 106 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 107 | }, 108 | { 109 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 110 | }, 111 | ] 112 | 113 | 114 | # Internationalization 115 | # https://docs.djangoproject.com/en/4.1/topics/i18n/ 116 | 117 | LANGUAGE_CODE = 'uz' 118 | 119 | TIME_ZONE = 'Asia/Tashkent' 120 | 121 | USE_I18N = True 122 | 123 | USE_TZ = True 124 | 125 | 126 | # Static files (CSS, JavaScript, Images) 127 | # https://docs.djangoproject.com/en/4.1/howto/static-files/ 128 | 129 | STATIC_URL = 'static/' 130 | 131 | STATIC_ROOT = BASE_DIR / 'static' 132 | 133 | MEDIA_URL = 'robot/media/' 134 | 135 | MEDIA_ROOT = BASE_DIR / 'robot/media/' 136 | 137 | # Default primary key field type 138 | # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field 139 | 140 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 141 | 142 | BOT_TOKEN = env.str('BOT_TOKEN') 143 | 144 | ADMINS_LIST = env.list('ADMINS_LIST') 145 | --------------------------------------------------------------------------------