Compare commits
29 Commits
e8e2d3dc58
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 652400e50f | |||
| 95195c2749 | |||
| 9979937113 | |||
| be80c4044b | |||
| 6549c3d70b | |||
| cc520caef5 | |||
| 51eebcc165 | |||
| ffe5e2e938 | |||
| 77a00d7623 | |||
| 369bd7a6e1 | |||
| 8604774741 | |||
| 5f2a00ba4a | |||
| 355f81520c | |||
| 1af9a7b4d9 | |||
| de9c0e6724 | |||
| 3ad35c6980 | |||
| b5a2938b12 | |||
| 5b09353b06 | |||
| 872db63c0c | |||
| 9af6b71712 | |||
| bda32cca6a | |||
| b23c1a8b62 | |||
| 882a06f226 | |||
| 50b329bd35 | |||
| a2509c629e | |||
| 2307637c80 | |||
| 631e7b4c13 | |||
| 9fae1cbe1c | |||
| bbf2b1e6f9 |
4
app/FSM/__init__.py
Normal file
4
app/FSM/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .states import OrderForm, SearchForm, OrderingForm
|
||||
|
||||
|
||||
__all__ = ["SearchForm", "OrderForm", "OrderingForm"]
|
||||
25
app/FSM/states.py
Normal file
25
app/FSM/states.py
Normal file
@@ -0,0 +1,25 @@
|
||||
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()
|
||||
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import os
|
||||
import asyncpg
|
||||
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')}@"
|
||||
f"{os.getenv('DB_HOST')}/{os.getenv('DATABASE')}")
|
||||
print(DATABASE_URL)
|
||||
engine = create_async_engine(DATABASE_URL, echo=True)
|
||||
async_session_ = async_sessionmaker(bind=engine, expire_on_commit=False)
|
||||
|
||||
@@ -13,10 +13,11 @@ class Base(DeclarativeBase):
|
||||
class Worker(Base):
|
||||
"""
|
||||
id SERIAL PRIMARY KEY,
|
||||
telegram_id INTEGER UNIQUE NOT NULL,
|
||||
telegram_id BIGINT UNIQUE NOT NULL,
|
||||
name VARCHAR NOT NULL,
|
||||
email VARCHAR(50),
|
||||
phone_number VARCHAR(20) NOT NULL,
|
||||
phone_number VARCHAR(20),
|
||||
job_title job_title default 'Сборщик',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
"""
|
||||
@@ -27,7 +28,7 @@ class Worker(Base):
|
||||
name = Column(String, nullable=False)
|
||||
email = Column(String, nullable=True)
|
||||
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())
|
||||
updated_at = Column(Date, onupdate=func.now())
|
||||
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import logging
|
||||
import os
|
||||
from typing import Any
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
from aiogram.filters import BaseFilter
|
||||
from keyboards.menu_commands import commands
|
||||
import os
|
||||
|
||||
loggger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
class IsAdmin(BaseFilter):
|
||||
def __init__(self):
|
||||
self.admins_ids = os.getenv("BOT_ADMINS").split(",")
|
||||
self.admins_ids = list(map(int, os.getenv("BOT_ADMINS").split(",")))
|
||||
|
||||
|
||||
async def __call__(self, message: Message | CallbackQuery) -> bool:
|
||||
return str(message.from_user.id) in self.admins_ids
|
||||
return message.from_user.id in self.admins_ids
|
||||
|
||||
|
||||
class CommandFilter(BaseFilter):
|
||||
@@ -23,3 +22,7 @@ class CommandFilter(BaseFilter):
|
||||
async def __call__(self, message: Message) -> bool:
|
||||
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
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
from .Filters import IsAdmin
|
||||
from .Filters import IsRegister
|
||||
|
||||
__all__ = ["IsRegister", "IsAdmin"]
|
||||
@@ -1,11 +1,9 @@
|
||||
import time
|
||||
import re
|
||||
from aiogram import Router, Bot, F
|
||||
from aiogram.types import (Message, ChatMemberUpdated, FSInputFile, CallbackQuery, ReplyKeyboardRemove)
|
||||
from loguru import logger
|
||||
from aiogram import Router, Bot, F
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
from handlers.registration import registration_confirm
|
||||
from filters.Filters import IsAdmin, CommandFilter
|
||||
from database import async_session_
|
||||
from filters.Filters import IsAdmin
|
||||
|
||||
admin_router = Router()
|
||||
|
||||
|
||||
@@ -1,61 +1,39 @@
|
||||
import asyncio
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
from pathlib import Path
|
||||
from aiogram import Router, Bot, F
|
||||
from aiogram.filters import CommandStart, Command
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove
|
||||
from aiogram.exceptions import AiogramError
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.fsm.context import FSMContext
|
||||
|
||||
from sqlalchemy import select, insert
|
||||
from sqlalchemy import select
|
||||
from loguru import logger
|
||||
from filters import IsAdmin
|
||||
from keyboards import create_inline_kb, commands, button_create
|
||||
from keyboards import create_inline_kb, button_create
|
||||
from database import async_session_, Order, Worker
|
||||
from FSM import SearchForm, OrderForm
|
||||
|
||||
orders_router = Router()
|
||||
|
||||
# orders_router.message.filter()
|
||||
|
||||
order_operation_base = {"add_order_photo": "Добавить фото",
|
||||
"get_order_photo": "Получить фото",
|
||||
"get_order_components": "Получить список комплектующих",
|
||||
"get_order_documentation": "Получить документацию"
|
||||
"get_order_documentation": "Получить документацию",
|
||||
"finish_work_on_order": "❌ Закрыть"
|
||||
}
|
||||
order_operation_update = {"add_order_documentation": "Добавить документацию"}
|
||||
|
||||
order_main = {"find_orders": "Найти заказ"}
|
||||
order_main = {"find_orders": "Найти заказ", "create_order": "Создать заказ"}
|
||||
order_main_update = {"create_order": "Создать заказ"}
|
||||
|
||||
find_order_params = {"search_by_name": "Поиск по названию", "search_by_description": "Поиск по описанию ",
|
||||
"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"))
|
||||
async def orders_menu(message: Message):
|
||||
order_main_upd = order_main_update if await IsAdmin()(message) else {}
|
||||
await message.answer(text="Доступные действия с заказами:",
|
||||
reply_markup=create_inline_kb(width=1, **order_main, **order_main_upd))
|
||||
reply_markup=create_inline_kb(width=1, **order_main))
|
||||
await message.delete()
|
||||
|
||||
|
||||
@orders_router.callback_query(lambda x: x.data.startswith("create_order"))
|
||||
@@ -86,10 +64,6 @@ async def get_order_customer(callback: CallbackQuery, state: FSMContext):
|
||||
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)
|
||||
async def order_description(message: Message, state: FSMContext):
|
||||
await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )")
|
||||
@@ -136,33 +110,30 @@ async def search_by_item(message: Message, state: FSMContext):
|
||||
selected_orders = result.scalars().all()
|
||||
|
||||
if selected_orders:
|
||||
await message.answer(text="Список найденных заказов: ",
|
||||
reply_markup=create_inline_kb(width=1, **dict(
|
||||
(f"show_order_{order.id}", f"Описание: {order.description or "Отсутствует"}"
|
||||
f"Заказ: №{order.id}\n"
|
||||
await message.answer(text="Список найденных заказов: ")
|
||||
sent_messages = []
|
||||
for order in selected_orders:
|
||||
sent_messages.append(await message.answer(text=f"Номер заказа: {order.id}\n"
|
||||
f"Заказчик: {order.customer}\n"
|
||||
) for order in
|
||||
selected_orders)))
|
||||
await state.update_data(search_result=selected_orders)
|
||||
f"Статус: {order.status_id}\n"
|
||||
f"Дата отгрузки: {order.end_work}\n"
|
||||
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)
|
||||
else:
|
||||
await message.answer(text="Заказов по вашему запросу не найдено")
|
||||
await state.clear()
|
||||
|
||||
|
||||
@orders_router.callback_query(SearchForm.search_result)
|
||||
async def show_order(callback: CallbackQuery, state: FSMContext):
|
||||
@orders_router.callback_query(SearchForm.search_result and (lambda x: "show_order_" in x.data))
|
||||
async def show_order(callback: CallbackQuery, state: FSMContext, bot: Bot):
|
||||
order_id = int(re.search(r"(\d+)", callback.data).group())
|
||||
|
||||
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 {}
|
||||
orders = await state.get_value("search_result")
|
||||
order = next(filter(lambda item: order_id == item.id, orders), None)
|
||||
|
||||
if order:
|
||||
await callback.message.answer(text=f"Номер заказа: {order.id}\n"
|
||||
@@ -172,21 +143,22 @@ async def show_order(callback: CallbackQuery, state: FSMContext):
|
||||
f"Дата отгрузки: {order.end_work}\n"
|
||||
f"Дата создания: {order.created_at}\n"
|
||||
f"Описание: {order.description}",
|
||||
reply_markup=create_inline_kb(width=2, **dict(
|
||||
reply_markup=create_inline_kb(width=1, **dict(
|
||||
(f"{clbk}_{order.id}", text) for clbk, text in order_operation_base.items()))
|
||||
)
|
||||
|
||||
await callback.message.delete()
|
||||
for message in await state.get_value("sent_messages"):
|
||||
await bot.delete_message(chat_id=callback.message.chat.id, message_id=message.message_id)
|
||||
await state.clear()
|
||||
|
||||
|
||||
@orders_router.callback_query(lambda x: x.data.startswith("get_order_photo"))
|
||||
async def send_order_photos(callback: CallbackQuery, bot: Bot):
|
||||
order_id = callback.data.split("_")[-1]
|
||||
media_item: Path
|
||||
media_group = []
|
||||
os.makedirs(Path(f"./photos/{order_id}/"), exist_ok=True)
|
||||
media_path = Path(f"./photos/{order_id}/").iterdir()
|
||||
order_photos_path = Path(f"/app/photos/{order_id}/")
|
||||
os.makedirs(order_photos_path, exist_ok=True)
|
||||
media_path = order_photos_path.iterdir()
|
||||
if not (media_item := next(media_path, None)):
|
||||
text = f"Фото по заказу \"{order_id}\" отсутствуют "
|
||||
else:
|
||||
@@ -194,7 +166,7 @@ async def send_order_photos(callback: CallbackQuery, bot: Bot):
|
||||
f"")
|
||||
await bot.send_message(chat_id=callback.from_user.id, text=text)
|
||||
while media_item or media_group:
|
||||
if len(media_group) == 10 or (media_group and not media_item):
|
||||
if len(media_group) == 10 or not media_item:
|
||||
await bot.send_media_group(chat_id=callback.from_user.id, media=media_group)
|
||||
media_group.clear()
|
||||
if media_item:
|
||||
@@ -205,8 +177,10 @@ async def send_order_photos(callback: CallbackQuery, bot: Bot):
|
||||
logger.error(f"Ошибка при обработке {media_path}: {err}")
|
||||
|
||||
media_item = next(media_path, None)
|
||||
await asyncio.sleep(600)
|
||||
await callback.message.delete()
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@orders_router.callback_query(lambda x: x.data.startswith("add_order_photo"))
|
||||
@@ -221,7 +195,7 @@ async def reply_for_photo(callback: CallbackQuery, bot: Bot):
|
||||
F.reply_to_message)
|
||||
async def add_order_photo(message: Message, bot: Bot):
|
||||
order_id = re.search(r"(\d+)", message.reply_to_message.text).group()
|
||||
order_photos_path = f"/app/photos/{order_id}/"
|
||||
order_photos_path = Path(f"/app/photos/{order_id}/")
|
||||
os.makedirs(order_photos_path, exist_ok=True)
|
||||
|
||||
item = message.video or message.photo[-1]
|
||||
@@ -241,3 +215,8 @@ 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)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@orders_router.callback_query(F.data.startswith("finish_work_on_order"))
|
||||
async def finish_work_on_order(callback: CallbackQuery):
|
||||
await callback.message.delete()
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import os
|
||||
from asyncio import Event, wait_for, TimeoutError
|
||||
|
||||
from aiogram import Router, Bot
|
||||
from aiogram.filters import CommandStart
|
||||
from aiogram.types import Message, User
|
||||
|
||||
from sqlalchemy import insert, select
|
||||
|
||||
from loguru import logger
|
||||
from keyboards import create_inline_kb
|
||||
from database import async_session_, Worker
|
||||
from filters import IsRegister
|
||||
|
||||
|
||||
registration_router = Router()
|
||||
|
||||
registration_router.message.filter(IsRegister() or CommandStart())
|
||||
registration_confirm: dict[int, Event] = {}
|
||||
user_info_template = ("Новый пользователь ждет регистрации:\n"
|
||||
"Имя: {}\n"
|
||||
@@ -19,28 +20,29 @@ user_info_template = ("Новый пользователь ждет регист
|
||||
"Юзернейм: @{}\n"
|
||||
"ID: @msg_{}\n")
|
||||
|
||||
admins_ids = list(map(int, os.getenv("BOT_ADMINS").split(",")))
|
||||
|
||||
|
||||
|
||||
@registration_router.message(CommandStart())
|
||||
async def registration_command(message: Message, bot: Bot):
|
||||
async def start_command(message: Message, bot: Bot):
|
||||
async with async_session_() as session:
|
||||
async with session.begin():
|
||||
result = await session.execute(select(Worker).where(Worker.telegram_id == message.from_user.id))
|
||||
user = result.scalars().first()
|
||||
if not user:
|
||||
|
||||
user = message.from_user
|
||||
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.username if user.username else 'Не указан', user.id)
|
||||
for admin in admins_ids:
|
||||
for admin in list(map(int, os.getenv("BOT_ADMINS").split(","))):
|
||||
try:
|
||||
await bot.send_message(chat_id=admin, text=user_info)
|
||||
await bot.send_message(chat_id=admin, text='Зарегистрировать пользователя',
|
||||
reply_markup=create_inline_kb(width=2, **dict_for_inline))
|
||||
except Exception as err:
|
||||
pass
|
||||
await message.answer("Запрос на регистрацию отправлен администратору, ожидайте подтверждения.")
|
||||
|
||||
except Exception:
|
||||
logger.error(f"{start_command.__name__} failed")
|
||||
|
||||
reg_confirm = Event()
|
||||
registration_confirm[user.id] = reg_confirm
|
||||
try:
|
||||
@@ -49,7 +51,7 @@ async def registration_command(message: Message, bot: Bot):
|
||||
async with local_session.begin():
|
||||
local_session.add(Worker(telegram_id=user.id, name=user.first_name))
|
||||
|
||||
await message.answer("Регистрация подтверждена")
|
||||
await message.answer("Регистрация подтверждена, для просмотра доступных действий нажмите кнопку 'MENU'")
|
||||
except TimeoutError:
|
||||
await message.answer("Время ожидания истекло.")
|
||||
|
||||
@@ -57,3 +59,8 @@ async def registration_command(message: Message, bot: Bot):
|
||||
|
||||
else:
|
||||
await message.answer("Работа бота возобновлена")
|
||||
|
||||
|
||||
@registration_router.message()
|
||||
async def catch_message(message: Message):
|
||||
await message.answer("Для работы с ботом, требуется регистрация\nНажмите /start для регистрации")
|
||||
@@ -1,12 +1,14 @@
|
||||
import os
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(".env")
|
||||
|
||||
from aiogram import Dispatcher, Bot
|
||||
from handlers import *
|
||||
from keyboards import set_main_menu
|
||||
from middlewares import AccessCheckMiddleware
|
||||
from middlewares import SessionMiddleware
|
||||
|
||||
load_dotenv(".env")
|
||||
bot = Bot(token=os.getenv("TOKEN"))
|
||||
|
||||
|
||||
@@ -16,7 +18,7 @@ async def main() -> None:
|
||||
dp.startup.register(set_main_menu)
|
||||
dp.include_router(registration_router)
|
||||
dp.include_router(admin_router)
|
||||
dp.update.outer_middleware(AccessCheckMiddleware())
|
||||
dp.update.outer_middleware(SessionMiddleware())
|
||||
dp.include_router(orders_router)
|
||||
dp.include_router(components_router)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from .outer_middlewares import AccessCheckMiddleware
|
||||
from .outer_middlewares import SessionMiddleware
|
||||
|
||||
|
||||
__all__ = ["AccessCheckMiddleware"]
|
||||
__all__ = ["SessionMiddleware"]
|
||||
@@ -1,29 +1,29 @@
|
||||
import logging
|
||||
from typing import Any, Awaitable, Callable, Dict
|
||||
from aiogram import BaseMiddleware, Bot
|
||||
from aiogram.types import TelegramObject
|
||||
from database import async_session_, Worker
|
||||
from sqlalchemy import select
|
||||
from loguru import logger
|
||||
from database import async_session_, Worker
|
||||
|
||||
|
||||
|
||||
class AccessCheckMiddleware(BaseMiddleware):
|
||||
class SessionMiddleware(BaseMiddleware):
|
||||
sessions_in_memory_db = set()
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
|
||||
event: TelegramObject,
|
||||
data: Dict[str, Any]
|
||||
) -> Any:
|
||||
logger.info("Session check")
|
||||
event_data = event.message or event.callback_query
|
||||
user = event_data.from_user.id
|
||||
if user not in self.sessions_in_memory_db:
|
||||
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))
|
||||
user = result.scalars().first()
|
||||
if user:
|
||||
self.sessions_in_memory_db.add(event_data.from_user.id)
|
||||
user_in_db = result.scalars().first()
|
||||
if not user_in_db:
|
||||
data["through_registration"] = True
|
||||
else:
|
||||
self.sessions_in_memory_db.add(user)
|
||||
return await handler(event, data)
|
||||
return None
|
||||
|
||||
|
||||
37
drone.yaml
37
drone.yaml
@@ -20,28 +20,35 @@ steps:
|
||||
- docker build -t myapp:${DRONE_COMMIT_SHA} .
|
||||
|
||||
- name: deploy
|
||||
image: alpine
|
||||
image: docker
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run/docker.sock
|
||||
- name: env
|
||||
path: /srv/prod/telegram_bot/
|
||||
environment:
|
||||
ENV_CONTENT:
|
||||
from_secret: DOT_ENV_CONTENT
|
||||
TOKEN:
|
||||
from_secret: TOKEN
|
||||
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:
|
||||
- apk add --no-cache openssh
|
||||
- echo "$ENV_CONTENT" > .env
|
||||
settings:
|
||||
host: localhost
|
||||
username: ronis_0505
|
||||
password: 667766
|
||||
script:
|
||||
- docker pull myapp:${DRONE_COMMIT_SHA}
|
||||
- docker stop myapp || true
|
||||
- docker rm myapp || true
|
||||
- docker run -d --name myapp \
|
||||
--network prod_net \
|
||||
-v /srv/prod/telegram_bot/photos:/app/photos/ \
|
||||
myapp:${DRONE_COMMIT_SHA}
|
||||
- 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}
|
||||
|
||||
|
||||
volumes:
|
||||
- name: dockersock
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
- name: env
|
||||
host:
|
||||
path: /srv/prod/telegram_bot/
|
||||
Reference in New Issue
Block a user