Aliasse und Scripting in mIRC

welche sich bei mir bewährt haben


Fertige Scripte
Verwende ich nur als Ideenlieferanten und zum Abschauen von Kniffen. Ich basteln mir meine Sachen gerne so zurecht, wie ich sie persönlich am liebsten habe. Und mag es auch nicht, einfach ein 'irgendwas' installiert zu haben, von dem ich nicht weiß, was es macht. Im schlimmsten Fall sogar eine Hintertür enthält. Desweiteren ist das Erstellen der Scripte mit der halbe Spaß daran ;)

Loggen der im Channel befindlichen User
Einladungen in meine Höhle
Sprechen über FurBot
Nick-Widerherstellung
Hilfe für Away
Automatisches Anmelden bei Nickserv
Whois mit Idlezeit

Loggen der im Channel befindlichen User
Um beim Durchsichten der Logs - speziell mit dafür vorgesehenen Tools - zu wissen, ob sich zu einer gegebenen Zeit ein User im Channel befand, so kann man nur darauf schauen, ob er irgendetwas sagte, machte, den Channel betrat oder ihn verließ. Komplett lurkende Personen - gerade auch Idler - sind dadurch nicht erfassbar. Hier kommt ein wenig Scripting ins Spiel, um die beim Betreten des Channels anwesenden Personen im Log zu protokollieren.

In mIRC in der script.ini dafür folgende Zeilen hinzufügen:

on ^*:JOIN:*:{ 
  ; wenn ich einen Channel betrete: Alle Namen auflisten lassen, für das log
  if ($nick == $me) { 
    set $($+(%,$network,.,$cid,.log_names,.,$chan),1) true
    ; /names $chan    ; unnötig, da mIRC dies bereits einmal macht, und das reicht
  }
}

raw 366:*: {
  if ( $($+(%,$network,.,$cid,.log_names,.,$2),2) == true ) {
    unset $($+(%,$network,.,$cid,.log_names,.,$2),1)
    var %i = 1,%users | while ($nick($2,%i)) { %users = %users $v1 | inc %i }
    echo -t $2 Users on $2: %users
    halt
  }
}
Die technische Erklärung dafür:
Das OnJoin-Ereignis wird ausgelöst, wenn ein User, uns selber eingeschlossen, einen Channel betritt. Wir prüfen, ob es sich hierbei um uns handelt (Ereignisauslösender Nick $nick identisch mit unserem eigenen Nick $me), setzen die Variable %jnames auf den Namen des Channels und fordern mittels /names $chan die Userliste des Channels an.
Die Benutzer kriegen wir mit dem Statuscode 353 zurück. Die Parameter hierbei sind:
$1 eigener Nick
$2 "=" (Gleichheitszeichen)
$3 betreffender Channel
$4- die im Channel befindlichen Nicks
Ist dir Rückmeldung für uns bestimmt (%jnames gleich Channelname $3) so geben wir mittels "echo" im betreffenden Fenster (-t $3) aus, welche User sich im Channel befinden. Mit dem "halt" unterdrücken wir die Anzeige im Statusfenster, so daß sich dort nichts ändert.
Der Statuscode 366 informiert uns darüber, daß alle Benutzer übertragen wurden - das ist notwendig, da pro 353-Block nur eine begrenzte Zahl Namen übertragen werden kann und bei mehr Benutzern mehrere solche Blöcke gesendet werden. Diese Ausgabe unterdrücken wir (halt), löschen jedoch %jnames vorher. Dadurch ist sichergestellt, daß wir nur unsere eigene /names-Anfrage abfangen und den normalen Betrieb nicht weiter stören.
Die Parameter hierbei sind:
$1 eigener Nick
$2 betreffender Channel
$3- "End of /NAMES list."
(d.h. einmal ist der Channelname im dritten, dann im zweiten Parameter anzutreffen)

Das Ergebnis
[06:59] * Now talking in #Zefiro
[06:59] Users on #Zefiro: @Zefiro @FurBot
[06:59] <Zefiro> *schnurr*

Einladungen in meine Höhle
spreche ich recht häufig aus. Natürlich habe ich auch hierfür ein kleines Alias:
/inv {
  if ($network == FurNet) {
    if ($1 $+ _ != _) { 
      /invite $1 #Zefiro
    } 
    elseif ( $query($active) ) {
      /invite $active #Zefiro
    } 
  }
}
/invnot /invite $($+(%,$network,.,$cid,.lastnotifyon),2) #Zefiro
Benutzt wird das ganze dann mit einem /inv nick. In einem Query kann ich den Nick auch weglassen und nur /inv tippen. Die betreffende Person wird dann in meine Höhle eingeladen. (natürlich benötigt /invite Op-Rechte in meiner Höhle).

