Skypeのチャットに自動応答するJavaScriptを簡単に作れるようにする
前回書いてた、
一本のプログラムだけが走っていて、チャットのメッセージを監視し、条件に合ったメッセージを見つけたら決められたスクリプトを呼び出すようなのを作りたい。
つまり、自動応答のコアになるようなやつ。あとは実際の応答ロジックはプラグイン式に手軽に書く。
Skypeのチャットに自動応答するJavaScript - 今日覚えたこと
というのを作った。
autoreply.js
まずはメインとなるスクリプト。このスクリプトは、設定を読み込んだら無限ループをして、Skypeのチャットを監視する。そして何か発言を受信したら、設定に従って外部スクリプトを呼び出し、その処理結果を自動的に発言するもの。
// config var conf = eval_file('autoreply.config.json'); // attach Skype var skype = new ActiveXObject('Skype4COM.Skype'); WScript.ConnectObject(skype, 'Skype_'); skype.Attach(); // main while(true){ WScript.Sleep(1000); } // event function Skype_MessageStatus(msg, status){ if(status == skype.Convert.TextToChatMessageStatus('RECEIVED')){ var user = msg.FromDisplayName; var body = msg.Body; var timestamp = msg.Timestamp; var chat = msg.Chat; WScript.echo('received: ' + [chat.FriendlyName, user, timestamp].join('::')); WScript.echo('body: ' + body); for(var i = 0; i < conf.length; i++){ var item = conf[i]; if((!item.chat || item.chat.test(chat.FriendlyName)) && (!item.user || item.user.test(user)) && (!item.body || item.body.test(body))){ WScript.echo('file: ' + item.file); var f = eval_file(item.file); var reply = f(user, body); if(!reply) continue; chat.SendMessage(reply); WScript.echo('reply: ' + reply); } } } } // eval function eval_file(filename){ var fso = new ActiveXObject('Scripting.FileSystemObject'); var path = fso.GetParentFolderName(WScript.ScriptFullName); var stream = fso.OpenTextFile(fso.BuildPath(path, filename), 1, false, -2); var t = stream.ReadAll(); var result = eval('(function(){ return (' + t + '); })();'); stream.Close(); return result; }
autoreply.config.json
設定はJSONで書く。
[ { chat: /チャットタイトルの条件の正規表現(省略可)/, user: /発言したユーザIDの条件の正規表現(省略可)/, body: /発言内容の条件の正規表現(省略可)/, file: '条件に合致したときに呼び出すjsファイル.js' }, { // 複数の条件が指定できる。 } ]
こんな感じの書式。chat, user, body には正規表現を指定して、その条件に合致する発言を受信したときに、file に指定されたJavaScriptを呼び出すわけだ。
条件は省略可能なので、fileだけを指定することも可能。その場合、全ての発言に対してスクリプトが呼び出される。
スクリプト
呼び出されるスクリプトは、無名関数の形で書く。2つの引数を取り、nullまたは文字列を返す。
function(user, body){ if(body == 'おはよう'){ return 'おはようございます'; }else{ return null; } }
例えば上記のような感じ。
この例は、受信した内容が「おはよう」であった場合に「おはようございます」を返している。returnで返した文字列が、自動応答の内容として発言されることになる。nullを返した場合は何も発言されない。
要は、何か文字列を返すような無名関数を書けばいい。それだけ。
使い方の例 : 天気予報
例えば、「天気」の文字が含む発言があった場合に、天気予報を返すような自動応答プログラムは、以下のように作る。
autoreply.config.json
設定ファイルはこんな感じ。
[ { body: /天気/, file: 'weather.js' } ]
/天気/ の正規表現にマッチしたときに weather.js を呼び出す設定。
weather.js
そして肝心の weather.js は以下。
function(user, body){ var xmlhttp = new ActiveXObject('Msxml2.XMLHTTP'); var uri = 'http://weather.livedoor.com/forecast/rss/4/25.xml'; xmlhttp.open('GET', uri, false); xmlhttp.send(null); if(xmlhttp.status != 200) return null; var result = []; var items = xmlhttp.responseXML.getElementsByTagName('item'); for(var i = 0; i < items.length; i++){ var category = items[i].getElementsByTagName('category')[0].firstChild.nodeValue; var desc = items[i].getElementsByTagName('description')[0].firstChild.nodeValue; if(!/PR/.test(category)) result.push(desc); if(3 <= result.length) break; } return result.join('\n'); }
livedoorがWeather Hacksで提供している天気予報のRSSを取得して、その中から最新3件分の天気予報を返却している。