Dennis: ICQ Nachrichten automatisiert versenden

Hi liebes Forum,

heute habe ich ein etwas komplizierteres Problem - und zwar beschäftige ich mich mit der Aufgabe ICQ Nachrichten unter einem Linux Debian System automatisiert zu versenden.

Etwas konkreter: An meiner Schule gibt es Vertretungspläne, diese werden auch immer aktuell auf der Schulhomepage zur Verfügung gestellt. Jetzt würde ich gerne alle Schüler, die sich für diesen Service eingetragen haben automatisiert per ICQ benachrichten, wenn ein neuer Vertretungsplan hochgeladen wurde (Idealfall: ...und der Plan den Schüler betrifft). Dazu müsste ich das Versenden der Nachrichten über Kommandozeile starten - entweder aus PHP, oder aus einer beliebigen anderen Programmiersprache, da VServer (Root-Rechte), bin ich nicht sonderlich gebunden.

Ich habe dann eben mal etwas bei Google gestöbert und bin auch recht bald auf mICQ gestoßen. Ließ sich auch problemlos installieren, ich kann es auch problemlos nutzen - dazu logge ich mich über SSH ein, starte das Programm und kann dann interaktiv in diesem Programm Nachirichten schreiben. Soweit alles gut.

Jetzt kann ich aber das Programm aus einer anderen Software heraus schlecht interaktiv bedienen - deshalb geht es so, wie ich herrausgefunden habe:

./micq -u <ICQ-Nr> -p <Passwd> -C "msg <Empf>[,<Empf2>] <Nachricht>"

So kann ich eine Nachricht an einen oder mehrere Empfänger verschicken, ich kann auch mehrere Nachrichten nacheinander verschicken, indem ich sie alle für -C übergebe[1] - auch das funktioniert also soweit gut.

Jetzt gibt es jedoch ein Problem, da recht viele Leute bei uns ICQ besitzen (bei uns in der Klasse eigentlich alle, in anderen Klassen sicherlich ähnlich) und das Feature sicherlich interessant ist, könnten das bis zu 800 Leute werden, die benachrichtig werden müssen - dabei ist das erste Problem das ich habe, dass ich ja nicht einen unendlich langen Befehl absetzen kann, der Befehl wird natürlich unheimlich lang, wenn man (für den Idealfall) jedem Schüler bzw. jeder Klassenstufe eine eigene Nachricht schreibt.

Ich habe es jetzt noch nicht so konkret getestet, aber ich meine zu wissen, dass es irgendwo eine Beschränkung in der Länge der Eingabe gibt, so dass das auf jeden Fall schon daran scheitern würde.

So - was spricht dagegen, einfach das auf mehrere Aufrufe aufzuteilen? Das geht deshalb nicht, weil sich für jeden Aufruf neu eingeloggt wird - und bei mehr als 5 mal einloggen in 30 Minuten oder so blockiert der ICQ Server, geht also auch nicht.

Und das ist die Stelle, wo ich mit meinem Latein am Ende bis - zwei[2] Fragen:

  1. Gibt es irgendwie eine Möglichkeit, ein Programm interaktiv zu bedienen, jedoch nicht über SSH, sondern eben aus einem anderen Programm heraus?
  2. Gibt es die Möglichkeit mICQ irgendwie so zu starten (der Entwickler antwortete auf meine Mail nicht), dass es als Deamon im Hintergrund läuft und ich über irgendeine Schnittstelle, dann Nachrichten verschicken kann, der ICQ-User aber eben die ganze Zeit eingeloggt bleibt?
  3. kenn jemand ein Programm, was 2) kann?

MfG, Dennis.