Um Personen, die in meiner Notify-Liste stehen und online kommen schnell einzuladen, habe ich den Alias /invnot. Dies lädt die Person ein, welche als letztes online gekommen ist - sehr praktisch, wenn ich z.B. gerade auf sie gewartet habe und die Notify-Meldung in irgendeinem Channel oder Query sehe. Dies könnte man zwar auch automatisieren, jedoch ist es mir lieber, derartiges persönlich zu machen.

Damit dies funktioniert, müssen noch diese Zeilen in Remote eingetragen werden:
on *:NOTIFY: {
    set $($+(%,$network,.,$cid,.lastnotifyon),1) $nick
  }
}

Sprechen über FurBot
FurBot war in meiner Höhle hauptsächlich aus ästhetischen und Rollenspielgründen, bis er von Igor abgelöst wurde. Ich fand es schöner, einen kleinen Roboter zu haben, der (via Symbiose) alle Aktionen von ChanServ ausführt. In meine gelegentlichen Rollenspielsitzungen bezog ich ihn auch regelmäßig mit ein. Hierbei ist es sehr hilfreich, ohne viel Tippen ihn zum Agieren zu veranlassen.
Die Kommandos, um FurBot etwas sagen oder tun zu lassen sehen so aus:
/msg BotServ act #Zefiro stellt sich vor
/msg BotServ say #Zefiro Ich bin der bot
Dies hat gleich mehrere Nachteile.
- es ist ein langer Text zum Tippen
- (tipp)fehleranfällig
- taucht in den Logs doppelt auf
Zum dritten Punkt: die Anweisung an den Bot wird im Channel als private Message (an BotServ) deutlich gemacht, direkt danach kommt die Aktion des Bots zurück. Für einzelne Aktionen mag dies nicht viel ausmachen, doch nachdem ich einmal eine ganze Session über nur 'durch den Bot' gehandelt habe, wurde dies schnell unansehlich und verwirrend.
Eine Alternative wäre die Verwendung eines Query zum BotServ. Dies ist jedoch sehr verwirrend, da man im einen Fenster schreiben, im anderen lesen muß. Im Log ist immer noch alles doppelt vorhanden, jetzt auf zwei Logs aufgeteilt. Alternativ könnte man den Botquery vom Log ausschließen. Zwar muß man schon weniger tippen, jedoch immer noch zuviel.

Die Lösung: Aliasdefinitionen für FurBot
/bsay /raw -q PRIVMSG BotServ :say $$chan $$1-
/bact /raw -q PRIVMSG BotServ :act $$chan $$1-
Weist FurBot an, im aktiven Channel die betreffende Aktion auszuführen bzw. sein Sprüchlein zu sagen. Durch die Verwendung von $$1- wird der gesamte übergebene Text verwendet, die Zeile jedoch ignoriert, wenn nichts angegeben wurde. $$chan bewirkt, daß sich die Ausgabe auf den aktiven Channel bezieht - und ignoriert wird, wenn sie nicht in einem Channelfenster gegeben wurde. Anstelle von /msg wird hier ein raw-Kommando verwendet, da hierbei mittels -q (quiet) die Ausgabe im Channel unterdrückt werden kann.
Diese beiden Aliasse setzen vorraus, daß man sich in einem Channel befindet, dort auch FurBot anwesend ist sowie man die nötigen Rechte besitzt (soweit ich weiß ist Founder-Level-Access zum Channel notwendig).

Anzumerken ist noch, daß durch die Art und Weise, wie mIRC mit Scripten umgeht, alle Leerzeichen auf eines verkürzt werden. Es ist somit nicht möglich einen Satz zu sagen, in dem mehrere Leerzeichen hintereinander auftauchen. Bei normaler Benutzung fällt dies jedoch nicht auf.

