LimeChat2 で外部コマンド出力を受け取る

 LimeExecPlus と言うものを作りました。標準の Execute,ExecuteMinimize (Exec,ExecMin) では実行ができても出力は受け取れないようなので。
 これを使えば Perl,PHP,Ruby みたいなスクリプト言語でマクロを処理する事が出来るようになります (ただし、これらのスクリプト言語のインストールが必要)。

★ つかいかた

 4つの関数があります。

  1. ExecPlus
  2. ExecPlusSilent
  3. ExecPlusTimeout
  4. ExecPlusTimeoutSilent

 ExecPlus、ExecPlusSilent は $DllString の Input をそのまま実行します。
 だからと言って調子に乗って %m (受信メッセージ) を Input に指定して簡易ランチャーみたいなことをするとセキュリティホールになりかねませんので注意して下さい (条件部のユーザが %me (自分) だけならまだ大丈夫かも)。でも万が一この DLL を使って大変な事になっても責任はとれません。

1. ExecPlus, ExecPlusSilent

 例えば、

動作: Send
送信先: %f
動作の情報: $DllString(LimeExecPlus.dll,ExecPlus,test.exe %m)

 とすると、DLL と同じフォルダにある「test.exe」に引数として受信メッセージを付けたものを実行し、発言を受けたとこに出力します。同じ要領で

$DllString(LimeExecPlus.dll,ExecPlus,php test.php %m)

 とすると、環境変数 PATH が通っていれば php ファイルが実行できます (PHP.exe へのフルパスを指定すれば環境変数は弄らなくても済みます)。

 もし、実行に失敗すると

ERROR: CreateProcess failed.

 のような文字が (送信先、この場合は発言を受けたとこに) 出力されます。エラーメッセージを切るためには ExecPlusSilent を使います。

2. ExecPlusTimeout, ExecPlusTimeoutSilent

 しかし、LimeChat の DllString の性質上、実行が終了するまで LimeChat が反応しないため、外部実行ファイルがフリーズすると LimeChat も巻き添えを食らってフリーズします。
 これを防止するため、普段は ExecPlusTimeout を使うとよいかもしれません。例えば

動作: Send
送信先: %f
動作の情報: $DllString(LimeExecPlus.dll,ExecPlusTimeout,1000 test.exe %m)

 とすると、1000ミリ秒 (=1秒) 経っても実行が終わらない場合は放置して、エラーメッセージを出力した後 LimeChat に制御を戻します。ExecPlusSilent と同様に ExecPlusTimeoutSilent にするとエラーメッセージは出力されません。
 実行が遅い場合は EXE に変換すると軽くなるかもしれません (例えば Perl,PHP,Ruby いずれも EXE への変換アプリが存在します)。

3. ヒント
  • 動作毎にプロセスを生成する事になるので頻繁にイベントを起こすと動きがぬるくなります。「反応条件」で絞ってあげてください。
4. 既知の不具合
  • 動作で Send を選択して複数行出力しようとしてもできない
    • LimeChat の仕様で、改行すると次の行で NOTICE が自動的に付加されずそのまま送信されてしまうようです。動作を Raw にしてスクリプト側に発言を受けたチャンネルを引数として渡してうまく処理するしかないかも。
  • % を含む文字がちゃんと出力されない (例: URLエンコード文字列)
    • LimeChat の仕様で、「動作の情報」の文字列はマクロ変数展開の対象となります (例: %a,%1,%2...)。うまく置換して下さい。PHP ならこんな感じ?

ereg_replace("%([0-9acdfhlmnstuy])","%%\\1",$output);

    • 大文字は展開されないので放置で良いようです。