package com.thebluealliance.androidclient.imgur; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import com.appspot.tbatv_prod_hrd.TeamMedia; import com.appspot.tbatv_prod_hrd.model.ModelsMobileApiMessagesBaseResponse; import com.appspot.tbatv_prod_hrd.model.ModelsMobileApiMessagesMediaSuggestionMessage; import com.thebluealliance.androidclient.TBAAndroid; import com.thebluealliance.androidclient.TbaLogger; import com.thebluealliance.androidclient.config.AppConfig; import com.thebluealliance.androidclient.datafeed.gce.GceAuthController; import com.thebluealliance.androidclient.di.components.DaggerSuggestionComponent; import com.thebluealliance.androidclient.di.components.SuggestionComponent; import com.thebluealliance.androidclient.helpers.TeamHelper; import com.thebluealliance.imgur.ImgurApi; import com.thebluealliance.imgur.responses.UploadResponse; import android.app.IntentService; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import java.io.File; import javax.inject.Inject; import okhttp3.MediaType; import okhttp3.RequestBody; import retrofit2.Response; /** * An {@link IntentService} that takes details about an image stored locally, uploads it to imgur, * and then posts it as a suggestion to TBA */ public class ImgurSuggestionService extends IntentService { public static final String EXTRA_FILEPATH = "filepath"; public static final String EXTRA_TITLE = "title"; public static final String EXTRA_DESCRIPTION = "description"; public static final String EXTRA_TEAMKEY = "teamKey"; public static final String EXTRA_YEAR = "year"; private static final String TEAM_LINK = "team"; private static final String DELETEHASH_KEY = "deletehash"; @Inject ImgurApi mImgurApi; @Inject TeamMedia mTeamMediaApi; @Inject GceAuthController mGceAuthController; @Inject AppConfig mAppConfig; /** * Create a new Intent pass to {@link Context#startService(Intent)} that uploads the given image * file to imgur and suggests it to The Blue Alliance. * * @param context Context to create the intent with * @param filepath Local filepath of the image file to suggest * @param title Title for the image on imgur * @param description Description for the image on imgur * @param teamKey Team to suggest the image with * @param year Year to suggest the image for, along with teamKey * @return An Intent to pass to {@link Context#startService(Intent)} */ public static Intent newIntent(Context context, String filepath, String title, String description, String teamKey, int year) { Intent intent = new Intent(context, ImgurSuggestionService.class); intent.putExtra(EXTRA_FILEPATH, filepath); intent.putExtra(EXTRA_TITLE, title); intent.putExtra(EXTRA_DESCRIPTION, description); intent.putExtra(EXTRA_TEAMKEY, teamKey); intent.putExtra(EXTRA_YEAR, year); return intent; } /** * Create a new Intent pass to {@link Context#startService(Intent)} that uploads the given image * file to imgur and suggests it to The Blue Alliance. This method will automatically generate * a title and description for the image; useful if the user didn't specify any. * * @param context Context to create the intent with * @param filepath Local filepath of the image file to suggest * @param teamKey Team to suggest the image with * @param year Year to suggest the image for, along with teamKey * @return An Intent to pass to {@link Context#startService(Intent)} */ public static Intent newIntent(Context context, String filepath, String teamKey, int year) { Intent intent = new Intent(context, ImgurSuggestionService.class); intent.putExtra(EXTRA_FILEPATH, filepath); intent.putExtra(EXTRA_TITLE, "Team " + TeamHelper.getTeamNumber(teamKey) + " (" + year + ")"); intent.putExtra(EXTRA_DESCRIPTION, "Uploaded from The Blue Alliance Android app"); intent.putExtra(EXTRA_TEAMKEY, teamKey); intent.putExtra(EXTRA_YEAR, year); return intent; } /** * Creates an ImgurSuggestionService */ public ImgurSuggestionService() { super("imgurSuggestion"); } @Override public void onCreate() { super.onCreate(); getComponent().inject(this); } @Override protected void onHandleIntent(Intent intent) { TbaLogger.d("IMGUR SERVICE START"); String filepath = intent.getStringExtra(EXTRA_FILEPATH); String title = intent.getStringExtra(EXTRA_TITLE); String description = intent.getStringExtra(EXTRA_DESCRIPTION); String teamKey = intent.getStringExtra(EXTRA_TEAMKEY); int year = intent.getIntExtra(EXTRA_YEAR, 0); ImgurUploadNotification notification = new ImgurUploadNotification(getApplicationContext()); notification.onUploadStarting(); boolean successful = true; // Get a wake lock so any long uploads will not be interrupted PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName()); wakeLock.acquire(); // Catch-all error handling for now // TODO should we catch each exception individually and handle them better (e.g. retyr?) try { String authToken = getAuthHeader(); File file = new File(filepath); RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file); RequestBody titlePart = RequestBody.create(MediaType.parse("text/plain"), title); RequestBody descPart = RequestBody.create(MediaType.parse("text/plain"), description); Response<UploadResponse> response = mImgurApi.uploadImage(authToken, titlePart, descPart, body).execute(); if (response != null && response.isSuccessful()) { UploadResponse uploadResponse = response.body(); TbaLogger.d("Uploaded imgur image: " + uploadResponse.data.link); String link = uploadResponse.data.link; String deletehash = uploadResponse.data.deletehash; TbaLogger.d("Imgur link: " + link); // Do suggestion String authHeader = mGceAuthController.getAuthHeader(); ModelsMobileApiMessagesMediaSuggestionMessage message = buildSuggestionMessage( teamKey, year, link, deletehash); Response<ModelsMobileApiMessagesBaseResponse> suggestionResponse = mTeamMediaApi.suggestion(authHeader, message).execute(); if (suggestionResponse != null && suggestionResponse.isSuccessful()) { // Yay, everything worked! } else { // Crap // TODO handle this successful = false; } } else { TbaLogger.e("Error uploading imgur image\n" + response.code() + " " + response.message()); successful = false; } } catch (Exception e) { // Something broke successful = false; e.printStackTrace(); } finally { if (successful) { notification.onUploadSuccess(); } else { notification.onUploadFailure(); } // Delete the temp cached image new File(filepath).delete(); wakeLock.release(); } } private SuggestionComponent getComponent() { TBAAndroid application = (TBAAndroid) getApplication(); return DaggerSuggestionComponent.builder() .applicationComponent(application.getComponent()) .gceModule(application.getGceModule()) .httpModule(application.getHttpModule()) .imgurModule(application.getImgurModule()) .tBAAndroidModule(application.getModule()) .build(); } private String getAuthHeader() { String clientId = mAppConfig.getString("imgur_clientId"); return String.format("Client-ID %1$s", clientId); } private static ModelsMobileApiMessagesMediaSuggestionMessage buildSuggestionMessage( String teamKey, int year, String imgurLink, String deleteHash) { ModelsMobileApiMessagesMediaSuggestionMessage message = new ModelsMobileApiMessagesMediaSuggestionMessage(); message.media_url = imgurLink; message.reference_key = teamKey; message.year = year; message.reference_type = TEAM_LINK; message.details_json = getDetailsJson(deleteHash); return message; } private static String getDetailsJson(String deletehash) { JsonObject json = new JsonObject(); json.add(DELETEHASH_KEY, new JsonPrimitive(deletehash)); return json.toString(); } }