[AHK] 조아라 자동 로그인 + 마나 모으기 매크로
안녕하세요.
이번엔 제가 만든 오토핫키 매크로를 공개하고자 합니다.
오토핫키로 이런것도 된다! 이걸 알리기 위해 포스팅합니다.
사실 오토핫키는 윈도우 상에서 뭐든지 가능합니다.
다만 사용자의 상상력 부족과 스크립트 코딩 능력 부족으로 구현을 못 할뿐이죠.
서론이 길었네요. 바로 매크로 소개로 넘어가보겠습니다.
일단 이 매크로는 다중 아이디의 일일 마나 모으기 작업을 원 클릭으로 해결하기 위해 만들었습니다.
사실 다중 아이디라고 해봤자 아이디가 두개밖에 없지만서도요.
로그인->마나 모으기 페이지 이동->마나 모으기 클릭->확인-로그아웃 X 아이디 갯수
이런 작업이다보니 매일 하기가 힘들어서 마나 모으기가 여의치 않았습니다.
그래서 만들었습니다.
자동 로그인 주소는 loginurl.exe 이란 유틸로 얻었습니다.
그외 자바스크립트 동작은 HTML 소스를 분석해서 얻었구요.
일단 매크로를 만들기전에 어떻게 만들지 스크립트 구조를 대충 생각합니다.
그리고 GUI 모양도 대충 생각을 해놓죠.
매크로 이름은 조아라 마나 채굴기로 정하고
아이디와 비번을 저장,
여러 아이디를 추가할 수 있고
초기화, 설정 저장, 마나 채굴(동작) 버튼을 구상했습니다.
포토샵으로 대충 타이틀을 만들고
코드를 짭니다.
보안을 위해 ID와 비번은 레지스트리에 저장을 하고
비밀번호는 암호화를 합니다.
암호화는 비번+컴퓨터이름을 조합하여 암호화를 합니다.
단순하지만 1차적으로 쉽게 알아차리긴 어렵습니다.
완성된 매크로입니다.
아래는 코드입니다.
막 짜다보니 군더더기가 많네요.
응용한다면 특정 시간대에 동작을 한다던지
부팅 후 일정시간 후에 동작을 한다던지
여러 방법이 있겠습니다.
+ 추가
암호를 저장한다는것에 대해 저어한다면
1. 저장 기능 없이 그냥 사용하기
2. 조아라 아이디 비번을 다른 커뮤니티, 포탈의 비번과 전혀 다른 비번으로 사용
3. 스크립트에서 conversion() function을 독자적으로 수정해서 사용
#NoEnv
#SingleInstance force
#Persistent
SetBatchLines,-1
CoordMode, Pixel, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Screen
SetTitleMatchMode, 2
SetControlDelay,400
global js1,js2,js3,logout,getmana,clickmana,inputNum,lastNum,workTemp,delaymsec:=1500
workTemp:= A_Temp . "\joaraManaDigger\"
logout:="http://www.joara.com/logOut.html"
getmana:="http://www.joara.com/member/get_mana.html"
clickmana:="javascript:document.getElementById('mana_check').click();"
js1:="javascript:document.write('<form style=""visibility:hidden"" name=lf method=post action=""https://www.joara.com/loginExe.html""><input name=""member_id"" value="""
js2:="""><input name=""passwd"" value="""
js3:="""></form><script>lf.submit();</script>');"
FileCreateDir, % workTemp
FileInstall, joara\img\title.jpg, % workTemp . "title.jpg", 1
InputListYpos:=85
inputNum:=1
Gui, 1:New
Gui, 1:Color, White
Gui, 1:Add, Picture, x17 y0 w400 h80, % workTemp . "title.jpg"
Loop
{
RegRead, opID, HKCU,Software\JoaraManaDigger,ID%A_Index%
RegRead, opPW, HKCU,Software\JoaraManaDigger,PW%A_Index%
if ( ErrorLevel = 0 ){
if ( A_Index > 1 )
inputNum++
opPW:=conversion(opPW,A_ComputerName)
Gui, 1:font,w600
Gui, 1:Add, Text, % "x10 y" . InputListYpos+3+((A_Index-1)*30) . " w50 h20 +Center vlistNo" . inputNum, % inputNum
Gui, 1:font,w400
Gui, 1:Add, Edit,% "x80 y" InputListYpos+((A_Index-1)*30) " w140 h20 -Multi vID" inputNum,% opID
Gui, 1:Add, Edit,% "x230 y" InputListYpos+((A_Index-1)*30) " w160 h20 +Password -Multi vPW" inputNum,% opPW
}else if ( ErrorLevel = 1 ){
if ( A_Index = 1 ){
Gui, 1:font,w600
Gui, 1:Add, Text, % "x10 y" . InputListYpos+3+((A_Index-1)*30) . " w50 h20 +Center vlistNo" . inputNum, % inputNum
Gui, 1:font,w400
Gui, 1:Add, Edit,% "x80 y" InputListYpos+((A_Index-1)*30) " w140 h20 -Multi vID" inputNum
Gui, 1:Add, Edit,% "x230 y" InputListYpos+((A_Index-1)*30) " w160 h20 -Multi +Password vPW" inputNum
}
break
}else{
MsgBox, 레지스트리 오류
gosub, CloseAndClear
}
}
Gui, 1:Add, Button, % "x10 y" . InputListYpos+30+((inputNum-1)*30) . " w70 h30", 초기화
Gui, 1:Add, Button, % "x115 y" . InputListYpos+30+((inputNum-1)*30) . " w110 h30", 저장
Gui, 1:Add, Button, % "x250 y" . InputListYpos+30+((inputNum-1)*30) . " w170 h30", 마나채굴
Gui, 1:Add, Button, x400 y%InputListYpos% w20 h20, +
Gui, 1:Show, % "w438 h" . InputListYpos+65+((inputNum-1)*30), JoaraManaDigger
Return
Button+:
WinGetPos,c_guiX,c_guiY,c_guiW,c_guiH,JoaraManaDigger
Guicontrol,1:+Resize,JoaraManaDigger
GuiControlGet,b,Pos,초기화
GuiControl,1:Move,초기화,% "x" bX " y" bY+30
GuiControlGet,b,Pos,저장
GuiControl,1:Move,저장,% "x" bX " y" bY+30
GuiControlGet,b,Pos,마나채굴
GuiControl,1:Move,마나채굴,% "x" bX " y" bY+30
WinMove,JoaraManaDigger,,c_guiX,c_guiY,c_guiW,c_guiH+30
inputNum++
Gui, 1:font,w600
Gui, 1:Add, Text, % "x10 y" . bY+3 . " w50 h20 +Center vlistNo" . inputNum, % inputNum
Gui, 1:font,w400
Gui, 1:Add, Edit, x80 y%bY% w140 h20 -Multi vID%inputNum%
Gui, 1:Add, Edit, x230 y%bY% w160 h20 -Multi +Password vPW%inputNum%
Guicontrol,1:-Resize,JoaraManaDigger
return
Button초기화:
MsgBox,4,설정 초기화 ,정말 모든 설정을 초기화 합니까?
IfMsgBox, Yes
RegDelete,HKCU,Software\JoaraManaDigger
Reload
return
Button저장:
gui,1:submit,nohide
set:=1
Loop,% inputNum*2
{
GuiControlGet,Edit%A_Index%
prt:=Edit%A_Index%
if prt
{
odd:=Mod(A_Index,2)
if ( odd != 0 ){
RegWrite,REG_SZ,HKEY_CURRENT_USER,Software\JoaraManaDigger,ID%set%,%prt%
}else{
RegWrite,REG_SZ,HKEY_CURRENT_USER,Software\JoaraManaDigger,PW%set%,% conversion(prt,A_ComputerName)
set++
}
}
}
MsgBox,저장됨!
return
Button마나채굴:
result:=
Loop
{
RegRead, opID, HKCU,Software\JoaraManaDigger,ID%A_Index%
RegRead, opPW, HKCU,Software\JoaraManaDigger,PW%A_Index%
if ( ErrorLevel = 0 ){
opPW:=conversion(opPW,A_ComputerName)
goIE(logout)
sleep,% delaymsec
goIE(getmana)
sleep,% delaymsec
js:=% js1 opID js2 opPW js3
goIE(js)
sleep,% delaymsec
goIE(clickmana)
sleep,% delaymsec
ControlFocus,Button1,ahk_class #32770,확인
ControlSend,Button1,{Enter down}{Enter up},ahk_class #32770,확인
sleep,% delaymsec
}else if ( ErrorLevel = 1 ){
break
}
}
return
GuiClose:
gosub, CloseAndClear
return
CloseButton:
gosub, CloseAndClear
return
Exit:
gosub, CloseAndClear
return
CloseAndClear:
FileRemoveDir,% workTemp, 1
ExitApp
return
Pause::Pause
WBGet(WinTitle="ahk_class IEFrame", Svr#=1) { ;// based on ComObjQuery docs
static msg := DllCall("RegisterWindowMessage", "str", "WM_HTML_GETOBJECT")
, IID := "{0002DF05-0000-0000-C000-000000000046}" ;// IID_IWebBrowserApp
;// , IID := "{332C4427-26CB-11D0-B483-00C04FD90119}" ;// IID_IHTMLWindow2
SendMessage msg, 0, 0, Internet Explorer_Server%Svr#%, %WinTitle%
if (ErrorLevel != "FAIL") {
lResult:=ErrorLevel, VarSetCapacity(GUID,16,0)
if DllCall("ole32\CLSIDFromString", "wstr","{332C4425-26CB-11D0-B483-00C04FD90119}", "ptr",&GUID) >= 0 {
DllCall("oleacc\ObjectFromLresult", "ptr",lResult, "ptr",&GUID, "ptr",0, "ptr*",pdoc)
return ComObj(9,ComObjQuery(pdoc,IID,IID),1), ObjRelease(pdoc)
}
}
}
goIE(load_url){
global wb
IfWinNotExist,ahk_class IEFrame
wb:=ComObjCreate("InternetExplorer.Application")
else
wb:=WBGet()
wb.Visible := true
isBusy()
wb.Navigate(load_url)
isBusy()
return
}
isBusy(){
while wb.busy
{
IfWinExist,ahk_class #32770,확인
{
ControlFocus,Button1,ahk_class #32770,확인
ControlSend,Button1,{Enter down}{Enter up},ahk_class #32770,확인
}
Sleep 50
}
return
}
conversion(Data,PW){
ATrim = %A_AutoTrim%
AutoTrim, Off
BLines = %A_BatchLines%
SetBatchlines, -1
StringLen, PWLen, PW
IfNotEqual, PW, %OldPW%
{
Loop, 256
{
a := A_Index - 1
Transform, ModVal, Mod, %a%, %PWLen%
ModVal ++
StringMid, C, PW, %ModVal%, 1
Transform, AscVar, Asc, %C%
Key%a% = %AscVar%
sBox%a% = %a%
}
b = 0
Loop, 256
{
a := A_Index - 1
TempVar := b + sBox%a% + Key%a%
Transform, b, Mod, %TempVar%, 256
T := sBox%a%
sBox%a% := sBox%b%
sBox%b% = %T%
}
OldPW = %PW%
}
StringLen, DataLen, Data
Result =
i = 0
j = 0
Loop, %DataLen%
{
TmpVar := i + 1
Transform, i, Mod, %TmpVar%, 256
TmpVar := sBox%i% + j
Transform, j, Mod, %TmpVar%, 256
TmpVar := sBox%i% + sBox%j%
Transform, TmpVar2, Mod, %TmpVar%, 256
k := sBox%TmpVar2%
StringMid, TmpVar, Data, %A_Index%, 1
Transform, AscVar, Asc, %TmpVar%
Transform, C, BitXOR, %AscVar%, %k%
IfEqual, C, 0
C = %k%
Transform, ChrVar, Chr, %C%
Result = %Result%%ChrVar%
}
AutoTrim, %ATrim%
SetBatchlines, %BLines%
Return %Result%
}
+ 추가 내용 (2016년 9월 26일)
수정한 스크립트를 올립니다.
변경점
- 스크립트 실행시 자동으로 IE 창을 엽니다.(조아라 사이트로 이동)
- 아이디 앞에 체크칸을 둬서 자동 실행하지 않을 아이디는 체크를 풀어서 제외시킬수 있습니다.
No. 옆의 체크는 전체 체크/해제 기능입니다.
- IE창의 로딩 완료 상태 체크 스크립트를 수정하여 좀 더 빠르고 원활한 동작을 수행합니다.
컴파일과 스크립트 파일 압축
joaraManaDigger160926.zip