package com.iamthefij.otbeta.api; import android.content.Context; import android.net.http.HttpResponseCache; import android.util.Log; import com.goebl.david.Webb; import com.iamthefij.otbeta.PersistentCookieStore; import org.json.JSONArray; import org.json.JSONObject; import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookiePolicy; import java.util.ArrayList; import java.util.List; import java.util.Locale; /** * Simple client for communicating with netpulse */ public class Client { private static final String BASE_URL = "https://orangetheoryfitness.netpulse.com/np"; private static final String TAG = "OTBeta"; private final Webb webb; public Client(Context context) { webb = Webb.create(); webb.setBaseUri(BASE_URL); // Session id is stored in a cookie so this is used to persist the logged in session CookieManager cookieManager = new CookieManager(new PersistentCookieStore(context), CookiePolicy.ACCEPT_ALL); CookieHandler.setDefault(cookieManager); } /** * Returns a list of all OT locations along with Uuids * * @return List of {@link Location} instances with minimal information */ public List getLocations() { return getLocations("simple"); } /** * Returns a list of all OT locations along with Uuids and Address information * * @return List of {@link Location} with detailed address information */ public List getLocationsWithDetail() { return getLocations("detail"); } private List getLocations(String responseType) { JSONArray response = webb.get("/company/children") .param("responseType", responseType) .param("partnerAlias", "clubComq") .ensureSuccess() .asJsonArray() .getBody(); JSONObject location; List locations = new ArrayList<>(response.length()); for (int i = 0; i < response.length(); i++) { location = response.optJSONObject(i); if (location != null) { locations.add(new Location(location)); } } Log.d(TAG, String.format("getLocations: Added %d locations to list", locations.size())); return locations; } /** * Authenticates a user and returns their information * * User session is stored as a cookie * * @param username Email address of the user to authenticate * @param password Password for the authenticating user * @param homeClub {@link Location} instance of the users home club * @return {@link Exerciser} representing the authenticated user or null */ public Exerciser login(String username, String password, Location homeClub) { return login(username, password, homeClub.getUuid()); } private Exerciser login(String username, String password, String homeClubUuid) { JSONObject response = webb.post("/exerciser/login") .param("username", username) .param("password", password) .param("homeClubUuid", homeClubUuid) .ensureSuccess() .asJsonObject() .getBody(); return new Exerciser(response); } /** * Gets the full profile for a given Exerciser * * @param exerciser usr to retrieve profile for * @return ExerciserProfile instance with extended user data */ public ExerciserProfile getExerciserProfile(Exerciser exerciser) { JSONObject response = webb.get("/exerciser/" + exerciser.getUuid()) .ensureSuccess() .asJsonObject() .getBody(); return new ExerciserProfile(response); } /** * Gets a monthly summary for an exerciser for a given number of months from the current date * * @param exerciser {@link Exerciser} instance of a user to get summary for * @param months max number of months to return * @return list of {@link Interval} results containing the summaries */ public List getMonthlyWorkoutSummary(Exerciser exerciser, int months) { return getWorkouts(exerciser.getUuid(), null, null, months, "month"); } /** * Gets list of recent individual workout summaries for an exerciser from the current date * * @param exerciser {@link Exerciser} instance of a user to get summary for * @param count max number of workouts to return * @return list of {@link Interval} results containing the summaries */ public List getWorkouts(Exerciser exerciser, int count) { return getWorkouts(exerciser.getUuid(), null, null, count, "single"); } private List getWorkouts(String exerciserUuid, String filter, String endDate, Integer intervalCount, String interval) { // Set default values if (filter == null) filter = "all"; if (endDate == null) endDate = "20450101"; // Arbitrarily future date if (intervalCount == null) intervalCount = 10; // "single" "month" if (interval == null) filter = "single"; JSONObject response = webb.get("/exerciser/" + exerciserUuid + "/workouts") .param("filter", filter) .param("endDate", endDate) .param("intervalCount", intervalCount) .param("interval", interval) .ensureSuccess() .asJsonObject() .getBody(); Interval.setSpeedUnit(response.optString("speedUnit")); Interval.setDistanceUnit(response.optString("distanceUnit")) ; JSONArray intervalResponse = response.optJSONArray("intervals"); if (intervalResponse != null) { List intervals = new ArrayList<>(intervalResponse.length()); for (int i = 0; i < intervalResponse.length(); i++) { JSONObject intervalData = intervalResponse.optJSONObject(i); if (intervalData != null) { intervals.add(new Interval(intervalData)); } } Log.d(TAG, String.format("getWorkouts: Added %d intervals to list", intervals.size())); return intervals; } else { Log.i(TAG, "getWorkouts: Could not parse workout intervals"); } return null; } /** * Gets all details for a given workout * * This is where most of the interesting data is including all metrics for HR * * @param exerciser {@link Exerciser} instance of a user workout for * @param interval the {@link Interval} to retrieve details of * @return a {@link Workout} instance containing all details and metrics */ public Workout getWorkout(Exerciser exerciser, Interval interval) { return getWorkout(exerciser.getUuid(), interval.getId()); } private Workout getWorkout(String exerciserUuid, int intervalId) { JSONObject response = webb.get("/exerciser/" + exerciserUuid + "/workout/" + String.valueOf(intervalId)) .ensureSuccess() .useCaches(true) .asJsonObject() .getBody(); HttpResponseCache cache = HttpResponseCache.getInstalled(); if (cache != null) { Log.d(TAG, String.format(Locale.US, "getWorkout: Got location. Cache results: hit %d, total requests %d", cache.getHitCount(), cache.getRequestCount())); } else { Log.d(TAG, "getWorkout: Got location. No installed cache."); } return new Workout(response); } }