Skip to content

Instantly share code, notes, and snippets.

@davidsth
Last active June 6, 2017 22:22
Show Gist options
  • Save davidsth/84793f44ba6852e34e9a0a3076aa9707 to your computer and use it in GitHub Desktop.
Save davidsth/84793f44ba6852e34e9a0a3076aa9707 to your computer and use it in GitHub Desktop.
from optparse import OptionParser
import ctypes
from ctypes import wintypes
import time
user32 = ctypes.WinDLL('user32', use_last_error=True)
INPUT_MOUSE = 0
INPUT_KEYBOARD = 1
INPUT_HARDWARE = 2
KEYEVENTF_EXTENDEDKEY = 0x0001
KEYEVENTF_KEYUP = 0x0002
KEYEVENTF_UNICODE = 0x0004
KEYEVENTF_SCANCODE = 0x0008
MAPVK_VK_TO_VSC = 0
# msdn.microsoft.com/en-us/library/dd375731
VK_TAB = 0x09
VK_MENU = 0x12
VK_UP = 0x26
VK_CONTROL = 0x11
VK_A = 0x41
VK_Q = 0x51
VK_DELETE = 0x2E
VK_RETURN = 0x0D
# C struct definitions
wintypes.ULONG_PTR = wintypes.WPARAM
class MOUSEINPUT(ctypes.Structure):
_fields_ = (("dx", wintypes.LONG),
("dy", wintypes.LONG),
("mouseData", wintypes.DWORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", wintypes.ULONG_PTR))
class KEYBDINPUT(ctypes.Structure):
_fields_ = (("wVk", wintypes.WORD),
("wScan", wintypes.WORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", wintypes.ULONG_PTR))
def __init__(self, *args, **kwds):
super(KEYBDINPUT, self).__init__(*args, **kwds)
# some programs use the scan code even if KEYEVENTF_SCANCODE
# isn't set in dwFflags, so attempt to map the correct code.
if not self.dwFlags & KEYEVENTF_UNICODE:
self.wScan = user32.MapVirtualKeyExW(self.wVk,
MAPVK_VK_TO_VSC, 0)
class HARDWAREINPUT(ctypes.Structure):
_fields_ = (("uMsg", wintypes.DWORD),
("wParamL", wintypes.WORD),
("wParamH", wintypes.WORD))
class INPUT(ctypes.Structure):
class _INPUT(ctypes.Union):
_fields_ = (("ki", KEYBDINPUT),
("mi", MOUSEINPUT),
("hi", HARDWAREINPUT))
_anonymous_ = ("_input",)
_fields_ = (("type", wintypes.DWORD),
("_input", _INPUT))
LPINPUT = ctypes.POINTER(INPUT)
def _check_count(result, func, args):
if result == 0:
raise ctypes.WinError(ctypes.get_last_error())
return args
user32.SendInput.errcheck = _check_count
user32.SendInput.argtypes = (wintypes.UINT, # nInputs
LPINPUT, # pInputs
ctypes.c_int) # cbSize
# Functions
def PressKey(hexKeyCode):
x = INPUT(type=INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=hexKeyCode))
user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
def ReleaseKey(hexKeyCode):
x = INPUT(type=INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=hexKeyCode,
dwFlags=KEYEVENTF_KEYUP))
user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
def main():
parser = OptionParser()
parser.add_option("-r", "--repeat", dest="repeat",
help="number of messages to remove. If not provided it will run once and stop")
(options, args) = parser.parse_args()
if not options.repeat:
parser.error('number of message to delete not specified\n\tex: cleanup_dms --repeat 10')
repeat = options.repeat
if (options.repeat):
repeat = int(options.repeat)
else:
repeat = 1
print("Please have your discord tab open for the dm you would like to delete.\n")
for i in range(10, 0, -1):
print("Starting up in %d seconds:", i)
time.sleep(1)
for i in range(repeat):
PressKey(VK_UP) # Alt
ReleaseKey(VK_UP)
PressKey(VK_CONTROL)
PressKey(VK_A)
ReleaseKey(VK_A)
time.sleep(0.5)
ReleaseKey(VK_CONTROL)
time.sleep(0.5)
PressKey(VK_DELETE)
ReleaseKey(VK_DELETE)
PressKey(VK_RETURN)
ReleaseKey(VK_RETURN)
time.sleep(1)
PressKey(VK_RETURN)
ReleaseKey(VK_RETURN)
time.sleep(1)
if __name__=="__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment