Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ Force stop Instagram and **clear its cache** to apply the changes properly.
- [BrianML](https://github.com/brianml31)
- [silvzr](https://github.com/silvzr)
- [oct888](https://github.com/oct888)
- [HalfManBear](https://github.com/halfmanbear)

## πŸ™Œ Special Thanks
- [xHookman](https://github.com/xHookman)
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId "ps.reso.instaeclipse"
minSdkVersion 28
targetSdk 34
versionCode 9
versionName '0.4.2'
versionCode 10
versionName '0.4.3'

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
12 changes: 8 additions & 4 deletions app/src/main/java/ps/reso/instaeclipse/Xposed/Module.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,14 @@ protected void afterHookedMethod(MethodHookParam param) {
}

try {
FollowerIndicator followerIndicator = new FollowerIndicator(); // Follower Indicator
String bridge = followerIndicator.findFollowerStatusMethod(Module.dexKitBridge);
if (FeatureFlags.showFollowerToast) {
followerIndicator.checkFollow(hostClassLoader, bridge);
FollowerIndicator followerIndicator = new FollowerIndicator();
FollowerIndicator.FollowMethodResult result =
followerIndicator.findFollowerStatusMethod(Module.dexKitBridge);

if (result != null && FeatureFlags.showFollowerToast) {
followerIndicator.checkFollow(hostClassLoader, result.methodName, result.userClassName);
} else {
XposedBridge.log("(InstaEclipse | FollowerToast): ❌ Method not found");
}
} catch (Throwable ignored) {
XposedBridge.log("(InstaEclipse | FollowerToast): ❌ Failed to hook");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ private void setupContributorsAndSpecialThanks(View rootView) {
new Contributor("ReSo7200", "https://github.com/ReSo7200", "https://linkedin.com/in/abdalhaleem-altamimi", null),
new Contributor("frknkrc44", "https://github.com/frknkrc44", null, null),
new Contributor("BrianML", "https://github.com/brianml31", null, "https://t.me/instamoon_channel"),
new Contributor("silvzr", "https://github.com/silvzr", null, null)
new Contributor("silvzr", "https://github.com/silvzr", null, null),
new Contributor("oct", "https://github.com/oct888", null, null),
new Contributor("HalfManBear", "https://github.com/halfmanbear", null, null)
);

List<Contributor> specialThanks = Arrays.asList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
return;
}
String x = clipData.getItemAt(0).getText().toString();
if (x.contains("https://www.instagram.com/") && x.contains("?igsh=")) { // Global
param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?igsh=.*", ""));
if (x.contains("https://www.instagram.com/") && (x.contains("igsh=") || (x.contains("ig_rid=")))) { // Global
param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?.*", ""));
} else if (x.contains("https://www.instagram.com/") && x.contains("?utm_source=")) { // Stories
param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?utm_source=.*", ""));
}
else if (x.contains("https://www.instagram.com/") && x.contains("?story_media_id=")){ // Highlights
param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?story_media_id=.*", ""));
}
// Saved-by rule: match saved-by or saved_by anywhere in query
else if (x.contains("https://www.instagram.com/") &&
x.matches("(?i).*saved[-_]by.*")) {
param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?.*", ""));
}
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ps.reso.instaeclipse.mods.devops.config;

import static ps.reso.instaeclipse.utils.feature.FeatureFlags.isImportingConfig;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
Expand All @@ -21,57 +23,60 @@ public class ConfigManager {

// Import meta config from clipboard
public static void importConfigFromClipboard(Context context) {
android.app.ProgressDialog progress = new android.app.ProgressDialog(context);
progress.setMessage("Importing config...");
progress.setCancelable(false);
progress.show();

new Thread(() -> {
try {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
if (clipboard == null || !clipboard.hasPrimaryClip()) {
return;
}

ClipData clipData = clipboard.getPrimaryClip();
if (clipData == null || clipData.getItemCount() == 0) {
return;
}

CharSequence clipText = clipData.getItemAt(0).getText();
if (clipText == null || clipText.length() == 0) {
return;
}

String json = clipText.toString().trim();
if (!json.startsWith("{") || !json.endsWith("}")) {
return;
}

File dest = new File(context.getFilesDir(), "mobileconfig/mc_overrides.json");
if (!Objects.requireNonNull(dest.getParentFile()).exists()) {
dest.getParentFile().mkdirs();
}

try (FileOutputStream fos = new FileOutputStream(dest, false)) {
fos.write(json.getBytes(StandardCharsets.UTF_8));
fos.flush();
if (isImportingConfig) {
android.app.ProgressDialog progress = new android.app.ProgressDialog(context);
progress.setMessage("Importing config...");
progress.setCancelable(false);
progress.show();

new Thread(() -> {
try {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
if (clipboard == null || !clipboard.hasPrimaryClip()) {
return;
}

ClipData clipData = clipboard.getPrimaryClip();
if (clipData == null || clipData.getItemCount() == 0) {
return;
}

CharSequence clipText = clipData.getItemAt(0).getText();
if (clipText == null || clipText.length() == 0) {
return;
}

String json = clipText.toString().trim();
if (!json.startsWith("{") || !json.endsWith("}")) {
return;
}

File dest = new File(context.getFilesDir(), "mobileconfig/mc_overrides.json");
if (!Objects.requireNonNull(dest.getParentFile()).exists()) {
dest.getParentFile().mkdirs();
}

try (FileOutputStream fos = new FileOutputStream(dest, false)) {
fos.write(json.getBytes(StandardCharsets.UTF_8));
fos.flush();
}

new Handler(Looper.getMainLooper()).post(() -> {
progress.dismiss();
Toast.makeText(context, "βœ… Imported into mc_overrides.json", Toast.LENGTH_LONG).show();
XposedBridge.log("InstaEclipse | βœ… JSON imported from clipboard into mc_overrides.json");
});

} catch (Exception e) {
XposedBridge.log("InstaEclipse | ❌ Clipboard import failed: " + e.getMessage());
new Handler(Looper.getMainLooper()).post(() -> {
progress.dismiss();
Toast.makeText(context, "❌ Failed to import config", Toast.LENGTH_LONG).show();
});
}
}).start();
}

new Handler(Looper.getMainLooper()).post(() -> {
progress.dismiss();
Toast.makeText(context, "βœ… Imported into mc_overrides.json", Toast.LENGTH_LONG).show();
XposedBridge.log("InstaEclipse | βœ… JSON imported from clipboard into mc_overrides.json");
});

} catch (Exception e) {
XposedBridge.log("InstaEclipse | ❌ Clipboard import failed: " + e.getMessage());
new Handler(Looper.getMainLooper()).post(() -> {
progress.dismiss();
Toast.makeText(context, "❌ Failed to import config", Toast.LENGTH_LONG).show();
});
}
}).start();
}

// Export meta config to Device
Expand Down
46 changes: 25 additions & 21 deletions app/src/main/java/ps/reso/instaeclipse/mods/ghost/ViewOnce.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,36 +51,40 @@ public void handleViewOnceBlock(DexKitBridge bridge) {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
if (!FeatureFlags.isGhostViewOnce) {
// If Ghost View Once is disabled, allow normal execution
return; // Feature disabled β†’ skip
}

Object rw = param.args[2]; // Third argument (visual item object)
if (rw == null) {
return;
}

Object rw = param.args[2]; // Third argument (likely visual item object)

if (rw != null) {
Method[] allMethods = rw.getClass().getDeclaredMethods();

for (Method m : allMethods) {
if (m.getParameterTypes().length == 0 &&
m.getReturnType() == String.class) {
try {
m.setAccessible(true);
String value = (String) m.invoke(rw);

if (value != null && value.contains("send_visual_item_seen_marker")) {
// If it matches visual seen marker, block it
param.setResult(null);
return;
}
} catch (Throwable ignored) {
// Ignore reflection exceptions
}
for (Method m : rw.getClass().getDeclaredMethods()) {
// Only check methods with no params returning String
if (m.getParameterTypes().length != 0 || m.getReturnType() != String.class) {
continue;
}

try {
m.setAccessible(true);
String value = (String) m.invoke(rw);
if (value == null) {
continue;
}

if (value.contains("visual_item_seen") ||
value.contains("send_visual_item_seen_marker")) {
// XposedBridge.log("Blocked ViewOnce send: " + value);
param.setResult(null); // Block this call
}
} catch (Throwable ignored) {
// Ignore reflection errors
}
}
}
});


XposedBridge.log("(InstaEclipse | ViewOnce): βœ… Hooked (dynamic check): " +
method.getClassName() + "." + method.getName());
FeatureStatusTracker.setHooked("GhostViewOnce");
Expand Down
Loading