# KSirc ハンドブック

Andrew
Stanley-Jones

    asj@chowtown.cban.com

26/05/2000
0.09.00

この文書は KSirc 0.9 について記述されています。

KDE
KSirc
irc
Internet relay chat

## インストール

バイナリインストール

- KDEを使用していない場合

      	cd /usr/local/
      	tar -zxvf <ksirc file>
      	tar -zxvf kdehelp-netscape.tgz

  (Ksirc/Sirc ホームページをご覧下さい。)

  "ksirc"と入力するとksircが起動します。 perl5がインストールされていなければなりません。

  オンラインヘルプが必要でKDEがない場合は、netscapeが必要です。ksirc.org/pub/ksircからkdehelp-netscape.tgzを入手して下さい。

- KDE上での使用

      	cd $KDEDIR/..
      	tar -zxvf <ksirc file>

  "ksirc"と入力するとksircが起動します。

## kSirc カラー

KSircは、mIreにより使用されているカラー体系に従い、日常の利用においてより強力になるように若干変更を加えています。

    <fg> == 前景色
    <bg> == 背景色
    &lsqb;&rsqb; == オプション

### mIrc互換

フォーマット：

- 0x03<fg>&lsqb;,<bg>&rsqb; 前景色と背景色を設定する

- 0x03 THAT行に対するデフォルトをリセットする

### KSirc独自

フォーマット：

- ˜<fg>&lsqb;,<bg>&rsqb; 前景色と背景色を設定する

- ˜c tpデフォルトをリセットする

- ˜b ボールド・フォントを設定する

- ˜u アンダーラインを設定する

- ˜i イタリックを設定する

- ˜r 反転を設定する

なぜKSireでは 0x03 (ˆC) の代わりに ˜ を使用するように変更したのでしょうか？ これは、スクリプトで 0x03 を使用するのが難しく、必ずしもすべてのC関数がこれを好んでいるようには見えないからです。また、 ˜<letter> は、mIreの機能変更を無駄にせずに、もっと多くのコマンドを作ることができます。

### カラー番号

1. 白

2. 黒

3. 青

4. 緑

5. 赤

6. 茶

7. 紫

8. 橙

9. 黄

10. 明るい緑

11. 青緑

12. 明るい青緑

13. 明るい青

14. 桃色

15. 灰色

16. 明るい灰色

### ボールド、アンダーライン、反転、およびカラーの送信方法

下記のキーの組み合わせを使用することにより、コントロール・コードをテキストに挿入できます。

- Control-B ボールド・テキスト

- Control-U アンダーライン付きテキスト

- Control-R 　反転テキスト

- Control-K カラー・テキスト

- Control-O プレーン・テキスト

### 例

文章の1つの単語にアンダーラインを付けるには、下記のようにします：

1. Control-U を入力する

2. 単語を入力する

3. 再度 Control-U を入力する

開始コードと終了コードに囲まれたテキストのみが影響を受けます。他のすべてのコントロール・コードでこの方法を使用できます。

Control-K コントロール・コードは、カラー番号を指定できる点が少し異なります。文章の1つの単語にカラーを付けるには下記のようにします。

1. Control-K を入力する

2. 0〜15の間の数を入力する

3. 単語を入力する

4. 再度 Control-K を入力する

単語の背景色も変更したい場合は、1つの数値の代わりに2つの数値をカンマで区切って入力する必要があります。最初の数値はテキスト・カラー、2番目の数値は背景色です。カラーの範囲は0〜15です。リストは前の項にあります。

テキストを複数のコントロール・コードで囲むこともできます。たとえば、単語をボールドにし、アンダーラインとカラーを付けることができます。

## フィルタ

### フィルタ規則とフィルタの作り方

ちょっと判断できないというなら、待ってください。躊躇を吹き飛ばすような素晴らしいフィルタ・ビルダを作りたいと思います。 けれどもそれにはしばらくかかります。

フィルターは、置換の際、"match"する文字列を探してから、"From"と"To"を使用しようとします。サブステーションを使用して両方のオペレーションを簡単に行うことができれば、置換をより細かくコントロールできます。match、from、toは、すべて perl の 正規表現(regular expressions)です。規則は降順で評価されます。トップの規則が最初に評価され、次にトップから2番目の式、というように進みます。すべての文字列は、下記のように評価されます：

$<name> は、環境変数 <name> に展開されます。 これは、規則を挿入したときにただちに行われ、その時点以降変更されません。したがって、これはおそらく限定された値になります。

$$<name> は、マッチの際にperlの $<name> 変数に置き換えられます。これは、置換の中で$1、$2のような部分文字列とすることも、あるいはsircのもとで利用できる通常の変数（$nick、$channelなど）とすることもできます。

行の前に1回だけ使用された ˜<name>˜ は、その行のテキストを <name> と呼ばれるウィンドウに送信します。このウィンドウが存在しない場合、フォーカスのあった最後のウィンドウに送られます。 いくつかの特殊なウィンドウがあり、すべて1個の"!"が前に付いています。

!default

  現在のデフォルト・ウィンドウ。存在が保障されています。

!all

  すべてのウィンドウに送信します。テキストがどのように解析されるかに応じて、必ずしもすべてのウィンドウに表示されるとは限りません。たとえば、チャネル・ウィンドウは、ニックがチャネルにない限り、part/quitを表示しません。

!discard

  テキストを破棄します。

