/** * Copyright (c) 2008-2012 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sakaiproject.profile2.logic; import java.util.HashMap; import java.util.Map; import lombok.Setter; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.sakaiproject.profile2.dao.ProfileDao; import org.sakaiproject.profile2.model.ExternalIntegrationInfo; import org.sakaiproject.profile2.util.ProfileConstants; import org.sakaiproject.profile2.util.ProfileUtils; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.auth.AccessToken; /** * Implementation of ProfileExternalIntegrationLogic API * * @author Steve Swinsburg (steve.swinsburg@gmail.com) * */ public class ProfileExternalIntegrationLogicImpl implements ProfileExternalIntegrationLogic { private static final Logger log = Logger.getLogger(ProfileExternalIntegrationLogicImpl.class); /** * OAuth Consumer registration details for Profile2. */ @Deprecated private final String TWITTER_OAUTH_CONSUMER_KEY="XzSPZIj0LxNaaoBz8XrgZQ"; @Deprecated private final String TWITTER_OAUTH_CONSUMER_SECRET="FSChsnmTufYi3X9H25YdFRxBhPXgnh2H0lMnLh7ZVG4"; /** * {@inheritDoc} */ public ExternalIntegrationInfo getExternalIntegrationInfo(String userUuid) { ExternalIntegrationInfo info = dao.getExternalIntegrationInfo(userUuid); if(info != null) { return info; } return getDefaultExternalIntegrationInfo(userUuid); } /** * {@inheritDoc} */ public boolean updateExternalIntegrationInfo(ExternalIntegrationInfo info) { if(dao.updateExternalIntegrationInfo(info)){ log.info("ExternalIntegrationInfo updated for user: " + info.getUserUuid()); return true; } return false; } /** * {@inheritDoc} */ public Map<String,String> getTwitterOAuthConsumerDetails() { Map<String,String> map = new HashMap<String,String>(); map.put("key", sakaiProxy.getServerConfigurationParameter("profile2.twitter.oauth.key", TWITTER_OAUTH_CONSUMER_KEY)); map.put("secret", sakaiProxy.getServerConfigurationParameter("profile2.twitter.oauth.secret", TWITTER_OAUTH_CONSUMER_SECRET)); return map; } /** * {@inheritDoc} */ public String getTwitterName(ExternalIntegrationInfo info) { if(info == null){ return null; } //get values String token = info.getTwitterToken(); String secret = info.getTwitterSecret(); if(StringUtils.isNotBlank(token) && StringUtils.isNotBlank(secret)) { //global config Map<String,String> config = getTwitterOAuthConsumerDetails(); //token for user AccessToken accessToken = new AccessToken(token, secret); //setup TwitterFactory factory = new TwitterFactory(); Twitter twitter = factory.getInstance(); twitter.setOAuthConsumer(config.get("key"), config.get("secret")); twitter.setOAuthAccessToken(accessToken); //check try { return twitter.verifyCredentials().getScreenName(); } catch (TwitterException e) { log.error("Error retrieving Twitter credentials: " + e.getClass() + ": " + e.getMessage()); } } return null; } /** * {@inheritDoc} */ public boolean validateTwitterCredentials(ExternalIntegrationInfo info) { return StringUtils.isNotBlank(getTwitterName(info)); } /** * {@inheritDoc} */ public void sendMessageToTwitter(final String userUuid, String message){ //setup class thread to call later class TwitterUpdater implements Runnable{ private Thread runner; private String userUuid; private String userToken; private String userSecret; private String message; public TwitterUpdater(String userUuid, String userToken, String userSecret, String message) { this.userUuid=userUuid; this.userToken=userToken; this.userSecret=userSecret; this.message=message; runner = new Thread(this,"Profile2 TwitterUpdater thread"); runner.start(); } //do it! public synchronized void run() { //global config Map<String,String> config = getTwitterOAuthConsumerDetails(); //token for user AccessToken accessToken = new AccessToken(userToken, userSecret); //setup TwitterFactory factory = new TwitterFactory(); Twitter twitter = factory.getInstance(); twitter.setOAuthConsumer(config.get("key"), config.get("secret")); twitter.setOAuthAccessToken(accessToken); try { twitter.updateStatus(message); log.info("Twitter status updated for: " + userUuid); //post update event sakaiProxy.postEvent(ProfileConstants.EVENT_TWITTER_UPDATE, "/profile/"+userUuid, true); } catch (TwitterException e) { log.error("ProfileLogic.sendMessageToTwitter() failed. " + e.getClass() + ": " + e.getMessage()); } } } //is twitter enabled if(!sakaiProxy.isTwitterIntegrationEnabledGlobally()){ return; } //get user info ExternalIntegrationInfo info = getExternalIntegrationInfo(userUuid); String token = info.getTwitterToken(); String secret = info.getTwitterSecret(); if(StringUtils.isBlank(token) || StringUtils.isBlank(secret)) { return; } //PRFL-423 limit to 140 chars //Hardcoded limit because 140 is the Twitter requirement so no need to make configurable message = ProfileUtils.truncate(message, 140, false); //instantiate class to send the data new TwitterUpdater(userUuid, token, secret, message); } /** * {@inheritDoc} */ public String getGoogleAuthenticationUrl() { String clientId = sakaiProxy.getServerConfigurationParameter("profile2.integration.google.client-id", null); if(StringUtils.isBlank(clientId)){ log.error("Google integration not properly configured. Please set the client id"); return null; } StringBuilder sb = new StringBuilder(); sb.append("https://accounts.google.com/o/oauth2/auth?"); sb.append("client_id="); sb.append(clientId); sb.append("&redirect_uri="); sb.append(ProfileConstants.GOOGLE_REDIRECT_URI); sb.append("&response_type=code"); sb.append("&scope="); sb.append(ProfileConstants.GOOGLE_DOCS_SCOPE); return sb.toString(); } /** * Get a default record, will only contain the userUuid * @param userUuid * @return */ private ExternalIntegrationInfo getDefaultExternalIntegrationInfo(String userUuid) { ExternalIntegrationInfo info = new ExternalIntegrationInfo(); info.setUserUuid(userUuid); return info; } @Setter private ProfileDao dao; @Setter private SakaiProxy sakaiProxy; }