前回はログ取ったりリアクションをつけたりだけだったので、ちゃんとBOT風の動きができるようにしてみたい。
javascript実行
まずはHTML書き換えでメッセージを作る。
1 |
document.querySelector("textarea").innerHTML="test"; |
これはDOMを見ると変更されてるが、Discord画面上では変化がない。
こうすると表示に test と出てきた。
1 |
document.querySelector("textarea").value="test"; |
しかしウィンドウをクリックする(アクティブにする)と消えてしまう。
ページ遷移形でないものはたいていスクリプト制御してるので書き換えは無理そう。
入力イベントを発火させてみる(キー入力の偽装)。
1 2 3 4 |
var e = document.createEvent("Event"); e.initEvent("keydown"); e.keyCode = 65; document.forms[0][2].dispatchEvent(e); |
keyup, keypress, inputなど組み合わせて試すも変化なし。
手動入力したのちに以下を実行する(Enter入力イベント)と投稿できた。
1 2 3 4 |
var e = document.createEvent("Event"); e.initEvent("keypress", true, false); e.keyCode = 13; document.forms[0][2].dispatchEvent(e); |
イベント自体が阻害されているわけではないみたい。
casperjsのログイン自動化で同じようなことがあった気がするので調査。
CasperjsのこことPhantomjsのここを見ると1文字ずつkeydown, keypressしている。
参考にしてあれこれ試すも失敗。
最後にmonitorEventsを利用して、実際のkeydownと比較しつつ寄せていく。
1 2 3 4 5 |
var opt={key:"a", char:"a",keyCode:65,bubbles:true,code:"KeyA",composed:true,view:window,sourceCapabilities:new InputDeviceCapabilities(),cancelable:true}; var ev1 = new KeyboardEvent("keydown",opt); var ev2 = new KeyboardEvent("keyup",opt); document.forms[0][2].dispatchEvent(ev1); document.forms[0][2].dispatchEvent(ev2); |
左が手動(普通に”a”と打ち込む)、右がスクリプトによる入力。
あとはisTrusted あたりを偽装できればだけどセキュリティ的に無理そう。
どうもブラウザが実行主体で制限しているような気がする。
過去に偽装してるものも見つけたけど今は出来なかった。
直接打ち込むのは無理そうなので、1つ上の次元で何とかしてみる。
ブラウザの自動操作(casperjs)
環境があるので使ってみましたが基本的に監視には向いてないです。
これはブラウザ操作とhtml操作のスクリプトが分離しているからです。
getHTMLでとってきたDOMはもう変化しませんし、evaluateメソッドで走らせたスクリプトの結果を受け取るのは面倒です。
なので独自メソッドを使って書き直します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
function sendMsg(csp,msg){ csp.sendKeys('textarea', msg, {reset: true,keepFocus: true}); //なぜかこれだと送信できない //csp.sendKeys('textarea', casper.page.event.key.Enter, {reset: false,keepFocus: true}); csp.evaluate(function(){ var e = document.createEvent("Event"); e.initEvent("keypress", true, false); e.keyCode = 13; document.forms[0][2].dispatchEvent(e); }); } function observe(csp){ var lng = $(csp.getHTML(".messages.scroller",true)).find(".markup").length; csp.waitFor(function check() { return this.evaluate(function(lng) { return document.querySelectorAll(".messages.scroller .markup").length != lng; },lng); }, function then() { var msg = $(csp.getHTML(".messages.scroller",true)).find(".markup").last().html(); casper.echo(msg); switch(msg){ case "hoge" :sendMsg(csp,"huga");break; case "ぬるぽ" :sendMsg(csp,"ガッ");break; } observe(csp); },function timeout() { //do nothing or observe(csp); },30*60*1000); } casper.then(function(){ casper.echo("wait start"); observe(this); }); |
ログイン等は前回と同じ。
waitForメソッドを使って30分間の監視してます。
ちなみに実装だけならcasperjsのループ処理で作った方が簡単です。
1 2 3 4 5 |
function loop(){ //差分検出処理 if(!isEnd)casper.wait(1000,loop); } loop(); |
処理としては”hoge”と書き込めばhugaと返し、「ぬるぽ」に「ガッ」します。
自身の書き込みも拾ってますが前回同様に名前で判定したりして変更できます。
書き換えるとボット風の行動が可能ですが、処理を間違えれば連投などでチャンネルやディスコードからBAN食らうかもしれないので気を付けないといけません。
用途としては、ちょっとしたチャネル内の独自ゲームとか集計とか。