|
12 | 12 | import com.google.gson.JsonObject; |
13 | 13 | import net.dec4234.javadestinyapi.exceptions.APIException; |
14 | 14 | import net.dec4234.javadestinyapi.material.clan.Clan; |
| 15 | +import net.dec4234.javadestinyapi.material.clan.ClanMember; |
| 16 | +import net.dec4234.javadestinyapi.material.clan.GroupType; |
15 | 17 | import net.dec4234.javadestinyapi.material.user.BungieUser; |
16 | 18 | import net.dec4234.javadestinyapi.material.user.UserCredential; |
17 | 19 | import net.dec4234.javadestinyapi.material.user.UserCredentialType; |
18 | 20 | import net.dec4234.javadestinyapi.responses.user.SanitizedUsernamesResponse; |
19 | 21 | import net.dec4234.javadestinyapi.utils.HttpUtils; |
20 | 22 | import net.dec4234.javadestinyapi.utils.StringUtils; |
| 23 | +import net.dec4234.javadestinyapi.utils.fast.Pagination; |
21 | 24 | import net.dec4234.javadestinyapi.utils.framework.OAuthManager; |
| 25 | +import org.jetbrains.annotations.NotNull; |
22 | 26 |
|
23 | 27 | import java.util.ArrayList; |
| 28 | +import java.util.Iterator; |
24 | 29 | import java.util.LinkedList; |
25 | 30 | import java.util.List; |
26 | 31 |
|
27 | 32 | /** |
28 | 33 | * This is the base class for the entire API. It MUST be initialized with an API key before <u>any part</u> |
29 | 34 | * of the API is used. |
| 35 | + * // TODO: its time to rethink this class and instancing the API |
30 | 36 | */ |
31 | 37 | public class DestinyAPI { |
32 | 38 |
|
@@ -163,8 +169,9 @@ public static SanitizedUsernamesResponse getSanitizedUsernames(String id) throws |
163 | 169 | } |
164 | 170 |
|
165 | 171 | /** |
166 | | - * Get a BungieUser from a Steam ID |
167 | | - * NOT the same IDs used by Bungie to identify individual users |
| 172 | + * Get a BungieUser from a Steam ID, which is NOT the same IDs used by Bungie to identify individual users. |
| 173 | + * @param steamID The steamID corresponding with the user you are looking for. |
| 174 | + * @return The bungie user corresponding with that steam ID |
168 | 175 | */ |
169 | 176 | public static BungieUser getMemberFromSteamID(String steamID) throws APIException { |
170 | 177 | return getMemberFromPlatformID("SteamId", steamID); |
@@ -251,44 +258,85 @@ public static BungieUser getUserWithName(String nameAndDiscrim) throws APIExcept |
251 | 258 | /** |
252 | 259 | * Search users across all platforms for anyone with that name. |
253 | 260 | * <p> |
254 | | - * Searching "dec4234" will return an array containing a single |
255 | | - * BungieUser. While searching "Gladd" or "Datto" should return many users. |
256 | | - * <p> |
257 | | - * // TODO: Issue #16 |
| 261 | + * Returns a "Pagination" object. This allows you to request the next page of guardians with that name one at a time, |
| 262 | + * rather than returning a huge array after a long time. This was proposed in issue #16. |
| 263 | + * <br> |
| 264 | + * <pre> |
| 265 | + * {@code |
| 266 | + * Pagination<List<BungieUser>> pagination = DestinyAPI.searchUsers("Etho"); |
| 267 | + * for(List<BungieUser> bungieUsers : pagination) { // iterate through all pages one by one |
| 268 | + * bungieUsers.forEach(bungieUser -> { // Print details for users on the current page |
| 269 | + * System.out.println(bungieUser); |
| 270 | + * }); |
| 271 | + * } |
| 272 | + * } |
| 273 | + * </pre> |
| 274 | + * @param name The name of the user you want to search for |
| 275 | + * @return A Pagination object that returns a List of matching bungie users per page. |
258 | 276 | */ |
259 | | - public static List<BungieUser> searchUsers(String name) throws APIException { |
260 | | - List<BungieUser> users = new ArrayList<>(); |
261 | | - |
| 277 | + public static Pagination<List<BungieUser>> searchUsers(String name) throws APIException { |
262 | 278 | JsonObject body = new JsonObject(); |
263 | 279 | body.addProperty("displayNamePrefix", name); |
264 | 280 |
|
265 | | - List<JsonObject> jsonObjects = new ArrayList<>(); |
| 281 | + return new Pagination<>() { |
| 282 | + private int i = 0; |
| 283 | + private boolean isDone = false; |
| 284 | + |
| 285 | + @Override |
| 286 | + public boolean hasNext() throws APIException { |
| 287 | + if(isDone) { |
| 288 | + return false; |
| 289 | + } |
266 | 290 |
|
267 | | - for (int i = 0; i < 100; i++) { // Start at page 0 and increment each time until there are no more valid pages |
268 | | - JsonObject jsonObject = httpUtils.urlRequestPOST(HttpUtils.URL_BASE + "/User/Search/GlobalName/" + i + "/", body); |
| 291 | + JsonObject response = httpUtils.urlRequestPOST(HttpUtils.URL_BASE + "/User/Search/GlobalName/" + i + "/", body); |
| 292 | + i++; |
269 | 293 |
|
270 | | - // Only continue looping if the result has a list of search results |
271 | | - if (jsonObject.has("Response") && jsonObject.getAsJsonObject("Response").getAsJsonArray("searchResults").size() != 0) { |
272 | | - JsonArray jsonArray = jsonObject.getAsJsonObject("Response").getAsJsonArray("searchResults"); |
| 294 | + List<JsonObject> jsonObjects = new ArrayList<>(); |
| 295 | + List<BungieUser> users = new ArrayList<>(); |
273 | 296 |
|
274 | | - for (JsonElement jsonElement : jsonArray) { // Add all user info objects into one list |
275 | | - jsonObjects.add(jsonElement.getAsJsonObject()); |
| 297 | + // Only continue looping if the result has a list of search results |
| 298 | + if (response.has("Response") && !response.getAsJsonObject("Response").getAsJsonArray("searchResults").isEmpty()) { |
| 299 | + JsonArray jsonArray = response.getAsJsonObject("Response").getAsJsonArray("searchResults"); |
| 300 | + |
| 301 | + for (JsonElement jsonElement : jsonArray) { // Add all user info objects into one list |
| 302 | + jsonObjects.add(jsonElement.getAsJsonObject()); |
| 303 | + } |
| 304 | + } else { |
| 305 | + currentResponse = null; |
| 306 | + this.hasGrabbed = false; |
| 307 | + this.isDone = true; |
| 308 | + return false; |
276 | 309 | } |
277 | | - } else { |
278 | | - break; |
279 | | - } |
280 | | - } |
281 | 310 |
|
282 | | - // Process the one big list to convert bungie.net profile info into destiny profile info |
283 | | - for (JsonObject jsonObject : jsonObjects) { |
284 | | - BungieUser bungieUser = processListOfProfiles(jsonObject.getAsJsonArray("destinyMemberships")); |
| 311 | + // Process the one big list to convert bungie.net profile info into destiny profile info |
| 312 | + for (JsonObject jsonObject : jsonObjects) { |
| 313 | + BungieUser bungieUser = processListOfProfiles(jsonObject.getAsJsonArray("destinyMemberships")); |
285 | 314 |
|
286 | | - if (bungieUser != null) { |
287 | | - users.add(bungieUser); |
288 | | - } |
289 | | - } |
| 315 | + if (bungieUser != null) { |
| 316 | + users.add(bungieUser); |
| 317 | + } |
| 318 | + } |
| 319 | + |
| 320 | + this.currentResponse = users; |
| 321 | + this.hasGrabbed = false; |
| 322 | + return true; |
| 323 | + } |
290 | 324 |
|
291 | | - return users; |
| 325 | + @Override |
| 326 | + public List<BungieUser> next() throws APIException { |
| 327 | + if(isDone) { |
| 328 | + return null; |
| 329 | + } |
| 330 | + |
| 331 | + if(!hasGrabbed) { |
| 332 | + hasGrabbed = true; |
| 333 | + return this.currentResponse; |
| 334 | + } else { |
| 335 | + this.hasNext(); |
| 336 | + return this.currentResponse; |
| 337 | + } |
| 338 | + } |
| 339 | + }; |
292 | 340 | } |
293 | 341 |
|
294 | 342 | /** |
@@ -403,6 +451,33 @@ public static List<BungieUser> searchGlobalDisplayNames(String prefix) throws AP |
403 | 451 | return bungieUsers; |
404 | 452 | } |
405 | 453 |
|
| 454 | + /** |
| 455 | + * Search for the clan with the given name. This is given as the preferred method for searching for clans by name. |
| 456 | + * @param search The search query |
| 457 | + * @return A single clan that matches the search query, null if none are found |
| 458 | + * @throws APIException If anything goes wrong when interacting with the API |
| 459 | + */ |
| 460 | + public static Clan searchClan(String search) throws APIException { |
| 461 | + JsonObject body = new JsonObject(); |
| 462 | + body.addProperty("groupName", search); |
| 463 | + body.addProperty("groupType", GroupType.CLAN.getType()); |
| 464 | + |
| 465 | + JsonObject jsonObject = httpUtils.urlRequestPOST(HttpUtils.URL_BASE + "/GroupV2/NameV2/", body); |
| 466 | + |
| 467 | + if(!jsonObject.has("Response")) { |
| 468 | + return null; // no clan found -- error 686 |
| 469 | + } |
| 470 | + |
| 471 | + jsonObject = jsonObject.getAsJsonObject("Response"); |
| 472 | + |
| 473 | + if(jsonObject.has("founder") && jsonObject.has("detail")) { |
| 474 | + long id = jsonObject.getAsJsonObject("detail").get("groupId").getAsLong(); |
| 475 | + return new Clan(id, jsonObject.getAsJsonObject("detail"), jsonObject.getAsJsonObject("founder")); |
| 476 | + } else { |
| 477 | + return null; |
| 478 | + } |
| 479 | + } |
| 480 | + |
406 | 481 | public static String getApiKey() { |
407 | 482 | return apiKey; |
408 | 483 | } |
|
0 commit comments