You've already forked Travel-Agent
chore: Global project refactoring
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
# Files
|
# Files
|
||||||
README.md
|
README.md
|
||||||
task.md
|
|
||||||
check.sh
|
check.sh
|
||||||
.flake8
|
.flake8
|
||||||
template.env
|
|
||||||
|
|
||||||
# Folders
|
# Folders
|
||||||
img/
|
img/
|
||||||
|
|||||||
@@ -2,11 +2,8 @@ FROM python:3.12-slim
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy requirements file
|
|
||||||
COPY requirements/prod.txt .
|
COPY requirements/prod.txt .
|
||||||
|
|
||||||
# Install Python dependencies
|
|
||||||
RUN pip install --no-cache-dir -r prod.txt
|
RUN pip install --no-cache-dir -r prod.txt
|
||||||
|
|
||||||
# Copy the rest of the application files
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
+3
-4
@@ -38,10 +38,9 @@ async def main() -> None:
|
|||||||
profile_command.router,
|
profile_command.router,
|
||||||
create_travel_command.router,
|
create_travel_command.router,
|
||||||
travels_command.router,
|
travels_command.router,
|
||||||
|
menu.router,
|
||||||
menu.router, # type: ignore
|
profile.router,
|
||||||
profile.router, # type: ignore
|
travels.router,
|
||||||
travels.router, # type: ignore
|
|
||||||
)
|
)
|
||||||
|
|
||||||
await bot.delete_webhook(drop_pending_updates=True)
|
await bot.delete_webhook(drop_pending_updates=True)
|
||||||
|
|||||||
+17
-17
@@ -1,11 +1,10 @@
|
|||||||
# type: ignore
|
__all__ = ("router",)
|
||||||
__all__ = ()
|
|
||||||
|
|
||||||
from aiogram import F, Router
|
from aiogram import F, Router
|
||||||
from aiogram.exceptions import TelegramBadRequest
|
from aiogram.exceptions import TelegramBadRequest
|
||||||
from aiogram.filters import StateFilter
|
from aiogram.filters import StateFilter
|
||||||
from aiogram.fsm.context import FSMContext
|
from aiogram.fsm.context import FSMContext
|
||||||
from aiogram.types import CallbackQuery
|
from aiogram.types import CallbackQuery, Message
|
||||||
|
|
||||||
from app import messages
|
from app import messages
|
||||||
from app.config import Config
|
from app.config import Config
|
||||||
@@ -20,24 +19,18 @@ router = Router(name="menu_callback")
|
|||||||
|
|
||||||
|
|
||||||
@router.callback_query(
|
@router.callback_query(
|
||||||
F.data == "menu_profile", RegisteredCallback(), StateFilter(None),
|
F.data == "menu_profile",
|
||||||
|
RegisteredCallback(),
|
||||||
|
StateFilter(None),
|
||||||
)
|
)
|
||||||
async def profile_callback(callback: CallbackQuery) -> None:
|
async def profile_callback(callback: CallbackQuery) -> None:
|
||||||
if callback.data is None or callback.message is None:
|
if callback.data is None or not isinstance(callback.message, Message):
|
||||||
return
|
return
|
||||||
|
|
||||||
user = User().get_user_by_telegram_id(callback.from_user.id)
|
user = User().get_user_by_telegram_id(callback.from_user.id)
|
||||||
|
|
||||||
await callback.message.answer(
|
await callback.message.answer(
|
||||||
messages.PROFILE.format(
|
user.get_profile_text(),
|
||||||
username=user.username,
|
|
||||||
age=user.age,
|
|
||||||
bio=user.bio if user.bio else messages.NOT_SET,
|
|
||||||
sex=user.sex.capitalize(),
|
|
||||||
country=user.country,
|
|
||||||
city=user.city,
|
|
||||||
date_joined=user.get_human_readable_datejoined(),
|
|
||||||
),
|
|
||||||
reply_markup=get(),
|
reply_markup=get(),
|
||||||
)
|
)
|
||||||
await callback.answer()
|
await callback.answer()
|
||||||
@@ -49,13 +42,15 @@ async def profile_callback(callback: CallbackQuery) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@router.callback_query(
|
@router.callback_query(
|
||||||
F.data == "menu_create_travel", RegisteredCallback(), StateFilter(None),
|
F.data == "menu_create_travel",
|
||||||
|
RegisteredCallback(),
|
||||||
|
StateFilter(None),
|
||||||
)
|
)
|
||||||
async def create_travel_callback(
|
async def create_travel_callback(
|
||||||
callback: CallbackQuery,
|
callback: CallbackQuery,
|
||||||
state: FSMContext,
|
state: FSMContext,
|
||||||
) -> None:
|
) -> None:
|
||||||
if callback.data is None or callback.message is None:
|
if callback.data is None or not isinstance(callback.message, Message):
|
||||||
return
|
return
|
||||||
|
|
||||||
await callback.message.answer(
|
await callback.message.answer(
|
||||||
@@ -75,11 +70,16 @@ async def create_travel_callback(
|
|||||||
|
|
||||||
|
|
||||||
@router.callback_query(
|
@router.callback_query(
|
||||||
F.data == "menu_travels", RegisteredCallback(), StateFilter(None),
|
F.data == "menu_travels",
|
||||||
|
RegisteredCallback(),
|
||||||
|
StateFilter(None),
|
||||||
)
|
)
|
||||||
async def travels_callback(
|
async def travels_callback(
|
||||||
callback: CallbackQuery,
|
callback: CallbackQuery,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
if not isinstance(callback.message, Message):
|
||||||
|
return
|
||||||
|
|
||||||
page = 0
|
page = 0
|
||||||
|
|
||||||
user = User().get_user_by_telegram_id(callback.from_user.id)
|
user = User().get_user_by_telegram_id(callback.from_user.id)
|
||||||
|
|||||||
+14
-12
@@ -1,5 +1,4 @@
|
|||||||
# type: ignore
|
__all__ = ("router",)
|
||||||
__all__ = ()
|
|
||||||
|
|
||||||
from aiogram import F, Router
|
from aiogram import F, Router
|
||||||
from aiogram.exceptions import TelegramBadRequest
|
from aiogram.exceptions import TelegramBadRequest
|
||||||
@@ -31,7 +30,11 @@ async def profile_change_callback(
|
|||||||
callback: CallbackQuery,
|
callback: CallbackQuery,
|
||||||
state: FSMContext,
|
state: FSMContext,
|
||||||
) -> None:
|
) -> None:
|
||||||
if callback.data is None or callback.message is None:
|
if (
|
||||||
|
callback.data is None
|
||||||
|
or callback.message is None
|
||||||
|
or not isinstance(callback.message, Message)
|
||||||
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
column = callback.data.replace("profile_change_", "")
|
column = callback.data.replace("profile_change_", "")
|
||||||
@@ -70,6 +73,13 @@ async def profile_change_callback(
|
|||||||
|
|
||||||
@router.message(UserAlteringState.value, F.text, Registered())
|
@router.message(UserAlteringState.value, F.text, Registered())
|
||||||
async def profile_change_entered(message: Message, state: FSMContext) -> None:
|
async def profile_change_entered(message: Message, state: FSMContext) -> None:
|
||||||
|
if (
|
||||||
|
message.text is None
|
||||||
|
or message.from_user is None
|
||||||
|
or message.bot is None
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
column = (await state.get_data()).get("column")
|
column = (await state.get_data()).get("column")
|
||||||
value = message.text.strip()
|
value = message.text.strip()
|
||||||
|
|
||||||
@@ -205,15 +215,7 @@ async def profile_change_entered(message: Message, state: FSMContext) -> None:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await message.bot.edit_message_text(
|
await message.bot.edit_message_text(
|
||||||
messages.PROFILE.format(
|
user.get_profile_text(),
|
||||||
username=user.username,
|
|
||||||
age=user.age,
|
|
||||||
bio=user.bio if user.bio else messages.NOT_SET,
|
|
||||||
sex=user.sex.capitalize(),
|
|
||||||
country=user.country,
|
|
||||||
city=user.city,
|
|
||||||
date_joined=user.get_human_readable_datejoined(),
|
|
||||||
),
|
|
||||||
message.chat.id,
|
message.chat.id,
|
||||||
state_data["profile_message_id"],
|
state_data["profile_message_id"],
|
||||||
reply_markup=get(),
|
reply_markup=get(),
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
# type: ignore
|
__all__ = ("router",)
|
||||||
__all__ = ()
|
|
||||||
|
|
||||||
from aiogram import F, Router
|
from aiogram import F, Router
|
||||||
from aiogram.exceptions import TelegramBadRequest
|
from aiogram.exceptions import TelegramBadRequest
|
||||||
from aiogram.filters import StateFilter
|
from aiogram.filters import StateFilter
|
||||||
from aiogram.types import CallbackQuery
|
from aiogram.types import CallbackQuery, Message
|
||||||
|
|
||||||
from app import messages
|
from app import messages
|
||||||
from app.config import Config
|
from app.config import Config
|
||||||
@@ -17,9 +16,14 @@ router = Router(name="menu_callback")
|
|||||||
|
|
||||||
|
|
||||||
@router.callback_query(
|
@router.callback_query(
|
||||||
F.data.startswith("travels_page"), RegisteredCallback(), StateFilter(None),
|
F.data.startswith("travels_page"),
|
||||||
|
RegisteredCallback(),
|
||||||
|
StateFilter(None),
|
||||||
)
|
)
|
||||||
async def travels_callback(callback: CallbackQuery) -> None:
|
async def travels_callback(callback: CallbackQuery) -> None:
|
||||||
|
if callback.data is None or not isinstance(callback.message, Message):
|
||||||
|
return
|
||||||
|
|
||||||
page = int(callback.data.replace("travels_page_", ""))
|
page = int(callback.data.replace("travels_page_", ""))
|
||||||
|
|
||||||
user = User().get_user_by_telegram_id(callback.from_user.id)
|
user = User().get_user_by_telegram_id(callback.from_user.id)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__all__ = ()
|
__all__ = ("router",)
|
||||||
|
|
||||||
from aiogram import F, Router
|
from aiogram import F, Router
|
||||||
from aiogram.filters import Command, StateFilter
|
from aiogram.filters import Command, StateFilter
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__all__ = ()
|
__all__ = ("router",)
|
||||||
|
|
||||||
from aiogram import Router
|
from aiogram import Router
|
||||||
from aiogram.filters import Command, StateFilter
|
from aiogram.filters import Command, StateFilter
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__all__ = ()
|
__all__ = ("router",)
|
||||||
|
|
||||||
from aiogram import Router
|
from aiogram import Router
|
||||||
from aiogram.filters import Command, StateFilter
|
from aiogram.filters import Command, StateFilter
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
__all__ = ()
|
__all__ = ("router",)
|
||||||
|
|
||||||
from aiogram import Router
|
from aiogram import Router
|
||||||
from aiogram.filters import Command, StateFilter
|
from aiogram.filters import Command, StateFilter
|
||||||
from aiogram.types import Message
|
from aiogram.types import Message
|
||||||
|
|
||||||
from app import messages
|
|
||||||
from app.filters.user import Registered
|
from app.filters.user import Registered
|
||||||
from app.keyboards.profile import get
|
from app.keyboards.profile import get
|
||||||
from app.models.user import User
|
from app.models.user import User
|
||||||
@@ -21,14 +20,6 @@ async def command_profile_handler(message: Message) -> None:
|
|||||||
user = User().get_user_by_telegram_id(message.from_user.id)
|
user = User().get_user_by_telegram_id(message.from_user.id)
|
||||||
|
|
||||||
await message.answer(
|
await message.answer(
|
||||||
messages.PROFILE.format(
|
user.get_profile_text(),
|
||||||
username=user.username,
|
|
||||||
age=user.age,
|
|
||||||
bio=user.bio if user.bio else messages.NOT_SET,
|
|
||||||
sex=user.sex.capitalize(),
|
|
||||||
country=user.country,
|
|
||||||
city=user.city,
|
|
||||||
date_joined=user.get_human_readable_datejoined(),
|
|
||||||
),
|
|
||||||
reply_markup=get(),
|
reply_markup=get(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__all__ = ()
|
__all__ = ("router",)
|
||||||
|
|
||||||
from aiogram import F, Router
|
from aiogram import F, Router
|
||||||
from aiogram.filters import CommandStart, StateFilter
|
from aiogram.filters import CommandStart, StateFilter
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__all__ = ()
|
__all__ = ("router",)
|
||||||
|
|
||||||
from aiogram import Router
|
from aiogram import Router
|
||||||
from aiogram.filters import Command, StateFilter
|
from aiogram.filters import Command, StateFilter
|
||||||
|
|||||||
+36
-32
@@ -1,4 +1,4 @@
|
|||||||
__all__ = ("sex_keyboard",)
|
__all__ = ("sex_keyboard", "travels_keyboard")
|
||||||
|
|
||||||
from aiogram.types import InlineKeyboardButton
|
from aiogram.types import InlineKeyboardButton
|
||||||
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder
|
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder
|
||||||
@@ -10,9 +10,9 @@ def sex_keyboard(choices: str | list):
|
|||||||
builder = ReplyKeyboardBuilder()
|
builder = ReplyKeyboardBuilder()
|
||||||
|
|
||||||
if isinstance(choices, str):
|
if isinstance(choices, str):
|
||||||
text = [choices]
|
choices = [choices]
|
||||||
|
|
||||||
[builder.button(text=txt) for txt in text]
|
[builder.button(text=choice) for choice in choices]
|
||||||
return builder.as_markup(resize_keyboard=True)
|
return builder.as_markup(resize_keyboard=True)
|
||||||
|
|
||||||
|
|
||||||
@@ -36,41 +36,45 @@ def travels_keyboard(travels: list, page: int, pages: int):
|
|||||||
|
|
||||||
builder.row(*rows, width=2)
|
builder.row(*rows, width=2)
|
||||||
|
|
||||||
if pages > 1:
|
navigation_row = []
|
||||||
navigation_row = []
|
|
||||||
|
|
||||||
if page > 0:
|
|
||||||
navigation_row.append(
|
|
||||||
InlineKeyboardButton(
|
|
||||||
text="⬅️", callback_data=f"travels_page_{page - 1}",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
navigation_row.append(
|
|
||||||
InlineKeyboardButton(
|
|
||||||
text=" ", callback_data="pass",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
if page > 0:
|
||||||
navigation_row.append(
|
navigation_row.append(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
text=f"{page + 1}/{pages}", callback_data="pass",
|
text="⬅️",
|
||||||
|
callback_data=f"travels_page_{page - 1}",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
navigation_row.append(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text=" ",
|
||||||
|
callback_data="pass",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if page < pages - 1:
|
navigation_row.append(
|
||||||
navigation_row.append(
|
InlineKeyboardButton(
|
||||||
InlineKeyboardButton(
|
text=f"{page + 1}/{pages}",
|
||||||
text="➡️", callback_data=f"travels_page_{page + 1}",
|
callback_data="pass",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
navigation_row.append(
|
|
||||||
InlineKeyboardButton(
|
|
||||||
text=" ", callback_data="pass",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
builder.row(*navigation_row)
|
if page < pages - 1:
|
||||||
|
navigation_row.append(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text="➡️",
|
||||||
|
callback_data=f"travels_page_{page + 1}",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
navigation_row.append(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text=" ",
|
||||||
|
callback_data="pass",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
builder.row(*navigation_row)
|
||||||
|
|
||||||
return builder.as_markup()
|
return builder.as_markup()
|
||||||
|
|||||||
+7
-5
@@ -4,14 +4,16 @@ MENU = "<b>Menu:</b>"
|
|||||||
|
|
||||||
TRAVELS = "📃 <b>Travels:</b>"
|
TRAVELS = "📃 <b>Travels:</b>"
|
||||||
NO_TRAVELS = "No travels yet. You can create one with /create_travel command."
|
NO_TRAVELS = "No travels yet. You can create one with /create_travel command."
|
||||||
CREATE_TRAVEL = "🧳 Let's create new travel!\n<i>Enter /cancel to cancel creating.</i>"
|
CREATE_TRAVEL = (
|
||||||
INPUT_TRAVEL_TITLE = "Enter travel title:\n<i>Maximum length: 30 characters</i>"
|
"🧳 Let's create new travel!\n<i>Enter /cancel to cancel creating.</i>"
|
||||||
|
)
|
||||||
|
INPUT_TRAVEL_TITLE = (
|
||||||
|
"Enter travel title:\n<i>Maximum length: 30 characters</i>"
|
||||||
|
)
|
||||||
INPUT_TRAVEL_CALLBACK = (
|
INPUT_TRAVEL_CALLBACK = (
|
||||||
"All right, travel <b>{key}</b> is set to: <b>{value}</b>"
|
"All right, travel <b>{key}</b> is set to: <b>{value}</b>"
|
||||||
)
|
)
|
||||||
INPUT_TRAVEL_DESCRIPTION = (
|
INPUT_TRAVEL_DESCRIPTION = "Enter travel description (enter /skip if you want to skip this step):\n<i>Maximum length: 100 characters</i>"
|
||||||
"Enter travel description (enter /skip if you want to skip this step):\n<i>Maximum length: 100 characters</i>"
|
|
||||||
)
|
|
||||||
INPUT_TRAVEL_DESCRIPTION_SKIPPED = "Sure. You can always fill it later."
|
INPUT_TRAVEL_DESCRIPTION_SKIPPED = "Sure. You can always fill it later."
|
||||||
TRAVEL_CREATED = "Travel <b>{title}</b> successfully created! You can now view and edit it in the travels list (/travels command)."
|
TRAVEL_CREATED = "Travel <b>{title}</b> successfully created! You can now view and edit it in the travels list (/travels command)."
|
||||||
ACTION_CANCELED = "❌ Action canceled"
|
ACTION_CANCELED = "❌ Action canceled"
|
||||||
|
|||||||
+14
-3
@@ -5,7 +5,7 @@ import re
|
|||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy.orm import relationship, validates
|
from sqlalchemy.orm import relationship, validates
|
||||||
|
|
||||||
from app import session
|
from app import messages, session
|
||||||
from app.models import Base
|
from app.models import Base
|
||||||
from app.utils import geo
|
from app.utils import geo
|
||||||
from app.utils.db import utcnow
|
from app.utils.db import utcnow
|
||||||
@@ -97,12 +97,23 @@ class User(Base):
|
|||||||
|
|
||||||
return normalized_value
|
return normalized_value
|
||||||
|
|
||||||
def get_user_travels(self):
|
def get_user_travels(self) -> list:
|
||||||
return self.owned_travels + self.travels
|
return self.owned_travels + self.travels
|
||||||
|
|
||||||
def get_human_readable_datejoined(self):
|
def get_human_readable_datejoined(self) -> str:
|
||||||
return self.date_joined.strftime("%Y-%m-%d %H:%M:%S")
|
return self.date_joined.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
def get_profile_text(self) -> str:
|
||||||
|
return messages.PROFILE.format(
|
||||||
|
username=self.username,
|
||||||
|
age=self.age,
|
||||||
|
bio=self.bio if self.bio else messages.NOT_SET,
|
||||||
|
sex=self.sex.capitalize(),
|
||||||
|
country=self.country,
|
||||||
|
city=self.city,
|
||||||
|
date_joined=self.get_human_readable_datejoined(),
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_user_queryset_by_telegram_id(cls, telegram_id):
|
def get_user_queryset_by_telegram_id(cls, telegram_id):
|
||||||
return session.query(cls).filter(cls.telegram_id == telegram_id)
|
return session.query(cls).filter(cls.telegram_id == telegram_id)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ NC='\033[0m'
|
|||||||
sort-requirements requirements/dev.txt
|
sort-requirements requirements/dev.txt
|
||||||
sort-requirements requirements/prod.txt
|
sort-requirements requirements/prod.txt
|
||||||
sort-requirements requirements/test.txt
|
sort-requirements requirements/test.txt
|
||||||
sort-requirements requirements/lints.txt
|
sort-requirements requirements/lint.txt
|
||||||
printf "${GREEN}Requirements sorted${NC}\n"
|
printf "${GREEN}Requirements sorted${NC}\n"
|
||||||
|
|
||||||
black .
|
black .
|
||||||
|
|||||||
+17
-14
@@ -3,7 +3,7 @@ version: "3"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:latest
|
image: postgres:16.2-alpine
|
||||||
container_name: postgres
|
container_name: postgres
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: pg_isready -U postgres -h localhost
|
test: pg_isready -U postgres -h localhost
|
||||||
@@ -11,21 +11,21 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: postgres
|
POSTGRES_DB: ${POSTGRES_DB:-postgres}
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||||||
POSTGRES_PASSWORD: wTAb5KoZ4dBtscg
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "${POSTGRES_PORT:-5432}:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:latest
|
image: redis:7.2-alpine
|
||||||
container_name: redis
|
container_name: redis
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
|
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
|
||||||
ports:
|
ports:
|
||||||
- "6379:6379"
|
- "${REDIS_PORT:-6379}:6379"
|
||||||
volumes:
|
volumes:
|
||||||
- redis_data:/data
|
- redis_data:/data
|
||||||
|
|
||||||
@@ -38,20 +38,23 @@ services:
|
|||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
BOT_TOKEN: 6943803094:AAEHG-vOP2pNEuxb9rDIhisiQuGLuBIjx1Q
|
BOT_TOKEN: ${BOT_TOKEN:-6943803094:AAEHG-vOP2pNEuxb9rDIhisiQuGLuBIjx1Q}
|
||||||
REDIS_URL: redis://redis:6379/
|
REDIS_URL: redis://redis:${REDIS_PORT:-6379}/
|
||||||
SQLALCHEMY_DATABASE_URI: postgresql://postgres:wTAb5KoZ4dBtscg@postgres:5432/postgres
|
SQLALCHEMY_DATABASE_URI: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres}
|
||||||
entrypoint: ["bash", "-c"]
|
entrypoint: ["bash", "-c"]
|
||||||
command: ["alembic -c app/alembic.ini upgrade head && python -m app"]
|
command: ["alembic -c app/alembic.ini upgrade head && python -m app"]
|
||||||
|
|
||||||
pgadmin:
|
pgadmin:
|
||||||
image: dpage/pgadmin4
|
image: dpage/pgadmin4:8.4
|
||||||
container_name: pgadmin
|
container_name: pgadmin
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
PGADMIN_DEFAULT_EMAIL: admin@mail.com
|
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL:-admin@mail.com}
|
||||||
PGADMIN_DEFAULT_PASSWORD: admin
|
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD:-admin}
|
||||||
ports:
|
ports:
|
||||||
- "5050:80"
|
- "${PGADMIN_PORT:-5050}:80"
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- pgadmin_data:/var/lib/pgadmin
|
- pgadmin_data:/var/lib/pgadmin
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ sort-requirements
|
|||||||
|
|
||||||
-r prod.txt
|
-r prod.txt
|
||||||
-r test.txt
|
-r test.txt
|
||||||
-r lints.txt
|
-r lint.txt
|
||||||
|
|||||||
+18
-2
@@ -1,2 +1,18 @@
|
|||||||
BOT_TOKEN = <your_bot_token>
|
# For app
|
||||||
SQLALCHEMY_DATABASE_URI = <database_uri>
|
|
||||||
|
BOT_TOKEN = <your_bot_token> # default: 6943803094:AAEHG-vOP2pNEuxb9rDIhisiQuGLuBIjx1Q
|
||||||
|
SQLALCHEMY_DATABASE_URI = <database_uri> # no need to specify if docker is used
|
||||||
|
REDIS_URL = <redis_url> # no need to specify if docker is used
|
||||||
|
|
||||||
|
# For docker(remove if you want to keep defaults)
|
||||||
|
|
||||||
|
POSTGRES_PORT = <port_to_be_forwared> # default: 5432
|
||||||
|
POSTGRES_DB = <db_name> # default: postgres
|
||||||
|
POSTGRES_USER = <postgres_user> # default: postgres
|
||||||
|
POSTGRES_PASSWORD = <password> # default: postgres
|
||||||
|
|
||||||
|
REDIS_PORT = <port_to_be_forwared> # default: 6379
|
||||||
|
|
||||||
|
PGADMIN_PORT = <port_to_be_forwared> # default: 5050
|
||||||
|
PGADMIN_EMAIL = <email> # default: admin@mail.com
|
||||||
|
PGADMIN_PASSWORD <password> # default: admin
|
||||||
|
|||||||
Reference in New Issue
Block a user