package org.fluxtream.connectors.twitter;
import java.util.HashMap;
import java.util.List;
import net.sf.json.JSONArray;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.fluxtream.core.aspects.FlxLogger;
import org.fluxtream.core.connectors.ObjectType;
import org.fluxtream.core.connectors.annotations.Updater;
import org.fluxtream.core.connectors.updaters.AbstractUpdater;
import org.fluxtream.core.connectors.updaters.AuthExpiredException;
import org.fluxtream.core.connectors.updaters.RateLimitReachedException;
import org.fluxtream.core.connectors.updaters.UpdateFailedException;
import org.fluxtream.core.connectors.updaters.UpdateInfo;
import org.fluxtream.core.domain.ApiKey;
import org.fluxtream.core.domain.ChannelMapping;
import org.fluxtream.core.services.impl.BodyTrackHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Updater(prettyName = "Twitter", value = 12,
updateStrategyType= org.fluxtream.core.connectors.Connector.UpdateStrategyType.INCREMENTAL,
bodytrackResponder = TwitterBodytrackResponder.class,
objectTypes={TweetFacet.class,
TwitterDirectMessageFacet.class, TwitterMentionFacet.class},
defaultChannels = {"Twitter.activity"})
public class TwitterFeedUpdater extends AbstractUpdater {
private static final String STATUSES_USER_TIMELINE = "statuses/user_timeline";
private static final String DIRECT_MESSAGES_SENT = "direct_messages/sent";
private static final String STATUSES_MENTIONS_TIMELINE = "statuses/mentions_timeline";
private static final String DIRECT_MESSAGES = "direct_messages";
FlxLogger logger = FlxLogger.getLogger(TwitterFeedUpdater.class);
@Autowired
BodyTrackHelper bodyTrackHelper;
public TwitterFeedUpdater() {
super();
}
OAuthConsumer setupConsumer(ApiKey apiKey) {
String twitterConsumerKey = guestService.getApiKeyAttribute(apiKey, "twitterConsumerKey");
String twitterConsumerSecret = guestService.getApiKeyAttribute(apiKey, "twitterConsumerSecret");
OAuthConsumer consumer = new CommonsHttpOAuthConsumer(
twitterConsumerKey,
twitterConsumerSecret);
String accessToken = guestService.getApiKeyAttribute(apiKey, "accessToken");
String tokenSecret = guestService.getApiKeyAttribute(apiKey,"tokenSecret");
consumer.setTokenWithSecret(accessToken,
tokenSecret);
return consumer;
}
@Override
public void updateConnectorDataHistory(UpdateInfo updateInfo) throws Exception {
final OAuthConsumer consumer = setupConsumer(updateInfo.apiKey);
List<ObjectType> objectTypes = updateInfo.objectTypes();
if (objectTypes.contains(ObjectType.getObjectType(connector(), "tweet"))) {
getStatuses(updateInfo, consumer);
} else if (objectTypes.contains(ObjectType.getObjectType(connector(), "mention"))) {
getMentions(updateInfo, consumer);
} else if (objectTypes.contains(ObjectType.getObjectType(connector(), "dm"))) {
getReceivedDirectMessages(updateInfo, consumer);
getSentDirectMessages(updateInfo, consumer);
}
}
@Override
public void updateConnectorData(UpdateInfo updateInfo) throws Exception {
final OAuthConsumer consumer = setupConsumer(updateInfo.apiKey);
List<ObjectType> objectTypes = updateInfo.objectTypes();
if (objectTypes.contains(ObjectType.getObjectType(connector(), "tweet"))) {
refreshStatuses(updateInfo, consumer);
} else if (objectTypes.contains(ObjectType.getObjectType(connector(), "mention"))) {
refreshMentions(updateInfo, consumer);
} else if (objectTypes.contains(ObjectType.getObjectType(connector(), "dm"))) {
refreshReceivedDirectMessages(updateInfo, consumer);
refreshSentDirectMessages(updateInfo, consumer);
}
}
private void refreshStatuses(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TweetFacet mostRecentTweet = jpaDaoService.findOne("twitter.tweet.biggestTwitterId", TweetFacet.class, updateInfo.apiKey.getGuestId());
TweetFacet lastMostRecentTweet = mostRecentTweet;
if (mostRecentTweet!=null) {
int newerTweets = 1;
while (newerTweets>0) {
newerTweets = getStatusesAfter(updateInfo, mostRecentTweet.tweetId+1, consumer);
mostRecentTweet = jpaDaoService.findOne("twitter.tweet.biggestTwitterId", TweetFacet.class, updateInfo.apiKey.getGuestId());
if (lastMostRecentTweet.tweetId==mostRecentTweet.tweetId)
break;
lastMostRecentTweet = mostRecentTweet;
}
}
}
private void refreshMentions(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TwitterMentionFacet mostRecentMention = jpaDaoService.findOne("twitter.mention.biggestTwitterId", TwitterMentionFacet.class, updateInfo.apiKey.getGuestId());
TwitterMentionFacet lastMostRecentMention = mostRecentMention;
if (mostRecentMention!=null) {
int newerMentions = 1;
while (newerMentions>0) {
newerMentions = getMentionsAfter(updateInfo, mostRecentMention.twitterId+1, consumer);
mostRecentMention = jpaDaoService.findOne("twitter.mention.biggestTwitterId", TwitterMentionFacet.class, updateInfo.apiKey.getGuestId());
if (lastMostRecentMention.twitterId==mostRecentMention.twitterId)
break;
lastMostRecentMention = mostRecentMention;
}
}
}
private void refreshReceivedDirectMessages(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TwitterDirectMessageFacet mostRecentDM = jpaDaoService.findOne("twitter.received.dm.biggestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
TwitterDirectMessageFacet lastMostRecentDM = mostRecentDM;
if (mostRecentDM!=null) {
int newerDMs = 1;
while (newerDMs>0) {
newerDMs = getDirectMessagesReceivedAfter(updateInfo, mostRecentDM.twitterId + 1, consumer);
mostRecentDM = jpaDaoService.findOne("twitter.received.dm.biggestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
if (lastMostRecentDM.twitterId==mostRecentDM.twitterId)
break;
lastMostRecentDM = mostRecentDM;
}
}
}
private void refreshSentDirectMessages(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TwitterDirectMessageFacet mostRecentDM = jpaDaoService.findOne("twitter.sent.dm.biggestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
TwitterDirectMessageFacet lastMostRecentDM = mostRecentDM;
if (mostRecentDM!=null) {
int newerDMs = 1;
while (newerDMs>0) {
newerDMs = getDirectMessagesSentAfter(updateInfo, mostRecentDM.twitterId+1, consumer);
mostRecentDM = jpaDaoService.findOne("twitter.sent.dm.biggestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
if (lastMostRecentDM.twitterId==mostRecentDM.twitterId)
break;
lastMostRecentDM = mostRecentDM;
}
}
}
private void getStatuses(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TweetFacet oldestTweet = jpaDaoService.findOne("twitter.tweet.smallestTwitterId", TweetFacet.class, updateInfo.apiKey.getGuestId());
if (oldestTweet==null) {
getStatuses(updateInfo, -1, -1, consumer);
} else
getStatusesBefore(updateInfo, oldestTweet.tweetId-1, consumer);
oldestTweet = jpaDaoService.findOne("twitter.tweet.smallestTwitterId", TweetFacet.class, updateInfo.apiKey.getGuestId());
TweetFacet lastOldestTweet = oldestTweet;
if (oldestTweet!=null) {
int olderTweets = 1;
while(olderTweets>0) {
olderTweets = getStatusesBefore(updateInfo, oldestTweet.tweetId-1, consumer);
oldestTweet = jpaDaoService.findOne("twitter.tweet.smallestTwitterId", TweetFacet.class, updateInfo.apiKey.getGuestId());
if (oldestTweet.tweetId==lastOldestTweet.tweetId)
break;
lastOldestTweet = oldestTweet;
}
}
}
private void getMentions(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TwitterMentionFacet oldestMention = jpaDaoService.findOne("twitter.mention.smallestTwitterId", TwitterMentionFacet.class, updateInfo.apiKey.getGuestId());
if (oldestMention==null) {
getMentions(updateInfo, -1, -1, consumer);
} else {
getMentionsBefore(updateInfo, oldestMention.twitterId-1, consumer);
}
oldestMention = jpaDaoService.findOne("twitter.mention.smallestTwitterId", TwitterMentionFacet.class, updateInfo.apiKey.getGuestId());
TwitterMentionFacet lastOldestMention = oldestMention;
if (oldestMention!=null) {
int olderMentions = 1;
while(olderMentions>0) {
olderMentions = getMentionsBefore(updateInfo, oldestMention.twitterId-1, consumer);
oldestMention = jpaDaoService.findOne("twitter.mention.smallestTwitterId", TwitterMentionFacet.class, updateInfo.apiKey.getGuestId());
if (lastOldestMention.twitterId==oldestMention.twitterId)
break;
lastOldestMention = oldestMention;
}
}
}
private void getReceivedDirectMessages(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TwitterDirectMessageFacet oldestDM = jpaDaoService.findOne("twitter.received.dm.smallestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
if (oldestDM==null) {
getReceivedDirectMessages(updateInfo, -1, -1, consumer);
} else {
getDirectMessagesReceivedBefore(updateInfo, oldestDM.twitterId-1, consumer);
}
oldestDM = jpaDaoService.findOne("twitter.received.dm.smallestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
TwitterDirectMessageFacet lastOldestDM = oldestDM;
if (oldestDM!=null) {
int olderDMs = 1;
while(olderDMs>0) {
olderDMs = getDirectMessagesReceivedBefore(updateInfo, oldestDM.twitterId-1, consumer);
oldestDM = jpaDaoService.findOne("twitter.received.dm.smallestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
if (lastOldestDM.twitterId==oldestDM.twitterId)
break;
lastOldestDM = oldestDM;
}
}
}
private void getSentDirectMessages(UpdateInfo updateInfo, OAuthConsumer consumer) throws Exception {
TwitterDirectMessageFacet oldestDM = jpaDaoService.findOne("twitter.sent.dm.smallestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
if (oldestDM==null) {
getSentDirectMessages(updateInfo, -1, -1, consumer);
} else {
getDirectMessagesSentBefore(updateInfo, oldestDM.twitterId-1, consumer);
}
oldestDM = jpaDaoService.findOne("twitter.sent.dm.smallestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
TwitterDirectMessageFacet lastOldestDM = oldestDM;
if (oldestDM!=null) {
int olderDMs = 1;
while(olderDMs>0) {
olderDMs = getDirectMessagesSentBefore(updateInfo, oldestDM.twitterId-1, consumer);
oldestDM = jpaDaoService.findOne("twitter.sent.dm.smallestTwitterId", TwitterDirectMessageFacet.class, updateInfo.apiKey.getGuestId());
if (lastOldestDM.twitterId==oldestDM.twitterId)
break;
lastOldestDM = oldestDM;
}
}
}
private int getMentionsBefore(UpdateInfo updateInfo, long max_id, OAuthConsumer consumer) throws Exception {
return getMentions(updateInfo, max_id, -1, consumer);
}
private int getMentionsAfter(UpdateInfo updateInfo, long since_id, OAuthConsumer consumer) throws Exception {
return getMentions(updateInfo, -1, since_id, consumer);
}
private int getDirectMessagesReceivedBefore(UpdateInfo updateInfo, long max_id, OAuthConsumer consumer) throws Exception {
return getReceivedDirectMessages(updateInfo, max_id, -1, consumer);
}
private int getDirectMessagesReceivedAfter(UpdateInfo updateInfo, long since_id, OAuthConsumer consumer) throws Exception {
return getReceivedDirectMessages(updateInfo, -1, since_id, consumer);
}
private int getDirectMessagesSentBefore(UpdateInfo updateInfo, long max_id, OAuthConsumer consumer) throws Exception {
return getSentDirectMessages(updateInfo, max_id, -1, consumer);
}
private int getDirectMessagesSentAfter(UpdateInfo updateInfo, long since_id, OAuthConsumer consumer) throws Exception {
return getSentDirectMessages(updateInfo, -1, since_id, consumer);
}
private int getStatusesBefore(UpdateInfo updateInfo, long max_id, OAuthConsumer consumer) throws Exception {
return getStatuses(updateInfo, max_id, -1, consumer);
}
private int getStatusesAfter(UpdateInfo updateInfo, long since_id, OAuthConsumer consumer) throws Exception {
return getStatuses(updateInfo, -1, since_id, consumer);
}
private int getStatuses(UpdateInfo updateInfo, long max_id, long since_id, OAuthConsumer consumer) throws Exception {
checkRateLimitInfo(updateInfo, STATUSES_USER_TIMELINE);
long then = System.currentTimeMillis();
String requestUrl = "https://api.twitter.com/1.1/statuses/user_timeline.json?exclude_replies=true&count=200";
if (max_id!=-1)
requestUrl+="&max_id=" + max_id;
else if (since_id!=-1)
requestUrl+="&since_id=" + since_id;
HttpGet request = new HttpGet(requestUrl);
consumer.sign(request);
HttpClient client = env.getHttpClient();
HttpResponse response = client.execute(request);
extractRateLimitHeaders(response, STATUSES_USER_TIMELINE, updateInfo);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
countSuccessfulApiCall(updateInfo.apiKey,
updateInfo.objectTypes, then, requestUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String json = responseHandler.handleResponse(response);
JSONArray statuses = JSONArray.fromObject(json);
if (statuses!=null) {
apiDataService.cacheApiDataJSON(updateInfo, json, -1, -1);
}
return statuses.size();
} else {
final String reasonPhrase = response.getStatusLine().getReasonPhrase();
countFailedApiCall(updateInfo.apiKey, updateInfo.objectTypes, then, requestUrl, reasonPhrase,
statusCode, reasonPhrase);
if (statusCode==401)
throw new AuthExpiredException();
else if (statusCode>=400&&statusCode<500)
throw new UpdateFailedException("Unexpected response code " + statusCode, new Exception(), true,
ApiKey.PermanentFailReason.clientError(statusCode, reasonPhrase));
throw new UpdateFailedException(new Exception());
}
}
private void checkRateLimitInfo(final UpdateInfo updateInfo, String methodName) throws RateLimitReachedException {
final Integer remainingAPICalls = updateInfo.getRemainingAPICalls(methodName);
if (remainingAPICalls!=null && remainingAPICalls<1) {
throw new RateLimitReachedException();
}
}
private void extractRateLimitHeaders(HttpResponse response, String methodName, UpdateInfo updateInfo) {
extractLimitRemainingHeader(response, methodName, updateInfo);
extractLimitResetHeader(response, methodName, updateInfo);
extractLimitLimitHeader(response, methodName, updateInfo);
}
private void extractLimitLimitHeader(final HttpResponse response, final String methodName, final UpdateInfo updateInfo) {
final Header[] limitLimitHeaders = response.getHeaders("X-Rate-Limit-Limit");
if (limitLimitHeaders!=null&&limitLimitHeaders.length>0) {
final String value = limitLimitHeaders[0].getValue();
if (value!=null) {
try {
int limit = Integer.valueOf(value);
updateInfo.setContext(methodName + "/X-Rate-Limit-Limit", limit);
} catch(NumberFormatException e) {
logger.warn("Could not parse X-Rate-Limit-Limit Twitter API header, its value is [" + value + "]");
}
}
}
}
private void extractLimitRemainingHeader(final HttpResponse response, final String methodName, final UpdateInfo updateInfo) {
final Header[] limitRemainingHeaders = response.getHeaders("X-Rate-Limit-Remaining");
if (limitRemainingHeaders!=null&&limitRemainingHeaders.length>0) {
final String value = limitRemainingHeaders[0].getValue();
if (value!=null) {
try {
int remaining = Integer.valueOf(value);
updateInfo.setRemainingAPICalls(methodName, remaining);
} catch(NumberFormatException e) {
logger.warn("Could not parse X-Rate-Limit-Remaining Twitter API header, its value is [" + value + "]");
}
}
}
}
private void extractLimitResetHeader(final HttpResponse response, final String methodName, final UpdateInfo updateInfo) {
final Header[] limitResetHeaders = response.getHeaders("X-Rate-Limit-Reset");
if (limitResetHeaders!=null&&limitResetHeaders.length>0) {
final String value = limitResetHeaders[0].getValue();
if (value!=null) {
try {
long resetTime = Long.valueOf(value)*1000;
updateInfo.setResetTime(methodName, resetTime);
} catch(NumberFormatException e) {
logger.warn("Could not parse X-Rate-Limit-Reset Twitter API header; its value is [" + value + "]");
}
}
}
}
private int getReceivedDirectMessages(UpdateInfo updateInfo, long max_id, long since_id, OAuthConsumer consumer) throws Exception {
checkRateLimitInfo(updateInfo, DIRECT_MESSAGES);
long then = System.currentTimeMillis();
String requestUrl = "https://api.twitter.com/1.1/direct_messages.json?count=200";
if (max_id!=-1)
requestUrl+="&max_id=" + max_id;
else if (since_id!=-1)
requestUrl+="&since_id=" + since_id;
HttpGet request = new HttpGet(requestUrl);
consumer.sign(request);
HttpClient client = env.getHttpClient();
HttpResponse response = client.execute(request);
extractRateLimitHeaders(response, DIRECT_MESSAGES, updateInfo);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
countSuccessfulApiCall(updateInfo.apiKey,
updateInfo.objectTypes, then, requestUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String json = responseHandler.handleResponse(response);
JSONArray directMessages = JSONArray.fromObject(json);
if (directMessages!=null) {
updateInfo.setContext("sent", "0");
apiDataService.cacheApiDataJSON(updateInfo, json, -1, -1);
}
return directMessages.size();
} else {
final String reasonPhrase = response.getStatusLine().getReasonPhrase();
logger.warn("getReceivedDirectMessages reason=" +
reasonPhrase + " httpCode=" + response.getStatusLine().getStatusCode());
countFailedApiCall(updateInfo.apiKey,
updateInfo.objectTypes, then, requestUrl, reasonPhrase,
statusCode, reasonPhrase);
if (statusCode==401)
throw new AuthExpiredException();
else if (statusCode>=400&&statusCode<500)
throw new UpdateFailedException("Unexpected response code " + statusCode, new Exception(), true,
ApiKey.PermanentFailReason.clientError(statusCode, reasonPhrase));
throw new UpdateFailedException(new Exception());
}
}
private int getSentDirectMessages(UpdateInfo updateInfo, long max_id, long since_id, OAuthConsumer consumer) throws Exception {
checkRateLimitInfo(updateInfo, DIRECT_MESSAGES_SENT);
long then = System.currentTimeMillis();
String requestUrl = "https://api.twitter.com/1.1/direct_messages/sent.json?count=200";
if (max_id!=-1)
requestUrl+="&max_id=" + max_id;
else if (since_id!=-1)
requestUrl+="&since_id=" + since_id;
HttpGet request = new HttpGet(requestUrl);
consumer.sign(request);
HttpClient client = env.getHttpClient();
HttpResponse response = client.execute(request);
extractRateLimitHeaders(response, DIRECT_MESSAGES_SENT, updateInfo);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
countSuccessfulApiCall(updateInfo.apiKey,
updateInfo.objectTypes, then, requestUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String json = responseHandler.handleResponse(response);
JSONArray directMessages = JSONArray.fromObject(json);
if (directMessages!=null) {
updateInfo.setContext("sent", "1");
apiDataService.cacheApiDataJSON(updateInfo, json, -1, -1);
}
return directMessages.size();
} else {
final String reasonPhrase = response.getStatusLine().getReasonPhrase();
countFailedApiCall(updateInfo.apiKey, updateInfo.objectTypes, then, requestUrl, reasonPhrase,
statusCode, reasonPhrase);
if (statusCode==401)
throw new AuthExpiredException();
else if (statusCode>=400&&statusCode<500)
throw new UpdateFailedException("Unexpected response code " + statusCode, new Exception(), true,
ApiKey.PermanentFailReason.clientError(statusCode, reasonPhrase));
throw new UpdateFailedException(new Exception());
}
}
private int getMentions(UpdateInfo updateInfo, long max_id, long since_id, OAuthConsumer consumer) throws Exception {
checkRateLimitInfo(updateInfo, STATUSES_MENTIONS_TIMELINE);
long then = System.currentTimeMillis();
String requestUrl = "https://api.twitter.com/1.1/statuses/mentions_timeline.json?count=200";
if (max_id!=-1)
requestUrl+="&max_id=" + max_id;
else if (since_id!=-1)
requestUrl+="&since_id=" + since_id;
HttpGet request = new HttpGet(requestUrl);
consumer.sign(request);
HttpClient client = env.getHttpClient();
HttpResponse response = client.execute(request);
extractRateLimitHeaders(response, STATUSES_MENTIONS_TIMELINE, updateInfo);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
countSuccessfulApiCall(updateInfo.apiKey,
updateInfo.objectTypes, then, requestUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String json = responseHandler.handleResponse(response);
JSONArray mentions = JSONArray.fromObject(json);
if (mentions!=null) {
apiDataService.cacheApiDataJSON(updateInfo, json, -1, -1);
}
return mentions.size();
} else {
final String reasonPhrase = response.getStatusLine().getReasonPhrase();
countFailedApiCall(updateInfo.apiKey,
updateInfo.objectTypes, then, requestUrl, reasonPhrase,
statusCode, reasonPhrase);
if (statusCode==401)
throw new AuthExpiredException();
else if (statusCode>=400&&statusCode<500)
throw new UpdateFailedException("Unexpected response code " + statusCode, new Exception(), true,
ApiKey.PermanentFailReason.clientError(statusCode, reasonPhrase));
throw new UpdateFailedException(new Exception());
}
}
@Override
public void setDefaultChannelStyles(ApiKey apiKey) {
BodyTrackHelper.ChannelStyle channelStyle = new BodyTrackHelper.ChannelStyle();
channelStyle.timespanStyles = new BodyTrackHelper.MainTimespanStyle();
channelStyle.timespanStyles.defaultStyle = new BodyTrackHelper.TimespanStyle();
channelStyle.timespanStyles.defaultStyle.fillColor = "#92EF75";
channelStyle.timespanStyles.defaultStyle.borderColor = "#92EF75";
channelStyle.timespanStyles.defaultStyle.borderWidth = 2;
channelStyle.timespanStyles.defaultStyle.top = 0.25;
channelStyle.timespanStyles.defaultStyle.bottom = 0.75;
channelStyle.timespanStyles.values = new HashMap();
BodyTrackHelper.TimespanStyle stylePart = new BodyTrackHelper.TimespanStyle();
stylePart.top = 0.25;
stylePart.bottom = 0.75;
stylePart.fillColor = "#92EF75";
stylePart.borderColor = "#92EF75";
channelStyle.timespanStyles.values.put("tweet",stylePart);
stylePart = new BodyTrackHelper.TimespanStyle();
stylePart.top = 0.25;
stylePart.bottom = 0.75;
stylePart.fillColor = "#92EF75";
stylePart.borderColor = "#92EF75";
channelStyle.timespanStyles.values.put("dm",stylePart);
stylePart = new BodyTrackHelper.TimespanStyle();
stylePart.top = 0.25;
stylePart.bottom = 0.75;
stylePart.fillColor = "#92EF75";
stylePart.borderColor = "#92EF75";
channelStyle.timespanStyles.values.put("mention",stylePart);
bodyTrackHelper.setBuiltinDefaultStyle(apiKey.getGuestId(), apiKey.getConnector().getName(), "activity", channelStyle);
}
}