TwitterのUserStreamを取得して、どんどんとmesしていくスクリプト。
hspextのpipeexec命令でも使って、別プロセスとして動かすことを想定して作りました。
固まることが多々あります。だからpipeを使えってことなんですけども。
TwitterのUserStreamを取得して、どんどんとmesしていくスクリプト。
hspextのpipeexec命令でも使って、別プロセスとして動かすことを想定して作りました。
固まることが多々あります。だからpipeを使えってことなんですけども。
#runtime "hsp3cl" #packopt name "USA" #module #defcfunc strCnt str p1, str p2 string = p1 count=0 : i=-1 repeat i = instr(string, i+1, p2) if i=-1 : break count++ loop logmes "21" return count #deffunc getBlockStr str p1, int p2, int p3, var block, var other string = p1 count= 0 : i=0 sdim p2_s poke p2_s, 0, p2 head=instr(string, 0, p2_s) if head=-1 : block="" : other=string : return block repeat ,head if peek(string, cnt)=$00 : return "-1" if peek(string, cnt)=p2 : count++ if peek(string, cnt)=p3 : count-- if count=0 : break i++ loop block=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 p1 sdim p2 API = p4 if vartype(p5) != 2 : return 0 hConnect = 0 //InternetConnectのハンドル hRequest = 0 //HttpOpenRequestのハンドル API_statcode = 0 //リクエストの結果コード API_p1Length = 0 //データ長 API_rsize = 1024 //バッファ初期値 API_hsize = 0 //取得したバイト数が代入される変数 dup TS_AccessToken,TS_AccessToken@TsubuyakiSoup dup TS_Consumer_Key, TS_Consumer_Key@TsubuyakiSoup dup TS_Consumer_Secret,TS_Consumer_Secret@TsubuyakiSoup dup TS_AccessTokenSecret, TS_AccessTokenSecret@TsubuyakiSoup dup TS_RequestToken, TS_RequestToken@TsubuyakiSoup dup 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_AccessToken SigKey = TS_Consumer_Secret+" "+TS_AccessTokenSecret if (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" : break if cnt = length(p5)-1 : TokenStr = TS_RequestToken : SigKey = TS_Consumer_Secret+" "+TS_RequestTokenSecret loop } } // シグネチャ生成 SigArrayMax = 6 + length(p5) sdim SigArray, 500, SigArrayMax SigNonce = RandomString(8,32) time SigTime SigArray(0) = "oauth_consumer_key=" + TS_Consumer_Key SigArray(1) = "oauth_nonce=" + SigNonce SigArray(2) = "oauth_signature_method=HMAC-SHA1" SigArray(3) = "oauth_timestamp=" + SigTime SigArray(4) = "oauth_token="+ TokenStr SigArray(5) = "oauth_version=1.0" repeat SigArrayMax - 6 SigArray(6+cnt) = p5(cnt) loop //ソート SortString SigArray //"&"で連結 TransStr = ""+ Method +" "+ Scheme +"://userstream.twitter.com/"+ VersionStr + API +" " repeat SigArrayMax if SigArray(cnt) = "" : continue TransStr += SigArray(cnt) +"&" loop TransStr = strmid(TransStr, 0, strlen(TransStr)-1) Signature = SignatureEncode(TransStr, SigKey) // データ整形 if (p3 = 1) { //POST PostStr = "" repeat SigArrayMax PostStr += SigArray(cnt) +"&" loop PostStr += "oauth_signature="+ Signature PostStrLen = strlen(PostStr) AddUrl = "" } else { //GET PostStr = 0 PostStrLen = 0 AddUrl = "?" repeat SigArrayMax AddUrl += SigArray(cnt) +"&" loop AddUrl += "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 = 3000 sdim p2, p2Size //ヘッダの取得 if ( HttpQueryInfo(hRequest, 22, p2, p2Size, 0) ) { //ヘッダの解析 notesel p2 repeat notemax noteget API_BufStr, cnt API_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))) loop noteunsel } else { //ヘッダの取得ができなかった場合 API_statcode = -1 } return API_statcode //適当な部分もある、UserStreamのデータ取得 #deffunc getBody_US var p1 wait 10 p2Size = 3000 sdim p2, p2Size //入手可能なデータ量を取得 InternetQueryDataAvailable hRequest, varptr(API_rsize), 0, 0 //バッファの初期化 sdim API_bufStr, API_rsize+1 sdim p1, API_rsize+1 repeat InternetReadFile hRequest, API_bufStr, API_rsize, API_hsize p1 += strmid(API_bufStr, 0, API_hsize) wait 10 if (API_hsize = 1)||(API_hsize!API_rsize)||(API_hsize=0) : break loop return 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を設定してください。" : end if getarg(0,1)="" : mes "USA: 引数が不正です。" : end //引数が一つもない状態 // 初期化 TS_Init "TsubuyakiSoup Sample", CONSUMER_KEY, CONSUMER_SECRET, 20 // 設定ファイルの有無確認 xToken = "" xSecret = "" exist "Setting.txt" if strsize != -1 { notesel SFA noteload "Setting.txt" if (Decryption(SFA, "SampleKey")=0) : dialog "ファイルの復号に失敗したため、読み込むことができませんでした。終了します。" : end noteget xToken,0 noteget xSecret,1 noteunsel SetAccessToken xToken, xSecret } if ( (xToken ="") or (xSecret = "") ) : dialog "「Sample01_OAuth.hsp」か「Sample02_xAuth.hsp」を実行して「Setting.txt」を作成してください。" : end repeat //コマンドラインの2~の要素を、UserStreamAPIに対しての引数とする。 if getarg(cnt+2,1)="" : break Arg.cnt = getarg(cnt+2,1) loop parentpid = 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 ; HTTPS buf="" *main ; 結果待ちのためのループ wait 100 getBody_US body buf+=body gosub *comp exitcode = 0 GetExitCodeProcess hParent, varptr(exitcode) //親プロセスの実行状況確認 if exitcode!$103 : goto *exit //親プロセスが閉じられていたら、*exitへ。 wait 30 goto *main *exit //親プロセスが閉じられたっぽい。 mes "USA: exit" wait 500 end *comp ; 完了 getBlockStr body, '{', '}', block, buf //bodyの{と}の間をブロックとしてblockに格納、余ったごみをbufへ。 mes block return