[1] ./micq -u ... -p ... -C "msg foo test" "msg bar test2" "exit"
[2] Uups, sind drei geworden ;-)

  1. Ave Dennis,

    gehst Du unter die ICQ-Spammer?

    Jetzt kann ich aber das Programm aus einer anderen Software heraus schlecht interaktiv bedienen - deshalb geht es so, wie ich herrausgefunden habe:
      ./micq -u <ICQ-Nr> -p <Passwd> -C "msg <Empf>[,<Empf2>] <Nachricht>"
    Und das ist die Stelle, wo ich mit meinem Latein am Ende bis - zwei[2] Fragen:

    und das reicht Dir nicht?

    tja, dafür stelle ich Dir die vierte:
    [4] Warum stellst Du Dir nicht einfach ein Shellskript zusammen, das für jeden einzelnen Schüler einen entsprechende Befehlszeile enthält? Führe anschließend dieses Shellskript aus.

    Vincens te salutat.

    1. hi,

      Warum stellst Du Dir nicht einfach ein Shellskript zusammen, das für jeden einzelnen Schüler einen entsprechende Befehlszeile enthält?

      Hat er doch geschrieben:
      Weil beim Aufruf mit dieser Syntax jedes mal ein neuer Login stattfindet, und ICQ darauf nach einer handvoll sauer reagiert.

      gruß,
      wahsaga

      --
      /voodoo.css:
      #GeorgeWBush { position:absolute; bottom:-6ft; }
      1. Hallo wahsaga,

        mea culpa.

        Warum stellst Du Dir nicht einfach ein Shellskript zusammen, das für jeden einzelnen Schüler einen entsprechende Befehlszeile enthält?

        Hat er doch geschrieben:
        Weil beim Aufruf mit dieser Syntax jedes mal ein neuer Login stattfindet, und ICQ darauf nach einer handvoll sauer reagiert.

        Ich hatte überlesen, dass jeder Aufruf von micq ein Login verursacht und den folgenden Abschnitt

        So - was spricht dagegen, einfach das auf mehrere Aufrufe aufzuteilen? Das geht deshalb nicht, weil sich für jeden Aufruf neu eingeloggt wird - und bei mehr als 5 mal einloggen in 30 Minuten oder so blockiert der ICQ Server, geht also auch nicht.

        völlig missverstanden.

        Als erstes würde ich versuchen, die maximale Anweisungslänge zu ermitteln. Reicht diese nicht aus, wäre es einen Versuch mit einer Pipe wert.

        Freundliche Grüße

        Vinzenz

        1. Hi Vinzenz,

          Als erstes würde ich versuchen, die maximale Anweisungslänge zu ermitteln. Reicht diese nicht aus, wäre es einen Versuch mit einer Pipe wert.

          Ich habe mir gerade folgendes Shell-Script geschrieben:

          #!/bin/bash

          echo "#!/bin/bash" > micq-test
            echo "" >> micq-test
            echo -n "./micq/bin/micq -u 241664302 -p susanne -C " >> micq-test

          I=1
            while [ $I -le 100 ]
            do
              echo -n ""msg $1 Hallo $1, dies ist die $I. Nachricht, es wurde ein neuer Vertretungsplan hochgeladen für den xx.xx.xxxx, Version x - laut diesem Plan sind folgende Stunden bei dir betroffen: 1. Stunde - Mathe, 2. Stunde - Deutsch. Der Plan ist einzusehen unter http://www.gymnasium-odenthal.de/vp/plan-xx-xx-xxx.html - Fehler bitte bei Dennis Riehle melden." " >> micq-test
              I=expr $I + 1
            done

          echo ""exit"" >> micq-test

          Aufgerufen mit ./generate Dennis generiert es mir die Shell-Datei, die ich dann nur noch ausführen muss. Habe ich dann auch gemacht - Nachricht 1, sowie Nachricht 94 bis 100 sind angekommen bei mir, alle anderen nicht.

          100 Nachrichten scheinen also wohl vom Programm angenommen zu werden, jedoch werden wohl irgendwie nur knapp 10 versendet - möglicherweise muss ich die mit einer gewissen Pause dazwischen versenden...

          MfG, Dennis.

          1. Hi Ingrid,

            echo -n "./micq/bin/micq -u 241664302 -p susanne -C " >> micq-test

            Copy & Paste sind zwei sehr gefährliche Funktionen ;-)

            MfG, Dennis.

          2. Hallo Dennis,

            echo -n "./micq/bin/micq -u 241664302 -p susanne -C " >> micq-test

            dieses Passwort hält einem Wörterbuchangriff nicht stand ;-)

            Freundliche Grüße

            Vinzenz

    2. Hallo Vinzenz.

      [4] Warum stellst Du Dir nicht einfach ein Shellskript zusammen, das für jeden einzelnen Schüler einen entsprechende Befehlszeile enthält? Führe anschließend dieses Shellskript aus.

      Ich schätze deswegen:

      Das geht deshalb nicht, weil sich für jeden Aufruf neu eingeloggt wird - und bei mehr als 5 mal einloggen in 30 Minuten oder so blockiert der ICQ Server, geht also auch nicht.

      Ave Dennis,
      Vincens te salutat.

      Der Aprilscherz von letztem Jahr hat wohl einen tiefen Eindruck hinterlassen.

      Einen schönen Montag noch.

      Gruß, Ashura

      --
      sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
      „It is required that HTML be a common language between all platforms. This implies no device-specific markup, or anything which requires control over fonts or colors, for example. This is in keeping with the SGML ideal.“
      [HTML Design Constraints: Logical Markup]
      1. Hallo

        Ave Dennis,
        Vincens te salutat.

        Der Aprilscherz von letztem Jahr hat wohl einen tiefen Eindruck hinterlassen.

        nein, eher das Ausgangsposting:

        Und das ist die Stelle, wo ich mit meinem Latein am Ende [...]

        Freundliche Grüße

        Vinzenz

    3. Hi Vinzenz,

      gehst Du unter die ICQ-Spammer?

      Nein, das ist ja nur für die Schüler unserer Schule, die sich da eingetragen haben ;-) Und ja, ich werde da schon einen entsprechenden Schutz einbauen, dass nicht einfach jeder da beliebige ICQ-Nummern eintragen kann.

      ./micq -u <ICQ-Nr> -p <Passwd> -C "msg <Empf>[,<Empf2>] <Nachricht>"
      Und das ist die Stelle, wo ich mit meinem Latein am Ende bis - zwei[2] Fragen:

      und das reicht Dir nicht?

      tja, dafür stelle ich Dir die vierte:
      [4] Warum stellst Du Dir nicht einfach ein Shellskript zusammen, das für jeden einzelnen Schüler einen entsprechende Befehlszeile enthält? Führe anschließend dieses Shellskript aus.

      Möglicherweise ist das in dem (etwas längeren) Posting untergegangen:

      So - was spricht dagegen, einfach das auf mehrere Aufrufe aufzuteilen? Das geht deshalb nicht, weil sich für jeden Aufruf neu eingeloggt wird - und bei mehr als 5 mal einloggen in 30 Minuten oder so blockiert der ICQ Server, geht also auch nicht.

      Wenn ich dich richtig verstehe, plädierst du für so ein Shell-Script:

      ./micq ... -C "msg User1 Nachricht" "exit"
        ./micq ... -C "msg User2 Nachricht2" "exit"
        usw.

      Aber das geht aus oben genanntem Grund nicht - das hat ja auch seine Richtigkeit irgendwo finde ich. Oder verstehe ich dich falsch und du meinst etwas anderes?

      MfG, Dennis.

  2. Hi,

    handrolled is best :)

    da ich von icq gar nicht begeistert bin, aber natürlich der generelle gruppenzwang besteht, bin ich dazu übergegangen jabber zu benutzen. such dir einen geeigneten server, der einen ICQ transport unterstützt.
      ich kenne leider nur das Perl Modul, aber ich schätze es sehr. Evtl gibt es ja für PHP etwas Ähnliches.

    es gab mal einen recht einfachen artikel bei heise, aber natürlich find ich den auf anhieb nicht ...

    gruss

    --
    Swiss Army Chainsaw
    Terrorific!
    Given a cow full of milk, should the milk un-cow itself, or should the cow milk itself?
    1. Hallo,

      es gab mal einen recht einfachen artikel bei heise, aber natürlich find ich den auf anhieb nicht ...

      äh ja, kein wunder

      gruss

      --
      Swiss Army Chainsaw
      Terrorific!
      Given a cow full of milk, should the milk un-cow itself, or should the cow milk itself?
    2. Hi Eternius,

      ich kenne leider nur das Perl Modul, aber ich schätze es sehr. Evtl gibt es ja für PHP etwas Ähnliches.

      Ich habe eine class.jabber.php gefunden, die sehr viel versprechend aussieht auf den ersten Blick - Google hält weitere Ergebnisse parat.

      da ich von icq gar nicht begeistert bin, aber natürlich der generelle gruppenzwang besteht, ...

      geht mir genauso...

      ...bin ich dazu übergegangen jabber zu benutzen. such dir einen geeigneten server, der einen ICQ transport unterstützt.

      Hm, als das mit dem Transport (auch in Wikipedia) habe ich vom Prinzip her schon verstanden - ich weiß nur noch nicht, wie ich an so einen Server gelange und wie ich in letztlich verwende.

      Zuerst mal habe ich hier eine Liste der verbreitesten Server gefunden, aber das scheint irgendwie mehr die Server-Software zu sein, wenn ich das richtig verstanden habe. Dann habe ich hier noch eine weitere Serverliste gefunden - doch welchen Server kann und darf ich nutzen?

      MfG, Dennis.

      1. Hi,

        Hm, als das mit dem Transport (auch in Wikipedia) habe ich vom Prinzip her schon verstanden - ich weiß nur noch nicht, wie ich an so einen Server gelange und wie ich in letztlich verwende.

        ui, ich meinte eigentlich einen server der die services schon bereitstellt wie http://web.amessage.info/ oder http://jabber.ccc.de/ (also keinen selber installieren), da registrierst du deinen bot account und gut ist.
          der transport heisst dann (für den ersten server) icq.amessage.info und nennt sich JIT, bei dem musst du dich mit der bot icq nummer/pwd registrieren (das muss nur einmal gemacht werden, da die icq daten für den transport auf dem server gespeichert werden, ist zumindest bei diesem hier so, zum testen empfehle ich dir den psi messenger, da gibt es einen punkt service discovery)

        wenn sich dann der bot auf dem jabber server einloggt, loggt der server automatisch den bot mit den daten bei icq ein.

        gruss

        --
        Swiss Army Chainsaw
        Terrorific!
        Given a cow full of milk, should the milk un-cow itself, or should the cow milk itself?
        1. Hi Eternius,

          Erst mal vielen Dank für dein Bemühen!

          ui, ich meinte eigentlich einen server der die services schon bereitstellt wie http://web.amessage.info/ oder http://jabber.ccc.de/ (also keinen selber installieren), da registrierst du deinen bot account und gut ist.

          Ja, so habe ich es jetzt auch gemacht und auch gemeint ;-)

          der transport heisst dann (für den ersten server) icq.amessage.info und nennt sich JIT, bei dem musst du dich mit der bot icq nummer/pwd registrieren (das muss nur einmal gemacht werden, da die icq daten für den transport auf dem server gespeichert werden, ist zumindest bei diesem hier so, zum testen empfehle ich dir den psi messenger, da gibt es einen punkt service discovery)

          Es hatte ein Weilchen gedauert, bis ich alles so herausgefunden habe, aber jetzt klappt es, dass ich mit PSI anmelde und die ICQ User online sehe und in ICQ auch den Jabber-User online sehe.

          Jetzt habe ich also dann versucht, mich mit der class.jabber.php einzuloggen, dazu folgendes PHP Script (Ausschnit):

          $jabber->server   = "jabber.freenet.de";  
          $jabber->port     = 5222;  
          $jabber->username = "vpsystems@jabber.freenet.de";  
          $jabber->password = "driehle";  
          $jabber->resource = "ClassJabberPHP";  
            
          $jabber->Connect() or print("Error while connecting");  
          $jabber->SendAuth() or print("Error while authenticating");
          

          Die class.jabber.php ist immer noch diese hier - ist das jetzt irgendwo ein direkter Fehler zu erkennen? Es bleibt einfach nur bei einem "Error while authenticating", ein Aktivieren der Fehlermeldungen der Klasse hat noch das hier an den Tag gebracht:

          SEND: <iq type='get' id='auth_66c32e46f7fe3f17307ab65886003fd7'>
                  <query xmlns='jabber:iq:auth'>
                     <username>vpsystems@jabber.freenet.de</username>
                  </query>
                </iq>

          RECV: <iq type='error' id='auth_66c32e46f7fe3f17307ab65886003fd7'>
                  <query xmlns='jabber:iq:auth'>
                    <username>vpsystems@jabber.freenet.de</username>
                  </query>
                  <error code='406'>Not Acceptable</error>
                </iq>

          Es scheint also, als ob die Klasse sich versuchen würde zu authentifizieren, dies jedoch fehl schlägt. Anschließend versucht die Klasse dann den Account zu registrieren, was der Sever aber mit "Bitte Benutzername und Passwort angeben" kommentiert.

          Mache ich jetzt etwas falsch (z.B. falsche Verbindungsdaten) oder liegts an der Klasse? (Ich glaube ja eher ersteres *g*)

          MfG, Dennis.

          1. Hi :D

            so versuche er folgendes:

            $jabber->server   = "jabber.freenet.de";

            $jabber->port     = 5222;
            $jabber->username = "vpsystems@jabber.freenet.de";

            $jabber->username   = "vpsystems";

            $jabber->password = "driehle";
            $jabber->resource = "ClassJabberPHP";

            $jabber->Connect() or print("Error while connecting");
            $jabber->SendAuth() or print("Error while authenticating");

              
            gruss
            
            -- 
            Swiss Army Chainsaw  
              
            Terrorific!  
            Given a cow full of milk, should the milk un-cow itself, or should the cow milk itself?
            
            1. Hi Eternius,

              so versuche er folgendes:
              $jabber->username   = "vpsystems";

              Ah - ja, das funktioniert einwandfrei! Danke.

              Ok, nächstes Problem ;-) Jetzt geht es an das Versenden einer Nachricht:

              $jabber->SendMessage("238968xxx@icq.jabber.freenet.de", NULL, NULL,  
                                   array("body" => "Hallo Dennis", "thread" => "01"));
              

              Als Ausgabe erhalte ich:

              SEND: <message to='238968xxx@icq.jabber.freenet.de' type='' id='_1144084996'>  
                      <thread>01</thread>  
                      <body>Hallo Dennis</body>  
                    </message>
              

              Ich sehe nirgendwo etwas von einer Fehlermeldung (habe das $jabber->enable_logging direkt vor SendMessage gesetzt). Bei mir in ICQ kommt keine Nachricht an (im Gegensatz zu einer über PSI versendeten Nachricht).

              Einfach mal ganz konkret die Frage in den Raum gestellt: Was mache ich falsch?

              MfG, Dennis.

              1. Hi :)

                Ok, nächstes Problem ;-) Jetzt geht es an das Versenden einer Nachricht:

                $jabber->SendMessage("238968xxx@icq.jabber.freenet.de", NULL, NULL,

                array("body" => "Hallo Dennis", "thread" => "01"));

                  
                  ich verwende nur den Message Typ 'chat', falls das nicht funktioniert, anderen server probieren, falls das nicht funktioniert ... :(  
                  
                gruss
                
                -- 
                Swiss Army Chainsaw  
                  
                Terrorific!  
                Given a cow full of milk, should the milk un-cow itself, or should the cow milk itself?
                
                1. Hi Eternius,

                  $jabber->SendMessage("238968xxx@icq.jabber.freenet.de", NULL, NULL,

                  array("body" => "Hallo Dennis", "thread" => "01"));

                  
                  >   
                  > ich verwende nur den Message Typ 'chat', falls das nicht funktioniert, anderen server probieren, falls das nicht funktioniert ... :(  
                    
                  "chat" verändert nichts - allerdings habe ich gerade parallel PSI auf meinem PC am laufen und bin dort online, so kommt meine Nachricht an. Ich vermute es liegt an dem ICQ Transfer - wahrscheinlich muss ich den im Script noch explizit herstellen...  
                    
                  Dafür habe ich erst mal das hier mir angeguckt:  
                    
                  ~~~php
                  $foo = $jabber->TransportRegistrationDetails("icq.jabber.freenet.de");  
                  print_r($foo);
                  

                  Ausgabe:

                  Array
                  (
                      [0] => username
                      [1] => password
                      [2] => registered
                      [3] => x
                  )

                  Das sind also anscheinen die Informationen, die TransportRegistraion() haben will.

                  $jabber->TransportRegistration("icq.jabber.freenet.de",  
                                                 array("username" => "238968xxx", "password" => "<PW>")  
                                                 );
                  

                  Allerdings hat auch das nicht geholfen...

                  Ah - ich korrigiere mich - ich habe die falsche ICQ-Nummer bei username verwendet ;-) Ok, jetzt die richtige Nummer verwendet, jetzt kommt immerhin schon mal der Benutzer bei mir in meinem ICQ online. Allerdings bleibt er online und geht nicht mehr offline ^^ Zumindest nicht direkt nachdem das Script fertig ist (welches natürlich $jabber->Disconnect() enthält). Na ja, mal schauen, ob der irgendwann noch von alleine offline geht...

                  Die versendete Nachricht ist allerdings immer noch nicht durchgekommen.

                  MfG, Dennis.

                  1. Hi Ingrid,

                    Die versendete Nachricht ist allerdings immer noch nicht durchgekommen.

                    Korrigiere mich, jetzt ist sie da!

                    Folgendes Verhalten habe ich festgestellt:

                    • Beim ersten Scriptaufruf kommt der User in ICQ online, jedoch keine Nachricht an
                    • Beim weiteren Scriptaufrufen kommt die Nachricht durch
                    • Gehe ich in PSI online und wieder offline, so ist der ICQ User auch wieder offline

                    Irgendwo scheint da also noch ein Bug zu sein, den ich nicht finde:

                    require("class.jabber.php");  
                      
                    $jabber = new Jabber;  
                      
                    $jabber->server   = "jabber.freenet.de";  
                    $jabber->port     = 5222;  
                    $jabber->username = "vpsystems";  
                    $jabber->password = "<PW>";  
                    $jabber->resource = "ClassJabberPHP";  
                      
                    //$jabber->enable_logging = true;  
                    //$jabber->log_filename   = "logfile";  
                      
                    $jabber->Connect() or print("Error while connecting");  
                    $jabber->SendAuth() or print("Error while authenticating");  
                      
                    //$foo = $jabber->TransportRegistrationDetails("icq.jabber.freenet.de");  
                    //print_r($foo);  
                    $jabber->TransportRegistration("icq.jabber.freenet.de", array("username" => "241664xxx", "password" => "<PW>"));  
                      
                    $jabber->SendMessage("238968xxx@icq.jabber.freenet.de", NULL, NULL,  
                                         array("body" => "Hallo Dennis", "thread" => "01"));  
                      
                    $jabber->Disconnect();
                    

                    Vielleicht muss ich den registrierten Transport auch wieder "de-registrieren"... Allerdings finde ich im Manual der class.jabber.php keine Funktion dazu.

                    MfG, Dennis.

                    1. Hi Ingrid,

                      Folgendes Verhalten habe ich festgestellt:

                      • Beim ersten Scriptaufruf kommt der User in ICQ online, jedoch keine Nachricht an

                      - Der User in ICQ bleibt online

                      • Beim weiteren Scriptaufrufen kommt die Nachricht durch
                      • Gehe ich in PSI online und wieder offline, so ist der ICQ User auch wieder offline

                      Da habe ich doch glatt das wichtigste vergessen ;-)

                      Jedenfalls habe ich jetzt folgendes beobachtet: Nach knapp zwei Stunden, war der ICQ User immer noch online, heute morgen - also ca. 11 Stunden später - war er dann wieder offline, er scheint also schon irgendwann von alleine rauszufliegen (was ich auch so erwartet habe, allerdings deutlich früher - und natürlich wundert es mich, dass er nicht direkt nach Scriptende wieder draußen ist).

                      MfG, Dennis.

                      1. Hi Ingrid,

                        Jedenfalls habe ich jetzt folgendes beobachtet: Nach knapp zwei Stunden, war der ICQ User immer noch online, heute morgen - also ca. 11 Stunden später - war er dann wieder offline, er scheint also schon irgendwann von alleine rauszufliegen (was ich auch so erwartet habe, allerdings deutlich früher - und natürlich wundert es mich, dass er nicht direkt nach Scriptende wieder draußen ist).

                        Also - ich habe nun, glaube ich bzw. hoffe ich zumindestens, die Probleme gelöst, als da waren:

                        1. Beim ersten Versuch kommt die Nachricht nicht durch
                        2. Der User in ICQ bleibt online

                        Ich zeige euch einfach noch mal mein jetziges Script:

                        // Erst mal mit den gegebenen Daten Verbindung herstellen  
                        $jabber->Connect() or print("Error while connecting");  
                        // und authentifizieren  
                        $jabber->SendAuth() or print("Error while authenticating");  
                          
                        // Jetzt erst mal noch den Status explizit auf online setzen, es  
                        // gibt glaube ich keine Garantie dafür, dass das automatisch der  
                        // Fall ist!  
                        $jabber->SendPresence(NULL, NULL, "online");  
                          
                        // Den Transport herstellen, wie ich es bis jetzt auch immer gemacht  
                        // habe, mit Benutzername und Passwort  
                        $jabber->TransportRegistration("icq.jabber.freenet.de",  
                                                       array("username" => "241664xxx",  
                                                             "password" => "<PW>")  
                                                       );  
                        // Nun ist eine kleine Pause nötig, bis der Transport auch wirklich  
                        // hergestellt ist - wartet man diese Zeit ab, so kommt der User in  
                        // ICQ auch wirklich online, egal was vorher war  
                        sleep(5);  
                          
                        // Nun schreiben wir die Nachricht bzw. in einer Schleife auch mehrer  
                        // Nachrichten, sollte eigentlich alles problemlos möglich sein  
                        $jabber->SendMessage("238968604@icq.jabber.freenet.de", NULL, NULL,  
                                             array("body" => "Hallo Dennis",  
                                                   "thread" => "01")  
                                             );  
                          
                        // So, hier kommt jetzt die wichtige Stelle, dass der User in ICQ auch  
                        // direkt wieder offline geht und nicht nächsten Stunden da online  
                        // bleibt bis er irgendwann gekickt wird ;-)  
                        // Wir müssen einfach nur explizit unseren Status wieder auf offline  
                        // setzen, und schwupps ist der ICQ User weg!  
                        $jabber->SendPresence("unavailable", NULL, "not there");  
                          
                        // Jetzt einfach nur noch disconnecten - die Methode Disconnect() macht  
                        // eben das Setzen des Status auf offline nicht, sondern bricht einfach  
                        // nur sofort die Verbindung (ordnungsgemäß) ab.  
                        $jabber->Disconnect();
                        

                        Ich habe jetzt also nun die gewünschte Möglichkeit die Nachrichten zu Versenden gefunden, und mit Jabber ist das auf jeden Falle einfacher als direkt über ICQ und vorallem leichter aus PHP zu bedienen, ich brauche keine weitere Software mehr.

                        In diesem Sinne: Alle Fliegen mit einer Klappe geschlagen, noch mal einen herzlichen Dank an Eternius - ich wusste zwar, dass es Jabber gibt, aber es war mir nicht bekannt, dass es diese Transports gibt, mit denen eine Verbindung zum ICQ Netzwerk möglich ist. Du hast mir also die Augen geöffnet Eternius ;-)

                        MfG, Dennis.

                        1. Heißa, Dennis,

                          // So, hier kommt jetzt die wichtige Stelle, dass der User in ICQ auch
                          // direkt wieder offline geht und nicht nächsten Stunden da online
                          // bleibt bis er irgendwann gekickt wird ;-)
                          // Wir müssen einfach nur explizit unseren Status wieder auf offline
                          // setzen, und schwupps ist der ICQ User weg!
                          $jabber->SendPresence("unavailable", NULL, "not there");

                          Warum stört dich, dass der ICQ-Account (im Deutschen schreibt man zusammengesetzte Wörter übrigens mit Bindestrich oder zusammen) online bleibt? Ich persönlich setze auch Jabber-Transports ein, aber ich finde es recht praktisch, dass der ICQ-Account online bleibt, so sperrt mich der ICQ-Server wenigstens nicht wegen zu häufigen Statuswechselns.

                          Gautera!
                          Grüße aus Biberach Riss,
                          Candid Dauth

                          --
                          Ein Fußball-Fan? Noch auf der Suche eine Schlafmöglichkeit im Großraum Stuttgart für die WM 2006? Wie wäre es mit Herrenberg, einer gemütlichen Kleinstadt am Rande des Schönbuchs – von der Lage her ideal, auch für andere Vorhaben im Urlaub. Ferienwohnungen-Herrenberg.com.
                          http://cdauth.de/
                          1. Hi Candid,

                            Warum stört dich, dass der ICQ-Account (im Deutschen schreibt man zusammengesetzte Wörter übrigens mit Bindestrich oder zusammen) online bleibt? Ich persönlich setze auch Jabber-Transports ein, aber ich finde es recht praktisch, dass der ICQ-Account online bleibt, so sperrt mich der ICQ-Server wenigstens nicht wegen zu häufigen Statuswechselns.

                            Stimmt, aber das ist noch mal ein eigenes Thema - in diesem Fall ging es mir lediglich darum, überhaupt eine Möglichkeit zu finden, den ICQ-Account wieder offline zu bringen ;-) Für die Praxis ist es natürlich (insbesondere sofern man häufiger den Status wechselt) besser, den ICQ-Account dann online zu lassen.

                            Andererseits ist mein Script ja eigentlich eh mehr dafür gedacht, _ständig_ online zu sein - im Normalfall soll der eigentlich nie offline sein ;-)

                            MfG, Dennis.

  3. Hi,

    Ich bin natürlich mittlerweile fleißig am weiterarbeiten - und da möchte ich für Leute die eventuell über das Archiv auf diesen Thread stoßen noch ein paar Anmerkungen los werden - oder für den Fall, das auch jetzt jemand darüber diskutieren will ;-)

    Problem 1: Der Login

    Worauf man achten muss ist, dass die ICQ-Server nach zu häufigen Logins und Logouts einen nicht mehr rein lassen, d.h. das Script läuft weiterhin recht fehlerfrei ab, weil der Login in Jabber problemlos klappt, aber der Transport zu ICQ klappt eben nicht und die gesendeten Nachrichten kommen nicht an.

    Man wird wenn man so etwas testet wohl nicht mir einem ICQ-Accoutn auskommen ;-) Ich arbeite zur Zeit z.B. mit 4 Accouts, 3 für diese Sache und der eine, den ich selber normal verwende - Schade nur, das ICQ keine Möglichkeit bietet Accounts zu löschen, aber na ja - das ist nicht mein Problem *fg*

    Ich arbeite zur Zeit so: ICQ gestartet mit meinem normalen User, PSI gestartet mit dem einen Jabber Account und einem der 3 Test-User für den ICQ-Transport - und dann noch die Kommandozeile vom Server, von dem aus das Script läuft, wie PSI bei mir lokal. Dann schreibe ich mir immer Nachrichten an meinen Hauptaccount in ICQ ;-)

    Das Problem mit dem Login ist daran zu erkennen, wenn der verwendete der 3 User in ICQ gar nicht erst onlinen kommt, eventuell eine Fehlermeldung "Turboing, connect later", Lösung: Einfach den nächsten Account nutzen ;-)

    Problem 2: Nachrichten mit Umlauten

    Sobald ich versucht habe, eine Nachricht mit Umlauten zu senden, hat nichts mehr geklappt, folgendes Phänomen: Der verwendete der drei User ist in ICQ online gekommen, war die 5 Sekunden bis das Script mit dem Versenden der Nachrichten beginnt online und ist mit dem ersten Versenden der Nachrichten offline gegangen. Für diese Nachricht wurde beim Versenden im Script noch Erfolg gemeldet, für die Nachfolgenden Fehlschlag.

    Ich habe zuerst versucht, die Umlaute als UTF8 zu kodieren mit utf8_encode(), hat nicht funktioniert, dann habe ich versucht sie mit &uuml; usw. zu kodieren, ebenfalls negativ.

    Es scheint ausschließlich zu funktionieren, wenn man alle Sonderzeichen, also alle nicht-alphanumerischen Zeichen als numerische Referenzen notiert, also z.B. für ein kleines ü: &#252;

    Die Länge und Zeilenumbrüche in der Nachricht sind egal - das hatte ich zuerst auch noch als Fehlerkritierien betrachtet, kann ich jetzt aber ausschließen, ich habe jetzt schon Nachrichten über 6000 Zeichen verschickt, ebenfalls mit Zeilenumbruch.

    Allerdings scheint aber einer bestimmten Länge eventuell der ICQ-Spam Filter einzuspringen - die Kritieren hierzu konnte ich noch nicht feststellen, Fakt ist, dass Sven (der so freundlich ist mir beim Testen zu helfen, Danke Sven!!) eine Meldung des Spam-Filters bekommen hat und ich nicht, obwohl wir beide die selben Texte zugeschickt bekommen haben.

    Empfehlenswert sind Abstände von 5 Sekunden beim Senden der Nachrichten, dann konnte ich bis jetzt beliebig lange Nachrichten verschicken, eventuell sind auch Abstände von 3 Sekunden noch drin, weniger ist aber nicht möglich. Bei Abständen von einer Sekunde ist nach 16 Nachrichten irgendwann Schluss und man fliegt raus - ein sinnvoller Schutz von ICQ gegen Spam!

    MfG, Dennis.

    1. Hi Ingrid,

      Empfehlenswert sind Abstände von 5 Sekunden beim Senden der Nachrichten, dann konnte ich bis jetzt beliebig lange Nachrichten verschicken, eventuell sind auch Abstände von 3 Sekunden noch drin, weniger ist aber nicht möglich. Bei Abständen von einer Sekunde ist nach 16 Nachrichten irgendwann Schluss und man fliegt raus - ein sinnvoller Schutz von ICQ gegen Spam!

      Ich habe mittlerweile mal noch ein paar weitere Tests gemacht - es ist mir gelungen, 60 Nachrichten (an zwei Leute jeweils 30 Stück) im 4 Sekunden Takt zu verschicken, im 3 Sekunden Takt ist bereits nach etwas über 20 Nachrichten Schluss, im 3,5 Sekunden Takt sind die letzten 6 Nachrichten nicht mehr angekommen. Wenn man von einem 4 Sekunden Takt ausgeht, so kann man in 300 Nachrichten in 20 Minuten verschicken, das dürfte für die meisten Zwecke ausreichen, ansonsten kann man ja auch mit zwei Bots arbeiten, die parallel Nachrichten verschicken.

      MfG, Dennis.

  4. Hi again,

    ich habe gerade noch eine weitere Feststellung gemacht - nachdem die Jabber-Bots (mit ICQ Transport) eine Nacht durchgelaufen waren (und einfach nur online bzw. "Away" waren und nur geantwortet haben, wenn jemand geschrieben hat, sonst aber nichts gemacht haben), waren sie in ICQ offline, in Jabber aber weiterhin online.

    Schmeißt ICQ einen nach einer bestimmten Zeit raus, sodass ich mich neu einloggen muss? Kann ich irgendwie feststellen, dass ich in ICQ rausgeflogen bin (im PHP Script)?

    MfG, Dennis.

    1. Hallo,

      Schmeißt ICQ einen nach einer bestimmten Zeit raus, sodass ich mich neu einloggen muss?

      vermutlich; aber am Protokoll wurde in letzter Zeit Modifizierungen vergenommen.

      Kann ich irgendwie feststellen, dass ich in ICQ rausgeflogen bin (im PHP Script)?

      Das ist nur durch einen kleinen Trick mit if([link:http://de3.php.net/manual/de/function.stream-socket-get-name.php@title=stream_socket_get_name]($stream,TRUE)!==FALSE){} möglich. fwrite(), feof() und der Gleichen melden leider nicht, wenn die Verbindung zusammenbricht ;(

      Nun kommt es darauf an, wie Du Dein Script aufgebaut hast. Wenn es in einer while(1)-Schleife mit fgets() auf eigehende Daten an einer blockierten Verbindung wartet, kannst Du natürlich nicht feststellen, ob derweil die Verbindung bereits geschlossen wurde. Das Script wird bis zum konfigurierten/programmierten timeout beflissen warten und warten und warten und... Daher arbeite ich mit kürzeren timeouts, die die Verbindung clientseitig schließen. Das hat so seinen Grund. Allerdings hilft Dir das in Deinem Fall nicht weiter, da Du ja so lange, wie Du nicht gekickt wirst, bemüht bist die Verbindung zu halten.

      Also würde ich an Deiner Stelle die Verbindung öffnen und sie mit stream_set_blocking() entblocken. Das wirklich ärgerliche dabei ist, daß hierbei verschiedene Nebeneffekte zu beobachten sind. So mußt Du in der while-Schleife, deren Anweisungsblock für das Auslesen der Daten aus der Verbindung verantwortlich ist, mit usleep() selbst dafür sorgetragen, daß Dir der Prozess nicht alle Systemresourcen auffrist. Sind dann wirklich Daten da, kann es Dir passieren, daß Du mit einem fgets() nicht alle Daten einer ICQ-Message mit einmal bekommst, denn die Verbingung ist ja nicht blockiert. Soweit nur zu den Gründen, warum ich darauf so erpicht bin, nach Möglichkeit Verbindungen clientseitig mit einem timeout zu versehen ;)

      (BTW.: Die Funktion stream_get_meta_data(), bei der man ja vermuten dürfte, daß man z. B. den Verbindungsstatus, aber auch unter "unread_bytes" die empfangene Datengröße ablesen kann, ist totaler Schrott!)

      Ich hatte Dir oben ja geschrieben, daß timeouts ja auch clientseitig gesetzt werden können. Möglicher Weise ist genau _das_ Dein eigentliches Problem. Mit oben beschreibenem Steuerfluß einer nicht blockierten Verbindung kannst Du innerhalb Deiner while-Schleife eine Routine einbauen, die mit stream_set_timeout() in einem Interval dafür sorgt, daß das timeout regelmäßig aufgefrischt wird.

      Gruß aus Berlin!
      eddi

      1. Hi eddi,

        Das ist nur durch einen kleinen Trick mit if([link:http://de3.php.net/manual/de/function.stream-socket-get-name.php@title=stream_socket_get_name]($stream,TRUE)!==FALSE){} möglich. fwrite(), feof() und der Gleichen melden leider nicht, wenn die Verbindung zusammenbricht ;(

        Nun, ich kommuniziere ja nicht direkt mit ICQ - ich arbeite über Jabber, welches einen Transport zu ICQ hergestellt hat, dazu verwende ich die class.jabber.php - ich denke das einfachste wird sein, wenn ich einfach mich automatisch alle 2 Stunden aus- und wieder einlogge.

        MfG, Dennis.

        1. Hi Ingrid,

          ich denke das einfachste wird sein, wenn ich einfach mich automatisch alle 2 Stunden aus- und wieder einlogge.

          Ok - auf die Art und Weise mache ich es jetzt einfach, bis jetzt keine Probleme damit.

          MfG, Dennis.

  5. Hi liebes Forum,

    nachdem ihr mir alle jetzt kräftig geholfen habt, wofür ich mich hiermit nochmmals herzlich Bedanke(!), möchte ich diesen Thread nun schließen. Für später im Archiv suchende stelle ich hiermit noch mein Script zur Verfügung, welches gerne verwendet werden kann. Man benötigt allerdigns für das Script in dieser Form PHP5.

    ============= Start jabber-bot1.php ============

    #!/usr/local/bin/php5  
    <?php  
      
    // configuration  
    define("BOT", "Bot1");  
    define("PID_FILE", "run/jabber-bot1.pid");  
    define("LOG_FILE", "logs/jabber-bot1.log");  
      
    // be nice and say hello  
    echo "This is Jabber " . BOT . ", I am starting...\n";  
      
    // check if there is already a bot running  
    if(file_exists(PID_FILE)) {  
      echo "PID File exists, perhabs there's already a bot running?\n";  
      echo "Aborting...\n";  
      exit;  
    }  
      
    // fork, so that process is running in the backround  
    $pid = pcntl_fork();  
    if($pid == -1) {  
      echo "Could not fork, exit.\n";  
      exit;  
    }  
    elseif($pid) {  
      echo "Jabber Bot forked, its PID is $pid.\n";  
      exit;  
    }  
    elseif(!posix_setsid()) {  
      echo "Could not detach from terminal, exit.\n";  
      exit;  
    }  
    else {  
      // write pid into pid file  
      file_put_contents(PID_FILE, posix_getpid());  
      // log startup  
      $log = "[" . date("Y-m-d H:i:s") . "] Started up\n";  
      file_put_contents(LOG_FILE, $log, FILE_APPEND);  
    }  
      
    // register shutdown and restart functions  
    pcntl_signal(SIGTERM, "shutdown");  
    pcntl_signal(SIGHUP,  "restart");  
    pcntl_signal(SIGINT,  "shutdown");  
      
    // load some stuff we need  
    require("class.jabber.php");  
    $config = parse_ini_file("accounts.conf", true);  
      
    // the class for answering  
    require("./responds.class.php");  
    $responds = new Responds;  
      
    // create jabber instance with parameters  
    $jabber = new Jabber;  
    $jabber->server   = $config['Jabber']['server'];  
    $jabber->port     = $config['Jabber']['host'];  
    $jabber->resource = "ClassJabberPHP";  
      
    // set username and password for this bot  
    $jabber->username = $config[BOT]['jabber_id'];  
    $jabber->password = $config[BOT]['jabber_pw'];  
      
    // connect and log in  
    $jabber->Connect() or die("Error while connecting\n");  
    $jabber->SendAuth() or die("Error while authenticating\n");  
      
    // register transport for ICQ  
    @$jabber->TransportRegistration(  
               $config['Jabber']['transport'],  
               array(  
                 "username" => $config[BOT]['transport_id'],  
                 "password" => $config[BOT]['transport_pw']  
               )  
             );  
      
    // need to wait some seconds, till transport is established!  
    sleep(10);  
      
    // tell them we're online  
    $jabber->SendPresence(NULL, NULL, $responds->GetPresence(), "away");  
      
    // declare ticks  
    declare(ticks=1);  
      
    // start with main programm  
    while(true) {  
      // get packets that came in  
      $jabber->Listen();  
      // and react to the first one  
      $packet = $jabber->GetFirstFromQueue();  
      if($packet !== false AND isset($packet['message'])) {  
        $from    = $jabber->GetInfoFromMessageFrom($packet);  
        $message = $jabber->GetInfoFromMessageBody($packet);  
        $answer  = $responds->GetRespond($message);  
        $answer  = $responds->escape($answer);  
        $jabber->SendMessage(  
                  $from,  
                  "chat",  
                  NULL,  
                  array(  
                    "body" => $answer,  
                    "thread" => "01"  
                  )  
                );  
        $log = "[" . date("Y-m-d H:i:s") . "] Answered to message of " . $from . "\n";  
        file_put_contents(LOG_FILE, $log, FILE_APPEND);  
      }  
      sleep(5);  
    }  
      
    // what to by shutdown  
    function shutdown($sig) {  
      global $jabber;  
      echo BOT . ": Received " . ($sig == SIGTERM ? "SIGTERM" : "SIGINT") . "... \n";  
      // disconnect from jabber  
      $jabber->SendPresence("unavailable", NULL, "offline");  
      $jabber->Disconnect();  
      // delete pid file  
      if(file_exists(PID_FILE)) {  
        unlink(PID_FILE);  
      }  
      // log shutdown  
      $log = "[" . date("Y-m-d H:i:s") . "] Shutted down\n";  
      file_put_contents(LOG_FILE, $log, FILE_APPEND);  
      exit;  
    }  
      
    // what to do by restarting  
    function restart() {  
      // forget messages in queue  
      $jabber->packet_queue = array();  
      // disconnect from jabber  
      $jabber->SendPresence("unavailable", NULL, "offline");  
      $jabber->Disconnect();  
      // connect and log in  
      $jabber->Connect() or die("Error while connecting\n");  
      $jabber->SendAuth() or die("Error while authenticating\n");  
      $jabber->SendPresence(NULL, NULL, $responds->GetPresence(), "away");  
      // log restart  
      $log = "[" . date("Y-m-d H:i:s") . "] Restarted\n";  
      file_put_contents(LOG_FILE, $log, FILE_APPEND);  
    }  
      
    ?>
    

    ============= Ende jabber-bot1.php =============

    Der Name des Scriptes ist egal - es ist dafür ausgelegt, über Kommandozeile gestartet zu werden!
    In den ersten drei Zeilen wird das Script konfiguriert - es muss erst mal festgelegt werden, wie der Bot sich identifiziert. Einfach auf Bot1 lassen, sofern man nicht mehrere Bots parallel verwendet. Anschließend kann noch der Pfad zum PID und zum Log-File festgelegt werden.

    Man braucht allerdings noch folgende Datei namens accounts.conf:

    ============= Start accounts.conf ==============

    ; Login Information to Jabber Server  
      
    [Jabber]  
    server = "jabber.freenet.de"  
    host = 5222  
    transport = "icq.jabber.freenet.de"  
      
    ; Account Information for Bots  
      
    [Bot1]  
    jabber_id = "Jabber-ID"  
    jabber_pw = "Passwort für Jabber ID"  
    transport_id = "ICQ Nummer"  
    transport_pw = "Passowrt für ICQ Nummer  
      
    ; es können weitere Blöcke für weitere Bots  
    ; folgen, der Name des Bots muss der PHP-Konstante  
    ; BOT entsprechen.  
      
    ; EOF
    

    ============= Ende jabber-bot.php ==============

    Die Informationen im [Jabber] Block müsste man natürlich noch entsprechend anpassen, jenachdem welchen Jabber-Server man verwendet.

    Starten lässt sich der Bot (sofern man im Verzeichnis des PHP-Scriptes ist) einfach mit
      ./jabber-bot1.php
    Beenden lässt er sich mit
      kill cat run/jabber-bot1.pid
    Und neustarten geht mit
      kill -HUP cat run/jabber-bot1.pid
    Damit wird auch direkt klar, dass für solche Spielereien Kommandozeilen-Zugriff vorausgesetzt ist ;-)

    In diesem Sinne wünsche ich also viel Spaß mit dem Script und self.close() ;-)

    MfG, Dennis.

    1. Hi Ingrid,

      function shutdown($sig) {

      global $jabber;
        echo BOT . ": Received " . ($sig == SIGTERM ? "SIGTERM" : "SIGINT") . "... \n";

        
      Das das Script nicht auf einer Shell läuft, führt das echo zu einem Absturz und somit schlägt der Shutdown fehl, der ICQ User bleibt online und die PID-Datei wird nicht gelöscht. Um dieses Problem zu umgehen muss die Zeile mit echo komplett gelöscht werden - wer will kann die Information ja auch noch ins Log-File schreiben.  
        
        
      MfG, Dennis.
      
      -- 
      Mein SelfCode: [ie:{ fl:( br:> va:) ls:\[ fo:) rl:( n4:# ss:) de:\] js:| ch:{ sh:| mo:} zu:|](http://www.peter.in-berlin.de/projekte/selfcode/?code=ie%3A%7B+fl%3A%28+br%3A%3E+va%3A%29+ls%3A%5B+fo%3A%29+rl%3A%28+n4%3A%23+ss%3A%29+de%3A%5D+js%3A%7C+ch%3A%7B+sh%3A%7C+mo%3A%7D+zu%3A%7C)  
        
      [MySQLDBExport - Eine PHP Klasse für MySQL Dumps](http://tutorial.riehle-web.com/scripts/#mysql)  
      [schweinisch](http://www.schaumerlmal.de/blog/log.php/2006/04/schweinisch) - [www.schaumerlmal.de](http://www.schaumerlmal.de/blog/)