001/*
002 * Copyright (c) 2010-2024 Mark Allen, Norbert Bartels.
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a copy
005 * of this software and associated documentation files (the "Software"), to deal
006 * in the Software without restriction, including without limitation the rights
007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008 * copies of the Software, and to permit persons to whom the Software is
009 * furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
020 * THE SOFTWARE.
021 */
022package com.restfb;
023
024import java.util.List;
025
026import com.restfb.batch.BatchRequest;
027import com.restfb.batch.BatchResponse;
028import com.restfb.exception.*;
029import com.restfb.exception.devicetoken.FacebookDeviceTokenCodeExpiredException;
030import com.restfb.exception.devicetoken.FacebookDeviceTokenDeclinedException;
031import com.restfb.exception.devicetoken.FacebookDeviceTokenPendingException;
032import com.restfb.exception.devicetoken.FacebookDeviceTokenSlowdownException;
033import com.restfb.scope.ScopeBuilder;
034import com.restfb.types.DebugTokenInfo;
035import com.restfb.types.DeviceCode;
036
037/**
038 * Specifies how a <a href="http://developers.facebook.com/docs/api">Facebook Graph API</a> client must operate.
039 * <p>
040 * If you'd like to...
041 * 
042 * <ul>
043 * <li>Fetch an object: use {@link #fetchObject(String, Class, Parameter...)} or
044 * {@link #fetchObjects(List, Class, Parameter...)}</li>
045 * <li>Fetch a connection: use {@link #fetchConnection(String, Class, Parameter...)}</li>
046 * <li>Execute operations in batch: use {@link #executeBatch(BatchRequest...)} or {@link #executeBatch(List, List)}</li>
047 * <li>Publish data: use {@link #publish(String, Class, Parameter...)} or
048 * {@link #publish(String, Class, BinaryAttachment, Parameter...)}</li>
049 * <li>Delete an object: use {@link #deleteObject(String, Parameter...)}</li>
050 * </ul>
051 * 
052 * <p>
053 * You may also perform some common access token operations. If you'd like to...
054 * 
055 * <ul>
056 * <li>Extend the life of an access token: use {@link #obtainExtendedAccessToken(String, String, String)}</li>
057 * <li>Obtain an access token for use on behalf of an application instead of a user, use
058 * {@link #obtainAppAccessToken(String, String)}.</li>
059 * <li>Convert old-style session keys to OAuth access tokens: use
060 * {@link #convertSessionKeysToAccessTokens(String, String, String...)}</li>
061 * <li>Verify and extract data from a signed request: use {@link #parseSignedRequest(String, String, Class)}</li>
062 * </ul>
063 * 
064 * @author <a href="http://restfb.com">Mark Allen</a>
065 * @author Scott Hernandez
066 * @author Mattia Tommasone
067 * @author <a href="http://ex-nerd.com">Chris Petersen</a>
068 * @author Josef Gierbl
069 * @author Broc Seib
070 */
071public interface FacebookClient {
072  /**
073   * Fetches a single <a href="http://developers.facebook.com/docs/reference/api/">Graph API object</a>, mapping the
074   * result to an instance of {@code objectType}.
075   * 
076   * @param <T>
077   *          Java type to map to.
078   * @param object
079   *          ID of the object to fetch, e.g. {@code "me"}.
080   * @param objectType
081   *          Object type token.
082   * @param parameters
083   *          URL parameters to include in the API call (optional).
084   * @return An instance of type {@code objectType} which contains the requested object's data.
085   * @throws FacebookException
086   *           If an error occurs while performing the API call.
087   */
088  <T> T fetchObject(String object, Class<T> objectType, Parameter... parameters);
089
090  /**
091   * creates a new <code>FacebookClient</code> from an old one.
092   * <p>
093   * App secret and api version are taken from the original client.
094   *
095   * @param accessToken
096   *          this accesstoken is used for the new client
097   * @return a new Facebookclient
098   */
099  FacebookClient createClientWithAccessToken(String accessToken);
100
101  /**
102   * Fetches multiple <a href="http://developers.facebook.com/docs/reference/api/">Graph API objects</a> in a single
103   * call, mapping the results to an instance of {@code objectType}.
104   * <p>
105   * You'll need to write your own container type ({@code objectType}) to hold the results. See
106   * <a href="http://restfb.com">http://restfb.com</a> for an example of how to do this.
107   * 
108   * @param <T>
109   *          Java type to map to.
110   * @param ids
111   *          IDs of the objects to fetch, e.g. {@code "me", "arjun"}.
112   * @param objectType
113   *          Object type token.
114   * @param parameters
115   *          URL parameters to include in the API call (optional).
116   * @return An instance of type {@code objectType} which contains the requested objects' data.
117   * @throws FacebookException
118   *           If an error occurs while performing the API call.
119   */
120  <T> T fetchObjects(List<String> ids, Class<T> objectType, Parameter... parameters);
121
122  /**
123   * Fetches a Graph API {@code Connection} type, mapping the result to an instance of {@code connectionType}.
124   * 
125   * @param <T>
126   *          Java type to map to.
127   * @param connection
128   *          The name of the connection, e.g. {@code "me/feed"}.
129   * @param connectionType
130   *          Connection type token.
131   * @param parameters
132   *          URL parameters to include in the API call (optional).
133   * @return An instance of type {@code connectionType} which contains the requested Connection's data.
134   * @throws FacebookException
135   *           If an error occurs while performing the API call.
136   */
137  <T> Connection<T> fetchConnection(String connection, Class<T> connectionType, Parameter... parameters);
138
139  /**
140   * Fetches a previous/next page of a Graph API {@code Connection} type, mapping the result to an instance of
141   * {@code connectionType}.
142   * 
143   * @param <T>
144   *          Java type to map to.
145   * @param connectionPageUrl
146   *          The URL of the connection page to fetch, usually retrieved via {@link Connection#getPreviousPageUrl()} or
147   *          {@link Connection#getNextPageUrl()}.
148   * @param connectionType
149   *          Connection type token.
150   * @return An instance of type {@code connectionType} which contains the requested Connection's data.
151   * @throws FacebookException
152   *           If an error occurs while performing the API call.
153   */
154  <T> Connection<T> fetchConnectionPage(String connectionPageUrl, Class<T> connectionType);
155
156  /**
157   * Executes operations as a batch using the <a href="https://developers.facebook.com/docs/reference/api/batch/">Batch
158   * API</a>.
159   * 
160   * @param batchRequests
161   *          The operations to execute.
162   * @return The execution results in the order in which the requests were specified.
163   */
164  List<BatchResponse> executeBatch(BatchRequest... batchRequests);
165
166  /**
167   * Executes operations as a batch using the <a href="https://developers.facebook.com/docs/reference/api/batch/">Batch
168   * API</a>.
169   * 
170   * @param batchRequests
171   *          The operations to execute.
172   * @return The execution results in the order in which the requests were specified.
173   */
174  List<BatchResponse> executeBatch(List<BatchRequest> batchRequests);
175
176  /**
177   * Executes operations as a batch with binary attachments using the
178   * <a href="https://developers.facebook.com/docs/reference/api/batch/">Batch API</a>.
179   * 
180   * @param batchRequests
181   *          The operations to execute.
182   * @param binaryAttachments
183   *          Binary attachments referenced by the batch requests.
184   * @return The execution results in the order in which the requests were specified.
185   * @since 1.6.5
186   */
187  List<BatchResponse> executeBatch(List<BatchRequest> batchRequests, List<BinaryAttachment> binaryAttachments);
188
189  /**
190   * Performs a <a href="http://developers.facebook.com/docs/api#publishing">Graph API publish</a> operation on the
191   * given {@code connection}, mapping the result to an instance of {@code objectType}.
192   * 
193   * @param <T>
194   *          Java type to map to.
195   * @param connection
196   *          The Connection to publish to.
197   * @param objectType
198   *          Object type token.
199   * @param parameters
200   *          URL parameters to include in the API call.
201   * @return An instance of type {@code objectType} which contains the Facebook response to your publish request.
202   * @throws FacebookException
203   *           If an error occurs while performing the API call.
204   */
205  <T> T publish(String connection, Class<T> objectType, Parameter... parameters);
206
207  /**
208   * Performs a <a href="http://developers.facebook.com/docs/api#publishing">Graph API publish</a> operation on the
209   * given {@code connection} and includes some files - photos, for example - in the publish request, and mapping the
210   * result to an instance of {@code objectType}.
211   * 
212   * @param <T>
213   *          Java type to map to.
214   * @param connection
215   *          The Connection to publish to.
216   * @param objectType
217   *          Object type token.
218   * @param binaryAttachments
219   *          The files to include in the publish request.
220   * @param parameters
221   *          URL parameters to include in the API call.
222   * @return An instance of type {@code objectType} which contains the Facebook response to your publish request.
223   * @throws FacebookException
224   *           If an error occurs while performing the API call.
225   */
226  <T> T publish(String connection, Class<T> objectType, List<BinaryAttachment> binaryAttachments,
227      Parameter... parameters);
228
229  /**
230   * Performs a <a href="http://developers.facebook.com/docs/api#publishing">Graph API publish</a> operation on the
231   * given {@code connection} and includes a file - a photo, for example - in the publish request, and mapping the
232   * result to an instance of {@code objectType}.
233   * 
234   * @param <T>
235   *          Java type to map to.
236   * @param connection
237   *          The Connection to publish to.
238   * @param objectType
239   *          Object type token.
240   * @param binaryAttachment
241   *          The file to include in the publish request.
242   * @param parameters
243   *          URL parameters to include in the API call.
244   * @return An instance of type {@code objectType} which contains the Facebook response to your publish request.
245   * @throws FacebookException
246   *           If an error occurs while performing the API call.
247   */
248  <T> T publish(String connection, Class<T> objectType, BinaryAttachment binaryAttachment, Parameter... parameters);
249
250  /**
251   * Performs a <a href="http://developers.facebook.com/docs/api#publishing">Graph API publish</a> operation on the
252   * given {@code connection} and includes special body in the publish request, and mapping the result to an instance of
253   * {@code objectType}.
254   *
255   * @param <T>
256   *          Java type to map to.
257   * @param connection
258   *          The Connection to publish to.
259   * @param objectType
260   *          Object type token.
261   * @param body
262   *          The body used in the POST request.
263   * @param parameters
264   *          URL parameters to include in the API call.
265   * @return An instance of type {@code objectType} which contains the Facebook response to your publish request.
266   * @throws FacebookException
267   *           If an error occurs while performing the API call.
268   */
269  <T> T publish(String connection, Class<T> objectType, Body body, Parameter... parameters);
270
271  /**
272   * Performs a <a href="http://developers.facebook.com/docs/api#deleting">Graph API delete</a> operation on the given
273   * {@code object}.
274   * 
275   * @param object
276   *          The ID of the object to delete.
277   * @param parameters
278   *          URL parameters to include in the API call.
279   * @return {@code true} if Facebook indicated that the object was successfully deleted, {@code false} otherwise.
280   * @throws FacebookException
281   *           If an error occurred while attempting to delete the object.
282   */
283  boolean deleteObject(String object, Parameter... parameters);
284
285  /**
286   * Converts an arbitrary number of {@code sessionKeys} to OAuth access tokens.
287   * <p>
288   * See the <a href="http://developers.facebook.com/docs/guides/upgrade">Facebook Platform Upgrade Guide</a> for
289   * details on how this process works and why you should convert your application's session keys if you haven't
290   * already.
291   * 
292   * @param appId
293   *          A Facebook application ID.
294   * @param secretKey
295   *          A Facebook application secret key.
296   * @param sessionKeys
297   *          The Old REST API session keys to be converted to OAuth access tokens.
298   * @return A list of access tokens ordered to correspond to the {@code sessionKeys} argument list.
299   * @throws FacebookException
300   *           If an error occurs while attempting to convert the session keys to API keys.
301   * @since 1.6
302   */
303  List<AccessToken> convertSessionKeysToAccessTokens(String appId, String secretKey, String... sessionKeys);
304
305  /**
306   * Obtains an access token which can be used to perform Graph API operations on behalf of a user.
307   * <p>
308   * See <a href="https://developers.facebook.com/docs/facebook-login/access-tokens">Access Tokens</a>.
309   *
310   * @param appId
311   *          The ID of the app for which you'd like to obtain an access token.
312   * @param appSecret
313   *          The secret for the app for which you'd like to obtain an access token.
314   * @param redirectUri
315   *          The redirect URI which was used to obtain the {@code verificationCode}.
316   * @param verificationCode
317   *          The verification code in the Graph API callback to the redirect URI.
318   * @return The access token for the user identified by {@code appId}, {@code appSecret}, {@code redirectUri} and
319   *         {@code verificationCode}.
320   * @throws FacebookException
321   *           If an error occurs while attempting to obtain an access token.
322   * @since 1.8.0
323   */
324  AccessToken obtainUserAccessToken(String appId, String appSecret, String redirectUri, String verificationCode);
325
326  /**
327   * Obtains an access token which can be used to perform Graph API operations on behalf of an application instead of a
328   * user.
329   * <p>
330   * See <a href="https://developers.facebook.com/docs/authentication/applications/" >Facebook's authenticating as an
331   * app documentation</a>.
332   * 
333   * @param appId
334   *          The ID of the app for which you'd like to obtain an access token.
335   * @param appSecret
336   *          The secret for the app for which you'd like to obtain an access token.
337   * @return The access token for the application identified by {@code appId} and {@code appSecret}.
338   * @throws FacebookException
339   *           If an error occurs while attempting to obtain an access token.
340   * @since 1.6.10
341   */
342  AccessToken obtainAppAccessToken(String appId, String appSecret);
343
344  /**
345   * Obtains an extended access token for the given existing, non-expired, short-lived access_token.
346   * <p>
347   * See <a href="https://developers.facebook.com/roadmap/offline-access-removal/#extend_token">Facebook's extend access
348   * token documentation</a>.
349   * 
350   * @param appId
351   *          The ID of the app for which you'd like to obtain an extended access token.
352   * @param appSecret
353   *          The secret for the app for which you'd like to obtain an extended access token.
354   * @param accessToken
355   *          The non-expired, short-lived access token to extend.
356   * @return An extended access token for the given {@code accessToken}.
357   * @throws FacebookException
358   *           If an error occurs while attempting to obtain an extended access token.
359   * @since 1.6.10
360   */
361  AccessToken obtainExtendedAccessToken(String appId, String appSecret, String accessToken);
362
363  /**
364   * Generates an {@code appsecret_proof} value.
365   * <p>
366   * See <a href="https://developers.facebook.com/docs/graph-api/securing-requests">Facebook's 'securing requests'
367   * documentation</a> for more info.
368   * 
369   * @param accessToken
370   *          The access token required to generate the {@code appsecret_proof} value.
371   * @param appSecret
372   *          The secret for the app for which you'd like to generate the {@code appsecret_proof} value.
373   * @return A hex-encoded SHA256 hash as a {@code String}.
374   * @throws IllegalStateException
375   *           If creating the {@code appsecret_proof} fails.
376   * @since 1.6.13
377   */
378  String obtainAppSecretProof(String accessToken, String appSecret);
379
380  /**
381   * Convenience method which invokes {@link #obtainExtendedAccessToken(String, String, String)} with the current access
382   * token.
383   * 
384   * @param appId
385   *          The ID of the app for which you'd like to obtain an extended access token.
386   * @param appSecret
387   *          The secret for the app for which you'd like to obtain an extended access token.
388   * @return An extended access token for the given {@code accessToken}.
389   * @throws FacebookException
390   *           If an error occurs while attempting to obtain an extended access token.
391   * @throws IllegalStateException
392   *           If this instance was not constructed with an access token.
393   * @since 1.6.10
394   */
395  AccessToken obtainExtendedAccessToken(String appId, String appSecret);
396
397  /**
398   * Obtain a refreshed Instagram extended access token.
399   *
400   * <p>
401   * This method is used to refresh an existing Instagram extended access token. Extended access tokens expire after a
402   * certain period of time, and this method allows you to obtain a new one using the refresh token provided with the
403   * original extended access token.
404   *
405   * @return A new {@link AccessToken} object containing the refreshed access token, expiration time, and token type.
406   * @throws FacebookResponseContentException
407   *           If the response from the Facebook API cannot be parsed or if the access token cannot be extracted from
408   *           the response.
409   */
410  AccessToken obtainRefreshedExtendedAccessToken();
411
412  /**
413   * Parses a signed request and verifies it against your App Secret.
414   * <p>
415   * See <a href="http://developers.facebook.com/docs/howtos/login/signed-request/">Facebook's signed request
416   * documentation</a>.
417   * 
418   * @param signedRequest
419   *          The signed request to parse.
420   * @param appSecret
421   *          The secret for the app that can read this signed request.
422   * @param objectType
423   *          Object type token.
424   * @param <T>
425   *          class of objectType
426   * @return An instance of type {@code objectType} which contains the decoded object embedded within
427   *         {@code signedRequest}.
428   * @throws FacebookSignedRequestParsingException
429   *           If an error occurs while trying to process {@code signedRequest}.
430   * @throws FacebookSignedRequestVerificationException
431   *           If {@code signedRequest} fails verification against {@code appSecret}.
432   * @since 1.6.13
433   */
434  <T> T parseSignedRequest(String signedRequest, String appSecret, Class<T> objectType);
435
436  /**
437   * Method to initialize the device access token generation.
438   * <p>
439   * You receive a {@link DeviceCode} instance and have to show the user the {@link DeviceCode#getVerificationUri()} and
440   * the {@link DeviceCode#getUserCode()}. The user have to enter the user code at the verification url.
441   * <p>
442   * Save the {@link DeviceCode#getCode()} to use it later, when polling Facebook with the
443   * {@link #obtainDeviceAccessToken(java.lang.String)} method.
444   *
445   * @param scope
446   *          List of Permissions to request from the person using your app.
447   * @return Instance of {@code DeviceCode} including the information to obtain the Device access token
448   */
449  DeviceCode fetchDeviceCode(ScopeBuilder scope);
450
451  /**
452   * Method to poll Facebook and fetch the Device Access Token.
453   * <p>
454   * You have to use this method to check if the user confirms the authorization.
455   * <p>
456   * {@link FacebookOAuthException} can be thrown if the authorization is declined or still pending.
457   *
458   * @param code
459   *          The device
460   * @return An extended access token for the given {@link AccessToken}.
461   * @throws com.restfb.exception.devicetoken.FacebookDeviceTokenCodeExpiredException
462   *           the {@link DeviceCode#getCode()} is expired, please fetch a new {@link DeviceCode}.
463   * @throws com.restfb.exception.devicetoken.FacebookDeviceTokenPendingException
464   *           the user has not finished the authorisation process, yet. Please poll again later.
465   * @throws com.restfb.exception.devicetoken.FacebookDeviceTokenDeclinedException
466   *           the user declined the authorisation. You have to handle this problem.
467   * @throws com.restfb.exception.devicetoken.FacebookDeviceTokenSlowdownException
468   *           you tried too often to fetch the device access token. You have to use a larger interval
469   * @since 1.12.0
470   */
471  AccessToken obtainDeviceAccessToken(String code) throws FacebookDeviceTokenCodeExpiredException,
472      FacebookDeviceTokenPendingException, FacebookDeviceTokenDeclinedException, FacebookDeviceTokenSlowdownException;
473
474  /**
475   * <p>
476   * When working with access tokens, you may need to check what information is associated with them, such as its user
477   * or expiry. To get this information you can use the debug tool in the developer site, or you can use this function.
478   * </p>
479   * 
480   * <p>
481   * You must instantiate your FacebookClient using your App Access Token, or a valid User Access Token from a developer
482   * of the app.
483   * </p>
484   * 
485   * <p>
486   * Note that if your app is set to Native/Desktop in the Advanced settings of your App Dashboard, the underlying
487   * GraphAPI endpoint will not work with your app token unless you change the "App Secret in Client" setting to NO. If
488   * you do not see this setting, make sure your "App Type" is set to Native/Desktop and then press the save button at
489   * the bottom of the page. This will not affect apps set to Web.
490   * </p>
491   * 
492   * <p>
493   * The response of the API call is a JSON array containing data and a map of fields. For example:
494   * </p>
495   * 
496   * <pre>
497   * {@code
498   * {
499   *     "data": {
500   *         "app_id": 138483919580948, 
501   *         "application": "Social Cafe", 
502   *         "expires_at": 1352419328, 
503   *         "is_valid": true, 
504   *         "issued_at": 1347235328, 
505   *         "metadata": {
506   *             "sso": "iphone-safari"
507   *         }, 
508   *         "scopes": [
509   *             "email", 
510   *             "publish_actions"
511   *         ], 
512   *         "user_id": 1207059
513   *     }
514   * }
515   * }
516   * </pre>
517   * 
518   * <p>
519   * Note that the {@code issued_at} field is not returned for short-lived access tokens.
520   * </p>
521   * 
522   * <p>
523   * See <a href="https://developers.facebook.com/docs/howtos/login/debugging-access-tokens/"> Debugging an Access
524   * Token</a>
525   * </p>
526   * 
527   * @param inputToken
528   *          The Access Token to debug.
529   * 
530   * @return A JsonObject containing the debug information for the accessToken.
531   * @since 1.6.13
532   */
533  DebugTokenInfo debugToken(String inputToken);
534
535  /**
536   * Gets the {@code JsonMapper} used to convert Facebook JSON to Java objects.
537   * 
538   * @return The {@code JsonMapper} used to convert Facebook JSON to Java objects.
539   * @since 1.6.7
540   */
541  JsonMapper getJsonMapper();
542
543  /**
544   * Gets the {@code WebRequestor} used to talk to the Facebook API endpoints.
545   * 
546   * @return The {@code WebRequestor} used to talk to the Facebook API endpoints.
547   * @since 1.6.7
548   */
549  WebRequestor getWebRequestor();
550
551  /**
552   * generates an logout url
553   * 
554   * @param next
555   *          may be null, url the webpage should redirect after logout
556   * @return the logout url
557   * @since 1.9.0
558   */
559  String getLogoutUrl(String next);
560
561  /**
562   * generates the login dialog url
563   *
564   * @param appId
565   *          The ID of your app, found in your app's dashboard.
566   * @param redirectUri
567   *          The URL that you want to redirect the person logging in back to. This URL will capture the response from
568   *          the Login Dialog. If you are using this in a webview within a desktop app, this must be set to
569   *          <code>https://www.facebook.com/connect/login_success.html</code>.
570   * @param scope
571   *          List of Permissions to request from the person using your app.
572   * @param state
573   *         The state parameter is used to prevent CSRF attacks.
574   * @param parameters
575   *          List of additional parameters
576   * @since 1.9.0
577   * @return the login dialog url
578   */
579  String getLoginDialogUrl(String appId, String redirectUri, ScopeBuilder scope, String state, Parameter... parameters);
580
581  /**
582   * generates the login dialog url
583   * 
584   * @param appId
585   *          The ID of your app, found in your app's dashboard.
586   * @param redirectUri
587   *          The URL that you want to redirect the person logging in back to. This URL will capture the response from
588   *          the Login Dialog. If you are using this in a webview within a desktop app, this must be set to
589   *          <code>https://www.facebook.com/connect/login_success.html</code>.
590   * @param scope
591   *          List of Permissions to request from the person using your app.
592   * @param additionalParameters
593   *          List of additional parameters
594   * @since 1.9.0
595   * @return the login dialog url
596   */
597  String getLoginDialogUrl(String appId, String redirectUri, ScopeBuilder scope, Parameter... additionalParameters);
598
599}