TwitterのUserStreamを取得して、どんどんとmesしていくスクリプト。
hspextのpipeexec命令でも使って、別プロセスとして動かすことを想定して作りました。
固まることが多々あります。だからpipeを使えってことなんですけども。
TwitterのUserStreamを取得して、どんどんとmesしていくスクリプト。
hspextのpipeexec命令でも使って、別プロセスとして動かすことを想定して作りました。
固まることが多々あります。だからpipeを使えってことなんですけども。
#runtime "hsp3cl"#packopt name "USA"#module#defcfunc strCnt str p1, str p2string = p1count=0 : i=-1repeati = instr(string, i+1, p2)if i=-1 : breakcount++looplogmes "21"return count#deffunc getBlockStr str p1, int p2, int p3, var block, var otherstring = p1count= 0 : i=0sdim p2_spoke p2_s, 0, p2head=instr(string, 0, p2_s)if head=-1 : block="" : other=string : return blockrepeat ,headif peek(string, cnt)=$00 : return "-1"if peek(string, cnt)=p2 : count++if peek(string, cnt)=p3 : count--if count=0 : breaki++loopblock=strmid(string, head, i+1)other=strmid(string, head+i+1, strlen(string))return block#global#include "TsubuyakiSoup.as"#module UserStream#uselib "crtdll.dll"#func time "time" var#uselib "wininet.dll"#cfunc InternetOpen "InternetOpenA" sptr, int, sptr, sptr, int#cfunc InternetOpenUrl "InternetOpenUrlA" int, str, sptr, int, int, int#func InternetReadFile "InternetReadFile" int, var, int, var#func InternetCloseHandle "InternetCloseHandle" int#cfunc InternetConnect "InternetConnectA" int, str, int, sptr, sptr, int, int, int#cfunc HttpOpenRequest "HttpOpenRequestA" int, sptr, str, sptr, sptr, sptr, int, int#cfunc HttpSendRequest "HttpSendRequestA" int, sptr, int, sptr, int#cfunc HttpQueryInfo "HttpQueryInfoA" int, int, var, var, int#func InternetQueryDataAvailable "InternetQueryDataAvailable" int, int, int, int#func InternetSetOption "InternetSetOptionA" int, int, int, int#define INTERNET_FLAG_IGNORE_CERT_DATE_INVALID 0x2000#define INTERNET_FLAG_IGNORE_CERT_CN_INVALID 0x1000//------------------------------------------------------------//OAuth認証を含めた、UserStreamの初期化#deffunc UserStreamInit var p1, var p2, int p3, str p4, array p5// 引数チェック&初期化sdim p1sdim p2API = p4if vartype(p5) != 2 : return 0hConnect = 0 //InternetConnectのハンドルhRequest = 0 //HttpOpenRequestのハンドルAPI_statcode = 0 //リクエストの結果コードAPI_p1Length = 0 //データ長API_rsize = 1024 //バッファ初期値API_hsize = 0 //取得したバイト数が代入される変数dup TS_AccessToken,TS_AccessToken@TsubuyakiSoupdup TS_Consumer_Key, TS_Consumer_Key@TsubuyakiSoupdup TS_Consumer_Secret,TS_Consumer_Secret@TsubuyakiSoupdup TS_AccessTokenSecret, TS_AccessTokenSecret@TsubuyakiSoupdup TS_RequestToken, TS_RequestToken@TsubuyakiSoupdup TS_RequestTokenSecret, TS_RequestTokenSecret@TsubuyakiSoup// メソッドの設定if (p3 = 1) {Method = "POST"} else {Method = "GET"}// ポート&フラグの設定UsePort = 443 : RequestFlag = -2147483648 | 0x800000 | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |INTERNET_FLAG_IGNORE_CERT_CN_INVALID : Scheme = "https"VersionStr = "2/"TokenStr = TS_AccessTokenSigKey = TS_Consumer_Secret+" "+TS_AccessTokenSecretif (strmid(API,0,5) = "oauth") {VersionStr = ""if (API = "oauth/access_token") {repeat length(p5)if (p5(cnt) = "x_auth_mode=client_auth") : UsePort = 443 : RequestFlag = -2139082752 : Scheme = "https" : breakif cnt = length(p5)-1 : TokenStr = TS_RequestToken : SigKey = TS_Consumer_Secret+" "+TS_RequestTokenSecretloop}}// シグネチャ生成SigArrayMax = 6 + length(p5)sdim SigArray, 500, SigArrayMaxSigNonce = RandomString(8,32)time SigTimeSigArray(0) = "oauth_consumer_key=" + TS_Consumer_KeySigArray(1) = "oauth_nonce=" + SigNonceSigArray(2) = "oauth_signature_method=HMAC-SHA1"SigArray(3) = "oauth_timestamp=" + SigTimeSigArray(4) = "oauth_token="+ TokenStrSigArray(5) = "oauth_version=1.0"repeat SigArrayMax - 6SigArray(6+cnt) = p5(cnt)loop//ソートSortString SigArray//"&"で連結TransStr = ""+ Method +" "+ Scheme +"://userstream.twitter.com/"+ VersionStr + API +" "repeat SigArrayMaxif SigArray(cnt) = "" : continueTransStr += SigArray(cnt) +"&"loopTransStr = strmid(TransStr, 0, strlen(TransStr)-1)Signature = SignatureEncode(TransStr, SigKey)// データ整形if (p3 = 1) {//POSTPostStr = ""repeat SigArrayMaxPostStr += SigArray(cnt) +"&"loopPostStr += "oauth_signature="+ SignaturePostStrLen = strlen(PostStr)AddUrl = ""} else {//GETPostStr = 0PostStrLen = 0AddUrl = "?"repeat SigArrayMaxAddUrl += SigArray(cnt) +"&"loopAddUrl += "oauth_signature="+ Signature}logmes TransStr//サーバへ接続hConnect = InternetConnect(TwiH_hInet@TsubuyakiSoup, "userstream.twitter.com", UsePort, 0, 0, 3, 0, 0)if (hConnect) {//リクエストの初期化hRequest = HttpOpenRequest(hConnect, Method, VersionStr+API+AddUrl, "HTTP/1.1", 0, 0, RequestFlag, 0)if (hRequest) {logmes VersionStr+API+AddUrl//サーバへリクエスト送信if ( HttpSendRequest(hRequest, 0, 0, PostStr, PostStrLen)) {API_statcode = 0} else {//サーバへリクエスト送信できなかった場合API_statcode = -2}} else {//Requestハンドルを取得できなかった場合API_statcode = -3}} else {//Connectハンドルを取得できなかった場合API_statcode = -4}return API_statcode//適当な部分もある、UserStreamのヘッダ取得#deffunc getHead_US var p2//ヘッダを取得する変数の初期化p2Size = 3000sdim p2, p2Size//ヘッダの取得if ( HttpQueryInfo(hRequest, 22, p2, p2Size, 0) ) {//ヘッダの解析notesel p2repeat notemaxnoteget API_BufStr, cntAPI_buf = instr(API_BufStr, 0, "Status: ") //ステータスコードif (API_Buf != -1) : API_statcode = int(strmid(API_BufStr, API_buf+8, 3))API_buf = instr(API_BufStr, 0, "Content-Length: ") //長さif (API_Buf != -1) : API_p1Length = int(strmid(API_BufStr, -1, strlen(API_BufStr)-API_buf+16))API_buf = instr(API_BufStr, 0, "X-RateLimit-Limit: ") //60分間にAPIを実行できる回数if (API_Buf != -1) : TS_RateLimit(0) = int(strmid(API_BufStr, -1, strlen(API_BufStr)-(API_buf+19)))API_buf = instr(API_BufStr, 0, "X-RateLimit-Remaining: ") //APIを実行できる残り回数if (API_Buf != -1) : TS_RateLimit(1) = int(strmid(API_BufStr, -1, strlen(API_BufStr)-(API_buf+23)))API_buf = instr(API_BufStr, 0, "X-RateLimit-Reset: ") //リセットする時間if (API_Buf != -1) : TS_RateLimit(2) = int(strmid(API_BufStr, -1, strlen(API_BufStr)-(API_buf+19)))loopnoteunsel} else {//ヘッダの取得ができなかった場合API_statcode = -1}return API_statcode//適当な部分もある、UserStreamのデータ取得#deffunc getBody_US var p1wait 10p2Size = 3000sdim p2, p2Size//入手可能なデータ量を取得InternetQueryDataAvailable hRequest, varptr(API_rsize), 0, 0//バッファの初期化sdim API_bufStr, API_rsize+1sdim p1, API_rsize+1repeatInternetReadFile hRequest, API_bufStr, API_rsize, API_hsizep1 += strmid(API_bufStr, 0, API_hsize)wait 10if (API_hsize = 1)||(API_hsize!API_rsize)||(API_hsize=0) : breakloopreturn API_statcode#global#uselib "KERNEL32.DLL"#cfunc OpenProcess "OpenProcess" int,int,int#func GetExitCodeProcess "GetExitCodeProcess" int,int#define PROCESS_QUERY_INFORMATION $400 //OpenProcess時に使う。//コマンドライン解析用。http://lldev.jp/hsp/tips/miscellaneous.html#cmdlineprmsからDLしてください。#include "cmdline_parser/gm_cmdline_parser.hsp";サンプル用設定ファイル#include "SampleSetting.hsp"if CONSUMER_KEY = "" : mes "「SampleSetting.hsp」でConsumerKeyとConsumerSecretを設定してください。" : endif getarg(0,1)="" : mes "USA: 引数が不正です。" : end //引数が一つもない状態// 初期化TS_Init "TsubuyakiSoup Sample", CONSUMER_KEY, CONSUMER_SECRET, 20// 設定ファイルの有無確認xToken = ""xSecret = ""exist "Setting.txt"if strsize != -1 {notesel SFAnoteload "Setting.txt"if (Decryption(SFA, "SampleKey")=0) : dialog "ファイルの復号に失敗したため、読み込むことができませんでした。終了します。" : endnoteget xToken,0noteget xSecret,1noteunselSetAccessToken xToken, xSecret}if ( (xToken ="") or (xSecret = "") ) : dialog "「Sample01_OAuth.hsp」か「Sample02_xAuth.hsp」を実行して「Setting.txt」を作成してください。" : endrepeat //コマンドラインの2~の要素を、UserStreamAPIに対しての引数とする。if getarg(cnt+2,1)="" : breakArg.cnt = getarg(cnt+2,1)loopparentpid = int(getarg(1,1))hParent=OpenProcess(PROCESS_QUERY_INFORMATION, 0, parentpid) //親プロセス実行状況確認時に使う。if hParent=0 : mes "USA: error "+__LINE__ : wait 500 : end //OpenProcessが実行できなかった場合。api = getarg(0,1)UserStreamInit body, head, 0, api, Arg ; HTTPSbuf=""*main; 結果待ちのためのループwait 100getBody_US bodybuf+=bodygosub *compexitcode = 0GetExitCodeProcess hParent, varptr(exitcode) //親プロセスの実行状況確認if exitcode!$103 : goto *exit //親プロセスが閉じられていたら、*exitへ。wait 30goto *main*exit//親プロセスが閉じられたっぽい。mes "USA: exit"wait 500end*comp; 完了getBlockStr body, '{', '}', block, buf //bodyの{と}の間をブロックとしてblockに格納、余ったごみをbufへ。mes blockreturn