Nick-Widerherstellung
Meine Höhle ist leider weit abseits jeglicher Zivilisation. Mittels langen Kabeln über komplizierten Wegen, Funkstrecken und anderen gelangt das lebensspendende Internet zu mir - jedoch mit deutlichen Verlusten.
Ein sich hieraus ergebendes Problem sind recht häufige Disconnects. mIRC reconnected zwar selbstständig, doch wenn der Server die alte Verbindung noch nicht vollständig getrennt hat, so ist der Nick blockiert. Hier soll ein Ersatznick gewählt werden, der jedoch sobald verfügbar mit dem gewünschten Nick ausgetauscht wird. Da wir nun Services im FurNet haben, soll hierfür auch das Ghost-Kommando verwendet werden.
Ebenfalls möchte ich beim manuellen Starten von mIRC wieder mit dem Grundnick 'Zefiro' online gehen, nicht mit dem, welchen ich beim letzten Chatten evtl. noch hatte.
mIRC selber bietet nur an entweder den letzten Nick wiederherzustellen, oder einen Alternativnick zu verwenden wenn der letzte in Verwendung ist, oder aber den Nick nicht zu ändern. Da ich nach einem mIRC-Neustart gerne meinen normalen Nick ('Zefiro') habe, nach einer reinen Verbindungstrennung jedoch den zuletzt gewählten und zusätzlich nachdem mein Wunschnick frei wird auch gleich auf diesen zurückschwenken möchte - idealerweise ihn vorher zu ghosten - benötige ich ein passendes Script dafür.

Folgende Zeilen müssen hierfür eingefügt werden:

Alias
/nick {
  ; Debug-Ausgabe
  ;  .echo Wunschnick geändert von $($+(%,$network,.,$cid,.lastnick),2) auf $1
  ; Nick und alternativen Nick setzen (für einen sinnvollen Ersatz bei Disconnect)
  ; wichtig: anick ändert evtl. den Nick, daher nick hinter anick setzen
  ; wichtiger: dieses Ändern ist superlästig, da alle das mitkriegen! Bessere Lösung finden!!
  ;.!anick $($+(%,$network,.,$cid,.lastnick),2) $+ _
  /!nick $1
  ; Nick als gewünschten Nick merken
  set $($+(%,$network,.,$cid,.lastnick),1) $1
  ; awayinfo löschen (meist nach /afk)
  if ($($+(%,$network,.,$cid,.lastaway),2) $+ _ != _) { 
    /away
  }
}

Variables (werden automatisch angelegt)
; Status für die Nickwiederherstellung nach einem Disconnect
; 0 - normal / inaktiv
; 1 - Reconnect brachte anderen Nick, Umbenennen wird versucht (setzt OnConnect)
; 2 - Nick schon vorhanden, GHOST wird versucht (setzt RAW 433 = Nick Exists)
;%notifynickchange 0

; der letzte von uns aktiv gewählte Nick, wird nach Disconnect als Reconnectnick verwendet
;%lastnick Zefiro

; das Passwort für Nickserv für meine registrierten Nicks
%config.FurNet.nickservpwd password

Remote
on *:START: {
  ; den Nick zurückstellen, wenn er vom letztenmal noch anders war
  ; (optional, und wenig tauglich im Multi-netz-Betrieb)
  ;/nick Zefiro
}

on *:DISCONNECT: {
  ; Informative (Debugging) Ausgabe, erscheint direkt nach dem Disconnect (auch wenn Usergewollt)
  echo last wanted nick was: $($+(%,$network,.,$cid,.lastnick),2) (actual nick was $me $+ )
  ; Letzten Nick merken - redundant, da wir /nick ja auch abfangen
  ; hiermit kriegen wir serverseitiges Umbenennen mit - wollen wir dies denn als neuen Wunschnick?
  ; Ausnahme: wenn wir gerade versuchen, uns umzubenennen - dann %lastnick unverändert lassen
  if ($($+(%,$network,.,$cid,.notifynickchange),2) == 0) {
    set $($+(%,$network,.,$cid,.lastnick),1) $me
  }
  ; wenn wir grade dabei waren, uns umzubenennen - notify löschen
  if ($($+(%,$network,.,$cid,.notifynickchange),2) == 2) {
    /!notify -r $($+(%,$network,.,$cid,.lastnick),2)
  }
}

on *:CONNECT: {
  ; wir wollen nicht invisible sein - selbst wenn +i serverdefault ist
  /mode $me -i
  ; sind wir, wer wir sein wollen?
  if ($me != $($+(%,$network,.,$cid,.lastnick),2)) {
    set $($+(%,$network,.,$cid,.notifynickchange),1) 1
    /!anick $($+(%,$network,.,$cid,.lastnick),2) $+ _
    /!nick $($+(%,$network,.,$cid,.lastnick),2)
  }
  ; wenn noch ein away gesetzt war, neu setzen
  if ($($+(%,$network,.,$cid,.lastaway),2) $+ _ != _) { 
    /away $($+(%,$network,.,$cid,.lastaway),2)
  }
}

on *:NOTIFY: {
  ; Reconnect-Notify wegfiltern
  if ($nick == $($+(%,$network,.,$cid,.lastnick),2)) {
    halt
  } 
  else {
    ; für /invnot
    set $($+(%,$network,.,$cid,.lastnotifyon),1) $nick
  }
}

on *:UNOTIFY: {
  if ($nick == $($+(%,$network,.,$cid,.lastnick),2) && $($+(%,$network,.,$cid,.notifynickchange),2) == 2) {
    unset $($+(%,$network,.,$cid,.notifynickchange),1)
    /!nick $($+(%,$network,.,$cid,.lastnick),2)
    /!notify -r $($+(%,$network,.,$cid,.lastnick),2)
    halt
  }
}

raw 433:*: { ; Nick schon vergeben
  if ($1 == *) {
    echo Nick exists: $1- (was: $($+(%,$network,.,$cid,.lastnick),2))
  } 
  else if ($($+(%,$network,.,$cid,.notifynickchange),2) == 1) {
    set $($+(%,$network,.,$cid,.notifynickchange),1) 2
    /!notify $($+(%,$network,.,$cid,.lastnick),2)
    ; GHOSTen - vielleicht hilft's ja... (sofern der aktuelle Nick erkannt ist und der neue mir auch gehört)
    if ($($+(%,config.,$network,.nickservpwd),2) $+ _ != _) {
      /raw -q PRIVMSG nickserv : $+ ghost $($+(%,$network,.,$cid,.lastnick),2) $($+(%,config.,$network,.nickservpwd),2)
    }
    halt
  } 
  else { ; Nickchange wurde manuell angestossen
    ; alter Nick ist weiterhin 'gewünschter' Nick bzgl. Autorename (/nick ändert .lastnick)
    set $($+(%,$network,.,$cid,.lastnick),1) $1
  }
}

; ein Ghost-Kommando meldete, daß der Nick nicht in Verwendung sei
; kam das von uns? $2 ist der Nick
On ^*:NOTICE:Nick*isn't currently in use.:*: {
  ; NickServ gibt den Nick in Fettschrift zurück, daher mit den entsprechenden Steuerzeichen vergleichen
  if ($2 ==  $+ $($+(%,$network,.,$cid,.lastnick),2) $+  && $($+(%,$network,.,$cid,.notifynickchange),2) == 2) {
    /!echo NickServ says, $($+(%,$network,.,$cid,.lastnick),2) is available - renaming
    unset $($+(%,$network,.,$cid,.notifynickchange),1)
    /!nick $($+(%,$network,.,$cid,.lastnick),2)
    /!notify -r $($+(%,$network,.,$cid,.lastnick),2)
    haltdef
  }
}
Dies liefert die gewünschte Funktionalität und hat sich im Praxiseinsatz als sehr robust erwiesen. Ein paar Probleme hat es sicherlich noch - so bleibt von Zeit zu Zeit der eigene Nick in der Notify-Liste erhalten. Ein Sicherheitscheck gegen Nickserv wäre noch sehr sinnvoll - das Passwort soll nur gesendet werden, wenn wir im richtigen Netz sind und die Hostmask von Nickserv mit 'services@irc.furnet.org' übereinstimmt. Dafür wird jedoch ein /whois und eine weitere Stufe in der asynchronen Kette notwendig. Da die Services fast immer zur Verfügung stehen habe ich dies bisher nicht implementiert.
Mittlerweile habe ich auch eine multiservertaugliche Variante, die problemlos mit mehreren Verbindungen zurechtkommt. Allerdings hat sie noch den Schönheitsfehler daß beim mIRC-Neustarten nicht mehr der Defaultnick gesetzt wird. Deshalb habe ich diese noch nicht hier online gestellt. Über Anregungen dazu würde ich mich sehr freuen, Mail genügt.

Hilfe für Away
Die /away Funktion nutze ich nur sehr selten. Normalerweise verlasse ich das IRC, wenn ich für längere Zeit nicht am Rechner bin - jedoch lese ich regelmäßig mit, wenn ich da bin. Durch Blinken macht mIRC auf sich aufmerksam, so daß ich nichts übersehen kann.
Hin und wieder setze ich mich dann jedoch trotzdem mal auf away. Und vergesse das dann prompt, wieder zurückzustellen...

