/*
+---------------------------------------------------------------------------+
| Facebook Development Platform Java Client |
+---------------------------------------------------------------------------+
| Copyright (c) 2007-2008 Facebook, Inc. |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| |
| 1. Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| 2. Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+---------------------------------------------------------------------------+
| For help with this library, contact developers-help@facebook.com |
+---------------------------------------------------------------------------+
*/
package com.facebook.api;
import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
/**
* Base class for interacting with the Facebook Application Programming Interface (API).
* Most Facebook API methods map directly to function calls of this class.
* <br/>
* Instances of FacebookRestClient should be initialized via calls to
* {@link #auth_createToken}, followed by {@link #auth_getSession}.
* <br/>
* For continually updated documentation, please refer to the
* <a href="http://wiki.developers.facebook.com/index.php/API">
* Developer Wiki</a>.
*/
public abstract class FacebookRestClient<T>
implements IFacebookRestClient<T> {
public static URL SERVER_URL = null;
public static URL HTTPS_SERVER_URL = null;
static {
try {
SERVER_URL = new URL(SERVER_ADDR);
HTTPS_SERVER_URL = new URL(HTTPS_SERVER_ADDR);
} catch (MalformedURLException e) {
System.err.println("MalformedURLException: " + e.getMessage());
System.exit(1);
}
}
protected final String _secret;
protected final String _apiKey;
protected final URL _serverUrl;
protected String _sessionKey;
protected boolean _isDesktop = false;
protected int _userId = -1;
/**
* filled in when session is established
* only used for desktop apps
*/
protected String _sessionSecret;
/**
* The number of parameters required for every request.
* @see #callMethod(IFacebookMethod,Collection)
*/
public static int NUM_AUTOAPPENDED_PARAMS = 6;
private static boolean DEBUG = false;
protected Boolean _debug = null;
protected File _uploadFile = null;
protected static final String CRLF = "\r\n";
protected static final String PREF = "--";
protected static final int UPLOAD_BUFFER_SIZE = 512;
public static final String MARKETPLACE_STATUS_DEFAULT = "DEFAULT";
public static final String MARKETPLACE_STATUS_NOT_SUCCESS = "NOT_SUCCESS";
public static final String MARKETPLACE_STATUS_SUCCESS = "SUCCESS";
protected FacebookRestClient(URL serverUrl, String apiKey, String secret, String sessionKey) {
_sessionKey = sessionKey;
_apiKey = apiKey;
_secret = secret;
_serverUrl = (null != serverUrl) ? serverUrl : SERVER_URL;
}
/**
* The response format in which results to FacebookMethod calls are returned
* @return the format: either XML, JSON, or null (API default)
*/
public String getResponseFormat() {
return null;
}
/**
* Retrieves whether two users are friends.
* @param userId1
* @param userId2
* @return T
* @see <a href="http://wiki.developers.facebook.com/index.php/Friends.areFriends">
* Developers Wiki: Friends.areFriends</a>
*/
public T friends_areFriends(int userId1, int userId2)
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.FRIENDS_ARE_FRIENDS,
new Pair<String, CharSequence>("uids1", Integer.toString(userId1)),
new Pair<String, CharSequence>("uids2", Integer.toString(userId2)));
}
/**
* Retrieves whether pairs of users are friends.
* Returns whether the first user in <code>userIds1</code> is friends with the first user in
* <code>userIds2</code>, the second user in <code>userIds1</code> is friends with the second user in
* <code>userIds2</code>, etc.
* @param userIds1
* @param userIds2
* @return T
* @throws IllegalArgumentException if one of the collections is null, or empty, or if the
* collection sizes differ.
* @see <a href="http://wiki.developers.facebook.com/index.php/Friends.areFriends">
* Developers Wiki: Friends.areFriends</a>
*/
public T friends_areFriends(Collection<Integer> userIds1, Collection<Integer> userIds2)
throws FacebookException, IOException {
if (userIds1 == null || userIds2 == null || userIds1.isEmpty() || userIds2.isEmpty()) {
throw new IllegalArgumentException("Collections passed to friends_areFriends should not be null or empty");
}
if (userIds1.size() != userIds2.size()) {
throw new IllegalArgumentException(String.format("Collections should be same size: got userIds1: %d elts; userIds2: %d elts",
userIds1.size(), userIds2.size()));
}
return this.callMethod(FacebookMethod.FRIENDS_ARE_FRIENDS,
new Pair<String, CharSequence>("uids1", delimit(userIds1)),
new Pair<String, CharSequence>("uids2", delimit(userIds2)));
}
/**
* Gets the FBML for a user's profile, including the content for both the profile box
* and the profile actions.
* @param userId the user whose profile FBML to set
* @return a T containing FBML markup
*/
public T profile_getFBML(Integer userId)
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.PROFILE_GET_FBML,
new Pair<String, CharSequence>("uid", Integer.toString(userId)));
}
/**
* Recaches the referenced url.
* @param url string representing the URL to refresh
* @return boolean indicating whether the refresh succeeded
*/
public boolean fbml_refreshRefUrl(String url)
throws FacebookException, IOException {
return fbml_refreshRefUrl(new URL(url));
}
/**
* Helper function: assembles the parameters used by feed_publishActionOfUser and
* feed_publishStoryToUser
* @param feedMethod feed_publishStoryToUser / feed_publishActionOfUser
* @param title title of the story
* @param body body of the story
* @param images optional images to be included in he story
* @param priority
* @return whether the call to <code>feedMethod</code> was successful
*/
protected boolean feedHandler(IFacebookMethod feedMethod, CharSequence title, CharSequence body,
Collection<IFeedImage> images, Integer priority)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(feedMethod.numParams());
params.add(new Pair<String, CharSequence>("title", title));
if (null != body)
params.add(new Pair<String, CharSequence>("body", body));
if (null != priority)
params.add(new Pair<String, CharSequence>("priority", priority.toString()));
handleFeedImages(params, images);
return extractBoolean(this.callMethod(feedMethod, params));
}
/**
* Adds image parameters to a list of parameters
* @param params
* @param images
*/
protected void handleFeedImages(List<Pair<String, CharSequence>> params,
Collection<IFeedImage> images) {
if (images != null && images.size() > 4) {
throw new IllegalArgumentException("At most four images are allowed, got " +
Integer.toString(images.size()));
}
if (null != images && !images.isEmpty()) {
int image_count = 0;
for (IFeedImage image : images) {
++image_count;
String imageUrl = image.getImageUrlString();
assert null != imageUrl && "".equals(imageUrl) : "Image URL must be provided";
params.add(new Pair<String, CharSequence>(String.format("image_%d", image_count),
image.getImageUrlString()));
assert null != image.getLinkUrl() : "Image link URL must be provided";
params.add(new Pair<String, CharSequence>(String.format("image_%d_link", image_count),
image.getLinkUrl().toString()));
}
}
}
/**
* Publish the notification of an action taken by a user to newsfeed.
* @param title the title of the feed story (up to 60 characters, excluding tags)
* @param body (optional) the body of the feed story (up to 200 characters, excluding tags)
* @param images (optional) up to four pairs of image URLs and (possibly null) link URLs
* @return whether the story was successfully published; false in case of permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishActionOfUser">
* Developers Wiki: Feed.publishActionOfUser</a>
*/
public boolean feed_publishActionOfUser(CharSequence title, CharSequence body,
Collection<IFeedImage> images)
throws FacebookException, IOException {
return feedHandler(FacebookMethod.FEED_PUBLISH_ACTION_OF_USER, title, body, images, null);
}
/**
* Publish the notification of an action taken by a user to newsfeed.
* @param title the title of the feed story (up to 60 characters, excluding tags)
* @param body (optional) the body of the feed story (up to 200 characters, excluding tags)
* @return whether the story was successfully published; false in case of permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishActionOfUser">
* Developers Wiki: Feed.publishActionOfUser</a>
*/
public boolean feed_publishActionOfUser(CharSequence title, CharSequence body)
throws FacebookException, IOException {
return feed_publishActionOfUser(title, body, null);
}
/**
* Call this function to retrieve the session information after your user has
* logged in.
* @param authToken the token returned by auth_createToken or passed back to your callback_url.
*/
public abstract String auth_getSession(String authToken)
throws FacebookException, IOException;
/**
* Publish a story to the logged-in user's newsfeed.
* @param title the title of the feed story
* @param body the body of the feed story
* @return whether the story was successfully published; false in case of permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishStoryToUser">
* Developers Wiki: Feed.publishStoryToUser</a>
*/
public boolean feed_publishStoryToUser(CharSequence title, CharSequence body)
throws FacebookException, IOException {
return feed_publishStoryToUser(title, body, null, null);
}
/**
* Publish a story to the logged-in user's newsfeed.
* @param title the title of the feed story
* @param body the body of the feed story
* @param images (optional) up to four pairs of image URLs and (possibly null) link URLs
* @return whether the story was successfully published; false in case of permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishStoryToUser">
* Developers Wiki: Feed.publishStoryToUser</a>
*/
public boolean feed_publishStoryToUser(CharSequence title, CharSequence body,
Collection<IFeedImage> images)
throws FacebookException, IOException {
return feed_publishStoryToUser(title, body, images, null);
}
/**
* Publish a story to the logged-in user's newsfeed.
* @param title the title of the feed story
* @param body the body of the feed story
* @param priority
* @return whether the story was successfully published; false in case of permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishStoryToUser">
* Developers Wiki: Feed.publishStoryToUser</a>
*/
public boolean feed_publishStoryToUser(CharSequence title, CharSequence body, Integer priority)
throws FacebookException, IOException {
return feed_publishStoryToUser(title, body, null, priority);
}
/**
* Publish a story to the logged-in user's newsfeed.
* @param title the title of the feed story
* @param body the body of the feed story
* @param images (optional) up to four pairs of image URLs and (possibly null) link URLs
* @param priority
* @return whether the story was successfully published; false in case of permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishStoryToUser">
* Developers Wiki: Feed.publishStoryToUser</a>
*/
public boolean feed_publishStoryToUser(CharSequence title, CharSequence body,
Collection<IFeedImage> images, Integer priority)
throws FacebookException, IOException {
return feedHandler(FacebookMethod.FEED_PUBLISH_STORY_TO_USER, title, body, images, priority);
}
/**
* Publishes a Mini-Feed story describing an action taken by a user, and
* publishes aggregating News Feed stories to the friends of that user.
* Stories are identified as being combinable if they have matching templates and substituted values.
* @param actorId deprecated
* @param titleTemplate markup (up to 60 chars, tags excluded) for the feed story's title
* section. Must include the token <code>{actor}</code>.
* @return whether the action story was successfully published; false in case
* of a permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishTemplatizedAction">
* Developers Wiki: Feed.publishTemplatizedAction</a>
* @see <a href="http://developers.facebook.com/tools.php?feed">
* Developers Resources: Feed Preview Console </a>
* @deprecated since 01/18/2008
*/
public boolean feed_publishTemplatizedAction(Integer actorId, CharSequence titleTemplate)
throws FacebookException, IOException {
if (null != actorId && actorId != this._userId) {
throw new IllegalArgumentException("Actor ID parameter is deprecated");
}
return feed_publishTemplatizedAction(titleTemplate, null, null, null, null, null, null, /*pageActorId*/ null);
}
/**
* Publishes a Mini-Feed story describing an action taken by the logged-in user, and
* publishes aggregating News Feed stories to their friends.
* Stories are identified as being combinable if they have matching templates and substituted values.
* @param titleTemplate markup (up to 60 chars, tags excluded) for the feed story's title
* section. Must include the token <code>{actor}</code>.
* @return whether the action story was successfully published; false in case
* of a permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishTemplatizedAction">
* Developers Wiki: Feed.publishTemplatizedAction</a>
* @see <a href="http://developers.facebook.com/tools.php?feed">
* Developers Resources: Feed Preview Console </a>
*/
public boolean feed_publishTemplatizedAction(CharSequence titleTemplate)
throws FacebookException, IOException {
return feed_publishTemplatizedAction(titleTemplate, null, null, null, null, null, null, /*pageActorId*/ null);
}
/**
* Publishes a Mini-Feed story describing an action taken by the logged-in user (or, if
* <code>pageActorId</code> is provided, page), and publishes aggregating News Feed stories
* to the user's friends/page's fans.
* Stories are identified as being combinable if they have matching templates and substituted values.
* @param titleTemplate markup (up to 60 chars, tags excluded) for the feed story's title
* section. Must include the token <code>{actor}</code>.
* @param pageActorId (optional) the ID of the page into whose mini-feed the story is being published
* @return whether the action story was successfully published; false in case
* of a permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishTemplatizedAction">
* Developers Wiki: Feed.publishTemplatizedAction</a>
* @see <a href="http://developers.facebook.com/tools.php?feed">
* Developers Resources: Feed Preview Console </a>
*/
public boolean feed_publishTemplatizedAction(CharSequence titleTemplate, Long pageActorId)
throws FacebookException, IOException {
return feed_publishTemplatizedAction(titleTemplate, null, null, null, null, null, null, pageActorId);
}
/**
* Publishes a Mini-Feed story describing an action taken by the logged-in user, and
* publishes aggregating News Feed stories to their friends.
* Stories are identified as being combinable if they have matching templates and substituted values.
* @param actorId deprecated.
* @param titleTemplate markup (up to 60 chars, tags excluded) for the feed story's title
* section. Must include the token <code>{actor}</code>.
* @param titleData (optional) contains token-substitution mappings for tokens that appear in
* titleTemplate. Should not contain mappings for the <code>{actor}</code> or
* <code>{target}</code> tokens. Required if tokens other than <code>{actor}</code>
* or <code>{target}</code> appear in the titleTemplate.
* @param bodyTemplate (optional) markup to be displayed in the feed story's body section.
* can include tokens, of the form <code>{token}</code>, to be substituted using
* bodyData.
* @param bodyData (optional) contains token-substitution mappings for tokens that appear in
* bodyTemplate. Required if the bodyTemplate contains tokens other than <code>{actor}</code>
* and <code>{target}</code>.
* @param bodyGeneral (optional) additional body markup that is not aggregated. If multiple instances
* of this templated story are combined together, the markup in the bodyGeneral of
* one of their stories may be displayed.
* @param targetIds The user ids of friends of the actor, used for stories about a direct action between
* the actor and these targets of his/her action. Required if either the titleTemplate or bodyTemplate
* includes the token <code>{target}</code>.
* @param images (optional) additional body markup that is not aggregated. If multiple instances
* of this templated story are combined together, the markup in the bodyGeneral of
* one of their stories may be displayed.
* @return whether the action story was successfully published; false in case
* of a permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishTemplatizedAction">
* Developers Wiki: Feed.publishTemplatizedAction</a>
* @see <a href="http://developers.facebook.com/tools.php?feed">
* Developers Resources: Feed Preview Console </a>
* @deprecated since 01/18/2008
*/
public boolean feed_publishTemplatizedAction(Integer actorId, CharSequence titleTemplate,
Map<String, CharSequence> titleData,
CharSequence bodyTemplate,
Map<String, CharSequence> bodyData,
CharSequence bodyGeneral,
Collection<Integer> targetIds,
Collection<IFeedImage> images)
throws FacebookException, IOException {
return feed_publishTemplatizedAction(titleTemplate, titleData, bodyTemplate, bodyData, bodyGeneral,
targetIds, images, /*pageActorId*/ null);
}
/**
* Publishes a Mini-Feed story describing an action taken by the logged-in user (or, if
* <code>pageActorId</code> is provided, page), and publishes aggregating News Feed stories
* to the user's friends/page's fans.
* Stories are identified as being combinable if they have matching templates and substituted values.
* @param titleTemplate markup (up to 60 chars, tags excluded) for the feed story's title
* section. Must include the token <code>{actor}</code>.
* @param titleData (optional) contains token-substitution mappings for tokens that appear in
* titleTemplate. Should not contain mappings for the <code>{actor}</code> or
* <code>{target}</code> tokens. Required if tokens other than <code>{actor}</code>
* or <code>{target}</code> appear in the titleTemplate.
* @param bodyTemplate (optional) markup to be displayed in the feed story's body section.
* can include tokens, of the form <code>{token}</code>, to be substituted using
* bodyData.
* @param bodyData (optional) contains token-substitution mappings for tokens that appear in
* bodyTemplate. Required if the bodyTemplate contains tokens other than <code>{actor}</code>
* and <code>{target}</code>.
* @param bodyGeneral (optional) additional body markup that is not aggregated. If multiple instances
* of this templated story are combined together, the markup in the bodyGeneral of
* one of their stories may be displayed.
* @param targetIds The user ids of friends of the actor, used for stories about a direct action between
* the actor and these targets of his/her action. Required if either the titleTemplate or bodyTemplate
* includes the token <code>{target}</code>.
* @param images (optional) additional body markup that is not aggregated. If multiple instances
* of this templated story are combined together, the markup in the bodyGeneral of
* one of their stories may be displayed.
* @param pageActorId (optional) the ID of the page into whose mini-feed the story is being published
* @return whether the action story was successfully published; false in case
* of a permission error
* @see <a href="http://wiki.developers.facebook.com/index.php/Feed.publishTemplatizedAction">
* Developers Wiki: Feed.publishTemplatizedAction</a>
* @see <a href="http://developers.facebook.com/tools.php?feed">
* Developers Resources: Feed Preview Console </a>
*/
public boolean feed_publishTemplatizedAction(CharSequence titleTemplate,
Map<String, CharSequence> titleData,
CharSequence bodyTemplate,
Map<String, CharSequence> bodyData,
CharSequence bodyGeneral,
Collection<Integer> targetIds,
Collection<IFeedImage> images,
Long pageActorId)
throws FacebookException, IOException {
assert null != titleTemplate && !"".equals(titleTemplate);
FacebookMethod method = FacebookMethod.FEED_PUBLISH_TEMPLATIZED_ACTION;
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(method.numParams());
params.add(new Pair<String, CharSequence>("title_template", titleTemplate));
if (null != titleData && !titleData.isEmpty()) {
JSONObject titleDataJson = new JSONObject();
titleDataJson.putAll(titleData);
params.add(new Pair<String, CharSequence>("title_data", titleDataJson.toString()));
}
if (null != bodyTemplate && !"".equals(bodyTemplate)) {
params.add(new Pair<String, CharSequence>("body_template", bodyTemplate));
if (null != bodyData && !bodyData.isEmpty()) {
JSONObject bodyDataJson = new JSONObject();
bodyDataJson.putAll(bodyData);
params.add(new Pair<String, CharSequence>("body_data", bodyDataJson.toString()));
}
}
if (null != bodyGeneral && !"".equals(bodyGeneral)) {
params.add(new Pair<String, CharSequence>("body_general", bodyGeneral));
}
if (null != targetIds && !targetIds.isEmpty()) {
params.add(new Pair<String, CharSequence>("target_ids", delimit(targetIds)));
}
if (null != pageActorId) {
params.add(new Pair<String, CharSequence>("page_actor_id", pageActorId.toString()));
}
handleFeedImages(params, images);
return extractBoolean(this.callMethod(method, params));
}
/**
* Retrieves the membership list of a group
* @param groupId the group id
* @return a T containing four membership lists of
* 'members', 'admins', 'officers', and 'not_replied'
*/
public T groups_getMembers(Number groupId)
throws FacebookException, IOException {
assert (null != groupId);
return this.callMethod(FacebookMethod.GROUPS_GET_MEMBERS,
new Pair<String, CharSequence>("gid", groupId.toString()));
}
private static String encode(CharSequence target) {
String result = target.toString();
try {
result = URLEncoder.encode(result, "UTF8");
} catch (UnsupportedEncodingException e) {
System.err.printf("Unsuccessful attempt to encode '%s' into UTF8", result);
}
return result;
}
/**
* Retrieves the membership list of an event
* @param eventId event id
* @return T consisting of four membership lists corresponding to RSVP status, with keys
* 'attending', 'unsure', 'declined', and 'not_replied'
*/
public T events_getMembers(Number eventId)
throws FacebookException, IOException {
assert (null != eventId);
return this.callMethod(FacebookMethod.EVENTS_GET_MEMBERS,
new Pair<String, CharSequence>("eid", eventId.toString()));
}
/**
* Retrieves the friends of the currently logged in user, who are also users
* of the calling application.
* @return array of friends
*/
public T friends_getAppUsers()
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.FRIENDS_GET_APP_USERS);
}
/**
* Retrieves the results of a Facebook Query Language query
* @param query : the FQL query statement
* @return varies depending on the FQL query
*/
public T fql_query(CharSequence query)
throws FacebookException, IOException {
assert (null != query);
return this.callMethod(FacebookMethod.FQL_QUERY,
new Pair<String, CharSequence>("query", query));
}
private String generateSignature(List<String> params, boolean requiresSession) {
String secret = (isDesktop() && requiresSession) ? this._sessionSecret : this._secret;
return FacebookSignatureUtil.generateSignature(params, secret);
}
public static void setDebugAll(boolean isDebug) {
FacebookRestClient.DEBUG = isDebug;
}
private static CharSequence delimit(Collection iterable) {
// could add a thread-safe version that uses StringBuffer as well
if (iterable == null || iterable.isEmpty())
return null;
StringBuilder buffer = new StringBuilder();
boolean notFirst = false;
for (Object item : iterable) {
if (notFirst)
buffer.append(",");
else
notFirst = true;
buffer.append(item.toString());
}
return buffer;
}
/**
* Call the specified method, with the given parameters, and return a DOM tree with the results.
*
* @param method the fieldName of the method
* @param paramPairs a list of arguments to the method
* @throws Exception with a description of any errors given to us by the server.
*/
protected T callMethod(IFacebookMethod method, Pair<String, CharSequence>... paramPairs)
throws FacebookException, IOException {
return callMethod(method, Arrays.asList(paramPairs));
}
/**
* Used to retrieve photo objects using the search parameters (one or more of the
* parameters must be provided).
*
* @param albumId retrieve from photos from this album (optional)
* @param photoIds retrieve from this list of photos (optional)
* @return an T of photo objects.
* @see #photos_get(Integer, Long, Collection)
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.get">
* Developers Wiki: Photos.get</a>
*/
public T photos_get(Long albumId, Collection<Long> photoIds)
throws FacebookException, IOException {
return photos_get( /*subjId*/null, albumId, photoIds);
}
/**
* Used to retrieve photo objects using the search parameters (one or more of the
* parameters must be provided).
*
* @param photoIds retrieve from this list of photos (optional)
* @return an T of photo objects.
* @see #photos_get(Integer, Long, Collection)
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.get">
* Developers Wiki: Photos.get</a>
*/
public T photos_get(Collection<Long> photoIds)
throws FacebookException, IOException {
return photos_get( /*subjId*/null, /*albumId*/null, photoIds);
}
/**
* Used to retrieve photo objects using the search parameters (one or more of the
* parameters must be provided).
*
* @param subjId retrieve from photos associated with this user (optional).
* @param albumId retrieve from photos from this album (optional)
* @return an T of photo objects.
* @see #photos_get(Integer, Long, Collection)
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.get">
* Developers Wiki: Photos.get</a>
*/
public T photos_get(Integer subjId, Long albumId)
throws FacebookException, IOException {
return photos_get(subjId, albumId, /*photoIds*/null) ;
}
/**
* Used to retrieve photo objects using the search parameters (one or more of the
* parameters must be provided).
*
* @param subjId retrieve from photos associated with this user (optional).
* @param photoIds retrieve from this list of photos (optional)
* @return an T of photo objects.
* @see #photos_get(Integer, Long, Collection)
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.get">
* Developers Wiki: Photos.get</a>
*/
public T photos_get(Integer subjId, Collection<Long> photoIds)
throws FacebookException, IOException {
return photos_get(subjId, /*albumId*/null, photoIds);
}
/**
* Used to retrieve photo objects using the search parameters (one or more of the
* parameters must be provided).
*
* @param subjId retrieve from photos associated with this user (optional).
* @return an T of photo objects.
* @see #photos_get(Integer, Long, Collection)
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.get">
* Developers Wiki: Photos.get</a>
*/
public T photos_get(Integer subjId)
throws FacebookException, IOException {
return photos_get(subjId, /*albumId*/null, /*photoIds*/null);
}
/**
* Used to retrieve photo objects using the search parameters (one or more of the
* parameters must be provided).
*
* @param albumId retrieve from photos from this album (optional)
* @return an T of photo objects.
* @see #photos_get(Integer, Long, Collection)
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.get">
* Developers Wiki: Photos.get</a>
*/
public T photos_get(Long albumId)
throws FacebookException, IOException {
return photos_get(/*subjId*/null, albumId, /*photoIds*/null);
}
/**
* Used to retrieve photo objects using the search parameters (one or more of the
* parameters must be provided).
*
* @param subjId retrieve from photos associated with this user (optional).
* @param albumId retrieve from photos from this album (optional)
* @param photoIds retrieve from this list of photos (optional)
* @return an T of photo objects.
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.get">
* Developers Wiki: Photos.get</a>
*/
public T photos_get(Integer subjId, Long albumId, Collection<Long> photoIds)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.PHOTOS_GET.numParams());
boolean hasUserId = null != subjId && 0 != subjId;
boolean hasAlbumId = null != albumId && 0 != albumId;
boolean hasPhotoIds = null != photoIds && !photoIds.isEmpty();
if (!hasUserId && !hasAlbumId && !hasPhotoIds) {
throw new IllegalArgumentException("At least one of photoIds, albumId, or subjId must be provided");
}
if (hasUserId)
params.add(new Pair<String, CharSequence>("subj_id", Integer.toString(subjId)));
if (hasAlbumId)
params.add(new Pair<String, CharSequence>("aid", Long.toString(albumId)));
if (hasPhotoIds)
params.add(new Pair<String, CharSequence>("pids", delimit(photoIds)));
return this.callMethod(FacebookMethod.PHOTOS_GET, params);
}
/**
* Retrieves the requested info fields for the requested set of users.
* @param userIds a collection of user IDs for which to fetch info
* @param fields a set of strings describing the info fields desired, such as "last_name", "sex"
* @return a T consisting of a list of users, with each user element
* containing the requested fields.
*/
public T users_getInfo(Collection<Integer> userIds, Set<CharSequence> fields)
throws FacebookException, IOException {
// assertions test for invalid params
if (null == userIds) {
throw new IllegalArgumentException("userIds cannot be null");
}
if (fields == null || fields.isEmpty()) {
throw new IllegalArgumentException("fields should not be empty");
}
return this.callMethod(FacebookMethod.USERS_GET_INFO,
new Pair<String, CharSequence>("uids", delimit(userIds)),
new Pair<String, CharSequence>("fields", delimit(fields)));
}
/**
* Retrieves the tags for the given set of photos.
* @param photoIds The list of photos from which to extract photo tags.
* @return the created album
*/
public T photos_getTags(Collection<Long> photoIds)
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.PHOTOS_GET_TAGS,
new Pair<String, CharSequence>("pids", delimit(photoIds)));
}
/**
* Retrieves the groups associated with a user
* @param userId Optional: User associated with groups.
* A null parameter will default to the session user.
* @param groupIds Optional: group ids to query.
* A null parameter will get all groups for the user.
* @return array of groups
*/
public T groups_get(Integer userId, Collection<Long> groupIds)
throws FacebookException, IOException {
boolean hasGroups = (null != groupIds && !groupIds.isEmpty());
if (null != userId)
return hasGroups ?
this.callMethod(FacebookMethod.GROUPS_GET, new Pair<String, CharSequence>("uid", userId.toString()),
new Pair<String, CharSequence>("gids", delimit(groupIds))) :
this.callMethod(FacebookMethod.GROUPS_GET, new Pair<String, CharSequence>("uid", userId.toString()));
else
return hasGroups ?
this.callMethod(FacebookMethod.GROUPS_GET, new Pair<String, CharSequence>("gids", delimit(groupIds))) :
this.callMethod(FacebookMethod.GROUPS_GET);
}
/**
* Call the specified method, with the given parameters, and return a DOM tree with the results.
*
* @param method the fieldName of the method
* @param paramPairs a list of arguments to the method
* @throws Exception with a description of any errors given to us by the server.
*/
protected T callMethod(IFacebookMethod method, Collection<Pair<String, CharSequence>> paramPairs)
throws FacebookException, IOException {
HashMap<String, CharSequence> params =
new HashMap<String, CharSequence>(2 * method.numTotalParams());
params.put("method", method.methodName());
params.put("api_key", _apiKey);
params.put("v", TARGET_API_VERSION);
String format = getResponseFormat();
if (null != format) {
params.put("format", format);
}
if (method.requiresSession()) {
params.put("call_id", Long.toString(System.currentTimeMillis()));
params.put("session_key", _sessionKey);
}
CharSequence oldVal;
for (Pair<String, CharSequence> p : paramPairs) {
oldVal = params.put(p.first, p.second);
if (oldVal != null)
System.err.printf("For parameter %s, overwrote old value %s with new value %s.", p.first,
oldVal, p.second);
}
assert (!params.containsKey("sig"));
String signature =
generateSignature(FacebookSignatureUtil.convert(params.entrySet()), method.requiresSession());
params.put("sig", signature);
boolean doHttps = this.isDesktop() && FacebookMethod.AUTH_GET_SESSION.equals(method);
InputStream data = method.takesFile()
? postFileRequest(method.methodName(), params)
: postRequest(method.methodName(), params, doHttps, /*doEncode*/true);
return parseCallResult(data, method);
}
/**
* Parses the result of an API call into a T.
* @param data an InputStream with the results of a request to the Facebook servers
* @param method the method called
* @throws FacebookException if <code>data</code> represents an error
* @throws IOException if <code>data</code> is not readable
* @return a T
*/
protected abstract T parseCallResult(InputStream data, IFacebookMethod method)
throws FacebookException, IOException;
/**
* Recaches the referenced url.
* @param url the URL to refresh
* @return boolean indicating whether the refresh succeeded
*/
public boolean fbml_refreshRefUrl(URL url)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.FBML_REFRESH_REF_URL,
new Pair<String, CharSequence>("url", url.toString())));
}
/**
* Retrieves the outstanding notifications for the session user.
* @return a T containing
* notification count pairs for 'messages', 'pokes' and 'shares',
* a uid list of 'friend_requests', a gid list of 'group_invites',
* and an eid list of 'event_invites'
*/
public T notifications_get()
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.NOTIFICATIONS_GET);
}
/**
* Retrieves the requested info fields for the requested set of users.
* @param userIds a collection of user IDs for which to fetch info
* @param fields a set of ProfileFields
* @return a T consisting of a list of users, with each user element
* containing the requested fields.
*/
public T users_getInfo(Collection<Integer> userIds, EnumSet<ProfileField> fields)
throws FacebookException, IOException {
// assertions test for invalid params
assert (userIds != null);
assert (fields != null);
assert (!fields.isEmpty());
return this.callMethod(FacebookMethod.USERS_GET_INFO,
new Pair<String, CharSequence>("uids", delimit(userIds)),
new Pair<String, CharSequence>("fields", delimit(fields)));
}
/**
* Retrieves the user ID of the user logged in to this API session
* @return the Facebook user ID of the logged-in user
*/
public int users_getLoggedInUser()
throws FacebookException, IOException {
T result = this.callMethod(FacebookMethod.USERS_GET_LOGGED_IN_USER);
return extractInt(result);
}
/**
* Call this function to get the user ID.
*
* @return The ID of the current session's user, or -1 if none.
*/
public int auth_getUserId(String authToken)
throws FacebookException, IOException {
/*
* Get the session information if we don't have it; this will populate
* the user ID as well.
*/
if (null == this._sessionKey)
auth_getSession(authToken);
return this._userId;
}
public boolean isDesktop() {
return this._isDesktop;
}
private boolean photos_addTag(Long photoId, Double xPct, Double yPct, Integer taggedUserId,
CharSequence tagText)
throws FacebookException, IOException {
assert (null != photoId && !photoId.equals(0));
assert (null != taggedUserId || null != tagText);
assert (null != xPct && xPct >= 0 && xPct <= 100);
assert (null != yPct && yPct >= 0 && yPct <= 100);
T d =
this.callMethod(FacebookMethod.PHOTOS_ADD_TAG, new Pair<String, CharSequence>("pid", photoId.toString()),
new Pair<String, CharSequence>("tag_uid", taggedUserId.toString()),
new Pair<String, CharSequence>("x", xPct.toString()),
new Pair<String, CharSequence>("y", yPct.toString()));
return extractBoolean(d);
}
/**
* Retrieves an indicator of whether the logged-in user has installed the
* application associated with the _apiKey.
* @return boolean indicating whether the user has installed the app
*/
public boolean users_isAppAdded()
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.USERS_IS_APP_ADDED));
}
/**
* Retrieves whether the logged-in user has granted the specified permission
* to this application.
* @param permission an extended permission (e.g. FacebookExtendedPerm.MARKETPLACE,
* "photo_upload")
* @return boolean indicating whether the user has the permission
* @see FacebookExtendedPerm
* @see <a href="http://wiki.developers.facebook.com/index.php/Users.hasAppPermission">
* Developers Wiki: Users.hasAppPermission</a>
*/
public boolean users_hasAppPermission(CharSequence permission)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.USERS_HAS_APP_PERMISSION,
new Pair<String, CharSequence>("ext_perm", permission)));
}
/**
* Sets the logged-in user's Facebook status.
* Requires the status_update extended permission.
* @return whether the status was successfully set
* @see #users_hasAppPermission
* @see FacebookExtendedPerm#STATUS_UPDATE
* @see <a href="http://wiki.developers.facebook.com/index.php/Users.setStatus">
* Developers Wiki: Users.setStatus</a>
*/
public boolean users_setStatus(String status)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.USERS_SET_STATUS,
new Pair<String, CharSequence>("status", status)));
}
/**
* Clears the logged-in user's Facebook status.
* Requires the status_update extended permission.
* @return whether the status was successfully cleared
* @see #users_hasAppPermission
* @see FacebookExtendedPerm#STATUS_UPDATE
* @see <a href="http://wiki.developers.facebook.com/index.php/Users.setStatus">
* Developers Wiki: Users.setStatus</a>
*/
public boolean users_clearStatus()
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.USERS_SET_STATUS,
new Pair<String, CharSequence>("clear", "1")));
}
/**
* Adds a tag to a photo.
* @param photoId The photo id of the photo to be tagged.
* @param xPct The horizontal position of the tag, as a percentage from 0 to 100, from the left of the photo.
* @param yPct The list of photos from which to extract photo tags.
* @param tagText The text of the tag.
* @return whether the tag was successfully added.
*/
public boolean photos_addTag(Long photoId, CharSequence tagText, Double xPct, Double yPct)
throws FacebookException, IOException {
return photos_addTag(photoId, xPct, yPct, null, tagText);
}
/**
* Helper function for posting a request that includes raw file data, eg {@link #photos_upload(File)}.
* @param methodName the name of the method
* @param params request parameters (not including the file)
* @return an InputStream with the request response
* @see #photos_upload(File)
*/
protected InputStream postFileRequest(String methodName, Map<String, CharSequence> params)
throws IOException {
assert (null != _uploadFile);
try {
BufferedInputStream bufin = new BufferedInputStream(new FileInputStream(_uploadFile));
String boundary = Long.toString(System.currentTimeMillis(), 16);
URLConnection con = SERVER_URL.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "multipart/form-data; charset=UTF-8; boundary=" + boundary);
con.setRequestProperty("MIME-version", "1.0");
DataOutputStream out = new DataOutputStream(con.getOutputStream());
for (Map.Entry<String, CharSequence> entry : params.entrySet()) {
out.writeBytes(PREF + boundary + CRLF);
out.writeBytes("Content-disposition: form-data; name=\"" + entry.getKey() + "\"");
out.writeBytes(CRLF + CRLF);
byte[] bytes = entry.getValue().toString().getBytes("UTF-8");
out.write(bytes);
out.writeBytes(CRLF);
}
out.writeBytes(PREF + boundary + CRLF);
out.writeBytes("Content-disposition: form-data; filename=\"" + _uploadFile.getName() + "\"" +
CRLF);
out.writeBytes("Content-Type: image/jpeg" + CRLF);
// out.writeBytes("Content-Transfer-Encoding: binary" + CRLF); // not necessary
// Write the file
out.writeBytes(CRLF);
byte b[] = new byte[UPLOAD_BUFFER_SIZE];
int byteCounter = 0;
int i;
while (-1 != (i = bufin.read(b))) {
byteCounter += i;
out.write(b, 0, i);
}
out.writeBytes(CRLF + PREF + boundary + PREF + CRLF);
out.flush();
out.close();
InputStream is = con.getInputStream();
return is;
} catch (Exception e) {
logException(e);
return null;
}
}
/**
* Logs an exception with default message
* @param e the exception
*/
protected final void logException(Exception e) {
logException("exception", e);
}
/**
* Logs an exception with an introductory message in addition to the
* exception's getMessage().
* @param msg message
* @param e exception
* @see Exception#getMessage
*/
protected void logException(CharSequence msg, Exception e) {
System.err.println(msg + ":" + e.getMessage());
e.printStackTrace();
}
/**
* Logs a message. Override this for more detailed logging.
* @param message
*/
protected void log(CharSequence message) {
System.out.println(message);
}
/**
* @return whether debugging is activated
*/
public boolean isDebug() {
return (null == _debug) ? DEBUG : _debug.booleanValue();
}
/**
* Send a notification message to the specified users on behalf of the logged-in user.
*
* @param recipientIds the user ids to which the message is to be sent. if empty,
* notification will be sent to logged-in user.
* @param notification the FBML to be displayed on the notifications page; only a stripped-down
* set of FBML tags that result in text and links is allowed
* @return a URL, possibly null, to which the user should be redirected to finalize
* the sending of the email
* @see <a href="http://wiki.developers.facebook.com/index.php/Notifications.sendEmail">
* Developers Wiki: notifications.send</a>
*/
public void notifications_send(Collection<Integer> recipientIds, CharSequence notification)
throws FacebookException, IOException {
assert (null != notification);
ArrayList<Pair<String, CharSequence>> args = new ArrayList<Pair<String, CharSequence>>(3);
if (null != recipientIds && !recipientIds.isEmpty()) {
args.add(new Pair<String, CharSequence>("to_ids", delimit(recipientIds)));
}
args.add(new Pair<String, CharSequence>("notification", notification));
this.callMethod(FacebookMethod.NOTIFICATIONS_SEND, args);
}
/**
* Send a notification message to the logged-in user.
*
* @param notification the FBML to be displayed on the notifications page; only a stripped-down
* set of FBML tags that result in text and links is allowed
* @return a URL, possibly null, to which the user should be redirected to finalize
* the sending of the email
* @see <a href="http://wiki.developers.facebook.com/index.php/Notifications.sendEmail">
* Developers Wiki: notifications.send</a>
*/
public void notifications_send(CharSequence notification)
throws FacebookException, IOException {
notifications_send(/*recipients*/null, notification);
}
/**
* Sends a notification email to the specified users, who must have added your application.
* You can send five (5) emails to a user per day. Requires a session key for desktop applications, which may only
* send email to the person whose session it is. This method does not require a session for Web applications.
* Either <code>fbml</code> or <code>text</code> must be specified.
*
* @param recipientIds up to 100 user ids to which the message is to be sent
* @param subject the subject of the notification email (optional)
* @param fbml markup to be sent to the specified users via email; only a stripped-down set of FBML tags
* that result in text, links and linebreaks is allowed
* @param text the plain text to send to the specified users via email
* @return a comma-separated list of the IDs of the users to whom the email was successfully sent
* @see <a href="http://wiki.developers.facebook.com/index.php/Notifications.send">
* Developers Wiki: notifications.sendEmail</a>
*/
public String notifications_sendEmail(Collection<Integer> recipientIds, CharSequence subject, CharSequence fbml, CharSequence text)
throws FacebookException, IOException {
if (null == recipientIds || recipientIds.isEmpty()) {
throw new IllegalArgumentException("List of email recipients cannot be empty");
}
boolean hasText = null != text && (0 != text.length());
boolean hasFbml = null != fbml && (0 != fbml.length());
if (!hasText && !hasFbml) {
throw new IllegalArgumentException("Text and/or fbml must not be empty");
}
ArrayList<Pair<String, CharSequence>> args = new ArrayList<Pair<String, CharSequence>>(4);
args.add(new Pair<String, CharSequence>("recipients", delimit(recipientIds)));
args.add(new Pair<String, CharSequence>("subject", subject));
if (hasText) {
args.add(new Pair<String, CharSequence>("text", text));
}
if (hasFbml) {
args.add(new Pair<String, CharSequence>("fbml", fbml));
}
// this method requires a session only if we're dealing with a desktop app
T result = this.callMethod(this.isDesktop() ? FacebookMethod.NOTIFICATIONS_SEND_EMAIL
: FacebookMethod.NOTIFICATIONS_SEND_EMAIL, args);
return extractString(result);
}
/**
* Sends a notification email to the specified users, who must have added your application.
* You can send five (5) emails to a user per day. Requires a session key for desktop applications, which may only
* send email to the person whose session it is. This method does not require a session for Web applications.
*
* @param recipientIds up to 100 user ids to which the message is to be sent
* @param subject the subject of the notification email (optional)
* @param fbml markup to be sent to the specified users via email; only a stripped-down set of FBML
* that allows only tags that result in text, links and linebreaks is allowed
* @return a comma-separated list of the IDs of the users to whom the email was successfully sent
* @see <a href="http://wiki.developers.facebook.com/index.php/Notifications.send">
* Developers Wiki: notifications.sendEmail</a>
*/
public String notifications_sendEmail(Collection<Integer> recipientIds, CharSequence subject, CharSequence fbml)
throws FacebookException, IOException {
return notifications_sendEmail(recipientIds, subject, fbml, /*text*/null);
}
/**
* Sends a notification email to the specified users, who must have added your application.
* You can send five (5) emails to a user per day. Requires a session key for desktop applications, which may only
* send email to the person whose session it is. This method does not require a session for Web applications.
*
* @param recipientIds up to 100 user ids to which the message is to be sent
* @param subject the subject of the notification email (optional)
* @param text the plain text to send to the specified users via email
* @return a comma-separated list of the IDs of the users to whom the email was successfully sent
* @see <a href="http://wiki.developers.facebook.com/index.php/Notifications.sendEmail">
* Developers Wiki: notifications.sendEmail</a>
*/
public String notifications_sendEmailPlain(Collection<Integer> recipientIds, CharSequence subject, CharSequence text)
throws FacebookException, IOException {
return notifications_sendEmail(recipientIds, subject, /*fbml*/null, text);
}
/**
* Extracts a URL from a result that consists of a URL only.
* @param result
* @return the URL
*/
protected abstract URL extractURL(T result)
throws IOException;
/**
* Recaches the image with the specified imageUrl.
* @param imageUrl String representing the image URL to refresh
* @return boolean indicating whether the refresh succeeded
*/
public boolean fbml_refreshImgSrc(String imageUrl)
throws FacebookException, IOException {
return fbml_refreshImgSrc(new URL(imageUrl));
}
/**
* Uploads a photo to Facebook.
* @param photo an image file
* @return a T with the standard Facebook photo information
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.upload">
* Developers wiki: Photos.upload</a>
*/
public T photos_upload(File photo)
throws FacebookException, IOException {
return photos_upload(photo, /*caption*/ null, /*albumId*/ null) ;
}
/**
* Uploads a photo to Facebook.
* @param photo an image file
* @param caption a description of the image contents
* @return a T with the standard Facebook photo information
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.upload">
* Developers wiki: Photos.upload</a>
*/
public T photos_upload(File photo, String caption)
throws FacebookException, IOException {
return photos_upload(photo, caption, /*albumId*/null) ;
}
/**
* Uploads a photo to Facebook.
* @param photo an image file
* @param albumId the album into which the photo should be uploaded
* @return a T with the standard Facebook photo information
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.upload">
* Developers wiki: Photos.upload</a>
*/
public T photos_upload(File photo, Long albumId)
throws FacebookException, IOException {
return photos_upload(photo, /*caption*/null, albumId);
}
/**
* Uploads a photo to Facebook.
* @param photo an image file
* @param caption a description of the image contents
* @param albumId the album into which the photo should be uploaded
* @return a T with the standard Facebook photo information
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.upload">
* Developers wiki: Photos.upload</a>
*/
public T photos_upload(File photo, String caption, Long albumId)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.PHOTOS_UPLOAD.numParams());
assert (photo.exists() && photo.canRead());
this._uploadFile = photo;
if (null != albumId)
params.add(new Pair<String, CharSequence>("aid", Long.toString(albumId)));
if (null != caption)
params.add(new Pair<String, CharSequence>("caption", caption));
return callMethod(FacebookMethod.PHOTOS_UPLOAD, params);
}
/**
* Creates an album.
* @param albumName The list of photos from which to extract photo tags.
* @return the created album
*/
public T photos_createAlbum(String albumName)
throws FacebookException, IOException {
return this.photos_createAlbum(albumName, null, /*description*/null) /*location*/;
}
/**
* Adds a tag to a photo.
* @param photoId The photo id of the photo to be tagged.
* @param xPct The horizontal position of the tag, as a percentage from 0 to 100, from the left of the photo.
* @param yPct The vertical position of the tag, as a percentage from 0 to 100, from the top of the photo.
* @param taggedUserId The list of photos from which to extract photo tags.
* @return whether the tag was successfully added.
*/
public boolean photos_addTag(Long photoId, Integer taggedUserId, Double xPct, Double yPct)
throws FacebookException, IOException {
return photos_addTag(photoId, xPct, yPct, taggedUserId, null);
}
/**
* Adds several tags to a photo.
* @param photoId The photo id of the photo to be tagged.
* @param tags A list of PhotoTags.
* @return a list of booleans indicating whether the tag was successfully added.
*/
public T photos_addTags(Long photoId, Collection<PhotoTag> tags)
throws FacebookException, IOException {
assert (photoId > 0);
assert (null != tags && !tags.isEmpty());
JSONArray jsonTags = new JSONArray();
for (PhotoTag tag : tags) {
jsonTags.add(tag.jsonify());
}
return this.callMethod(FacebookMethod.PHOTOS_ADD_TAG,
new Pair<String, CharSequence>("pid", photoId.toString()),
new Pair<String, CharSequence>("tags", jsonTags.toString()));
}
public void setIsDesktop(boolean isDesktop) {
this._isDesktop = isDesktop;
}
/**
* Returns all visible events according to the filters specified. This may be used to find all events of a user, or to query specific eids.
* @param eventIds filter by these event ID's (optional)
* @param userId filter by this user only (optional)
* @param startTime UTC lower bound (optional)
* @param endTime UTC upper bound (optional)
* @return T of events
*/
public T events_get(Integer userId, Collection<Long> eventIds, Long startTime, Long endTime)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.EVENTS_GET.numParams());
boolean hasUserId = null != userId && 0 != userId;
boolean hasEventIds = null != eventIds && !eventIds.isEmpty();
boolean hasStart = null != startTime && 0 != startTime;
boolean hasEnd = null != endTime && 0 != endTime;
if (hasUserId)
params.add(new Pair<String, CharSequence>("uid", Integer.toString(userId)));
if (hasEventIds)
params.add(new Pair<String, CharSequence>("eids", delimit(eventIds)));
if (hasStart)
params.add(new Pair<String, CharSequence>("start_time", startTime.toString()));
if (hasEnd)
params.add(new Pair<String, CharSequence>("end_time", endTime.toString()));
return this.callMethod(FacebookMethod.EVENTS_GET, params);
}
/**
* Sets the FBML for a user's profile, including the content for both the profile box
* and the profile actions.
* @param userId the user whose profile FBML to set
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @return a boolean indicating whether the FBML was successfully set
* @deprecated Use {@link FacebookRestClient#profile_setFBML(CharSequence,CharSequence,Long)} instead.
* @see #profile_setFBML(CharSequence,CharSequence,Long)
*/
public boolean profile_setFBML(CharSequence fbmlMarkup, Integer userId)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.PROFILE_SET_FBML,
new Pair<String, CharSequence>("uid", Integer.toString(userId)),
new Pair<String, CharSequence>("markup", fbmlMarkup)));
}
/**
* Sets the FBML for a profile box on the logged-in user's profile.
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFbml</a>
*/
public boolean profile_setProfileFBML(CharSequence fbmlMarkup)
throws FacebookException, IOException {
return profile_setFBML(fbmlMarkup, /* profileActionFbmlMarkup */null, /* mobileFbmlMarkup */null,
/* profileId */null);
}
/**
* Sets the FBML for profile actions for the logged-in user.
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setProfileActionFBML(CharSequence fbmlMarkup)
throws FacebookException, IOException {
return profile_setFBML( /* profileFbmlMarkup */null, fbmlMarkup, /* mobileFbmlMarkup */null,
/* profileId */null);
}
/**
* Sets the FBML for the logged-in user's profile on mobile devices.
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setMobileFBML(CharSequence fbmlMarkup)
throws FacebookException, IOException {
return profile_setFBML( /* profileFbmlMarkup */null, /* profileActionFbmlMarkup */null, fbmlMarkup,
/* profileId */null);
}
/**
* Sets the FBML for a profile box on the user or page profile with ID <code>profileId</code>.
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @param profileId a page or user ID (null for the logged-in user)
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFbml</a>
*/
public boolean profile_setProfileFBML(CharSequence fbmlMarkup, Long profileId)
throws FacebookException, IOException {
return profile_setFBML(fbmlMarkup, /* profileActionFbmlMarkup */null, /* mobileFbmlMarkup */null, profileId);
}
/**
* Sets the FBML for profile actions for the user or page profile with ID <code>profileId</code>.
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @param profileId a page or user ID (null for the logged-in user)
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setProfileActionFBML(CharSequence fbmlMarkup, Long profileId)
throws FacebookException, IOException {
return profile_setFBML( /* profileFbmlMarkup */null, fbmlMarkup, /* mobileFbmlMarkup */null, profileId);
}
/**
* Sets the FBML for the user or page profile with ID <code>profileId</code> on mobile devices.
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @param profileId a page or user ID (null for the logged-in user)
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setMobileFBML(CharSequence fbmlMarkup, Long profileId)
throws FacebookException, IOException {
return profile_setFBML( /* profileFbmlMarkup */null, /* profileActionFbmlMarkup */null, fbmlMarkup, profileId);
}
/**
* Sets the FBML for the profile box and profile actions for the logged-in user.
* Refer to the FBML documentation for a description of the markup and its role in various contexts.
* @param profileFbmlMarkup the FBML for the profile box
* @param profileActionFbmlMarkup the FBML for the profile actions
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setFBML(CharSequence profileFbmlMarkup, CharSequence profileActionFbmlMarkup)
throws FacebookException, IOException {
return profile_setFBML(profileFbmlMarkup, profileActionFbmlMarkup, /* mobileFbmlMarkup */null, /* profileId */null);
}
/**
* Sets the FBML for the profile box and profile actions for the user or page profile with ID <code>profileId</code>.
* Refer to the FBML documentation for a description of the markup and its role in various contexts.
* @param profileFbmlMarkup the FBML for the profile box
* @param profileActionFbmlMarkup the FBML for the profile actions
* @param profileId a page or user ID (null for the logged-in user)
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setFBML(CharSequence profileFbmlMarkup, CharSequence profileActionFbmlMarkup, Long profileId)
throws FacebookException, IOException {
return profile_setFBML(profileFbmlMarkup, profileActionFbmlMarkup, /* mobileFbmlMarkup */null, profileId);
}
/**
* Sets the FBML for the profile box, profile actions, and mobile devices for the logged-in user.
* Refer to the FBML documentation for a description of the markup and its role in various contexts.
* @param profileFbmlMarkup the FBML for the profile box
* @param profileActionFbmlMarkup the FBML for the profile actions
* @param mobileFbmlMarkup the FBML for mobile devices
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setFBML(CharSequence profileFbmlMarkup, CharSequence profileActionFbmlMarkup, CharSequence mobileFbmlMarkup)
throws FacebookException, IOException {
return profile_setFBML(profileFbmlMarkup, profileActionFbmlMarkup, mobileFbmlMarkup, /* profileId */null);
}
/**
* Sets the FBML for the profile box, profile actions, and mobile devices for the user or page profile with ID <code>profileId</code>.
* Refer to the FBML documentation for a description of the markup and its role in various contexts.
* @param profileFbmlMarkup the FBML for the profile box
* @param profileActionFbmlMarkup the FBML for the profile actions
* @param mobileFbmlMarkup the FBML for mobile devices
* @param profileId a page or user ID (null for the logged-in user)
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML">
* Developers wiki: Profile.setFBML</a>
*/
public boolean profile_setFBML(CharSequence profileFbmlMarkup, CharSequence profileActionFbmlMarkup,
CharSequence mobileFbmlMarkup, Long profileId)
throws FacebookException, IOException {
if (null == profileFbmlMarkup && null == profileActionFbmlMarkup && null == mobileFbmlMarkup) {
throw new IllegalArgumentException("At least one of the FBML parameters must be provided");
}
if (this.isDesktop() && (null != profileId && this._userId != profileId)) {
throw new IllegalArgumentException("Can't set FBML for another user from desktop app");
}
FacebookMethod method = FacebookMethod.PROFILE_SET_FBML;
ArrayList<Pair<String, CharSequence>> params = new ArrayList<Pair<String, CharSequence>>(method.numParams());
if (null != profileId && !this.isDesktop())
params.add(new Pair<String, CharSequence>("uid", profileId.toString()));
if (null != profileFbmlMarkup)
params.add(new Pair<String, CharSequence>("profile", profileFbmlMarkup));
if (null != profileActionFbmlMarkup)
params.add(new Pair<String, CharSequence>("profile_action", profileActionFbmlMarkup));
if (null != mobileFbmlMarkup)
params.add(new Pair<String, CharSequence>("mobile_fbml", mobileFbmlMarkup));
return extractBoolean(this.callMethod(method, params));
}
/**
* Associates a "<code>handle</code>" with FBML markup so that the handle can be used within the
* <a href="http://wiki.developers.facebook.com/index.php/Fb:ref">fb:ref</a> FBML tag.
* A handle is unique within an application and allows an application to publish identical FBML
* to many user profiles and do subsequent updates without having to republish FBML for each user.
*
* @param handle a string, unique within the application, that
* @param fbmlMarkup refer to the FBML documentation for a description of the markup and its role in various contexts
* @return a boolean indicating whether the FBML was successfully set
* @see <a href="http://wiki.developers.facebook.com/index.php/Fbml.setRefHandle">
* Developers Wiki: Fbml.setRefHandle</a>
*/
public boolean fbml_setRefHandle(CharSequence handle, CharSequence fbmlMarkup)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.FBML_SET_REF_HANDLE,
new Pair<String, CharSequence>("handle", handle),
new Pair<String, CharSequence>("fbml", fbmlMarkup)));
}
/**
* Determines whether this application can send SMS to the user identified by <code>userId</code>
* @param userId a user ID
* @return true if sms can be sent to the user
* @see FacebookExtendedPerm#SMS
* @see <a href="http://wiki.developers.facebook.com/index.php/Mobile#Application_generated_messages">
* Developers Wiki: Mobile: Application Generated Messages</a>
*/
public boolean sms_canSend(Integer userId)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.SMS_CAN_SEND,
new Pair<String, CharSequence>("uid",
userId.toString())));
}
/**
* Sends a message via SMS to the user identified by <code>userId</code> in response
* to a user query associated with <code>mobileSessionId</code>.
*
* @param userId a user ID
* @param response the message to be sent via SMS
* @param mobileSessionId the mobile session
* @throws FacebookException in case of error
* @throws IOException
* @see FacebookExtendedPerm#SMS
* @see <a href="http://wiki.developers.facebook.com/index.php/Mobile#Application_generated_messages">
* Developers Wiki: Mobile: Application Generated Messages</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Mobile#Workflow">
* Developers Wiki: Mobile: Workflow</a>
*/
public void sms_sendResponse(Integer userId, CharSequence response, Integer mobileSessionId)
throws FacebookException, IOException {
this.callMethod(FacebookMethod.SMS_SEND_MESSAGE,
new Pair<String, CharSequence>("uid", userId.toString()),
new Pair<String, CharSequence>("message", response),
new Pair<String, CharSequence>("session_id", mobileSessionId.toString()));
}
/**
* Sends a message via SMS to the user identified by <code>userId</code>.
* The SMS extended permission is required for success.
*
* @param userId a user ID
* @param message the message to be sent via SMS
* @throws FacebookException in case of error
* @throws IOException
* @see FacebookExtendedPerm#SMS
* @see <a href="http://wiki.developers.facebook.com/index.php/Mobile#Application_generated_messages">
* Developers Wiki: Mobile: Application Generated Messages</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Mobile#Workflow">
* Developers Wiki: Mobile: Workflow</a>
*/
public void sms_sendMessage(Integer userId, CharSequence message)
throws FacebookException, IOException {
this.callMethod(FacebookMethod.SMS_SEND_MESSAGE,
new Pair<String, CharSequence>("uid", userId.toString()),
new Pair<String, CharSequence>("message", message),
new Pair<String, CharSequence>("req_session", "0"));
}
/**
* Sends a message via SMS to the user identified by <code>userId</code>, with
* the expectation that the user will reply. The SMS extended permission is required for success.
* The returned mobile session ID can be stored and used in {@link #sms_sendResponse} when
* the user replies.
*
* @param userId a user ID
* @param message the message to be sent via SMS
* @return a mobile session ID (can be used in {@link #sms_sendResponse})
* @throws FacebookException in case of error, e.g. SMS is not enabled
* @throws IOException
* @see FacebookExtendedPerm#SMS
* @see <a href="http://wiki.developers.facebook.com/index.php/Mobile#Application_generated_messages">
* Developers Wiki: Mobile: Application Generated Messages</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Mobile#Workflow">
* Developers Wiki: Mobile: Workflow</a>
*/
public int sms_sendMessageWithSession(Integer userId, CharSequence message)
throws FacebookException, IOException {
return extractInt(this.callMethod(FacebookMethod.SMS_SEND_MESSAGE,
new Pair<String, CharSequence>("uid", userId.toString()),
new Pair<String, CharSequence>("message", message),
new Pair<String, CharSequence>("req_session", "1")));
}
/**
* Delimits a collection entries into a single CharSequence, using <code>delimiter</code>
* to delimit each entry, and <code>equals</code> to delimit the key from the value inside
* each entry.
* @param entries
* @param delimiter used to delimit one entry from another
* @param equals used to delimit key from value
* @param doEncode whether to encode the value of each entry
* @return a CharSequence that contains all the entries, appropriately delimited
*/
protected static CharSequence delimit(Collection<Map.Entry<String, CharSequence>> entries,
CharSequence delimiter, CharSequence equals,
boolean doEncode) {
if (entries == null || entries.isEmpty())
return null;
StringBuilder buffer = new StringBuilder();
boolean notFirst = false;
for (Map.Entry<String, CharSequence> entry : entries) {
if (notFirst)
buffer.append(delimiter);
else
notFirst = true;
CharSequence value = entry.getValue();
buffer.append(entry.getKey()).append(equals).append(doEncode ? encode(value) : value);
}
return buffer;
}
/**
* Creates an album.
* @param name The album name.
* @param location The album location (optional).
* @param description The album description (optional).
* @return an array of photo objects.
*/
public T photos_createAlbum(String name, String description, String location)
throws FacebookException, IOException {
assert (null != name && !"".equals(name));
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.PHOTOS_CREATE_ALBUM.numParams());
params.add(new Pair<String, CharSequence>("name", name));
if (null != description)
params.add(new Pair<String, CharSequence>("description", description));
if (null != location)
params.add(new Pair<String, CharSequence>("location", location));
return this.callMethod(FacebookMethod.PHOTOS_CREATE_ALBUM, params);
}
public void setDebug(boolean isDebug) {
_debug = isDebug;
}
/**
* Extracts a Boolean from a result that consists of a Boolean only.
* @param result
* @return the Boolean
*/
protected boolean extractBoolean(T result) {
return 1 == extractInt(result);
}
/**
* Extracts an Integer from a result that consists of an Integer only.
* @param result
* @return the Integer
*/
protected abstract int extractInt(T result);
/**
* Extracts an Long from a result that consists of a Long only.
* @param result
* @return the Long
*/
protected abstract Long extractLong(T result);
/**
* Retrieves album metadata for a list of album IDs.
* @param albumIds the ids of albums whose metadata is to be retrieved
* @return album objects
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.getAlbums">
* Developers Wiki: Photos.getAlbums</a>
*/
public T photos_getAlbums(Collection<Long> albumIds)
throws FacebookException, IOException {
return photos_getAlbums(null, /*userId*/albumIds);
}
/**
* Retrieves album metadata for albums owned by a user.
* @param userId (optional) the id of the albums' owner (optional)
* @return album objects
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.getAlbums">
* Developers Wiki: Photos.getAlbums</a>
*/
public T photos_getAlbums(Integer userId)
throws FacebookException, IOException {
return photos_getAlbums(userId, null) /*albumIds*/;
}
/**
* Retrieves album metadata. Pass a user id and/or a list of album ids to specify the albums
* to be retrieved (at least one must be provided)
*
* @param userId (optional) the id of the albums' owner (optional)
* @param albumIds (optional) the ids of albums whose metadata is to be retrieved
* @return album objects
* @see <a href="http://wiki.developers.facebook.com/index.php/Photos.getAlbums">
* Developers Wiki: Photos.getAlbums</a>
*/
public T photos_getAlbums(Integer userId, Collection<Long> albumIds)
throws FacebookException, IOException {
boolean hasUserId = null != userId && userId != 0;
boolean hasAlbumIds = null != albumIds && !albumIds.isEmpty();
assert (hasUserId || hasAlbumIds); // one of the two must be provided
if (hasUserId)
return (hasAlbumIds) ?
this.callMethod(FacebookMethod.PHOTOS_GET_ALBUMS, new Pair<String, CharSequence>("uid",
Integer.toString(userId)),
new Pair<String, CharSequence>("aids", delimit(albumIds))) :
this.callMethod(FacebookMethod.PHOTOS_GET_ALBUMS,
new Pair<String, CharSequence>("uid", Integer.toString(userId)));
else
return this.callMethod(FacebookMethod.PHOTOS_GET_ALBUMS,
new Pair<String, CharSequence>("aids", delimit(albumIds)));
}
/**
* Recaches the image with the specified imageUrl.
* @param imageUrl the image URL to refresh
* @return boolean indicating whether the refresh succeeded
*/
public boolean fbml_refreshImgSrc(URL imageUrl)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.FBML_REFRESH_IMG_SRC,
new Pair<String, CharSequence>("url",
imageUrl.toString())));
}
/**
* Retrieves the friends of the currently logged in user.
* @return T of friends
* @see <a href="http://wiki.developers.facebook.com/index.php/Friends.get">
* Developers Wiki: Friends.get</a>
*/
public T friends_get()
throws FacebookException, IOException {
return this.friends_get( /*friendListId */null);
}
/**
* Retrieves the friends of the currently logged in user that
* are members of the friends list with ID <code>friendListId</code>.
* @param friendListId the friend list for which friends should be fetched.
* if <code>null</code>, all friends will be retrieved.
* @return T of friends
* @see <a href="http://wiki.developers.facebook.com/index.php/Friends.get">
* Developers Wiki: Friends.get</a>
*/
public T friends_get(Long friendListId)
throws FacebookException, IOException {
FacebookMethod method = FacebookMethod.FRIENDS_GET;
Collection<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(method.numParams());
if (null != friendListId) {
if (0L >= friendListId) {
throw new IllegalArgumentException("given invalid friendListId " + friendListId.toString());
}
params.add(new Pair<String, CharSequence>("flid", friendListId.toString()));
}
return this.callMethod(method, params);
}
/**
* Retrieves the friend lists of the currently logged in user.
* @return T of friend lists
* @see <a href="http://wiki.developers.facebook.com/index.php/Friends.getLists">
* Developers Wiki: Friends.getLists</a>
*/
public T friends_getLists()
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.FRIENDS_GET_LISTS);
}
private InputStream postRequest(CharSequence method, Map<String, CharSequence> params,
boolean doHttps, boolean doEncode)
throws IOException {
CharSequence buffer = (null == params) ? "" : delimit(params.entrySet(), "&", "=", doEncode);
URL serverUrl = (doHttps) ? HTTPS_SERVER_URL : _serverUrl;
if (isDebug()) {
StringBuilder debugMsg =
new StringBuilder().append(method).append(" POST: ").append(serverUrl.toString()).append("?");
debugMsg.append(buffer);
log(debugMsg);
}
HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection();
try {
conn.setRequestMethod("POST");
} catch (ProtocolException ex) {
logException(ex);
}
conn.setDoOutput(true);
conn.connect();
conn.getOutputStream().write(buffer.toString().getBytes());
return conn.getInputStream();
}
/**
* Call this function and store the result, using it to generate the
* appropriate login url and then to retrieve the session information.
* @return an authentication token
*/
public String auth_createToken()
throws FacebookException, IOException {
T d = this.callMethod(FacebookMethod.AUTH_CREATE_TOKEN);
return extractString(d);
}
/**
* Extracts a String from a T consisting entirely of a String.
* @param result
* @return the String
*/
protected abstract String extractString(T result);
/**
* Create a marketplace listing
* @param showOnProfile whether the listing can be shown on the user's profile
* @param attrs the properties of the listing
* @return the id of the created listing
* @see MarketplaceListing
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.createListing">
* Developers Wiki: marketplace.createListing</a>
*/
public Long marketplace_createListing(Boolean showOnProfile, MarketplaceListing attrs)
throws FacebookException, IOException {
T result =
this.callMethod(FacebookMethod.MARKETPLACE_CREATE_LISTING,
new Pair<String, CharSequence>("show_on_profile", showOnProfile ? "1" : "0"),
new Pair<String, CharSequence>("listing_id", "0"),
new Pair<String, CharSequence>("listing_attrs", attrs.jsonify().toString()));
return this.extractLong(result);
}
/**
* Modify a marketplace listing
* @param listingId identifies the listing to be modified
* @param showOnProfile whether the listing can be shown on the user's profile
* @param attrs the properties of the listing
* @return the id of the edited listing
* @see MarketplaceListing
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.createListing">
* Developers Wiki: marketplace.createListing</a>
*/
public Long marketplace_editListing(Long listingId, Boolean showOnProfile,
MarketplaceListing attrs)
throws FacebookException, IOException {
T result =
this.callMethod(FacebookMethod.MARKETPLACE_CREATE_LISTING,
new Pair<String, CharSequence>("show_on_profile", showOnProfile ? "1" : "0"),
new Pair<String, CharSequence>("listing_id", listingId.toString()),
new Pair<String, CharSequence>("listing_attrs", attrs.jsonify().toString()));
return this.extractLong(result);
}
/**
* Remove a marketplace listing
* @param listingId the listing to be removed
* @return boolean indicating whether the listing was removed
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.removeListing">
* Developers Wiki: marketplace.removeListing</a>
*/
public boolean marketplace_removeListing(Long listingId)
throws FacebookException, IOException {
return marketplace_removeListing(listingId, MARKETPLACE_STATUS_DEFAULT);
}
/**
* Remove a marketplace listing
* @param listingId the listing to be removed
* @param status MARKETPLACE_STATUS_DEFAULT, MARKETPLACE_STATUS_SUCCESS, or MARKETPLACE_STATUS_NOT_SUCCESS
* @return boolean indicating whether the listing was removed
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.removeListing">
* Developers Wiki: marketplace.removeListing</a>
*/
public boolean marketplace_removeListing(Long listingId, CharSequence status)
throws FacebookException, IOException {
assert MARKETPLACE_STATUS_DEFAULT.equals(status) || MARKETPLACE_STATUS_SUCCESS.equals(status) ||
MARKETPLACE_STATUS_NOT_SUCCESS.equals(status) : "Invalid status: " + status;
T result =
this.callMethod(FacebookMethod.MARKETPLACE_REMOVE_LISTING, new Pair<String, CharSequence>("listing_id",
listingId.toString()),
new Pair<String, CharSequence>("status", status));
return this.extractBoolean(result);
}
/**
* Get the categories available in marketplace.
* @return a T listing the marketplace categories
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.getCategories">
* Developers Wiki: marketplace.getCategories</a>
*/
public T marketplace_getCategories()
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.MARKETPLACE_GET_CATEGORIES);
}
/**
* Get the subcategories available for a category.
* @param category a category, e.g. "HOUSING"
* @return a T listing the marketplace sub-categories
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.getSubCategories">
* Developers Wiki: marketplace.getSubCategories</a>
*/
public T marketplace_getSubCategories(CharSequence category)
throws FacebookException, IOException {
return this.callMethod(FacebookMethod.MARKETPLACE_GET_SUBCATEGORIES,
new Pair<String, CharSequence>("category", category));
}
/**
* Fetch marketplace listings, filtered by listing IDs and/or the posting users' IDs.
* @param listingIds listing identifiers (required if uids is null/empty)
* @param userIds posting user identifiers (required if listingIds is null/empty)
* @return a T of marketplace listings
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.getListings">
* Developers Wiki: marketplace.getListings</a>
*/
public T marketplace_getListings(Collection<Long> listingIds, Collection<Integer> userIds)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.MARKETPLACE_GET_LISTINGS.numParams());
if (null != listingIds && !listingIds.isEmpty()) {
params.add(new Pair<String, CharSequence>("listing_ids", delimit(listingIds)));
}
if (null != userIds && !userIds.isEmpty()) {
params.add(new Pair<String, CharSequence>("uids", delimit(userIds)));
}
assert !params.isEmpty() : "Either listingIds or userIds should be provided";
return this.callMethod(FacebookMethod.MARKETPLACE_GET_LISTINGS, params);
}
/**
* Search for marketplace listings, optionally by category, subcategory, and/or query string.
* @param category the category of listings desired (optional except if subcategory is provided)
* @param subCategory the subcategory of listings desired (optional)
* @param query a query string (optional)
* @return a T of marketplace listings
* @see <a href="http://wiki.developers.facebook.com/index.php/Marketplace.search">
* Developers Wiki: marketplace.search</a>
*/
public T marketplace_search(CharSequence category, CharSequence subCategory, CharSequence query)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.MARKETPLACE_SEARCH.numParams());
if (null != category && !"".equals(category)) {
params.add(new Pair<String, CharSequence>("category", category));
if (null != subCategory && !"".equals(subCategory)) {
params.add(new Pair<String, CharSequence>("subcategory", subCategory));
}
}
if (null != query && !"".equals(query)) {
params.add(new Pair<String, CharSequence>("query", category));
}
return this.callMethod(FacebookMethod.MARKETPLACE_SEARCH, params);
}
/**
* Retrieves the requested profile fields for the Facebook Pages with the given
* <code>pageIds</code>. Can be called for pages that have added the application
* without establishing a session.
* @param pageIds the page IDs
* @param fields a set of page profile fields
* @return a T consisting of a list of pages, with each page element
* containing the requested fields.
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.getInfo">
* Developers Wiki: Pages.getInfo</a>
*/
public T pages_getInfo(Collection<Long> pageIds, EnumSet<PageProfileField> fields)
throws FacebookException, IOException {
if (pageIds == null || pageIds.isEmpty()) {
throw new IllegalArgumentException("pageIds cannot be empty or null");
}
if (fields == null || fields.isEmpty()) {
throw new IllegalArgumentException("fields cannot be empty or null");
}
IFacebookMethod method =
null == this._sessionKey ? FacebookMethod.PAGES_GET_INFO_NO_SESSION : FacebookMethod.PAGES_GET_INFO;
return this.callMethod(method,
new Pair<String, CharSequence>("page_ids", delimit(pageIds)),
new Pair<String, CharSequence>("fields", delimit(fields)));
}
/**
* Retrieves the requested profile fields for the Facebook Pages with the given
* <code>pageIds</code>. Can be called for pages that have added the application
* without establishing a session.
* @param pageIds the page IDs
* @param fields a set of page profile fields
* @return a T consisting of a list of pages, with each page element
* containing the requested fields.
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.getInfo">
* Developers Wiki: Pages.getInfo</a>
*/
public T pages_getInfo(Collection<Long> pageIds, Set<CharSequence> fields)
throws FacebookException, IOException {
if (pageIds == null || pageIds.isEmpty()) {
throw new IllegalArgumentException("pageIds cannot be empty or null");
}
if (fields == null || fields.isEmpty()) {
throw new IllegalArgumentException("fields cannot be empty or null");
}
IFacebookMethod method =
null == this._sessionKey ? FacebookMethod.PAGES_GET_INFO_NO_SESSION : FacebookMethod.PAGES_GET_INFO;
return this.callMethod(method,
new Pair<String, CharSequence>("page_ids", delimit(pageIds)),
new Pair<String, CharSequence>("fields", delimit(fields)));
}
/**
* Retrieves the requested profile fields for the Facebook Pages of the user with the given
* <code>userId</code>.
* @param userId the ID of a user about whose pages to fetch info (defaulted to the logged-in user)
* @param fields a set of PageProfileFields
* @return a T consisting of a list of pages, with each page element
* containing the requested fields.
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.getInfo">
* Developers Wiki: Pages.getInfo</a>
*/
public T pages_getInfo(Integer userId, EnumSet<PageProfileField> fields)
throws FacebookException, IOException {
if (fields == null || fields.isEmpty()) {
throw new IllegalArgumentException("fields cannot be empty or null");
}
if (userId == null) {
userId = this._userId;
}
return this.callMethod(FacebookMethod.PAGES_GET_INFO,
new Pair<String, CharSequence>("uid", userId.toString()),
new Pair<String, CharSequence>("fields", delimit(fields)));
}
/**
* Retrieves the requested profile fields for the Facebook Pages of the user with the given
* <code>userId</code>.
* @param userId the ID of a user about whose pages to fetch info (defaulted to the logged-in user)
* @param fields a set of page profile fields
* @return a T consisting of a list of pages, with each page element
* containing the requested fields.
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.getInfo">
* Developers Wiki: Pages.getInfo</a>
*/
public T pages_getInfo(Integer userId, Set<CharSequence> fields)
throws FacebookException, IOException {
if (fields == null || fields.isEmpty()) {
throw new IllegalArgumentException("fields cannot be empty or null");
}
if (userId == null) {
userId = this._userId;
}
return this.callMethod(FacebookMethod.PAGES_GET_INFO,
new Pair<String, CharSequence>("uid", userId.toString()),
new Pair<String, CharSequence>("fields", delimit(fields)));
}
/**
* Checks whether a page has added the application
* @param pageId the ID of the page
* @return true if the page has added the application
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.isAppAdded">
* Developers Wiki: Pages.isAppAdded</a>
*/
public boolean pages_isAppAdded(Long pageId)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.PAGES_IS_APP_ADDED,
new Pair<String,CharSequence>("page_id", pageId.toString())));
}
/**
* Checks whether a user is a fan of the page with the given <code>pageId</code>.
* @param pageId the ID of the page
* @param userId the ID of the user (defaults to the logged-in user if null)
* @return true if the user is a fan of the page
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.isFan">
* Developers Wiki: Pages.isFan</a>
*/
public boolean pages_isFan(Long pageId, Integer userId)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.PAGES_IS_FAN,
new Pair<String,CharSequence>("page_id", pageId.toString()),
new Pair<String,CharSequence>("uid", userId.toString())));
}
/**
* Checks whether the logged-in user is a fan of the page with the given <code>pageId</code>.
* @param pageId the ID of the page
* @return true if the logged-in user is a fan of the page
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.isFan">
* Developers Wiki: Pages.isFan</a>
*/
public boolean pages_isFan(Long pageId)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.PAGES_IS_FAN,
new Pair<String,CharSequence>("page_id", pageId.toString())));
}
/**
* Checks whether the logged-in user for this session is an admin of the page
* with the given <code>pageId</code>.
* @param pageId the ID of the page
* @return true if the logged-in user is an admin
* @see <a href="http://wiki.developers.facebook.com/index.php/Pages.isAdmin">
* Developers Wiki: Pages.isAdmin</a>
*/
public boolean pages_isAdmin(Long pageId)
throws FacebookException, IOException {
return extractBoolean(this.callMethod(FacebookMethod.PAGES_IS_ADMIN,
new Pair<String, CharSequence>("page_id",
pageId.toString())));
}
/**
* Sets several property values for an application. The properties available
* are analogous to the ones editable via the Facebook Developer application.
* A session is not required to use this method.
* @param properties an ApplicationPropertySet that is translated into
* a single JSON String.
* @return a boolean indicating whether the properties were successfully set
*/
public boolean admin_setAppProperties(ApplicationPropertySet properties)
throws FacebookException, IOException {
if (null == properties || properties.isEmpty()) {
throw new IllegalArgumentException("expecting a non-empty set of application properties");
}
return extractBoolean(this.callMethod(FacebookMethod.ADMIN_SET_APP_PROPERTIES,
new Pair<String, CharSequence>("properties", properties.toJsonString())));
}
/**
* Gets property values previously set for an application on either the Facebook Developer application or
* the with the <code>admin.setAppProperties</code> call.
* A session is not required to use this method.
* @param properties an enumeration of the properties to get
* @return an ApplicationPropertySet
* @see ApplicationProperty
* @see <a href="http://wiki.developers.facebook.com/index.php/Admin.getAppProperties">
* Developers Wiki: Admin.getAppProperties</a>
*/
public ApplicationPropertySet admin_getAppProperties(EnumSet<ApplicationProperty> properties)
throws FacebookException, IOException {
if (null == properties || properties.isEmpty()) {
throw new IllegalArgumentException("expecting a non-empty set of application properties");
}
JSONArray propList = new JSONArray();
for (ApplicationProperty prop : properties) {
propList.add(prop.propertyName());
}
String propJson =
extractString(this.callMethod(FacebookMethod.ADMIN_GET_APP_PROPERTIES,
new Pair<String, CharSequence>("properties", propList.toString())));
return new ApplicationPropertySet(propJson);
}
/**
* Retrieves all cookies for the application and the given <code>userId</code>.
* If a <code>cookieName</code> is specified, only that cookie will be returned.
*
* @param userId The user from whom to get the cookies (defaults to logged-in user).
* @param cookieName The name of the cookie to get. If null, all cookies
* will be returned
* @return a T of cookies.
* @see <a href="http://wiki.developers.facebook.com/index.php/Data.getCookies">
* Developers Wiki: Data.getCookies</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Cookies">
* Developers Wiki: Cookies</a>
*/
public T data_getCookies(Integer userId, CharSequence cookieName)
throws FacebookException, IOException {
Collection<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.DATA_GET_COOKIES.numParams());
params.add(new Pair<String,CharSequence>("uid", userId.toString()));
if (null != cookieName) {
params.add(new Pair<String,CharSequence>("name", cookieName.toString()));
}
return this.callMethod(FacebookMethod.DATA_GET_COOKIES, params);
}
/**
* Retrieves all cookies for the application and the given <code>userId</code>.
*
* @param userId The user from whom to get the cookies (defaults to logged-in user).
* @return a T of cookies.
* @see <a href="http://wiki.developers.facebook.com/index.php/Data.getCookies">
* Developers Wiki: Data.getCookies</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Cookies">
* Developers Wiki: Cookies</a>
*/
public T data_getCookies(Integer userId)
throws FacebookException, IOException {
return data_getCookies(userId, /*cookieName*/ null);
}
/**
* Sets a cookie for a given user and application.
* @param userId The user for whom this cookie needs to be set
* @param cookieName Name of the cookie.
* @param cookieValue Value of the cookie.
* @return true if cookie was successfully set, false otherwise
* @see <a href="http://wiki.developers.facebook.com/index.php/Data.getCookies">
* Developers Wiki: Data.setCookie</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Cookies">
* Developers Wiki: Cookies</a>
*/
public boolean data_setCookie(Integer userId, CharSequence cookieName, CharSequence cookieValue)
throws FacebookException, IOException {
return data_setCookie(userId, cookieName, cookieValue, /*expiresTimestamp*/null, /*path*/ null);
}
/**
* Sets a cookie for a given user and application.
* @param userId The user for whom this cookie needs to be set
* @param cookieName Name of the cookie.
* @param cookieValue Value of the cookie.
* @param path Path relative to the application's callback URL, with which the cookie should be associated.
* If null, defaulted to "/"
* @return true if cookie was successfully set, false otherwise
* @see <a href="http://wiki.developers.facebook.com/index.php/Data.getCookies">
* Developers Wiki: Data.setCookie</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Cookies">
* Developers Wiki: Cookies</a>
*/
public boolean data_setCookie(Integer userId, CharSequence cookieName, CharSequence cookieValue, CharSequence path)
throws FacebookException, IOException {
return data_setCookie(userId, cookieName, cookieValue, /*expiresTimestamp*/null, path);
}
/**
* Sets a cookie for a given user and application.
* @param userId The user for whom this cookie needs to be set
* @param cookieName Name of the cookie.
* @param cookieValue Value of the cookie.
* @param expiresTimestamp Time stamp when the cookie should expire. If not specified, the cookie never expires.
* @return true if cookie was successfully set, false otherwise
* @see <a href="http://wiki.developers.facebook.com/index.php/Data.getCookies">
* Developers Wiki: Data.setCookie</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Cookies">
* Developers Wiki: Cookies</a>
*/
public boolean data_setCookie(Integer userId, CharSequence cookieName, CharSequence cookieValue, Long expiresTimestamp)
throws FacebookException, IOException {
return data_setCookie(userId, cookieName, cookieValue, expiresTimestamp, /*path*/ null);
}
/**
* Sets a cookie for a given user and application.
* @param userId The user for whom this cookie needs to be set
* @param cookieName Name of the cookie.
* @param cookieValue Value of the cookie.
* @param expiresTimestamp Time stamp when the cookie should expire. If not specified, the cookie never expires.
* @return true if cookie was successfully set, false otherwise
* @see <a href="http://wiki.developers.facebook.com/index.php/Data.getCookies">
* Developers Wiki: Data.setCookie</a>
* @see <a href="http://wiki.developers.facebook.com/index.php/Cookies">
* Developers Wiki: Cookies</a>
*/
public boolean data_setCookie(Integer userId, CharSequence cookieName, CharSequence cookieValue, Long expiresTimestamp, CharSequence path)
throws FacebookException, IOException {
if (null == userId || 0 >= userId)
throw new IllegalArgumentException("userId should be provided.");
if (null == cookieName || null == cookieValue)
throw new IllegalArgumentException("cookieName and cookieValue should be provided.");
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(FacebookMethod.DATA_GET_COOKIES.numParams());
params.add(new Pair<String, CharSequence>("uid", userId.toString()));
params.add(new Pair<String, CharSequence>("name", cookieName));
params.add(new Pair<String, CharSequence>("value", cookieValue));
if (null != expiresTimestamp && expiresTimestamp >= 0L)
params.add(new Pair<String, CharSequence>("expires", expiresTimestamp.toString()));
if (null != path)
params.add(new Pair<String, CharSequence>("path", path));
return extractBoolean(this.callMethod(FacebookMethod.DATA_GET_COOKIES, params));
}
public boolean data_setUserPreference(Integer did, String value)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(2);
params.add(new Pair<String, CharSequence>("pref_id", did.toString()));
params.add(new Pair<String, CharSequence>("value", value));
return extractBoolean(this.callMethod(FacebookMethod.DATA_SET_USERPREF, params));
}
public T data_getUserPreference(Integer did)
throws FacebookException, IOException {
ArrayList<Pair<String, CharSequence>> params =
new ArrayList<Pair<String, CharSequence>>(1);
params.add(new Pair<String, CharSequence>("pref_id", did.toString()));
return this.callMethod(FacebookMethod.DATA_GET_USERPREF, params);
}
}