Skip to content

Commit

Permalink
* Team messaging background task,
Browse files Browse the repository at this point in the history
* Project creation date for creation date sorting
* Email services fixed
* User statistics for validation time spent.
  • Loading branch information
prabinoid committed Nov 19, 2024
1 parent 5be6a30 commit e4c3b6c
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 135 deletions.
33 changes: 6 additions & 27 deletions backend/api/teams/actions.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
from databases import Database
from fastapi import APIRouter, Depends, Request, Body, BackgroundTasks
from fastapi import APIRouter, BackgroundTasks, Body, Depends, Request
from fastapi.responses import JSONResponse
from loguru import logger

from backend.db import get_db
from backend.db import db_connection, get_db
from backend.models.dtos.message_dto import MessageDTO
from backend.models.dtos.user_dto import AuthUserDTO
from backend.models.postgis.user import User
from backend.services.team_service import (
TeamService,
TeamJoinNotAllowed,
TeamService,
TeamServiceError,
)
from backend.models.postgis.user import User
from backend.services.users.authentication_service import login_required
from backend.models.dtos.user_dto import AuthUserDTO

router = APIRouter(
prefix="/teams",
Expand Down Expand Up @@ -314,19 +314,6 @@ async def post(
)


import asyncio


# Function to run async code in a thread
def run_asyncio_in_thread(func, *args, **kwargs):
# Create a new event loop for the thread
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
# Create a new database connection (to be used in this thread)
db = get_db()
loop.run_until_complete(func(*args, db=db, **kwargs))


@router.post("/{team_id}/actions/message-members/")
async def post(
request: Request,
Expand Down Expand Up @@ -411,22 +398,14 @@ async def post(
)

try:
# Start a new thread for sending messages
# Use threading to run the async function in a separate thread
# threading.Thread(
# target=run_asyncio_in_thread,
# args=(TeamService.send_message_to_all_team_members, team_id, team.name, message_dto, user.id)
# ).start()

background_tasks.add_task(
TeamService.send_message_to_all_team_members,
team_id,
team.name,
message_dto,
user.id,
db,
db_connection.database,
)

return JSONResponse(
content={"Success": "Message sent successfully"}, status_code=200
)
Expand Down
7 changes: 3 additions & 4 deletions backend/db.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from backend.config import settings
from sqlalchemy.orm import declarative_base

from databases import Database
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import declarative_base, sessionmaker

from backend.config import settings

Base = declarative_base()

Expand Down
14 changes: 8 additions & 6 deletions backend/models/dtos/user_dto.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from backend.models.dtos.stats_dto import Pagination
from backend.models.dtos.mapping_dto import TaskDTO
from backend.models.dtos.interests_dto import InterestDTO
from backend.models.postgis.statuses import MappingLevel, UserRole
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel, Field
from pydantic.functional_validators import field_validator

from backend.models.dtos.interests_dto import InterestDTO
from backend.models.dtos.mapping_dto import TaskDTO
from backend.models.dtos.stats_dto import Pagination
from backend.models.postgis.statuses import MappingLevel, UserRole


def is_known_role(value):
"""Validates that supplied user role is known value"""
Expand Down
2 changes: 2 additions & 0 deletions backend/models/postgis/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def from_dto(cls, to_user_id: int, dto: MessageDTO):
message.to_user_id = to_user_id
message.project_id = dto.project_id
message.task_id = dto.task_id
message.date = timestamp()
message.read = False
if dto.message_type is not None:
message.message_type = MessageType(dto.message_type)

Expand Down
1 change: 1 addition & 0 deletions backend/models/postgis/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ def create_draft_project(self, draft_project_dto: DraftProjectDTO):
self.organisation_id = self.organisation.id
self.status = ProjectStatus.DRAFT.value
self.author_id = draft_project_dto.user_id
self.created = timestamp()
self.last_updated = timestamp()

async def set_project_aoi(self, draft_project_dto: DraftProjectDTO, db: Database):
Expand Down
2 changes: 1 addition & 1 deletion backend/services/messaging/message_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ async def _push_messages(messages: list, db: Database):
continue
# If the notification is enabled, send an email
messages_objs.append(obj)
SMTPService.send_email_alert(
await SMTPService.send_email_alert(
user.email_address,
user.username,
user.is_email_verified,
Expand Down
21 changes: 11 additions & 10 deletions backend/services/messaging/smtp_service.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import urllib.parse
from loguru import logger
from itsdangerous import URLSafeTimedSerializer

from fastapi_mail import MessageSchema, MessageType
from itsdangerous import URLSafeTimedSerializer
from loguru import logger

# from backend import mail, create_app
from backend import create_app, mail
from backend.config import settings
from backend.models.postgis.message import Message as PostgisMessage
from backend.models.postgis.statuses import EncouragingEmailType
from backend.services.messaging.template_service import (
get_template,
format_username_link,
get_template,
)
from backend.config import settings


class SMTPService:
Expand All @@ -32,15 +33,15 @@ async def send_verification_email(to_address: str, username: str):
return True

@staticmethod
def send_welcome_email(to_address: str, username: str):
async def send_welcome_email(to_address: str, username: str):
"""Sends email welcoming new user to tasking manager"""
values = {
"USERNAME": username,
}
html_template = get_template("welcome.html", values)

subject = "Welcome to Tasking Manager"
SMTPService._send_message(to_address, subject, html_template)
await SMTPService._send_message(to_address, subject, html_template)
return True

@staticmethod
Expand All @@ -63,7 +64,7 @@ async def send_contact_admin_email(data):
await SMTPService._send_message(email_to, subject, message, message)

@staticmethod
def send_email_to_contributors_on_project_progress(
async def send_email_to_contributors_on_project_progress(
email_type: str,
project_id: int = None,
project_name: str = None,
Expand Down Expand Up @@ -120,12 +121,12 @@ def send_email_to_contributors_on_project_progress(
logger.debug(
f"Sending {email_type} email to {contributor.email_address} for project {project_id}"
)
SMTPService._send_message(
await SMTPService._send_message(
contributor.email_address, subject, html_template
)

@staticmethod
def send_email_alert(
async def send_email_alert(
to_address: str,
username: str,
user_email_verified: bool,
Expand Down Expand Up @@ -172,7 +173,7 @@ def send_email_alert(
"MESSAGE_TYPE": message_type,
}
html_template = get_template("message_alert_en.html", values)
SMTPService._send_message(to_address, subject, html_template)
await SMTPService._send_message(to_address, subject, html_template)

return True

Expand Down
72 changes: 34 additions & 38 deletions backend/services/team_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,30 @@
from markdown import markdown

from backend.exceptions import NotFound
from backend.models.dtos.message_dto import MessageDTO
from backend.models.dtos.stats_dto import Pagination
from backend.models.dtos.team_dto import (
ListTeamsDTO,
TeamDTO,
NewTeamDTO,
TeamsListDTO,
ProjectTeamDTO,
TeamDetailsDTO,
TeamDTO,
TeamSearchDTO,
TeamsListDTO,
)

from backend.models.dtos.message_dto import MessageDTO
from backend.models.dtos.stats_dto import Pagination
from backend.models.postgis.message import Message, MessageType
from backend.models.postgis.team import Team, TeamMembers
from backend.models.postgis.project import ProjectTeams
from backend.models.postgis.statuses import (
TeamJoinMethod,
TeamMemberFunctions,
TeamVisibility,
TeamRoles,
TeamVisibility,
UserRole,
)
from backend.models.postgis.team import Team, TeamMembers
from backend.services.messaging.message_service import MessageService
from backend.services.organisation_service import OrganisationService
from backend.services.users.user_service import UserService
from backend.services.messaging.message_service import MessageService


class TeamServiceError(Exception):
Expand Down Expand Up @@ -790,34 +789,31 @@ async def send_message_to_all_team_members(
team_name: str,
message_dto: MessageDTO,
user_id: int,
db: Database = None,
database: Database,
):
if db is None:
print("inside....")
db = await acquire_connection()
print("Sending message to the team...")
print(db)
team_members = await TeamService._get_active_team_members(team_id, db)
user = await UserService.get_user_by_id(user_id, db)
print("Fetched User....")

sender = user.username
message_dto.message = (
"A message from {}, manager of {} team:<br/><br/>{}".format(
MessageService.get_user_profile_link(sender),
MessageService.get_team_link(team_name, team_id, False),
markdown(message_dto.message, output_format="html"),
)
)
messages = []
for team_member in team_members:
print("Looping teams.......")

if team_member.user_id != user_id:
message = Message.from_dto(team_member.user_id, message_dto)
message.message_type = MessageType.TEAM_BROADCAST.value
await Message.save(message, db)
user = await UserService.get_user_by_id(team_member.user_id, db)
messages.append(dict(message=message, user=user))

await MessageService._push_messages(messages)
try:
async with database.connection() as conn:
team_members = await TeamService._get_active_team_members(team_id, conn)
user = await UserService.get_user_by_id(user_id, conn)
sender = user.username
message_dto.message = (
"A message from {}, manager of {} team:<br/><br/>{}".format(
MessageService.get_user_profile_link(sender),
MessageService.get_team_link(team_name, team_id, False),
markdown(message_dto.message, output_format="html"),
)
)
messages = []
for team_member in team_members:
if team_member.user_id != user_id:
message = Message.from_dto(team_member.user_id, message_dto)
message.message_type = MessageType.TEAM_BROADCAST.value
user = await UserService.get_user_by_id(
team_member.user_id, conn
)
messages.append(dict(message=message, user=user))
# Push messages
await MessageService._push_messages(messages, conn)
logger.info("Messages sent successfully.")
except Exception as e:
logger.error(f"Error sending messages in background task: {str(e)}")
Loading

0 comments on commit e4c3b6c

Please sign in to comment.