eljaviluki / grindrplus Goto Github PK
View Code? Open in Web Editor NEWMaking Grindr funnier than ever before!
Making Grindr funnier than ever before!
Doesn't work with lsposed for Android 13
Before knowing this mod, every time a new version of Grindr came out the app would stop working until I updated it, like a connection error, it happened to me with version 8.12 when version 8.12.1 came out, and it happened again when it came out version 8.13. when I found this mod and had to go back to version 8.11 to use it I didn't have a problem again, but now that the mod was updated to version 8.17 the same problem is happening to me, I can't use Grindr without updating to version 8.17.1 , I get a connection error. for now I went back to version 8.16 which works for me, but I would like to know if this problem occurs to someone else or is it a problem with my device.
sorry for my bad english, i only speak spanish, google translate is to blame π€£
I tried the latest release with v9.9.1 with LSPatch, but it crashes upon startup
version: v1.1 (for v8.17.1)
in the recent builds, added profile fields were re-enabled.
this triggers a nasty bug involving the BMI field when i view my own profile.
expected result: my profile says normal weight
actual result: damn thing says i'm overweight!
workaround: avoid looking at my own profile
lol im kidding :-p
...edited and closed
Currently using Latest version of LsPosed (Zygisk) with this and I'm getting errors that say to check my connection or something went wrong.
I have no VPN or Custom DNS enabled. This doesn't seem to be due to the hook but i can't find the cause of it
Extra Details:
Device: OnePlus 8 5G UW (IN2020)
Android Version: 11
ROM: OxygenOS
Magisk: Hidden
SafetyNet: Passing
Grindr Version: 8.23.0
You "unlocked" the functions, but they don't work, they are only activated for the application.
At least those that have to do with remote chats do work.
I'm sure most of you know how to get Grindr back up and running from the Pull request but I feel me and some others are sadly left behind as we honestly don't have a clue what to do. Is anyone kind enough to help out on how to get it working? I'm currently on 9.6.0
I would highly appreciate this and others too!
It's been a while since I was banned from grindr, and to this day I still do not know the reason, since they say I broke a rule, which? do not quote.
And I wanted to circumvent the ban, I tried some xposed modules to circumvent the deviceid and everything else, but to no avail.
I imagine that they use the IMEI to ban the device, then it would be good if there was a function to circumvent this through the module itself
Title says pretty much what I mean.
It is pretty hard to know who has blocked you when all we can see are profile ID numbers. I guess using the person's profile name would be better.
Forced to update to V8.17.1, I tried to modify the version in the file app\src\main\java\com\eljaviluki\grindrplus\Hooker.kt, make an .apk with android studio but it's not OK⦠I'm not a programmer so I don't know what to do....
Almost everything works as one would expect, but when clicking on a profile in the Unlimited section, it loads the very first profile in the grid instead. Everything in the xtra section will load a profile properly, after that only the very first profile loads, meaning that clicking a profile in an Unlimited section loads the very first profile of the entire grid. Watching the API, it doesn't appear there is even an attempt to fetch the profile data if you are past the xtra section and inside the unlimited area.
A bug happening on latest 8.23.0 version.
Hi guys, I wonder if you would like to join a new Discord that I would create to share our experience on the app and make this project more engaging and cooperative.
I should assign the task of moderation and maintenance of that hypothetical server to several people, since it is something that I cannot spend my time alone with, much less under personal circumstances.
I look forward to ideas on how to organize everything. Honestly, I don't have much knowledge in setting up servers on Discord today, but this could be a great opportunity for that to stop being true.
Cheers!
I noticed all other unlimited features works except for this one, for awhile now. Wondering any reason behind that?
Will the app continue to be updated or has the project been abandoned? I see that Grindr is already several versions ahead and the project has been two months without news
hi, thanks, great work!
a shitty thing about grindr is that the service tries to convey a fake sensation of unlimited guys. it does this by deleting old messages, unblocking profiles you previously blocked, and the like. a user can also block you and immediately unblock you to wipe your message history, in which the user might have acted impolitely and you might have chosen to thumb him down for it for instance.
i once hacked grindr and did several changes to lessen the impact of the "no history" features of grindr. some changes i remember:
many other changes, but those were most of the ones related to increased accountability. anyway, just food for thought.
I don't know where to ask but here. I just want to learn more about the "hidden features" that this mod enabled per the "Extra Features" on the ReadMe. I want to know what these features are, because obviously, they're hidden. I hope Javi can elaborate on this more. I love this mod to bits.
You can choose filters but they aren't working correctly. At least the online now doesn't
I'm getting errors for the added profile views, even though they are showing up and working, there are errors there in logcat. I downloaded and compiled the code and commented out that section and the errors are gone. This started happening a few versions of Grindr ago.
My concern is the errors being sent to Grindr as I had one of their employees message me in the past on XDA letting me know that an old patch that had errors for people jwas being sent to them, I think through crashlytics.
I've tested this one a couple devices, one with EdXposed and another with LSPosed, both get the errors about the params being null even though the profileID shows up and the mod works fine. EdXposed was on Android 9 but I wasn't sure if that is the issue there. Below are parts of the log copied from logcat, with date and time removed...
Thank you for the awesome mod and all the hard work you've put into it!! It's appreciated.
[date/time redacted E/LSPosed-Bridge]
java.lang.NullPointerException: param.args[0] must not be null
at com.eljaviluki.grindrplus.Hooks$addExtraProfileFields$1.afterHookedMethod(Hooks.kt:121)
at de.robv.android.xposed.XposedBridge$AdditionalHookInfo.callback(Unknown Source:147)
at LSPHooker_.h(Unknown Source:14)
at com.grindrapp.android.ui.profileV2.ProfileFieldsView$a.invokeSuspend(Unknown Source:12)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(SourceFile:4)
at kotlinx.coroutines.DispatchedTask.run(SourceFile:18)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:241)
at android.app.ActivityThread.main(ActivityThread.java:7617)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
[date/time redacted E/LSPosed-Bridge]
java.lang.NullPointerException: param.args[0] must not be null
at com.eljaviluki.grindrplus.Hooks$addExtraProfileFields$1.afterHookedMethod(Hooks.kt:121)
at de.robv.android.xposed.XposedBridge$AdditionalHookInfo.callback(Unknown Source:147)
at LSPHooker_.h(Unknown Source:14)
at com.grindrapp.android.ui.profileV2.ProfileFieldsView$a.invokeSuspend(Unknown Source:12)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(SourceFile:4)
at kotlinx.coroutines.DispatchedTask.run(SourceFile:18)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:241)
at android.app.ActivityThread.main(ActivityThread.java:7617)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Latest deploy working correctly, now it only requires monitoring.
Originally posted by @Crusnikos in Crusnikos/markasplayed#13 (comment)
Grindr is painful to be used without this app! Please help us πππ»!
I tested with a friend, once we both have the mod enabled, we were not able to see typing status or read status on messages sent between us, it works for other who don't have the mod.
Grindr Xtra and unlimited allows you to create up to 10 albums, is it possible to add this function to the mod? It would be more comfortable to send an album according to the role of the other person, so I don't show everything π€ππ
[Off-Topic comment]
Latest deploy working correctly, now it only requires monitoring.
Originally posted by @Crusnikos in Crusnikos/markasplayed#13 (comment)
Hi,
I can't root, but I'm interested in the module. Would it be possible to distribute this mod as a binary patch for a known version of Grindr (for ReVanced, for example)?
[]
The new release is still sending analytics logs to /v3/logging/mobile/logs
The api reference was updated from
const val AnalyticsRestService = "$_api.c"
to
const val AnalyticsRestService = "$_api.b"
Also the option to send videos in chat does not show up, just the live chat option. If I disable the mod or just the Session Implementation and Feature Granting and rebuild the mod then the sending videos in chat option shows up again
Hi ! It is impossible to connect to my Google account from the application with the mod (mod installed from Lspatch with Shizuku), is there a solution for this? It says that it's not possible to connect to Google because the app is currently being tested, and that you have to be a grindr developer... Thank you!
NOT TOTALLY RELATED TO THIS MODULE ,but on old phones (rooted with inbuilt lineage OS tool not Magisk ) grindr after version 8.12 added lots of code in smali (class 3) to check for root and preventing the app from working at all regardless of xposed .
so please if possible add someway to hide root with your mods otherwise grindr will never even connect to the server ,thanks
Hello,
Does Grindr have a HWID system in place?
As far as I know, usage of multiple accounts and/or sharing accounts is prohibited and can lead to permanent deactivation of all accounts, and I assume they use IDs from your Android device to assure you are respecting their accounts policy.
With that being said, I would like to know if you have information on which identifiers are used, and if it'd be possible to create a hook to disable these verifications or to spoof them.
I'd love to help creating a hook for it, but for that I would need some info on where to get information from the Grindr .apk, as I don't know much about Xposed hacking, etc.
A Discord server would be fantastic for discussing such things!
Greetings! It seems like versiΓ³n 9.9.1 is patched. Can you plz update the app so we can all enjoy this amazing module π
I get that the guy doesn't want to code anymore or whatever but i'm not paying whatever obscene amount they're charging for me to filter who I've talked to, I just want my macro to work properly so I don't message the same people 5 times a day.
Can anyone fix this thing or at least point me to another way to get something like a bypass or something?
Hi,
Relying on XPosed framework might not be the easiest way to hook / debug (although this might be my own lack of familiarity with this framework).
I've written two (very dirty) scripts to convert the hooks to a Frida JavaScript script. Ideally, relying on frida gadget this might remove as well the need for rooting.
Everything is automatically converted except for the addExtraProfileFields
hook which is having a bit too much logic for a straightforward JS generation.
Happy to take feedbacks on this, and if Frida compatibility is something useful for others, I think it should be possible to refactor the current code to ease automatic generation to both XPosed and Frida.
Here are the useful scripts. They are very dirty at the moment and only meant as a PoC.
My main script is :
# Add our mock of Constants
cat > grindrplusfrida.js <<EOF
var Constants = {
GRINDR_PKG: "com.grindrapp.android",
}
EOF
# Fetch latest Obfuscations from upstream and convert to Frida-readable script
curl "https://raw.githubusercontent.com/ElJaviLuki/GrindrPlus/master/app/src/main/java/com/eljaviluki/grindrplus/Obfuscation.kt" | sed -e "s/^package.*//" | sed -e "s/object \(.*\) {/\1: {/" | sed -e "s/const val \(.*\) =/\1:/" | sed -e "s/private//" | sed -e "s/^Constants:/var Constants =/" | sed -e "s/^Obfuscation:/var Obfuscation =/" | sed -e "s/\"$/\",/" | sed -e "s/ }/ },/" | sed -e "s/\([a-zA-Z]\)$/\1,/" >> grindrplusfrida.js
# Add our custom mocking
cat >> grindrplusfrida.js <<EOF
// Mock GApp / Hooker / Build
const GApp = Obfuscation.GApp;
const Hooker = {
pkgParam: {
classLoader: undefined,
}
};
const Build = {
VERSION: {
SDK_INT: Java.use('android.os.Build\$VERSION').SDK_INT
}
}
/**
* Handle templating in GApp variable.
*/
function applyReplacements(obj, parent) {
if (typeof obj != 'object') {
return obj.replace(
/\\\$(_[a-zA-Z]*)\./,
function replacer(match, p1) {
return parent[p1] + '.';
}
)
}
for (let key of Object.keys(obj)) {
obj[key] = applyReplacements(obj[key], Object.assign({}, parent, obj));
}
return obj;
}
// Useful return values
const RETURN_TRUE = function () { return true; }
const RETURN_FALSE = function () { return false; }
const RETURN_LONG_MAX_VALUE = function () { return Java.use('java.lang.Long').MAX_VALUE };
const RETURN_INTEGER_MAX_VALUE = function () { return Java.use('java.lang.Integer').MAX_VALUE };
/**
* Fake Duration class
*/
class Duration {
constructor(duration) {
this.duration = duration;
}
inWholeMilliseconds() {
return this.duration;
}
}
/**
* Mock listOf
*/
function listOf(...args) {
return args;
}
/**
* Frida implementation of findClass
*/
function findClass(className) {
const classLoaders = Java.enumerateClassLoadersSync();
for (const classLoader in classLoaders) {
try {
classLoaders[classLoader].findClass(className);
var classFactory = Java.ClassFactory.get(classLoaders[classLoader]);
return classFactory.use(className);
} catch (exc) {
continue;
}
}
}
/**
* Frida implementation of getStaticObjectField
*/
function getStaticObjectField(loadedClass, fieldName) {
return loadedClass[fieldName];
}
/**
* Frida implementation of setStaticLongField
*/
function setStaticLongField(loadedClass, fieldName, value) {
loadedClass[fieldName] = value;
}
/**
* Frida implementation of findAndHookMethod
*/
function findAndHookMethod(loadedClass, methodName, ...args) {
if (args.length == 1) {
// No extra arguments, last one is implementation
loadedClass[methodName].overloads[0].implementation = args[0];
} else {
// Multiple arguments, last one is implementation
const implementation = args.pop();
// Find correct overload based on types
const overloadSelectionTypes = args.map(
function (type) {
if (typeof type == 'string') {
return type;
} else {
return type.\$className;
}
});
// Rewrite implementation
if (typeof implementation == 'function') {
loadedClass[methodName].overload(...overloadSelectionTypes).implementation = implementation;
} else if (typeof implementation == 'object') {
loadedClass[methodName].overload(...overloadSelectionTypes).implementation = function (...functionArgs) {
const param = {
thisObject: this,
};
if (implementation.beforeHookedMethod) {
// TODO
}
this[methodName](...functionArgs);
if (implementation.afterHookedMethod) {
implementation.afterHookedMethod(this);
}
};
}
}
}
EOF
# Fetch latest implementations of hooks from upstream and convert to Frida-readable version
curl "https://raw.githubusercontent.com/ElJaviLuki/GrindrPlus/master/app/src/main/java/com/eljaviluki/grindrplus/Hooks.kt" | sed -e "s/^ }/ },/" | sed -e "s/^package.*//" | sed -e "s/^import .*//" | sed -e "s/fun /function /" | sed -e "s/val /var /" | sed -e "s/String::class.java/'java.lang.String'/" | sed -e "s/Boolean::class.javaPrimitiveType/'boolean'/" | sed -e "s/override fun/fun/" | sed -e "s/function afterHookedMethod/afterHookedMethod: function /" | sed -e "s/object Hooks /var Hooks = /" | sed -e "s/ function \([a-zA-Z]*\)(/\1: function \(/" | sed -e "s/function\(.*\)(\(.*\):.*)/function\1\(\2\)/" | python generate.py >> grindrplusfrida.js
# Append our custom execution code
cat >> grindrplusfrida.js <<EOF
// Reimplementation from https://www.securify.nl/blog/android-frida-hooking-disabling-flagsecure/
Hooks.allowScreenshotsHook = function() {
// https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_SECURE
var FLAG_SECURE = 0x2000;
var Window = Java.use("android.view.Window");
var setFlags = Window.setFlags; //.overload("int", "int")
setFlags.implementation = function (flags, mask) {
flags &= ~FLAG_SECURE;
setFlags.call(this, flags, mask);
// Since setFlags returns void, we don't need to return anything
};
}
Java.perform(function () {
applyReplacements(Obfuscation, {});
Hooks.allowScreenshotsHook();
Hooks.hookUserSessionImpl();
Hooks.unlimitedExpiringPhotos();
Hooks.hookFeatureGranting();
Hooks.allowSomeExperiments();
Hooks.allowVideocallsOnEmptyChats();
Hooks.allowMockProvider();
const threeMinutes = new Duration(3 * 60 * 1000);
Hooks.hookOnlineIndicatorDuration(threeMinutes);
Hooks.unlimitedTaps();
Hooks.removeExpirationOnExpiringPhotos();
});
EOF
And it requires an extra generate.py
script:
import re
import sys
def removeFunctionBlock(script, startMatch):
start = script.find(startMatch)
start_idx = start + script[start:].find('{') + 1
counter = 1
for idx, char in enumerate(script[start_idx:]):
if char == '{':
counter +=1
elif char == '}':
counter -=1
if counter == 0:
break
return (script[:start_idx] + '}' + script[start_idx + idx + 1:])
def forEachSyntax(script):
forEach_idx = [
m.start() for m in re.finditer('forEach', script)
]
for start_idx in forEach_idx:
first_brace_idx = script[start_idx:].find('{')
counter = 1
for idx, char in enumerate(script[start_idx + first_brace_idx + 1:]):
if char == '{':
counter +=1
elif char == '}':
counter -=1
if counter == 0:
break
block = list(
script[start_idx + first_brace_idx: start_idx + first_brace_idx + idx].strip()
)
block[0] = '('
block = ''.join(block)
block = block.replace('->', '=> {') + '})'
script = (
script[:start_idx + first_brace_idx]
+ block
+ script[start_idx + first_brace_idx + idx + 2:]
)
return script
def XC_MethodHook(script):
XC_idx = [
m.start() for m in re.finditer('object : XC_MethodHook\(\){', script)
]
for start_idx in XC_idx:
first_brace_idx = script[start_idx:].find('{')
counter = 1
for idx, char in enumerate(script[start_idx + first_brace_idx + 1:]):
if char == '{':
counter += 1
elif char == '}':
counter -= 1
if counter == 0:
break
block = script[start_idx : start_idx + first_brace_idx + idx]
block = block.replace('XC_MethodHook()', '{ XC_MethodHook: ')
script = (
script[:start_idx - 1]
+ '{' + block + '}}'
+ script[start_idx + first_brace_idx + idx:]
)
return script
if __name__ == '__main__':
script = sys.stdin.read()
script = removeFunctionBlock(script, 'allowScreenshotsHook: function')
script = removeFunctionBlock(script, 'addExtraProfileFields: function')
script = forEachSyntax(script)
script = XC_MethodHook(script)
print(script)
Best
hi,
expectation: message is added to save phrases
reality: command is ignored
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.