Skip to content

Commit

Permalink
Merge pull request #659 from weni-ai/feature/rabbitmq-apps
Browse files Browse the repository at this point in the history
Feature/rabbitmq apps
  • Loading branch information
BarbosaJackson authored Jul 27, 2023
2 parents 5c1384b + 5a82d45 commit 4321b88
Show file tree
Hide file tree
Showing 21 changed files with 440 additions and 1,393 deletions.
26 changes: 2 additions & 24 deletions connect/api/v1/project/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,30 +595,8 @@ def create(self, validated_data, request):
template.classifier_uuid = classifier_uuid
template.flow_uuid = flow_uuid

# Integrate WhatsApp
token = request._auth
if not settings.TESTING:
try:
integrations_client = IntegrationsRESTClient()
response = integrations_client.whatsapp_demo_integration(str(project.uuid), token=token)
except Exception as error:
logger.error(error)
template.delete()
data.update(
{
"message": "Could not integrate Whatsapp demo",
"status": "FAILED"
}
)
return data
else:
response = {
"router_token": "wa-demo-12345",
"redirect_url": 'https://wa.me/5582123456?text=wa-demo-12345'
}

wa_demo_token = response.get("router_token")
redirect_url = response.get("redirect_url")
wa_demo_token = "wa-demo-12345"
redirect_url = 'https://wa.me/5582123456?text=wa-demo-12345'
template.wa_demo_token = wa_demo_token
template.redirect_url = redirect_url
template.save(update_fields=["classifier_uuid", "flow_uuid", "wa_demo_token", "redirect_url"])
Expand Down
9 changes: 8 additions & 1 deletion connect/api/v2/projects/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
TemplateProject,
RequestChatsPermission,
)
from connect.template_projects.models import TemplateType

logger = logging.getLogger(__name__)
User = get_user_model()
Expand Down Expand Up @@ -209,14 +210,20 @@ def create(self, validated_data):
}

is_template = extra_data.get("template")
project_template_type = None
if is_template:
project_template_type = TemplateType.objects.filter(name=extra_data.get("template_type"))
if project_template_type.exists():
project_template_type = project_template_type.first()

instance = Project.objects.create(
name=validated_data.get("name"),
timezone=str(validated_data.get("timezone")),
organization=validated_data.get("organization"),
is_template=True if extra_data.get("template") else False,
created_by=user,
template_type=extra_data.get("template_type")
template_type=extra_data.get("template_type"),
project_template_type=project_template_type,
)

created, flows_info = self.create_flows_project(validated_data, user, is_template, str(instance.uuid))
Expand Down
6 changes: 4 additions & 2 deletions connect/api/v2/projects/tests.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import json
import uuid
from unittest import skipIf
from unittest.mock import Mock, patch

from rest_framework import status
from rest_framework.test import APIRequestFactory, force_authenticate

from django.test import TestCase
from unittest.mock import Mock, patch

from connect.api.v1.tests.utils import create_user_and_token
from connect.common.models import Organization, BillingPlan, OrganizationRole, Project
Expand All @@ -13,7 +15,7 @@

from connect.api.v1.internal.flows.flows_rest_client import FlowsRESTClient


@skipIf(True,'deprecated')
class ProjectViewSetTestCase(TestCase):
@patch("connect.common.signals.update_user_permission_project")
@patch("connect.billing.get_gateway")
Expand Down
20 changes: 20 additions & 0 deletions connect/common/migrations/0080_auto_20230727_1400.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 3.2.20 on 2023-07-27 14:00

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('template_projects', '0004_templatetype_uuid'),
('common', '0079_auto_20230523_1821'),
]

operations = [
migrations.AddField(
model_name='project',
name='project_template_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='template_projects', to='template_projects.templatetype'),
),
]
8 changes: 8 additions & 0 deletions connect/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
IntelligenceRESTClient,
)
from connect.api.v1.internal.flows.flows_rest_client import FlowsRESTClient
from connect.template_projects.models import TemplateType
# from connect.api.v1.internal.chats.chats_rest_client import ChatsRESTClient
from rest_framework import status
from connect.common.helpers import send_mass_html_mail
Expand Down Expand Up @@ -724,6 +725,13 @@ class Meta:
null=True,
blank=True,
)
project_template_type = models.ForeignKey(
TemplateType,
on_delete=models.SET_NULL,
related_name="template_projects",
null=True,
blank=True
)

def __str__(self):
return f"{self.uuid} - Project: {self.name} - Org: {self.organization.name}"
Expand Down
14 changes: 14 additions & 0 deletions connect/common/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from connect.api.v1.internal.intelligence.intelligence_rest_client import IntelligenceRESTClient
from connect.api.v1.internal.chats.chats_rest_client import ChatsRESTClient
from connect.common.tasks import update_user_permission_project
from connect.internals.event_driven.producer.rabbitmq_publisher import RabbitmqPublisher
from requests.exceptions import HTTPError
from rest_framework.exceptions import APIException

