Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Version 0.2.0
  • Loading branch information
Josh Lospinoso committed Nov 1, 2015
1 parent 1b88e10 commit c244438
Show file tree
Hide file tree
Showing 35 changed files with 781 additions and 43 deletions.
4 changes: 2 additions & 2 deletions build.gradle
@@ -1,8 +1,8 @@
apply plugin:'java'
apply plugin:'groovy'

version = '0.1.0'
description = 'MMS batch service'
version = '0.2.0'
description = 'A multimedia message and email batch service'

task wrapper(type: Wrapper) {
gradleVersion = '2.6'
Expand Down
3 changes: 3 additions & 0 deletions config.json
Expand Up @@ -3,6 +3,9 @@
"subscribers": [
"5551234567"
],
"emailSubscribers": [
"dailyc@lospi.net"
],
"messages": [
"Hello world!",
"Foo!"
Expand Down
1 change: 1 addition & 0 deletions dailyc-core/build.gradle
Expand Up @@ -19,6 +19,7 @@ repositories {

dependencies {
compile project(':mogreet')
compile project(':dailyc-mail')
compile ('org.springframework.boot:spring-boot-starter-actuator',
'org.codehaus.groovy:groovy-all:2.4.+',
'org.springframework:spring-context:4.+',
Expand Down
Expand Up @@ -2,12 +2,17 @@ package net.lospi.dailyc

import groovy.json.JsonSlurper
import groovy.util.logging.Slf4j
import net.lospi.dailyc.comm.MailSender
import net.lospi.dailyc.comm.MogreetSender
import net.lospi.dailyc.comm.MogreetSubscriber
import net.lospi.dailyc.comm.MogreetUploader
import net.lospi.dailyc.persistence.BatchLoader
import net.lospi.dailyc.persistence.Dao
import net.lospi.dailyc.util.Hasher
import net.lospi.mail.core.EmailSendResponseFactory
import net.lospi.mail.MailManager
import net.lospi.mail.multipart.JpegDataSourceFactory
import net.lospi.mail.multipart.MultipartMailFactory
import net.lospi.mogreet.MogreetManager
import net.lospi.mogreet.core.AuthorizationToken
import net.lospi.mogreet.core.BaseResponse
Expand Down Expand Up @@ -55,11 +60,27 @@ class DailycConfiguration {
private String databaseUsername
@Value('${database.password}')
private String databasePassword
@Value('${email.userName}')
private String emailUserName
@Value('${email.password}')
private String emailPassword
@Value('${email.hostName}')
private String emailHostName
@Value('${email.sslSmtpPort}')
private String sslSmtpPort
@Value('${email.attachmentName}')
private String emailAttachmentName
@Value('${email.fromName}')
private String emailFromName
@Value('${email.toName}')
private String emailToName
@Value('${email.from}')
private String emailFrom

@Bean
public DataSource dataSource() {
new DriverManagerDataSource( driverClassName:databaseDriver, url:databaseUrl, username:databaseUsername,
password:databasePassword )
new DriverManagerDataSource(driverClassName:databaseDriver, url:databaseUrl, username:databaseUsername,
password:databasePassword)
}

@Bean
Expand Down Expand Up @@ -88,6 +109,16 @@ class DailycConfiguration {
getRequestEncoder, postRequestEncoder)
}

@Bean
public MailManager mailManager() {
MultipartMailFactory multipartMailFactory = new MultipartMailFactory()
EmailSendResponseFactory emailSendResponseFactory = new EmailSendResponseFactory()
JpegDataSourceFactory jpegDataSourceFactory = new JpegDataSourceFactory()
return new MailManager(emailUserName, emailPassword, emailHostName, sslSmtpPort,
emailAttachmentName, emailFromName,
emailToName, multipartMailFactory, emailSendResponseFactory, jpegDataSourceFactory)
}

@Bean
DailycManager dailycBatch() {
File configFile = new File(configPath)
Expand All @@ -99,8 +130,11 @@ class DailycConfiguration {
MogreetSender sender = new MogreetSender(manager: manager, campaignId: campaignId, from: from)
MogreetSubscriber subscriber = new MogreetSubscriber(manager: manager, campaignId: campaignId)
MogreetUploader mogreetUploader = new MogreetUploader(manager: manager)
MailManager mailManager = mailManager()
MailSender mailSender = new MailSender(from: emailFrom, mailManager: mailManager)
new DailycManager(mogreetSender: sender, mogreetSubscriber: subscriber,
mogreetUploader: mogreetUploader, dao: dao, batchLoader: batchLoader)
mogreetUploader: mogreetUploader, dao: dao,
batchLoader: batchLoader, mailSender: mailSender)
}

private AuthorizationToken makeToken() throws IOException {
Expand Down
69 changes: 52 additions & 17 deletions dailyc-core/src/main/groovy/net/lospi/dailyc/DailycManager.groovy
@@ -1,18 +1,22 @@
package net.lospi.dailyc

import groovy.util.logging.Slf4j
import net.lospi.dailyc.comm.MailSender
import net.lospi.dailyc.comm.MogreetSender
import net.lospi.dailyc.comm.MogreetSubscriber
import net.lospi.dailyc.comm.MogreetUploader
import net.lospi.dailyc.core.EmailSubscriber
import net.lospi.dailyc.core.ImageFile
import net.lospi.dailyc.core.MessageBody
import net.lospi.dailyc.core.Subscriber
import net.lospi.dailyc.persistence.BatchLoader
import net.lospi.dailyc.persistence.Dao
import net.lospi.mail.MailManager
import net.lospi.mogreet.core.UploadResponse

@Slf4j
class DailycManager implements Runnable {
MailSender mailSender
MogreetSender mogreetSender
MogreetSubscriber mogreetSubscriber
MogreetUploader mogreetUploader
Expand All @@ -30,39 +34,48 @@ class DailycManager implements Runnable {
log.info("[+] Loaded {} messages from disk", messages.size())
def nMessages = dao.loadMessages(messages).size()
log.info("[+] {} messages updated", nMessages)
log.debug("[ ] Updating subscribers")
log.debug("[ ] Updating MMS subscribers")
def subscribers = batchLoader.subscribers
log.info("[+] Loaded {} subscribers from disk", subscribers.size())
log.info("[+] Loaded {} MMS subscribers from disk", subscribers.size())
def nSubscribers = dao.loadSubscribers(subscribers).size()
log.info("[+] {} subscribers updated", nSubscribers)
log.info("[+] {} MMS subscribers updated", nSubscribers)
log.debug("[ ] Updating email subscribers")
def emailSubscribers = batchLoader.emailSubscribers
log.info("[+] Loaded {} email subscribers from disk", emailSubscribers.size())
def nEmailSubscribers = dao.loadEmailSubscribers(emailSubscribers).size()
log.info("[+] {} email subscribers updated", nEmailSubscribers)
def nextMessage = dao.nextMessageBody()
def nextImage = dao.nextImageFile()
log.info("[ ] Next message: {}", nextMessage.contents)
log.info("[ ] Next image: {}", nextImage.name)
if(nextMessage.lastUse)
log.warn("[-] Next message has been used previously: {}", nextMessage.lastUse)
if(nextImage.lastUse)
log.warn("[-] Previous message has been used previously: {}", nextImage.lastUse)
log.warn("[-] Next image has been used previously: {}", nextImage.lastUse)
}

void run() {
def selectedFile = dao.nextImageFile()
def selectedMessage = dao.nextMessageBody()
def subscribers = dao.getSubscribers()
def emailSubscribers = dao.getEmailSubscribers()

validateInput(selectedMessage, selectedFile, subscribers)
validateInput(selectedMessage, selectedFile, subscribers, emailSubscribers)
String contentId = uploadContent(selectedFile)
int messagesSuccessful = sendMessages(subscribers, selectedMessage, selectedFile, contentId)
reportOnBatchSuccess(messagesSuccessful, subscribers)
int mmsSuccessful = sendMms(subscribers, selectedMessage, selectedFile, contentId)
int emailSuccessful = sendEmail(emailSubscribers, selectedMessage, selectedFile)
reportOnBatchSuccess(mmsSuccessful, emailSuccessful, subscribers, emailSubscribers)
}

private void reportOnBatchSuccess(int messagesSuccessful, List<Subscriber> numbers) {
if (messagesSuccessful == numbers.size()) {
private void reportOnBatchSuccess(int mmsSuccessful, int emailSuccessful,
List<Subscriber> numbers, List<EmailSubscriber> emails) {
def numberRequested = numbers.size() + emails.size()
def numberSuccessful = mmsSuccessful + emailSuccessful;
if (numberRequested == numberSuccessful) {
log.info("[+] Batch completed with all messages sent successfully.")
} else {
def numberFailed = numbers.size() - messagesSuccessful
log.error("[-] Batch completed with {} of {} messages sent successfully.", messagesSuccessful, numbers.size())
throw new RuntimeException(String.format("%d messages failed to send", numberFailed))
log.error("[-] Batch completed with {} of {} messages sent successfully.", numberSuccessful, numberRequested)
throw new RuntimeException(String.format("%d messages failed to send", numberRequested - numberSuccessful))
}
}

Expand All @@ -84,19 +97,22 @@ class DailycManager implements Runnable {
contentId
}

private void validateInput(selectedMessage, selectedFile, numbers) {
private void validateInput(selectedMessage, selectedFile, numbers, emails) {
if (!selectedMessage)
throw new RuntimeException("MessageBodyGenerator returned null message.")
if (!selectedFile)
throw new RuntimeException("ImageFileGenerator returned null ImageFile.")
if (numbers.size() == 0)
throw new RuntimeException("SubscriberGenerator returned no numbers.")
if (emails.size() == 0)
throw new RuntimeException("EmailSubscriberGenerator returned no numbers.")
log.info("[+] Selected message: \"{}\"", selectedMessage)
log.info("[+] Selected file: {}", selectedFile)
log.info("[+] {} subscribers.", numbers.size())
log.info("[+] {} MMS subscribers.", numbers.size())
log.info("[+] {} email subscribers.", numbers.size())
}

private int sendMessages(List<Subscriber> subscribers, MessageBody messageBody, ImageFile imageFile,
private int sendMms(List<Subscriber> subscribers, MessageBody messageBody, ImageFile imageFile,
String contentId) {
return subscribers.count{ subscriber ->
try {
Expand All @@ -107,11 +123,30 @@ class DailycManager implements Runnable {
def mms = dao.createSentMms(subscriber, messageBody, imageFile, date)
log.info("[+] Sent MMS \n{}", mms)
} else {
log.error("[-] Not sent to {}:\n{}\n{}", subscriber, subscribeResponse, sendResponse)
log.error("[-] MMS not sent to {}:\n{}\n{}", subscriber, subscribeResponse, sendResponse)
}
return sendResponse.successful
} catch (any) {
log.error("[-] Could not subscribe/send to {}:\n", subscriber, any.toString())
log.error("[-] Could not subscribe/send to {}: {}\n", subscriber, any.toString())
return false
}
}
}

private int sendEmail(List<EmailSubscriber> emailSubscribers, MessageBody messageBody, ImageFile imageFile) {
return emailSubscribers.count{ subscriber ->
try {
def sendResponse = mailSender.send(subscriber, messageBody, imageFile)
if (sendResponse.successful) {
Date date = new Date()
def email = dao.createSentEmail(subscriber, messageBody, imageFile, date)
log.info("[+] Sent email \n{}", email)
} else {
log.error("[-] Email not sent to {}:\n{}", subscriber, sendResponse)
}
return sendResponse.successful
} catch (any) {
log.error("[-] Could not send to {}: {}\n", subscriber, any.toString())
return false
}
}
Expand Down
@@ -0,0 +1,25 @@
package net.lospi.dailyc.comm

import groovy.util.logging.Slf4j
import net.lospi.dailyc.core.EmailSubscriber
import net.lospi.dailyc.core.ImageFile
import net.lospi.dailyc.core.MessageBody
import net.lospi.mail.MailManager
import net.lospi.mail.core.EmailSendRequest

@Slf4j
class MailSender {
MailManager mailManager
String from

def send(EmailSubscriber emailSubscriber, MessageBody messageBody, ImageFile imageFile) {
log.info("[ ] Sending image {} to email {}; message: {}", imageFile, emailSubscriber, messageBody)
def request = new EmailSendRequest(emailSubscriber.address, from, messageBody.contents, imageFile.image)
def result = mailManager.send(request)
if(result.successful)
log.info("[+] Success! Response from mail server: {}", result.messageResponse)
else
log.error("[-] Failure! Response from mail server: %n{}", result.messageResponse)
return result
}
}
@@ -1,6 +1,7 @@
package net.lospi.dailyc.comm

import groovy.util.logging.Slf4j
import net.lospi.dailyc.core.EmailSubscriber
import net.lospi.dailyc.core.MessageBody
import net.lospi.dailyc.core.Subscriber
import net.lospi.mogreet.MogreetManager
Expand Down
@@ -0,0 +1,28 @@
package net.lospi.dailyc.core

import grails.persistence.Entity

@Entity
class EmailSubscriber {
String address
Date lastUse

static hasMany = [
sentEmail : SentEmail
]

static constraints = {
lastUse(nullable: true)
}

@Override
public String toString() {
return """\
EmailSubscriber{
id=$id,
address='$address',
lastUse=$lastUse,
version=$version
}"""
}
}
@@ -0,0 +1,4 @@
package net.lospi.dailyc.core

class NoEmailSubscribersException {
}
22 changes: 22 additions & 0 deletions dailyc-core/src/main/groovy/net/lospi/dailyc/core/SentEmail.groovy
@@ -0,0 +1,22 @@
package net.lospi.dailyc.core

import grails.persistence.Entity

@Entity
class SentEmail {
EmailSubscriber emailSubscriber
MessageBody messageBody
ImageFile imageFile
Date sentDate

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("SentEmail{");
sb.append("emailSubscriber=").append(emailSubscriber);
sb.append(", messageBody=").append(messageBody);
sb.append(", imageFile=").append(imageFile);
sb.append(", sentDate=").append(sentDate);
sb.append('}');
return sb.toString();
}
}
Expand Up @@ -20,6 +20,10 @@ class BatchLoader {
(List<String>) getKey("subscribers")
}

List<String> getEmailSubscribers() {
(List<String>) getKey("emailSubscribers")
}

private File getKeyFile(String key) {
String path = getKey(key)
File file = new File(path)
Expand Down
Expand Up @@ -8,6 +8,10 @@ import net.lospi.dailyc.util.Hasher
class Dao {
Hasher hasher

List<EmailSubscriber> loadEmailSubscribers(List<String> emailSubscribers) {
emailSubscribers.collect{EmailSubscriber.findOrSaveByAddress(it)}
}

List<Subscriber> loadSubscribers(List<String> subscribers) {
subscribers.collect{Subscriber.findOrSaveByNumber(it)}
}
Expand Down Expand Up @@ -49,6 +53,13 @@ class Dao {
subscribers
}

List<Subscriber> getEmailSubscribers() {
def emailSubscribers = EmailSubscriber.getAll()
if(emailSubscribers.size() == 0)
throw new NoSubscribersException()
emailSubscribers
}

SentMms createSentMms(Subscriber subscriber, MessageBody messageBody, ImageFile imageFile, Date sentDate) {
SentMms sentMms = new SentMms(subscriber: subscriber, messageBody: messageBody, imageFile: imageFile,
sentDate: sentDate)
Expand All @@ -60,4 +71,16 @@ class Dao {
imageFile.save()
sentMms.save()
}

SentEmail createSentEmail(EmailSubscriber emailSubscriber, MessageBody messageBody, ImageFile imageFile, Date sentDate) {
SentEmail sentMms = new SentEmail(emailSubscriber: emailSubscriber, messageBody: messageBody, imageFile: imageFile,
sentDate: sentDate)
emailSubscriber.lastUse = sentDate
messageBody.lastUse = sentDate
imageFile.lastUse = sentDate
emailSubscriber.save()
messageBody.save()
imageFile.save()
sentMms.save()
}
}

0 comments on commit c244438

Please sign in to comment.