add com.github.jreddit:1.0.4 package
This commit is contained in:
		
							parent
							
								
									3f65168b94
								
							
						
					
					
						commit
						4b47d907cd
					
				| @ -4,7 +4,14 @@ repositories { | ||||
| apply plugin: "java" | ||||
| 
 | ||||
| dependencies { | ||||
|     compile "com.github.jreddit:jreddit:1.0.3" | ||||
|     //compile "com.github.jreddit:jreddit:1.0.3" //not supported by reddit api anymore | ||||
|     //jreddit 1.0.4 dependencies | ||||
|     compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1' | ||||
|     compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.3' | ||||
|     compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.0' | ||||
|     testCompile group: 'commons-validator', name: 'commons-validator', version: '1.4.1' | ||||
|     testCompile group: 'junit', name: 'junit', version: '4.8.1' | ||||
|     testCompile group: 'org.mockito', name: 'mockito-core', version: '1.9.5' | ||||
| } | ||||
| 
 | ||||
| sourceSets { | ||||
|  | ||||
							
								
								
									
										370
									
								
								src/main/com/github/jreddit/oauth/RedditOAuthAgent.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								src/main/com/github/jreddit/oauth/RedditOAuthAgent.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,370 @@ | ||||
| package com.github.jreddit.oauth; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import javax.xml.bind.DatatypeConverter; | ||||
| 
 | ||||
| import org.apache.oltu.oauth2.client.OAuthClient; | ||||
| import org.apache.oltu.oauth2.client.URLConnectionClient; | ||||
| import org.apache.oltu.oauth2.client.request.OAuthClientRequest; | ||||
| import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; | ||||
| import org.apache.oltu.oauth2.common.OAuthProviderType; | ||||
| import org.apache.oltu.oauth2.common.exception.OAuthProblemException; | ||||
| import org.apache.oltu.oauth2.common.exception.OAuthSystemException; | ||||
| import org.apache.oltu.oauth2.common.message.types.GrantType; | ||||
| 
 | ||||
| import com.github.jreddit.oauth.app.RedditApp; | ||||
| import com.github.jreddit.oauth.exception.RedditOAuthException; | ||||
| import com.github.jreddit.oauth.param.RedditDuration; | ||||
| import com.github.jreddit.oauth.param.RedditScopeBuilder; | ||||
| import com.github.jreddit.request.util.KeyValueFormatter; | ||||
| 
 | ||||
| /** | ||||
|  * Thread-safe reddit OAuth agent.<br> | ||||
|  * <br> | ||||
|  * Communicates with reddit to retrieve tokens, and converts them | ||||
|  * into {@link RedditToken}s, which are used internally by jReddit. This class | ||||
|  * supports both the <i>code grant flow</i> and <i>implicit grant flow</i>. | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class RedditOAuthAgent { | ||||
|      | ||||
|     /** Reddit authorization endpoint. */ | ||||
|     private static final String REDDIT_AUTHORIZE = "https://www.reddit.com/api/v1/authorize?"; | ||||
|      | ||||
|     /** Grant type for an installed client (weirdly enough a URI). */ | ||||
|     private static final String GRANT_TYPE_INSTALLED_CLIENT = "https://oauth.reddit.com/grants/installed_client"; | ||||
|      | ||||
|     /** Grant type for client credentials (described in OAuth2 standard). */ | ||||
|     private static final String GRANT_TYPE_CLIENT_CREDENTIALS = "client_credentials"; | ||||
|      | ||||
|     /* Parameter keys */ | ||||
|     private static final String PARAM_CLIENT_ID = "client_id"; | ||||
|     private static final String PARAM_RESPONSE_TYPE = "response_type"; | ||||
|     private static final String PARAM_STATE = "state"; | ||||
|     private static final String PARAM_REDIRECT_URI = "redirect_uri"; | ||||
|     private static final String PARAM_DURATION = "duration"; | ||||
|     private static final String PARAM_SCOPE = "scope"; | ||||
|     private static final String PARAM_GRANT_TYPE = "grant_type"; | ||||
|     private static final String PARAM_CODE = "code"; | ||||
|     private static final String PARAM_DEVICE_ID = "device_id"; | ||||
|      | ||||
|     /* Header keys */ | ||||
|     private static final String HEADER_USER_AGENT = "User-Agent"; | ||||
|     private static final String HEADER_AUTHORIZATION = "Authorization"; | ||||
|      | ||||
|     /** User agent. */ | ||||
|     private final String userAgent; | ||||
|      | ||||
|     /** OAuth2 client for OAuth related requests. */ | ||||
|     private OAuthClient oAuthClient; | ||||
|      | ||||
|     /** Reddit application. */ | ||||
|     private RedditApp redditApp; | ||||
|      | ||||
|     /** | ||||
|      * Constructor for a Reddit OAuth agent.<br> | ||||
|      * <br> | ||||
|      * A default Apache OAuthClient will be made to perform the OAuth communication. | ||||
|      *  | ||||
|      * @param userAgent User agent for your application (e.g. "jReddit: Reddit API Wrapper for Java") | ||||
|      * @param redditApp Reddit application | ||||
|      */ | ||||
|     public RedditOAuthAgent(String userAgent, RedditApp redditApp) { | ||||
|         this(userAgent, redditApp, new OAuthClient(new URLConnectionClient())); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Constructor for a Reddit OAuth agent. | ||||
|      *  | ||||
|      * @param userAgent User agent for your application (e.g. "jReddit: Reddit API Wrapper for Java") | ||||
|      * @param redditApp Reddit application | ||||
|      * @param oAuthClient Apache OAuth2 client | ||||
|      */ | ||||
|     public RedditOAuthAgent(String userAgent, RedditApp redditApp, OAuthClient oAuthClient) { | ||||
|         this.userAgent = userAgent; | ||||
|         this.redditApp = redditApp; | ||||
|         this.oAuthClient = oAuthClient; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate the <i>code flow</i> Uniform Resource Locator (URI) for a | ||||
|      * reddit user to authorize your application.<br> | ||||
|      * <br> | ||||
|      * The user will, after authorization, receive a <i>code</i>. This can be turned into | ||||
|      * a <i>RedditToken</i> using {@link #token(String)}. | ||||
|      *  | ||||
|      * @param scopeBuilder Authorization scope builder (must not be <i>null</i>) | ||||
|      * @param duration Duration that the token can last | ||||
|      *  | ||||
|      * @return The URI users need to visit and retrieve the <i>code</i> from | ||||
|      *  | ||||
|      * @see {@link #token(String)} for converting the <i>code</i> into a usable <i>RedditToken</i> | ||||
|      */ | ||||
|     public synchronized String generateCodeFlowURI(RedditScopeBuilder scopeBuilder, RedditDuration duration) { | ||||
|          | ||||
|         // Set parameters | ||||
|         Map<String, String> params = new HashMap<String, String>(); | ||||
|         params.put(PARAM_CLIENT_ID, redditApp.getClientID()); | ||||
|         params.put(PARAM_RESPONSE_TYPE, "code"); | ||||
|         params.put(PARAM_STATE, UUID.randomUUID().toString()); | ||||
|         params.put(PARAM_REDIRECT_URI, redditApp.getRedirectURI()); | ||||
|         params.put(PARAM_DURATION, duration.value()); | ||||
|         params.put(PARAM_SCOPE, scopeBuilder.build()); | ||||
|          | ||||
|         // Create URI | ||||
|         return REDDIT_AUTHORIZE + KeyValueFormatter.format(params, true); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate the <i>implicit flow</i> Uniform Resource Locator (URI) for a | ||||
|      * reddit user to authorize your application.<br> | ||||
|      * <br> | ||||
|      * The user will, after authorization, receive token information. This can be turned into | ||||
|      * a <i>RedditToken</i> using {@link #tokenFromInfo(String, String, long, String)}. | ||||
|      *  | ||||
|      * @param scopeBuilder Authorization scope builder (must not be <i>null</i>) | ||||
|      *  | ||||
|      * @return The URI users need to visit and retrieve the <i>token information</i> from | ||||
|      *  | ||||
|      * @see {@link #tokenFromInfo(String, String, long, String)} for converting the | ||||
|      * <i>token information</i> into <i>RedditToken</i> | ||||
|      */ | ||||
|     public synchronized String generateImplicitFlowURI(RedditScopeBuilder scopeBuilder) { | ||||
|          | ||||
|         // Set parameters | ||||
|         Map<String, String> params = new HashMap<String, String>(); | ||||
|         params.put(PARAM_CLIENT_ID, redditApp.getClientID()); | ||||
|         params.put(PARAM_RESPONSE_TYPE, "token"); | ||||
|         params.put(PARAM_STATE, UUID.randomUUID().toString()); | ||||
|         params.put(PARAM_REDIRECT_URI, redditApp.getRedirectURI()); | ||||
|         params.put(PARAM_SCOPE, scopeBuilder.build()); | ||||
|          | ||||
|         // Create URI | ||||
|         return REDDIT_AUTHORIZE + KeyValueFormatter.format(params, true); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add a user agent to the OAuth request. | ||||
|      *  | ||||
|      * @param request OAuth request | ||||
|      */ | ||||
|     private void addUserAgent(OAuthClientRequest request) { | ||||
|         request.addHeader(HEADER_USER_AGENT, userAgent); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add the basic authentication protocol to the OAuth request using | ||||
|      * the credentials of the Reddit application provided. | ||||
|      *  | ||||
|      * @param request OAuth request | ||||
|      * @param app Reddit application | ||||
|      */ | ||||
|     private void addBasicAuthentication(OAuthClientRequest request, RedditApp app) { | ||||
|         String authString = app.getClientID() + ":" + app.getClientSecret(); | ||||
|         String authStringEnc = DatatypeConverter.printBase64Binary(authString.getBytes()); | ||||
|         request.addHeader(HEADER_AUTHORIZATION, "Basic " + authStringEnc); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Token retrieval (<i>code</i> flow).<br> | ||||
|      * <br> | ||||
|      * Retrieve a token for a specific user, meaning that the token is <u>coupled to a user</u>.  | ||||
|      * After it has expired, the token will no longer work. You must either request a new | ||||
|      * token, or refresh it using {@link #refreshToken(RedditToken)}. | ||||
|      * | ||||
|      * @param code One-time code received from the user, after manual authorization by that user | ||||
|      *  | ||||
|      * @return Token (associated with a user) | ||||
|      *  | ||||
|      * @throws RedditOAuthException | ||||
|      */ | ||||
|     public synchronized RedditToken token(String code) throws RedditOAuthException { | ||||
|          | ||||
|         try { | ||||
|          | ||||
|             // Set general values of the request | ||||
|             OAuthClientRequest request = OAuthClientRequest | ||||
|                 .tokenProvider(OAuthProviderType.REDDIT) | ||||
|                 .setGrantType(GrantType.AUTHORIZATION_CODE) | ||||
|                 .setClientId(redditApp.getClientID()) | ||||
|                 .setClientSecret(redditApp.getClientSecret()) | ||||
|                 .setRedirectURI(redditApp.getRedirectURI()) | ||||
|                 .setParameter(PARAM_CODE, code) | ||||
|                 .buildBodyMessage(); | ||||
|              | ||||
|             // Add the user agent | ||||
|             addUserAgent(request); | ||||
|              | ||||
|             // Add basic authentication | ||||
|             addBasicAuthentication(request, redditApp); | ||||
|              | ||||
|             // Return a wrapper controlled by jReddit | ||||
|             return new RedditToken(oAuthClient.accessToken(request)); | ||||
|          | ||||
|         } catch (OAuthSystemException oase) { | ||||
|             throw new RedditOAuthException(oase); | ||||
|         } catch (OAuthProblemException oape) { | ||||
|             throw new RedditOAuthException(oape); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Refresh token.<br> | ||||
|      * <br> | ||||
|      * This is <u>only</u> possible for tokens retrieved through the <u>code flow</u> | ||||
|      * authorization and had their duration set to permanent. Tokens that do not have | ||||
|      * a refresh_token with them or are expired, will not be able to be refreshed.  | ||||
|      * In that case, a new one must be acquired.  | ||||
|      * | ||||
|      * @param rToken Reddit token (which needs to be refreshed) | ||||
|      * | ||||
|      * @return Whether the token was successfully refreshed | ||||
|      *  | ||||
|      * @throws RedditOAuthException | ||||
|      *  | ||||
|      * @see RedditToken#isRefreshable() | ||||
|      */ | ||||
|     public synchronized boolean refreshToken(RedditToken rToken) throws RedditOAuthException { | ||||
|          | ||||
|         try { | ||||
|              | ||||
|             // Check whether the token can be refreshed | ||||
|             if (rToken.isRefreshable()) { | ||||
|              | ||||
|                 // Set general values of the request | ||||
|                 OAuthClientRequest request = OAuthClientRequest | ||||
|                     .tokenProvider(OAuthProviderType.REDDIT) | ||||
|                     .setGrantType(GrantType.REFRESH_TOKEN) | ||||
|                     .setRefreshToken(rToken.getRefreshToken()) | ||||
|                     .buildBodyMessage(); | ||||
|                  | ||||
|                 // Add the user agent | ||||
|                 addUserAgent(request); | ||||
|                  | ||||
|                 // Add basic authentication | ||||
|                 addBasicAuthentication(request, redditApp); | ||||
|                  | ||||
|                 // Return a wrapper controlled by jReddit | ||||
|                 rToken.refresh(oAuthClient.accessToken(request)); | ||||
|                  | ||||
|                 return true; | ||||
|              | ||||
|             } else { | ||||
|                  | ||||
|                 // The token cannot be refreshed | ||||
|                 return false; | ||||
|                  | ||||
|             } | ||||
|          | ||||
|          | ||||
|         } catch (OAuthSystemException oase) { | ||||
|             throw new RedditOAuthException(oase); | ||||
|         } catch (OAuthProblemException oape) { | ||||
|             throw new RedditOAuthException(oape); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Token retrieval (<i>app-only</i> flow).<br> | ||||
|      * <br> | ||||
|      * Retrieve a token for the <u>application-only</u>, meaning that the | ||||
|      * token is <u>not coupled to any user</u>. The token is typically only | ||||
|      * <u>valid for a short period of time</u> (at the moment of writing: 1 hour). | ||||
|      * After it has expired, the token will no longer work. You must request a <u>new</u> | ||||
|      * token in that case. Refreshing an application-only token is not possible. | ||||
|      * | ||||
|      * @param confidential <i>True</i>: confidential clients (web apps / scripts) not acting on | ||||
|      *                     behalf of one or more logged out users. <i>False</i>: installed app types, | ||||
|      *                     and other apps acting on behalf of one or more logged out users. | ||||
|      *  | ||||
|      * @return Token (not associated with a user) | ||||
|      *  | ||||
|      * @throws RedditOAuthException | ||||
|      */ | ||||
|     public synchronized RedditToken tokenAppOnly(boolean confidential) throws RedditOAuthException { | ||||
|          | ||||
|         try { | ||||
|          | ||||
|             // Set general values of the request | ||||
|             TokenRequestBuilder builder = OAuthClientRequest | ||||
|                 .tokenProvider(OAuthProviderType.REDDIT) | ||||
|                 .setParameter(PARAM_GRANT_TYPE, confidential ? GRANT_TYPE_CLIENT_CREDENTIALS : GRANT_TYPE_INSTALLED_CLIENT) | ||||
|                 .setClientId(redditApp.getClientID()) | ||||
|                 .setClientSecret(redditApp.getClientSecret()); | ||||
|              | ||||
|             // If it is not acting on behalf of a unique client, a unique device identifier must be generated: | ||||
|             if (!confidential) { | ||||
|                 builder = builder.setParameter(PARAM_DEVICE_ID, UUID.randomUUID().toString()); | ||||
|             } | ||||
|              | ||||
|             // Build the request | ||||
|             OAuthClientRequest request = builder.buildBodyMessage(); | ||||
|              | ||||
|             // Add the user agent | ||||
|             addUserAgent(request); | ||||
|              | ||||
|             // Add basic authentication | ||||
|             addBasicAuthentication(request, redditApp); | ||||
|              | ||||
|             // Return a wrapper controlled by jReddit | ||||
|             return new RedditToken(oAuthClient.accessToken(request)); | ||||
|              | ||||
|         } catch (OAuthSystemException oase) { | ||||
|             throw new RedditOAuthException(oase); | ||||
|         } catch (OAuthProblemException oape) { | ||||
|             throw new RedditOAuthException(oape); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate a token from information received using the <i>implicit grant flow</i>.<br> | ||||
|      * <br> | ||||
|      * <b>WARNING:</b> The expiration of the token is no longer very accurate. There is a delay | ||||
|      * between the user receiving the token, and inputting it into this function. Beware that the | ||||
|      * token might expire earlier than that the token reports it to. | ||||
|      *  | ||||
|      * @param accessToken Access token | ||||
|      * @param tokenType Token type (commonly "bearer") | ||||
|      * @param expiresIn Expires in (seconds) | ||||
|      * @param scope Scope | ||||
|      *  | ||||
|      * @return <i>RedditToken</i> generated using the given information. | ||||
|      */ | ||||
|     public synchronized RedditToken tokenFromInfo(String accessToken, String tokenType, long expiresIn, String scope) { | ||||
|         return new RedditToken(accessToken, tokenType, expiresIn, scope); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Revocation of a <i>RedditToken</i>.<br> | ||||
|      * <br> | ||||
|      * Be sure to not use the token after | ||||
|      * calling this function, as its state pertaining its validity (e.g. scope,  | ||||
|      * expiration, refreshability) is no longer valid when it is revoked.<br> | ||||
|      * <br> | ||||
|      * <i>Note: Per RFC 7009, this request will return a success (204) response | ||||
|      * even if the passed in token was never valid.</i> | ||||
|      *  | ||||
|      * @param token <i>RedditToken</i> to revoke | ||||
|      * @param revokeAccessTokenOnly Whether to only revoke the access token, or both | ||||
|      *  | ||||
|      * @return Whether the token is no longer valid | ||||
|      */ | ||||
|     public boolean revoke(RedditToken token, boolean revokeAccessTokenOnly) { | ||||
|         // TODO: Implement | ||||
|         // https://www.reddit.com/api/v1/revoke_token | ||||
|         // In POST data: token=TOKEN&token_type_hint=TOKEN_TYPE | ||||
|         // TOKEN_TYPE: refresh_token or access_token | ||||
|         //  | ||||
|         return true; | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										187
									
								
								src/main/com/github/jreddit/oauth/RedditToken.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/main/com/github/jreddit/oauth/RedditToken.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | ||||
| package com.github.jreddit.oauth; | ||||
| 
 | ||||
| import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; | ||||
| 
 | ||||
| import com.github.jreddit.oauth.param.RedditScope; | ||||
| import com.github.jreddit.oauth.param.RedditTokenCompleteScope; | ||||
| 
 | ||||
| /** | ||||
|  * OAuth2 token wrapper for reddit.<br> | ||||
|  * <br> | ||||
|  * This class wraps the information received from reddit following | ||||
|  * the request for a token.<br> | ||||
|  * A token has three dimensions: | ||||
|  * <ul> | ||||
|  * <li><b>scope:</b> what can it be used for? | ||||
|  * <li><b>expiration:</b> how long can it be used? | ||||
|  * <li><b>refreshable:</b> can its duration be prolonged? | ||||
|  * </ul> | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  * | ||||
|  */ | ||||
| public class RedditToken { | ||||
| 
 | ||||
|     /** Token type parameter. */ | ||||
|     public static final String PARAM_TOKEN_TYPE = "token_type"; | ||||
|      | ||||
|     /** Access token. */ | ||||
|     private String accessToken; | ||||
|      | ||||
|     /** Refresh token. */ | ||||
|     private String refreshToken; | ||||
|      | ||||
|     /** Manager of the scopes that this token applies to. */ | ||||
|     private RedditTokenCompleteScope scopes; | ||||
|      | ||||
|     /** Token type. Only value possible (15-06-2015): bearer */ | ||||
|     private String tokenType; | ||||
|      | ||||
|     /** Time at which the token expires (seconds since UNIX epoch). */ | ||||
|     private long expiration; | ||||
|      | ||||
|     /** How long the token was valid starting from its creation (in seconds). */ | ||||
|     private long expirationSpan; | ||||
|      | ||||
|     /** | ||||
|      * @param token JSON response after an OAuth2 token request | ||||
|      */ | ||||
|     protected RedditToken(OAuthJSONAccessTokenResponse token) { | ||||
|         this.accessToken = token.getAccessToken(); | ||||
|         this.refreshToken = token.getRefreshToken(); | ||||
|         this.expiration = currentTimeSeconds() + token.getExpiresIn(); | ||||
|         this.expirationSpan = token.getExpiresIn(); | ||||
|         this.scopes = new RedditTokenCompleteScope(token.getScope()); | ||||
|         this.tokenType = token.getParam(PARAM_TOKEN_TYPE); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Reddit token constructor with specific user-provided parameters. | ||||
|      *  | ||||
|      * @param accessToken Access token | ||||
|      * @param tokenType Type of token (commonly "bearer") | ||||
|      * @param expiresIn Expires in (seconds) | ||||
|      * @param scope Scope | ||||
|      */ | ||||
|     protected RedditToken(String accessToken, String tokenType, long expiresIn, String scope) { | ||||
|         this.accessToken = accessToken; | ||||
|         this.refreshToken = null; | ||||
|         this.expiration = currentTimeSeconds() + expiresIn; | ||||
|         this.expirationSpan = expiresIn; | ||||
|         this.scopes = new RedditTokenCompleteScope(scope); | ||||
|         this.tokenType = tokenType; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Refresh this reddit token with data received from the new token. | ||||
|      *  | ||||
|      * @param token Token received from a refresh request to reddit | ||||
|      */ | ||||
|     public void refresh(OAuthJSONAccessTokenResponse token) { | ||||
|         this.accessToken = token.getAccessToken(); | ||||
|         this.expiration = currentTimeSeconds() + token.getExpiresIn(); | ||||
|         this.expirationSpan = token.getExpiresIn(); | ||||
|         this.scopes = new RedditTokenCompleteScope(token.getScope()); | ||||
|         this.tokenType = token.getParam(PARAM_TOKEN_TYPE); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve the access token. | ||||
|      *  | ||||
|      * @return Access token (e.g. "jsdkjfskaj9f8-dnafk") | ||||
|      */ | ||||
|     public String getAccessToken() { | ||||
|         return accessToken; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve the refresh token. | ||||
|      *  | ||||
|      * @return Refresh token (e.g. "nvkJu9kjdada2-d98afj") | ||||
|      */ | ||||
|     public String getRefreshToken() { | ||||
|         return refreshToken; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve whether the token is expired. | ||||
|      *  | ||||
|      * @return Is the token expired? | ||||
|      */ | ||||
|     public boolean isExpired() { | ||||
|         return expiration < currentTimeSeconds(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Check whether this token possess this particular authorization scope. | ||||
|      * If it does not support the scope, it means that the token does | ||||
|      * not have approval from the user to perform the actions belonging to  | ||||
|      * that scope. | ||||
|      *  | ||||
|      * @param scope Reddit scope | ||||
|      *  | ||||
|      * @return Does this token support this scope? | ||||
|      */ | ||||
|     public boolean hasScope(RedditScope scope) { | ||||
|         return this.scopes.has(scope); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve the expiration. | ||||
|      *  | ||||
|      * @return Expiration time (seconds since UNIX epoch) | ||||
|      */ | ||||
|     public long getExpiration() { | ||||
|         return expiration; | ||||
|     }     | ||||
|     /** | ||||
|      * Retrieve the token type. | ||||
|      *  | ||||
|      * @return Token type (e.g. "bearer") | ||||
|      */ | ||||
|     public String getTokenType() { | ||||
|         return tokenType; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Check whether the token can be refreshed. | ||||
|      * This means that a refresh token exists. | ||||
|      *  | ||||
|      * @return Can the token be refreshed? | ||||
|      */ | ||||
|     public boolean isRefreshable() { | ||||
|         return this.getRefreshToken() != null; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Check whether this token will expire within the given time frame (given in seconds). | ||||
|      *  | ||||
|      * @param seconds Amount of seconds | ||||
|      *  | ||||
|      * @return Will the token expire within the given time frame? | ||||
|      */ | ||||
|     public boolean willExpireIn(long seconds) { | ||||
|         return currentTimeSeconds() + seconds > expiration; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve the original expiration span of the token starting from its creation. | ||||
|      *  | ||||
|      * @return Expiration span (in seconds) | ||||
|      */ | ||||
|     public long getExpirationSpan() { | ||||
|         return expirationSpan; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve the current time in seconds. | ||||
|      *  | ||||
|      * Uses <i>System.currentTimeMillis()</i>. | ||||
|      *  | ||||
|      * @return Current time in seconds. | ||||
|      */ | ||||
|     private static long currentTimeSeconds() { | ||||
|         return System.currentTimeMillis() / (long) 1000; | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										52
									
								
								src/main/com/github/jreddit/oauth/app/RedditApp.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/main/com/github/jreddit/oauth/app/RedditApp.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| package com.github.jreddit.oauth.app; | ||||
| 
 | ||||
| public abstract class RedditApp { | ||||
|      | ||||
|     private final String clientID; | ||||
|     private final String clientSecret; | ||||
|     private final String redirectURI; | ||||
|      | ||||
|     /** | ||||
|      * Reddit Application.<br> | ||||
|      * <br> | ||||
|      * <i>All</i> information given in this constructor <i>must</i> | ||||
|      * match the information stated on reddit. | ||||
|      *  | ||||
|      * @param clientID Client identifier (e.g. "p_jcolKysdMFud") | ||||
|      * @param clientSecret Client secret (e.g. "gko_LXEJKF89djs98fhFJkj9s") | ||||
|      * @param redirectURI Redirect URI (e.g. "http://www.example.com/auth") | ||||
|      */ | ||||
|     public RedditApp(String clientID, String clientSecret, String redirectURI) { | ||||
|         this.clientID = clientID; | ||||
|         this.clientSecret = clientSecret; | ||||
|         this.redirectURI = redirectURI; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve client identifier. | ||||
|      *  | ||||
|      * @return Client identifier (e.g. "p_jcolKysdMFud") | ||||
|      */ | ||||
|     public String getClientID() { | ||||
|         return clientID; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve client secret. | ||||
|      *  | ||||
|      * @return Client secret (e.g. "gko_LXEJKF89djs98fhFJkj9s") | ||||
|      */ | ||||
|     public String getClientSecret() { | ||||
|         return clientSecret; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve redirect Uniform Resource Identifier. | ||||
|      *  | ||||
|      * @return Redirect URI (e.g. "http://www.example.com/auth") | ||||
|      */ | ||||
|     public String getRedirectURI() { | ||||
|         return redirectURI; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| package com.github.jreddit.oauth.app; | ||||
| 
 | ||||
| public class RedditInstalledApp extends RedditApp { | ||||
| 
 | ||||
|     /** | ||||
|      * Reddit Installed Application.<br> | ||||
|      * <br> | ||||
|      * <i>All</i> information given in this constructor <i>must</i> | ||||
|      * match the information stated on reddit. The secret is defaulted | ||||
|      * to an empty string. | ||||
|      *  | ||||
|      * @param clientID Client identifier (e.g. "p_jcolKysdMFud") | ||||
|      * @param redirectURI Redirect URI (e.g. "http://www.example.com/auth") | ||||
|      */ | ||||
|     public RedditInstalledApp(String clientID, String redirectURI) { | ||||
|         super(clientID, "", redirectURI); // Empty string is the secret for an installed app | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/main/com/github/jreddit/oauth/app/RedditScriptApp.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/main/com/github/jreddit/oauth/app/RedditScriptApp.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| package com.github.jreddit.oauth.app; | ||||
| 
 | ||||
| public class RedditScriptApp extends RedditApp { | ||||
| 
 | ||||
|     /** | ||||
|      * Reddit Script Application.<br> | ||||
|      * <br> | ||||
|      * <i>All</i> information given in this constructor <i>must</i> | ||||
|      * match the information stated on reddit. | ||||
|      *  | ||||
|      * @param clientID Client identifier (e.g. "p_jcolKysdMFud") | ||||
|      * @param clientSecret Client secret (e.g. "gko_LXEJKF89djs98fhFJkj9s") | ||||
|      * @param redirectURI Redirect URI (e.g. "http://www.example.com/auth") | ||||
|      */ | ||||
|     public RedditScriptApp(String clientID, String clientSecret, String redirectURI) { | ||||
|         super(clientID, clientSecret, redirectURI); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/main/com/github/jreddit/oauth/app/RedditWebApp.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/main/com/github/jreddit/oauth/app/RedditWebApp.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| package com.github.jreddit.oauth.app; | ||||
| 
 | ||||
| public class RedditWebApp extends RedditApp { | ||||
| 
 | ||||
|     /** | ||||
|      * Reddit Web Application.<br> | ||||
|      * <br> | ||||
|      * <i>All</i> information given in this constructor <i>must</i> | ||||
|      * match the information stated on reddit. | ||||
|      *  | ||||
|      * @param clientID Client identifier (e.g. "p_jcolKysdMFud") | ||||
|      * @param clientSecret Client secret (e.g. "gko_LXEJKF89djs98fhFJkj9s") | ||||
|      * @param redirectURI Redirect URI (e.g. "http://www.example.com/auth") | ||||
|      */ | ||||
|     public RedditWebApp(String clientID, String clientSecret, String redirectURI) { | ||||
|         super(clientID, clientSecret, redirectURI); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										47
									
								
								src/main/com/github/jreddit/oauth/client/RedditClient.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/main/com/github/jreddit/oauth/client/RedditClient.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| package com.github.jreddit.oauth.client; | ||||
| 
 | ||||
| import com.github.jreddit.oauth.RedditToken; | ||||
| import com.github.jreddit.request.RedditGetRequest; | ||||
| import com.github.jreddit.request.RedditPostRequest; | ||||
| 
 | ||||
| public abstract class RedditClient { | ||||
|      | ||||
|     /** API Domain of OAuth */ | ||||
|     public static final String OAUTH_API_DOMAIN = "https://oauth.reddit.com"; | ||||
|      | ||||
|     /** | ||||
|      * Perform a POST reddit request authenticated with the given reddit token.<br> | ||||
|      * <br> | ||||
|      * Does the following: (a) generates the URI (including query parameters) and appends | ||||
|      * it to the reddit base, (b) adds the POST body parameters, | ||||
|      * (c) adds the authorization from the token to the request, and | ||||
|      * (d) executes the request.<br> | ||||
|      * <br> | ||||
|      * <i>Exception handling: if any function raises an exception, | ||||
|      * it will be logged using SLF4J. The result would be null.</i> | ||||
|      *  | ||||
|      * @param rToken Reddit token | ||||
|      * @param request Reddit POST request | ||||
|      *  | ||||
|      * @return Response from reddit (raw), if failed <i>null</i> | ||||
|      */ | ||||
|     public abstract String post(RedditToken rToken, RedditPostRequest request); | ||||
|      | ||||
|     /** | ||||
|      * Perform a GET reddit request authenticated with the given reddit token.<br> | ||||
|      * <br> | ||||
|      * Does the following: (a) generates the URI (including query parameters) and appends | ||||
|      * it to the reddit base, (b) adds the authorization from the token to | ||||
|      * the request, and (c) executes the request.<br> | ||||
|      * <br> | ||||
|      * <i>Exception handling: if any function raises an exception, | ||||
|      * it will be logged using SLF4J. The result would be null.</i> | ||||
|      *  | ||||
|      * @param rToken Reddit token | ||||
|      * @param request Reddit GET request | ||||
|      *  | ||||
|      * @return Response from reddit (raw), if failed <i>null</i> | ||||
|      */ | ||||
|     public abstract String get(RedditToken rToken, RedditGetRequest request); | ||||
|      | ||||
| } | ||||
							
								
								
									
										141
									
								
								src/main/com/github/jreddit/oauth/client/RedditHttpClient.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/main/com/github/jreddit/oauth/client/RedditHttpClient.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | ||||
| package com.github.jreddit.oauth.client; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.UnsupportedEncodingException; | ||||
| 
 | ||||
| import org.apache.http.HttpRequest; | ||||
| import org.apache.http.HttpResponse; | ||||
| import org.apache.http.client.ClientProtocolException; | ||||
| import org.apache.http.client.HttpClient; | ||||
| import org.apache.http.client.methods.HttpGet; | ||||
| import org.apache.http.client.methods.HttpPost; | ||||
| import org.apache.http.client.methods.HttpUriRequest; | ||||
| import org.apache.http.entity.StringEntity; | ||||
| import org.apache.http.util.EntityUtils; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.oauth.RedditToken; | ||||
| import com.github.jreddit.request.RedditGetRequest; | ||||
| import com.github.jreddit.request.RedditPostRequest; | ||||
| 
 | ||||
| /** | ||||
|  * HTTP client implementation for a <i>RedditClient</i>. | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  *  | ||||
|  * @see RedditClient | ||||
|  */ | ||||
| public class RedditHttpClient extends RedditClient { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(RedditHttpClient.class); | ||||
|      | ||||
|     private final String userAgent; | ||||
|      | ||||
|     private final HttpClient httpClient; | ||||
|      | ||||
|     /** | ||||
|      * @param userAgent User agent of your application | ||||
|      * @param httpClient HTTP client to use for the requests | ||||
|      */ | ||||
|     public RedditHttpClient(String userAgent, HttpClient httpClient) { | ||||
|         this.userAgent = userAgent; | ||||
|         this.httpClient = httpClient; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String post(RedditToken rToken, RedditPostRequest redditRequest) { | ||||
|          | ||||
|         try { | ||||
|          | ||||
|             // Create post request | ||||
|             HttpPost request = new HttpPost(OAUTH_API_DOMAIN + redditRequest.generateRedditURI()); | ||||
|      | ||||
|             // Add parameters to body | ||||
|             request.setEntity(new StringEntity(redditRequest.generateBody())); | ||||
|              | ||||
|             // Add authorization | ||||
|             addAuthorization(request, rToken); | ||||
|              | ||||
|             // Add user agent | ||||
|             addUserAgent(request); | ||||
|              | ||||
|             // Add content type | ||||
|             request.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); | ||||
|              | ||||
|             return executeHttpRequest(request); | ||||
|          | ||||
|         } catch (UnsupportedEncodingException uee) { | ||||
|             LOGGER.warn("Unsupported Encoding Exception thrown in POST request when encoding body", uee); | ||||
|         } | ||||
|          | ||||
|         return null; | ||||
|          | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String get(RedditToken rToken, RedditGetRequest redditRequest) { | ||||
|          | ||||
|         // Create get request | ||||
|         HttpGet request = new HttpGet(OAUTH_API_DOMAIN + redditRequest.generateRedditURI()); | ||||
| 
 | ||||
|         // Add authorization | ||||
|         addAuthorization(request, rToken); | ||||
|          | ||||
|         // Add user agent | ||||
|         addUserAgent(request); | ||||
| 
 | ||||
|         return executeHttpRequest(request); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Execute the given HTTP request. | ||||
|      *  | ||||
|      * @param request HTTP request | ||||
|      *  | ||||
|      * @return Result, <i>null</i> if failed | ||||
|      */ | ||||
|     private String executeHttpRequest(HttpUriRequest request) { | ||||
|         try { | ||||
|              | ||||
|             // Attempt to do execute request | ||||
|             HttpResponse response = httpClient.execute(request); | ||||
|              | ||||
|             // Return response if successful | ||||
|             if (response != null) { | ||||
|                 return EntityUtils.toString(response.getEntity(), "UTF-8"); | ||||
|             } | ||||
|              | ||||
|         } catch (UnsupportedEncodingException uee) { | ||||
|             LOGGER.warn("Unsupported Encoding Exception thrown in request", uee); | ||||
|         } catch (ClientProtocolException cpe) { | ||||
|             LOGGER.warn("Client Protocol Exception thrown in request", cpe); | ||||
|         } catch (IOException ioe) { | ||||
|             LOGGER.warn("I/O Exception thrown in request", ioe); | ||||
|         } | ||||
|          | ||||
|         return null; | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add authorization to the HTTP request. | ||||
|      *  | ||||
|      * @param request HTTP request | ||||
|      * @param rToken Reddit token (generally of the "bearer" type) | ||||
|      */ | ||||
|     private void addAuthorization(HttpRequest request, RedditToken rToken) { | ||||
|         request.addHeader("Authorization", rToken.getTokenType() + " " + rToken.getAccessToken()); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add user agent to the HTTP request. | ||||
|      *  | ||||
|      * @param request HTTP request | ||||
|      */ | ||||
|     private void addUserAgent(HttpRequest request) { | ||||
|         request.addHeader("User-Agent", userAgent); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										101
									
								
								src/main/com/github/jreddit/oauth/client/RedditPoliteClient.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/main/com/github/jreddit/oauth/client/RedditPoliteClient.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | ||||
| package com.github.jreddit.oauth.client; | ||||
| 
 | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.oauth.RedditToken; | ||||
| import com.github.jreddit.request.RedditGetRequest; | ||||
| import com.github.jreddit.request.RedditPostRequest; | ||||
| 
 | ||||
| /** | ||||
|  * Wrapper for any reddit client, which makes it <i>polite</i>. | ||||
|  * Polite means that it will only send requests in an interval, | ||||
|  * and does not overload reddit. It will also mean you will get | ||||
|  * less denial messages from reddit *hint* *hint*. | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class RedditPoliteClient extends RedditClient { | ||||
|      | ||||
|     /** Logger for this class. */ | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(RedditPoliteClient.class); | ||||
|      | ||||
|     /** Wrapped reddit client. */ | ||||
|     private RedditClient redditClient; | ||||
|      | ||||
|     /** Default interval in milliseconds (1 per second). */ | ||||
|     private static final long DEFAULT_INTERVAL = 1000L; | ||||
|      | ||||
|     /** Default interval in milliseconds. */ | ||||
|     private long interval; | ||||
| 
 | ||||
|     /** Last time a request was made. */ | ||||
|     private long lastReqTime = 0; | ||||
|      | ||||
|     /** | ||||
|      * Polite wrapper around the reddit client. | ||||
|      *  | ||||
|      * @param redditClient Reddit client to wrap | ||||
|      */ | ||||
|     public RedditPoliteClient(RedditClient redditClient) { | ||||
|         this(redditClient, DEFAULT_INTERVAL); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Polite wrapper around the reddit client with configurable time. | ||||
|      *  | ||||
|      * @param redditClient Reddit client to wrap | ||||
|      * @param interval Interval in milliseconds | ||||
|      */ | ||||
|     public RedditPoliteClient(RedditClient redditClient, long interval) { | ||||
|         this.redditClient = redditClient; | ||||
|         this.interval = interval; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String post(RedditToken rToken, RedditPostRequest request) { | ||||
|         waitIfNeeded(); | ||||
|         String result = redditClient.post(rToken, request); | ||||
|         noteTime(); | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String get(RedditToken rToken, RedditGetRequest request) { | ||||
|         waitIfNeeded(); | ||||
|         String result = redditClient.get(rToken, request); | ||||
|         noteTime(); | ||||
|         return result; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Note the current time. | ||||
|      */ | ||||
|     private void noteTime() { | ||||
|         lastReqTime = System.currentTimeMillis(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Wait if required. | ||||
|      */ | ||||
|     private void waitIfNeeded() { | ||||
| 
 | ||||
|         // Calculate elapsed milliseconds | ||||
|         long elapsed = System.currentTimeMillis() - lastReqTime; | ||||
| 
 | ||||
|         // If enough time has elapsed, no need to wait | ||||
|         if (elapsed >= interval) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // If not enough time was elapsed, wait the remainder | ||||
|         long toWait = interval - elapsed; | ||||
|         try { | ||||
|             Thread.sleep(toWait); | ||||
|         } catch (InterruptedException ie) { | ||||
|             LOGGER.warn("Interrupted Exception thrown while politely waiting for remainder of interval", ie); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| package com.github.jreddit.oauth.exception; | ||||
| 
 | ||||
| import org.apache.oltu.oauth2.common.exception.OAuthProblemException; | ||||
| import org.apache.oltu.oauth2.common.exception.OAuthSystemException; | ||||
| 
 | ||||
| public class RedditOAuthException extends Exception { | ||||
|      | ||||
|     private static final long serialVersionUID = 2403104136770312353L; | ||||
| 
 | ||||
|     public RedditOAuthException(OAuthSystemException e) { | ||||
|         super("A OAuth system exception was thrown when authenticating with reddit.", e); | ||||
|     } | ||||
|      | ||||
|     public RedditOAuthException(OAuthProblemException e) { | ||||
|         super("A OAuth problem exception was thrown when authenticating with reddit.", e); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										27
									
								
								src/main/com/github/jreddit/oauth/param/RedditDuration.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/main/com/github/jreddit/oauth/param/RedditDuration.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| package com.github.jreddit.oauth.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enumerator for the duration of tokens.<br> | ||||
|  * <br> | ||||
|  * There are two possible values: | ||||
|  * <ul> | ||||
|  *   <li><b>permanent:</b> The token can be refreshed as many times as the application desires.</li> | ||||
|  *   <li><b>temporary:</b> The token cannot be refreshed, and will last for <i>one hour</i>.</li> | ||||
|  * </ul> | ||||
|  */ | ||||
| public enum RedditDuration { | ||||
| 
 | ||||
|     PERMANENT("permanent"), | ||||
|     TEMPORARY("temporary"); | ||||
|      | ||||
|     private final String value; | ||||
| 
 | ||||
|     RedditDuration(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										48
									
								
								src/main/com/github/jreddit/oauth/param/RedditScope.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/main/com/github/jreddit/oauth/param/RedditScope.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| package com.github.jreddit.oauth.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enumerator for the possible authorization scopes for reddit requests.<br> | ||||
|  * <br> | ||||
|  * These scopes are used to specify what actions an application | ||||
|  * can perform with the generated token. The scope can be combined | ||||
|  * together, so that a single token can have access to multiple scopes. | ||||
|  *  | ||||
|  * @see RedditScopeBuilder | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum RedditScope { | ||||
| 
 | ||||
|     IDENTITY("identity"),  | ||||
|     EDIT("edit"),  | ||||
|     FLAIR("flair"),  | ||||
|     HISTORY("history"),   | ||||
|     MODCONFIG("modconfig"),   | ||||
|     MODFLAIR("modflair"),  | ||||
|     MODLOG("modlog"),  | ||||
|     MODPOSTS("modposts"),   | ||||
|     MODWIKI("modwiki"),  | ||||
|     MYSUBREDDITS("mysubreddits"),  | ||||
|     PRIVATEMESSAGE("privatemessages"),   | ||||
|     READ("read"),  | ||||
|     REPORT("report"),   | ||||
|     SAVE("save"),  | ||||
|     SUBMIT("submit"),   | ||||
|     SUBSCRIBE("subscribe"),   | ||||
|     VOTE("vote"),  | ||||
|     WIKIEDIT("wikiedit"),   | ||||
|     WIKIREAD("wikiread"); | ||||
|      | ||||
|     protected static final String SEPARATOR = ","; | ||||
|      | ||||
|     private final String value; | ||||
| 
 | ||||
|     RedditScope(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										100
									
								
								src/main/com/github/jreddit/oauth/param/RedditScopeBuilder.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/main/com/github/jreddit/oauth/param/RedditScopeBuilder.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | ||||
| package com.github.jreddit.oauth.param; | ||||
| 
 | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| /** | ||||
|  * Builder for the scopes of a request. | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  * | ||||
|  */ | ||||
| public class RedditScopeBuilder { | ||||
| 
 | ||||
|     /** Set of reddit scopes. */ | ||||
|     private Set<RedditScope> scopes; | ||||
|      | ||||
|     public RedditScopeBuilder() { | ||||
|         scopes = new HashSet<RedditScope>(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Build a string for the request. Called upon by | ||||
|      * <i>RedditToken</i> when requesting a token that | ||||
|      * allows scope definition. | ||||
|      *  | ||||
|      * @return String list of the scopes | ||||
|      */ | ||||
|     public String build() { | ||||
|          | ||||
|         // Add each scope to the scope list | ||||
|         String s = ""; | ||||
|         for (RedditScope scope : scopes) { | ||||
|             s += scope.value() + RedditScope.SEPARATOR; | ||||
|         } | ||||
|          | ||||
|         // Remove final separator | ||||
|         if (s.length() > 0) { | ||||
|             s = s.substring(0, s.length() - RedditScope.SEPARATOR.length()); | ||||
|         } | ||||
|          | ||||
|         // Return scope list | ||||
|         return s; | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add a scope to the builder. If the scope has already  | ||||
|      * been added, it will not be added double. | ||||
|      *  | ||||
|      * @param scope Reddit scope | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public RedditScopeBuilder addScope(RedditScope scope) { | ||||
|         scopes.add(scope); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add multiple scopes to the builder. If a scope has already  | ||||
|      * been added, it will not be added double. | ||||
|      *  | ||||
|      * @param scopes Multiple scopes | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public RedditScopeBuilder addScopes(RedditScope... scopes) { | ||||
|         for (RedditScope scope : scopes) { | ||||
|             addScope(scope); | ||||
|         } | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Remove a scope from the builder. | ||||
|      *  | ||||
|      * @param scope Reddit scope | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public RedditScopeBuilder removeScope(RedditScope scope) { | ||||
|         scopes.remove(scope); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Remove multiple scopes from the builder. | ||||
|      *  | ||||
|      * @param scopes Multiple scopes | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public RedditScopeBuilder removeScopes(RedditScope... scopes) { | ||||
|         for (RedditScope scope : scopes) { | ||||
|             removeScope(scope); | ||||
|         } | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,48 @@ | ||||
| package com.github.jreddit.oauth.param; | ||||
| 
 | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| /** | ||||
|  * Manager of the scopes a response from reddit returns. | ||||
|  * Used by <i>RedditToken</i> to parse the list of scopes it receives. | ||||
|  *  | ||||
|  * @see {@link com.github.jreddit.oauth.RedditToken} | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class RedditTokenCompleteScope { | ||||
| 
 | ||||
|     /** Set of scopes. */ | ||||
|     private Set<String> scopes; | ||||
|      | ||||
|     /** | ||||
|      * @param scopes List of scopes (e.g. "flair,edit") | ||||
|      */ | ||||
|     public RedditTokenCompleteScope(String scopes) { | ||||
|          | ||||
|         // Create set | ||||
|         this.scopes = new HashSet<String>(); | ||||
|          | ||||
|         // Split up | ||||
|         String[] split = scopes.split(RedditScope.SEPARATOR); | ||||
|          | ||||
|         // Add each to the set | ||||
|         for (String s : split) { | ||||
|             this.scopes.add(s); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Check whether it has this scope. | ||||
|      *  | ||||
|      * @param scope Reddit scope | ||||
|      *  | ||||
|      * @return Does it have this scope? | ||||
|      */ | ||||
|     public boolean has(RedditScope scope) { | ||||
|         return scopes.contains(scope.value()); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										269
									
								
								src/main/com/github/jreddit/parser/entity/Comment.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								src/main/com/github/jreddit/parser/entity/Comment.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,269 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToBoolean; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToDouble; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToInteger; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToString; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.JSONObject; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.imaginary.CommentTreeElement; | ||||
| import com.github.jreddit.parser.entity.imaginary.MixedListingElement; | ||||
| 
 | ||||
| /** | ||||
|  * A Reddit comment. Contains the edited timestamp, the body | ||||
|  * | ||||
|  * @author Benjamin Jakobus | ||||
|  * @author Raul Rene Lepsa | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class Comment extends Thing implements CommentTreeElement, MixedListingElement { | ||||
| 
 | ||||
|     private String author;            // Username of the author | ||||
|     private String parentId;        // Parent identifier | ||||
|     private String subreddit;        // Subreddit name | ||||
|     private String subredditId;        // Subreddit identifier | ||||
|     private String linkId;            // Submission (aka. link) identifier | ||||
|     private String bodyHTML;        // The body with HTML markup | ||||
|     private Boolean scoreHidden;    // Whether the score is hidden | ||||
|     private String body;            // The actual body | ||||
|     private Boolean edited;         // Edited timestamp | ||||
|     private double created;         // Created timestamp | ||||
|     private double createdUTC;      // Created UTC timestamp | ||||
|     private List<CommentTreeElement> replies;  // Replies if retrieved | ||||
|     private Integer gilded;            // Amount of times the comment been gilded | ||||
|     private Integer score;            // Karma score | ||||
|     private Integer upvotes;        // Number of upvotes that this body received | ||||
|     private Integer downvotes;      // Number of downvotes that this body received | ||||
|      | ||||
|     // Possible fields to add as well: | ||||
| //    private String bannedBy; | ||||
| //    String likes; | ||||
| //    private String approvedBy; | ||||
| //    private String authorFlairCSSClass; | ||||
| //    private String authorFlairText; | ||||
| //    String num_reports = null; | ||||
| //    String distinguished = null; | ||||
| 
 | ||||
|     public Comment(JSONObject obj) { | ||||
|         super(safeJsonToString(obj.get("name"))); | ||||
|          | ||||
|         this.setAuthor(safeJsonToString(obj.get("author"))); | ||||
|         this.setParentId(safeJsonToString(obj.get("parent_id"))); | ||||
|         this.setBody(safeJsonToString(obj.get("body"))); | ||||
|         this.setEdited(safeJsonToBoolean(obj.get("edited"))); | ||||
|         this.setCreated(safeJsonToDouble(obj.get("created"))); | ||||
|         this.setCreatedUTC(safeJsonToDouble(obj.get("created_utc"))); | ||||
|         this.setGilded(safeJsonToInteger(obj.get("gilded"))); | ||||
|         this.setScore(safeJsonToInteger(obj.get("score"))); | ||||
|         this.setUpvotes(safeJsonToInteger(obj.get("ups"))); | ||||
|         this.setDownvotes(safeJsonToInteger(obj.get("downs"))); | ||||
|         this.setSubreddit(safeJsonToString(obj.get("subreddit"))); | ||||
|         this.setSubredditId(safeJsonToString(obj.get("subreddit_id"))); | ||||
|         this.setLinkId(safeJsonToString(obj.get("link_id"))); | ||||
|         this.setBodyHTML(safeJsonToString(obj.get("body_html"))); | ||||
|         this.setScoreHidden(safeJsonToBoolean(obj.get("score_hidden"))); | ||||
| 
 | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve the replies of this comment. | ||||
|      *  | ||||
|      * @return Replies (will <i>always</i> initialized, and empty if there are no replies) | ||||
|      */ | ||||
|     public List<CommentTreeElement> getReplies() { | ||||
|         return this.replies; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Set the replies of this comment. | ||||
|      *  | ||||
|      * @param replies Comment tree of replies | ||||
|      */ | ||||
|     public void setReplies(List<CommentTreeElement> replies) { | ||||
|         this.replies = replies; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve the username of the author. | ||||
|      *  | ||||
|      * @return Username of the author | ||||
|      */ | ||||
|     public String getAuthor() { | ||||
|         return author; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set the username of the author | ||||
|      *  | ||||
|      * @param author Username of the author | ||||
|      */ | ||||
|     public void setAuthor(String author) { | ||||
|         this.author = author; | ||||
|     } | ||||
| 
 | ||||
|     public String getParentId() { | ||||
|         return parentId; | ||||
|     } | ||||
| 
 | ||||
|     public void setParentId(String parentId) { | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
| 
 | ||||
|     public String getBody() { | ||||
|         return body; | ||||
|     } | ||||
| 
 | ||||
|     public void setBody(String body) { | ||||
|         this.body = body; | ||||
|     } | ||||
| 
 | ||||
|     public Boolean getEdited() { | ||||
|         return edited; | ||||
|     } | ||||
| 
 | ||||
|     public void setEdited(Boolean edited) { | ||||
|         this.edited = edited; | ||||
|     } | ||||
| 
 | ||||
|     public double getCreated() { | ||||
|         return created; | ||||
|     } | ||||
| 
 | ||||
|     public void setCreated(double created) { | ||||
|         this.created = created; | ||||
|     } | ||||
| 
 | ||||
|     public Integer getGilded() { | ||||
|         return gilded; | ||||
|     } | ||||
| 
 | ||||
|     public void setGilded(Integer gilded) { | ||||
|         this.gilded = gilded; | ||||
|     } | ||||
| 
 | ||||
|     public Integer getUpvotes() { | ||||
|         return upvotes; | ||||
|     } | ||||
| 
 | ||||
|     public void setUpvotes(Integer upvotes) { | ||||
|         this.upvotes = upvotes; | ||||
|     } | ||||
| 
 | ||||
|     public Integer getDownvotes() { | ||||
|         return downvotes; | ||||
|     } | ||||
| 
 | ||||
|     public void setDownvotes(Integer downvotes) { | ||||
|         this.downvotes = downvotes; | ||||
|     } | ||||
|      | ||||
|     public double getCreatedUTC() { | ||||
|         return createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public void setCreatedUTC(double createdUTC) { | ||||
|         this.createdUTC = createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public Integer getScore() { | ||||
|         return score; | ||||
|     } | ||||
| 
 | ||||
|     public void setScore(Integer score) { | ||||
|         this.score = score; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return the subreddit | ||||
|      */ | ||||
|     public String getSubreddit() { | ||||
|         return subreddit; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param subreddit the subreddit to set | ||||
|      */ | ||||
|     public void setSubreddit(String subreddit) { | ||||
|         this.subreddit = subreddit; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return the subredditId | ||||
|      */ | ||||
|     public String getSubredditId() { | ||||
|         return subredditId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param subredditId the subredditId to set | ||||
|      */ | ||||
|     public void setSubredditId(String subredditId) { | ||||
|         this.subredditId = subredditId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return the linkId | ||||
|      */ | ||||
|     public String getLinkId() { | ||||
|         return linkId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param linkId the linkId to set | ||||
|      */ | ||||
|     public void setLinkId(String linkId) { | ||||
|         this.linkId = linkId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return the bodyHTML | ||||
|      */ | ||||
|     public String getBodyHTML() { | ||||
|         return bodyHTML; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param bodyHTML the bodyHTML to set | ||||
|      */ | ||||
|     public void setBodyHTML(String bodyHTML) { | ||||
|         this.bodyHTML = bodyHTML; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return the scoreHidden | ||||
|      */ | ||||
|     public Boolean isScoreHidden() { | ||||
|         return scoreHidden; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param scoreHidden the scoreHidden to set | ||||
|      */ | ||||
|     public void setScoreHidden(Boolean scoreHidden) { | ||||
|         this.scoreHidden = scoreHidden; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "Comment(" + identifier + ")<" + ((body.length() > 10) ? body.substring(0, 10) : body) + ">"; | ||||
|     }     | ||||
|      | ||||
|     @Override | ||||
|     public boolean equals(Object other) { | ||||
|         return other instanceof Comment && this.getFullName().equals(((Comment) other).getFullName()); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|         return this.hashCode() * this.getFullName().hashCode(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int compareTo(Thing o) { | ||||
|         return this.getFullName().compareTo(o.getFullName()); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										44
									
								
								src/main/com/github/jreddit/parser/entity/Kind.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/main/com/github/jreddit/parser/entity/Kind.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| /** | ||||
|  * Enumeration to represent the different types of Things. | ||||
|  */ | ||||
| public enum Kind { | ||||
| 
 | ||||
|     COMMENT("t1"), ACCOUNT("t2"), LINK("t3"), MESSAGE("t4"), SUBREDDIT("t5"), AWARD("t6"), PROMO_CAMPAIGN("t8"), MORE("more"), LISTING("listing"); | ||||
| 
 | ||||
|     private String value; | ||||
| 
 | ||||
|     /** | ||||
|      * Type enumeration constructor. | ||||
|      * @param value String representation | ||||
|      */ | ||||
|     Kind(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve the value of the type. | ||||
|      * @return Type String representation. | ||||
|      */ | ||||
|     public String value() { | ||||
|         return value; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Match a string with its respective kind. | ||||
|      *  | ||||
|      * @param t String kind (e.g. "t1" or "t5") | ||||
|      *  | ||||
|      * @return Match kind (null, it not found) | ||||
|      */ | ||||
|     public static Kind match(String t) { | ||||
|         for (Kind k : Kind.values()) { | ||||
|             if (k.value().equals(t)) { | ||||
|                 return k; | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										167
									
								
								src/main/com/github/jreddit/parser/entity/Message.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								src/main/com/github/jreddit/parser/entity/Message.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,167 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| import org.json.simple.JSONObject; | ||||
| 
 | ||||
| /** | ||||
|  * Encapsulates the private messages. | ||||
|  * Corresponds to the <code>Kind.MESSAGES</code>, which is has the value t4 for the Reddit API | ||||
|  * | ||||
|  * @author Karan Goel | ||||
|  * @author Raul Rene Lepsa | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class Message { | ||||
|      | ||||
|     // The ID of this message | ||||
|     private String id; | ||||
| 
 | ||||
|     // Name  - a combination of the Message Type (t4) and the ID of the message | ||||
|     private String fullName; | ||||
| 
 | ||||
|     // Name of the author of the message | ||||
|     private String author; | ||||
| 
 | ||||
|     // Recipient of the message | ||||
|     private String recipient; | ||||
| 
 | ||||
|     // The body of the message | ||||
|     private String body; | ||||
| 
 | ||||
|     // HTML version of the Body | ||||
|     private String bodyHtml; | ||||
| 
 | ||||
|     // If the message was a comment or not | ||||
|     private boolean isComment; | ||||
| 
 | ||||
|     // If it is a comment, it has a parent | ||||
|     private String parentId; | ||||
|      | ||||
|     // Timestamp of when the message was created | ||||
|     private String created; | ||||
| 
 | ||||
|     // UTC timestamp of when the message was created | ||||
|     private String createdUTC; | ||||
|          | ||||
|     // The content of the message | ||||
|     private String context; | ||||
|      | ||||
|     // The subject of the message | ||||
|     private String subject; | ||||
| 
 | ||||
|     public Message(JSONObject jsonObject) { | ||||
|          | ||||
|         this.setBody(jsonObject.get("body").toString()); | ||||
|         this.setComment(Boolean.valueOf(jsonObject.get("was_comment").toString())); | ||||
|         this.setFullName(jsonObject.get("name").toString()); | ||||
|         if (jsonObject.get("author") == null) | ||||
|         { | ||||
|             this.setAuthor("reddit"); | ||||
|         } else { | ||||
|             this.setAuthor(jsonObject.get("author").toString()); | ||||
|         } | ||||
|         this.setCreated(jsonObject.get("created").toString()); | ||||
|         this.setRecipient(jsonObject.get("dest").toString()); | ||||
|         this.setCreatedUTC(jsonObject.get("created_utc").toString()); | ||||
|         this.setBodyHtml(jsonObject.get("body_html").toString()); | ||||
|         this.setSubject(jsonObject.get("subject").toString()); | ||||
|         this.setContext(jsonObject.get("context").toString()); | ||||
|         this.setId(jsonObject.get("id").toString()); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(String id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public String getAuthor() { | ||||
|         return author; | ||||
|     } | ||||
| 
 | ||||
|     public void setAuthor(String author) { | ||||
|         this.author = author; | ||||
|     } | ||||
| 
 | ||||
|     public String getRecipient() { | ||||
|         return recipient; | ||||
|     } | ||||
| 
 | ||||
|     public void setRecipient(String recipient) { | ||||
|         this.recipient = recipient; | ||||
|     } | ||||
| 
 | ||||
|     public String getBody() { | ||||
|         return body; | ||||
|     } | ||||
| 
 | ||||
|     public void setBody(String body) { | ||||
|         this.body = body; | ||||
|     } | ||||
| 
 | ||||
|     public String getBodyHtml() { | ||||
|         return bodyHtml; | ||||
|     } | ||||
| 
 | ||||
|     public void setBodyHtml(String bodyHtml) { | ||||
|         this.bodyHtml = bodyHtml; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isComment() { | ||||
|         return isComment; | ||||
|     } | ||||
| 
 | ||||
|     public void setComment(boolean isComment) { | ||||
|         this.isComment = isComment; | ||||
|     } | ||||
| 
 | ||||
|     public String getFullName() { | ||||
|         return fullName; | ||||
|     } | ||||
| 
 | ||||
|     public void setFullName(String fullName) { | ||||
|         this.fullName = fullName; | ||||
|     } | ||||
| 
 | ||||
|     public String getCreated() { | ||||
|         return created; | ||||
|     } | ||||
| 
 | ||||
|     public void setCreated(String created) { | ||||
|         this.created = created; | ||||
|     } | ||||
| 
 | ||||
|     public String getCreatedUTC() { | ||||
|         return createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public void setCreatedUTC(String createdUTC) { | ||||
|         this.createdUTC = createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public String getContext() { | ||||
|         return context; | ||||
|     } | ||||
| 
 | ||||
|     public void setContext(String context) { | ||||
|         this.context = context; | ||||
|     } | ||||
| 
 | ||||
|     public String getSubject() { | ||||
|         return subject; | ||||
|     } | ||||
| 
 | ||||
|     public void setSubject(String subject) { | ||||
|         this.subject = subject; | ||||
|     } | ||||
| 
 | ||||
|     public String getParentId() { | ||||
|         return parentId; | ||||
|     } | ||||
| 
 | ||||
|     public void setParentId(String parentId) { | ||||
|         this.parentId = parentId; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/main/com/github/jreddit/parser/entity/MessageType.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/com/github/jreddit/parser/entity/MessageType.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| /** | ||||
|  * Deal with different types of messages | ||||
|  * | ||||
|  * @author Raul Rene Lepsa | ||||
|  */ | ||||
| public enum MessageType { | ||||
| 
 | ||||
|     INBOX("inbox"), SENT("sent"), UNREAD("unread"); | ||||
| 
 | ||||
|     private String value; | ||||
| 
 | ||||
|     MessageType(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String getValue() { | ||||
|         return value; | ||||
|     } | ||||
| 
 | ||||
|     public void setValue(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										106
									
								
								src/main/com/github/jreddit/parser/entity/More.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/main/com/github/jreddit/parser/entity/More.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.JSONArray; | ||||
| import org.json.simple.JSONObject; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.imaginary.CommentTreeElement; | ||||
| import com.github.jreddit.parser.util.JsonUtils; | ||||
| 
 | ||||
| /** | ||||
|  * MORE entity. Can only exist in a comment tree, and thus | ||||
|  * implements the <i>CommenTreeElement</i> interface. | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class More extends Thing implements CommentTreeElement { | ||||
| 
 | ||||
|     /** List of comment identifiers (ID36) that are his children. */ | ||||
|     private List<String> children; | ||||
|      | ||||
|     /** Counting number assigned by reddit (does not tell much in a comment tree). */ | ||||
|     private Long count; | ||||
|      | ||||
|     /** Parent comment fullname. */ | ||||
|     private String parentId; | ||||
|      | ||||
|     /** | ||||
|      * Construct a "More" thing. | ||||
|      *  | ||||
|      * @param obj JSON object | ||||
|      */ | ||||
|     public More(JSONObject obj) { | ||||
|         super(Kind.MORE.value() + "_NONE"); | ||||
|          | ||||
|         // The obj.get("name") and obj.get("id") are neglected, as these | ||||
|         // are already implicitly included in the children array. | ||||
|          | ||||
|         // Retrieve count from JSON | ||||
|         this.count = JsonUtils.safeJsonToLong(obj.get("count")); | ||||
|          | ||||
|         // Retrieve parent identifier from JSON | ||||
|         this.parentId = JsonUtils.safeJsonToString(obj.get("parent_id")); | ||||
|          | ||||
|         // Iterate over children | ||||
|         this.children = new ArrayList<String>(); | ||||
|         JSONArray jsonChildren = (JSONArray) obj.get("children"); | ||||
|         for (Object child : jsonChildren) { | ||||
|             this.children.add(JsonUtils.safeJsonToString(child)); | ||||
|         } | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve the children ID36 comment identifiers. | ||||
|      *  | ||||
|      * @return The children (e.g. ["dja241", "dsfjak24"]) | ||||
|      */ | ||||
|     public List<String> getChildren() { | ||||
|         return children; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve the counting number assigned by reddit (does not tell much in this case). | ||||
|      *  | ||||
|      * @return The counting number | ||||
|      */ | ||||
|     public Long getCount() { | ||||
|         return count; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve how many children (comments) the MORE hides. | ||||
|      *  | ||||
|      * @return How many comments the more hides ({@link #getChildren()}'s size) | ||||
|      */ | ||||
|     public int getChildrenSize() { | ||||
|         return children.size(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve the parent fullname comment identifier. | ||||
|      *  | ||||
|      * @return The parent identifier (e.g. "t1_38942f") | ||||
|      */ | ||||
|     public String getParentId() { | ||||
|         return parentId; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int compareTo(Thing o) { | ||||
|         if (!(o instanceof More)) { | ||||
|             return 1; | ||||
|         } else { | ||||
|             return ((More) o).getChildren().equals(this.getChildren()) ? 0 : -1; | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "More()<" + this.getChildrenSize() + " more directly underneath>"; | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										546
									
								
								src/main/com/github/jreddit/parser/entity/Submission.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										546
									
								
								src/main/com/github/jreddit/parser/entity/Submission.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,546 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToBoolean; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToDouble; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToLong; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToString; | ||||
| 
 | ||||
| import org.json.simple.JSONObject; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.imaginary.MixedListingElement; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * This class represents a vote on a link submission on Reddit. | ||||
|  * | ||||
|  * @author Omer Elnour | ||||
|  * @author Andrei Sfat | ||||
|  * @author Raul Rene Lepsa | ||||
|  * @author Jonny Krysh | ||||
|  * @author Danny Tsegai | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class Submission extends Thing implements MixedListingElement { | ||||
|      | ||||
|     /* All String values */ | ||||
|     private String url; | ||||
|     private String permalink; | ||||
|     private String author; | ||||
|     private String title; | ||||
|     private String subreddit; | ||||
|     private String subredditId; | ||||
|     private String thumbnail; | ||||
|     private String selftext; | ||||
|     private String selftextHTML; | ||||
|     private String domain; | ||||
|     private String bannedBy; | ||||
|     private String approvedBy; | ||||
|     private String authorFlairCSSClass; | ||||
|     private String linkFlairCSSClass; | ||||
|     private String authorFlairText; | ||||
|     private String linkFlairText; | ||||
|     private String distinguished; | ||||
|     private String from; | ||||
|     private String fromId; | ||||
|     private String removalReason; | ||||
|     private String fromKind; | ||||
|      | ||||
|     /* All Long values */ | ||||
|     private Long gilded; | ||||
|     private Long commentCount; | ||||
|     private Long reportCount; | ||||
|     private Long score; | ||||
|     private Long upVotes; | ||||
|     private Long downVotes; | ||||
| 
 | ||||
|     /* All Double values */ | ||||
|     private Double created; | ||||
|     private Double createdUTC; | ||||
|     private Double upvoteRatio; | ||||
|      | ||||
|     /* All Boolean values */ | ||||
|     private Boolean visited; | ||||
|     private Boolean self; | ||||
|     private Boolean saved; | ||||
|     private Boolean edited; | ||||
|     private Boolean stickied; | ||||
|     private Boolean nsfw; | ||||
|     private Boolean hidden; | ||||
|     private Boolean clicked; | ||||
|     private Boolean likes; | ||||
| 
 | ||||
|     /** | ||||
|      * Create a Submission from a JSONObject | ||||
|      * | ||||
|      * @param obj The JSONObject to load Submission data from | ||||
|      */ | ||||
|     public Submission(JSONObject obj) { | ||||
|         super(safeJsonToString(obj.get("name"))); | ||||
| 
 | ||||
|         setURL(safeJsonToString(obj.get("url"))); | ||||
|         setPermalink(safeJsonToString(obj.get("permalink"))); | ||||
|         setAuthor(safeJsonToString(obj.get("author"))); | ||||
|         setTitle(safeJsonToString(obj.get("title"))); | ||||
|         setSubreddit(safeJsonToString(obj.get("subreddit"))); | ||||
|         setSubredditId(safeJsonToString(obj.get("subreddit_id"))); | ||||
|         setThumbnail(safeJsonToString(obj.get("thumbnail"))); | ||||
|         setSelftext(safeJsonToString(obj.get("selftext"))); | ||||
|         setSelftextHTML(safeJsonToString(obj.get("selftext_html"))); | ||||
|         setDomain(safeJsonToString(obj.get("domain"))); | ||||
|         setBannedBy(safeJsonToString(obj.get("banned_by"))); | ||||
|         setApprovedBy(safeJsonToString(obj.get("approved_by"))); | ||||
|         setAuthorFlairCSSClass(safeJsonToString(obj.get("author_flair_css_class"))); | ||||
|         setLinkFlairCSSClass(safeJsonToString(obj.get("link_flair_css_class"))); | ||||
|         setDistinguished(safeJsonToString(obj.get("distinguished"))); | ||||
|         setAuthorFlairText(safeJsonToString(obj.get("author_flair_text"))); | ||||
|         setLinkFlairText(safeJsonToString(obj.get("link_flair_text"))); | ||||
|         setFrom(safeJsonToString(obj.get("from"))); | ||||
|         setFromId(safeJsonToString(obj.get("from_id"))); | ||||
|         setRemovalReason(safeJsonToString(obj.get("removal_reason"))); | ||||
|         setFromKind(safeJsonToString(obj.get("from_kind"))); | ||||
|          | ||||
|         setGilded(safeJsonToLong(obj.get("gilded"))); | ||||
|         setCommentCount(safeJsonToLong(obj.get("num_comments"))); | ||||
|         setReportCount(safeJsonToLong(obj.get("num_reports"))); | ||||
|         setScore(safeJsonToLong(obj.get("score"))); | ||||
|         setUpVotes(safeJsonToLong(obj.get("ups"))); | ||||
|         setDownVotes(safeJsonToLong(obj.get("downs"))); | ||||
|          | ||||
|         setCreated(safeJsonToDouble(obj.get("created"))); | ||||
|         setCreatedUTC(safeJsonToDouble(obj.get("created_utc"))); | ||||
|         setUpvoteRatio(safeJsonToDouble(obj.get("upvote_ratio"))); | ||||
|          | ||||
|         setVisited(safeJsonToBoolean(obj.get("visited"))); | ||||
|         setSelf(safeJsonToBoolean(obj.get("is_self"))); | ||||
|         setSaved(safeJsonToBoolean(obj.get("saved"))); | ||||
|         setEdited(safeJsonToBoolean(obj.get("edited"))); | ||||
|         setStickied(safeJsonToBoolean(obj.get("stickied"))); | ||||
|         setNSFW(safeJsonToBoolean(obj.get("over_18"))); | ||||
|         setHidden(safeJsonToBoolean(obj.get("hidden"))); | ||||
|         setClicked(safeJsonToBoolean(obj.get("clicked"))); | ||||
|         setLikes(safeJsonToBoolean(obj.get("likes"))); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     public String getFromKind() { | ||||
|         return fromKind; | ||||
|     } | ||||
| 
 | ||||
|     private void setFromKind(String fromKind) { | ||||
|         this.fromKind = fromKind; | ||||
|     } | ||||
| 
 | ||||
|     public String getRemovalReason() { | ||||
|         return removalReason; | ||||
|     } | ||||
| 
 | ||||
|     private void setRemovalReason(String removalReason) { | ||||
|         this.removalReason = removalReason; | ||||
|     } | ||||
| 
 | ||||
|     public String getFrom() { | ||||
|         return from; | ||||
|     } | ||||
| 
 | ||||
|     private void setFrom(String from) { | ||||
|         this.from = from; | ||||
|     } | ||||
| 
 | ||||
|     public String getFromId() { | ||||
|         return fromId; | ||||
|     } | ||||
| 
 | ||||
|     private void setFromId(String fromId) { | ||||
|         this.fromId = fromId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Up-vote ratio (total number of up-votes divided by total number of votes) | ||||
|      */ | ||||
|     public Double getUpvoteRatio() { | ||||
|         return upvoteRatio; | ||||
|     } | ||||
| 
 | ||||
|     private void setUpvoteRatio(Double upvoteRatio) { | ||||
|         this.upvoteRatio = upvoteRatio; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * @return The CSS class of the author | ||||
|      */ | ||||
|     public String getAuthorFlairCSSClass() { | ||||
|         return authorFlairCSSClass; | ||||
|     } | ||||
| 
 | ||||
|     private void setAuthorFlairCSSClass(String authorFlairCSSClass) { | ||||
|         this.authorFlairCSSClass = authorFlairCSSClass; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @return The text of the flair of the author | ||||
|      */ | ||||
|     public String getAuthorFlairText() { | ||||
|         return authorFlairText; | ||||
|     } | ||||
| 
 | ||||
|     private void setAuthorFlairText(String authorFlairText) { | ||||
|         this.authorFlairText = authorFlairText; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * @return Flair text of the submission ('link') | ||||
|      */ | ||||
|     public String getLinkFlairText() { | ||||
|         return linkFlairText; | ||||
|     } | ||||
| 
 | ||||
|     private void setLinkFlairText(String linkFlairText) { | ||||
|         this.linkFlairText = linkFlairText; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * @return The CSS class of the submission ('link') flair | ||||
|      */ | ||||
|     public String getLinkFlairCSSClass() { | ||||
|         return linkFlairCSSClass; | ||||
|     } | ||||
| 
 | ||||
|     private void setLinkFlairCSSClass(String linkFlairCSSClass) { | ||||
|         this.linkFlairCSSClass = linkFlairCSSClass; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the post is distinguished (e.g. by a "moderator") | ||||
|      */ | ||||
|     public String getDistinguished() { | ||||
|         return distinguished; | ||||
|     } | ||||
| 
 | ||||
|     private void setDistinguished(String distinguished) { | ||||
|         this.distinguished = distinguished; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the user that authenticated the retrieval of this submission upvoted it | ||||
|      */ | ||||
|     public Boolean getLikes() { | ||||
|         return likes; | ||||
|     } | ||||
| 
 | ||||
|     private void setLikes(Boolean likes) { | ||||
|         this.likes = likes; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @return The username of the one that approved this submission to the subreddit it belongs to | ||||
|      */ | ||||
|     public String getApprovedBy() { | ||||
|         return approvedBy; | ||||
|     } | ||||
| 
 | ||||
|     private void setApprovedBy(String approvedBy) { | ||||
|         this.approvedBy = approvedBy; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the user that authenticated the retrieval of this submission has hidden it | ||||
|      */ | ||||
|     public Boolean isHidden() { | ||||
|         return hidden; | ||||
|     } | ||||
| 
 | ||||
|     private void setHidden(Boolean hidden) { | ||||
|         this.hidden = hidden; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the user that authenticated the retrieval of this submission has already clicked on it before | ||||
|      */ | ||||
|     public Boolean isClicked() { | ||||
|         return clicked; | ||||
|     } | ||||
| 
 | ||||
|     private void setClicked(Boolean clicked) { | ||||
|         this.clicked = clicked; | ||||
|     } | ||||
| 
 | ||||
|     public void setUpVotes(Long upVotes) { | ||||
|         this.upVotes = upVotes; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The score (number of upvotes minus number of downvotes) | ||||
|      */ | ||||
|     public Long getScore() { | ||||
|         return score; | ||||
|     } | ||||
|      | ||||
|     private void setScore(Long score) { | ||||
|         this.score = score; | ||||
|     } | ||||
|      | ||||
|     public void setAuthor(String author) { | ||||
|         this.author = author; | ||||
|     } | ||||
| 
 | ||||
|     public void setCreatedUTC(Double createdUTC) { | ||||
|         this.createdUTC = createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public void setDownVotes(Long downVotes) { | ||||
|         this.downVotes = downVotes; | ||||
|     } | ||||
| 
 | ||||
|     public void setCommentCount(Long commentCount) { | ||||
|         this.commentCount = commentCount; | ||||
|     } | ||||
| 
 | ||||
|     public void setSubreddit(String subreddit) { | ||||
|         this.subreddit = subreddit; | ||||
|     } | ||||
| 
 | ||||
|     public void setTitle(String title) { | ||||
|         this.title = title; | ||||
|     } | ||||
| 
 | ||||
|     public void setURL(String url) { | ||||
|         this.url = url; | ||||
|     } | ||||
| 
 | ||||
|     public String getURL() { | ||||
|         return url; | ||||
|     } | ||||
| 
 | ||||
|     public String getPermalink() { | ||||
|         return permalink; | ||||
|     } | ||||
| 
 | ||||
|     public void setPermalink(String permalink) { | ||||
|         this.permalink = permalink; | ||||
|     } | ||||
| 
 | ||||
|     public Long getCommentCount() { | ||||
|         return commentCount; | ||||
|     } | ||||
| 
 | ||||
|     public Long getUpVotes() { | ||||
|         return upVotes; | ||||
|     } | ||||
| 
 | ||||
|     public Long getDownVotes() { | ||||
|         return downVotes; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public Double getCreatedUTC() { | ||||
|         return createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public String getAuthor() { | ||||
|         return author; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Title of the submission | ||||
|      */ | ||||
|     public String getTitle() { | ||||
|         return title; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Subreddit name (e.g. "programming') | ||||
|      */ | ||||
|     public String getSubreddit() { | ||||
|         return subreddit; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Subreddit ID36 identifier | ||||
|      */ | ||||
|     public String getSubredditId() { | ||||
|         return subredditId; | ||||
|     } | ||||
| 
 | ||||
|     public void setSubredditId(String subredditId) { | ||||
|         this.subredditId = subredditId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Thumbnail image URL | ||||
|      */ | ||||
|     public String getThumbnail() { | ||||
|         return thumbnail; | ||||
|     } | ||||
| 
 | ||||
|     private void setThumbnail(String thumbnail) { | ||||
|         this.thumbnail = thumbnail; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The self text of the submission (written by the author) | ||||
|      */ | ||||
|     public String getSelftext() { | ||||
|         return selftext; | ||||
|     } | ||||
| 
 | ||||
|     private void setSelftext(String selftext) { | ||||
|         this.selftext = selftext; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The self text of the submission in HTML (written by the author) | ||||
|      */ | ||||
|     public String getSelftextHTML() { | ||||
|         return selftextHTML; | ||||
|     } | ||||
| 
 | ||||
|     private void setSelftextHTML(String selftextHTML) { | ||||
|         this.selftextHTML = selftextHTML; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The domain of the URL this submission links to | ||||
|      */ | ||||
|     public String getDomain() { | ||||
|         return domain; | ||||
|     } | ||||
| 
 | ||||
|     private void setDomain(String domain) { | ||||
|         this.domain = domain; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The username of the moderator that banned this submission | ||||
|      */ | ||||
|     public String getBannedBy() { | ||||
|         return bannedBy; | ||||
|     } | ||||
| 
 | ||||
|     private void setBannedBy(String bannedBy) { | ||||
|         this.bannedBy = bannedBy; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Count of how many times this submission received gold ('was gilded') | ||||
|      */ | ||||
|     public Long getGilded() { | ||||
|         return gilded; | ||||
|     } | ||||
| 
 | ||||
|     private void setGilded(Long gilded) { | ||||
|         this.gilded = gilded; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Count of how many times this submission was reported | ||||
|      */ | ||||
|     public Long getReportCount() { | ||||
|         return reportCount; | ||||
|     } | ||||
| 
 | ||||
|     private void setReportCount(Long reportCount) { | ||||
|         this.reportCount = reportCount; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The created time-stamp (ms since Unix epoch) | ||||
|      */ | ||||
|     public Double getCreated() { | ||||
|         return created; | ||||
|     } | ||||
| 
 | ||||
|     private void setCreated(Double created) { | ||||
|         this.created = created; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the user that authenticated the retrieval of this submission has already visited it before | ||||
|      */ | ||||
|     public Boolean isVisited() { | ||||
|         return visited; | ||||
|     } | ||||
| 
 | ||||
|     private void setVisited(Boolean visited) { | ||||
|         this.visited = visited; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether it is a self post | ||||
|      */ | ||||
|     public Boolean isSelf() { | ||||
|         return self; | ||||
|     } | ||||
| 
 | ||||
|     private void setSelf(Boolean self) { | ||||
|         this.self = self; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the user that authenticated the retrieval of this submission has saved it | ||||
|      */ | ||||
|     public Boolean isSaved() { | ||||
|         return saved; | ||||
|     } | ||||
| 
 | ||||
|     private void setSaved(Boolean saved) { | ||||
|         this.saved = saved; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the submission has been edited | ||||
|      */ | ||||
|     public Boolean isEdited() { | ||||
|         return edited; | ||||
|     } | ||||
| 
 | ||||
|     private void setEdited(Boolean edited) { | ||||
|         this.edited = edited; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the submission is sticked to the top of the subreddit | ||||
|      */ | ||||
|     public Boolean isStickied() { | ||||
|         return stickied; | ||||
|     } | ||||
| 
 | ||||
|     private void setStickied(Boolean stickied) { | ||||
|         this.stickied = stickied; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Whether the post is Not Suited For Work (contains adult content) | ||||
|      */ | ||||
|     public Boolean isNSFW() { | ||||
|         return nsfw; | ||||
|     } | ||||
| 
 | ||||
|     private void setNSFW(Boolean nsfw) { | ||||
|         this.nsfw = nsfw; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "Submission(" + this.getFullName() + ")<" + title + ">"; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public boolean equals(Object other) { | ||||
|         return other instanceof Submission && this.getFullName().equals(((Submission) other).getFullName()); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|         return this.hashCode() * this.getFullName().hashCode(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int compareTo(Thing o) { | ||||
|         return this.getFullName().compareTo(o.getFullName()); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										223
									
								
								src/main/com/github/jreddit/parser/entity/Subreddit.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								src/main/com/github/jreddit/parser/entity/Subreddit.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,223 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToBoolean; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToDouble; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToLong; | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToString; | ||||
| 
 | ||||
| import org.json.simple.JSONObject; | ||||
| 
 | ||||
| /** | ||||
|  * Encapsulates a subreddit. | ||||
|  * | ||||
|  * @author Benjamin Jakobus | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public class Subreddit extends Thing { | ||||
|      | ||||
|     private String displayName; | ||||
|     private String title; | ||||
|     private String url; | ||||
|     private String description; | ||||
|     private String subredditType; | ||||
|      | ||||
|     private double created; | ||||
|     private double createdUTC; | ||||
| 
 | ||||
|     private Boolean nsfw; | ||||
| 
 | ||||
|     private Long subscribers; | ||||
|      | ||||
|     // Other possible fields | ||||
|      | ||||
|     // Submit text HTML | ||||
| //    String submit_text_html = null; | ||||
|      | ||||
|     // Whether user is banned | ||||
| //    Boolean user_is_banned = null; | ||||
|      | ||||
|     // Submit text | ||||
| //    String submit_text = "submit text for subreddit"; | ||||
|      | ||||
|     // Header image | ||||
| //    String header_img = "http://a.thumbs.redditmedia.com/yyL5sveWcgkCPKbr.png"; | ||||
|      | ||||
|     // Description in HTML markup | ||||
| //    String description_html = "<div>HTML description for subreddit</d>"; | ||||
|      | ||||
|     // Whether user is moderator | ||||
| //    Boolean user_is_moderator = null; | ||||
|      | ||||
|     // Header title | ||||
| //    String header_title = "Header title for subreddit"; | ||||
|      | ||||
|     // Submit link title | ||||
| //    String submit_link_label = "Submit link label"; | ||||
|      | ||||
|     // Accounts active | ||||
| //    String accounts_active = null; | ||||
|      | ||||
|     // Whether it allows public traffic | ||||
| //    Boolean public_traffic = true; | ||||
|      | ||||
|     // Size of header | ||||
| //    JSONArray header_size = JsonHelpers.jsonArrayOf(160, 64); | ||||
|      | ||||
|     // Submit text label | ||||
| //    String submit_text_label = "Submit text label"; | ||||
|      | ||||
|     // Whether user is contributor | ||||
| //    Boolean user_is_contributor = null; | ||||
|      | ||||
|     // Public description | ||||
| //    String public_description = "Public description of subreddit"; | ||||
|      | ||||
|     // Amount of minutes the comment score is hidden | ||||
| //    long comment_score_hide_mins = 0; | ||||
|      | ||||
|     // What types of submissions are allowed | ||||
| //    String submission_type = "any"; | ||||
|      | ||||
|     // Whether the user is contributor | ||||
| //    Boolean user_is_subscriber = null; | ||||
|      | ||||
|     /** | ||||
|      * Create a Submission from a JSONObject | ||||
|      * | ||||
|      * @param obj The JSONObject to load Submission data from | ||||
|      */ | ||||
|     public Subreddit(JSONObject obj) { | ||||
|         super(safeJsonToString(obj.get("name"))); | ||||
|          | ||||
|         setDisplayName(safeJsonToString(obj.get("display_name"))); | ||||
|         setTitle(safeJsonToString(obj.get("title"))); | ||||
|         setURL(safeJsonToString(obj.get("url"))); | ||||
|         setCreated(safeJsonToDouble(obj.get("created"))); | ||||
|         setCreatedUTC(safeJsonToDouble(obj.get("created_utc"))); | ||||
|         setNSFW(safeJsonToBoolean(obj.get("over18"))); | ||||
|         setSubscribers(safeJsonToLong(obj.get("subscribers"))); | ||||
|         setDescription(safeJsonToString(obj.get("description"))); | ||||
|         setSubredditType(safeJsonToString(obj.get("subreddit_type"))); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     private void setCreated(double created) { | ||||
|         this.created = created; | ||||
|     } | ||||
| 
 | ||||
|     private void setCreatedUTC(double createdUTC) { | ||||
|         this.createdUTC = createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     private void setDescription(String description) { | ||||
|         this.description = description; | ||||
|     } | ||||
| 
 | ||||
|     private void setDisplayName(String displayName) { | ||||
|         this.displayName = displayName; | ||||
|     } | ||||
| 
 | ||||
|     private void setNSFW(Boolean nsfw) { | ||||
|         this.nsfw = nsfw; | ||||
|     } | ||||
| 
 | ||||
|     private void setSubscribers(long subscribers) { | ||||
|         this.subscribers = subscribers; | ||||
|     } | ||||
| 
 | ||||
|     private void setTitle(String title) { | ||||
|         this.title = title; | ||||
|     } | ||||
| 
 | ||||
|     private void setURL(String url) { | ||||
|         this.url = url; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Timestamp of when the subreddit was created. | ||||
|      */ | ||||
|     public double getCreated() { | ||||
|         return created; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return UTC timestamp of when the subreddit was created. | ||||
|      */ | ||||
|     public double getCreatedUTC() { | ||||
|         return createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return Description detailing the subreddit. | ||||
|      */ | ||||
|     public String getDescription() { | ||||
|         return description; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The subreddit's display name. | ||||
|      */ | ||||
|     public String getDisplayName() { | ||||
|         return displayName; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The number of subscribers for this subreddit. | ||||
|      */ | ||||
|     public long getSubscribers() { | ||||
|         return subscribers; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The subreddit's title. | ||||
|      */ | ||||
|     public String getTitle() { | ||||
|         return title; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return The subreddit's URL. | ||||
|      */ | ||||
|     public String getURL() { | ||||
|         return url; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return True if the subreddit is marked as containing adult content; false if not. | ||||
|      */ | ||||
|     public Boolean isNSFW() { | ||||
|         return nsfw; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @return The type of subreddit (e.g. "private" or "public") | ||||
|      */ | ||||
|     public String getSubredditType() { | ||||
|         return subredditType; | ||||
|     } | ||||
| 
 | ||||
|     public void setSubredditType(String type) { | ||||
|         this.subredditType = type; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "Subreddit(" + this.getFullName() + ")<" + this.getDisplayName() + ">"; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public boolean equals(Object other) { | ||||
|         return (other instanceof Subreddit && this.getFullName().equals(((Subreddit) other).getFullName())); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|         return this.hashCode() * this.getFullName().hashCode(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int compareTo(Thing o) { | ||||
|         return this.getFullName().compareTo(o.getFullName()); | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/main/com/github/jreddit/parser/entity/Thing.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/main/com/github/jreddit/parser/entity/Thing.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| /** | ||||
|  * This class represents a reddit "thing" | ||||
|  * | ||||
|  * @author <a href="http://www.omrlnr.com">Omer Elnour</a> | ||||
|  * @author Simon Kassing | ||||
|  * @see <a href="http://www.reddit.com/dev/api#fullname">Reddit API Reference</a> | ||||
|  */ | ||||
| public abstract class Thing implements Comparable<Thing> { | ||||
|      | ||||
|     /** | ||||
|      * The kind of this thing. | ||||
|      *  | ||||
|      * @see <a href="http://www.reddit.com/dev/api#fullnames">Reddit API Reference for full names (section 'kind prefixes')</a> | ||||
|      */ | ||||
|     protected final Kind kind; | ||||
| 
 | ||||
|     /** | ||||
|      * The identifier of this thing. | ||||
|      *  | ||||
|      * @see <a href="http://www.reddit.com/dev/api#fullnames">Reddit API Reference for full names (section 'identifier')</a> | ||||
|      */ | ||||
|     protected final String identifier; | ||||
|      | ||||
|     /** | ||||
|      * The full name of this thing. | ||||
|      * Combination of its kind ({@link #getKind() getKind}) and its unique ID. | ||||
|      * | ||||
|      * @see <a href="http://www.reddit.com/dev/api#fullnames">Reddit API Reference for full names</a> | ||||
|      */ | ||||
|     protected final String fullName; | ||||
| 
 | ||||
|     /** | ||||
|      * Constructor. Must be called. | ||||
|      * @param name Full name of the thing | ||||
|      */ | ||||
|     public Thing(String name) { | ||||
|         assert name.contains("_") : "A full name must contain an underscore."; | ||||
|         this.fullName = name; | ||||
|         String[] split = name.split("_"); | ||||
|         this.kind = Kind.match(split[0]); | ||||
|         this.identifier = split[1]; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve the kind of this thing. | ||||
|      * Example: t3 indicates a kind 3 (a link). | ||||
|      * | ||||
|      * @see <a href="http://www.reddit.com/dev/api#fullnames">Reddit API Reference for full names (section 'kind prefixes')</a> | ||||
|      */ | ||||
|     public Kind getKind() { | ||||
|         return kind; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Retrieve the identifier of this thing. | ||||
|      * Example: 15bfi0. | ||||
|      * | ||||
|      * @see <a href="http://www.reddit.com/dev/api#fullnames">Reddit API Reference for full names (section 'identifier')</a> | ||||
|      */ | ||||
|     public String getIdentifier() { | ||||
|         return identifier; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Retrieve the full name of this thing. | ||||
|      * Combination of its kind (see {@link #getKind() getKind}) and its unique ID, combined with a underscore. | ||||
|      * Example: t3_15bfi0 indicates a kind 3 (a link) and as unique identifier 15bfi0. | ||||
|      * | ||||
|      * @see <a href="http://www.reddit.com/dev/api#fullnames">Reddit API Reference for full names</a> | ||||
|      */ | ||||
|     public String getFullName() { | ||||
|         return fullName; | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										212
									
								
								src/main/com/github/jreddit/parser/entity/UserInfo.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								src/main/com/github/jreddit/parser/entity/UserInfo.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,212 @@ | ||||
| package com.github.jreddit.parser.entity; | ||||
| 
 | ||||
| import org.json.simple.JSONObject; | ||||
| 
 | ||||
| /** | ||||
|  * Encapsulates user information (regarding karma, emails, identifiers, statuses, created time and current modhash) | ||||
|  * | ||||
|  * @author Raul Rene Lepsa | ||||
|  */ | ||||
| public class UserInfo { | ||||
| 
 | ||||
|     // User identifier | ||||
|     private String id; | ||||
| 
 | ||||
|     // The user's name | ||||
|     private String name; | ||||
| 
 | ||||
|     // Modhash token | ||||
|     private String modhash; | ||||
| 
 | ||||
|     // Karma points for all the comments | ||||
|     private long commentKarma; | ||||
| 
 | ||||
|     // Karma points for all the submitted links | ||||
|     private long linkKarma; | ||||
| 
 | ||||
|     // Whether the user is a moderator | ||||
|     private boolean isMod; | ||||
| 
 | ||||
|     // Whether or not the user has moderator email | ||||
|     private Boolean hasModMail; | ||||
| 
 | ||||
|     // Whether the account is associated with an email address | ||||
|     private Boolean hasMail; | ||||
| 
 | ||||
|     // Indicates whether the user has verified the email address | ||||
|     private Boolean hasVerifiedEmail; | ||||
| 
 | ||||
|     // Whether the user is a gold member | ||||
|     private boolean isGold; | ||||
| 
 | ||||
|     // Timestamp of the creation date | ||||
|     private double created; | ||||
| 
 | ||||
|     // UTC timestamp of creation date | ||||
|     private double createdUTC; | ||||
| 
 | ||||
|     // Indicates whether this user is friends with the currently connected one. Believe it or not, you can actually be  | ||||
|     // friends with yourself. http://www.reddit.com/r/reddit.com/comments/duf7q/random_reddit_protip_you_can_add_yourself_as_a/ | ||||
|     private boolean isFriend; | ||||
| 
 | ||||
|     // Indicates whether the user is over 18 | ||||
|     private Boolean over18; | ||||
| 
 | ||||
|     public UserInfo() { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public UserInfo(JSONObject info) { | ||||
|          | ||||
|         setHasMail((Boolean) info.get("has_mail")); | ||||
|         setHasModMail((Boolean) info.get("has_mod_mail")); | ||||
|         setCommentKarma((Long) info.get("comment_karma")); | ||||
|         setCreatedUTC((Double) info.get("created_utc")); | ||||
|         setGold((Boolean) info.get("is_gold")); | ||||
|         setLinkKarma((Long) info.get("link_karma")); | ||||
|         setMod((Boolean) info.get("is_mod")); | ||||
|         setFriend((Boolean) info.get("is_friend")); | ||||
|         setModhash((String) info.get("modhash")); | ||||
|         setHasVerifiedEmail((Boolean) info.get("has_verified_email")); | ||||
|         setId((String) info.get("id")); | ||||
|         setOver18((Boolean) info.get("over_18")); | ||||
|         setCreated((Double) info.get("created")); | ||||
|         setName((String) info.get("name")); | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(String id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
| 
 | ||||
|     public String getModhash() { | ||||
|         return modhash; | ||||
|     } | ||||
| 
 | ||||
|     public void setModhash(String modhash) { | ||||
|         this.modhash = modhash; | ||||
|     } | ||||
| 
 | ||||
|     public long getCommentKarma() { | ||||
|         return commentKarma; | ||||
|     } | ||||
| 
 | ||||
|     public void setCommentKarma(long commentKarma) { | ||||
|         this.commentKarma = commentKarma; | ||||
|     } | ||||
| 
 | ||||
|     public long getLinkKarma() { | ||||
|         return linkKarma; | ||||
|     } | ||||
| 
 | ||||
|     public void setLinkKarma(long linkKarma) { | ||||
|         this.linkKarma = linkKarma; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isMod() { | ||||
|         return isMod; | ||||
|     } | ||||
| 
 | ||||
|     public void setMod(boolean isMod) { | ||||
|         this.isMod = isMod; | ||||
|     } | ||||
| 
 | ||||
|     public Boolean getHasModMail() { | ||||
|         return hasModMail; | ||||
|     } | ||||
| 
 | ||||
|     public void setHasModMail(Boolean hasModMail) { | ||||
|         this.hasModMail = hasModMail; | ||||
|     } | ||||
| 
 | ||||
|     public Boolean getHasMail() { | ||||
|         return hasMail; | ||||
|     } | ||||
| 
 | ||||
|     public void setHasMail(Boolean hasMail) { | ||||
|         this.hasMail = hasMail; | ||||
|     } | ||||
| 
 | ||||
|     public Boolean isHasVerifiedEmail() { | ||||
|         return hasVerifiedEmail; | ||||
|     } | ||||
| 
 | ||||
|     public void setHasVerifiedEmail(Boolean hasVerifiedEmail) { | ||||
|         this.hasVerifiedEmail = hasVerifiedEmail; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isGold() { | ||||
|         return isGold; | ||||
|     } | ||||
| 
 | ||||
|     public void setGold(boolean isGold) { | ||||
|         this.isGold = isGold; | ||||
|     } | ||||
| 
 | ||||
|     public double getCreated() { | ||||
|         return created; | ||||
|     } | ||||
| 
 | ||||
|     public void setCreated(double created) { | ||||
|         this.created = created; | ||||
|     } | ||||
| 
 | ||||
|     public double getCreatedUTC() { | ||||
|         return createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public void setCreatedUTC(double createdUTC) { | ||||
|         this.createdUTC = createdUTC; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isFriend() { | ||||
|         return isFriend; | ||||
|     } | ||||
| 
 | ||||
|     public void setFriend(boolean isFriend) { | ||||
|         this.isFriend = isFriend; | ||||
|     } | ||||
| 
 | ||||
|     public Boolean getOver18() { | ||||
|         return over18; | ||||
|     } | ||||
| 
 | ||||
|     public void setOver18(Boolean over18) { | ||||
|         this.over18 = over18; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         StringBuilder result = new StringBuilder(); | ||||
|         String newLine = System.getProperty("line.separator"); | ||||
|          | ||||
|         result.append("id: ").append(id).append(newLine) | ||||
|               .append("name: ").append(name).append(newLine) | ||||
|               .append("modhash: ").append(modhash).append(newLine) | ||||
|               .append("commentKarma: ").append(commentKarma).append(newLine) | ||||
|               .append("linkKarma: ").append(linkKarma).append(newLine) | ||||
|               .append("isModerator: ").append(isMod).append(newLine) | ||||
|               .append("hasModMail: ").append(hasModMail).append(newLine) | ||||
|               .append("hasMail: ").append(hasMail).append(newLine) | ||||
|               .append("hasVerifiedEmail: ").append(hasVerifiedEmail).append(newLine) | ||||
|               .append("isGold: ").append(isGold).append(newLine) | ||||
|               .append("Created: ").append(created).append(newLine) | ||||
|               .append("CreatedUTC: ").append(createdUTC).append(newLine) | ||||
|               .append("isFriend: ").append(isFriend).append(newLine) | ||||
|               .append("over18: ").append(over18); | ||||
|          | ||||
|         return result.toString(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| package com.github.jreddit.parser.entity.imaginary; | ||||
| 
 | ||||
| /** | ||||
|  * Interface to abstract over the two possible elements in a | ||||
|  * comment tree, namely a {@link Comment} or a {@link More} thing. If an object | ||||
|  * is of the type of this interface, it means that it <i>must</i> | ||||
|  * be either an {@link Comment} or a {@link More} thing. | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  *  | ||||
|  * @see com.github.jreddit.parser.entity.Comment | ||||
|  * @see com.github.jreddit.parser.entity.More | ||||
|  */ | ||||
| public interface CommentTreeElement { | ||||
|     // Empty because only an abstraction for either a Comment or a More thing | ||||
| } | ||||
| @ -0,0 +1,35 @@ | ||||
| package com.github.jreddit.parser.entity.imaginary; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Submission; | ||||
| 
 | ||||
| public class FullSubmission { | ||||
| 
 | ||||
|     private Submission submission; | ||||
|     private List<CommentTreeElement> commentTree; | ||||
|      | ||||
|     public FullSubmission(Submission submission, List<CommentTreeElement> commentTree) { | ||||
|         this.submission = submission; | ||||
|         this.commentTree = commentTree; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      * @return the submission | ||||
|      */ | ||||
|     public Submission getSubmission() { | ||||
|         return submission; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      * @return the commentTree | ||||
|      */ | ||||
|     public List<CommentTreeElement> getCommentTree() { | ||||
|         return commentTree; | ||||
|     } | ||||
|      | ||||
|      | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| package com.github.jreddit.parser.entity.imaginary; | ||||
| 
 | ||||
| /** | ||||
|  * Interface to abstract over the two possible elements in a | ||||
|  * mixed listing, namely a {@link Comment} or a {@link Submission} thing.  | ||||
|  * If an object is of the type of this interface, it means that it <i>must</i> | ||||
|  * be either of the respective {@link Comment} or {@link Submission} class.  | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  *  | ||||
|  * @see com.github.jreddit.parser.entity.Comment | ||||
|  * @see com.github.jreddit.parser.entity.Submission | ||||
|  */ | ||||
| public interface MixedListingElement { | ||||
|  // Empty because only an abstraction for either a Comment or a Submission thing | ||||
| } | ||||
| @ -0,0 +1,29 @@ | ||||
| package com.github.jreddit.parser.exception; | ||||
| 
 | ||||
| import org.json.simple.parser.ParseException; | ||||
| 
 | ||||
| public class RedditParseException extends Exception { | ||||
| 
 | ||||
|     private static final long serialVersionUID = -1031803118041533936L; | ||||
|      | ||||
|     public RedditParseException(String custom) { | ||||
|         super("Could not parse response from reddit (" + custom + ")"); | ||||
|     } | ||||
|      | ||||
|     public RedditParseException(String custom, Throwable t) { | ||||
|         super("Could not parse response from reddit (" + custom + ")", t); | ||||
|     } | ||||
|      | ||||
|     public RedditParseException() { | ||||
|         this("undefined (null) response"); | ||||
|     } | ||||
|      | ||||
|     public RedditParseException(int errorCode) { | ||||
|         this("contained HTTP error code: " + errorCode); | ||||
|     } | ||||
|      | ||||
|     public RedditParseException(ParseException pe) { | ||||
|         this("invalid JSON format", pe); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,55 @@ | ||||
| package com.github.jreddit.parser.listing; | ||||
| 
 | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.parser.ParseException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Comment; | ||||
| import com.github.jreddit.parser.entity.Thing; | ||||
| import com.github.jreddit.parser.exception.RedditParseException; | ||||
| 
 | ||||
| public class CommentsListingParser extends RedditListingParser { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(CommentsListingParser.class); | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a list of comments. | ||||
|      * This parser expects the JSON to be of a listing of comments.<br> | ||||
|      * <br> | ||||
|      * <i>Note: this parsing can only be performed on listings of comments, not on | ||||
|      * a comment tree of a submission.</i> | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @return Parsed list of comments | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      * @throws RedditRequestException | ||||
|      */ | ||||
|     public List<Comment> parse(String jsonText) throws RedditParseException { | ||||
|          | ||||
|         // Parse to a list of things | ||||
|         List<Thing> things = this.parseGeneric(jsonText); | ||||
|          | ||||
|         // List of comment and submission mixed elements | ||||
|         List<Comment> comments = new LinkedList<Comment>(); | ||||
|          | ||||
|         // Iterate over things | ||||
|         for (Thing t : things) { | ||||
|              | ||||
|             if (t instanceof Comment) { | ||||
|                 comments.add((Comment) t); | ||||
|             } else { | ||||
|                 LOGGER.warn("Encountered an unexpected reddit thing (" + t.getKind().value() + "), skipping it."); | ||||
|             } | ||||
|              | ||||
|         } | ||||
|          | ||||
|         // Return resulting comments list | ||||
|         return comments; | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,84 @@ | ||||
| package com.github.jreddit.parser.listing; | ||||
| 
 | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.JSONObject; | ||||
| import org.json.simple.parser.JSONParser; | ||||
| import org.json.simple.parser.ParseException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Comment; | ||||
| import com.github.jreddit.parser.entity.More; | ||||
| import com.github.jreddit.parser.entity.Thing; | ||||
| import com.github.jreddit.parser.entity.imaginary.CommentTreeElement; | ||||
| import com.github.jreddit.parser.exception.RedditParseException; | ||||
| 
 | ||||
| public class CommentsMoreParser extends RedditListingParser { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(CommentsMoreParser.class); | ||||
|      | ||||
|     private static final JSONParser JSON_PARSER = new JSONParser(); | ||||
|      | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a list of new additional comment tree elements. | ||||
|      * This parser expects the JSON to be of a listing of comments and more's.<br> | ||||
|      * <br> | ||||
|      * <i>Note: this parsing can only be performed on listings of comments and more's, not on | ||||
|      * a comment tree of a submission.</i> | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @return Parsed list of comments | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      * @throws RedditRequestException | ||||
|      */ | ||||
|     public List<CommentTreeElement> parse(String jsonText) throws RedditParseException { | ||||
|          | ||||
|         try { | ||||
|              | ||||
|             // Parse JSON response | ||||
|             Object response = JSON_PARSER.parse(jsonText); | ||||
|              | ||||
|             // Validate main | ||||
|             this.validate(response); | ||||
|              | ||||
|             // Move to the main object | ||||
|             JSONObject main = (JSONObject) ((JSONObject) response).get("json"); | ||||
|              | ||||
|             // List of comment and more mixed elements | ||||
|             List<CommentTreeElement> elements = new LinkedList<CommentTreeElement>(); | ||||
|              | ||||
|             // If the main has data (it can happen that it does not, when no comments identifiers were passed along) | ||||
|             if (main.get("data") != null) { | ||||
|              | ||||
|                 // Parse to a list of things | ||||
|                 List<Thing> things = this.parseGeneric(main.toJSONString(), "things"); | ||||
|              | ||||
|                 // Iterate over things | ||||
|                 for (Thing t : things) { | ||||
|                      | ||||
|                     if (t instanceof Comment) { | ||||
|                         elements.add((Comment) t); | ||||
|                     } else if (t instanceof More) { | ||||
|                         elements.add((More) t); | ||||
|                     } else { | ||||
|                         LOGGER.warn("Encountered an unexpected reddit thing (" + t.getKind().value() + "), skipping it."); | ||||
|                     } | ||||
|                      | ||||
|                 } | ||||
|              | ||||
|             } | ||||
|              | ||||
|             // Return resulting element list | ||||
|             return elements; | ||||
|          | ||||
|         } catch (ParseException pe) { | ||||
|             throw new RedditParseException(pe); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,62 @@ | ||||
| package com.github.jreddit.parser.listing; | ||||
| 
 | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.parser.ParseException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Comment; | ||||
| import com.github.jreddit.parser.entity.Submission; | ||||
| import com.github.jreddit.parser.entity.Thing; | ||||
| import com.github.jreddit.parser.entity.imaginary.MixedListingElement; | ||||
| import com.github.jreddit.parser.exception.RedditParseException; | ||||
| 
 | ||||
| /** | ||||
|  * Parser for a listing that has both submissions and comments mixed together. | ||||
|  *  | ||||
|  * @author Simon Kassing | ||||
|  *  | ||||
|  * @see MixedListingElement | ||||
|  */ | ||||
| public class MixedListingParser extends RedditListingParser { | ||||
|      | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(MixedListingParser.class); | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a list of submissions and comments. | ||||
|      * This parser expects the JSON to be of a listing of submissions and comments. | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @return Parsed list of submissions | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      */ | ||||
|     public List<MixedListingElement> parse(String jsonText) throws RedditParseException { | ||||
|          | ||||
|         // Parse to a list of things | ||||
|         List<Thing> things = this.parseGeneric(jsonText); | ||||
|          | ||||
|         // List of comment and submission mixed elements | ||||
|         List<MixedListingElement> mixedElements = new LinkedList<MixedListingElement>(); | ||||
|          | ||||
|         // Iterate over things | ||||
|         for (Thing t : things) { | ||||
|              | ||||
|             if (t instanceof Comment) { | ||||
|                 mixedElements.add((Comment) t); | ||||
|             } else if (t instanceof Submission) { | ||||
|                 mixedElements.add((Submission) t); | ||||
|             } else { | ||||
|                 LOGGER.warn("Encountered an unexpected reddit thing (" + t.getKind().value() + "), skipping it."); | ||||
|             } | ||||
|              | ||||
|         } | ||||
|          | ||||
|         // Return result | ||||
|         return mixedElements; | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,193 @@ | ||||
| package com.github.jreddit.parser.listing; | ||||
| 
 | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToString; | ||||
| 
 | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.JSONArray; | ||||
| import org.json.simple.JSONObject; | ||||
| import org.json.simple.parser.JSONParser; | ||||
| import org.json.simple.parser.ParseException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Comment; | ||||
| import com.github.jreddit.parser.entity.Kind; | ||||
| import com.github.jreddit.parser.entity.More; | ||||
| import com.github.jreddit.parser.entity.Submission; | ||||
| import com.github.jreddit.parser.entity.Subreddit; | ||||
| import com.github.jreddit.parser.entity.Thing; | ||||
| import com.github.jreddit.parser.exception.RedditParseException; | ||||
| import com.github.jreddit.parser.util.JsonUtils; | ||||
| 
 | ||||
| public class RedditListingParser { | ||||
|      | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(RedditListingParser.class); | ||||
|      | ||||
|     protected static final JSONParser JSON_PARSER = new JSONParser(); | ||||
|      | ||||
|     /** | ||||
|      * Validate that it is indeed the starting of a listing of reddit things. | ||||
|      *  | ||||
|      * @param response Object returned by JSON parser | ||||
|      *  | ||||
|      * @throws RedditRequestException If the response is not valid listing of reddit things | ||||
|      */ | ||||
|     public void validate(Object response) throws RedditParseException { | ||||
|          | ||||
|         // Check for null | ||||
|         if (response == null) { | ||||
|             throw new RedditParseException(); | ||||
|         } | ||||
|          | ||||
|         // Check it is a JSON response | ||||
|         if (!(response instanceof JSONObject)) { | ||||
|             throw new RedditParseException("not a JSON response"); | ||||
|         } | ||||
|          | ||||
|         // Cast to JSON object | ||||
|         JSONObject jsonResponse = ((JSONObject) response); | ||||
|          | ||||
|         // Check for error | ||||
|         if (jsonResponse.get("error") != null) { | ||||
|             throw new RedditParseException(JsonUtils.safeJsonToInteger(jsonResponse.get("error"))); | ||||
|         } | ||||
|          | ||||
|         // Check that data exists | ||||
|         if (jsonResponse.get("data") == null && jsonResponse.get("json") == null) { | ||||
|             throw new RedditParseException("data is missing from listing"); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a list of things. | ||||
|      * This parser expects the JSON to be of a listing of things, and supports  | ||||
|      * the following things: <i>More</i>, <i>Comment</i>, <i>Submission</i>, and <i>Subreddit</i>. | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @return Parsed list of things | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      */ | ||||
|     public List<Thing> parseGeneric(String jsonText) throws RedditParseException { | ||||
|         return parseGeneric(jsonText, "children"); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a list of things. | ||||
|      * This parser expects the JSON to be of a listing of things, and supports  | ||||
|      * the following things: <i>More</i>, <i>Comment</i>, <i>Submission</i>, and <i>Subreddit</i>.<br> | ||||
|      * <br> | ||||
|      * <i>Note: if it encounters an invalid element (e.g. missing kind or data), it will | ||||
|      * log a warning using SLF4J and would return null.</i> | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @param listingName Name of the listing name within the data | ||||
|      *  | ||||
|      * @return Parsed list of things | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      */ | ||||
|     public List<Thing> parseGeneric(String jsonText, String listingName) throws RedditParseException { | ||||
|          | ||||
|         try { | ||||
|          | ||||
|             // List of submissions | ||||
|             List<Thing> things = new LinkedList<Thing>(); | ||||
|              | ||||
|             // Send request to reddit server via REST client | ||||
|             Object response = JSON_PARSER.parse(jsonText); | ||||
|              | ||||
|             // Check for reddit error, can throw a RedditError | ||||
|             validate(response); | ||||
|              | ||||
|             // Cast to a JSON object | ||||
|             JSONObject object = (JSONObject) response; | ||||
|              | ||||
|             // Get the array of children | ||||
|             JSONArray array = (JSONArray) ((JSONObject) object.get("data")).get(listingName); | ||||
|      | ||||
|             // Iterate over array of children | ||||
|             for (Object element : array) { | ||||
|                  | ||||
|                 // Get the element | ||||
|                 JSONObject data = (JSONObject) element; | ||||
|                  | ||||
|                 // Make sure it is of the correct kind | ||||
|                 String kindData = safeJsonToString(data.get("kind")); | ||||
|                 Object objData = data.get("data"); | ||||
|                  | ||||
|                 // If no kind is given | ||||
|                 if (kindData == null) { | ||||
|                     LOGGER.warn("Kind data missing, skipping it."); | ||||
|                      | ||||
|                 // If no data is given | ||||
|                 } else if (objData == null || !(objData instanceof JSONObject)) { | ||||
|                     LOGGER.warn("Object data missing, skipping it."); | ||||
|                      | ||||
|                 } else { | ||||
|                      | ||||
|                     // Attempt to match | ||||
|                     Kind kind = Kind.match(kindData); | ||||
|                      | ||||
|                     // Parse the thing | ||||
|                     Thing thing = parseThing(kind, ((JSONObject) data.get("data"))); | ||||
|                      | ||||
|                     // Show warning if failed | ||||
|                     if (thing == null) { | ||||
|                         LOGGER.warn("Encountered invalid kind for a listing (" + kindData + "), skipping it."); | ||||
|      | ||||
|                     } else { | ||||
|                         things.add(thing); | ||||
|                     } | ||||
|                      | ||||
|                 } | ||||
|                  | ||||
|             } | ||||
|              | ||||
|             // Finally return list of submissions  | ||||
|             return things; | ||||
|          | ||||
|         } catch (ParseException pe) { | ||||
|             throw new RedditParseException(pe); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Parse the data into a thing if possible. | ||||
|      *  | ||||
|      * @param kind Kind of data | ||||
|      * @param data Data for the thing | ||||
|      * @return The thing generated from the data, if failed <i>null</i> | ||||
|      */ | ||||
|     private Thing parseThing(Kind kind, JSONObject data) { | ||||
|          | ||||
|         // For a comment | ||||
|         if (kind == Kind.COMMENT) {  | ||||
|             return new Comment(data); | ||||
|              | ||||
|         // For a submission | ||||
|         } else if (kind == Kind.LINK) { | ||||
|             return new Submission(data); | ||||
|          | ||||
|         // For a subreddit | ||||
|         } else if (kind == Kind.SUBREDDIT) {  | ||||
|             return new Subreddit(data); | ||||
|            | ||||
|         // For a more | ||||
|         } else if (kind == Kind.MORE) {  | ||||
|             return new More(data); | ||||
|              | ||||
|         // In all other cases (null, or of a different type) | ||||
|         } else { | ||||
|             return null; | ||||
|         } | ||||
|          | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,51 @@ | ||||
| package com.github.jreddit.parser.listing; | ||||
| 
 | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.parser.ParseException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Submission; | ||||
| import com.github.jreddit.parser.entity.Thing; | ||||
| import com.github.jreddit.parser.exception.RedditParseException; | ||||
| 
 | ||||
| public class SubmissionsListingParser extends RedditListingParser { | ||||
|      | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(SubmissionsListingParser.class); | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a list of submissions. | ||||
|      * This parser expects the JSON to be of a listing of submissions ('links'). | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @return Parsed list of submissions | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      */ | ||||
|     public List<Submission> parse(String jsonText) throws RedditParseException { | ||||
|          | ||||
|         // Parse to a list of things | ||||
|         List<Thing> things = this.parseGeneric(jsonText); | ||||
|          | ||||
|         // List of comment and submission mixed elements | ||||
|         List<Submission> submissions = new LinkedList<Submission>(); | ||||
|          | ||||
|         // Iterate over things | ||||
|         for (Thing t : things) { | ||||
|              | ||||
|             if (t instanceof Submission) { | ||||
|                 submissions.add((Submission) t); | ||||
|             } else { | ||||
|                 LOGGER.warn("Encountered an unexpected reddit thing (" + t.getKind().value() + "), skipping it."); | ||||
|             } | ||||
|              | ||||
|         } | ||||
|          | ||||
|         // Return resulting comments list | ||||
|         return submissions; | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,51 @@ | ||||
| package com.github.jreddit.parser.listing; | ||||
| 
 | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.parser.ParseException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Subreddit; | ||||
| import com.github.jreddit.parser.entity.Thing; | ||||
| import com.github.jreddit.parser.exception.RedditParseException; | ||||
| 
 | ||||
| public class SubredditsListingParser extends RedditListingParser { | ||||
|      | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(SubredditsListingParser.class); | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a list of subreddits. | ||||
|      * This parser expects the JSON to be of a listing of subreddits. | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @return Parsed list of subreddits | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      */ | ||||
|     public List<Subreddit> parse(String jsonText) throws RedditParseException { | ||||
|          | ||||
|         // Parse to a list of things | ||||
|         List<Thing> things = this.parseGeneric(jsonText); | ||||
|          | ||||
|         // List of comment and submission mixed elements | ||||
|         List<Subreddit> subreddits = new LinkedList<Subreddit>(); | ||||
|          | ||||
|         // Iterate over things | ||||
|         for (Thing t : things) { | ||||
|              | ||||
|             if (t instanceof Subreddit) { | ||||
|                 subreddits.add((Subreddit) t); | ||||
|             } else { | ||||
|                 LOGGER.warn("Encountered an unexpected reddit thing (" + t.getKind().value() + "), skipping it."); | ||||
|             } | ||||
|              | ||||
|         } | ||||
|          | ||||
|         // Return resulting comments list | ||||
|         return subreddits; | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,156 @@ | ||||
| package com.github.jreddit.parser.single; | ||||
| 
 | ||||
| import static com.github.jreddit.parser.util.JsonUtils.safeJsonToString; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.json.simple.JSONArray; | ||||
| import org.json.simple.JSONObject; | ||||
| import org.json.simple.parser.JSONParser; | ||||
| import org.json.simple.parser.ParseException; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Comment; | ||||
| import com.github.jreddit.parser.entity.Kind; | ||||
| import com.github.jreddit.parser.entity.More; | ||||
| import com.github.jreddit.parser.entity.Submission; | ||||
| import com.github.jreddit.parser.entity.imaginary.CommentTreeElement; | ||||
| import com.github.jreddit.parser.entity.imaginary.FullSubmission; | ||||
| import com.github.jreddit.parser.exception.RedditParseException; | ||||
| import com.github.jreddit.parser.util.JsonUtils; | ||||
| 
 | ||||
| public class FullSubmissionParser { | ||||
| 
 | ||||
|     protected static final JSONParser JSON_PARSER = new JSONParser(); | ||||
|      | ||||
|     /** | ||||
|      * Parse JSON received from reddit into a full submission. | ||||
|      * A full submissions means it has both (a) the submission, and (b) the comment tree. | ||||
|      *  | ||||
|      * @param jsonText JSON Text | ||||
|      * @return Full submission | ||||
|      *  | ||||
|      * @throws ParseException | ||||
|      */ | ||||
|     public FullSubmission parse(String jsonText) throws RedditParseException { | ||||
|          | ||||
|         try { | ||||
|          | ||||
|             // Parse JSON text | ||||
|             Object response = JSON_PARSER.parse(jsonText); | ||||
|          | ||||
|             // Validate response | ||||
|             validate(response); | ||||
|      | ||||
|             // Create submission (casting with JSON is horrible) | ||||
|             JSONObject main = (JSONObject) ((JSONArray) response).get(0); | ||||
|             Submission submission = new Submission((JSONObject) ((JSONObject) ((JSONArray)((JSONObject) main.get("data")).get("children")).get(0)).get("data")); | ||||
|               | ||||
|             // Create comment tree | ||||
|             JSONObject mainTree =  (JSONObject) ((JSONArray) response).get(1); | ||||
|             List<CommentTreeElement> commentTree = parseRecursive(mainTree); | ||||
|              | ||||
|             // Return the set of submission and its comment tree | ||||
|             return new FullSubmission(submission,  commentTree); | ||||
|          | ||||
|         } catch (ParseException pe) { | ||||
|             throw new RedditParseException(pe); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Parse a JSON object consisting of comments and add them | ||||
|      * to the already existing list of comments. This does NOT create | ||||
|      * a new comment list. | ||||
|      *  | ||||
|      * @param comments     List of comments | ||||
|      * @param object    JSON Object | ||||
|      */ | ||||
|     protected List<CommentTreeElement> parseRecursive(JSONObject main) throws RedditParseException { | ||||
| 
 | ||||
|         List<CommentTreeElement> commentTree = new ArrayList<CommentTreeElement>(); | ||||
|          | ||||
|         // Iterate over the comment tree results | ||||
|         JSONArray array = (JSONArray) ((JSONObject) main.get("data")).get("children"); | ||||
|         for (Object element : array) { | ||||
|              | ||||
|             // Get the element | ||||
|             JSONObject data = (JSONObject) element; | ||||
|              | ||||
|             // Make sure it is of the correct kind | ||||
|             String kind = safeJsonToString(data.get("kind")); | ||||
|              | ||||
|             // If it is a comment | ||||
|             if (kind != null && kind.equals(Kind.COMMENT.value())) { | ||||
|                  | ||||
|                 // Create comment | ||||
|                 Comment comment = new Comment( (JSONObject) data.get("data") ); | ||||
|                  | ||||
|                 // Retrieve replies | ||||
|                 Object replies = ((JSONObject) data.get("data")).get("replies"); | ||||
|                  | ||||
|                 // If it is an JSON object | ||||
|                 if (replies instanceof JSONObject) { | ||||
|                     comment.setReplies(parseRecursive( (JSONObject) replies )); | ||||
|                      | ||||
|                 // If there are no replies, end with an empty one | ||||
|                 } else { | ||||
|                     comment.setReplies(new ArrayList<CommentTreeElement>()); | ||||
|                 } | ||||
|                  | ||||
|                 // Add comment to the tree | ||||
|                 commentTree.add(comment); | ||||
|             } | ||||
|              | ||||
|             // If it is a more | ||||
|             if (kind != null && kind.equals(Kind.MORE.value())) { | ||||
|                  | ||||
|                 // Add to comment tree | ||||
|                 commentTree.add(new More((JSONObject) data.get("data"))); | ||||
|                  | ||||
|             } | ||||
|              | ||||
|         } | ||||
|          | ||||
|         return commentTree; | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Validate that it is in fact a full submission. | ||||
|      *  | ||||
|      * @param response Object from the JSON parser | ||||
|      *  | ||||
|      * @throws RedditRequestException If the JSON is in incorrect format | ||||
|      */ | ||||
|     public void validate(Object response) throws RedditParseException { | ||||
|          | ||||
|         // Check for null | ||||
|         if (response == null) { | ||||
|             throw new RedditParseException(); | ||||
|         } | ||||
|          | ||||
|         // Check it is a JSON response | ||||
|         if (response instanceof JSONObject) { | ||||
| 
 | ||||
|             // Cast to JSON object | ||||
|             JSONObject jsonResponse = (JSONObject) response; | ||||
|              | ||||
|             // Check for error | ||||
|             if (jsonResponse.get("error") != null) { | ||||
|                 throw new RedditParseException(JsonUtils.safeJsonToInteger(jsonResponse.get("error"))); | ||||
|             } else { | ||||
|                 throw new RedditParseException("invalid json format, started with object (should start with array)"); | ||||
|             } | ||||
|          | ||||
|         } | ||||
|          | ||||
|         // It must start with an array | ||||
|         if (!(response instanceof JSONArray)) { | ||||
|             throw new RedditParseException("invalid json format, did not start with array"); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,96 @@ | ||||
| package com.github.jreddit.parser.util; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Comment; | ||||
| import com.github.jreddit.parser.entity.imaginary.CommentTreeElement; | ||||
| 
 | ||||
| public class CommentTreeUtils { | ||||
|      | ||||
|     private CommentTreeUtils() { | ||||
|         // Empty to disallow the invocation of the default constructor for this utility class | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Flatten the comment tree. | ||||
|      * The original comment tree is not overwritten. | ||||
|      *  | ||||
|      * @param cs        List of comments that you get returned from one of the other methods here | ||||
|      *  | ||||
|      * @return    Flattened comment tree. | ||||
|      */ | ||||
|     public static List<CommentTreeElement> flattenCommentTree(List<CommentTreeElement> commentTree) { | ||||
|         List<CommentTreeElement> target = new ArrayList<CommentTreeElement>(); | ||||
|         flattenCommentTree(commentTree, target); | ||||
|         return target; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Flatten the comment tree. | ||||
|      * The original comment tree is not overwritten. | ||||
|      *  | ||||
|      * @param cs        List of comments that you get returned from one of the other methods here | ||||
|      * @param target    List in which to place the flattened comment tree. | ||||
|      */ | ||||
|     private static void flattenCommentTree(List<CommentTreeElement> commentTree, List<CommentTreeElement> target) { | ||||
|         for (CommentTreeElement c : commentTree) { | ||||
|             target.add(c); | ||||
|             if (c instanceof Comment) { | ||||
|                 flattenCommentTree(((Comment)c).getReplies(), target); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Get printable version of the given comment tree. | ||||
|      *  | ||||
|      * @param cs     List of comment tree elements | ||||
|      *  | ||||
|      * @return Printable comment tree | ||||
|      */ | ||||
|     public static String printCommentTree(List<CommentTreeElement> cs) { | ||||
|         StringBuilder builder = new StringBuilder(); | ||||
|         for (CommentTreeElement c : cs) { | ||||
|             builder.append(printCommentTree(c, 0)); | ||||
|         } | ||||
|         return builder.toString(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Get printable version of a comment at a specific level.<br> | ||||
|      * <br> | ||||
|      * <i>Note: uses unsafe recursion</i> | ||||
|      *  | ||||
|      * @param c            Comment | ||||
|      * @param level        Level to place at | ||||
|      *  | ||||
|      * @return Printable comment tree | ||||
|      */ | ||||
|     private static String printCommentTree(CommentTreeElement c, int level) { | ||||
|          | ||||
|         // Initialize empty buffer | ||||
|         StringBuilder builder = new StringBuilder(); | ||||
|          | ||||
|         // Add tabulation | ||||
|         for (int i = 0; i < level; i++) { | ||||
|             builder.append("\t"); | ||||
|         } | ||||
|          | ||||
|         // Comment string | ||||
|         builder.append(c.toString()); | ||||
|         builder.append("\n"); | ||||
|          | ||||
|         // Iterate over children | ||||
|         if (c instanceof Comment) { | ||||
|             for (CommentTreeElement child : ((Comment) c).getReplies()) { | ||||
|                 builder.append(printCommentTree(child, level + 1)); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         // Return the buffer | ||||
|         return builder.toString(); | ||||
|          | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										98
									
								
								src/main/com/github/jreddit/parser/util/JsonUtils.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/main/com/github/jreddit/parser/util/JsonUtils.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| package com.github.jreddit.parser.util; | ||||
| 
 | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| /** | ||||
|  * Safe utilities (not throwing exceptions) for the conversion of JSON | ||||
|  * data into basic types such as Integer, Boolean, Long, and Double. | ||||
|  */ | ||||
| public final class JsonUtils { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtils.class); | ||||
|      | ||||
|     private JsonUtils() { | ||||
|         // forbid creating JsonUtils instance | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Safely converts an object into string (used because sometimes JSONObject's get() method returns null). | ||||
|      * | ||||
|      * @param obj The object to convert. | ||||
|      * @return The string. | ||||
|      */ | ||||
|     public static String safeJsonToString(Object obj) { | ||||
|         return obj == null ? null : obj.toString(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Safely converts an object into an integer | ||||
|      * | ||||
|      * @param obj The object to convert. | ||||
|      * @return an Integer representing the integer value of the Object (null if the object cannot be converted to an Integer) | ||||
|      */ | ||||
|     public static Integer safeJsonToInteger(Object obj) { | ||||
|         Integer intValue = null; | ||||
| 
 | ||||
|         try { | ||||
|             String str = safeJsonToString(obj); | ||||
|             intValue = str != null ? Integer.parseInt(str) : null; | ||||
|         } catch (NumberFormatException e) { | ||||
|             LOGGER.warn("Safe JSON conversion to Integer failed", e); | ||||
|         } | ||||
| 
 | ||||
|         return intValue; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Safely converts an object into an double | ||||
|      * | ||||
|      * @param obj The object to convert. | ||||
|      * @return a Double representing the double value of the Object (null if the object cannot be converted to Double) | ||||
|      */ | ||||
|     public static Double safeJsonToDouble(Object obj) { | ||||
|         Double doubleValue = null; | ||||
| 
 | ||||
|         try { | ||||
|             String str = safeJsonToString(obj); | ||||
|             doubleValue = str != null ? Double.parseDouble(str) : null; | ||||
|         } catch (NumberFormatException e) { | ||||
|             LOGGER.warn("Safe JSON conversion to Double failed", e); | ||||
|         } | ||||
| 
 | ||||
|         return doubleValue; | ||||
|     } | ||||
|      | ||||
|      | ||||
|     /** | ||||
|      * Safely converts an object into an boolean | ||||
|      * | ||||
|      * @param obj The object to convert. | ||||
|      * @return a Boolean representing the boolean value of the Object (null only if the object was also null) | ||||
|      */ | ||||
|     public static Boolean safeJsonToBoolean(Object obj) { | ||||
|         String str = safeJsonToString(obj); | ||||
|         Boolean booleanValue = str != null ? Boolean.parseBoolean(str) : null; | ||||
|         return booleanValue; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Safely converts an object into an long | ||||
|      * | ||||
|      * @param obj The object to convert. | ||||
|      * @return a Long representing the long value of the Object (null if the object cannot be converted to Long) | ||||
|      */ | ||||
|     public static Long safeJsonToLong(Object obj) { | ||||
|         Long longValue = null; | ||||
| 
 | ||||
|         try { | ||||
|             String str = safeJsonToString(obj); | ||||
|             longValue = str != null ? Long.parseLong(str) : null; | ||||
|         } catch (NumberFormatException e) { | ||||
|             LOGGER.warn("Safe JSON conversion to Long failed", e); | ||||
|         } | ||||
| 
 | ||||
|         return longValue; | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										48
									
								
								src/main/com/github/jreddit/request/RedditGetRequest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/main/com/github/jreddit/request/RedditGetRequest.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| package com.github.jreddit.request; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import com.github.jreddit.request.util.KeyValueFormatter; | ||||
| 
 | ||||
| public abstract class RedditGetRequest { | ||||
| 
 | ||||
|     /** Mapping of all request parameters. */ | ||||
|     private Map<String, String> parameters; | ||||
|      | ||||
|     /** | ||||
|      * Default constructor. | ||||
|      */ | ||||
|     public RedditGetRequest() { | ||||
|         parameters = new HashMap<String, String>(); | ||||
|     }  | ||||
|      | ||||
|     /** | ||||
|      * Add a parameter to the request. | ||||
|      * If the key of the parameter already exists, the previous value will be overwritten. | ||||
|      *  | ||||
|      * @param key Key of the parameter (e.g. "limit") | ||||
|      * @param value Value of the parameter (e.g. "100") | ||||
|      */ | ||||
|     protected void addParameter(String key, String value) { | ||||
|         parameters.put(key, value); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate the query parameters to be added to an URL. | ||||
|      *  | ||||
|      * @return Parameters (e.g. "limit=100&sort=top") | ||||
|      */ | ||||
|     protected String generateParameters() { | ||||
|         return KeyValueFormatter.format(parameters, true); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate the URI of the request. | ||||
|      * Be sure to call {@link #generateParameters()} to add the parameters to the end of the URL. | ||||
|      *  | ||||
|      * @return Reddit Uniform Resource Identifier (e.g. "/usr/endpoint?limit=100&sort=top") | ||||
|      */ | ||||
|     public abstract String generateRedditURI(); | ||||
|      | ||||
| } | ||||
							
								
								
									
										86
									
								
								src/main/com/github/jreddit/request/RedditPostRequest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/main/com/github/jreddit/request/RedditPostRequest.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | ||||
| package com.github.jreddit.request; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import com.github.jreddit.request.util.KeyValueFormatter; | ||||
| 
 | ||||
| public abstract class RedditPostRequest { | ||||
| 
 | ||||
|     /** Mapping of all request query parameters. */ | ||||
|     private Map<String, String> queryParameters; | ||||
|      | ||||
|     /** Mapping of all request body parameters. */ | ||||
|     private Map<String, String> bodyParameters;     | ||||
|      | ||||
|     /** | ||||
|      * Default constructor. | ||||
|      */ | ||||
|     public RedditPostRequest() { | ||||
|         queryParameters = new HashMap<String, String>(); | ||||
|         bodyParameters = new HashMap<String, String>();         | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add a parameter to the query of the request. | ||||
|      * If the key of the parameter already exists, the previous value will be overwritten. | ||||
|      *  | ||||
|      * @param key Key of the parameter (e.g. "limit") | ||||
|      * @param value Value of the parameter (e.g. "100") | ||||
|      */ | ||||
|     protected void addQueryParameter(String key, String value) { | ||||
|         queryParameters.put(key, value); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Add a parameter to the body of the request. | ||||
|      * If the key of the parameter already exists, the previous value will be overwritten. | ||||
|      *  | ||||
|      * @param key Key of the parameter (e.g. "id") | ||||
|      * @param value Value of the parameter (e.g. "dajkjsf8") | ||||
|      */ | ||||
|     protected void addBodyParameter(String key, String value) { | ||||
|         bodyParameters.put(key, value); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate the query parameters to be added to an URI.<br> | ||||
|      * <br> | ||||
|      * <i>Note: values are encoded.</i> | ||||
|      *  | ||||
|      * @return Query parameters (e.g. "limit=100&sort=top") | ||||
|      */ | ||||
|     protected String generateQueryParameters() { | ||||
|         return KeyValueFormatter.format(queryParameters, true); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate the body parameters to be added.<br> | ||||
|      * <br> | ||||
|      * <i>Note: values are encoded.</i> | ||||
|      *  | ||||
|      * @return Body parameters (e.g. "limit=100&sort=top") | ||||
|      */ | ||||
|     protected String generateBodyParameters() { | ||||
|         return KeyValueFormatter.format(bodyParameters, true); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Generate the URI of the request. | ||||
|      * Be sure to call {@link #generateQueryParameters()} in your implementation | ||||
|      * to add the parameters to the end of the URL. | ||||
|      *  | ||||
|      * @return Reddit Uniform Resource Identifier (e.g. "/usr/endpoint?limit=100&sort=top") | ||||
|      */ | ||||
|     public abstract String generateRedditURI(); | ||||
|      | ||||
|     /** | ||||
|      * Generate the body for a POST request using the POST parameters. | ||||
| 
 | ||||
|      * @return Body (e.g. "limit=100&sort=top" for parameters limit: 100 and sort: "top") | ||||
|      */ | ||||
|     public String generateBody() { | ||||
|         return generateBodyParameters(); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| package com.github.jreddit.request.action; | ||||
| 
 | ||||
| import com.github.jreddit.request.RedditPostRequest; | ||||
| 
 | ||||
| public abstract class MarkActionRequest extends RedditPostRequest { | ||||
| 
 | ||||
|     /** | ||||
|      * Action request. | ||||
|      *  | ||||
|      * @param fullname The fullname of the target (e.g. "t3_djkfsjka") | ||||
|      */ | ||||
|     public MarkActionRequest(String fullname) { | ||||
|         this.addBodyParameter("id", fullname); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| package com.github.jreddit.request.action.flair; | ||||
| 
 | ||||
| import com.github.jreddit.request.RedditPostRequest; | ||||
| 
 | ||||
| public class DeleteFlairRequest extends RedditPostRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/deleteflair.json?"; | ||||
| 
 | ||||
|     public DeleteFlairRequest(String username) { | ||||
|         this.addBodyParameter("name", username); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class HideRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/hide.json?"; | ||||
| 
 | ||||
|     public HideRequest(String fullname) { | ||||
|         super(fullname); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class MarkNsfwRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/marknsfw.json?"; | ||||
| 
 | ||||
|     public MarkNsfwRequest(String fullname) { | ||||
|         super(fullname); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class ReportRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/report.json?"; | ||||
| 
 | ||||
|     public ReportRequest(String fullname) { | ||||
|         super(fullname); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class SaveRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/save.json?"; | ||||
| 
 | ||||
|     public SaveRequest(String fullname) { | ||||
|         super(fullname); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class UnhideRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/unhide.json?"; | ||||
| 
 | ||||
|     public UnhideRequest(String fullname) { | ||||
|         super(fullname); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class UnmarkNsfwRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/unmarknsfw.json?"; | ||||
| 
 | ||||
|     public UnmarkNsfwRequest(String fullname) { | ||||
|         super(fullname); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class UnsaveRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/unsave.json?"; | ||||
| 
 | ||||
|     public UnsaveRequest(String fullname) { | ||||
|         super(fullname); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| package com.github.jreddit.request.action.mark; | ||||
| 
 | ||||
| import com.github.jreddit.request.action.MarkActionRequest; | ||||
| 
 | ||||
| 
 | ||||
| public class VoteRequest extends MarkActionRequest { | ||||
|      | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/vote.json?"; | ||||
| 
 | ||||
|     /** | ||||
|      * Vote request constructor. | ||||
|      *  | ||||
|      * @param fullname Fullname of what to vote on | ||||
|      * @param direction Direction (must be -1, 0, or 1) | ||||
|      */ | ||||
|     public VoteRequest(String fullname, int direction) { | ||||
|         super(fullname); | ||||
|         this.addBodyParameter("dir", String.valueOf(direction)); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return ENDPOINT_FORMAT; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,62 @@ | ||||
| package com.github.jreddit.request.retrieval; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Thing; | ||||
| import com.github.jreddit.request.RedditGetRequest; | ||||
| 
 | ||||
| public abstract class ListingRequest extends RedditGetRequest { | ||||
| 
 | ||||
|     /** | ||||
|      * @param count Starting count for first element of listing | ||||
|      * @return This request | ||||
|      */ | ||||
|     public ListingRequest setCount(int count) { | ||||
|         this.addParameter("count", String.valueOf(count)); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @param limit Maximum number of listing elements. This does not mean exactly this parameter will be returned. An upper bound (~100) is imposed by reddit. | ||||
|      * @return This request | ||||
|      */ | ||||
|     public ListingRequest setLimit(int limit) { | ||||
|         this.addParameter("limit", String.valueOf(limit)); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @param after The thing in a listing after which the newly requested listing should start. | ||||
|      * @return This request | ||||
|      */ | ||||
|     public ListingRequest setAfter(Thing after) { | ||||
|         return setAfter(after.getFullName()); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @param after The fullname of a thing in a listing after which the newly requested listing should start. | ||||
|      * @return This request | ||||
|      * @see ListingRequest#setAfter(Thing) The usage of setAfter(Thing) is preferred over this method | ||||
|      */ | ||||
|     public ListingRequest setAfter(String after) { | ||||
|         this.addParameter("after", after); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @param before The thing in a listing before which the newly requested listing should end. | ||||
|      * @return This request | ||||
|      */ | ||||
|     public ListingRequest setBefore(Thing before) { | ||||
|         return setBefore(before.getFullName()); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @param before The fullname of a thing in a listing before which the newly requested listing should end. | ||||
|      * @return This request | ||||
|      * @see ListingRequest#setBefore(Thing) The usage of setBefore(Thing) is preferred over this method | ||||
|      */ | ||||
|     public ListingRequest setBefore(String before) { | ||||
|         this.addParameter("before", before); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,40 @@ | ||||
| package com.github.jreddit.request.retrieval.comments; | ||||
| 
 | ||||
| import com.github.jreddit.request.retrieval.ListingRequest; | ||||
| import com.github.jreddit.request.retrieval.param.TimeSpan; | ||||
| import com.github.jreddit.request.retrieval.param.UserOverviewSort; | ||||
| 
 | ||||
| public class CommentsOfUserRequest extends ListingRequest { | ||||
| 
 | ||||
|     private static final String ENDPOINT_FORMAT = "/user/%s/comments.json?%s"; | ||||
| 
 | ||||
|     String username; | ||||
|      | ||||
|     /** | ||||
|      * @param username Username of a user (e.g. "JohnM") | ||||
|      */ | ||||
|     public CommentsOfUserRequest(String username) { | ||||
|         this.username = username; | ||||
|     } | ||||
| 
 | ||||
|     public CommentsOfUserRequest setSort(UserOverviewSort sort) { | ||||
|         this.addParameter("sort", sort.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public CommentsOfUserRequest setShowGiven() { | ||||
|         this.addParameter("show", "given"); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public CommentsOfUserRequest setTime(TimeSpan time) { | ||||
|         this.addParameter("t", time.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, username, this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,37 @@ | ||||
| package com.github.jreddit.request.retrieval.comments; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import com.github.jreddit.request.RedditGetRequest; | ||||
| import com.github.jreddit.request.retrieval.param.CommentSort; | ||||
| import com.github.jreddit.request.util.KeyValueFormatter; | ||||
| 
 | ||||
| public class MoreCommentsRequest extends RedditGetRequest { | ||||
| 
 | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/api/morechildren.json?%s"; | ||||
|      | ||||
|     /** | ||||
|      * @param submissionFullname Fullname of the submission (e.g. "t3_dajdkjf") | ||||
|      * @param commentIdentifiers List of comment ID36 identifiers (e.g. ["jdafid9", "jdafid10"]) | ||||
|      *  | ||||
|      * @see {@link com.github.jreddit.parser.entity.More#getChildren()} is typically used to retrieve the 2nd parameter | ||||
|      */ | ||||
|     public MoreCommentsRequest(String submissionFullname, List<String> commentIdentifiers) { | ||||
|         // Neglected optional "id" parameter, as it is only relevant for HTML | ||||
|         this.addParameter("api_type", "json"); | ||||
|         this.addParameter("link_id", submissionFullname); | ||||
|         this.addParameter("children", KeyValueFormatter.formatCommaSeparatedList(commentIdentifiers)); | ||||
|     } | ||||
| 
 | ||||
|     public MoreCommentsRequest setSort(CommentSort sort) { | ||||
|         this.addParameter("sort", sort.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,110 @@ | ||||
| package com.github.jreddit.request.retrieval.mixed; | ||||
| 
 | ||||
| import com.github.jreddit.parser.entity.Comment; | ||||
| import com.github.jreddit.parser.entity.Submission; | ||||
| import com.github.jreddit.request.RedditGetRequest; | ||||
| import com.github.jreddit.request.retrieval.param.CommentSort; | ||||
| 
 | ||||
| public class FullSubmissionRequest extends RedditGetRequest { | ||||
| 
 | ||||
|     private static final String ENDPOINT_FORMAT = "/comments/%s.json?%s"; | ||||
| 
 | ||||
|     private String submissionIdentifier; | ||||
|      | ||||
|     /** | ||||
|      * @param submissionIdentifier Submission ID36 identifier (e.g. "dfjIuf") | ||||
|      * | ||||
|      * @see {@link FullSubmissionRequest(Submission)} is preferred over this constructor | ||||
|      */ | ||||
|     public FullSubmissionRequest(String submissionIdentifier) { | ||||
|         this.submissionIdentifier = submissionIdentifier; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * @param submission Submission ID36 identifier (e.g. "dfjIuf") | ||||
|      */ | ||||
|     public FullSubmissionRequest(Submission submission) { | ||||
|         this(submission.getIdentifier()); | ||||
|     } | ||||
| 
 | ||||
|     public FullSubmissionRequest setSort(CommentSort sort) { | ||||
|         this.addParameter("sort", sort.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public FullSubmissionRequest setLimit(int limit) { | ||||
|         this.addParameter("limit", String.valueOf(limit)); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Set the comment that will be the (highlighted) focal point of the  | ||||
|      * returned view and <i>context</i> will be the number of parents shown. | ||||
|      *  | ||||
|      * @param commentIdentifier Comment ID36 identifier | ||||
|      *  | ||||
|      * @return This builder | ||||
|      *  | ||||
|      * @see Comment#getIdentifier() | ||||
|      * @see {@link #setContext(int)} | ||||
|      */ | ||||
|     public FullSubmissionRequest setComment(String commentIdentifier) { | ||||
|         this.addParameter("comment", commentIdentifier); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Set the number of parents shown. This will only affect the result if | ||||
|      * {@link #setComment(String)} has been set. | ||||
|      *  | ||||
|      * @param context Maximum number of parents shown (integer between 0 and 8) | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public FullSubmissionRequest setContext(int context) { | ||||
|         this.addParameter("context", String.valueOf(context)); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Set the maximum depth of subtrees in the thread. | ||||
|      *  | ||||
|      * @param depth An integer indicating maximum depth | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public FullSubmissionRequest setDepth(int depth) { | ||||
|         this.addParameter("depth", String.valueOf(depth)); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Set whether or not to show the edits in the comments. | ||||
|      *  | ||||
|      * @param showEdits Should the edits be shown? | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public FullSubmissionRequest setShowEdits(boolean showEdits) { | ||||
|         this.addParameter("showedits", String.valueOf(showEdits)); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Set whether or not the "more" buttons should be shown. | ||||
|      *  | ||||
|      * @param showMore Should the more buttons be shown? | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public FullSubmissionRequest setShowMore(boolean showMore) { | ||||
|         this.addParameter("showmore", String.valueOf(showMore)); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, submissionIdentifier, this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,63 @@ | ||||
| package com.github.jreddit.request.retrieval.mixed; | ||||
| 
 | ||||
| import com.github.jreddit.request.retrieval.ListingRequest; | ||||
| import com.github.jreddit.request.retrieval.param.TimeSpan; | ||||
| import com.github.jreddit.request.retrieval.param.UserMixedCategory; | ||||
| import com.github.jreddit.request.retrieval.param.UserOverviewSort; | ||||
| 
 | ||||
| public class MixedOfUserRequest extends ListingRequest { | ||||
| 
 | ||||
|     /** Endpoint format. */ | ||||
|     private static final String ENDPOINT_FORMAT = "/user/%s/%s.json?%s"; | ||||
|      | ||||
|     private UserMixedCategory category; | ||||
|     private String username; | ||||
|      | ||||
|     /** | ||||
|      * @param username Username of a user (e.g. "JohnM") | ||||
|      * @param category Category of mixed things | ||||
|      */ | ||||
|     public MixedOfUserRequest(String username, UserMixedCategory category) { | ||||
|         this.username = username; | ||||
|         this.category = category; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set the sorting method.<br> | ||||
|      * <br> | ||||
|      * <i>Note: This only works for Overview</i> | ||||
|      *  | ||||
|      * @param sort Sorting method | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public MixedOfUserRequest setSort(UserOverviewSort sort) { | ||||
|         this.addParameter("sort", sort.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Set the time span.<br> | ||||
|      * <br> | ||||
|      * <i>Note: This only works for Overview, and then specifically for the top/controversial sorting method.</i> | ||||
|      *  | ||||
|      * @param time Time span | ||||
|      *  | ||||
|      * @return This builder | ||||
|      */ | ||||
|     public MixedOfUserRequest setTime(TimeSpan time) { | ||||
|         this.addParameter("t", time.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public MixedOfUserRequest setShowGiven() { | ||||
|         this.addParameter("show", "given"); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, username, category.value(), this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,29 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enum to represent comment sorts on Reddit. You see these on a page that lists comments. | ||||
|  * | ||||
|  * @author Evin Ugur | ||||
|  * @author Raul Rene Lepsa | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum CommentSort { | ||||
| 
 | ||||
|     CONFIDENCE("confidence"), | ||||
|     NEW("new"),  | ||||
|     TOP("top"),  | ||||
|     CONTROVERSIAL("controversial"),  | ||||
|     OLD("old"),  | ||||
|     QA("qa"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     CommentSort(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,22 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enum to represent the possible query syntaxes. | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum QuerySyntax { | ||||
| 
 | ||||
|     CLOUDSEARCH            ("cloudsearch"),  | ||||
|     LUCENE                ("lucene"),  | ||||
|     PLAIN                ("plain"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     QuerySyntax(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enumeration to represent the different sort methods for submission search. | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum SearchSort { | ||||
| 
 | ||||
|     HOT("hot"),  | ||||
|     RELEVANCE("relevance"),  | ||||
|     NEW("new"),  | ||||
|     TOP("top"),  | ||||
|     COMMENTS("comments"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     SearchSort(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enum to represent submission sorts on Reddit. You see these on a page that lists Submissions. | ||||
|  * | ||||
|  * @author Evin Ugur | ||||
|  * @author Raul Rene Lepsa | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum SubmissionSort { | ||||
| 
 | ||||
|     HOT("hot"),  | ||||
|     NEW("new"),  | ||||
|     RISING("rising"),  | ||||
|     CONTROVERSIAL("controversial"),  | ||||
|     TOP("top"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     SubmissionSort(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enumeration to represent the different subreddit categories. | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum SubredditsView { | ||||
| 
 | ||||
|     NEW("new"),  | ||||
|     POPULAR("popular"),  | ||||
|     MINE_SUBSCRIBER("mine/subscriber"),  | ||||
|     MINE_CONTRIBUTOR("mine/contributor"),  | ||||
|     MINE_MODERATOR("mine/moderator"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     SubredditsView(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enumeration to represent the different submission search times. | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum TimeSpan { | ||||
| 
 | ||||
|     HOUR("hour"),  | ||||
|     DAY("day"),  | ||||
|     WEEK("week"),  | ||||
|     MONTH("month"),  | ||||
|     YEAR("year"), | ||||
|     ALL("all"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     TimeSpan(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| public enum UserMixedCategory { | ||||
|      | ||||
|     OVERVIEW("overview"),  | ||||
|     GILDED_RECEIVED("gilded"),  | ||||
|     GILDED_GIVEN("gilded/given"),  | ||||
|     SAVED("saved"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     UserMixedCategory(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,24 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| /** | ||||
|  * Enumeration to represent the different sort methods for the user overview. | ||||
|  * @author Simon Kassing | ||||
|  */ | ||||
| public enum UserOverviewSort { | ||||
|      | ||||
|     NEW("new"),  | ||||
|     HOT("hot"),  | ||||
|     TOP("top"),  | ||||
|     COMMENTS("controversial"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     UserOverviewSort(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package com.github.jreddit.request.retrieval.param; | ||||
| 
 | ||||
| public enum UserSubmissionsCategory { | ||||
|      | ||||
|     SUBMITTED("submitted"),  | ||||
|     UPVOTED("upvoted"),  | ||||
|     DOWNVOTED("downvoted"),  | ||||
|     HIDDEN("hidden"); | ||||
| 
 | ||||
|     private final String value; | ||||
| 
 | ||||
|     UserSubmissionsCategory(String value) { | ||||
|         this.value = value; | ||||
|     } | ||||
| 
 | ||||
|     public String value() { | ||||
|         return this.value; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| package com.github.jreddit.request.retrieval.submissions; | ||||
| 
 | ||||
| import com.github.jreddit.request.retrieval.ListingRequest; | ||||
| import com.github.jreddit.request.retrieval.param.SubmissionSort; | ||||
| 
 | ||||
| public class SubmissionsOfSubredditRequest extends ListingRequest { | ||||
| 
 | ||||
|     private static final String ENDPOINT_FORMAT = "/r/%s/%s.json?%s"; | ||||
|      | ||||
|     private SubmissionSort sort; | ||||
|     private String subreddit; | ||||
|      | ||||
|     /** | ||||
|      * @param subreddit Subreddit (e.g. "funny") | ||||
|      * @param sort Sorting method | ||||
|      */ | ||||
|     public SubmissionsOfSubredditRequest(String subreddit, SubmissionSort sort) { | ||||
|         this.subreddit = subreddit; | ||||
|         this.sort = sort; | ||||
|     } | ||||
|      | ||||
|     public SubmissionsOfSubredditRequest setShowAll() { | ||||
|         this.addParameter("show", "all"); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, subreddit, sort.value(), this.generateParameters()); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| package com.github.jreddit.request.retrieval.submissions; | ||||
| 
 | ||||
| import com.github.jreddit.request.retrieval.ListingRequest; | ||||
| import com.github.jreddit.request.retrieval.param.TimeSpan; | ||||
| import com.github.jreddit.request.retrieval.param.UserOverviewSort; | ||||
| import com.github.jreddit.request.retrieval.param.UserSubmissionsCategory; | ||||
| 
 | ||||
| public class SubmissionsOfUserRequest extends ListingRequest { | ||||
| 
 | ||||
|     private static final String ENDPOINT_FORMAT = "/user/%s/%s.json?%s"; | ||||
|      | ||||
|     private UserSubmissionsCategory category; | ||||
|     private String username; | ||||
|      | ||||
|     /** | ||||
|      * @param username Username of a user (e.g. "JohnM") | ||||
|      * @param category Category of user submissions | ||||
|      */ | ||||
|     public SubmissionsOfUserRequest(String username, UserSubmissionsCategory category) { | ||||
|         this.username = username; | ||||
|         this.category = category; | ||||
|     } | ||||
| 
 | ||||
|     public SubmissionsOfUserRequest setSort(UserOverviewSort sort) { | ||||
|         this.addParameter("sort", sort.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public SubmissionsOfUserRequest setTime(TimeSpan time) { | ||||
|         this.addParameter("t", time.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public SubmissionsOfUserRequest setShowGiven() { | ||||
|         this.addParameter("show", "given"); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, username, category.value(), this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| package com.github.jreddit.request.retrieval.submissions; | ||||
| 
 | ||||
| import com.github.jreddit.request.retrieval.ListingRequest; | ||||
| import com.github.jreddit.request.retrieval.param.QuerySyntax; | ||||
| import com.github.jreddit.request.retrieval.param.SearchSort; | ||||
| import com.github.jreddit.request.retrieval.param.TimeSpan; | ||||
| 
 | ||||
| public class SubmissionsSearchRequest extends ListingRequest { | ||||
| 
 | ||||
|     private static final String ENDPOINT_FORMAT = "/search.json?%s"; | ||||
| 
 | ||||
|     /** | ||||
|      * @param query Mandatory search query (e.g. "programming Java"), its syntax depends on what is set using {@link #setSyntax(QuerySyntax)}. | ||||
|      */ | ||||
|     public SubmissionsSearchRequest(String query) { | ||||
|         this.addParameter("q", query); | ||||
|     } | ||||
| 
 | ||||
|     public SubmissionsSearchRequest setSyntax(QuerySyntax syntax) { | ||||
|         this.addParameter("syntax", syntax.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public SubmissionsSearchRequest setSort(SearchSort sort) { | ||||
|         this.addParameter("sort", sort.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public SubmissionsSearchRequest setTimeSpan(TimeSpan time) { | ||||
|         this.addParameter("t", time.value()); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     public SubmissionsSearchRequest setShowAll() { | ||||
|         this.addParameter("show", "all"); | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,29 @@ | ||||
| package com.github.jreddit.request.retrieval.subreddits; | ||||
| 
 | ||||
| import com.github.jreddit.request.retrieval.ListingRequest; | ||||
| import com.github.jreddit.request.retrieval.param.SubredditsView; | ||||
| 
 | ||||
| public class SubredditsOfUserRequest extends ListingRequest { | ||||
|      | ||||
|     private static final String ENDPOINT_FORMAT = "/subreddits/%s.json?%s"; // ApiEndpointUtils.SUBREDDITS_GET | ||||
|      | ||||
|     private SubredditsView view; | ||||
|      | ||||
|     /** | ||||
|      * @param view View of the subreddits | ||||
|      */ | ||||
|     public SubredditsOfUserRequest(SubredditsView view) { | ||||
|         this.view = view; | ||||
|     } | ||||
|      | ||||
|     public SubredditsOfUserRequest setShowAll() { | ||||
|         this.addParameter("show", "all"); | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, view, this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package com.github.jreddit.request.retrieval.subreddits; | ||||
| 
 | ||||
| import com.github.jreddit.request.retrieval.ListingRequest; | ||||
| 
 | ||||
| public class SubredditsSearchRequest extends ListingRequest { | ||||
|      | ||||
|     private static final String ENDPOINT_FORMAT = "/subreddits/search.json?%s"; | ||||
|      | ||||
|     /** | ||||
|      * @param query Search query (e.g. "programming") | ||||
|      */ | ||||
|     public SubredditsSearchRequest(String query) { | ||||
|         this.addParameter("q", query); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String generateRedditURI() { | ||||
|         return String.format(ENDPOINT_FORMAT, this.generateParameters()); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,86 @@ | ||||
| package com.github.jreddit.request.util; | ||||
| 
 | ||||
| import java.io.UnsupportedEncodingException; | ||||
| import java.net.URLEncoder; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| public class KeyValueFormatter { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(KeyValueFormatter.class); | ||||
|      | ||||
|     private KeyValueFormatter() { | ||||
|         // Left empty to prevent instantiation of this utility class | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Format a mapping of key-value pairs to a string, separating key from value using an | ||||
|      * equals (=) sign, and separating pairs using an ampersand (&) sign. | ||||
|      *  | ||||
|      * @param keyValueParameters Mapping of key-value pairs | ||||
|      * @param encodeUTF8 Whether or not the values should be encoded in UTF-8 | ||||
|      *  | ||||
|      * @return Formatted string of key-value pairs (e.g. "a=1&b=something") | ||||
|      */ | ||||
|     public static String format(Map<String, String> keyValueParameters, boolean encodeUTF8) { | ||||
|          | ||||
|         // Key set | ||||
|         Set<String> keys = keyValueParameters.keySet(); | ||||
|          | ||||
|         // Iterate over keys | ||||
|         String paramsString = ""; | ||||
|         boolean start = true; | ||||
|         for (String key : keys) { | ||||
|              | ||||
|             // Add separation ampersand | ||||
|             if (!start) { | ||||
|                 paramsString = paramsString.concat("&"); | ||||
|             } else { | ||||
|                 start = false; | ||||
|             } | ||||
|              | ||||
|             // Retrieve value | ||||
|             String value = keyValueParameters.get(key); | ||||
|              | ||||
|             // Encode key | ||||
|             if (encodeUTF8) { | ||||
|                 try { | ||||
|                     value = URLEncoder.encode(value, "UTF-8"); | ||||
|                 } catch (UnsupportedEncodingException e) { | ||||
|                     LOGGER.warn("Unsupported Encoding Exception thrown when encoding value", e); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             // Add key-value pair | ||||
|             paramsString = paramsString.concat(key + "=" + value); | ||||
| 
 | ||||
|         } | ||||
|          | ||||
|         // Return final parameter string | ||||
|         return paramsString; | ||||
|          | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Format a comma separated list of the given list. | ||||
|      *  | ||||
|      * @param list List of strings | ||||
|      *  | ||||
|      * @return Comma-separated list string (e.g. "a,b,c,d") | ||||
|      */ | ||||
|     public static String formatCommaSeparatedList(List<String> list) { | ||||
|         StringBuilder builder = new StringBuilder(); | ||||
|         for (int i = 0; i < list.size(); i++) { | ||||
|             if (i != 0) { | ||||
|                 builder.append(","); | ||||
|             } | ||||
|             builder.append(list.get(i)); | ||||
|         } | ||||
|         return builder.toString(); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -10,7 +10,6 @@ import java.io.OutputStream; | ||||
| import java.net.InetSocketAddress; | ||||
| 
 | ||||
| public class Main { | ||||
| 
 | ||||
|     public static void main(String[] args) throws IOException { | ||||
|         HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0); | ||||
|         server.createContext("", new ErrorHandler()); | ||||
| @ -19,7 +18,6 @@ public class Main { | ||||
|         server.setExecutor(null); | ||||
|         server.start(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| class CommunityHandler implements HttpHandler { | ||||
|     @Override | ||||
|  | ||||
| @ -1,5 +1,12 @@ | ||||
| package sh.adb.RandomRedditMemesAPI; | ||||
| 
 | ||||
| public class RedditAPI  { | ||||
| import org.json.simple.parser.ParseException; | ||||
| 
 | ||||
| import com.github.jreddit.oauth.RedditOAuthAgent; | ||||
| import com.github.jreddit.oauth.RedditToken; | ||||
| import com.github.jreddit.oauth.app.RedditApp; | ||||
| import com.github.jreddit.oauth.app.RedditInstalledApp; | ||||
| import com.github.jreddit.oauth.exception.RedditOAuthException; | ||||
| 
 | ||||
| public class RedditAPI  { | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user