I however use it as a means for remote control of my scripts in a multitude of devices and places, from pretty much any device, able to send & receive messages to/from my scripts. I saw a post inquiring about such functionality,which is what prompted me to post it. Cheers.
EDIT: Updated Example to reflect a few more basic use cases...
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#SingleInstance, force
#Persistent
/*
Choose A Very Random channel name,the tlk.io premise is that all channels are public,if you want privacy pick a very convoluted channel name!
NOTE: tlk.io has this issue where if you login/out fast enough it displays a wrong number of active users, but this isn't a functional problem,
it's merely a UI bug & doesn't affect core functionality(Chat).
ALSO NOTE: tlk.io is like reddit,with pages defining threads,except by default all content in a channel is discarded within 10minutes...
I Use this script to control my scripts at a home & work from either place or from my phone...
NOTE: tlk.io doesn't recognise line breaks, so i suggest replacing line breaks with place holder characters
& reading them as line breaks by listener as in examples below...
*/
;receiver scripts would check for latest messages...
SetTimer, checkMsg, 1000
;sender would make a post & other receivers would constantly check page for latest post
s::tlkdotio("my-remote-control-channel", true, "someBot", "post this and log out - " A_TickCount, true)
;other examples...
;send an execute command example,where any post prefixed with ;#ExecScript will have listener script evaluate a post as a script to execute....
x::tlkdotio("my-remote-control-channel", true, "someBot", ";#ExecScript\n MsgBox, 0x40040, tlkdotio, >Remote Code Execution Example... " A_TickCount, true)
;run calc on remote system...
r::tlkdotio("my-remote-control-channel", true, "someBot", ";#ExecRun\n calc", true)
CheckMsg(){ ;basically the listener script...
Static
If !prevMsg
FileRead prevMsg, %A_Temp%\prevMsg
Try tdi := tlkdotio("my-remote-control-channel", true)
lastMsg := Trim(Trim(tdi.lastMsg,"`r`n"))
If (prevMsg <> lastMsg && tdi.lastUsr = "someBot"){ ;alerts when userName someBot makes a post...
prevMsg := lastMsg
FileDelete %A_Temp%\prevMsg
FileAppend % lastMsg, %A_Temp%\prevMsg ;for Persistence across script sessions
TrayTip, tlk.io [listener], % lastMsg
;Message Parsing Examples...
If (StrSplit(lastMsg,"\n")[1] = ";#ExecScript") ;remote exec, where entire message is considered a script to be executed...
ExecScript(StrReplace(lastMsg, "\n", "`n"), false)
Else If (StrSplit(lastMsg,"\n")[1] = ";#ExecRun") ;run applications on other system, application path & param must be on next line..
Run % Trim(StrSplit(lastMsg,"\n")[2])
;... ^Just a few examples of how you can use it beyond simple remote control of scripts themselves...
}
}
IsOnline(url:="http://google.com"){
if(!dllCall("Wininet.dll\InternetCheckConnection","Str",url,"Uint",1,"Uint",0))
return 0
return 1
}
ExecScript(Script, Wait:=true){
shell := ComObjCreate("WScript.Shell"),exec := shell.Exec("AutoHotkey.exe /ErrorStdOut *"),exec.StdIn.Write(script),exec.StdIn.Close()
if Wait
return exec.StdOut.ReadAll()
}
;channelName=echo resolves to https://tlk.io/echo
;,tlk.io is like reddit,with pages defining threads,except by default all content in a channel/thread is discarded within 10minutes...
tlkdotio(channelName:="", ieVisible:=true, userName:="", postText:="", logOut:=false){
Static pwb,lastMsgAggregated,ChatTextAggregated
OnExit, OnExit
If !IsOnline(){
Try pwb.quit
return
}
DHW := A_DetectHiddenWindows
DetectHiddenWindows, On
channelUrl := "https://tlk.io/" channelName
If !IsObject(pwb) && !(pwb:=setWbCom("tlk.io / " channelName, channelUrl)){ ;get pointer to specific window title and domain ;if window active
pwb := ComObjCreate("InternetExplorer.Application") ;create IE Object
pwb.visible := ieVisible ? True : False ; Set the IE object to visible
pwb.Navigate(channelUrl) ;Navigate to URL
While pwb.readyState != 4 || pwb.document.readyState != "complete" || pwb.busy ; wait for the page to load
Sleep, 10
}
If userName{
pwb.document.getElementByID("participant_nickname").value := userName
pwb.document.getElementByID("participant_nickname").focus()
Loop 6
ControlSend, Internet Explorer_Server%A_index%, {Enter}, % "ahk_id " pwb.hwnd
}
If postText{
Sleep 1000
pwb.document.getElementByID("message_body").value := postText
pwb.document.getElementByID("message_body").focus()
Loop 6
ControlSend, Internet Explorer_Server%A_index%, {Enter}, % "ahk_id " pwb.hwnd
}
If logOut
pwb.document.getElementByID("sign-out").click()
usersNum := pwb.document.getElementsByClassname("counter")[0].innerText ;number of users
usersNum := SubStr(usersNum,1,1)
usersList := pwb.document.getElementsByClassname("participants")[0].innerText ;users
;// write the Chat Source to an HTMLfile
chat := ""
chat := ComObjCreate("HTMLfile")
chat.write(chatSource)
links := chat.links
while (A_Index<=links.length, i:=A_Index-1)
linksList .= i ") " links[i].innerText "`nURL: " links[i].href "`n`n"
Loop{ ;loop through all posted messages on page... find last poster,... reset last msg instead of appending to it when user changes...
Try
thisUsr := pwb.document.getElementsByClassname("post-name")[A_Index-1].innerText
Catch
Break
msgUsrList .= msgUsrList ? thisUsr : "`n`n" thisUsr
lastUsr := thisUsr ? thisUsr : lastUsr
}
Loop{ ;loop through all posted messages on page...
Try
thisMsg := pwb.document.getElementsByClassname("post-message")[A_Index-1].innerText
Catch
Break
StringTrimRight, thisMsg, thisMsg, 10 ;trim excess garbage...
msgList .= msgList ? thisMsg : "`n`n" thisMsg
,lastMsg := thisMsg ? thisMsg : lastMsg
,lastMsgAggregated := SubStr(thisMsg,1,1) = "@" ? "" : lastMsgAggregated ;reset block msgs
,lastMsgAggregated := thisMsg ? lastMsgAggregated "`n" thisMsg : lastMsgAggregated
}
DetectHiddenWindows, % DHW
Return {links:linksList, lastUsr:lastUsr, lastMsg:lastMsg, lastMsgAggregated:lastMsgAggregated, msgList:msgList
, chatTextSource:StrReplace(pwb.document.getElementsByClassname("chat")[0].outerHTML,">Delete<") ;for debugging
, chatText:StrReplace(pwb.document.getElementsByClassname("chat")[0].innerText,"`n Delete ") ;for debugging
, usersList:usersList, usersNum:usersNum}
OnExit:
DetectHiddenWindows, on
Try pwb.quit
ExitApp
}
;***********Function*******************
setWbCom(name=false, url=false) {
; Set web browser COM pointer ; eserv_flag sets this.wb_eserv
if (!name AND !url) {
; Clear COM object
return false
}
; Set defaults. No promises.
wb:=false
For wb in ComObjCreate( "Shell.Application" ).Windows {
Try {
If ((InStr(wb.locationName, name) AND name) OR (InStr(wb.locationURL, url) AND url)) && InStr(wb.FullName, "iexplore.exe") {
return wb
}
} Catch, e {
if (e AND this.debug) {
FileAppend, % "`r`nCOM Error: " . e, % this.debug_file
}
}
}
if (debug) {
this.errorWindow("Failed to find web browser.`r`nName:`t" . name . "`r`nURL:`t" . url)
}
return false
}