com.textrecruit.ustack.main.UNotificationSvc Maven / Gradle / Ivy
The newest version!
package com.textrecruit.ustack.main;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.textrecruit.ustack.data.*;
import com.textrecruit.ustack.util.BasicUtils;
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import java.io.*;
import java.net.URI;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.*;
public class UNotificationSvc {
protected static Logger logger = Logger.getLogger(UNotificationSvc.class);
private boolean testMode;
private Hashtable supportingData;
private Hashtable attachments;
private List skips;
public static void main(String[] args) throws Exception {
if (args.length < 5)
{
System.err.println("Usage: com.textrecruit.ustack.main.UNotificationSvc -addpushqueue [appname] [queuename] [filename] [password]");
return;
}
if (args[0].equalsIgnoreCase("-addpushqueue"))
{
UOpts.setAppName(args[1]);
PushQueueInstance pushQ = PushQueueInstance.createKeyStore(args[2], new FileInputStream(args[3]), args[4]);
pushQ.save("System");
}
}
public UNotificationSvc()
{
this.attachments = new Hashtable();
this.supportingData = new Hashtable();
this.skips = new Vector();
}
public static KeyStore loadKeystore(InputStream keystoreStream, char[] password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore keyStore;
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(keystoreStream, password);
return keyStore;
}
/**
* A skip will tell the notification to run all the notifications except those that match in the parameters provided.
*
* Example:
*
* A site has 3 users subscribed to it's new.document notification event
*
* User #1 of the site initiated the new.document so he/she doesn't need to be alerted
*
* To do this, add user #1 to the skip list.
*
*
* SiteId's are also supported
*
* @param skip
*/
public void addSkip(String skip)
{
if (skip == null)
return;
skips.add(skip);
}
/**
* Sets an attachment. The provided name is used to name the file
* @param name
* @param location
* @return
*/
public UNotificationSvc setAttachment(String name, File location) {
if (name == null)
return this;
if (location == null)
attachments.remove(name);
else
attachments.put(name, location);
return this;
}
/** Set objects for use in the template */
public UNotificationSvc setData(String name, DBObject data)
{
if (name == null)
return this;
if (data == null)
supportingData.remove(name);
else
supportingData.put(name, data);
return this;
}
public void setTestMode(boolean mode)
{
testMode = mode;
}
/** Execute Notifications */
public int notify(String eventName, DBObject search)
{
int alertsSent = 0;
NotificationTemplate template = NotificationTemplate.getNotificationTemplate(eventName);
if (template == null)
return -1;
List notiList = NotificationInst.getNotifications(eventName, search);
for (NotificationInst notif : notiList)
{
BasicDBList recvTypes = notif.getTypeList();
for (int i = 0; i < recvTypes.size(); i++)
{
DBObject type = (DBObject)recvTypes.get(i);
// check if the template has the same type (or name)
DBObject templateTypeCheck = template.getType( (String)type.get("name") );
if (templateTypeCheck != null)
{
// send the actual notification
if (sendNotification(notif, template, type))
alertsSent++;
}
else
logger.warn(notif.getNotificationId() + " has template type '" + type.get("name") + "' but the template (" + eventName + ") does not.");
}
}
return alertsSent;
}
/**
* Actually send the notification - by known type then by an interface
* @param template
*/
private boolean sendNotification(NotificationInst notif, NotificationTemplate template, DBObject endpointConfig)
{
String type = (String)endpointConfig.get("name");
for (String skip : skips)
{
if (skip.equalsIgnoreCase((String)endpointConfig.get("userName")))
{
logger.info("Skipping Notification for user '" + skip + "' <- Configured");
return false;
}
else if (skip.equalsIgnoreCase((String)endpointConfig.get("siteId")))
{
logger.info("Skipping Notification for site id '" + skip + "' <- Configured");
return false;
}
}
if ("email".equalsIgnoreCase(type))
return sendEmail(notif, template, endpointConfig);
else if ("sms".equalsIgnoreCase(type))
return sendSMS(notif, template, endpointConfig);
else if ("facebook".equalsIgnoreCase(type))
return sendFacebook(notif, template, endpointConfig);
else
{
// TODO: Implement custom interface
logger.warn("Unknown template type '" + type + "'");
}
return false;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public boolean sendFacebook(NotificationInst notif, NotificationTemplate template, DBObject endpointConfig)
{
if (notif != null && notif.get("invalid") != null)
{
logger.info("Skipping Facebook Delivery for notification id [" + notif.getNotificationId() + "] => Reason: " + notif.get("invalid"));
return false;
}
DBObject templ = template.getType("facebook");
if (templ == null)
{
if (notif == null)
return false;
logger.info("Unknown template type [facebook] for notification id [" + notif.getNotificationId() + "]");
return false;
}
DefaultHttpClient client = null;
try {
String alert = processTemplate( (String)templ.get("templateText"), notif );
String destination = (String)endpointConfig.get("destination");
if (destination == null && templ.get("postTo") != null)
destination = processTemplate( (String)templ.get("postTo"), notif);
if (destination == null)
destination = "me";
String token = (String)endpointConfig.get("token");
// message=Play%20me%20in%20TWF%20now!&name=Join%20Now&caption=TWF&description=TWF%20Login&link=http://google.com?uid=1234
List qparams = new ArrayList();
qparams.add(new BasicNameValuePair("message", alert));
qparams.add(new BasicNameValuePair("name", (String)templ.get("linkName") ));
qparams.add(new BasicNameValuePair("caption", (String)templ.get("caption") ));
qparams.add(new BasicNameValuePair("description", (String)templ.get("description") ));
qparams.add(new BasicNameValuePair("link", processTemplate((String)templ.get("link"), notif) ));
qparams.add(new BasicNameValuePair("picture", (String)templ.get("picture") ));
qparams.add(new BasicNameValuePair("access_token", token));
URI uri = URIUtils.createURI("https", "graph.facebook.com", 443, "/" + destination + "/feed", null, null);
logger.info("URL: " + uri);
client = new DefaultHttpClient();
HttpPost post = new HttpPost(uri);
post.setEntity(new UrlEncodedFormEntity(qparams)); // setup parameters
HttpResponse response = client.execute(post);
qparams.clear();
if (response.getStatusLine().getStatusCode() == 200)
return true;
HttpEntity e = response.getEntity();
Writer writer = BasicUtils.getResponseString(e);
if (writer.toString().indexOf("Session has expired at unix time") > -1)
{
}
else
{
logger.error("Response Specifics: " + writer.toString());
if (notif != null)
notif.disable("Invalid response from Facebook API");
}
} catch (Exception er) {
logger.warn("Failed to deliver notification to Facebook", er);
close(client);
return false;
} finally {
close(client);
}
return true;
}
private void close(DefaultHttpClient client)
{
if (client == null)
return;
try {
client.getConnectionManager().shutdown();
} catch (Exception e) {}
}
/** Send an Email */
public boolean sendEmail(NotificationInst notif, NotificationTemplate template, DBObject endpointConfig)
{
DBObject typeData = template.getType("email");
// String emailToName = (String)endpointConfig.get("destinationName");
String emailToAddr = (String)endpointConfig.get("destination");
String emailFromName = processTemplate( (String)typeData.get("fromName"), notif );
String emailFromAddr = processTemplate( (String)typeData.get("fromAddress"), notif );
String subject = processTemplate( (String)typeData.get("subject"), notif );
EmailLog log = EmailLog.logEmail(emailToAddr, emailFromName, emailFromAddr, subject);
supportingData.put("email", new BasicDBObject("id", log.get("_id") + ""));
String emailBody = processTemplate( (String)typeData.get("templateText"), notif );
String campaignId = null;
boolean transactional = false;
if (typeData.get("campaignId") != null)
campaignId = processTemplate( (String)typeData.get("campaignId"), notif );
if (typeData.get("transactional") != null)
transactional = (Boolean)typeData.get("transactional");
String htmlEmailBody = null;
if (typeData.get("htmlTemplateText") != null)
htmlEmailBody = processTemplate( (String)typeData.get("htmlTemplateText"), notif );
InternetAddress[] ccArray = null;
if (typeData.get("cc") != null)
{
List ccList = new ArrayList();
String cc = processTemplate( (String)typeData.get("bcc"), notif );
String[] ccAddrs = cc.split(",");
for (String ccAddr : ccAddrs)
try { ccList.add(new InternetAddress(ccAddr)); } catch (AddressException ae) {}
if (ccList.size() > 0)
{
ccArray = new InternetAddress[ccList.size()];
ccList.toArray(ccArray);
}
}
InternetAddress[] bccArray = null;
if (typeData.get("bcc") != null)
{
List bccList = new ArrayList();
String bcc = processTemplate( (String)typeData.get("bcc"), notif );
String[] bccAddrs = bcc.split(",");
for (String bccAddr : bccAddrs)
try { bccList.add(new InternetAddress(bccAddr)); } catch (AddressException ae) {}
if (bccList.size() > 0)
{
bccArray = new InternetAddress[bccList.size()];
bccList.toArray(bccArray);
}
}
if (emailToAddr == null)
{
logger.warn("Invalid Email Destination (null): " + notif);
return false;
}
if (testMode)
logger.info("TESTMODE ==> From: " + emailFromAddr + " | To: " + emailToAddr + " | Subj: " + subject + " ==> " + emailBody);
else
{
boolean uns = Unsubscribe.getByEmail(emailToAddr);
if (uns)
{
log.put("unsubscribed", true);
EmailLog.save(log, "NotificationSvc");
logger.info(String.format("%s is on the unsubscribe list, ignoring [Skipped Email ID: %s]", emailToAddr, log.get("_id") + ""));
return false;
}
try {
Emailer.postMail(new InternetAddress[] { new InternetAddress(emailToAddr) }, null, bccArray, emailFromAddr, emailFromName, subject, emailBody, htmlEmailBody, attachments, campaignId, transactional);
} catch (AddressException err) {
logger.error("Invalid Address : " + err);
return false;
}
}
return true;
}
/**
* Clears out spaces and dashes from a phone number.
* @param toPhone
* @return
*/
public static String trimPhoneNumber(String toPhone) {
if (toPhone == null)
return null;
toPhone = toPhone.replaceAll(" ", "");
toPhone = toPhone.replaceAll("-", "");
return toPhone;
}
/** Send an SMS */
public boolean sendSMS(NotificationInst notif, NotificationTemplate template, DBObject endpointConfig)
{
String smsMsg = processTemplate( (String)template.getType("sms").get("templateText"), notif );
String destination = (String)endpointConfig.get("destination");
String toPhone = destination;
try {
// open secure connection
TwilioRestClient client = new TwilioRestClient(UOpts.getProperty("EvenFlow.Twillio.APIKey"), UOpts.getProperty("EvenFlow.Twillio.APIAuthToken"), null);
toPhone = trimPhoneNumber(toPhone);
if (toPhone != null && toPhone.length() == 10 && !toPhone.startsWith("1"))
toPhone = "1" + toPhone;
if (toPhone != null && !toPhone.startsWith("+"))
toPhone = "+" + toPhone;
logger.info("Sending SMS [" + UOpts.getProperty("EvenFlow.Twillio.SMSPhoneNumber") + " => " + toPhone + "] // " + smsMsg + " via Twilio");
Map params = new HashMap();
params.put("From", UOpts.getProperty("EvenFlow.Twillio.SMSPhoneNumber"));
params.put("To", toPhone);
params.put("Body", smsMsg);
TwilioRestResponse response = client.request("/2010-04-01/Accounts/" + client.getAccountSid() + "/SMS/Messages", "POST", params);
if (response == null)
throw new Exception("Failed to send SMS via Twillio [To: " + toPhone + "]");
else if (response.isError())
throw new Exception("Failed to send SMS via Twillio [To: " + toPhone + "] -> " + response.getHttpStatus() + " // " + response.getResponseText());
logger.info("Twillio Response: " + response.getResponseText());
} catch (Exception er) {
// queue message?
logger.error("Failed to deliver SMS to [To: " + toPhone + "/" + destination + "]", er);
}
return true;
}
/** Process Template Text */
private String processTemplate(String text, DBObject other)
{
while (text != null && text.indexOf("${") > -1)
{
int start = text.indexOf("${");
int end = text.indexOf("}", start + 1);
String variable = text.substring(start + 2, end);
String varValue = "";
if (variable.indexOf(".") > -1)
{
String loca = variable.substring(0, variable.indexOf("."));
DBObject obj = supportingData.get(loca);
if (obj != null)
varValue = "" + obj.get( variable.substring(variable.indexOf(".") + 1) );
}
else if (other != null)
varValue = "" + other.get( variable );
if (varValue == null || "null".equalsIgnoreCase(varValue))
varValue = "";
String newValue = text.substring(0, start);
newValue += varValue;
newValue += text.substring(end + 1, text.length());
text = newValue;
}
return (text == null ? "" : text);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy