# Chapitre 5. Programmation de votre Client Sirc

Attention : pour comprendre ceci, vous avez besoin de connaître perl (le langage de programmation; lisez les pages de manuel pour plus d'informations), et d'avoir lu soigneusement le README.

Pour un exemple de script sirc vraiment utile, regardez le fichier `n0thing.pl`; si vous vous demandez comment vous y prendre avec un script sirc, essayez de comprendre les fonctions qui y sont définies.

# 5.1. Commandes

Depuis les scripts `/loaded/tt>` (chargés) et `.sircrc.pl`, vous pouvez définir de nouvelles commmandes et donner leur exécution en perl.

Ces scripts sont en fait des fichiers en code perl, et ils sont chargés de façon correcte dans le contexte de sirc.

Pour définir une nouvelle commande, vous n'avez qu'à définir un sous-programme avec le nom `cmd_yourcommandname` (nomdevotrecommande) qui agit dans tous les cas, et appeller `&addcmd("yourcommandname");`

Vous pouvez également définir une aide pour la commande en appelant `&addhelp("yourcommandname", "Première ligne d'aide\nSeconde ligne d'aide...")`;

Votre sous-progamme prend tous ses arguments dans la variable globale `$args` (non analysée), son nom véritable dans `$cmd`, et la ligne entière de commande dans `$line`.

Il peut aussi utiliser un numéro de routine depuis le client sirc.

&load("file");

  charge un script sirc, vérifie dans @loadpath. que l'extension ".pl" est optionelle.

&dosplat;

  change une * dans le nom du canal courant, si elle est le premier mot de `$args`

&getarg;

  pour obtenir le premier mot de `$args` dans $newarg et le reste dans `$args`

&yetonearg;

  même chose, supprime une fin de ligne : dans `$args` s'il y en a une

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

  vérifie une égalité qui ignore la casse

&sl("text");

  pour envoyer une ligne de texte au serveur (la fin `"\n"` est ajoutée automatiquement)

&tell("txt");

  envoie du texte à l'écran, ajoute un `"\n"`, et uniquement s'il n'est pas en mode silencieux

&print("txt");

  envoie du texte à l'écran, ajoute un `"\n"`, sans tenir compte du mode silencieux

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

  édite "str" sur l'écran, place "prompt" comme invite temporaire s'il utilise ssfe, et guide les utilisateurs pour envoyer une ligne, la renvoie dans `$_`

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

  même chose pour les mots de passe d'invite; ssfe ne répétera pas le mot de passe

&dostatus;

  affiche de nouveau la ligne d'état

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

  envoie un message, l'édite. La destination peut être un pseudonyme, un canal, ou un =nick (DCC CHAT)

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

  envoie une remarque, l'édite. La destination peut être un canal ou un pseudonyme

&say("msg");

  signale quelque chose sur le canal courant, l'édite

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

  envoie un `/describe`, l'édite

&me("msg");

  effectue une action sur le canal courant, l'édite.

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

  ouvre une connexion tcp avec l'hôte et donne le port. Le premier argument`($fh)` doit être une variable et `&connect` la définit à la valeur du gestionnaire de fichiers associé à la connexion. `&tell's` nous indique un message et renvoie 0 s'il y a une erreur, sinon 1.

&listen($fh, port);

  ouvre un support d'écoute limité au port donné; laisse le système désigner un port si le port spécifié est 0 (ou si le second argument n'a pas disparu en totalité). Le premier argument doit être une variable et `&listen` la définit à la valeur du gestionnaire de fichiers associé au support d'écoute. & nous signale un message et renvoie 0 s'il y a une erreur, sinon retourne au port sur lequel le support est en attente.

&accept($nfh, $ofh);

  admet une connexion sur le gestionnaire de fichiers `$ofh` (qui doit se reporter à un support d'écoute), et le renvoie dans `$nfh`; `$nfh` doit être une variable, et sera modifée par `&accept`. `$ofh` automatiquement fermée par `&accept` renvoie une valeur booléenne, mais n'édite en aucun cas de message d'erreur.

&resolve("address");

  définit un nom d'hôte dans un fichier groupé (c'est-à-dire une chaîne de caractères de 4 bits représentant l'adresse IP). L'argument peut être un nom d'hôte, une adresse IP écrite en notation à quatre séries de chiffres, ou un (grand) nombre représentant l'adresse "lue" comme un nombre 32 bits dans une instruction réseau. Si la définition échoue, un résultat faux est renvoyé ("" ou 0 ou indéterminé).

  pour obtenir un système à quatre séries de chiffres, à partir duquel `&resolve` est renvoyé, utilisez `join(".", unpack("C4", &resolve("whatever")))`

&newfh;

  renvoie un nouveau nom à utiliser comme gestionnaire de fichiers

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

  définit une valeur à une variable SET, la valeur est validée, et cela n'a pas d'effet si la valeur est incorrecte ou si la variable n'existe pas. C'est la seule façon pour que les scripts modifient les valeurs des variables SET, sauf éventuellement celles qu'ils définissent eux-mêmes.

&docommand("command");

  interprète une ligne de commande comme si elle était tapée au clavier. Un *seul* interligne "/" désactivera l'extension alias/fonction sur la commande.

  *attention* cette routine appelle de façon récurrente le répartiteur de commandes pour elle-même, ce qui est assez gênant. C'est une vérification à l'encontre des boucles (récursion limitée à 20), mais c'est amplement suffisant pour que *vous* soyez sûr que vos scripts fonctionnent. Perl étant un langage doté de structures puissantes et performantes (au contraire de ircII ...), la récursion à ce niveau est à éviter autant que possible. descrip>

  Vous avez accès à un nombre de variables globales; notez que certaines ont été supprimées car elles ont été modifiées en variables SET, pour être lues dans %set et écrites avec &doset.

  A moins qu'autre chose ne soit spécifié, ces variables seront traitées en lecture seule par les scripts..

$version

  version de sirc's - doit toujours être un nombre, et ne doit jamais être modifiée par une fonction utilisateur

$add_ons

  chargement de modules supplémentaires; des scripts peuvent y ajouter un *nomdescript"

$restrict

  définie comme vraie si sirc tourne en mode restreint (sécurisé), qui interdit l'accès à l'interpréteur de commandes et au système de fichiers

$maxrecursion

  number of times &docommand : peut être appelée de façon récurrente avant de donner un message d'erreur "taux maximum de récursion dépassé" (vous pouvez modifier celle-ci, mais il n'est pas sûr qu'elle fonctionne sur des versions ultérieures où elle pourrait devenir une variable SET)

$nick

  votre pseudonyme courant

$server

  votre serveur courant

@channels

  liste des canaux sur lesquels vous êtes connecté

$talkchannel

  votre canal courant (ou '' s'il n'y en pas)

%mode

  tableau réunissant les modes des différents canaux sur lesquels nous sommes connectés. Les noms de canaux sont tous dans la case inférieure, et le mode est une chaîne de caractères sans +' ni -', et sans 'k' ou 'l' puisque ceux-ci sont traités séparément. La valeur des canaux sans aucun mode est '', tandis que la valeur pour les canaux sur lesquels nous ne sommes pas connectés est indéterminée.

%chankey

  touches des canaux, indéfini s'il n'y en a aucun ou si nous ne sommes pas connectés sur le canal. Les noms de canaux sont dans la case inférieure.

%limit

  limites des canaux, indéfini s'il n'y en aucun ou si nous ne sommes pas connectés sur le canal. Les noms de canaux sont dans la case inférieure.

%haveops

  tableau réunissant les variables booléennes, vrai si nous avons des opérations sur le canal. Les noms de canaux sont... vous le savez

$umode

  mode utilisateur, chaîne de caractères sans +' ni -'

$query

  tout interlocuteur que vous demandez, ou '' s'il n'y a personne

%aliases

  tableau réunissant les alias de substitution définis; le nom d'alias est en capitales

%set

  tableau réunissant les valeurs des variables SET; le nom de variable est également en capitales

%notify

  tableau réunissant la liste de notification; la valeur pour un pseudonyme donné est 0 pour un "absent", ou le moment de la plus récente notification pour ce pseudonyme

$bindaddr

  c'est l'adresse IP de la machine à laquelle les connexions de sortie sont limitées, jusqu'à ce que sirc puisse le signaler. Elle change lorsque la variable SET de "l'hôte local" change, et elle est déterminée à l'adresse IP de la machine proxy lorsque sirc tourne avec les supports de communication chargés. `$bindaddr` est une chaîne de caractères de 4 bits représentant un groupe `in_addr;` que vous obtenez en entier (comme il est d'usage dans DCC CHAT/SEND) avec `unpack("N", $binaddr);`, et un système à quatre séries de chiffres avec `join(".", unpack("C4", $bindaddr));`

A moins qu'autre chose ne soit spécifié, commandes et points d'insertion ne devraient jamais modifier les paramètres qui leur ont été assignés (c'est-à-dire faire quelque chose comme `$_[1]="some value"`. S'ils souhaitent en modifier des copies locales, ils commenceront avec `local(...)=@_;`

Si votre script utlise des variables globales, veuillez vous assurer qu'elles ne vont pas s'opposer à celles de sirc (même problème pour les noms de description de fichiers, et de procédures). Une bonne convention serait de donner à toutes ces variables et procédures un nom qui commence par le nom du script, ou avec quelques lettres de celui-ci. Par exemple, dans `n0thing.pl` toutes les variables globales de script et les procédures internes ont des noms qui commencent par "n_".

Exemple, que pourrait-on introduire directement dans un fichier `/load'ed`, une commande qui (cible?) un canal si vous en spécifiez un, et un pseudonyme si vous le mentionnez également :

     sub cmd_yeek {
       &dosplat;		# si le premier argument est *, remplacez-le avec $talkchannel
       &getarg;		# place le premier argument dans $newarg
       local($channel)=($talkchannel);	# par défaut, nous communiquons avec le canal $talkchannel
       if ($newarg =˜ /^[\#\&]/) {		# si le premier argument commence avec # or &
         $channel=$newarg;			# communiquez plutôt ici
         &getarg;				# et placez un argument supplémentaire
       }
       if ($newarg) {	# regardez si nous avons spécifié que nous (ciblons?)
         &describe($channel, "look at $newarg and *yeeeks*"); ("regardez $newarg et (*ciblez*")?)
       } else {		# or not (ou non)
         &describe($channel, "*yeeks* at the crowd"); ((*ciblez*?) le groupe*);
     }

     # \cb est la manière de spécifier ^B en perl
     &addcmd("yeek");
     &addhelp("yeek", "Usage: \cbYEEK\cb [<channel>] [<nick>]
     Cible sur le pseudonyme ou sur le canal entier
     Examples: /yeek someone ((cible?) un interlocuteur)
               /yeek * someone
      	  /yeek #channel  ((cible?) un canal)
      	  /yeek #channel someone"); ((cible?)à un interlocuteur sur le canal)