/* * Copyright (c) 2012 Socialize Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.socialize.networks.twitter; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import com.socialize.ConfigUtils; import com.socialize.ShareUtils; import com.socialize.Socialize; import com.socialize.SocializeService; import com.socialize.apache.http.entity.mime.HttpMultipartMode; import com.socialize.apache.http.entity.mime.MultipartEntity; import com.socialize.apache.http.entity.mime.content.ByteArrayBody; import com.socialize.apache.http.entity.mime.content.StringBody; import com.socialize.api.SocializeSession; import com.socialize.api.action.share.ShareOptions; import com.socialize.api.action.share.SocialNetworkShareListener; import com.socialize.api.action.user.UserSystem; import com.socialize.auth.AuthProviderInfoBuilder; import com.socialize.auth.AuthProviderType; import com.socialize.auth.DefaultUserProviderCredentials; import com.socialize.auth.UserProviderCredentials; import com.socialize.auth.twitter.TwitterAuthProviderInfo; import com.socialize.config.SocializeConfig; import com.socialize.entity.Entity; import com.socialize.listener.SocializeAuthListener; import com.socialize.net.HttpRequestListener; import com.socialize.net.HttpRequestProvider; import com.socialize.networks.DefaultPostData; import com.socialize.networks.SocialNetwork; import com.socialize.networks.SocialNetworkListener; import com.socialize.networks.SocialNetworkPostListener; import com.socialize.oauth.OAuthRequestSigner; import com.socialize.util.ImageUtils; import com.socialize.util.JSONParser; import com.socialize.util.StringUtils; import com.socialize.util.UrlBuilder; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.message.BasicNameValuePair; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.*; import java.util.Map.Entry; /** * @author Jason Polites * */ public class TwitterUtilsImpl implements TwitterUtilsProxy { private UserSystem userSystem; private SocializeConfig config; private OAuthRequestSigner requestSigner; private HttpRequestProvider httpRequestProvider; private ImageUtils imageUtils; private AuthProviderInfoBuilder authProviderInfoBuilder; private JSONParser jsonParser; private SocializeConfig socializeConfig; /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#link(android.app.Activity, com.socialize.listener.SocializeAuthListener) */ @Override public void link(Activity context, SocializeAuthListener listener) { getSocialize().authenticateForWrite(context, AuthProviderType.TWITTER, listener); } /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#link(android.app.Activity, java.lang.String, java.lang.String, com.socialize.listener.SocializeAuthListener) */ @Override public void link(Activity context, String token, String secret, SocializeAuthListener listener) { TwitterAuthProviderInfo twInfo = new TwitterAuthProviderInfo(); twInfo.setConsumerKey(config.getProperty(SocializeConfig.TWITTER_CONSUMER_KEY)); twInfo.setConsumerSecret(config.getProperty(SocializeConfig.TWITTER_CONSUMER_SECRET)); DefaultUserProviderCredentials credentials = new DefaultUserProviderCredentials(); credentials.setAuthProviderInfo(twInfo); credentials.setAccessToken(token); credentials.setTokenSecret(secret); getSocialize().authenticateKnownUser( context, credentials, listener); } /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#unlink(android.app.Activity) */ @Override public void unlink(Context context) { SocializeSession session = getSocialize().getSession(); session.clear(AuthProviderType.TWITTER); session.getUserSettings().setAutoPostTwitter(false); userSystem.saveSession(context, session); } /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#isLinked(android.content.Context) */ @Override public boolean isLinked(Context context) { return getSocialize().isAuthenticatedForWrite(AuthProviderType.TWITTER); } /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#isAvailable(android.content.Context) */ @Override public boolean isAvailable(Context context) { return authProviderInfoBuilder.isSupported(AuthProviderType.TWITTER); } /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#setCredentials(android.content.Context, java.lang.String, java.lang.String) */ @Override public void setCredentials(Context context, String consumerKey, String consumerSecret) { config.setTwitterKeySecret(consumerKey, consumerSecret); } /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#getAccessToken() */ @Override public String getAccessToken(Context context) { UserProviderCredentials creds = getSocialize().getSession().getUserProviderCredentials(AuthProviderType.TWITTER); if(creds != null) { return creds.getAccessToken(); } return null; } /* (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#getTokenSecret() */ @Override public String getTokenSecret(Context context) { UserProviderCredentials creds = getSocialize().getSession().getUserProviderCredentials(AuthProviderType.TWITTER); if(creds != null) { return creds.getTokenSecret(); } return null; } /* * (non-Javadoc) * @see com.socialize.networks.twitter.TwitterUtilsProxy#tweet(android.app.Activity, com.socialize.entity.Entity, java.lang.String, com.socialize.networks.SocialNetworkListener) */ @Override public void tweetEntity(final Activity context, final Entity entity, final String text, final SocialNetworkShareListener listener) { ShareOptions options = ShareUtils.getUserShareOptions(context); options.setText(text); options.setShowAuthDialog(false); ShareUtils.shareViaSocialNetworks(context, entity, options, listener, SocialNetwork.TWITTER); } @Override public void tweetPhoto(Activity context, PhotoTweet tweet, SocialNetworkPostListener listener) { try { MultipartEntity multipart = newMultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); ByteArrayBody body = new ByteArrayBody(tweet.getImageData(), "media"); StringBody status = new StringBody(tweet.getText()); StringBody possiblySensitive = new StringBody(String.valueOf(tweet.isPossiblySensitive())); multipart.addPart("media", body); multipart.addPart("status", status); multipart.addPart("possibly_sensitive", possiblySensitive); String photoEndpoint = config.getProperty("twitter.upload.endpoint"); post(context, photoEndpoint + "statuses/update_with_media.json", multipart, listener); } catch (Exception e) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, e); } } } // Mockable protected MultipartEntity newMultipartEntity(HttpMultipartMode mode) { return new MultipartEntity(mode); } @Override public void tweet(final Activity context, Tweet tweet, final SocialNetworkListener listener) { tweet(context, null, tweet, listener); } @Override public void tweet(final Activity context, Entity entity, Tweet tweet, final SocialNetworkListener listener) { DefaultPostData postData = new DefaultPostData(); Map<String, Object> map = new HashMap<String, Object>(); map.put("status", tweet.getText()); // Was failing: https://dev.twitter.com/discussions/8685 if(tweet.isShareLocation() && tweet.getLocation() != null) { map.put("lat", String.valueOf(tweet.getLocation().getLatitude())); map.put("long", String.valueOf(tweet.getLocation().getLongitude())); map.put("display_coordinates", "true"); } postData.setPostValues(map); postData.setEntity(entity); boolean okToGo = true; if(listener != null) { okToGo = !listener.onBeforePost(context, SocialNetwork.TWITTER, postData); } if(okToGo) { String path = postData.getPath(); if(StringUtils.isEmpty(path)) { path = "statuses/update.json"; } post(context, path, postData.getPostValues(), listener); } } @Override public void post(final Activity context, String resource, Map<String, Object> postData, final SocialNetworkPostListener listener) { try { Set<Entry<String, Object>> entries = postData.entrySet(); List<NameValuePair> data = new ArrayList<NameValuePair>(); for (Entry<String, Object> entry : entries) { String key = entry.getKey(); Object value = entry.getValue(); if(key != null && value != null) { data.add(new BasicNameValuePair(key, value.toString())); } } UrlEncodedFormEntity entity = new UrlEncodedFormEntity(data, "UTF-8"); String apiEndpoint = config.getProperty("twitter.api.endpoint"); post(context, apiEndpoint + resource, entity, listener); } catch (Exception e) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, e); } } } protected void post(final Activity context, String resource, HttpEntity entity, final SocialNetworkPostListener listener) { try { resource = resource.trim(); if(!resource.endsWith(".json")) { resource += ".json"; } HttpPost post = new HttpPost(resource); post.setEntity(entity); SocializeSession session = getSocialize().getSession(); UserProviderCredentials creds = session.getUserProviderCredentials(AuthProviderType.TWITTER); String consumerKey = ConfigUtils.getConfig(context).getProperty(SocializeConfig.TWITTER_CONSUMER_KEY); String consumerSecret = ConfigUtils.getConfig(context).getProperty(SocializeConfig.TWITTER_CONSUMER_SECRET); HttpPost signedRequest = requestSigner.sign(consumerKey, consumerSecret, creds.getAccessToken(), creds.getTokenSecret(), post, null); httpRequestProvider.post(signedRequest, new HttpRequestListener() { @Override public void onSuccess(HttpResponse response, String responseData) { try { JSONObject responseObject = jsonParser.parseObject(responseData); if(listener != null) { listener.onAfterPost(context, SocialNetwork.TWITTER, responseObject); } } catch (JSONException e) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, e); } } } @Override public void onError(Exception error, HttpResponse response, int errorCode, String responseData) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, error); } } }); } catch (Exception e) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, e); } } } @Override public void get(final Activity context, String resource, Map<String, Object> params, final SocialNetworkPostListener listener) { try { resource = resource.trim(); if(!resource.contains(".json")) { if(resource.contains("?")) { String[] split = resource.split("\\?"); split[0] += ".json"; resource = split[0] + split[1]; } else { resource += ".json"; } } String apiEndpoint = config.getProperty("twitter.api.endpoint"); UrlBuilder builder = new UrlBuilder(); builder.start(apiEndpoint + resource); if(params != null) { Set<Entry<String, Object>> entries = params.entrySet(); for (Entry<String, Object> entry : entries) { String key = entry.getKey(); Object value = entry.getValue(); if(key != null && entry != null) { builder.addParam(key, value.toString()); } } } HttpGet get = new HttpGet(builder.toString()); SocializeSession session = getSocialize().getSession(); UserProviderCredentials creds = session.getUserProviderCredentials(AuthProviderType.TWITTER); String consumerKey = ConfigUtils.getConfig(context).getProperty(SocializeConfig.TWITTER_CONSUMER_KEY); String consumerSecret = ConfigUtils.getConfig(context).getProperty(SocializeConfig.TWITTER_CONSUMER_SECRET); HttpGet signedRequest = requestSigner.sign(consumerKey, consumerSecret, creds.getAccessToken(), creds.getTokenSecret(), get, null); httpRequestProvider.get(signedRequest, new HttpRequestListener() { @Override public void onSuccess(HttpResponse response, String responseData) { try { JSONObject responseObject = jsonParser.parseObject(responseData); if(listener != null) { listener.onAfterPost(context, SocialNetwork.TWITTER, responseObject); } } catch (JSONException e) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, e); } } } @Override public void onError(Exception error, HttpResponse response, int errorCode, String responseData) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, error); } } }); } catch (Exception e) { if(listener != null) { listener.onNetworkError(context, SocialNetwork.TWITTER, e); } } } @Override public byte[] getImageForPost(Activity context, Uri imagePath) throws IOException { return imageUtils.scaleImage(context, imagePath); } @Override public byte[] getImageForPost(Activity context, Bitmap image, CompressFormat format) throws IOException { return imageUtils.scaleImage(context, image, format); } protected SocializeService getSocialize() { return Socialize.getSocialize(); } public void setUserSystem(UserSystem userSystem) { this.userSystem = userSystem; } public void setConfig(SocializeConfig config) { this.config = config; } public void setRequestSigner(OAuthRequestSigner requestSigner) { this.requestSigner = requestSigner; } public void setHttpRequestProvider(HttpRequestProvider httpRequestProvider) { this.httpRequestProvider = httpRequestProvider; } public void setImageUtils(ImageUtils imageUtils) { this.imageUtils = imageUtils; } public void setAuthProviderInfoBuilder(AuthProviderInfoBuilder authProviderInfoBuilder) { this.authProviderInfoBuilder = authProviderInfoBuilder; } public void setJsonParser(JSONParser jsonParser) { this.jsonParser = jsonParser; } }