Compare commits

..

3 Commits

Author SHA1 Message Date
b5fcdd2d38 Merge pull request 'dev_d' (#1) from dev_d into master
Some checks failed
continuous-integration/drone Build is failing
Reviewed-on: #1
2025-09-25 17:22:01 +03:00
3ff9fda739 fix drone file 2025-09-25 17:18:27 +03:00
54e17257d0 drone file configure
Some checks failed
continuous-integration/drone Build is failing
2025-09-25 16:49:23 +03:00
13 changed files with 144 additions and 164 deletions

View File

@@ -1,4 +0,0 @@
from .states import OrderForm, SearchForm, OrderingForm
__all__ = ["SearchForm", "OrderForm", "OrderingForm"]

View File

@@ -1,25 +0,0 @@
from aiogram.fsm.state import State, StatesGroup
class SearchForm(StatesGroup):
search_option = State()
data_to_search = State()
sent_messages = State()
search_result = State()
class OrderForm(StatesGroup):
id = State()
worker_id = State()
status_id = State()
counterparty = State()
customer = State()
commencement_work = State()
end_work = State()
description = State()
class OrderingForm(StatesGroup):
tools_list = State()

View File

@@ -1,8 +1,14 @@
import os import os
import asyncpg
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine, session from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine, session
import dotenv
# connection = psycopg2.connect(*(os.getenv(key) for key in ["DATABASE", "DB_HOST", "DB_USER", "DB_PASSWORD"]))
# connection.autocommit = True
dotenv.load_dotenv(".env")
DATABASE_URL = (f"postgresql+asyncpg://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@" DATABASE_URL = (f"postgresql+asyncpg://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@"
f"{os.getenv('DB_HOST')}/{os.getenv('DATABASE')}") f"{os.getenv('DB_HOST')}/{os.getenv('DATABASE')}")
print(DATABASE_URL)
engine = create_async_engine(DATABASE_URL, echo=True) engine = create_async_engine(DATABASE_URL, echo=True)
async_session_ = async_sessionmaker(bind=engine, expire_on_commit=False) async_session_ = async_sessionmaker(bind=engine, expire_on_commit=False)

View File

@@ -13,11 +13,10 @@ class Base(DeclarativeBase):
class Worker(Base): class Worker(Base):
""" """
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
telegram_id BIGINT UNIQUE NOT NULL, telegram_id INTEGER UNIQUE NOT NULL,
name VARCHAR NOT NULL, name VARCHAR NOT NULL,
email VARCHAR(50), email VARCHAR(50),
phone_number VARCHAR(20), phone_number VARCHAR(20) NOT NULL,
job_title job_title default 'Сборщик',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP updated_at TIMESTAMP
""" """
@@ -28,7 +27,7 @@ class Worker(Base):
name = Column(String, nullable=False) name = Column(String, nullable=False)
email = Column(String, nullable=True) email = Column(String, nullable=True)
phone_number = Column(String, default=None) phone_number = Column(String, default=None)
job_title = Column(job_title, default='Сборщик') job_title = Column(job_title, default='Сборщик'),
created_at = Column(Date, server_default=func.now()) created_at = Column(Date, server_default=func.now())
updated_at = Column(Date, onupdate=func.now()) updated_at = Column(Date, onupdate=func.now())

View File

@@ -1,18 +1,19 @@
import os import logging
from typing import Any
from aiogram.types import Message, CallbackQuery from aiogram.types import Message, CallbackQuery
from aiogram.filters import BaseFilter from aiogram.filters import BaseFilter
from keyboards.menu_commands import commands from keyboards.menu_commands import commands
import os
loggger = logging.getLogger(__name__)
class IsAdmin(BaseFilter): class IsAdmin(BaseFilter):
def __init__(self): def __init__(self):
self.admins_ids = list(map(int, os.getenv("BOT_ADMINS").split(","))) self.admins_ids = os.getenv("BOT_ADMINS").split(",")
async def __call__(self, message: Message | CallbackQuery) -> bool: async def __call__(self, message: Message | CallbackQuery) -> bool:
return message.from_user.id in self.admins_ids return str(message.from_user.id) in self.admins_ids
class CommandFilter(BaseFilter): class CommandFilter(BaseFilter):
@@ -22,7 +23,3 @@ class CommandFilter(BaseFilter):
async def __call__(self, message: Message) -> bool: async def __call__(self, message: Message) -> bool:
return message.text.startswith(tuple(self.commands.keys())) return message.text.startswith(tuple(self.commands.keys()))
class IsRegister(BaseFilter):
async def __call__(self, message: Message | CallbackQuery, **data: dict[str, Any]) -> bool:
return data.get("through_registration") is True

View File

@@ -1,4 +1 @@
from .Filters import IsAdmin from .Filters import IsAdmin
from .Filters import IsRegister
__all__ = ["IsRegister", "IsAdmin"]

View File

@@ -1,9 +1,11 @@
import time
import re import re
from loguru import logger
from aiogram import Router, Bot, F from aiogram import Router, Bot, F
from aiogram.types import Message, CallbackQuery from aiogram.types import (Message, ChatMemberUpdated, FSInputFile, CallbackQuery, ReplyKeyboardRemove)
from loguru import logger
from handlers.registration import registration_confirm from handlers.registration import registration_confirm
from filters.Filters import IsAdmin from filters.Filters import IsAdmin, CommandFilter
from database import async_session_
admin_router = Router() admin_router = Router()

View File

@@ -1,39 +1,61 @@
import asyncio
import os import os
import re
from pathlib import Path from pathlib import Path
import re
from aiogram import Router, Bot, F from aiogram import Router, Bot, F
from aiogram.filters import Command from aiogram.filters import CommandStart, Command
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove
from aiogram.exceptions import AiogramError from aiogram.exceptions import AiogramError
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext from aiogram.fsm.context import FSMContext
from sqlalchemy import select
from sqlalchemy import select, insert
from loguru import logger from loguru import logger
from keyboards import create_inline_kb, button_create from filters import IsAdmin
from keyboards import create_inline_kb, commands, button_create
from database import async_session_, Order, Worker from database import async_session_, Order, Worker
from FSM import SearchForm, OrderForm
orders_router = Router() orders_router = Router()
# orders_router.message.filter()
order_operation_base = {"add_order_photo": "Добавить фото", order_operation_base = {"add_order_photo": "Добавить фото",
"get_order_photo": "Получить фото", "get_order_photo": "Получить фото",
"get_order_components": "Получить список комплектующих", "get_order_components": "Получить список комплектующих",
"get_order_documentation": "Получить документацию", "get_order_documentation": "Получить документацию"
"finish_work_on_order": "❌ Закрыть"
} }
order_operation_update = {"add_order_documentation": "Добавить документацию"} order_operation_update = {"add_order_documentation": "Добавить документацию"}
order_main = {"find_orders": "Найти заказ", "create_order": "Создать заказ"} order_main = {"find_orders": "Найти заказ"}
order_main_update = {"create_order": "Создать заказ"} order_main_update = {"create_order": "Создать заказ"}
find_order_params = {"search_by_name": "Поиск по названию", "search_by_description": "Поиск по описанию ", find_order_params = {"search_by_name": "Поиск по названию", "search_by_description": "Поиск по описанию ",
"search_by_id": "Поиск по номеру заказа", "search_by_customer": "Поиск по заказчику"} "search_by_id": "Поиск по номеру заказа", "search_by_customer": "Поиск по заказчику"}
class SearchForm(StatesGroup):
search_option = State()
data_to_search = State()
search_result = State()
class OrderForm(StatesGroup):
id = State()
worker_id = State()
status_id = State()
counterparty = State()
customer = State()
commencement_work = State()
end_work = State()
description = State()
@orders_router.message(Command(commands="orders")) @orders_router.message(Command(commands="orders"))
async def orders_menu(message: Message): async def orders_menu(message: Message):
order_main_upd = order_main_update if await IsAdmin()(message) else {}
await message.answer(text="Доступные действия с заказами:", await message.answer(text="Доступные действия с заказами:",
reply_markup=create_inline_kb(width=1, **order_main)) reply_markup=create_inline_kb(width=1, **order_main, **order_main_upd))
await message.delete()
@orders_router.callback_query(lambda x: x.data.startswith("create_order")) @orders_router.callback_query(lambda x: x.data.startswith("create_order"))
@@ -64,6 +86,10 @@ async def get_order_customer(callback: CallbackQuery, state: FSMContext):
await state.set_state(OrderForm.customer) await state.set_state(OrderForm.customer)
# @orders_router.callback_query(OrderForm.counterparty)
# async def get_order_customer(message: Message, state: FSMContext):
#
@orders_router.message(OrderForm.customer) @orders_router.message(OrderForm.customer)
async def order_description(message: Message, state: FSMContext): async def order_description(message: Message, state: FSMContext):
await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )") await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )")
@@ -110,30 +136,33 @@ async def search_by_item(message: Message, state: FSMContext):
selected_orders = result.scalars().all() selected_orders = result.scalars().all()
if selected_orders: if selected_orders:
await message.answer(text="Список найденных заказов: ") await message.answer(text="Список найденных заказов: ",
sent_messages = [] reply_markup=create_inline_kb(width=1, **dict(
for order in selected_orders: (f"show_order_{order.id}", f"Описание: {order.description or "Отсутствует"}"
sent_messages.append(await message.answer(text=f"Номер заказа: {order.id}\n" f"Заказ: {order.id}\n"
f"Заказчик: {order.customer}\n" f"Заказчик: {order.customer}\n"
f"Статус: {order.status_id}\n" ) for order in
f"Дата отгрузки: {order.end_work}\n" selected_orders)))
f"Дата создания: {order.created_at}\n"
f"Описание: {order.description}",
reply_markup=create_inline_kb(width=1, **{
f"show_order_{order.id}": f"Заказ: №{order.id}"})))
await state.update_data(sent_messages=sent_messages)
await state.set_state(SearchForm.search_result)
await state.update_data(search_result=selected_orders) await state.update_data(search_result=selected_orders)
await state.set_state(SearchForm.search_result)
else: else:
await message.answer(text="Заказов по вашему запросу не найдено") await message.answer(text="Заказов по вашему запросу не найдено")
await state.clear() await state.clear()
@orders_router.callback_query(SearchForm.search_result and (lambda x: "show_order_" in x.data)) @orders_router.callback_query(SearchForm.search_result)
async def show_order(callback: CallbackQuery, state: FSMContext, bot: Bot): async def show_order(callback: CallbackQuery, state: FSMContext):
order_id = int(re.search(r"(\d+)", callback.data).group()) order_id = int(re.search(r"(\d+)", callback.data).group())
orders = await state.get_value("search_result")
order = next(filter(lambda item: order_id == item.id, orders), None) try:
async with async_session_() as local_session:
result = await local_session.execute(select(Order).filter(Order.id == order_id))
order = result.scalars().first()
except Exception as err:
logger.warning(err)
order_operation_upd = order_operation_update if await IsAdmin()(callback) else {}
if order: if order:
await callback.message.answer(text=f"Номер заказа: {order.id}\n" await callback.message.answer(text=f"Номер заказа: {order.id}\n"
@@ -143,22 +172,21 @@ async def show_order(callback: CallbackQuery, state: FSMContext, bot: Bot):
f"Дата отгрузки: {order.end_work}\n" f"Дата отгрузки: {order.end_work}\n"
f"Дата создания: {order.created_at}\n" f"Дата создания: {order.created_at}\n"
f"Описание: {order.description}", f"Описание: {order.description}",
reply_markup=create_inline_kb(width=1, **dict( reply_markup=create_inline_kb(width=2, **dict(
(f"{clbk}_{order.id}", text) for clbk, text in order_operation_base.items())) (f"{clbk}_{order.id}", text) for clbk, text in order_operation_base.items()))
) )
for message in await state.get_value("sent_messages"): await callback.message.delete()
await bot.delete_message(chat_id=callback.message.chat.id, message_id=message.message_id)
await state.clear() await state.clear()
@orders_router.callback_query(lambda x: x.data.startswith("get_order_photo")) @orders_router.callback_query(lambda x: x.data.startswith("get_order_photo"))
async def send_order_photos(callback: CallbackQuery, bot: Bot): async def send_order_photos(callback: CallbackQuery, bot: Bot):
order_id = callback.data.split("_")[-1] order_id = callback.data.split("_")[-1]
media_item: Path
media_group = [] media_group = []
order_photos_path = Path(f"/app/photos/{order_id}/") os.makedirs(Path(f"./photos/{order_id}/"), exist_ok=True)
os.makedirs(order_photos_path, exist_ok=True) media_path = Path(f"./photos/{order_id}/").iterdir()
media_path = order_photos_path.iterdir()
if not (media_item := next(media_path, None)): if not (media_item := next(media_path, None)):
text = f"Фото по заказу \"{order_id}\" отсутствуют " text = f"Фото по заказу \"{order_id}\" отсутствуют "
else: else:
@@ -166,7 +194,7 @@ async def send_order_photos(callback: CallbackQuery, bot: Bot):
f"") f"")
await bot.send_message(chat_id=callback.from_user.id, text=text) await bot.send_message(chat_id=callback.from_user.id, text=text)
while media_item or media_group: while media_item or media_group:
if len(media_group) == 10 or not media_item: if len(media_group) == 10 or (media_group and not media_item):
await bot.send_media_group(chat_id=callback.from_user.id, media=media_group) await bot.send_media_group(chat_id=callback.from_user.id, media=media_group)
media_group.clear() media_group.clear()
if media_item: if media_item:
@@ -177,10 +205,8 @@ async def send_order_photos(callback: CallbackQuery, bot: Bot):
logger.error(f"Ошибка при обработке {media_path}: {err}") logger.error(f"Ошибка при обработке {media_path}: {err}")
media_item = next(media_path, None) media_item = next(media_path, None)
try: await asyncio.sleep(600)
pass await callback.message.delete()
except:
pass
@orders_router.callback_query(lambda x: x.data.startswith("add_order_photo")) @orders_router.callback_query(lambda x: x.data.startswith("add_order_photo"))
@@ -195,7 +221,7 @@ async def reply_for_photo(callback: CallbackQuery, bot: Bot):
F.reply_to_message) F.reply_to_message)
async def add_order_photo(message: Message, bot: Bot): async def add_order_photo(message: Message, bot: Bot):
order_id = re.search(r"(\d+)", message.reply_to_message.text).group() order_id = re.search(r"(\d+)", message.reply_to_message.text).group()
order_photos_path = Path(f"/app/photos/{order_id}/") order_photos_path = f"/app/photos/{order_id}/"
os.makedirs(order_photos_path, exist_ok=True) os.makedirs(order_photos_path, exist_ok=True)
item = message.video or message.photo[-1] item = message.video or message.photo[-1]
@@ -215,8 +241,3 @@ async def add_order_photo(message: Message, bot: Bot):
await bot.delete_message(chat_id=message.chat.id, message_id=message.reply_to_message.message_id) await bot.delete_message(chat_id=message.chat.id, message_id=message.reply_to_message.message_id)
except: except:
pass pass
@orders_router.callback_query(F.data.startswith("finish_work_on_order"))
async def finish_work_on_order(callback: CallbackQuery):
await callback.message.delete()

