iRC DCC Chat

  • Hallo zusammen,

    ich bins mal wieder, mit einem Problem beim Erweitern des Basis-IRC-Client von BugFix.
    Und zwar möchte ich diesem aktuell die Möglichkeit zum DCC-Chat spendieren.

    Der Aufbau wird dazu wie folgt initialisiert. Ich sende über meinen mIRC-Client den Befehl /dcc chat NICK an den Server, welcher diesen widerrum an den entsprechenden User weiterschickt. Darin enthalten sind die IP + der Port, auf dem der DCC-Server vom mIRC-Client automatisch initialisiert wird. Beim Basis-Client kommt dies als NOTICE (mit IP) und PRIVMSG (mit Port) an. Die beiden benötigten Informationen habe ich mir bereits entsprechend zur Weiterverarbeitung "rausgesucht". Anschließend stelle ich eine TCP-Verbindung hierzu her. Schlägt diese fehl, informiere ich den User per NOTICE darüber. Kommt diese zustande .... und hier hakts zZ =)

    Ich wollte nun hier eine ähnliche While-Schleife einbauen, wie sie ja bereits schon für die Verbindung vom iRC-Server besteht. TCPConnect gibt auch erfolgreich ein socket zurück, bei $recv = TCPRecv($sockDcc, 8192) kommt dann der entsprechende Fehler, wo es aktuell nicht weitergeht. Da wirds dann wohl an "maxlen" haken. Und ich habe keine Ahnung, was man hier als Wert nehmen muss, bzw wo man das rausbekommen würde.

    Weiter wäre dann die Frage, was ich wie zurücksenden müsste (oder überhaupt), damit die Gegenseite eine Info bekommt, dass der DCC Chat initialisiert wird (oder später geschlossen). Wie ich mich eingelesen habe, würde eigentlich zum initialisieren /dcc chat bzw. auch /dcc chat NICK zurückgeschickt werden, zum abbrechen, sofern denn eine Verbindung besteht, /dcc close oder /dcc close chat NICK. Wenn ich das aber aktuell probiere, kommt nur zurück, dass "dcc" kein bekannter/ gültiger befehl ist. Aber ok, das Problem kommt dann (evtl) später noch.

    Wenn ich hierbei weiterkommen würde, könnte ich weiter am direkten DCC Chat arbeiten, wobei ich hier noch nicht weiss, was mich erwartet. Zumindest bei einem normalen Client kann man die Kommunikatikon wie folgt betreiben (/msg =NICK Text).

    Um folgendes müsste der Basis-Client erweitert werden:

    Spoiler anzeigen
    [autoit]

    Func _DCCConnect ($server, $port)
    Local $i = TCPConnect(TCPNameToIP($server), $port)
    If @error Then
    If @error = 1 Then
    SetError(1)
    Return "invalid IP"
    ElseIf @error = 2 Then
    SetError(1)
    Return "invalid Port"
    Else
    SetError(1)
    Return "other error " & @error
    EndIf
    EndIf
    Return $i
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _IRCSendNotice ($irc, $msg, $chan="")
    If $irc = -1 Then Return 0
    $crypt = _FiSH_Crypt($msg, $chan, 1)
    If Not @error Then $msg = $crypt
    If $chan = "" Then
    TCPSend($irc, $msg & @CRLF)
    If @error Then
    MsgBox(1, "IRC.au3", "Server has disconnected.")
    Return -1
    EndIf
    Return 1
    EndIf
    TCPSend($irc, "NOTICE " & $chan & " :" & $msg & @CRLF)
    If @error Then
    MsgBox(1, "IRC.au3", "Server has disconnected.")
    Return -1
    EndIf
    Return 1
    EndFunc

    [/autoit]

    und den Teil von

    [autoit]

    Case 'PRIVMSG' ; Nachricht empfangen

    [/autoit]

    hiermit ersetzen:

    Spoiler anzeigen
    [autoit]

    Case 'PRIVMSG' ; Nachricht empfangen
    ConsoleWrite(@TAB & @TAB & _ArrayToString($sTemp) & @CRLF)
    $USER = StringTrimLeft(StringLeft($sTemp[1], StringInStr($sTemp[1], '!')-1), 1)
    $text = ''
    $txtUSER = ''
    For $k = 4 To $sTemp[0]
    $text &= $sTemp[$k] & ' '
    Next
    $text = StringTrimLeft($text, 1)
    If StringInStr($text, 'ACTION', 1) Then ; Aktion von USER
    $text = StringTrimLeft($text, 8)
    $text = StringLeft($text, StringLen($text)-2)
    ConsoleWrite('***' & $USER & ' ' & $text & @CRLF)
    ElseIf StringInStr($text, 'DCC CHAT', 1) Then ; Direkt-Chatanfrage
    ConsoleWrite('<' & $USER & '> ' & $text & @CRLF) ; USER spricht
    $DCCPort = $sTemp[8]
    ConsoleWrite("DCC Chat von " & $USER & " [host: " & $sTemp[1] & "; ip: " & $DCCIP & "; port: " & $DCCPort & "]" & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Global $sockDcc = _DCCConnect($DCCIP, $DCCPort)
    If Not $sockDcc = -1 Then
    ConsoleWrite("DCC Chat established; socket: " & $sockDcc & @CRLF)

    While 1
    $msg = GUIGetMsg()
    If $msg = -3 Then
    Exit
    EndIf
    $recv = TCPRecv($sockDcc, 8192); Empfängt vom Server
    If @error Then
    Exit MsgBox(1, "IRC Example", "Server has errored or disconnected"); Verbindung zum Server besteht nicht mehr
    EndIf
    ;~ Local $sData = StringSplit($recv, @CRLF); Splittet die Nachrichten, wenn sie vom Server gruppiert werden
    ;~ For $i = 1 To $sData[0] Step 1; behandelt jede Nachricht einzeln
    ;~ Local $sTemp = StringSplit($sData[$i], " "); Splittet die Nachricht an den Leerzeichen
    ;~ If $sTemp[1] = "" Then ContinueLoop; Weiter, wenn leer
    ;~ If $sTemp[1] = "PING" Then _IRCPing($sock, $sTemp[2]); Prüft ob PING zurückgegeben wird
    ;~ If $sTemp[0] <= 2 Then ContinueLoop; meist nutzlose Informationen
    ;~ ConsoleWrite(_ArrayToString($sTemp) & @CRLF)
    ;~ Next
    WEnd
    ;~ ;Switch $sTemp[2]; Splittet die Command Nachricht
    ;~ ;Case "266"; Indikator der zeigt, dass alle Infos gesendet wurden

    [/autoit] [autoit][/autoit] [autoit]

    Else
    _IRCSendNotice($sock, "DCC Chat not established; error: " & $sockDcc, $USER)
    ConsoleWrite("DCC Chat not established; error: " & $sockDcc & @CRLF)
    EndIf

    Else
    If $sTemp[3] = $nick Then
    $USER = StringTrimLeft(StringLeft($sTemp[1], StringInStr($sTemp[1], '!')-1), 1)
    ConsoleWrite('<' & $USER & '> ' & $text & @CRLF) ; USER spricht
    EndIf
    EndIf
    Case 'NOTICE' ; Nachricht empfangen
    $USER = StringTrimLeft(StringLeft($sTemp[1], StringInStr($sTemp[1], '!')-1), 1)
    $text = ''
    $txtUSER = ''
    For $k = 4 To $sTemp[0]
    $text &= $sTemp[$k] & ' '
    Next
    $text = StringTrimLeft($text, 1)
    If StringInStr($text, 'DCC Chat', 1) Then ; Direkt-Chatanfrage
    ConsoleWrite('NOTiCE von [' & $USER & ']: ' & $text & @CRLF) ; USER spricht
    $DCCIP = StringTrimLeft(StringTrimRight($sTemp[6], 1), 1)
    Else
    ConsoleWrite('NOTiCE von [' & $USER & ']: ' & $text & @CRLF) ; USER spricht
    EndIf

    [/autoit]

    Meine Infos hierzu habe ich natürlich durch testen (was kommt bei den entpsrechenden User an) und von folgenden Links:

    http://home.epix.net/~ircadmin/advanced/dcc.html
    http://www.ircle.com/reference/commands.shtml
    http://www.michaelweil.de/irc/ctcp.htm
    http://www.netsplit.de/crimson/node45.html
    http://www.irchelp.org/irchelp/rfc/ctcpspec.html

    EDIT: getestet, dass die Verbindung geht, habe ich wie folgt:

    Da mein mIRC beim aufsetzen des DCC Servers immer Port 0 sendet, worauf natürlich keiner Connecten kann, habe ich den Server manuell aufgesetzt. Dazu habe ich folgenden Befehl verwendet:

    /dccserver +c on 5555

    +c steht hierbei für chat (möglich wären noch -f = fserve und +s = send)

    EDIT": kleinen Fehler in _DCCConect gefixt, weil da immer ein @error rauskam, obwohl keiner drin war =)