;Autohotkey+Web Short Message(com.wangtai.smstwoman)短信接口 ;Thinkai@2015-01-05 ;注意每次运行APP的管理网址都不一样 ManageUrl = http://192.168.1.106:1984/8119 ;获取参数 RegExMatch(ManageUrl,"^(http://.*:\d*/)(\d{4})",parameter) global parameter1 global parameter2 ;运用实例 ;发短信 if (SendMsg(10001,7)=1) MsgBox, 64, 提示, 短信发送成功 ;接收回复 NewMessage := GetNewMsg() From := NewMessage[1]["person"] ? NewMessage[1]["person"] "(" NewMessage[1]["address"] ")" : "未知(" NewMessage[1]["address"] ")" MsgBox % "From:" From "`n" NewMessage[1]["body"] ;获取联系人 Contact := GetContacts() for k,v in Contact { MsgBox, 64, 提示, 第一个联系人是%v%`,号码是%k% Return } ;获取新消息函数(调用后收到的) GetNewMsg(){ ;返回数组说明 ;数组[1]: ; _id:消息ID ; address:号码 ; body:短信正文 ; date:收信Uinx时间戳 ; person:联系人 Loop { res := URLDownloadToVar(parameter1 "get_new_msg/" parameter2 "/", "utf-8","POST") ;获取最新短信的JSON数据 if (strlen(res)>2) Return json_toobj(res) Sleep, 100 } } ;获取联系人函数 GetContacts(){ obj := {} ;初始数组 res := URLDownloadToVar(parameter1 "get_contacts/" parameter2 "/", "utf-8","POST") ;获取联系人的JSON数据 ;处理格式问题 StringTrimLeft, res, res, 1 StringTrimRight, res, res, 1 StringSplit, var, res, `, loop % var0 { tmp_var := var%A_index% RegExMatch(tmp_var,"""(.*)"":""(.*)""",m) m1 := RegExReplace(m1,"\s","") m1 := RegExReplace(m1,"\+86","") obj["" m1] := m2 ;注意此处数组key的类型 } Return obj ;返回数组 obj[电话号码] := 联系人姓名 } ;发短信函数 SendMsg(to,msg){ ;号码,消息 msg := urlencode(msg) Return URLDownloadToVar(parameter1 "send/" parameter2 "/" to "/", "utf-8","POST","msg=" msg) } URLDownloadToVar(url, Encoding = "",Method="GET",postData=""){ ;网址,编码,请求方式,post数据 hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1") if Method = GET { hObject.Open("GET",url) Try hObject.Send() catch e return -1 } else if Method = POST { hObject.Open("POST",url,False) hObject.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") Try hObject.Send(postData) catch e return -1 } if Encoding { oADO := ComObjCreate("adodb.stream") oADO.Type := 1 oADO.Mode := 3 oADO.Open() oADO.Write(hObject.ResponseBody) oADO.Position := 0 oADO.Type := 2 oADO.Charset := Encoding return oADO.ReadText(), oADO.Close() } return hObject.ResponseText } urlencode(string){ string := Ansi2UTF8(string) StringLen, len, string Loop % len { SetFormat, IntegerFast, hex ;运算结果为HEX StringMid, out, string, %A_Index%, 1 hex := Asc(out) ;获取单字节ascii值 hex2 := hex ;另存变量 StringReplace, hex, hex, 0x, , All SetFormat, IntegerFast, d hex2 := hex2 ;十进制化 ;判断是否可见单字节字符 是则直接连接 否则编码 If (hex2==33 || (hex2>=39 && hex2 <=42) || hex2==45 || hex2 ==46 || (hex2>=48 && hex2<=57) || (hex2>=65 && hex2<=90) || hex2==95 || (hex2>=97 && hex2<=122) || hex2==126) content .= out Else content .= "`%" hex } Return content } Ansi2Oem(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 1) Return zString } Oem2Ansi(zString) { Ansi2Unicode(zString, wString, 1) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2UTF8(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 65001) Return zString } UTF82Ansi(zString) { Ansi2Unicode(zString, wString, 65001) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2Unicode(ByRef sString, ByRef wString, CP = 0) { nSize := DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", 0 , "int", 0) VarSetCapacity(wString, nSize * 2) DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", &wString , "int", nSize) } Unicode2Ansi(ByRef wString, ByRef sString, CP = 0) { nSize := DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "Uint", 0 , "int", 0 , "Uint", 0 , "Uint", 0) VarSetCapacity(sString, nSize) DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "str", sString , "int", nSize , "Uint", 0 , "Uint", 0) } json_toobj(str){ quot := """" ; firmcoded specifically for readability. Hardcode for (minor) performance gain ws := "`t`n`r " Chr(160) ; whitespace plus NBSP. This gets trimmed from the markup obj := {} ; dummy object objs := [] ; stack keys := [] ; stack isarrays := [] ; stack literals := [] ; queue y := nest := 0 ; First pass swaps out literal strings so we can parse the markup easily StringGetPos, z, str, %quot% ; initial seek while !ErrorLevel { ; Look for the non-literal quote that ends this string. Encode literal backslashes as '\u005C' because the ; '\u..' entities are decoded last and that prevents literal backslashes from borking normal characters StringGetPos, x, str, %quot%,, % z + 1 while !ErrorLevel { StringMid, key, str, z + 2, x - z - 1 StringReplace, key, key, \\, \u005C, A If SubStr( key, 0 ) != "\" Break StringGetPos, x, str, %quot%,, % x + 1 } ; StringReplace, str, str, %quot%%t%%quot%, %quot% ; this might corrupt the string str := ( z ? SubStr( str, 1, z ) : "" ) quot SubStr( str, x + 2 ) ; this won't ; Decode entities StringReplace, key, key, \%quot%, %quot%, A StringReplace, key, key, \b, % Chr(08), A StringReplace, key, key, \t, % A_Tab, A StringReplace, key, key, \n, `n, A StringReplace, key, key, \f, % Chr(12), A StringReplace, key, key, \r, `r, A StringReplace, key, key, \/, /, A while y := InStr( key, "\u", 0, y + 1 ) if ( A_IsUnicode || Abs( "0x" SubStr( key, y + 2, 4 ) ) < 0x100 ) key := ( y = 1 ? "" : SubStr( key, 1, y - 1 ) ) Chr( "0x" SubStr( key, y + 2, 4 ) ) SubStr( key, y + 6 ) literals.insert(key) StringGetPos, z, str, %quot%,, % z + 1 ; seek } ; Second pass parses the markup and builds the object iteratively, swapping placeholders as they are encountered key := isarray := 1 ; The outer loop splits the blob into paths at markers where nest level decreases Loop Parse, str, % "]}" { StringReplace, str, A_LoopField, [, [], A ; mark any array open-brackets ; This inner loop splits the path into segments at markers that signal nest level increases Loop Parse, str, % "[{" { ; The first segment might contain members that belong to the previous object ; Otherwise, push the previous object and key to their stacks and start a new object if ( A_Index != 1 ) { objs.insert( obj ) isarrays.insert( isarray ) keys.insert( key ) obj := {} isarray := key := Asc( A_LoopField ) = 93 } ; arrrrays are made by pirates and they have index keys if ( isarray ) { Loop Parse, A_LoopField, `,, % ws "]" if ( A_LoopField != "" ) obj[key++] := A_LoopField = quot ? literals.remove(1) : A_LoopField } ; otherwise, parse the segment as key/value pairs else { Loop Parse, A_LoopField, `, Loop Parse, A_LoopField, :, % ws if ( A_Index = 1 ) key := A_LoopField = quot ? literals.remove(1) : A_LoopField else if ( A_Index = 2 && A_LoopField != "" ) obj[key] := A_LoopField = quot ? literals.remove(1) : A_LoopField } nest += A_Index > 1 } ; Loop Parse, str, % "[{" If !--nest Break ; Insert the newly closed object into the one on top of the stack, then pop the stack pbj := obj obj := objs.remove() obj[key := keys.remove()] := pbj If ( isarray := isarrays.remove() ) key++ } ; Loop Parse, str, % "]}" Return obj }
首先,使用USB网络共享\WIFI等方式使手机和电脑处于同一局域网。然后在手机上安装org.myklos.sendmessage这个App,并开启Server。(群发器已经打包了汉化版)
英文原版org.myklos.sendmessage.zip
打开手机软件上的地址,比如http://192.168.42.129:8080/ 看到内容即可开始使用。
在电脑上打开软件,填写上短信服务器地址即可开始使用。
参数:记录到文件,会把每一条记录写到文件
慢速发送,1秒一条,推荐手机慢的勾选
接口:
http://[服务器地址]/send/?pass=[密码 可空 ]&number=[号码]&data=[UTF-8 URLEncode的正文]&submit=&id=
php版
<?php $number = "10001"; //号码 $content = "测试thinkai.net"; //正文 $host = "192.168.42.129:8080"; //服务器地址 $pass = ""; //密码 $data = urlencode($content); //转码 $send = file_get_contents("http://$host/send/?pass=$pass&number=$number&data=$data&submit=&id="); //调用接口 $result = (explode("\n",$send)); //分割结果 echo str_replace("STATUS: ","",$result[0]); //显示状态 ?>
Autohotkey版
#NoTrayIcon ;转码函数 urlencode(string){ clip := ClipboardAll Clipboard = %string% Transform, string, Unicode Clipboard := clip StringLen, len, string SetFormat, IntegerFast, hex Loop { if A_Index > %len% Break StringMid, out, string, %A_Index%, 1 hex := Asc(out) hex := hex * 0x01 StringReplace, hex, hex, 0x, , All content = %content%`%%hex% } SetFormat, IntegerFast, d Return content } number = 10001 ; //号码 content = 测试thinkai.net ; //正文 host = 192.168.42.129:8080 ; //服务器地址 pass = ; //密码 data := urlencode(content) ; //转码 URLDownloadToFile, http://%host%/send/?pass=%pass%&number=%number%&data=%data%&submit=&id=, %A_Temp%\send.tmp FileRead, result, %A_Temp%\send.tmp StringSplit, result, result, `n ; //分割结果 StringReplace, status, result1, STATUS:%A_Space%, , MsgBox, 64, 结果, %status%
群发器源码
#NoTrayIcon ;不显示图标 FileInstall, org.myklos.sendmessage.apk, 网关服务器.apk ;打包文件 ;创建界面 Gui, Add, Text, x6 y7 w140 h50 , 短信网关地址`n例192.168.42.129:8080`n一行一个 Gui, Add, Edit, x6 y57 w140 h80 vgate, 192.168.42.129:8080 Gui, Add, CheckBox, x6 y137 w140 h20 vlog, 记录发送记录到文件 Gui, Add, CheckBox, x6 y157 w140 h20 vslow, 慢速发送 Gui, Add, Text, x146 y7 w100 h20 , 发送号码 Gui, Add, Edit, x146 y27 w100 h150 vhm Gui, Add, Text, x246 y7 w370 h20 , 短信内容 Gui, Add, Edit, x246 y27 w370 h150 vnr Gui, Add, Text, x6 y177 w240 h60 vshow Gui, Add, Button, x246 y177 w370 h60 gsend, 开始发送 Gui, Show,h246 w626, 群发短信单体版 ;检查是否使用过 加载上次填写的服务器地址 IfExist, gate.ini { FileRead, gate, gate.ini GuiControl, , gate, %gate% } ;转码函数 urlencode(string){ clip := ClipboardAll ;剪切板转存 Clipboard = %string% Transform, string, Unicode ;获取UTF-8 Clipboard := clip StringLen, len, string SetFormat, IntegerFast, hex ;运算结果为HEX Loop { if A_Index > %len% Break StringMid, out, string, %A_Index%, 1 hex := Asc(out) ;获取单字节ascii值 hex := hex * 0x01 StringReplace, hex, hex, 0x, , All content = %content%`%%hex% } SetFormat, IntegerFast, d ;运算结果为是静止 Return content } Return Send: ;从界面取回内容 GuiControlGet, hm GuiControlGet, nr GuiControlGet, gate GuiControlGet, log GuiControlGet, slow ;处理填写内容 IfNotInString, hm, `n { number0 = 1 number1 = %hm% } Else { StringReplace, hm, hm, `r, , All hm = %hm%`n StringReplace, hm, hm, `n`n, , All StringSplit, number, hm, `n } IfNotInString, gate, `n { gate0 = 1 gate1 = %gate% } Else { StringReplace, gate, gate, `r, , All gate = %gate%`n StringReplace, gate, gate, `n`n, , All StringSplit, gate, gate, `n } ;初始化 id = 0 success = 0 time = %A_Now% data := urlencode(nr) ;urlencode Loop { if A_Index > %number0% Break tmpnumber = % number%A_Index% if tmpnumber <> { StringReplace, tmpnumber, tmpnumber, -, , All b := tmpnumber/1 IfInString, b, .000000 { id += 1 if id > %gate0% id = 1 host = % gate%id% pass = ; //密码 GuiControl, , show, 网关:%host%`n号码:%tmpnumber%`n序号:%A_Index%`n ;显示 URLDownloadToFile, http://%host%/send/?pass=%pass%&number=%tmpnumber%&data=%data%&submit=&id=, %A_Temp%\send.tmp ;执行并抓回结果 FileRead, result, %A_Temp%\send.tmp StringSplit, result, result, `n ; //分割结果 StringReplace, status, result1, STATUS:%A_Space%, , GuiControl, , show, 网关:%host%`n号码:%tmpnumber%`n序号:%A_Index%`n状态:%status% if status = STATUS_OK success += 1 if log = 1 FileAppend, 网关:%host%`,号码:%tmpnumber%`,序号:%A_Index%`,状态:%status%`,时间:%A_Now%`n, %time%.log if slow = 1 sleep, 1000 ;Else ;sleep, 100 } } } GuiControl, , show, 共计发送%number0%条短信,其中成功%success%个! FileDelete, gate.ini FileAppend, %gate%, gate.ini Return GuiClose: ExitApp
安卓HTTP短信群发.zip 含汉化版org.myklos.sendmessage.apk
49 queries in 2.228 seconds |