Code: Select all
#If WinActive("ahk_exe Chrome.exe") ;Find Unsubscribe Button hit it
^u::
Send ^f
Sleep 200
SendInput Unsubscribe
Sendinput {esc}
Sleep 100
SendInput ^{enter}
return
Code: Select all
#If WinActive("ahk_exe Chrome.exe") ;Find Unsubscribe Button hit it
^u::
Send ^f
Sleep 200
SendInput Unsubscribe
Sendinput {esc}
Sleep 100
SendInput ^{enter}
return
Autohotkey may not be very suitable for this job. Maybe to some extent, but very unlikely to be really productive.reverberation wrote: ↑04 May 2020, 22:43I made this script to quickly unsubscribe from junk emails within Gmail. However, there are times where the email puts the link in "CLICK HERE" instead of "Unsubscribe". How do I improve on the code to cater for BOTH situations?
Code: Select all
#If WinActive("ahk_exe Chrome.exe") ;Find Unsubscribe Button hit it ^u:: Send ^f Sleep 200 SendInput Unsubscribe Sendinput {esc} Sleep 100 SendInput ^{enter} return
Code: Select all
q::
WinGet, hwnd, ID, ahk_class Chrome_WidgetWin_1,, Skype
oAcc := Acc_Get("Object", "4.2.1.1.2", 0, "ahk_id " hwnd) ; possible path on your Chrome is different
if (oAcc.accName(0) = "No results")
MsgBox, No results
else
msgbox, % oAcc.accName(0)
return
Acc_Init()
{
Static h
If Not h
h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromEvent(ByRef _idChild_, hWnd, idObject, idChild)
{
Acc_Init()
If DllCall("oleacc\AccessibleObjectFromEvent", "Ptr", hWnd, "UInt", idObject, "UInt", idChild, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
Return ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}
Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "")
{
Acc_Init()
If DllCall("oleacc\AccessibleObjectFromPoint", "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
Return ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}
Acc_ObjectFromWindow(hWnd, idObject = -4)
{
Acc_Init()
If DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
Return ComObjEnwrap(9,pacc,1)
}
Acc_WindowFromObject(pacc)
{
If DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0
Return hWnd
}
Acc_GetRoleText(nRole)
{
nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
Return sRole
}
Acc_GetStateText(nState)
{
nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
Return sState
}
Acc_SetWinEventHook(eventMin, eventMax, pCallback)
{
Return DllCall("SetWinEventHook", "Uint", eventMin, "Uint", eventMax, "Uint", 0, "Ptr", pCallback, "Uint", 0, "Uint", 0, "Uint", 0)
}
Acc_UnhookWinEvent(hHook)
{
Return DllCall("UnhookWinEvent", "Ptr", hHook)
}
/* Win Events:
pCallback := RegisterCallback("WinEventProc")
WinEventProc(hHook, event, hWnd, idObject, idChild, eventThread, eventTime)
{
Critical
Acc := Acc_ObjectFromEvent(_idChild_, hWnd, idObject, idChild)
; Code Here:
}
*/
; Written by jethrow
Acc_Role(Acc, ChildId=0) {
try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}
Acc_State(Acc, ChildId=0) {
try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
}
Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code
try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
catch
return
Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
return {x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")}
}
Acc_Parent(Acc) {
try parent:=Acc.accParent
return parent?Acc_Query(parent):
}
Acc_Child(Acc, ChildId=0) {
try child:=Acc.accChild(ChildId)
return child?Acc_Query(child):
}
Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Error(p="") {
static setting:=0
return p=""?setting:setting:=p
}
Acc_Children(Acc) {
if ComObjType(Acc,"Name") != "IAccessible"
ErrorLevel := "Invalid IAccessible Object"
else {
Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
Loop %cChildren%
i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
return Children.MaxIndex()?Children:
} else
ErrorLevel := "AccessibleChildren DllCall Failed"
}
if Acc_Error()
throw Exception(ErrorLevel,-1)
}
Acc_ChildrenByRole(Acc, Role) {
if ComObjType(Acc,"Name")!="IAccessible"
ErrorLevel := "Invalid IAccessible Object"
else {
Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
Loop %cChildren% {
i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
if NumGet(varChildren,i-8)=9
AccChild:=Acc_Query(child), ObjRelease(child), Acc_Role(AccChild)=Role?Children.Insert(AccChild):
else
Acc_Role(Acc, child)=Role?Children.Insert(child):
}
return Children.MaxIndex()?Children:, ErrorLevel:=0
} else
ErrorLevel := "AccessibleChildren DllCall Failed"
}
if Acc_Error()
throw Exception(ErrorLevel,-1)
}
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="") {
static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
AccObj := IsObject(WinTitle)? WinTitle
: Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
if ComObjType(AccObj, "Name") != "IAccessible"
ErrorLevel := "Could not access an IAccessible Object"
else {
StringReplace, ChildPath, ChildPath, _, %A_Space%, All
AccError:=Acc_Error(), Acc_Error(true)
Loop Parse, ChildPath, ., %A_Space%
try {
if A_LoopField is digit
Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
else
RegExMatch(A_LoopField, "(\D*)(\d*)", m), Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
if Not Children.HasKey(m2)
throw
AccObj := Children[m2]
} catch {
ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
if Acc_Error()
throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
return
}
Acc_Error(AccError)
StringReplace, Cmd, Cmd, %A_Space%, , All
properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
try {
if (Cmd = "Location")
AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
, ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
else if (Cmd = "Object")
ret_val := AccObj
else if Cmd in Role,State
ret_val := Acc_%Cmd%(AccObj, ChildID+0)
else if Cmd in ChildCount,Selection,Focus
ret_val := AccObj["acc" Cmd]
else
ret_val := AccObj["acc" Cmd](ChildID+0)
} catch {
ErrorLevel := """" Cmd """ Cmd Not Implemented"
if Acc_Error()
throw Exception("Cmd Not Implemented", -1, Cmd)
return
}
return ret_val, ErrorLevel:=0
}
if Acc_Error()
throw Exception(ErrorLevel,-1)
}
GuiClose:
ExitApp
EnumProcesses()
{
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms682489(v=vs.85).aspx
local hSnapshot := 0
if ( (hSnapshot := DLLCall("Kernel32.dll\CreateToolhelp32Snapshot", "UInt", 2, "UInt", 0, "Ptr")) == -1 ) ; TH32CS_SNAPPROCESS = 2 | INVALID_HANDLE_VALUE = -1
return 0
local PROCESSENTRY32 := ""
NumPut(VarSetCapacity(PROCESSENTRY32, A_PtrSize == 4 ? 556 : 568), &PROCESSENTRY32, "UInt")
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834(v=vs.85).aspx
local OutputVar := []
if ( DllCall("Kernel32.dll\Process32FirstW", "Ptr", hSnapshot, "UPtr", &PROCESSENTRY32) )
loop
OutputVar[A_Index] := { ProcessId: NumGet(&PROCESSENTRY32 + 8, "UInt")
, ParentProcessId: NumGet(&PROCESSENTRY32 + (A_PtrSize == 4 ? 24 : 32), "UInt")
, ProcessName: StrGet(&PROCESSENTRY32 + (A_PtrSize == 4 ? 36 : 44), "UTF-16")
, Threads: NumGet(&PROCESSENTRY32 + (A_PtrSize == 4 ? 20 : 28), "UInt") }
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms684836(v=vs.85).aspx
until (!DllCall("Kernel32.dll\Process32NextW", "Ptr", hSnapshot, "UPtr", &PROCESSENTRY32))
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
DllCall("Kernel32.dll\CloseHandle", "Ptr", hSnapshot)
return ObjLength(OutputVar) ? OutputVar : 0
} ;https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834(v=vs.85).aspx
Code: Select all
SetBatchLines, -1
linkText := "05 May 2020, 06:43"
js =
(
(() => {
const links = document.links;
for (let i = 0; i < links.length; i++) {
if (links[i].innerText == '%linkText%') {
links[i].click();
break
}
}
})();
)
$F1:: RunJsFromChromeAddressBar(js)
RunJsFromChromeAddressBar(js, exe := "chrome.exe") {
static WM_GETOBJECT := 0x3D
, ROLE_SYSTEM_TEXT := 0x2A
, STATE_SYSTEM_FOCUSABLE := 0x100000
, SELFLAG_TAKEFOCUS := 0x1
if !AccAddrBar {
window := "ahk_class Chrome_WidgetWin_1 ahk_exe " . exe
SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, % window
AccChrome := AccObjectFromWindow( WinExist(window) )
AccAddrBar := SearchElement(AccChrome, {Role: ROLE_SYSTEM_TEXT, State: STATE_SYSTEM_FOCUSABLE})
}
AccAddrBar.accValue(0) := "javascript:" . js
AccAddrBar.accSelect(SELFLAG_TAKEFOCUS, 0)
ControlSend,, {Enter}, % window, Chrome Legacy Window
}
SearchElement(parentElement, params)
{
found := true
for k, v in params {
try {
if (k = "ChildCount")
(parentElement.accChildCount != v && found := false)
else if (k = "State")
(!(parentElement.accState(0) & v) && found := false)
else
(parentElement["acc" . k](0) != v && found := false)
}
catch
found := false
} until !found
if found
Return parentElement
for k, v in AccChildren(parentElement)
if obj := SearchElement(v, params)
Return obj
}
AccObjectFromWindow(hWnd, idObject = 0) {
static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}"
, IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
, OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
, h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF
DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID)
if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0
Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
}
AccChildren(Acc) {
static VT_DISPATCH := 9
Loop 1 {
if ComObjType(Acc, "Name") != "IAccessible" {
error := "Invalid IAccessible Object"
break
}
try cChildren := Acc.accChildCount
catch
Return ""
Children := []
VarSetCapacity(varChildren, cChildren*(8 + A_PtrSize*2), 0)
res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0
, "Int", cChildren, "Ptr", &varChildren, "IntP", cChildren)
if (res != 0) {
error := "AccessibleChildren DllCall Failed"
break
}
Loop % cChildren {
i := (A_Index - 1)*(A_PtrSize*2 + 8)
child := NumGet(varChildren, i + 8)
Children.Push( (b := NumGet(varChildren, i) = VT_DISPATCH) ? AccQuery(child) : child )
( b && ObjRelease(child) )
}
}
if error
ErrorLevel := error
else
Return Children.MaxIndex() ? Children : ""
}
AccQuery(Acc) {
static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1
try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE)
}
Wow, this is amazing. I never knew this kind of interaction with Chrome was possible.teadrinker wrote: ↑05 May 2020, 08:17If using accsessible, it's easier to get acc-object of Chrome address bar and run javascript from it, which searches for a link with specified text and clicks it.Code: Select all
SetBatchLines, -1 linkText := "05 May 2020, 06:43" js = ( (() => { const links = document.links; for (let i = 0; i < links.length; i++) { if (links[i].innerText == '%linkText%') { links[i].click(); break } } })(); ) $F1:: RunJsFromChromeAddressBar(js) RunJsFromChromeAddressBar(js, exe := "chrome.exe") { static WM_GETOBJECT := 0x3D , ROLE_SYSTEM_TEXT := 0x2A , STATE_SYSTEM_FOCUSABLE := 0x100000 , SELFLAG_TAKEFOCUS := 0x1 if !AccAddrBar { window := "ahk_class Chrome_WidgetWin_1 ahk_exe " . exe SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, % window AccChrome := AccObjectFromWindow( WinExist(window) ) AccAddrBar := SearchElement(AccChrome, {Role: ROLE_SYSTEM_TEXT, State: STATE_SYSTEM_FOCUSABLE}) } AccAddrBar.accValue(0) := "javascript:" . js AccAddrBar.accSelect(SELFLAG_TAKEFOCUS, 0) ControlSend,, {Enter}, % window, Chrome Legacy Window } SearchElement(parentElement, params) { found := true for k, v in params { try { if (k = "ChildCount") (parentElement.accChildCount != v && found := false) else if (k = "State") (!(parentElement.accState(0) & v) && found := false) else (parentElement["acc" . k](0) != v && found := false) } catch found := false } until !found if found Return parentElement for k, v in AccChildren(parentElement) if obj := SearchElement(v, params) Return obj } AccObjectFromWindow(hWnd, idObject = 0) { static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}" , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}" , OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1 , h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr") VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID) if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0 Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE) } AccChildren(Acc) { static VT_DISPATCH := 9 Loop 1 { if ComObjType(Acc, "Name") != "IAccessible" { error := "Invalid IAccessible Object" break } try cChildren := Acc.accChildCount catch Return "" Children := [] VarSetCapacity(varChildren, cChildren*(8 + A_PtrSize*2), 0) res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0 , "Int", cChildren, "Ptr", &varChildren, "IntP", cChildren) if (res != 0) { error := "AccessibleChildren DllCall Failed" break } Loop % cChildren { i := (A_Index - 1)*(A_PtrSize*2 + 8) child := NumGet(varChildren, i + 8) Children.Push( (b := NumGet(varChildren, i) = VT_DISPATCH) ? AccQuery(child) : child ) ( b && ObjRelease(child) ) } } if error ErrorLevel := error else Return Children.MaxIndex() ? Children : "" } AccQuery(Acc) { static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1 try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE) }
Code: Select all
SetBatchLines, -1
js =
(
javascript:
(() => {
if (window.location.protocol === 'https:') {
document.documentElement.focus();
const timer = setInterval(() => {
if (document.hasFocus()) {
clearInterval(timer);
navigator.clipboard.writeText(document.documentElement.outerHTML);
}
}, 10);
}
else {
const textArea = document.createElement('textarea');
textArea.value = document.documentElement.outerHTML;
textArea.wrap = 'off';
textArea.rows = 100000;
textArea.style.position = 'fixed';
document.documentElement.appendChild(textArea);
textArea.focus();
textArea.select();
document.execCommand('copy');
textArea.parentNode.removeChild(textArea);
}
})();
)
Return
$F1::
Clipboard := ""
RunJsFromChromeAddressBar(js)
ClipWait, 2
MsgBox, % ErrorLevel ? "Failed to get value" : Clipboard
Return
RunJsFromChromeAddressBar(js, exe := "chrome.exe") {
static WM_GETOBJECT := 0x3D
, ROLE_SYSTEM_TEXT := 0x2A
, STATE_SYSTEM_FOCUSABLE := 0x100000
, SELFLAG_TAKEFOCUS := 0x1
, AccAddrBar
if !AccAddrBar {
window := "ahk_class Chrome_WidgetWin_1 ahk_exe " . exe
SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, % window
AccChrome := AccObjectFromWindow( WinExist(window) )
AccAddrBar := SearchElement(AccChrome, {Role: ROLE_SYSTEM_TEXT, State: STATE_SYSTEM_FOCUSABLE})
}
AccAddrBar.accValue(0) := "javascript:" . js
AccAddrBar.accSelect(SELFLAG_TAKEFOCUS, 0)
ControlSend,, {Enter}, % window, Chrome Legacy Window
}
SearchElement(parentElement, params)
{
found := true
for k, v in params {
try {
if (k = "ChildCount")
(parentElement.accChildCount != v && found := false)
else if (k = "State")
(!(parentElement.accState(0) & v) && found := false)
else
(parentElement["acc" . k](0) != v && found := false)
}
catch
found := false
} until !found
if found
Return parentElement
for k, v in AccChildren(parentElement)
if obj := SearchElement(v, params)
Return obj
}
AccObjectFromWindow(hWnd, idObject = 0) {
static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}"
, IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
, OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
, h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF
DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID)
if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0
Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
}
AccChildren(Acc) {
static VT_DISPATCH := 9
Loop 1 {
if ComObjType(Acc, "Name") != "IAccessible" {
error := "Invalid IAccessible Object"
break
}
try cChildren := Acc.accChildCount
catch
Return ""
Children := []
VarSetCapacity(varChildren, cChildren*(8 + A_PtrSize*2), 0)
res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0
, "Int", cChildren, "Ptr", &varChildren, "IntP", cChildren)
if (res != 0) {
error := "AccessibleChildren DllCall Failed"
break
}
Loop % cChildren {
i := (A_Index - 1)*(A_PtrSize*2 + 8)
child := NumGet(varChildren, i + 8)
Children.Push( (b := NumGet(varChildren, i) = VT_DISPATCH) ? AccQuery(child) : child )
( b && ObjRelease(child) )
}
}
if error
ErrorLevel := error
else
Return Children.MaxIndex() ? Children : ""
}
AccQuery(Acc) {
static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1
try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE)
}
Thanks.teadrinker wrote: ↑05 May 2020, 09:52The easiest way to get text is to put it on Clipboard.
Example of retrieving HTML code (thanks @malcev) :Anyway to use this method, you must have at least basic Javascript knowledge.Code: Select all
SetBatchLines, -1 js = ( javascript: (() => { if (window.location.protocol === 'https:') { document.documentElement.focus(); const timer = setInterval(() => { if (document.hasFocus()) { clearInterval(timer); navigator.clipboard.writeText(document.documentElement.outerHTML); } }, 10); } else { const textArea = document.createElement('textarea'); textArea.value = document.documentElement.outerHTML; textArea.wrap = 'off'; textArea.rows = 100000; textArea.style.position = 'fixed'; document.documentElement.appendChild(textArea); textArea.focus(); textArea.select(); document.execCommand('copy'); textArea.parentNode.removeChild(textArea); } })(); ) Return $F1:: Clipboard := "" RunJsFromChromeAddressBar(js) ClipWait, 2 MsgBox, % ErrorLevel ? "Failed to get value" : Clipboard Return RunJsFromChromeAddressBar(js, exe := "chrome.exe") { static WM_GETOBJECT := 0x3D , ROLE_SYSTEM_TEXT := 0x2A , STATE_SYSTEM_FOCUSABLE := 0x100000 , SELFLAG_TAKEFOCUS := 0x1 , AccAddrBar if !AccAddrBar { window := "ahk_class Chrome_WidgetWin_1 ahk_exe " . exe SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, % window AccChrome := AccObjectFromWindow( WinExist(window) ) AccAddrBar := SearchElement(AccChrome, {Role: ROLE_SYSTEM_TEXT, State: STATE_SYSTEM_FOCUSABLE}) } AccAddrBar.accValue(0) := "javascript:" . js AccAddrBar.accSelect(SELFLAG_TAKEFOCUS, 0) ControlSend,, {Enter}, % window, Chrome Legacy Window } SearchElement(parentElement, params) { found := true for k, v in params { try { if (k = "ChildCount") (parentElement.accChildCount != v && found := false) else if (k = "State") (!(parentElement.accState(0) & v) && found := false) else (parentElement["acc" . k](0) != v && found := false) } catch found := false } until !found if found Return parentElement for k, v in AccChildren(parentElement) if obj := SearchElement(v, params) Return obj } AccObjectFromWindow(hWnd, idObject = 0) { static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}" , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}" , OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1 , h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr") VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID) if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0 Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE) } AccChildren(Acc) { static VT_DISPATCH := 9 Loop 1 { if ComObjType(Acc, "Name") != "IAccessible" { error := "Invalid IAccessible Object" break } try cChildren := Acc.accChildCount catch Return "" Children := [] VarSetCapacity(varChildren, cChildren*(8 + A_PtrSize*2), 0) res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0 , "Int", cChildren, "Ptr", &varChildren, "IntP", cChildren) if (res != 0) { error := "AccessibleChildren DllCall Failed" break } Loop % cChildren { i := (A_Index - 1)*(A_PtrSize*2 + 8) child := NumGet(varChildren, i + 8) Children.Push( (b := NumGet(varChildren, i) = VT_DISPATCH) ? AccQuery(child) : child ) ( b && ObjRelease(child) ) } } if error ErrorLevel := error else Return Children.MaxIndex() ? Children : "" } AccQuery(Acc) { static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1 try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE) }
Hi guys, I'm totally lost here. does the code above serve the purpose of original topic? I don't have basic JS knowledge and based on the code itself (without comments).. I'm unable to understand what it does line by line.. especially how it finds "unsubscribe" link without any mention of unsubscribe at all.teadrinker wrote: ↑05 May 2020, 09:52The easiest way to get text is to put it on Clipboard.
Example of retrieving HTML code (thanks @malcev) :Anyway to use this method, you must have at least basic Javascript knowledge.Code: Select all
SetBatchLines, -1 js = ( javascript: (() => { if (window.location.protocol === 'https:') { document.documentElement.focus(); const timer = setInterval(() => { if (document.hasFocus()) { clearInterval(timer); navigator.clipboard.writeText(document.documentElement.outerHTML); } }, 10); } else { const textArea = document.createElement('textarea'); textArea.value = document.documentElement.outerHTML; textArea.wrap = 'off'; textArea.rows = 100000; textArea.style.position = 'fixed'; document.documentElement.appendChild(textArea); textArea.focus(); textArea.select(); document.execCommand('copy'); textArea.parentNode.removeChild(textArea); } })(); ) Return $F1:: Clipboard := "" RunJsFromChromeAddressBar(js) ClipWait, 2 MsgBox, % ErrorLevel ? "Failed to get value" : Clipboard Return RunJsFromChromeAddressBar(js, exe := "chrome.exe") { static WM_GETOBJECT := 0x3D , ROLE_SYSTEM_TEXT := 0x2A , STATE_SYSTEM_FOCUSABLE := 0x100000 , SELFLAG_TAKEFOCUS := 0x1 , AccAddrBar if !AccAddrBar { window := "ahk_class Chrome_WidgetWin_1 ahk_exe " . exe SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, % window AccChrome := AccObjectFromWindow( WinExist(window) ) AccAddrBar := SearchElement(AccChrome, {Role: ROLE_SYSTEM_TEXT, State: STATE_SYSTEM_FOCUSABLE}) } AccAddrBar.accValue(0) := "javascript:" . js AccAddrBar.accSelect(SELFLAG_TAKEFOCUS, 0) ControlSend,, {Enter}, % window, Chrome Legacy Window } SearchElement(parentElement, params) { found := true for k, v in params { try { if (k = "ChildCount") (parentElement.accChildCount != v && found := false) else if (k = "State") (!(parentElement.accState(0) & v) && found := false) else (parentElement["acc" . k](0) != v && found := false) } catch found := false } until !found if found Return parentElement for k, v in AccChildren(parentElement) if obj := SearchElement(v, params) Return obj } AccObjectFromWindow(hWnd, idObject = 0) { static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}" , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}" , OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1 , h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr") VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID) if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0 Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE) } AccChildren(Acc) { static VT_DISPATCH := 9 Loop 1 { if ComObjType(Acc, "Name") != "IAccessible" { error := "Invalid IAccessible Object" break } try cChildren := Acc.accChildCount catch Return "" Children := [] VarSetCapacity(varChildren, cChildren*(8 + A_PtrSize*2), 0) res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0 , "Int", cChildren, "Ptr", &varChildren, "IntP", cChildren) if (res != 0) { error := "AccessibleChildren DllCall Failed" break } Loop % cChildren { i := (A_Index - 1)*(A_PtrSize*2 + 8) child := NumGet(varChildren, i + 8) Children.Push( (b := NumGet(varChildren, i) = VT_DISPATCH) ? AccQuery(child) : child ) ( b && ObjRelease(child) ) } } if error ErrorLevel := error else Return Children.MaxIndex() ? Children : "" } AccQuery(Acc) { static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1 try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE) }
Code: Select all
SetBatchLines, -1
linkText := "Unsubscribe"
linkText2 := "CLICK HERE"
js =
(
(() => {
const links = document.links;
for (let i = 0; i < links.length; i++) {
if (links[i].innerText == '%linkText%' || links[i].innerText == '%linkText2%') {
links[i].click();
break
}
}
})();
)
q:: RunJsFromChromeAddressBar(js)
RunJsFromChromeAddressBar(js, exe := "chrome.exe") {
static WM_GETOBJECT := 0x3D
, ROLE_SYSTEM_TEXT := 0x2A
, STATE_SYSTEM_FOCUSABLE := 0x100000
, SELFLAG_TAKEFOCUS := 0x1
if !AccAddrBar {
window := "ahk_class Chrome_WidgetWin_1 ahk_exe " . exe
SendMessage, WM_GETOBJECT, 0, 1, Chrome_RenderWidgetHostHWND1, % window
AccChrome := AccObjectFromWindow( WinExist(window) )
AccAddrBar := SearchElement(AccChrome, {Role: ROLE_SYSTEM_TEXT, State: STATE_SYSTEM_FOCUSABLE})
}
AccAddrBar.accValue(0) := "javascript:" . js
AccAddrBar.accSelect(SELFLAG_TAKEFOCUS, 0)
ControlSend,, {Enter}, % window, Chrome Legacy Window
}
SearchElement(parentElement, params)
{
found := true
for k, v in params {
try {
if (k = "ChildCount")
(parentElement.accChildCount != v && found := false)
else if (k = "State")
(!(parentElement.accState(0) & v) && found := false)
else
(parentElement["acc" . k](0) != v && found := false)
}
catch
found := false
} until !found
if found
Return parentElement
for k, v in AccChildren(parentElement)
if obj := SearchElement(v, params)
Return obj
}
AccObjectFromWindow(hWnd, idObject = 0) {
static IID_IDispatch := "{00020400-0000-0000-C000-000000000046}"
, IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
, OBJID_NATIVEOM := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
, h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF
DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID)
if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0
Return ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
}
AccChildren(Acc) {
static VT_DISPATCH := 9
Loop 1 {
if ComObjType(Acc, "Name") != "IAccessible" {
error := "Invalid IAccessible Object"
break
}
try cChildren := Acc.accChildCount
catch
Return ""
Children := []
VarSetCapacity(varChildren, cChildren*(8 + A_PtrSize*2), 0)
res := DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0
, "Int", cChildren, "Ptr", &varChildren, "IntP", cChildren)
if (res != 0) {
error := "AccessibleChildren DllCall Failed"
break
}
Loop % cChildren {
i := (A_Index - 1)*(A_PtrSize*2 + 8)
child := NumGet(varChildren, i + 8)
Children.Push( (b := NumGet(varChildren, i) = VT_DISPATCH) ? AccQuery(child) : child )
( b && ObjRelease(child) )
}
}
if error
ErrorLevel := error
else
Return Children.MaxIndex() ? Children : ""
}
AccQuery(Acc) {
static IAccessible := "{618736e0-3c3d-11cf-810c-00aa00389b71}", VT_DISPATCH := 9, F_OWNVALUE := 1
try Return ComObject(VT_DISPATCH, ComObjQuery(Acc, IAccessible), F_OWNVALUE)
}
not sure if this is what you're looking for. I just hit view source while in the email page. 3 different samples attached:teadrinker wrote: ↑06 May 2020, 19:49@reverberation
Can you show HTML code of the link you need to click?
@teadrinker This is an amazing solution, isn't that an XSS procedure? if that is the case, then if a website is protected against it this script will not execute correctly, am I wrong?teadrinker wrote: ↑05 May 2020, 08:17If using accsessible, it's easier to get acc-object of Chrome address bar and run javascript from it, which searches for a link with specified text and clicks it.
@reverberation Indeed this code does what is intended to do, I strongly recommend you to study the fundamentals of how websites work in order to advance in web scripting. Most websites are based on three pillars, HTML, CSS and JavaScript, the first one provides structure the second the visuals and the third the interactivity. Now this code goes in to the last category and works injecting some JS code directly in the website to retrieve the element that is required. Learning HTML and CSS is fast and easy, in a week you can get a good grasp on it, for JS I recommend the book Head First JavaScript Programming, A Brain Friendly Guide by Eric Freeman and Elisabeth Robson, this is the friendliest book I've seen about JS.Hi guys, I'm totally lost here. does the code above serve the purpose of original topic? I don't have basic JS knowledge and based on the code itself (without comments).. I'm unable to understand what it does line by line.. especially how it finds "unsubscribe" link without any mention of unsubscribe at all.
Will also be keen to implement for "Submit" button if this works!
I tried it in a simple email with Unsubscribe link and it returned this: