Skip to content

Commit

Permalink
[API] begin an api to send messages to arbitrary phone numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
ninsuo committed Aug 29, 2022
1 parent 52a29ec commit 7126a8c
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 3 deletions.
6 changes: 3 additions & 3 deletions deploy/prod/cron.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ cron:
schedule: every 1 hours

# * * * * * <path/to/the/project>/symfony/bin/console pegass:files
- description: "Sync volunteers with the Pegass database"
url: /cron/pegass-files
schedule: every 24 hours
#- description: "Sync volunteers with the Pegass database"
# url: /cron/pegass-files
# schedule: every 24 hours
94 changes: 94 additions & 0 deletions symfony/src/Controller/Api/MessageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace App\Controller\Api;

use App\Base\BaseController;
use App\Entity\Structure;
use App\Facade\Trigger\SimpleMessageRequestFacade;
use App\Facade\Trigger\SimpleMessageResponseFacade;
use App\Form\Model\Campaign;
use App\Form\Model\SmsTrigger;
use App\Form\Type\AudienceType;
use App\Manager\CampaignManager;
use App\Manager\PlatformConfigManager;
use App\Manager\VolunteerManager;
use Bundles\ApiBundle\Annotation\Endpoint;
use Bundles\ApiBundle\Annotation\Facade;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\Routing\Annotation\Route;

/**
* Send a message
*
* These endpoints are used to send messages to a given phone number.
*
* @Route("/api/message", name="api_admin_message_")
* @IsGranted("ROLE_ADMIN")
*/
class MessageController extends BaseController
{
/**
* @var VolunteerManager
*/
private $volunteerManager;

/**
* @var PlatformConfigManager
*/
private $platformManager;

/**
* @var CampaignManager
*/
private $campaignManager;

public function __construct(VolunteerManager $volunteerManager,
PlatformConfigManager $platformManager,
CampaignManager $campaignManager)
{
$this->volunteerManager = $volunteerManager;
$this->platformManager = $platformManager;
$this->campaignManager = $campaignManager;
}

/**
* Send an SMS to a given structure and its sub structures.
*
* @Endpoint(
* priority = 700,
* request = @Facade(class = SimpleMessageRequestFacade::class),
* response = @Facade(class = SimpleMessageResponseFacade::class)
* )
*
* @Route("/{structureExternalId}/simple-sms", methods={"POST"})
* @Entity("structure", expr="repository.findOneByExternalIdAndCurrentPlatform(structureExternalId)")
* @IsGranted("STRUCTURE", subject="structure")
*/
public function simpleSms(Structure $structure, SimpleMessageRequestFacade $request)
{
// User is trying to set trigger's ownership to a volunteer that is out of his/her scope
$volunteer = $this->volunteerManager->findOneByInternalEmail($request->getSenderInternalEmail());
if (!$this->isGranted('VOLUNTEER', $volunteer)) {
throw $this->createNotFoundException();
}

$trigger = new SmsTrigger();
$trigger->setLanguage($this->platformManager->getPlaform($this->getPlatform())->getDefaultLanguage()->getLocale());
$trigger->setAudience(AudienceType::createEmptyData([
'structures_global' => [$structure->getId()],
'badges_all' => true,
]));
$trigger->setMessage($request->getMessage());

$campaign = new Campaign($trigger);
$campaign->label = sprintf('SimpleSms API (%s)', $this->getUser()->getUserIdentifier());

$entity = $this->campaignManager->launchNewCampaign($campaign, null, $volunteer);

return new SimpleMessageResponseFacade(
count(($entity->getCommunications()[0] ?? [])->getMessages()),
sprintf('%s%s', getenv('WEBSITE_URL'), $this->generateUrl('communication_index', ['id' => $entity->getId()]))
);
}
}
151 changes: 151 additions & 0 deletions symfony/src/Entity/MessageToGuest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

namespace App\Entity;

use App\Repository\MessageToGuestRepository;
use Doctrine\ORM\Mapping as ORM;