Expand Down Expand Up @@ -367,3 +368,16 @@ def request_chats_permission(sender, instance, created, **kwargs):
def send_email_create_project(sender, instance, created, **kwargs):
if created:
instance.send_email_create_project()
if not settings.TESTING:
message_body = {
"uuid": str(instance.uuid),
"name": instance.name,
"is_template": instance.is_template,
"user_email": instance.created_by.email if instance.created_by else None,
"date_format": instance.date_format,
"template_type_uuid": str(instance.project_template_type.uuid) if instance.project_template_type else None,
"timezone": str(instance.timezone)
}

rabbitmq_publisher = RabbitmqPublisher()
rabbitmq_publisher.send_message(message_body, exchange="projects.topic", routing_key="")
Empty file added connect/internals/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions connect/internals/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class InternalsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'connect.internals'
Empty file.
Empty file.
28 changes: 28 additions & 0 deletions connect/internals/event_driven/connection/rabbitmq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from pika import BlockingConnection, ConnectionParameters, PlainCredentials
from django.conf import settings


class RabbitMQConnection: # pragma: no cover
_instance = None

def __new__(cls):
if cls._instance is None:
cls._instance = super(RabbitMQConnection, cls).__new__(cls)
cls._instance.connect()
return cls._instance

def connect(self):
if not hasattr(self, "connection"):
self.connection = BlockingConnection(ConnectionParameters(
host=settings.EDA_BROKER_HOST,
port=settings.EDA_BROKER_PORT,
credentials=PlainCredentials(
username=settings.EDA_BROKER_USER,
password=settings.EDA_BROKER_PASSWORD
)
))
self.channel = self.connection.channel()

def close(self):
if hasattr(self, "connection"):
self.connection.close()
Empty file.
26 changes: 26 additions & 0 deletions connect/internals/event_driven/producer/rabbitmq_publisher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import json

from pika import BasicProperties
from typing import Dict

from connect.internals.event_driven.connection.rabbitmq import RabbitMQConnection


class RabbitmqPublisher: # pragma: no cover
def __init__(self) -> None:
self.rabbitmq_connection = RabbitMQConnection()

def send_message(self, body: Dict, exchange: str, routing_key: str):
try:
self.rabbitmq_connection.channel.basic_publish(
exchange=exchange,
routing_key=routing_key,
body=json.dumps(body),
properties=BasicProperties(
delivery_mode=2
)
)
print("Message sent")
except Exception as e:
print(e)
raise e
Empty file.
12 changes: 12 additions & 0 deletions connect/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
"connect.common.apps.CommonConfig",
"connect.billing",
"connect.template_projects",
"connect.internals",
"django_celery_results",
"django_celery_beat",
"storages",
Expand Down Expand Up @@ -541,3 +542,14 @@

OMIE_APP_KEY = env.str("OMIE_APP_KEY", default="ap_test")
OMIE_APP_SECRET = env.str("OMIE_APP_SECRET", default="sk_test")


# Event driven architecture settings
USE_EDA = env.bool("USE_EDA", default=False)

if USE_EDA:

EDA_BROKER_HOST = env.str("EDA_BROKER_HOST", default="localhost")
EDA_BROKER_PORT = env.int("EDA_BROKER_PORT", default=5672)
EDA_BROKER_USER = env.str("EDA_BROKER_USER", default="guest")
EDA_BROKER_PASSWORD = env.str("EDA_BROKER_PASSWORD", default="guest")
19 changes: 19 additions & 0 deletions connect/template_projects/migrations/0004_templatetype_uuid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.20 on 2023-07-27 14:00

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

dependencies = [
('template_projects', '0003_templatetype_photo'),
]

operations = [
migrations.AddField(
model_name='templatetype',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, verbose_name='UUID'),
),
]
6 changes: 5 additions & 1 deletion connect/template_projects/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import uuid as uuid4

from django.db import models
from .storage import TemplateTypeImageStorage


class TemplateType(models.Model):

level_field = [("low", 1), ("medium", 2), ("high", 3)]

uuid = models.UUIDField(
"UUID", default=uuid4.uuid4
)
category = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
name = models.CharField(max_length=255, null=True, blank=True)
Expand Down
24 changes: 24 additions & 0 deletions connect/template_projects/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import uuid

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings

from connect.internals.event_driven.producer.rabbitmq_publisher import RabbitmqPublisher
from connect.template_projects.models import TemplateType


@receiver(post_save, sender=TemplateType)
def create_template_type(sender, instance, created, **kwargs):
if created and not settings.TESTING:
rabbitmq_publisher = RabbitmqPublisher()
if instance.uuid is None:
instance.uuid = uuid.uuid4()
instance.save()

message_body = {
"uuid": str(instance.uuid),
"name": instance.name
}

rabbitmq_publisher.send_message(message_body, exchange="template-types.topic", routing_key="")
9 changes: 8 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,14 @@ services:
image: redis
ports:
- 6379:6379

rabbitmq:
image: rabbitmq:3.9.7-management
ports:
- "5672:5672" # Port to connect to RabbitMQ
- "15672:15672" # Port to access the RabbitMQ management interface
environment:
- RABBITMQ_DEFAULT_USER=${RABBITMQ_USER}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
networks:
weni:
external: true
Loading

0 comments on commit 4321b88

Please sign in to comment.