package cc.blynk.server.hardware.handlers.hardware.logic;
import cc.blynk.server.core.BlockingIOProcessor;
import cc.blynk.server.core.model.DashBoard;
import cc.blynk.server.core.model.widgets.notifications.Twitter;
import cc.blynk.server.core.processors.NotificationBase;
import cc.blynk.server.core.protocol.exceptions.NotificationBodyInvalidException;
import cc.blynk.server.core.protocol.model.messages.StringMessage;
import cc.blynk.server.core.session.HardwareStateHolder;
import cc.blynk.server.notifications.twitter.TwitterWrapper;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import static cc.blynk.server.core.protocol.enums.Response.NOTIFICATION_ERROR;
import static cc.blynk.server.core.protocol.enums.Response.NOTIFICATION_NOT_AUTHORIZED;
import static cc.blynk.utils.BlynkByteBufUtil.makeResponse;
import static cc.blynk.utils.BlynkByteBufUtil.ok;
/**
* Sends tweets from hardware.
*
* The Blynk Project.
* Created by Dmitriy Dumanskiy.
* Created on 2/1/2015.
*
*/
public class TwitLogic extends NotificationBase {
private static final Logger log = LogManager.getLogger(TwitLogic.class);
private final BlockingIOProcessor blockingIOProcessor;
private final TwitterWrapper twitterWrapper;
public TwitLogic(BlockingIOProcessor blockingIOProcessor, TwitterWrapper twitterWrapper, long notificationQuotaLimit) {
super(notificationQuotaLimit);
this.blockingIOProcessor = blockingIOProcessor;
this.twitterWrapper = twitterWrapper;
}
public void messageReceived(ChannelHandlerContext ctx, HardwareStateHolder state, StringMessage message) {
if (Twitter.isWrongBody(message.body)) {
throw new NotificationBodyInvalidException();
}
DashBoard dash = state.user.profile.getDashByIdOrThrow(state.dashId);
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 twit widget.");
ctx.writeAndFlush(makeResponse(message.id, NOTIFICATION_NOT_AUTHORIZED), ctx.voidPromise());
return;
}
checkIfNotificationQuotaLimitIsNotReached();
log.trace("Sending Twit for user {}, with message : '{}'.", state.user.email, message.body);
twit(ctx.channel(), state.user.email, twitterWidget.token, twitterWidget.secret, message.body, message.id);
}
private void twit(Channel channel, String email, String token, String secret, String body, int msgId) {
blockingIOProcessor.execute(() -> {
try {
twitterWrapper.send(token, secret, body);
channel.writeAndFlush(ok(msgId), channel.voidPromise());
} catch (Exception e) {
logError(e.getMessage(), email);
channel.writeAndFlush(makeResponse(msgId, NOTIFICATION_ERROR), channel.voidPromise());
}
});
}
private static void logError(String errorMessage, String email) {
if (errorMessage != null) {
if (errorMessage.contains("Status is a duplicate")) {
log.warn("Duplicate twit status for user {}.", email);
} else if (errorMessage.contains("Authentication credentials")) {
log.warn("Tweet authentication failure for {}.", email);
} else if (errorMessage.contains("The request is understood, but it has been refused.")) {
log.warn("User twit account is banned by twitter. {}.", email);
} else {
log.error("Error sending twit for user {}. Reason : {}", email, errorMessage);
}
}
}
}