/**
* Sometimes, we need to send messages to people that are not volunteers.
* Right now, the data structure doesn't allow it.
*
* This entity provides a way to store main information related to a message
* without needing a volunteer, a campaign, a communication and so on, but
* keeps billing information.
*
* @ORM\Entity(repositoryClass=MessageToGuestRepository::class)
*/
class MessageToGuest
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;

/**
* @ORM\Column(type="string", length=80)
*/
private $type;

/**
* @ORM\Column(type="string", length=255)
*/
private $destination;

/**
* @ORM\Column(type="text")
*/
private $body;

/**
* @ORM\Column(type="string", length=64, nullable=true)
*/
private $messageId;

/**
* @ORM\Column(type="string", length=16)
*/
private $cost;

/**
* @ORM\Column(type="string", length=3, nullable=true)
*/
private $currency;

/**
* @ORM\ManyToOne(targetEntity=Structure::class)
* @ORM\JoinColumn(nullable=false)
*/
private $structure;

public function getId(): ?int
{
return $this->id;
}

public function getType(): ?string
{
return $this->type;
}

public function setType(string $type): self
{
$this->type = $type;

return $this;
}

public function getDestination(): ?string
{
return $this->destination;
}

public function setDestination(string $destination): self
{
$this->destination = $destination;

return $this;
}

public function getBody(): ?string
{
return $this->body;
}

public function setBody(string $body): self
{
$this->body = $body;

return $this;
}

public function getMessageId(): ?string
{
return $this->messageId;
}

public function setMessageId(?string $messageId): self
{
$this->messageId = $messageId;

return $this;
}

public function getCost(): ?string
{
return $this->cost;
}

public function setCost(string $cost): self
{
$this->cost = $cost;

return $this;
}

public function getCurrency(): ?string
{
return $this->currency;
}

public function setCurrency(?string $currency): self
{
$this->currency = $currency;

return $this;
}

public function getStructure(): ?Structure
{
return $this->structure;
}

public function setStructure(?Structure $structure): self
{
$this->structure = $structure;

return $this;
}
}
76 changes: 76 additions & 0 deletions symfony/src/Repository/MessageToGuestRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace App\Repository;

use App\Entity\MessageToGuest;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Persistence\ManagerRegistry;

/**
* @method MessageToGuest|null find($id, $lockMode = null, $lockVersion = null)
* @method MessageToGuest|null findOneBy(array $criteria, array $orderBy = null)
* @method MessageToGuest[] findAll()
* @method MessageToGuest[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class MessageToGuestRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, MessageToGuest::class);
}

/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function add(MessageToGuest $entity, bool $flush = true): void
{
$this->_em->persist($entity);
if ($flush) {
$this->_em->flush();
}
}

/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function remove(MessageToGuest $entity, bool $flush = true): void
{
$this->_em->remove($entity);
if ($flush) {
$this->_em->flush();
}
}

// /**
// * @return MessageToGuest[] Returns an array of MessageToGuest objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('m')
->andWhere('m.exampleField = :val')
->setParameter('val', $value)
->orderBy('m.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/

/*
public function findOneBySomeField($value): ?MessageToGuest
{
return $this->createQueryBuilder('m')
->andWhere('m.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
2 changes: 2 additions & 0 deletions symfony/templates/new_communication/form_email.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

{{ form_row(form.multipleAnswer) }}

<br/>

<div class="h3">{{ 'form.communication.fields.preview'|trans }}</div>

{{ include('new_communication/preview.html.twig') }}
Expand Down
2 changes: 2 additions & 0 deletions symfony/templates/new_communication/form_sms.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@

{{ form_row(form.multipleAnswer) }}

<br/>

<div class="h3">{{ 'form.communication.fields.preview'|trans }}</div>

{{ include('new_communication/preview.html.twig') }}
Expand Down

0 comments on commit 7126a8c

Please sign in to comment.