Alias
; meine häufig verwendeten Nicks
/zef /nick Zefiro
/zzz /nick zZzZefiro
/work /nick Zefi_Work
/afk {
  ; Nick setzen
  /nick Zefi_AFK
  ; danach(!) away setzen
  if ($1 $+ _ != _) { 
    set $($+(%,$network,.,$cid,.lastaway),1) $1-
    /away $($+(%,$network,.,$cid,.lastaway),2)
  }
}

/away {
  set $($+(%,$network,.,$cid,.lastaway),1) $1-
  /!away $1-
}

/nick {
  ; awayinfo löschen (meist nach /afk)
  if (%lastaway $+ "_" != "_") { 
    /away
  }
}
jetzt kann ich mit /afk Futtern meinen Nick ändern und gleich einen Awaystatus mit angeben. Beim nächsten Nickchange wird dieser dann wieder zurückgesetzt.
Diese Lösung ist für mich viel praktischer als ein Auto-Away, was erst mit einer gewissen Verzögerung greift oder ein "Cancel away on Keypress", bei dem mein letzter im Weggehen getippter Satz den Away schon wieder aufhebt.

Automatisches Anmelden bei Nickserv
Zwar haben wir im Furnet die sehr praktische Funktion, daß das - nicht benötigte - Serverpasswort an Nickserv weitergereicht wird. Jedoch kommt es immer wieder vor - nach einigen Stunden unter unregistriertem Nick, oder nach einem Neustart von Services, daß eine erneute Identifizierung notwendig wird. Auch die Verbindung innerhalb des Netzes bricht öfters mal zusammen, was u.U. eine erneute Identifizierung notwendig macht.

Dieses kleine Script sorgt nun für eine automatische Identifizierung bei Nickserv. Zu beachten ist, daß es das Passwort ohne weitere Sicherheitschecks - ob 'Nickserv' wirklich Nickserv ist und die richtige Hostmask hat - herausgibt. Auch wäre eine Abfrage nett, für welchen Nick wir uns eigentlich registrieren, u.U. mit unterschiedlichen Passwörtern. Allerdings habe ich das bisher nie benötigt. Momentan wird nur anhand der Netzkennung unterschieden.

Variables
; das Passwort für Nickserv für meine registrierten Nicks
%config.FurNet.nickservpwd xxxxxxxx
%config.freenode.nickservpwd xxxxxxxx

Remote
On ^*:NOTICE:This nickname is registered and protected*:*: {
  if ($($+(%,config.,$network,.nickservpwd),2) $+ _ != _ && $nick == nickserv) {
    /raw -q PRIVMSG nickserv : $+ identify $($+(%,config.,$network,.nickservpwd),2)
  }
}

On ^*:NOTICE:This nickname is owned by someone else*:*: {
  if ($($+(%,config.,$network,.nickservpwd),2) $+ _ != _ && $nick == nickserv) {
    /raw -q PRIVMSG nickserv : $+ identify $($+(%,config.,$network,.nickservpwd),2)
  }
}

Whois mit Idlezeit
Lange habe ich mich darüber geärgert, daß ein /whois die Idlezeit nur für den gleichen Server anzeigt. Wollte ich also wissen, wie lange jemand schon idlet - um zu wissen ob es sich lohnt, ihn anzusprechen, oder warum er nicht reagiert - so musste ich mich auf dem gleichen Server befinden wie er. Ich war schon am überlegen, ein Bot-Netz zu bauen, die sich untereinander absprechen und die /whois zuschieben, damit der jeweilige Server abgefragt wird. Doch ein bißchen lesen in der Dokumentation brachte hervor, daß dies völlig unnötig ist - das Netz macht dies bereits für einen!
Man kann /whois einen zweiten Parameter angeben - den Server, den man befragen möchte. Noch besser, es ist sogar möglich hierbei einen Nick anzugeben - dann wird der Server befragt, auf dem dieser Nick ist. Durch ein /whois Zefiro Zefiro kriegt man also immer meine Idlezeit, unabhängig davon, ob man auf dem gleichen Server ist wie ich - oder nicht.
Alias
/whois !whois $$1 $$1
Das verwendet ab sofort die neue Methode. Auch alle Popups etc werden funktionieren, da sie die geänderten Aliasse berücksichtigen.
Zu bemerken bleibt noch daß nun ein /whois als Fehlermeldung "no such server" meldet anstelle "no such nick".

Weiterführende Literatur
mIRC FAQ (speziell Abschnitt 7)
Geetee's mIRC script pages
Scripte von mIRC.org
mircscripts.org
DALnet #Helpdesc: mIRC Scripting