式の残りの部分は通常の perl の 正規表現として扱われます。 perlre の manページをよく読むと役に立つかも知れませんが、正規表現の基本的理解が最も要求されます。

### 例:

1. すべての boren を boren から BoreN に変換したい

       Match: .*
       From: boren
       To: BoreN

   まっすぐ前に進み、すべてのものとマッチし、borenをBoreNに置き換えます。

2. 中にborenを含むすべてのものとマッチさせ、"boren"というウィンドウに送信したい

       Match: boren
       From: ^
       To: ˜boren˜

   "boren"を探し、見つかった場合、その文字列(ˆ)の先頭を ˜boren˜ に置き換えます。

3. &num;2 の結果、その文字列がすでに `˜somewindow˜` を持っていた場合、2つの `˜boren˜˜somewindow˜...` を持つことになります。その場合、代わりに下記のようにできます。

       Match: boren
       From: ^(?:˜\S+˜)
       To: ˜boren˜

   見たとおり、from行がやや複雑になっています。これは、 "`˜\S+˜`"の0個または1個のコピーとのマッチを指定します。つまり、1個のチルド、1個以上の非ホワイトスペース、その後にもう1個のチルドです。しつこく言えば、 `(*:˜\S+˜)`は、 0個または1個以上のチャネル・ディレクティブのマッチを指定しており、この場合、前の規則は壊されます。

4. Server killメッセージが出て、その後、長いおもしろくないものがだらだら続きます。 dalnetでの基本メッセージは下記のようなものです。

       *** Notice -- Received KILL message for BOBO!ANDY@line82-basel.datacomm.ch
       from NickServ Path: empire.ny.us.dal.net[209.51.168.14]!trapdoor.ca.us.dal
       .net[206.86.127.252]!caris.ca.us.dal.net[208.1.222.221]!services.dal.net[2
       008.1.222.222]!services.dal.net (NickServ Enforcement)

   このようなメッセージが大量に出た場合、画面を飛んで流れるメッセージすべてを見たくないでしょう。1度に1ビットずつそれらを処理するために、3つの規則を作成します。これをもっと少ない規則で行うこともできますが、これは基本的規則構造を分かりやすいステップで示そうというものであり、複数の規則を使用してメッセージを解析する方法を示しています。最初のステップはメッセージのPath:部分を削除することで、例4になります。

       Match: ^\*\*\*.* KILL message for.*
       From:  Path: \S+
       To: .

   Matchは、 `***`で始まるメッセージを探します。 *は、単独では直前の文字の0個または1個以上を意味するので、\をつけて引用にする必要があります。 `.*` は、 `" KILL message for"` を見つけるまでのすべてのものとのマッチを意味します。これにより、 `-- Received...` などに連結するのを避けることができます。末尾の `.*` は、行の最後までのすべてのものとのマッチを指定します。（必須ではないと思う）

   From は、スペース、Path:、スペース、およびホワイトスペースでないすべての文字をToに置き換えることを指定します。To は `"."` なので、パス全体が1個のピリオドに変わります。

   これでメッセージは下記のようになります。

       *** Notice -- Received KILL message for BOBO!ANDY@line82-basel.datacomm.ch
       from NickServ. (NickServ Enforcement)

   `NickServ` の後の新しい `"."` に気づきましたか?

5. これでメッセージはだいぶ簡潔になりましたが、NickServeからのKILLは実際には重要でないので、これらを `!discard` ウィンドウに転送することにしましょう。

       Match: ^\*\*\*.*KILL message.*\(NickServ Enforcement\)
       From: ^(?:˜\S+˜)
       To:  ˜!discard˜

   Match規則は、KILLメッセージを探し、NickServからのメッセージであることを確認します。 `\(` と `\)` に注目してください。 2個の `()` は 正規表現(regular expressions) で使用されているので、 引用にする必要があります。これは例3と非常によく似ています。

6. これで、NickServのKILLをすべてふるい出しましたが、メッセージはまだ一目で読みやすいものではありません。 そこで、下記のように並べ替えてみましょう。

       *** [KILL] <KILLER> killed <KILLED> (reason)
       Match: \*\*\*.*KILL message
       From: \*\*\*.*for (.*?) from (.*?)\. \((.*?)\).*
       To: *** [KILL] $$2 killed $$1 ($$3)

   このmatchは、 `***<something>` KILL message を探します。 さっき末尾に`˜<window>˜` を追加しているかも知れないので、`ˆ`は使用できません。

   from行は、あまり面白いものではありません。 `"for (.*?) "` は、forという単語の後に何かのテキストが付いているものを探します。 `.*?` は、改行以外の0個または1個以上の何かとのマッチを探しますが、必須ではありません。最初の終了条件が見つかると、最後でなくても停止します。つまり、これはスベースまでのすべてのものとマッチします。囲んでいる `()` は、内容を保存することを指定します。 各 () は、マッチしたデータを `$&num;` に保存します。 ここで `&num;` は最初の文字列を1として、順に大きくなります。この場合、 `$1` には、KILLされた人のニック／ユーザ情報が入ります。 `$2` にはKILLした人の名前が入ります。 `()` の間にKILLの理由があります。ここで、 `(` と `\(` はやや混乱を招きそうです。 `\(` は実際の文字 `'('` とマッチすることを忘れないでください。

