Skip to content

Commit

Permalink
Merge branch 'dev' into feature/tests_analytics
Browse files Browse the repository at this point in the history
  • Loading branch information
ErendzhenovBair authored Feb 7, 2024
2 parents 0825145 + dcad6b9 commit 1800177
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 57 deletions.
18 changes: 14 additions & 4 deletions infra/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
frontend:
container_name: frontend
image: zali1813/short_tracker_frontend:v1
restart: always
# restart: always
volumes:
- ../frontend/:/app/result_build/
# depends_on:
Expand Down Expand Up @@ -40,18 +40,28 @@ services:
- media_value:/var/html/media/
# depends_on:
# - backend

redis:
image: redis:alpine
restart: on-failure
ports:
- "6379:6379"
volumes:
- redis_data:/data
bot:
container_name: bot
image: zali1813/short_tracker_bot:v1
# build:
# context: ../short_tracker_bot
# dockerfile: Dockerfile
restart: always
env_file:
- ./.env
# depends_on:
# - backend
depends_on:
- redis

volumes:
static_value:
media_value:
postgres_data:
redis_data:

3 changes: 2 additions & 1 deletion short_tracker/api/v1/bot/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib.auth import get_user_model
from rest_framework.generics import ListAPIView
from rest_framework.generics import ListAPIView, GenericAPIView
from rest_framework.views import APIView

from .serializer import BotSerializer

Expand Down
18 changes: 13 additions & 5 deletions short_tracker/api/v1/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@ def has_permission(self, request, view):
class IsLeadOrPerformerHimselfOnly(permissions.BasePermission):

def has_permission(self, request, view):
is_lead = request.user.is_lead
return request.user.id == request.data.get('performers')[0] or is_lead
is_lead = request.user.is_authenticated and request.user.is_team_lead
return is_lead or (
request.user.is_authenticated
and request.user.id == request.data.get('performers')[0]
)


class IsCreatorOnly(permissions.BasePermission):

def has_permission(self, request, view):
is_lead = request.user.is_lead
return [request.user.id] == request.data.get('performers') or is_lead
is_lead = request.user.is_authenticated and request.user.is_team_lead
return is_lead or (
request.user.is_authenticated
and request.user.id == request.data.get('performers')[0]
)

def has_object_permission(self, request, view, obj):
return request.user.id == obj.creator.id
return (
request.user.is_authenticated
and request.user.id == obj.creator.id)
5 changes: 3 additions & 2 deletions short_tracker/short_tracker/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@
}

SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ACCESS_TOKEN_LIFETIME': timedelta(hours=8),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
}

Expand All @@ -159,6 +159,7 @@
'LOGIN_FIELD': 'email',
'PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND': True,
'HIDE_USERS': False,
'PERMISSIONS': {'user_create': ['api.v1.permissions.IsTeamLead']},
'SERIALIZERS': {
'user': 'api.v1.users.serializers.UserSerializer',
'current_user': 'api.v1.users.serializers.UserSerializer',
Expand Down
5 changes: 3 additions & 2 deletions short_tracker/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,12 @@ class CustomUser(AbstractUser):
)],
)
telegram_nickname = models.CharField(
max_length=32,
max_length=33,
verbose_name='Никнейм Телеграм',
unique=True,
validators=[
RegexValidator(
regex=r'^@[a-zA-Z0-9_]{5,32}\Z',
regex=r'^@[a-zA-Z0-9_]{5,33}\Z',
message='nickname содержит недопустимый символ'
)],
)
Expand Down
2 changes: 2 additions & 0 deletions short_tracker_bot/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ COPY short_tracker_bot/requirements.txt .

RUN pip install -r requirements.txt --no-cache-dir

RUN chmod 755 .

COPY ./short_tracker_bot .

# RUN python3 short_tracker_bot/bot.py
Expand Down
Binary file modified short_tracker_bot/requirements.txt
Binary file not shown.
8 changes: 5 additions & 3 deletions short_tracker_bot/short_tracker_bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

import dotenv
from aiogram import Bot, Dispatcher
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.fsm.storage.redis import RedisStorage
from aioredis import Redis
from config import COMMANDS
from handlers.hello import router

Expand All @@ -13,8 +14,9 @@

async def main():
bot = Bot(token=os.getenv('TOKEN'))
memory = MemoryStorage()
dp = Dispatcher(memory=memory)
redis = Redis(host='redis')
storage = RedisStorage(redis=redis)
dp = Dispatcher(storage=storage)
dp.include_router(router)
await bot.set_my_commands(commands=COMMANDS)
await dp.start_polling(bot)
Expand Down
7 changes: 6 additions & 1 deletion short_tracker_bot/short_tracker_bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@
TOKEN = '6787434498:AAHW5Y2gUJQLqttiQ-Vj9qulyBoTCHYYVu4'
URL = 'https://short-tracker.acceleratorpracticum.ru/api/v1/'
COMMANDS = [BotCommand(command='/start', description='Запуск бота')
]
]
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
' AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
}
103 changes: 64 additions & 39 deletions short_tracker_bot/short_tracker_bot/handlers/hello.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,13 @@
from aiogram.filters import CommandStart
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from config import URL
from config import HEADERS, URL
from keyboards.keyboards import start_keyboard

from .redis_data import get_data_from_redis, save_data_to_redis
from .requests import request_get, request_post

