/*
* 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.facebook.v2;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import com.socialize.Socialize;
import com.socialize.SocializeService;
import com.socialize.android.ioc.IBeanFactory;
import com.socialize.api.action.ShareType;
import com.socialize.auth.AuthProviderType;
import com.socialize.auth.facebook.FacebookSessionStore;
import com.socialize.config.SocializeConfig;
import com.socialize.entity.Entity;
import com.socialize.entity.PropagationInfo;
import com.socialize.entity.PropagationInfoResponse;
import com.socialize.entity.Share;
import com.socialize.error.SocializeException;
import com.socialize.facebook.AsyncFacebookRunner;
import com.socialize.facebook.AsyncFacebookRunner.RequestListener;
import com.socialize.facebook.Facebook;
import com.socialize.facebook.FacebookError;
import com.socialize.log.SocializeLogger;
import com.socialize.networks.*;
import com.socialize.networks.facebook.FacebookUtilsProxy;
import com.socialize.util.ImageUtils;
import com.socialize.util.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Posts to the Facebook wall.
* @author Jason Polites
*/
@Deprecated
public class DefaultFacebookWallPoster implements FacebookWallPoster {
private SocializeLogger logger;
private ImageUtils imageUtils;
private FacebookUtilsProxy facebookUtils;
private IBeanFactory<AsyncFacebookRunner> facebookRunnerFactory;
private SocializeConfig config;
@Override
public void postLike(Activity parent, Entity entity, PropagationInfo propInfo, SocialNetworkListener listener) {
if(config.isOGLike()) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("object", propInfo.getEntityUrl());
post(parent, "me/og.likes", params, listener);
}
else {
post(parent, entity, "", propInfo, listener);
}
}
@Override
public void postComment(Activity parent, Entity entity, String comment, PropagationInfo propInfo, SocialNetworkListener listener) {
post(parent, entity, comment, propInfo, listener);
}
@Override
public void postOG(Activity parent, Entity entity, String message, String action, PropagationInfo propInfo, SocialNetworkListener listener) {
String entityUrl = propInfo.getEntityUrl();
String linkName = entityUrl;
String link = entityUrl;
if(entity != null) {
linkName = entity.getDisplayName();
}
final Map<String, Object> params = new HashMap<String, Object>();
params.put("name", linkName);
params.put("message", message);
params.put("link", link);
params.put("type", "link");
DefaultPostData postData = new DefaultPostData();
postData.setPostValues(params);
postData.setEntity(entity);
postData.setPropagationInfo(propInfo);
post(parent, listener, postData);
}
@Override
public void post(Activity parent, Entity entity, String message, PropagationInfo propInfo, SocialNetworkListener listener) {
postOG(parent, entity, message, null, propInfo, listener);
}
@Override
public void post(Activity parent, SocialNetworkListener listener, PostData postData) {
boolean okToGo = true;
if(listener != null) {
okToGo = !listener.onBeforePost(parent, SocialNetwork.FACEBOOK, postData);
}
if(okToGo) {
Bundle bundle = new Bundle();
Map<String, Object> postValues = postData.getPostValues();
if(postValues != null) {
Set<Entry<String, Object>> entries = postValues.entrySet();
for (Entry<String, Object> entry : entries) {
if(entry != null) {
Object value = entry.getValue();
String key = entry.getKey();
if(key != null && value != null) {
if(value instanceof byte[]) {
bundle.putByteArray(entry.getKey(), (byte[]) value);
}
else {
bundle.putString(entry.getKey(), value.toString());
}
}
}
}
}
Facebook fb = getFacebook(parent);
final FacebookSessionStore store = newFacebookSessionStore();
store.restore(fb, parent);
AsyncFacebookRunner runner = newAsyncFacebookRunner(fb);
RequestListener requestListener = newRequestListener(parent, listener);
String path = postData.getPath();
if(StringUtils.isEmpty(path)) {
path = "me/links";
}
runner.request(path, bundle, "POST", requestListener, null);
}
}
@Override
public void postPhoto(Activity parent, Share share, String comment, Uri photoUri, SocialNetworkListener listener) {
PropagationInfoResponse propagationInfoResponse = share.getPropagationInfoResponse();
PropagationInfo propInfo = propagationInfoResponse.getPropagationInfo(ShareType.FACEBOOK);
if(propInfo != null) {
String link = propInfo.getAppUrl();
String appId = getFacebookAppId();
if(!StringUtils.isEmpty(appId)) {
postPhoto(parent, link, comment, photoUri, listener);
}
else {
String msg = "Cannot post message to Facebook. No app id found. Make sure you specify facebook.app.id in socialize.properties";
onError(parent, msg, new SocializeException(msg), listener);
}
}
else {
String msg = "Cannot post message to Facebook. No propagation info found";
onError(parent, msg, new SocializeException(msg), listener);
}
}
@Override
public void postPhoto(Activity parent, String link, String caption, Uri photoUri, SocialNetworkListener listener) {
try {
Bundle params = new Bundle();
params.putString("caption", caption + ": " + link);
params.putByteArray("photo", imageUtils.scaleImage(parent, photoUri));
Facebook fb = getFacebook(parent);
final FacebookSessionStore store = newFacebookSessionStore();
store.restore(fb, parent);
AsyncFacebookRunner runner = newAsyncFacebookRunner(fb);
RequestListener requestListener = newRequestListener(parent, listener);
runner.request("me/photos", params, "POST", requestListener, null);
}
catch (IOException e) {
if(listener != null) {
listener.onNetworkError(parent, SocialNetwork.FACEBOOK, e);
}
if(logger != null) {
logger.error("Unable to scale image for upload", e);
}
else {
SocializeLogger.e(e.getMessage(), e);
}
}
}
@Override
public void post(Activity parent, String graphPath, Map<String, Object> postData, SocialNetworkPostListener listener) {
doFacebookCall(parent, postData, graphPath, "POST", listener);
}
@Override
public void get(Activity parent, String graphPath, Map<String, Object> postData, SocialNetworkPostListener listener) {
doFacebookCall(parent, postData, graphPath, "GET", listener);
}
@Override
public void delete(Activity parent, String graphPath, Map<String, Object> postData, SocialNetworkPostListener listener) {
doFacebookCall(parent, postData, graphPath, "DELETE", listener);
}
protected void doFacebookCall(Activity parent, Map<String, Object> postData, String graphPath, String method, SocialNetworkPostListener listener) {
Bundle bundle = new Bundle();
if(postData != null) {
Set<Entry<String, Object>> entries = postData.entrySet();
for (Entry<String, Object> entry : entries) {
Object value = entry.getValue();
if(value instanceof byte[]) {
bundle.putByteArray(entry.getKey(), (byte[]) value);
}
else {
bundle.putString(entry.getKey(), value.toString());
}
}
}
doFacebookCall(parent, bundle, graphPath, method, listener);
}
public void getCurrentPermissions(final Activity parent, String token, final FacebookPermissionCallback callback) {
Facebook fb = new Facebook(getFacebookAppId());
fb.setAccessToken(token);
AsyncFacebookRunner runner = newAsyncFacebookRunner(fb);
runner.request("me/permissions", new RequestListener() {
@Override
public void onMalformedURLException(MalformedURLException e, Object state) {
handlePermissionError(parent, callback, e);
}
@Override
public void onIOException(IOException e, Object state) {
handlePermissionError(parent, callback, e);
}
@Override
public void onFileNotFoundException(FileNotFoundException e, Object state) {
handlePermissionError(parent, callback, e);
}
@Override
public void onFacebookError(FacebookError e, Object state) {
handlePermissionError(parent, callback, e);
}
@Override
public void onComplete(final String response, final Object state) {
if(callback != null) {
parent.runOnUiThread(new Runnable() {
@Override
public void run() {
callback.onComplete(response, state);
}
});
}
}
});
}
protected void handlePermissionError(Activity parent, final FacebookPermissionCallback callback, final Exception e) {
if(callback != null) {
parent.runOnUiThread(new Runnable() {
@Override
public void run() {
callback.onError(SocializeException.wrap(e));
}
});
}
}
protected void doFacebookCall(Activity parent, Bundle data, String graphPath, String method, SocialNetworkPostListener listener) {
Facebook fb = getFacebook(parent);
FacebookSessionStore store = newFacebookSessionStore();
store.restore(fb, parent);
AsyncFacebookRunner runner = newAsyncFacebookRunner(fb);
RequestListener requestListener = newRequestListener(parent, listener);
runner.request(graphPath, data, method, requestListener, null);
}
// So we can mock
protected Facebook getFacebook(Context context) {
return facebookUtils.getFacebook(context);
}
// So we can mock
protected RequestListener newRequestListener(final Activity parent, final SocialNetworkPostListener listener) {
final String defaultErrorMessage = "Facebook Error";
return new RequestListener() {
public void onMalformedURLException(MalformedURLException e, Object state) {
handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
}
public void onIOException(IOException e, Object state) {
handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
}
public void onFileNotFoundException(final FileNotFoundException e, Object state) {
handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
}
public void onFacebookError(FacebookError e, Object state) {
handleFacebookError(parent, 0, defaultErrorMessage, e, listener);
}
public void onComplete(final String response, Object state) {
JSONObject responseObject = null;
if(!StringUtils.isEmpty(response)) {
try {
responseObject = newJSONObject(response);
if(responseObject.has("error")) {
JSONObject error = responseObject.getJSONObject("error");
int code = 0;
if(error.has("code") && !error.isNull("code")) {
code = error.getInt("code");
}
if(error.has("message") && !error.isNull("message")) {
String msg = error.getString("message");
if(logger != null) {
logger.error(msg);
}
else {
System.err.println(msg);
}
handleFacebookError(parent, code, msg, new SocializeException(msg), listener);
}
else {
handleFacebookError(parent, code, defaultErrorMessage, new SocializeException("Facebook Error (Unknown)"), listener);
}
return;
}
}
catch (JSONException e) {
onError(parent, defaultErrorMessage, e, listener);
return;
}
}
if(listener != null) {
final JSONObject fResponse = responseObject;
parent.runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onAfterPost(parent, SocialNetwork.FACEBOOK, fResponse);
}
});
}
}
};
}
protected void handleFacebookError(final Activity parent, int code, String msg, Throwable e, SocialNetworkPostListener listener) {
// Check for token error:
// http://fbdevwiki.com/wiki/Error_codes
if(code == 190) {
// Clear the session cache
getSocialize().clear3rdPartySession(parent, AuthProviderType.FACEBOOK);
}
onError(parent, msg, e, listener);
}
protected JSONObject newJSONObject(String response) throws JSONException {
return new JSONObject(response);
}
// So we can mock
protected AsyncFacebookRunner newAsyncFacebookRunner(Facebook fb) {
if(facebookRunnerFactory != null) {
return facebookRunnerFactory.getBean(fb);
}
return new AsyncFacebookRunner(fb);
}
// So we can mock
protected FacebookSessionStore newFacebookSessionStore() {
return new FacebookSessionStore();
}
// So we can mock
protected SocializeService getSocialize() {
return Socialize.getSocialize();
}
// So we can mock
protected String getFacebookAppId() {
return config.getProperty(SocializeConfig.FACEBOOK_APP_ID);
}
public void setLogger(SocializeLogger logger) {
this.logger = logger;
}
protected void onError(final Activity parent, final String msg, final Throwable e, final SocialNetworkPostListener listener) {
if(logger != null) {
if(e != null) {
logger.error(msg, e);
}
else {
logger.error(msg);
}
}
else {
if(e != null) {
SocializeLogger.e(msg, e);
}
else {
System.err.println(msg);
}
}
if(listener != null) {
parent.runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onNetworkError(parent, SocialNetwork.FACEBOOK, SocializeException.wrap(e));
}
});
}
}
public void setImageUtils(ImageUtils imageUtils) {
this.imageUtils = imageUtils;
}
public void setFacebookRunnerFactory(IBeanFactory<AsyncFacebookRunner> facebookRunnerFactory) {
this.facebookRunnerFactory = facebookRunnerFactory;
}
public void setFacebookUtils(FacebookUtilsProxy facebookUtils) {
this.facebookUtils = facebookUtils;
}
public void setConfig(SocializeConfig config) {
this.config = config;
}
}