package cc.blynk.server.core.processors;
import cc.blynk.server.core.BlockingIOProcessor;
import cc.blynk.server.core.model.DashBoard;
import cc.blynk.server.core.model.auth.Session;
import cc.blynk.server.core.model.enums.PinType;
import cc.blynk.server.core.model.widgets.notifications.Notification;
import cc.blynk.server.core.model.widgets.notifications.Twitter;
import cc.blynk.server.core.model.widgets.others.eventor.Eventor;
import cc.blynk.server.core.model.widgets.others.eventor.Rule;
import cc.blynk.server.core.model.widgets.others.eventor.model.action.BaseAction;
import cc.blynk.server.core.model.widgets.others.eventor.model.action.SetPinAction;
import cc.blynk.server.core.model.widgets.others.eventor.model.action.notification.MailAction;
import cc.blynk.server.core.model.widgets.others.eventor.model.action.notification.NotificationAction;
import cc.blynk.server.core.model.widgets.others.eventor.model.action.notification.NotifyAction;
import cc.blynk.server.core.model.widgets.others.eventor.model.action.notification.TwitAction;
import cc.blynk.server.core.stats.GlobalStats;
import cc.blynk.server.notifications.push.GCMWrapper;
import cc.blynk.server.notifications.twitter.TwitterWrapper;
import cc.blynk.utils.NumberUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import static cc.blynk.server.core.protocol.enums.Command.EVENTOR;
import static cc.blynk.server.core.protocol.enums.Command.HARDWARE;
import static cc.blynk.utils.StringUtils.PIN_PATTERN;
/**
* Class responsible for handling eventor logic.
*
* The Blynk Project.
* Created by Dmitriy Dumanskiy.
* Created on 24.08.16.
*/
public class EventorProcessor {
private static final Logger log = LogManager.getLogger(EventorProcessor.class);
private final GCMWrapper gcmWrapper;
private final TwitterWrapper twitterWrapper;
private final BlockingIOProcessor blockingIOProcessor;
private final GlobalStats globalStats;
public EventorProcessor(GCMWrapper gcmWrapper, TwitterWrapper twitterWrapper, BlockingIOProcessor blockingIOProcessor, GlobalStats stats) {
this.gcmWrapper = gcmWrapper;
this.twitterWrapper = twitterWrapper;
this.blockingIOProcessor = blockingIOProcessor;
this.globalStats = stats;
}
public void process(Session session, DashBoard dash, int deviceId, byte pin, PinType type, String triggerValue, long now) {
Eventor eventor = dash.getWidgetByType(Eventor.class);
if (eventor == null || eventor.rules == null || eventor.deviceId != deviceId) {
return;
}
double valueParsed = NumberUtil.parseDouble(triggerValue);
if (valueParsed == NumberUtil.NO_RESULT) {
return;
}
for (Rule rule : eventor.rules) {
if (rule.isReady(pin, type)) {
if (rule.isValid(valueParsed)) {
if (!rule.isProcessed) {
for (BaseAction action : rule.actions) {
if (action.isValid()) {
if (action instanceof SetPinAction) {
execute(session, dash, deviceId, (SetPinAction) action, now);
} else if (action instanceof NotificationAction) {
execute(dash, triggerValue, (NotificationAction) action);
}
}
}
rule.isProcessed = true;
}
} else {
rule.isProcessed = false;
}
}
}
}
private void execute(DashBoard dash, String triggerValue, NotificationAction notificationAction) {
String body = PIN_PATTERN.matcher(notificationAction.message).replaceAll(triggerValue);
if (notificationAction instanceof NotifyAction) {
push(gcmWrapper, dash, body);
} else if (notificationAction instanceof TwitAction) {
twit(dash, body);
} else if (notificationAction instanceof MailAction) {
//email(dash, body);
}
globalStats.mark(EVENTOR);
}
private void twit(DashBoard dash, String body) {
if (Twitter.isWrongBody(body)) {
log.debug("Wrong twit body.");
return;
}
Twitter twitterWidget = dash.getWidgetByType(Twitter.class);
if (twitterWidget == null || !dash.isActive ||
twitterWidget.token == null || twitterWidget.token.isEmpty() ||
twitterWidget.secret == null || twitterWidget.secret.isEmpty()) {
log.debug("User has no access token provided for eventor twitting.");
return;
}
blockingIOProcessor.execute(() -> {
try {
twitterWrapper.send(twitterWidget.token, twitterWidget.secret, body);
} catch (Exception e) {
String errorMessage = e.getMessage();
if (errorMessage != null && errorMessage.contains("Eventor. Status is a duplicate")) {
log.warn("Error sending twit. Reason : {}", e.getMessage());
}
}
});
}
public static void push(GCMWrapper gcmWrapper, DashBoard dash, String body) {
if (Notification.isWrongBody(body)) {
log.debug("Wrong push body.");
return;
}
if (!dash.isActive) {
log.debug("Project not active.");
return;
}
Notification widget = dash.getWidgetByType(Notification.class);
if (widget == null || widget.hasNoToken()) {
log.debug("User has no access token provided for eventor push.");
return;
}
widget.push(gcmWrapper, body, dash.id);
}
private void execute(Session session, DashBoard dash, int deviceId, SetPinAction action, long now) {
final String body = action.makeHardwareBody();
session.sendMessageToHardware(dash.id, HARDWARE, 888, body, deviceId);
if (dash.isActive) {
session.sendToApps(HARDWARE, 888, dash.id, deviceId, body);
}
dash.update(deviceId, action.pin.pin, action.pin.pinType, action.value, now);
globalStats.mark(EVENTOR);
}
}