Skip to content

Commit

Permalink
re-written
Browse files Browse the repository at this point in the history
  • Loading branch information
ErrorxCode authored Jan 24, 2022
1 parent 21c15fe commit ae89116
Show file tree
Hide file tree
Showing 8 changed files with 806 additions and 328 deletions.
6 changes: 2 additions & 4 deletions EasyInsta/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ android {
defaultConfig {
minSdkVersion 24
targetSdkVersion 30
versionCode 2
versionName "2.0"
versionCode 25
versionName "2.5"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}

buildTypes {
Expand Down
936 changes: 632 additions & 304 deletions EasyInsta/src/main/java/com/xcoder/easyinsta/Instagram.java

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion EasyInsta/src/main/java/com/xcoder/easyinsta/Task.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.xcoder.easyinsta;

import org.jetbrains.annotations.NotNull;

public final class Task<T> {
protected T value;
protected Throwable exception;

protected Task(Exception e) {
public Task(Exception e) {
exception = e;
}

Expand All @@ -28,6 +30,7 @@ public void addOnCompleteListener(OnCompletionListener<T> callback) {
callback.onComplete(this);
}

@NotNull
public T getValue() {
return value;
}
Expand Down
138 changes: 119 additions & 19 deletions EasyInsta/src/main/java/com/xcoder/easyinsta/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,58 @@

import com.github.instagram4j.instagram4j.IGClient;
import com.github.instagram4j.instagram4j.actions.users.UserAction;
import com.github.instagram4j.instagram4j.models.direct.IGThread;
import com.github.instagram4j.instagram4j.models.direct.item.ThreadItem;
import com.github.instagram4j.instagram4j.models.direct.item.ThreadTextItem;
import com.github.instagram4j.instagram4j.models.media.timeline.TimelineMedia;
import com.github.instagram4j.instagram4j.models.user.Profile;
import com.github.instagram4j.instagram4j.models.user.User;
import com.github.instagram4j.instagram4j.requests.IGRequest;
import com.github.instagram4j.instagram4j.requests.direct.DirectInboxRequest;
import com.github.instagram4j.instagram4j.requests.direct.DirectThreadsRequest;
import com.github.instagram4j.instagram4j.requests.feed.FeedTimelineRequest;
import com.github.instagram4j.instagram4j.requests.friendships.FriendshipsActionRequest;
import com.github.instagram4j.instagram4j.requests.media.MediaInfoRequest;
import com.github.instagram4j.instagram4j.responses.IGResponse;
import com.github.instagram4j.instagram4j.responses.feed.FeedTimelineResponse;
import com.github.instagram4j.instagram4j.responses.feed.FeedUsersResponse;
import com.xcoder.easyinsta.exceptions.InstagramException;
import com.xcoder.easyinsta.exceptions.Reasons;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

class Utils {
private static IGClient client;
private Object meta;
protected Utils(IGClient client){


protected Utils(IGClient client) {
Utils.client = client;
}

protected <T extends IGResponse> Task<String> request(IGRequest<T> request) throws CompletionException {
Task<String> task = new Task<>();
CompletableFuture<T> response = client.sendRequest(request);
response.thenAccept(new Consumer<IGResponse>() {
public <T extends IGResponse> Task<Void> request(IGRequest<T> request) throws CompletionException {
Task<Void> task = new Task<>();
client.sendRequest(request).exceptionally(new Function<Throwable, T>() {
@Override
public void accept(IGResponse igResponse) {
task.value = igResponse.getMessage();
}
}).exceptionally(new Function<Throwable, Void>() {
@Override
public Void apply(Throwable throwable) {
public T apply(Throwable throwable) {
task.exception = throwable;
return null;
}
Expand All @@ -45,25 +62,25 @@ public Void apply(Throwable throwable) {
}


protected byte[] readFile(File file) throws IOException {
byte[] readFile(File file) throws IOException {
FileInputStream in = new FileInputStream(file);
byte[] bytes = new byte[in.available()];
in.read(bytes);
return bytes;
}


protected Task<String> followAction(String username, FriendshipsActionRequest.FriendshipsAction action){
protected Task<Void> followAction(String username, FriendshipsActionRequest.FriendshipsAction action) {
try {
User user = client.actions().users().findByUsername(username).get().getUser();
return request(new FriendshipsActionRequest(user.getPk(),action));
return request(new FriendshipsActionRequest(user.getPk(), action));
} catch (ExecutionException | InterruptedException e) {
return new Task<>(e);
}
}


protected Object getProfileMetadata(CompletableFuture<UserAction> response, String what){
protected Object getProfileMetadata(CompletableFuture<UserAction> response, String what) {
try {
response.thenAccept(new Consumer<UserAction>() {
@Override
Expand All @@ -81,8 +98,9 @@ public void accept(UserAction userAction) {
case "followings":
meta = userAction.getUser().getFollowing_count();
break;
default:
case "posts":
meta = userAction.getUser().getMedia_count();
break;
}
}
}).exceptionally(new Function<Throwable, Void>() {
Expand All @@ -93,12 +111,13 @@ public Void apply(Throwable throwable) {
}
}).join();
return meta;
} catch (CompletionException e){
} catch (CompletionException e) {
return e;
}
}

protected Task<List<String>> getFeeds(CompletableFuture<UserAction> response,boolean isFollowersFeed){

protected Task<List<String>> getFeeds(CompletableFuture<UserAction> response, boolean isFollowersFeed) {
Task<List<String>> task = new Task<>();
List<String> list = new ArrayList<>();
try {
Expand All @@ -120,8 +139,89 @@ public Void apply(Throwable throwable) {
}
}).join();
return task;
} catch (CompletionException e){
} catch (CompletionException e) {
return new Task<>(e);
}
}

@NotNull
protected IGThread getThread(String username) throws ExecutionException, InterruptedException {
List<IGThread> threads = client.sendRequest(new DirectInboxRequest()).get().getInbox().getThreads();
for (IGThread thread : threads)
for (Profile user : thread.getUsers()) {
if (user.getUsername().equals(username)) {
return thread;
}
}
throw new InstagramException("There is no user with username " + username, Reasons.INVALID_USERNAME);
}


protected List<ThreadItem> getThreadItem(String username, int count, boolean onlySent, @Nullable Instagram.OnProgressListener listener) throws ExecutionException, InterruptedException {
List<ThreadItem> list = new ArrayList<>();
IGThread thread = getThread(username);
String cursor = thread.getOldest_cursor();
list.add(thread.getItems().get(0));
if (count > 20) {
int loop = (count/20) + (count%20 == 0 ? 0 : 1);
for (int i = 0; i < loop; i++){
thread = client.sendRequest(new DirectThreadsRequest(thread.getThread_id(), cursor)).get().getThread();
list.addAll(thread.getItems());
cursor = thread.getOldest_cursor();
if (listener != null)
listener.onProgress((i + 1)*100/loop);
if (cursor == null)
break;
}
} else if (count == 0) {
while (cursor != null) {
thread = client.sendRequest(new DirectThreadsRequest(thread.getThread_id(), cursor)).get().getThread();
list.addAll(thread.getItems());
cursor = thread.getOldest_cursor();
}
} else {
while (list.size() < count) {
thread = client.sendRequest(new DirectThreadsRequest(thread.getThread_id(), cursor)).get().getThread();
list.addAll(thread.getItems());
cursor = thread.getOldest_cursor();
if (cursor == null)
break;
}
}
list.removeIf(threadItem -> onlySent && !isMessageSent(threadItem));
return list.stream().limit(count == 0 ? list.size() : count).collect(Collectors.toList());
}


protected List<ThreadItem> getThreadItem(String username, String from, int frequency, boolean onlySent, @Nullable Instagram.OnProgressListener listener) throws IllegalArgumentException, ExecutionException, InterruptedException {
List<ThreadItem> items = getThreadItem(username, 0, onlySent,listener);
List<String> messages = items
.stream()
.map(threadItem -> threadItem instanceof ThreadTextItem ? ((ThreadTextItem) threadItem).getText() : null)
.filter(Objects::nonNull)
.collect(Collectors.toList());


if (frequency == 0){
frequency = Collections.frequency(messages,from);
} else if (frequency < 0)
throw new IllegalArgumentException("Frequency can't be negative");

List<ThreadItem> threadItems = new ArrayList<>();
for (ThreadItem item : items) {
threadItems.add(item);
if (item instanceof ThreadTextItem && ((ThreadTextItem) item).getText().equals(from)){
if (frequency == 1)
return threadItems;
else
frequency--;
}
}
throw new IllegalArgumentException("There is no such message '" + from + "' in the chat");
}


protected boolean isMessageSent(ThreadItem item) {
return client.getSelfProfile().getPk() == item.getUser_id();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.xcoder.easyinsta.exceptions;

public class IGLoginException extends Exception {
private final Reasons reason;

public IGLoginException(String message, Reasons reason) {
super(message);
this.reason = reason;
}

public Reasons getReason() {
return reason;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.xcoder.easyinsta.exceptions;

public class InstagramException extends RuntimeException {
private final Reasons reason;

public InstagramException(String message, Reasons reason) {
super(message);
this.reason = reason;
}

public Reasons getReason() {
return reason;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.xcoder.easyinsta.exceptions;

public enum Reasons {
REQUIRE_2_FACTOR_AUTHENTICATION,
LOGIN_ERROR_UNKNOWN,
BIO_LENGTH_EXCEEDED,
UNSUPPORTED_FILE_FORMAT,
INVALID_CREDENTIALS,
CHALLENGE_REQUIRED,
CACHING_ERROR,
PROXY_ERROR,
NO_SUCH_ADMIN,
INVALID_USERNAME,
LOGIN_TOO_FREQUENTLY,
API_RESPONSE_ERROR,
NO_SUCH_MESSAGE

}
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ buildscript {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.android.tools.build:gradle:4.2.2'
classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:0.14.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
Expand Down

0 comments on commit ae89116

Please sign in to comment.