7. 生活をカラフルにする方法です。KSircにカラーを付けたいとします。カラー情報については、 色の章 を見てください。ここでは、各行で `<NICK>` の間のニックを強調するためのフィルター規則を示します。

       Match: ^(?:˜\S+˜)<\S+>
       From: <(\S+)>
       To: <˜4$$1˜c>

   ニックを取り出し、2個の `<>` の間にカラー番号4を追加します。 `˜c`はカラーをクリアします。

## キー

これは、Ksircのもとで利用可能なショートカット・キーとコマンド・キーのリストです。

- Alt-F Fileメニュー

- Alt-E Edit メニュー

- Ctrl-N 新しい Channel/Query ウィンドウ

- Ctrl-T ティッカー・モード

- Ctrl-Q 終了

- Ctrl-X ウィンドウの切り取り

- Ctrl-V 貼り付け

- Ctrl-Enter メッセージを送って来た前の人

- Ctrl-Shift-Enter メッセージを送って来た次の人

- Ctrl-K カラー・モードの開始

- Ctrl-U アンダーラインの開始／終了

- Ctrl-I イタリックの開始／終了

- Ctrl-B ボールドの開始／終了

- Ctrl-R 反転の開始／終了

- Tab ニック完了

## Sirc クライアントプログラミング

注意：これを理解するには、perl(プログラミング言語です。詳しくはperlのmanペー ジをご覧ください)を理解している必要があり、READMEを読んでいなければなりません。

sircスクリプトの有用な例として、`n0thing.pl`ファ イルを見てください。sircスクリプトがどのようなことを行うのか気になったら、こ こで定義されている機能を理解してみてください。

### コマンド

`/loaded`スクリプトと`.sircrc.pl`で、新しいコマンドを定義しperlに実装することができます。

これらのスクリプトは実際にperlコードのファイルで、sircのコンテクストに取り込まれます。

新しいコマンドを定義するのにしなければならないことは、どのような要求も行ってくれる`cmd&lowbar;yourcommandname`でsubを定義し、`&addcmd("yourcommandname");`を呼ぶことです。

また、`&addhelp("yourcommandname", "First line of help\nSecond line of help...")`をコールすることでコマンド用にいくつ かヘルプを定義することもできます。

subはその全引数をグローバル変数`$args`(非解析)で、その名称を`$cmd`で、全コマンドラインを`$line`で得ます。

sircクライアントから数々のルーチンを使用することもできます。

&load("file");

  sircスクリプトをロードし、@loadpathを検索します。拡張子".pl"はオプションです。

&dosplat;

  *が`$args`の最初の文字の場合、*をカレントチャ ンネル名にします。

&getarg;

  $newargで`$args`の最初の文字を、残りを`$args`で得ます。

&yetonearg;

  同様のこと、既に一つある場合、`$args`で後置を削除します。

&eq("txt1", "txt2");

  大文字、小文字の区別をしないのテスト。

&sl("text");

  テキストの一行をサーバに送ります。(最後の`"\n"`は自動的に追加されます。)

&tell("txt");

  `"\n"`を追加し、テキストをスクリーンに 送ります。無表示モード以外でです。

&print("txt");

  無表示モードであるかないかに関わらず、テキストに`"\n"`を追加し、テキストをスクリーンに送ります。

&getuserline("str", "prompt");

  "str"を表示し、ssfeを使っている場合、臨時プロンプトとして"prompt"を置きます。そして、ライン用にユーザを促し、その情報を`$&lowbar;`に返します。

&getuserpass("str", "prompt");

  パスワードのプロンプト状態と同様です。ssfeはパスワードを反映しません。

&dostatus;

  ステータス行を再表示します。

&msg("nck", "msg");

  メッセージを送り出力します。送り先は、ニック, チャンネル, =ニック(DCC CHAT)です。

&notice("nck", "msg");

  警告を送り、それを出力します。送り先は、チャンネルまたはニックです。

&say("msg");

  カレントチャンネルに何かを発言し、それを出力します。

&describe("nck", "msg");

  `/describe`を送り、それを出力します。

&me("msg");

  カレントチャンネルに働きかけ、それを出力します。

&connect($fh, "host", port);

  与えられたホストとポートにtcp接続を開きます。最初の引数である`($fh)`は変数でなければならず、`&connect`はその変数を接続に関係するファイルハンドルの値に 設定します。`&tell's`はメッセージで、エラーがあった時は0を返し、その他の場合は１を返します。

&listen($fh, port);

  与えられたポートにリスニングソケットの境界を開きます。指定したポー トが0の場合(または、第二引数が全く渡されない場合)、システムにポートを選択させます。最初の引数は変数でなければならず、`&listen`はその変数をリスニングソケットに関係しているファイルハンドルの値に設定します。&tell'sはメッセージで、エラーがあった時は0を返し、その他の場合はソケットが聞いているポートを返します。

&accept($nfh, $ofh);

  ファイルハンドル`$ofh`(これはリスニングソケットに言及します)上の接続を受け入れ、`$nfh`にそれを返します。`$nfh`は変数でなければならず、`&accept`によって変更されます。`$ofh`は、`&accept`によって自動的に閉じられます。ブール値を返しますが、どのような場合にもエラーメッセージを表示しません。