View File

@@ -1,18 +1,17 @@
import os import os
from asyncio import Event, wait_for, TimeoutError from asyncio import Event, wait_for, TimeoutError
from aiogram import Router, Bot from aiogram import Router, Bot
from aiogram.filters import CommandStart from aiogram.filters import CommandStart
from aiogram.types import Message, User from aiogram.types import Message, User
from sqlalchemy import insert, select from sqlalchemy import insert, select
from loguru import logger
from keyboards import create_inline_kb from keyboards import create_inline_kb
from database import async_session_, Worker from database import async_session_, Worker
from filters import IsRegister
registration_router = Router() registration_router = Router()
registration_router.message.filter(IsRegister() or CommandStart())
registration_confirm: dict[int, Event] = {} registration_confirm: dict[int, Event] = {}
user_info_template = ("Новый пользователь ждет регистрации:\n" user_info_template = ("Новый пользователь ждет регистрации:\n"
"Имя: {}\n" "Имя: {}\n"
@@ -20,29 +19,28 @@ user_info_template = ("Новый пользователь ждет регист
"Юзернейм: @{}\n" "Юзернейм: @{}\n"
"ID: @msg_{}\n") "ID: @msg_{}\n")
admins_ids = list(map(int, os.getenv("BOT_ADMINS").split(",")))
@registration_router.message(CommandStart()) @registration_router.message(CommandStart())
async def start_command(message: Message, bot: Bot): async def registration_command(message: Message, bot: Bot):
async with async_session_() as session: async with async_session_() as session:
async with session.begin():
result = await session.execute(select(Worker).where(Worker.telegram_id == message.from_user.id)) result = await session.execute(select(Worker).where(Worker.telegram_id == message.from_user.id))
user = result.scalars().first() user = result.scalars().first()
if not user: if not user:
user = message.from_user user = message.from_user
dict_for_inline = {f'reg_@{user.id}': 'Allow', f'del_@{user.id}': 'Reject'} dict_for_inline = {f'reg_@{user.id}': 'Allow', f'del_@{user.id}': 'Reject'}
user_info = user_info_template.format(user.first_name, user.last_name if user.last_name else 'Не указана', user_info = user_info_template.format(user.first_name, user.last_name if user.last_name else 'Не указана',
user.username if user.username else 'Не указан', user.id) user.username if user.username else 'Не указан', user.id)
for admin in list(map(int, os.getenv("BOT_ADMINS").split(","))): for admin in admins_ids:
try: try:
await bot.send_message(chat_id=admin, text=user_info) await bot.send_message(chat_id=admin, text=user_info)
await bot.send_message(chat_id=admin, text='Зарегистрировать пользователя', await bot.send_message(chat_id=admin, text='Зарегистрировать пользователя',
reply_markup=create_inline_kb(width=2, **dict_for_inline)) reply_markup=create_inline_kb(width=2, **dict_for_inline))
await message.answer("Запрос на регистрацию отправлен администратору, ожидайте подтверждения.") except Exception as err:
pass
except Exception:
logger.error(f"{start_command.__name__} failed")
reg_confirm = Event() reg_confirm = Event()
registration_confirm[user.id] = reg_confirm registration_confirm[user.id] = reg_confirm
try: try:
@@ -51,7 +49,7 @@ async def start_command(message: Message, bot: Bot):
async with local_session.begin(): async with local_session.begin():
local_session.add(Worker(telegram_id=user.id, name=user.first_name)) local_session.add(Worker(telegram_id=user.id, name=user.first_name))
await message.answer("Регистрация подтверждена, для просмотра доступных действий нажмите кнопку 'MENU'") await message.answer("Регистрация подтверждена")
except TimeoutError: except TimeoutError:
await message.answer("Время ожидания истекло.") await message.answer("Время ожидания истекло.")
@@ -59,8 +57,3 @@ async def start_command(message: Message, bot: Bot):
else: else:
await message.answer("Работа бота возобновлена") await message.answer("Работа бота возобновлена")
@registration_router.message()
async def catch_message(message: Message):
await message.answer("Для работы с ботом, требуется регистрация\nНажмите /start для регистрации")

View File

@@ -1,14 +1,12 @@
import os import os
import asyncio import asyncio
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv(".env")
from aiogram import Dispatcher, Bot from aiogram import Dispatcher, Bot
from handlers import * from handlers import *
from keyboards import set_main_menu from keyboards import set_main_menu
from middlewares import SessionMiddleware from middlewares import AccessCheckMiddleware
load_dotenv(".env")
bot = Bot(token=os.getenv("TOKEN")) bot = Bot(token=os.getenv("TOKEN"))
@@ -18,7 +16,7 @@ async def main() -> None:
dp.startup.register(set_main_menu) dp.startup.register(set_main_menu)
dp.include_router(registration_router) dp.include_router(registration_router)
dp.include_router(admin_router) dp.include_router(admin_router)
dp.update.outer_middleware(SessionMiddleware()) dp.update.outer_middleware(AccessCheckMiddleware())
dp.include_router(orders_router) dp.include_router(orders_router)
dp.include_router(components_router) dp.include_router(components_router)

View File

@@ -1,4 +1,4 @@
from .outer_middlewares import SessionMiddleware from .outer_middlewares import AccessCheckMiddleware
__all__ = ["SessionMiddleware"] __all__ = ["AccessCheckMiddleware"]

View File

@@ -1,29 +1,29 @@
import logging
from typing import Any, Awaitable, Callable, Dict from typing import Any, Awaitable, Callable, Dict
from aiogram import BaseMiddleware, Bot from aiogram import BaseMiddleware, Bot
from aiogram.types import TelegramObject from aiogram.types import TelegramObject
from sqlalchemy import select
from loguru import logger
from database import async_session_, Worker from database import async_session_, Worker
from sqlalchemy import select
class SessionMiddleware(BaseMiddleware):
class AccessCheckMiddleware(BaseMiddleware):
sessions_in_memory_db = set() sessions_in_memory_db = set()
async def __call__( async def __call__(
self, self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject, event: TelegramObject,
data: Dict[str, Any] data: Dict[str, Any]
) -> Any: ) -> Any:
logger.info("Session check")
event_data = event.message or event.callback_query event_data = event.message or event.callback_query
user = event_data.from_user.id user = event_data.from_user.id
if user not in self.sessions_in_memory_db: if user not in self.sessions_in_memory_db:
async with async_session_() as session: async with async_session_() as session:
async with session.begin():
result = await session.execute(select(Worker).where(Worker.telegram_id == event_data.from_user.id)) result = await session.execute(select(Worker).where(Worker.telegram_id == event_data.from_user.id))
user_in_db = result.scalars().first() user = result.scalars().first()
if not user_in_db: if user:
data["through_registration"] = True self.sessions_in_memory_db.add(event_data.from_user.id)
else:
self.sessions_in_memory_db.add(user)
return await handler(event, data) return await handler(event, data)
return None

View File

@@ -1,15 +1,19 @@
kind: pipeline kind: pipeline
type: docker type: docker
name: first_run name: default
clone: clone:
disable: true git:
url: https://gitea.ronis0505.tech/ronis_0505/telegram-bot-for-manipulate-orders.git
user:
from_secret: GITEA_USER
password:
from_secret: GITEA_TOKEN
steps: steps:
- name: clone - name: install-dependencies
image: alpine/git image: python:3.12
commands: commands:
- git clone https://git.ronis-0505.ru/ronis_0505/telegram-bot-for-manipulate-orders.git . - pip install -r pyproject.toml
- name: build - name: build
image: docker:dind image: docker:dind
@@ -20,35 +24,27 @@ steps:
- docker build -t myapp:${DRONE_COMMIT_SHA} . - docker build -t myapp:${DRONE_COMMIT_SHA} .
- name: deploy - name: deploy
image: docker image: appleboy/ssh
volumes:
- name: dockersock
path: /var/run/docker.sock
- name: env
path: /srv/prod/telegram_bot/
environment: environment:
TOKEN: ENV_CONTENT:
from_secret: TOKEN from_secret: DOT_ENV_CONTENT
BOT_ADMINS:
from_secret: BOT_ADMINS
DATABASE:
from_secret: DATABASE
DB_HOST:
from_secret: DB_HOST
DB_USER:
from_secret: DB_USER
DB_PASSWORD:
from_secret: DB_PASSWORD
commands: commands:
- echo "$ENV_CONTENT" > .env
settings:
host: https://gitea.ronis-0505.ru/ronis_0505/telegram-bot-for-manipulate-orders.git
username: ronis_0505
password: 667766
script:
- docker pull myapp:${DRONE_COMMIT_SHA}
- docker stop myapp || true - docker stop myapp || true
- docker rm myapp || true - docker rm myapp || true
- docker run --name=myapp -d --network=prod_net -v /srv/prod/telegram_bot/photos:/app/photos/ -v /srv/prod/telegram_bot/.env:/app/.env:ro myapp:${DRONE_COMMIT_SHA} - docker run -d --name myapp \
--network prod_net \
-v /srv/prod/telegram_bot/photos:/app/photos/ \
myapp:${DRONE_COMMIT_SHA}
volumes: volumes:
- name: dockersock - name: dockersock
host: host:
path: /var/run/docker.sock path: /var/run/docker.sock
- name: env
host:
path: /srv/prod/telegram_bot/