193 lines
7.1 KiB
Java
193 lines
7.1 KiB
Java
package awais.instagrabber.utils;
|
|
|
|
import android.content.ContentResolver;
|
|
import android.graphics.Bitmap;
|
|
import android.net.Uri;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.util.Map;
|
|
|
|
import awais.instagrabber.models.UploadPhotoOptions;
|
|
import awais.instagrabber.models.UploadVideoOptions;
|
|
import awais.instagrabber.webservices.interceptors.AddCookiesInterceptor;
|
|
import okhttp3.Call;
|
|
import okhttp3.Headers;
|
|
import okhttp3.MediaType;
|
|
import okhttp3.OkHttpClient;
|
|
import okhttp3.Request;
|
|
import okhttp3.RequestBody;
|
|
import okhttp3.Response;
|
|
import okhttp3.ResponseBody;
|
|
import okio.BufferedSink;
|
|
import okio.Okio;
|
|
import okio.Source;
|
|
|
|
public final class MediaUploader {
|
|
private static final String TAG = MediaUploader.class.getSimpleName();
|
|
private static final String HOST = "https://i.instagram.com";
|
|
private static final AppExecutors appExecutors = AppExecutors.INSTANCE;
|
|
|
|
public static void uploadPhoto(@NonNull final Uri uri,
|
|
@NonNull final ContentResolver contentResolver,
|
|
@NonNull final OnMediaUploadCompleteListener listener) {
|
|
BitmapUtils.loadBitmap(contentResolver, uri, 1000, false, new BitmapUtils.ThumbnailLoadCallback() {
|
|
@Override
|
|
public void onLoad(@Nullable final Bitmap bitmap, final int width, final int height) {
|
|
if (bitmap == null) {
|
|
listener.onFailure(new RuntimeException("Bitmap result was null"));
|
|
return;
|
|
}
|
|
uploadPhoto(bitmap, listener);
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(@NonNull final Throwable t) {
|
|
listener.onFailure(t);
|
|
}
|
|
});
|
|
}
|
|
|
|
private static void uploadPhoto(@NonNull final Bitmap bitmap,
|
|
@NonNull final OnMediaUploadCompleteListener listener) {
|
|
appExecutors.getTasksThread().submit(() -> {
|
|
final File file;
|
|
final long byteLength;
|
|
try {
|
|
file = BitmapUtils.convertToJpegAndSaveToFile(bitmap, null);
|
|
byteLength = file.length();
|
|
} catch (Exception e) {
|
|
listener.onFailure(e);
|
|
return;
|
|
}
|
|
final UploadPhotoOptions options = MediaUploadHelper.createUploadPhotoOptions(byteLength);
|
|
final Map<String, String> headers = MediaUploadHelper.getUploadPhotoHeaders(options);
|
|
final String url = HOST + "/rupload_igphoto/" + options.getName() + "/";
|
|
appExecutors.getNetworkIO().execute(() -> {
|
|
try (FileInputStream input = new FileInputStream(file)) {
|
|
upload(input, url, headers, listener);
|
|
} catch (IOException e) {
|
|
listener.onFailure(e);
|
|
} finally {
|
|
//noinspection ResultOfMethodCallIgnored
|
|
file.delete();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
public static void uploadVideo(final Uri uri,
|
|
final ContentResolver contentResolver,
|
|
final UploadVideoOptions options,
|
|
final OnMediaUploadCompleteListener listener) {
|
|
appExecutors.getTasksThread().submit(() -> {
|
|
final Map<String, String> headers = MediaUploadHelper.getUploadVideoHeaders(options);
|
|
final String url = HOST + "/rupload_igvideo/" + options.getName() + "/";
|
|
appExecutors.getNetworkIO().execute(() -> {
|
|
try (InputStream input = contentResolver.openInputStream(uri)) {
|
|
if (input == null) {
|
|
listener.onFailure(new RuntimeException("InputStream was null"));
|
|
return;
|
|
}
|
|
upload(input, url, headers, listener);
|
|
} catch (IOException e) {
|
|
listener.onFailure(e);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
private static void upload(@NonNull final InputStream input,
|
|
@NonNull final String url,
|
|
@NonNull final Map<String, String> headers,
|
|
@NonNull final OnMediaUploadCompleteListener listener) {
|
|
try {
|
|
final OkHttpClient client = new OkHttpClient.Builder()
|
|
.addInterceptor(new AddCookiesInterceptor())
|
|
.followRedirects(false)
|
|
.followSslRedirects(false)
|
|
.build();
|
|
final Request request = new Request.Builder()
|
|
.headers(Headers.of(headers))
|
|
.url(url)
|
|
.post(create(MediaType.parse("application/octet-stream"), input))
|
|
.build();
|
|
final Call call = client.newCall(request);
|
|
final Response response = call.execute();
|
|
final ResponseBody body = response.body();
|
|
if (!response.isSuccessful()) {
|
|
listener.onFailure(new IOException("Unexpected code " + response + (body != null ? ": " + body.string() : "")));
|
|
return;
|
|
}
|
|
listener.onUploadComplete(new MediaUploadResponse(response.code(), body != null ? new JSONObject(body.string()) : null));
|
|
} catch (Exception e) {
|
|
listener.onFailure(e);
|
|
}
|
|
}
|
|
|
|
public interface OnMediaUploadCompleteListener {
|
|
void onUploadComplete(MediaUploadResponse response);
|
|
|
|
void onFailure(Throwable t);
|
|
}
|
|
|
|
private static RequestBody create(final MediaType mediaType, final InputStream inputStream) {
|
|
return new RequestBody() {
|
|
@Override
|
|
public MediaType contentType() {
|
|
return mediaType;
|
|
}
|
|
|
|
@Override
|
|
public long contentLength() {
|
|
try {
|
|
return inputStream.available();
|
|
} catch (IOException e) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void writeTo(@NonNull BufferedSink sink) throws IOException {
|
|
try (Source source = Okio.source(inputStream)) {
|
|
sink.writeAll(source);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
public static class MediaUploadResponse {
|
|
private final int responseCode;
|
|
private final JSONObject response;
|
|
|
|
public MediaUploadResponse(int responseCode, JSONObject response) {
|
|
this.responseCode = responseCode;
|
|
this.response = response;
|
|
}
|
|
|
|
public int getResponseCode() {
|
|
return responseCode;
|
|
}
|
|
|
|
public JSONObject getResponse() {
|
|
return response;
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public String toString() {
|
|
return "MediaUploadResponse{" +
|
|
"responseCode=" + responseCode +
|
|
", response=" + response +
|
|
'}';
|
|
}
|
|
}
|
|
}
|