&resolve("address");

  ホストネームをパックして&lowbar;addrで分析します。(つまり、IPアドレスを表示する4バイト配列。) 引数はホストネーム、点で区切られた四つの記数法で書かれたIPアドレス、アドレスを表す(大きな)数字をとることができ、ネットワーク順に32ビットの数として"読まれ"ます。解析に失敗した場合、偽の結果(""、0 または undef) を返します。

  `&resolve`が返す内容から点で区切られた四つの記数を得るには、`join(".", unpack("C4", &resolve("whatever")))`を利用します。

&newfh;

  ファイルハンドルとして使用する新しい名前を返します。

&doset("variable", "value");

  SET変数に値を設定します。その値は検証され、不正であったり存在しない場合は効 果はありません。これは、もしかするとそれ自体を定義する場合を除いて、スク リプトがSET変数の値を変更すべき唯一の方法です。

&docommand("command");

  キーボードから入力しているかのようにコマンドラインを処理します。"/"を導く*single*はコマンド上のエイリアス/機能拡張を使用禁止にします。

  *注意*これは再帰的にそれ自体からコマンドディスパッチャをコールします。これはきわめてよくないことです。ループに対するテストはありますが(再帰の制限で、20にセットします)、スクリプトが動作するかどうかは自分次第です。Perlは強力な制御構 文(ircIIとは異なり)を持つ言語ですが、このレベルでの反復はできる限り避けるべきでしょう。

グローバル変数にアクセスすることができます。ただし&percnt;setで読み込まれ、 &dosetによって書き込めるように、SET変数に変わってしまっているため、それら の変数の中には削除されてしまっているものもあります。

特に明記しない限り、これらの変数はスクリプトで読み込み専用として扱われるべきです。

$version

  sircのバージョン - これは常に数字で、ユーザの機能では決して変更されません。

$add&lowbar;ons

  ロードされる追加モジュール。スクリプトは、"+scriptname"を追加することができます。

$restrict

  sircが制限(安全な)モードで稼働している場合、真を設定します。こうするとシェルや ファイルシステムへのアクセスを禁止します。

$maxrecursion

  "max recursion exceeded"エラーが発生する前に、&docommandの回数が再帰的にコールされます。(これを変更することはできますが、SET変数になるだろう今後のバージョンでの動作は保証されません。)

$nick

  現在のニック

$server

  現在のサーバ

@channels

  存在するチャンネルのリスト

$talkchannel

  現在のチャンネル(使用していない場合は''で表示されます)

&percnt;mode

  接続している別のチャンネルのモードによる連想配列。チャンネルの名称は全て小文字で、モードは+や-を除いた文字の文字列で、'k'または'l'も除かれます。というのは、それらが別々に扱われているからです。どのようなモードもないチャンネルの値は''で、接続していないチャンネルの値はundefです。

&percnt;chankey

  チャンネルのキーです。チャンネルに誰もいない、または接続していない場合はundefです。チャンネルの名称は小文字です。

&percnt;limit

  チャンネルへの制限です。チャンネルに誰もいない、または接続していない場合はundefです。チャンネルの名称は小文字です。

&percnt;haveops

  ブールの連想配列です。チャンネル内でopsがある場合は真です。チャンネルの名称はご存知の通りです。

$umode

  ユーザーモードです。+や-を除く文字列です。

$query

  問い合わせている相手の情報です。誰もいなければ''。

&percnt;aliases

  定義置換エイリアスの連想配列です。エイリアスの名称はCAPSにありま す。

&percnt;set

  SET変数値の連想配列です。この変数名もCAPSにあります。

&percnt;notify

  通知リストの連想配列です。与えられたニックの値は"不在"の場合は0、もしくはこの ニックの最新通知時間です。

$bindaddr

  sircが実行されている限り、接続の出力先につながっているマシンのこれはのIPアドレスです。 "localhost" SET変数を変えるとこのIPアドレスは変わり、sircがsocksサポートで実行している場合は、プロキシマシンのIPがセットされます。`$bindaddr`は4バイトの文字列で、`unpack("N", $binaddr);`を使って整数を取り出せる(DCC CHAT/SENDで用いられるように)パックされた`in&lowbar;addr;`や、`join(".", unpack("C4", $bindaddr));`を使って点で区切られた数を表示します。

特に明記しない限り、コマンドやフックはそれらに渡されるパラメータを変更すべ きではありません。(つまり、`$&lowbar;[1]="some value"`のようなことを行うことです。)それらのローカルコピーを変更したいなら、`local(...)=@&lowbar;;`から始めるべきでしょう。

また、スクリプトがグローバル変数を使うようなら、それらがsirc自体でのクラッシュがしないようにしてください(同様のことがファイル記述子名や手続き上もいえます。)良い規則は、全てのこれらの変数や処置にスクリプト名やその中の2、3文字で始まる名称を与えるようになっていることでしょう。例えば`n0thing.pl`では、全スクリプトのグローバル変数や内部処置に"n&lowbar;"で始まる名称がついています。

