feat: Random walking around in spoofed location (#805)
Co-authored-by: w451 <cheb> Co-authored-by: auth <64337177+authorisation@users.noreply.github.com>
This commit is contained in:
@@ -249,6 +249,7 @@ Thanks to everyone involved including the [third-party libraries](https://github
|
|||||||
- [TheVisual](https://github.com/TheVisual)
|
- [TheVisual](https://github.com/TheVisual)
|
||||||
- [CanerKaraca23](https://github.com/CanerKaraca23)
|
- [CanerKaraca23](https://github.com/CanerKaraca23)
|
||||||
- [bocajthomas](https://github.com/bocajthomas)
|
- [bocajthomas](https://github.com/bocajthomas)
|
||||||
|
- [w451](https://github.com/w451)
|
||||||
|
|
||||||
## Donate
|
## Donate
|
||||||
- LTC: LbBnT9GxgnFhwy891EdDKqGmpn7XtduBdE
|
- LTC: LbBnT9GxgnFhwy891EdDKqGmpn7XtduBdE
|
||||||
|
|||||||
@@ -636,6 +636,10 @@
|
|||||||
"name": "Coordinates",
|
"name": "Coordinates",
|
||||||
"description": "Set the coordinates of the spoofed location"
|
"description": "Set the coordinates of the spoofed location"
|
||||||
},
|
},
|
||||||
|
"walk_radius": {
|
||||||
|
"name": "Walk Radius",
|
||||||
|
"description": "Randomly walk around within this radius (ft)"
|
||||||
|
},
|
||||||
"always_update_location": {
|
"always_update_location": {
|
||||||
"name": "Always Update Location",
|
"name": "Always Update Location",
|
||||||
"description": "Force Snapchat to update location even if no GPS data is received"
|
"description": "Force Snapchat to update location even if no GPS data is received"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class Global : ConfigContainer() {
|
|||||||
inner class BetterLocation : ConfigContainer(hasGlobalState = true) {
|
inner class BetterLocation : ConfigContainer(hasGlobalState = true) {
|
||||||
val spoofLocation = boolean("spoof_location") { requireRestart() }
|
val spoofLocation = boolean("spoof_location") { requireRestart() }
|
||||||
val coordinates = mapCoordinates("coordinates", 0.0 to 0.0) // lat, long
|
val coordinates = mapCoordinates("coordinates", 0.0 to 0.0) // lat, long
|
||||||
|
val walkRadius = string("walk_radius") { requireRestart(); inputCheck = { it.toDoubleOrNull()?.isFinite() == true && it.toDouble() >= 0.0 } }
|
||||||
val alwaysUpdateLocation = boolean("always_update_location") { requireRestart() }
|
val alwaysUpdateLocation = boolean("always_update_location") { requireRestart() }
|
||||||
val suspendLocationUpdates = boolean("suspend_location_updates") { requireRestart() }
|
val suspendLocationUpdates = boolean("suspend_location_updates") { requireRestart() }
|
||||||
val spoofBatteryLevel = string("spoof_battery_level") { requireRestart(); inputCheck = { it.isEmpty() || it.toIntOrNull() in 0..100 } }
|
val spoofBatteryLevel = string("spoof_battery_level") { requireRestart(); inputCheck = { it.isEmpty() || it.toIntOrNull() in 0..100 } }
|
||||||
|
|||||||
@@ -11,9 +11,78 @@ import me.rhunk.snapenhance.core.features.impl.global.SuspendLocationUpdates
|
|||||||
import me.rhunk.snapenhance.core.util.hook.HookStage
|
import me.rhunk.snapenhance.core.util.hook.HookStage
|
||||||
import me.rhunk.snapenhance.core.util.hook.hook
|
import me.rhunk.snapenhance.core.util.hook.hook
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.hypot
|
||||||
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.sin
|
||||||
|
import kotlin.math.sqrt
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
|
|
||||||
class BetterLocation : Feature("Better Location", loadParams = FeatureLoadParams.INIT_SYNC) {
|
class BetterLocation : Feature("Better Location", loadParams = FeatureLoadParams.INIT_SYNC) {
|
||||||
|
//Latitude ft / deg /Longitude ft /deg = 1.26301179736
|
||||||
|
// 4ft/s * 1 degree/364000ft (latitude) * 1s/1000ms = .000000010989011 degrees/ms
|
||||||
|
val max_speed = 4.0 / 364000.0 / 1000.0
|
||||||
|
val pause_chance = .0023 // .23% chance to pause every second = after 5 minutes 50% chance of pause
|
||||||
|
val pause_duration = 60000L //ms
|
||||||
|
val pause_random = 30000L //ms
|
||||||
|
|
||||||
|
var pause_expire = 0L
|
||||||
|
var current_x = 0.0
|
||||||
|
var current_y = 0.0
|
||||||
|
var target_x = 0.0
|
||||||
|
var target_y = 0.0
|
||||||
|
var last_update_time = 0L
|
||||||
|
private fun updatePosition(){
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
|
||||||
|
if(current_x == target_x && current_y == target_y) {
|
||||||
|
val config = context.config.global.betterLocation
|
||||||
|
val walk_rad = if (config.walkRadius.get()
|
||||||
|
.toDoubleOrNull() == null
|
||||||
|
) 0.0 else (config.walkRadius.get().toDouble() / 364000.0) //Lat deg
|
||||||
|
|
||||||
|
if(last_update_time == 0L){ //Start at random position
|
||||||
|
val radius1 = sqrt(Math.random()) * walk_rad
|
||||||
|
val theta1 = Math.PI * 2.0 * Math.random()
|
||||||
|
current_x = cos(theta1) * radius1 * 1.26301179736
|
||||||
|
current_y = sin(theta1) * radius1
|
||||||
|
}
|
||||||
|
|
||||||
|
val radius2 = sqrt(Math.random()) * walk_rad
|
||||||
|
val theta2 = Math.PI * 2.0 * Math.random()
|
||||||
|
target_x = cos(theta2) * radius2 * 1.26301179736
|
||||||
|
target_y = sin(theta2) * radius2
|
||||||
|
} else if (pause_expire < now) {
|
||||||
|
val deltat = now - last_update_time
|
||||||
|
if(Math.random() > (1.0 - pause_chance).pow(deltat / 1000.0)){
|
||||||
|
pause_expire = now + pause_duration + (pause_random * Math.random()).toLong()
|
||||||
|
} else {
|
||||||
|
val max_dist = max_speed * deltat
|
||||||
|
val dist = hypot(target_x - current_x, target_y - current_y)
|
||||||
|
|
||||||
|
if (dist <= max_dist) {
|
||||||
|
current_x = target_x
|
||||||
|
current_y = target_y
|
||||||
|
} else {
|
||||||
|
val norm_x = (target_x - current_x) / dist * max_dist
|
||||||
|
val norm_y = (target_y - current_y) / dist * max_dist
|
||||||
|
current_x += norm_x
|
||||||
|
current_y += norm_y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_update_time = now
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLat() : Double {
|
||||||
|
updatePosition()
|
||||||
|
return (context.config.global.betterLocation.coordinates.get().first + current_x)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLong() : Double {
|
||||||
|
updatePosition()
|
||||||
|
return (context.config.global.betterLocation.coordinates.get().second + current_y)
|
||||||
|
}
|
||||||
private fun editClientUpdate(editor: EditorContext) {
|
private fun editClientUpdate(editor: EditorContext) {
|
||||||
val config = context.config.global.betterLocation
|
val config = context.config.global.betterLocation
|
||||||
|
|
||||||
@@ -22,11 +91,10 @@ class BetterLocation : Feature("Better Location", loadParams = FeatureLoadParams
|
|||||||
edit(1) {
|
edit(1) {
|
||||||
context.log.verbose("SCVSLocationUpdate ${this@apply}")
|
context.log.verbose("SCVSLocationUpdate ${this@apply}")
|
||||||
if (config.spoofLocation.get()) {
|
if (config.spoofLocation.get()) {
|
||||||
val coordinates by config.coordinates
|
|
||||||
remove(1)
|
remove(1)
|
||||||
remove(2)
|
remove(2)
|
||||||
addFixed32(1, coordinates.first.toFloat()) // lat
|
addFixed32(1, getLat().toFloat()) // lat
|
||||||
addFixed32(2, coordinates.second.toFloat()) // lng
|
addFixed32(2, getLong().toFloat()) // lng
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.alwaysUpdateLocation.get()) {
|
if (config.alwaysUpdateLocation.get()) {
|
||||||
@@ -79,9 +147,9 @@ class BetterLocation : Feature("Better Location", loadParams = FeatureLoadParams
|
|||||||
}
|
}
|
||||||
Location::class.java.apply {
|
Location::class.java.apply {
|
||||||
hook("getLatitude", HookStage.BEFORE) {
|
hook("getLatitude", HookStage.BEFORE) {
|
||||||
it.setResult(context.config.global.betterLocation.coordinates.get().first) }
|
it.setResult(getLat()) }
|
||||||
hook("getLongitude", HookStage.BEFORE) {
|
hook("getLongitude", HookStage.BEFORE) {
|
||||||
it.setResult(context.config.global.betterLocation.coordinates.get().second)
|
it.setResult(getLong())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,4 +172,4 @@ class ChatActionMenu : AbstractMenu() {
|
|||||||
|
|
||||||
viewGroup.addView(buttonContainer)
|
viewGroup.addView(buttonContainer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user