droefs / HLISA

A reimplementation of the Selenium API, emulating human interactions
https://pypi.org/project/HLISA/
GNU General Public License v3.0
73 stars 8 forks source link

Adding the ability to scale the typing speed when sending keys. #33

Open basvdl97 opened 1 year ago

basvdl97 commented 1 year ago

@droefs If you agree to this being useful, I was thinking to add typing_speed as an optional argument, that defaults to 1.

The typing_speed would appropriately scale the random normal distribution.

Reasons typing speed could be useful (if a site measures it):

droefs commented 1 year ago

This would definitely be useful, both for undetectability and usability as you suggest.

I would be happy to merge a pull request.

basvdl97 commented 1 year ago

I've been considering how to relocate the constants (as we talked about) along with this issue and I would like @droefs to look over this way of doing it.

The issue I have is that if I define these example constants:

'''
    HL_Selenium_Actions.addDelayAfterAction delay constants
'''
ACTION_DELAY_MEAN = 0.3
ACTION_DELAY_STD  = 0.1
ACTION_DELAY_MIN  = 0.025

And I would apply them to an existing line of code like:

self.actions.pause(std_positive(1.7, 0.7, 0.3))

It becomes rather long:

# code above ...
self.actions.pause(std_positive(
    ACTION_DELAY_MEAN , 
    ACTION_DELAY_STD, 
    ACTION_DELAY_MIN 
))
# code below ...

Functions that contain these delays will become long in not the prettiest way.

A somewhat okay solution would be to define an extra structure in the constants.py file that can be unpacked. But I found it hard to find a way to scale them, like in the case of the typing delays.

# extra structure in constants.py
ACTION_DELAY_KWARGS = {
    'mean': ACTION_DELAY_MEAN,
    'std': ACTION_DELAY_STD,
    'min': ACTION_DELAY_MIN
}

# then the pause can be done like this, but no scaling possible (I think).
self.actions.pause(std_positive(**ACTION_DELAY_KWARGS))

I thing the best solution to this is the same approach as HL_Selenium_Actions.addDelayAfterAction except just returning the delay related to the pause. My suggestion is to just like the constants are placed in a constants.py file, we place predefined delay functions in a delays.py file too. Example of delay file start:

import HLISA.constants as constants
from HLISA.utils import std_positive

'''
    HL_Selenium_Actions.addDelayAfterAction random delay picked from normal distribution for in-between
    humanlike actions.
'''
# standard
def action_delay():
    return std_positive(
        ACTION_DELAY_MEAN , 
        ACTION_DELAY_STD, 
        ACTION_DELAY_MIN 
    )

# with scaling
def other_action_delay(scaling=1.0):
    return std_positive(
        OTHER_ACTION_DELAY_MEAN*scaling , 
        OTHER_ACTION_DELAY_STD*scaling, 
        OTHER_ACTION_DELAY_MIN*scaling 
    )

With this implementation the adding of a predefined delay to the action (internal) chain would look like this:

import HLISA.delays as delays

# usage example without scaling
self.actions.pause(delays.action_delay())

# usage example with scaling
self.actions.pause(delays.other_action_delay(scaling=1.1))

To conclude, I want to know your thoughts on having to add multiple files to HLISA vs having long constants spelled out in existing function. Is adding constants.py and delays.py too much?

droefs commented 1 year ago

Thank you, this is a great contribution! It would be great to have this solution in HLISA.