Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Sms Alert System for Scala
[![Build Status](https://travis-ci.org/ColectivaLegal/ScalaSmsAlertSystem.svg?branch=master)](https://travis-ci.org/ColectivaLegal/ScalaSmsAlertSystem)

Below you will find basic setup instructions for developing the SysmAlertSystem.
Below you will find basic setup instructions for developing the SysmAlertSystem.

To begin with, please ensure you have the following installed on your local development system:
* JDK 8
* [SBT](http://www.scala-sbt.org/download.html)

JDK8 is currently required due to some incompatibilities between SBT's ivy implementation and JDK9
JDK8 is currently required due to some incompatibilities between SBT's ivy implementation and JDK9

## Twilio Setup

Expand Down Expand Up @@ -45,6 +45,8 @@ export TWILIO_USERNAME="..."
export TWILIO_PASSWORD="..."
# the phone number you created
export TWILIO_PHONE="..."
# your Google Maps geocoding API key
export MAPS_API_KEY="..."
sbt run
```

Expand Down
19 changes: 17 additions & 2 deletions app/controllers/AlertController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers

import javax.inject.{Inject, Singleton}

import models.{Address, Alert}
import models.SubscriberRepository
import play.api.data.Form
import play.api.data.Forms._
Expand All @@ -18,7 +19,7 @@ class AlertController @Inject()(cc: ControllerComponents, repo: SubscriberReposi
val alertForm = Form(
mapping(
"address" -> nonEmptyText
)(models.Alert.apply)(models.Alert.unapply)
)(Alert.apply)(Alert.unapply)
)
def get = Action { implicit request =>
Ok(views.html.alert(alertForm))
Expand All @@ -30,8 +31,22 @@ class AlertController @Inject()(cc: ControllerComponents, repo: SubscriberReposi
Future.successful(BadRequest(views.html.alert(formWithErrors)))
},
alert => {
val addresses = Address.geocode(alert.address)
if (addresses.length == 0) {
// TODO (benweedon 11/11/2017): Build in a mechanism for users to
// retry if no address match was found.
throw new IllegalArgumentException("no matching addresses found")
} else if (addresses.length > 1) {
// TODO (benweedon 11/11/2017): Build in a mechanism for users to
// validate which of the potential addresses they intended.
throw new IllegalArgumentException("the address entered was ambiguous")
}
// TODO (benweedon 11/11/2017): Find a better way to do this than
// defining a new alert. Perhaps, for example, the form should just
// produce an address string, rather than an alert object.
val alertToSend = Alert(addresses.head.toString)
repo.listActive().map { subscribers =>
val messages = alert.sendAlert(subscribers, messagesApi)
val messages = alertToSend.sendAlert(subscribers, messagesApi)
Redirect(routes.HomeController.index())
.flashing("success" -> ("Done! Messages sent with IDs " + messages.map(_.getSid()).mkString(",")))
}
Expand Down
14 changes: 12 additions & 2 deletions app/controllers/TwilioController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package controllers
import javax.inject.{Inject, Singleton}

import com.twilio.twiml.{Body, Message, MessagingResponse}
import models.{Alert}
import models.{Address, Alert}
import models.{SubscriberAction, AlertAction}
import models.{SubscriberRepository, SubscriberTransitions}
import play.api.data.Form
Expand Down Expand Up @@ -51,7 +51,17 @@ class TwilioController @Inject()(cc: ControllerComponents, repo: SubscriberRepos
def performAction(action: SubscriberAction) = {
action match {
case AlertAction(addr) =>
val alert = Alert(addr)
val addresses = Address.geocode(addr)
if (addresses.length == 0) {
// TODO (benweedon 11/11/2017): Build in a mechanism for users to
// retry if no address match was found.
throw new IllegalArgumentException("no matching addresses found")
} else if (addresses.length > 1) {
// TODO (benweedon 11/11/2017): Build in a mechanism for users to
// validate which of the potential addresses they intended.
throw new IllegalArgumentException("the address entered was ambiguous")
}
val alert = Alert(addresses.head.toString)
repo.listActive().map { subscribers =>
alert.sendAlert(subscribers, messagesApi)
}
Expand Down
23 changes: 23 additions & 0 deletions app/models/Address.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package models

import scala.collection.mutable.ListBuffer

import com.google.maps.{GeoApiContext, GeocodingApi}
import com.google.maps.model.GeocodingResult

case class Address(address: String, lat: Double, lng: Double) {
override def toString = address
}

object Address {
private val _context = new GeoApiContext.Builder().apiKey(sys.env("MAPS_API_KEY")).build();

def geocode(address: String) = {
val results = GeocodingApi.geocode(_context, address).await()
var addresses = new ListBuffer[Address]()
for (result <- results) {
addresses += Address(result.formattedAddress, result.geometry.location.lat, result.geometry.location.lng)
}
addresses.to[List]
}
}
16 changes: 9 additions & 7 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name := "SmsAlertSystemV2"
version := "1.0"

version := "1.0"

lazy val `smsalertsystemv2` = (project in file(".")).enablePlugins(PlayScala)

resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases"

resolvers += "Akka Snapshot Repository" at "http://repo.akka.io/snapshots/"

scalaVersion := "2.12.2"

libraryDependencies ++= Seq(
Expand All @@ -20,5 +20,7 @@ libraryDependencies ++= Seq(
"com.typesafe.play" %% "play-slick-evolutions" % "3.0.2",
"com.h2database" % "h2" % "1.4.194",
"com.typesafe.akka" %% "akka-testkit" % "2.5.4" % "test",
"org.scalatest" %% "scalatest" % "3.0.4" % "test"
)
"org.scalatest" %% "scalatest" % "3.0.4" % "test",
"com.google.maps" % "google-maps-services" % "0.2.4",
"org.slf4j" % "slf4j-nop" % "1.7.25" // needed for com.google.maps
)