例は、これはファイルにいれられ、チャンネルを指定するとyeekするコマンドの`/load'ed`ディレクトリです。ニックも同様です。

    sub cmd_yeek {
      &dosplat;		# 第1 argが * ならば、それを $talkchannel に置き換える
      &getarg;		# $newargで第1 argを得る
      local($channel)=($talkchannel);	# デフォルトでは、$talkchannelと話す
      if ($newarg =˜ /^[\#\&]/) {		# もし第1 arg が # または & で始まっているなら
        $channel=$newarg;			# 代わりにそこで話す
        &getarg;				# そして、特別な arg を得る
      }
      if ($newarg) {	# 誰に yeek しているか、指定したかのチェック
        &describe($channel, "look at $newarg and *yeeeks*");
      } else {		# そうでない場合
        &describe($channel, "*yeeks* at the crowd");
      }
    }

    # \cb は、perl では ^B と表記します。
    &addcmd("yeek");
    &addhelp("yeek", "Usage: \cbYEEK\cb [<channel>] [<nick>]
    Yeeks at the given nickname or at the whole channel.
    Examples: /yeek someone
              /yeek * someone
     	  /yeek #channel
     	  /yeek #channel someone");

### フック

`.sircrc.pl`からと同様に、`/load'ed`スクリプトから、指定されたイベントが発生する際コールされるsubsを定義することができます。これはircIIの`/on's`と同等です。

フックを宣言するには、`"hook&lowbar;somename"`と 呼ばれるサブルーチンを定義しなければなりません。これは`"hook&lowbar;type"`タイプのフックがトリガーされる際に望むこ とは何でも実行し、`&addhook("hook&lowbar;type", "somename");`をコールします。

フックを削除するには`&remhook("hook&lowbar;type", "somename");`をコールし ます。

全て3桁で数なので、数字フックもまた利用することができます。それらのう ちの一つを宣言するには、`"hook&lowbar;somename"`と 呼ばれるサブルーチンを定義します。このは、希望に添って行い、`&addhook("xxx", "somename")`をコールします。 xxxは、数字フックの返答数値です。

フックからコールされるSubsは、機能面で上記にリストされた同関数や変数、さらにいくつかの特別なもの(適用されるところならどこにでも)にアクセスします。

    $who		は、フックをトリガーしたニックです
    $user           は、ユーザ名に対応します
    $host		は、ホスト名に対応します

また、イベント用にディスプレイを(`&print`を使って)提供し、デフォルトを禁止しようとする場合、フックは変数`$silent`をセットすることもできます。これは、`"raw&lowbar;irc"`の他は、ircII`/on's`の`"ˆ"`スィッチと直接的に同等です。

`*`マークが付いているフックは、特別な変数 `$skip`も設定し、クライアンによって行を無視させることができます。一般的にこれはよくない考えです。ですからできる限り`$silent`を使ってください。これは、実際付随的ないくつかの機能を提供するフックのみ持ちうる可能性です。`"raw&lowbar;irc"`については、ircIIの`/on raw&lowbar;irc`上の`"ˆ"`スイッチと同等です。

次のフックが有効で、以下の引数でコールされます。

    action		ctcpアクションによって起動されます。
    		第1 argは送られるだろうニックもしくはチャンネルです。
    		第2 argはメッセージです。

    command	     *	コマンド入力するユーザよって起動されます。(/commandで
    		あるかテキストの一行であるかには関係しません。)
    		第1 argはユーザの行です。
    		このフックは、("print"や"status"のように)特別で、
                    これは、コマンドが解釈する内容を変えるために
                    その引数($_[0])を修正できます。
    		フックに$skip=1をセットすると、sircは
                    コマンドを無視します。

    chat_disconnect	dccチャットが消えた時起動します。(ユーザーがDCC CLOCE CHATを
    		使って閉じた場合は別です。)
    		第1 argはチャットと関連するニックです。

    ctcp	     *	あらゆるctcpで起動します。つまりクライアントが解釈する前で
                    結果としてctcpに答えます。
    		第1 argは送られるだろうニックやチャンネルです。
    		第2 argはctcpコマンドです。
    		第3 argは引数です。

    ctcp_reply	ctcpの応答で起動します。
    		第1 argは送られるだろニックもしくはチャンネルです。
    		第2 argはctcpコマンドです。
    		第3 argは引数です。

    dcc_chat	dccチャットで受信されたテキストによって起動します。
    		第1 argはニックです。
    		第2 argはテキストです。

    dcc_disconnect	dcc getやdcc sendが終了、または閉じた時実行します。
    		(ユーザーがDCC CLOSE GET/SENDを使って閉じた場合も含まれます。)
    		第1 argはチャットと関連するニックです。
    		第2 argはファイル名です。
    		第3 argは転送したバイト数です。
    		第4 argは転送に要した秒数です。

    dcc_request	受け取られるdccチャットや送信リクエストで起動します。
    		これはクライアントがリクエストを処理した後です。
    		あらゆる種類のauto-dccを実装したい場合に用いられるフックです。
    		第1 argはタイプ("CHAT" または "SEND")です。
    		第2 argはマシンアドレス(32ビット整数)です。
    		第3 argはポートです。
    		SENDが提供するDCC用に：
    		  第4 argはファイル名です。
    		  第5 argはファイルの長さです。

    disconnect	サーバへの接続を失ったり、/disconnectを使って中断すると
                    起動します。(/serverを使った際は別です。)
    		引数は渡されません。

    input	     *	クライアントがユーザに&getuserlineを使って一行用ユーザ
                    を必要とする際常に起動します。(つまり切断したり、
                    新しいニックを必要としたり、あるスクリプトが&getuserline
    		をコールしたときです。)
    		第1 argは"long"プロンプトです。
    		第2 argは"short"プロンプトです。
    		フックが$skipを設定している場合、&getuserlineは
                    ユーザになにも要求せず、$_の内容が返されます。

    invite		招待によって起動します。
    		第1 argは招待されたチャンネルです。

    join		参加によって起動します。
    		第1 argは$whoが参加しているチャンネルです。

    kick		キックによって起動します。
    		第1 argはキックされた人のニックです。
    		第2 argはキックアウトされたチャンネルです。
    		第3 argは理由です。

    leave		partsによって起動します。
    		第1 argは$whoが残っっているチャンネルです。

    mode		モードの変更によって起動します。
    		第1 argはチャンネルまたは変更が当てはまるユーザです。
    		第2 argはそれ自体モード変更です。

    msg		msgsによって起動します。
    		第1 argはメッセージです。

    nick		ニックを変更で起動します。
    		第1 argは$whoの新しいニックです。

    notice		通知によって起動します。
    		第1 argは送られるだろうニックやチャンネルです。
    		第2 argはメッセージです。

    server_notice	サーバからの通知で起動します。
    		第1 argは送られるだろうニックやチャンネルです。
    		第2 argはメッセージです。

    notify_signon	signon通知によって起動します。
    		第1 argはニックです。
    		$userや$hostは、意味あることは何も設定されません。

    notify_signoff	signoff通知によって起動します。
    		第1 argはニックです。
    		$userや$hostは、意味あることは何も設定されません。

    print	     *	画面にある行を表示すると起動します。
    		第1 argは出力される行です。
    		このフックは("status"や"command"のように)特別です。
    		出力される行の内容を変更するために引数($_[0])を
    		修正できます。
    		フックを$skip=1に設定すると、実際の出力は行われなく
    		なります。

    public		チャンネルへのnon-ctcpメッセージによって起動します。
    		第1 argはチャンネルです。
    		第2 argはメッセージです。

    raw_irc	     *	サーバラインによって起動します。
    		$who	は発信元(ユーザもしくはサーバ)です。
    		$user	はその人の名前です。(それがサーバからの場合は''です。)
    		$host	はその人のホスト名です。(上述と同様。)
    		第1 argはコマンドです。
    		第2 argは引数です。

    send_action	/meまたは/deを送ると起動します。
    		($who、$user、$hostはここでは適用しません。)
    		第1 argはニック/チャンネルです。
    		第2 argはアクションです。

    send_ctcp	ctcpを送ると起動します。
    		第1 argはctcpが送られているニックもしくはチャンネルです。
    		第2 argは完全なctcpテキストです。(タイプと引数)

    send_dcc_chat	dccチャットでテキストを送信すると起動します。
    		($who、$user、$hostはここでは適用されません。)
    		第1 argは送っているニックです。
    		第2 argはテキストです。

    send_text	/msgを送ったり、チャンネルで話したりすると起動します。
    		($who、$user、$hostはここでは適用されません。)
    		第1 argはニック/チャンネルです。
    		第2 argはmsgです。

    send_notice	通知を送ると起動します。
    		($who、$user、$hostはここでは適用されません)
    		第1 argはニック/チャンネルです。
    		第2 argは通知です。

    signoff		誰かが終了すると起動します。
    		第1 argは終了コメントです。

    status		sircが状況表示行を書き直すと起動します。(&dostatusが
    		コールされた結果のように、内部またはスクリプトのどちらかに
    		よってです。)
    		第1 argは指定した状況表示行です。
                    このフックは("print"や"command"のように)特別です。
                    状況表示行の内容を変更するために引数($_[0])を
                    修正できます。

    topic		誰かがトピックを変更すると起動します。
    		第1 argはチャンネルです。
    		第2 argは新しいトピックです。

    <3-digit nb>  * 特定のサーバの数値応答によって起動ます。
    		      第1 argはサーバが数値後に送り、解釈されなかったことです。
    		      (これは最後の引数の前に:がまだあるということです。)

例はファイルに入れられ、キックされたチャンネルに再加入するフックの /load'edディレクトリです。

    # auto-rejoin hook (自動再加入フック)

    sub hook_kicked {
      local($kicked, $where_from, $reason)=@_;
      					# argを用いたローカル vars
      if (&eq($kicked, $nick)) {		# キックされたら
        &sl("JOIN $where_from");		# JOIN をサーバに送信
      }
    }
    &addhook("kick", "kicked");	  	# フックの起動

その他の例としては、各々のメッセージでユーザ名やホスト名を表示す るためのものがあります。(/set printuhでよく行れます。)

    # userhost-on message hook

    sub hook_uhmsg {
      &tell("[\cb${who}!${user}\@${host}\cb] $_[0]");  # 全表示
      $silent=1;			# デフォルト画面の禁止
    }
    &addhook("msg", "uhmsg");	  	# フックの起動

### SET 変数

スクリプトはSET変数にアクセスすることができます。

- それらを読むには、`$set&lcub;"VARIABLE"&rcub;`を 見る必要があります。そこで変数名がcapsに書いてあります。

- それらを設定するには、`&doset("variable","value");`をコールします。変数名はどちらの場所に置かれてもよく、値がチェックさ れます。

スクリプトは、独自のSET変数も追加できます。デフォルト値や新しい値をチェックし て設定するフックを提供しつつです。これを行うには、スクリプトが次のようでなければなりません。

- `$set&lcub;"VAR"&rcub;="whatever";`を使ってデフォルト値として変数を設定します。 `&percnt;set`に設定用の値がない場合、sircはユー ザ`/set`に変数設定を認めません。

- `set&lowbar;somename`のようなsubを定義し、`&addset("var", "somename");`をコールします。 変数名は、どちらの場所でも渡すことができます。

SET変数のフックとして用いるsubは、第1引数として、指定された値を使ってコールされます。それらは、`$set&lcub;"VAR"&rcub;`の実際値を、与えられた値またはその他別の値に変更するかも(しないかも)しれません。規則上それらは、`&tell` anything とすべきではありません。また、不正な値は無視すべきです。

`$set&lcub;"VAR"&rcub;`に入るものは、人が読めるものでなければなりません。トグルのようなもののために`$set&lcub;"VAR"&rcub;`の値が"on"、"off"、またはそれに類するもので、`&doset`が(スクリプト内部へ)変数を0か1に設定できるようにしておくべきでしょう。それは、実際にスクリプトがチェックする値です。

### ユーザホストリクエスト

時には、機能上あるニックに対して全ユーザ名とホスト名を知る必要があります。フックでこういったことが生じ、ニックがアクションを起こした場合、ニックは`$who`に存在し、ユーザホストデータは既に`$user`及び`$host`に存在します。

一方、perl機能`&userhost`をコールしなければならない場合、そこに次のような3つの引数を与えます。ニックネーム、データが有効な時評価したいもの、そしてニックがIRC上で見つからない場合に評価したいもの。第3引数が省略されていると、sircはデフォルトメッセージである`"*?* somenickname not found on IRC"`を出力します。

sircの初期のバージョンと異なり、サーバから返答を得る前に短時間で複数のユーザホストリクエストを行うことが可能です。

例: 誰かの国コードを出力する機能

    # country code (国コード)

    sub printcountry {		# ホストの国コード出力

      if ($host =˜ /\.([^.]+)$/) {  # ホストの最終部分と一致
        local($c)=($1); 		# ローカル var $cにそれを出力
        $c="USA" if $c =˜ /^edu$/i;	# それが.edu ならば USA
        $c="USA (probably)" if $c =˜ /^com$/i || $c =˜ /^org$/i || $c =˜ /^net$/i;
    				# .org, .com または .net ならば
    				# おそらく USA 圏
        if ($c =˜ /^\d+$/) {	# 数値ならば
          &tell("*** out of luck, $who has an IP address :p");
    				# IPであると警告
        } else {			# その他の場合
          &tell("*** $who is in $c");
    				# 結果を報告
        }
      }
    }

    sub cmd_country {		# これがコマンドです

      &getarg;			# $newargに引数を得る
      if ($newarg) {		# そこにあると
        &userhost($newarg, "&printcountry;");
    				# &printcountry を用いてユーザホストの要請
    				# 取得のアクションとして
      } else {			# その他の場合
        &tell("*** Whose?");	# 警告
      }
    }

    &addcmd("country");		# コマンドをインストール

### タイマー

sircでは、ircIIの`/timer`機能のようにアクションを行うが、遅らせることができます。数秒後を指定できます。これは、その秒数までのみ正確です。

これを行うには、第1引数として待機秒数を用いて`&timer`機能を、第2引数として評価される文字列をコールします。

第3引数は、補充することができます。これはゼロ以外の数字でなければならず、 タイマーが参照番号として使われます。同参照番号を使った別のものが存在するタイマーを設定すると、最初の方が消去されます。数字が指定されていない場合、タイマーを削除することができません。

参照番号`$n`でタイマーを削除するには、 `&deltimer($n);`をコールします。

これでも十分にシンプルですが、例が必要なら、次を参照して下さい。： 10秒後に"hello"を出力するには、`&timer(10,"&tell('hello')");`とします。

終了したい場合`&timer(10, "&tell('hello')", 6);`とし、キャンセルするには`&deltimer(6);`とします。"6"が任意であることは言うまでもないでしょう。

### メインselect()ループにファイルハンドルを追加する

sirc 2.2のように、スクリプトはメインループにファイルハンドルを追加することができ、データが有効な場合コントロールするよう、それらにフックを設定することができます。

最初にファイルハンドルを開くかはスクリプト次第です。それは、ネットワーク接続、tty、パイプ (`open(FH, "program &verbar;")`にあるような)などを参照します。

ネットワークソケットを扱うと、perlの機能を使うよりもsircにより提供されるAPI(`&connect, &listen, &accept, &resolve, &newfh`や`$bindaddr`)を使用するこ とを強くお勧めします。これは、sockモジュールがロードされて、このスクリプトがsockプロキシ越に透過的稼働を行わせるる効果があります。ある特別な機能性(UDPソケット、または同リスニングソケットから多数接続を受け入れるような)を必要とする場合は、 perl自体の機能を利用することもできます。

ファイルハンドル上でデータが有効な場合コントロールを取り戻すには、 次のものから、またはそれを用いてfhのsirc`select()s`にファイルハンドルを追加します。

`&addsel($fh, "somename", flag);`。そこでsel&lowbar;somenameは、何か読み込むものがあるとコントロールを取り戻すサブで、sircに接続を緩衝させ、ラインに押し入れるとフラグは1で、sircにはデータには触れて欲し くない場合、フラグは0になります。

`sel&lowbar;somename`サブの規則は、2つの点で違いがあります。

- 緩衝されたファイルハンドルについては、読み込まれた行を含むシングル引数が渡されます。文末には、`\n`が含まれます。接続が閉じられたり、切断された場合、この引数は`''`で、ファイルハンドルは既に閉じられ、fhの設定から`select()`まで削除されています。自分自身で閉じる場合、sircに設定からそれを削除するように伝えるため`&remsel`を使わなければなりません。

- 緩衝されていないファイルハンドルについては、いかなる引数も渡されません。`select()`によって、fhが読み込み準備ができていると暗示されると、フックがコールされ、そこからの読みとりはフック次第です。(ブロックしていないことを確認して下さい。<>ではなくsysreadが使われるべきでしょう。)結局それを閉じ、`&remsel`を使って削除するのもフックによります。

`select()ed`上のfhの設定からファイルハンドルを削除するには、`$fh`がファイルハンドルになっている`&remsel($fh);`をコールします。

sircは、そこに与えるファイルハンドルが正当であるかどうかを全くチェックしない点に注意して下さい。`select()able`の設定で、閉じられたもしくは不正な`fh`が存在したり、緩衝されていない`sel&lowbar ;* hook`上のデータを実際に読み込まないと、`select()`でブロックを防ぐことで、sircによるCPUの使用率が多くなるでしょう。

このおおざっぱな使用例用に、ftp.plスクリプトをご覧ください。これはsirc内でftpクライアントを実装しています。(sircウェブページhttp://www.eleves.ens.fr:8080/home/espel/sirc/sirc.htmlにあります)。

### ボット

ircIIにボットを作るように、sircスクリプトにボットを作ることができます。それはおそらく悪い考えではないでしょう。というのは、全ての不完全なネットワークプログラミングやすでにサーバ類解析で、処理上素晴らしく強力なプログラミング言語(perl)があるからです。

しかしながらsircは、決してボットクライアントとはされません。また、ボットサポートのためベルや警笛を充実するつもりもありません。ですからこれについては-lや-qオプションを使って最低限のサポートのみ提供しました。

考えとしては、内部機能やフックの設定のようにボットをプログラムにして、`&addhook`や`&docommand`にコールし、それからこのようにsircをロードします。(明らかにssfeはありません。)

`nohup sirc -d -q -l <botfile> -i <bot's ircname> <nick> <server> >/dev/null &`

もちろん、これら全て`<>'s`がありません。`>/dev/null`は、そこで出力を制御します。というのは、どのようにしても画面上でそれを読んでいないはずだからです。

ボットでは、`"nick in use"`もしくは`"invalid" nick"`を伝えるラインを(数値フックを用いて)捕らえ、あるランダムなニックでサーバへのラインを送信し、それらをスキップさせたり、または、ボットはユーザがニックを要求しようとすることを阻止します。`"disconnect"`にもフックを設定し、`&docommand("server 0")`または`"server some.server"`を行わせるとよいでしょう。

サーバへの接続が確立する前でもファイルがロードされることも記憶しておいて下さい。そして、`&sl`へコールし、大概そこで`&docommand's`が失敗するでしょう。

以下はボットの例です。これは接続、チャンネルへ参加、切断された際の再接続、いくつかのコマンドへの応答、オーナのops、そして公的なことを除く全てをファイル上でログとして取ります。"mybot"のようなファイルにそれを保存すれば、これをロードでき、BubbleBotの方がよければ次のようにしてください。

`nohup sirc -d -q -l mybot -i "bot in sirc" BubbleBot some.server.edu >/dev/null`

    $botowner="espel\@clipper.ens.fr";	# 自分のアドレスへ変更

    $logfile=$ENV{'HOME'}."/.botlog";
    &docommand("log on");

    sub hook_publicstuff {		# 公的チャッタを表示禁止
      $silent=1;			# ログファイルを作成しない
    }
    &addhook("public", "publicstuff");

    sub hook_connected {
      &sl("JOIN #BotTub");
    }
    &addhook("376", "connected");   # "end of MOTD" 数値に参加

    srand;				# init ランダム数値生成

    sub hook_badnick {
      local($n);
      $n="B".(int(rand(1000000))+4587454);  # 不要情報ニックの送信...
      &sl("NICK $n");
      $skip=1;
    }
    &addhook("432", "badnick");             # 取り入れられると伝達されたら
    &addhook("433", "badnick");

    sub hook_disc {         # 切断されたら
      sleep(30);		# 30秒待機  (サーバがダウンしているならば
    			# マシンをダウンせずにクロール)
      &docommand("server 1"); # 同サーバに再接続
    }
    &addhook("disconnect", "disc");

    sub hook_joined {	# 誰かが参加したら
      local($ch)=($_[0]);
      $ch =˜ tr/A-Z/a-z/;	# 英小文字でチャンネルを設置
      if (&eq($botowner, "$user\@$host") && $haveops{$ch}) {
        &sl("MODE $ch +o $who");	# op if that's the owner and we have ops
      }
    }
    &addhook("join", "joined");

    sub hook_message {
      if (&eq($botowner, "$user\@$host")) {  # オーナからの msg ならば
        if ($_[0] =˜ /^die$/i) {             # die -> die
          &docommand("quit");
        } elsif ($_[0] =˜ /^say /i) {        # say <something> -> say it
          &say($');
        } elsif ($_[0] =˜ /^nick /i) {       # nick <nick> -> change nicks
          &sl("NICK $'");
        }
    # add more commands here
      }
    }
    &addhook("msg", "message");

日本語翻訳：レーザーファイブ info@laser5.co.jp