router = Router()
OLD_MESSAGES = []
OLD_REPLIES = []
TASKS_DICT = dict()
TASKS_EXPIRED = []
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
' AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
}


class Login(StatesGroup):
Expand Down Expand Up @@ -47,6 +40,7 @@ async def get_token(state, bot):
await state.update_data(new_token=f'Bearer {token.value}')
data_fsm = await state.get_data()
logging.info(f'NEW TOKEN {data_fsm["new_token"]}')
await bot.send_message('Вход успешно выполнен!')
return data_fsm['new_token']
else:
await bot.send_message(
Expand All @@ -58,22 +52,73 @@ async def get_token(state, bot):


async def get_messages(data, chat_id, bot: Bot):
logging.info('Вход в функцию получения сообщений')
for msg in data['results'][0]['messages']:
if msg['id'] not in OLD_MESSAGES:
OLD_MESSAGES.append(msg['id'])
logging.info(msg)
message_in_redis = get_data_from_redis(f'{chat_id}_msg_{msg["id"]}')
logging.info(message_in_redis)
if not message_in_redis:
await save_data_to_redis(
f'{chat_id}_msg_{msg["id"]}', msg['message_body']
)
await bot.send_message(
chat_id,
text=f'У вас новое сообщение\n\"{msg["message_body"]}\"'
)
for reply in msg['reply']:
if reply['id'] not in OLD_REPLIES:
OLD_REPLIES.append(reply['id'])
reply_in_redis = await get_data_from_redis(f'{chat_id}_reply_{msg["id"]}')
if not reply_in_redis:
await save_data_to_redis(
f'{chat_id}_reply_{msg["id"]}',
reply["reply_body"]
)
await bot.send_message(
chat_id,
text=f'На ваш запрос к лиду поступил ответ:\n{reply["reply_body"]}'
text=f'На ваш запрос к лиду поступил ответ:'
f'\n{reply["reply_body"]}'
)


async def get_tasks(data, chat_id, bot: Bot):
for task in data['results'][0]['tasks_for_user']:
if not get_data_from_redis(f'{chat_id}_task_{task["id"]}'):
await bot.send_message(
chat_id=chat_id,
text=f'У Вас появилась новая задача'
f' \"{task["description"]}\"'
)
await save_data_to_redis(
f'{chat_id}_task_{task["id"]}',
task['status']
)
current_status = await get_data_from_redis(
f'{chat_id}_task_status_{task["id"]}'
)
if task['status'] != current_status:
logging.info(f'Сравнение {task["status"], current_status}')
await save_data_to_redis(
f'{chat_id}_task_status_{task["id"]}',
task["status"]
)
await bot.send_message(
chat_id=chat_id,
text=f'Изменен статус задачи '
f'\"{task["description"]}\" на {task["status"]}')
if task['is_expired'] and not get_data_from_redis(
f'{chat_id}_status_{task["id"]}'
):
await save_data_to_redis(
f'{chat_id}_status_{task["id"]}',
task['is_expired']
)
performers = [performer['full_name'] for performer in task['performers']]
await bot.send_message(
chat_id=chat_id,
text=f'Задача \"{task["description"]}\" сотрудника'
f' {", ".join(performers)} просрочена'
)


async def get_data(state: FSMContext, bot: Bot):
data_fsm = await state.get_data()
token = data_fsm['new_token']
Expand All @@ -98,39 +143,19 @@ async def get_data(state: FSMContext, bot: Bot):
data = await request_get(
URL + 'bot/',
headers=headers)
logging.info('Запрос сообщений')
logging.info(f'Запрос сообщений')
await get_messages(data, chat_id, bot)
for task in data['results'][0]['tasks_for_user']:
if task['id'] not in TASKS_DICT.keys():
await bot.send_message(
chat_id=chat_id,
text=f'У Вас появилась новая задача \"{task["description"]}\"'
)
TASKS_DICT[task['id']] = task['status']
if task['status'] != TASKS_DICT[task['id']]:
TASKS_DICT[task['id']] = task['status']
await bot.send_message(
chat_id=chat_id,
text=f'Изменен статус задачи \"{task["description"]}\" на {task["status"]}')
if task['is_expired'] and task['id'] not in TASKS_EXPIRED:
TASKS_EXPIRED.append(task['id'])
performers = [
performer['full_name']
for performer in task['performers']]
await bot.send_message(
chat_id=chat_id,
text=f'Задача \"{task["description"]}\" сотрудника'
f' {", ".join(performers)} просрочена'
)
await get_tasks(data, chat_id, bot)
except Exception:
logging.error('Не удалось получить данные')
finally:
await asyncio.sleep(600)
await asyncio.sleep(15)


@router.message(CommandStart())
async def email(message: types.Message, state: FSMContext):
await state.update_data(chat_id=message.chat.id)

await state.set_state(Login.email)
await message.answer('Введите свою почту')

Expand Down
18 changes: 18 additions & 0 deletions short_tracker_bot/short_tracker_bot/handlers/redis_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import asyncio
import logging

import aioredis

redis = aioredis.Redis(host='redis')


async def save_data_to_redis(key, value):
await redis.set(key, value)



async def get_data_from_redis(key):
data = await redis.get(key)
if data:
return data.decode('utf-8')
return None

0 comments on commit 1800177

Please sign in to comment.