Помощь, связанная с IRC


Теперь у меня есть мой бот, чтобы отправлять сообщения, когда бот присоединяется. Однако как мне создать форму, в которой будут публиковаться данные, чтобы бот передал сообщение каналу?

Вот мой сценарий (переделанный):

<?php
set_time_limit(0);

$socket = fsockopen("//", 6667) or die();

$msg = $_POST['message'];
$pr = $_POST['percentage'];
$pr /= 100;

fputs($socket,"USER BOT 0 zo :ZH bot\n");
// Set the bots nickname
fputs($socket,"NICK BOT1\n");

fputs($socket,"JOIN #bots\n");

while(1) {

   while($data = fgets($socket, 128)) {
      // echo the data received to page
      echo nl2br($data);
      // flush old data, it isn't needed any longer.
      flush();

      $ex = explode(' ', $data);

      if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."\n");

      $search_string = "/^:([A-Za-z0-9_\-]+)[@!~a-zA-Z0-9@\.\-]+\s*([A-Z]+)\s*[:]*([\#a-zA-Z0-9\-]+)*\s*[:]*([!\#\-\.A-Za-z0-9 ]+)*/";

      $do = preg_match($search_string, $data, $matches);

      // check that there is a command received
      if(isset($matches['2'])) {
         switch($matches['2']) {
            case "PRIVMSG":
               $user = $matches['1'];
               $channel = $matches['3'];
               $chat_text = isset($matches['4']) ? $matches['4'] : "";

               // check chat for !time
               if(strtolower($chat_text) == "!time") { 
                  $output = "::::: " . date('l jS \of F Y h:i:s A') . " :::::";
                  fputs($socket, "PRIVMSG " . $channel . " :" . $output . "\n");
               } elseif(strtolower($chat_text) == "!hello") {
                  fputs($socket, "PRIVMSG " . $channel . " :Hello!\n");
               }
            break;

            case "JOIN":
               $user = $matches['1'];
               $channel = $matches['3'];
               fputs($socket, "PRIVMSG " . $channel . " :Welcome " . $user . " to " . $channel . "\n");
            break;
         }

      }
   }
}
?>

Например, создание формы, которая отправляла бы данные в IRC-канал. Выводом будет "информационный порт файла wget" < - Это будет текст, отправленный на IRC-канал.

Вот связанные части:

fputs($socket, "PRIVMSG " . $channel . " :Welcome " . $user . " to " . $channel ."\n");

Надеюсь, кто-нибудь сможет помочь.

 2
Author: hakre, 2010-11-19

2 answers

Хорошо, вот лучший ответ. Первая секция все еще стоит. Новый процесс PHP вызывается каждый раз, когда вы хотите запустить новый скрипт. Таким образом, вам нужен какой-то способ сделать IPC.

Вот как это делается на *nix (но не в Windows) в PHP:

Приемник:

<?php
$queueKey = 123321;

$queue = false;
if(msg_queue_exists($queueKey)) {
        echo "Queue Exists.\n";
}

// Join the queue
$queue = msg_get_queue($queueKey);

while(!($queue == false)) {
        // Note: This function could block if you feel like threading
        $msgRec = msg_receive(
                $queue,        // I: Queue to get messages from
                0,             // I: Message type (0 = first on queue)
                $msgType,      // O: Type of message received
                1024,          // I: Max message size
                $msgData,      // O: Data in the message
                true,          // I: Unserialize data
                MSG_IPC_NOWAIT // I: Don't block
        );

        if($msgRec) {
                echo "Message received:\n";
                echo "Type = $msgType\n";
                echo "Data = \n";
                print_r($msgData);
        }
}
?>

Отправитель:

<?php
$queueKey = 123321;

$queue = false;
if(msg_queue_exists($queueKey)) {
        echo "Queue Exists.\n";
} else {
        echo "WARNING: Queue does not exist. Maybe no listeners?\n";
}

$queue = msg_get_queue($queueKey);

$abc["something"] = "something value";
$abc["hello"] = "world";
$abc["fu"] = "bar";
msg_send(
        $queue, // Queue to send on
        1,      // Message type
        $abc,   // Data to send
        true,   // Serialize data?
        true    // Block
);

?>

Это должно привести (в контуре приемника) к чему-то подобному этому:

Message received:
Type = 1 
Data =
Array 
(
    [something] => something value
    [hello] => world
    [fu] => bar 
)

Ваш сценарий может выглядеть примерно так это

PostToMe.php :

<?php
$queueKey = 123321;

$queue = false;
if(msg_queue_exists($queueKey)) {
        echo "Queue Exists.\n";
} else {
        echo "WARNING: Queue does not exist. Maybe no listeners?\n";
}

$queue = msg_get_queue($queueKey);

msg_send(
        $queue, // Queue to send on
        1,      // Message type
        $_POST, // Data to send
        true,   // Serialize data?
        true    // Block
);

?>

Bot.php :

<?php 
set_time_limit(0); 

$socket = fsockopen("//", 6667) or die(); 

$msg = $_POST['message']; 
$pr = $_POST['percentage']; 
$pr /= 100; 

fputs($socket,"USER BOT 0 zo :ZH bot\n"); 
// Set the bots nickname 
fputs($socket,"NICK BOT1\n"); 

fputs($socket,"JOIN #bots\n"); 


$queueKey = 123321;
$queue = false;

// Join the IPC queue
$queue = msg_get_queue($queueKey);
if(!$queue) echo "ERROR: Could not join IPC queue. Form data will not be received";

while(1) { 
   // Handle new post info
   // You may want to increase the message size from 1024 if post data is large
   if(msg_receive($queue, 0, $msgType, 1024, $msgData, true, MSG_IPC_NOWAIT)) {
      // Handle data here. Post data is stored in $msgData
   }

   while($data = fgets($socket, 128)) { 
      // echo the data received to page 
      echo nl2br($data); 
      // flush old data, it isn't needed any longer. 
      flush(); 

      $ex = explode(' ', $data); 

      if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."\n"); 

      $search_string = "/^:([A-Za-z0-9_\-]+)[@!~a-zA-Z0-9@\.\-]+\s*([A-Z]+)\s*[:]*([\#a-zA-Z0-9\-]+)*\s*[:]*([!\#\-\.A-Za-z0-9 ]+)*/"; 

      $do = preg_match($search_string, $data, $matches); 

      // check that there is a command received 
      if(isset($matches['2'])) { 
         switch($matches['2']) { 
            case "PRIVMSG": 
               $user = $matches['1']; 
               $channel = $matches['3']; 
               $chat_text = isset($matches['4']) ? $matches['4'] : ""; 

               // check chat for !time 
               if(strtolower($chat_text) == "!time") {  
                  $output = "::::: " . date('l jS \of F Y h:i:s A') . " :::::"; 
                  fputs($socket, "PRIVMSG " . $channel . " :" . $output . "\n"); 
               } elseif(strtolower($chat_text) == "!hello") { 
                  fputs($socket, "PRIVMSG " . $channel . " :Hello!\n"); 
               } 
            break; 

            case "JOIN": 
               $user = $matches['1']; 
               $channel = $matches['3']; 
               fputs($socket, "PRIVMSG " . $channel . " :Welcome " . $user . " to " . $channel . "\n"); 
            break; 
         } 

      } 
   } 
} 
?> 
 3
Author: Ricky Cook, 2010-11-19 01:40:26

В принципе, этот скрипт будет работать все время. Способ работы PHP заключается в том, что для каждого запускаемого скрипта создается новый процесс PHP. Сценарии могут выполняться несколько раз одновременно, однако они не смогут напрямую взаимодействовать.

Вам нужно будет создать другой скрипт (или, по крайней мере, совершенно новую функцию этого), чтобы принять переменные post, а затем отправить их в работающую версию этого скрипта.

(Примечание: Я предоставлю 2 решения, так как 1 значительно сложнее. Кроме того, есть семафор, который я только что нашел, однако я точно не уверен, соответствует ли это нашим потребностям, потому что я почти ничего об этом не знаю http://php.net/manual/en/book.sem.php)

Лучший (Но Продвинутый)

Лучший способ, которым я могу это сделать, - использовать сокеты (особенно на *nix, поскольку сокеты отлично подходят для IPC [межпроцессной связи]). Это немного сложно, так как вы в основном создаете клиент/сервер просто для передачи деталей, затем вам нужно придумать какой-то протокол для вашего IPC.

Я не буду здесь ничего кодировать, но ссылки, которые имеют отношение к этому являются http://www.php.net/manual/en/function.socket-create.php http://www.php.net/manual/en/function.socket-bind.php http://www.php.net/manual/en/function.socket-listen.php http://www.php.net/manual/en/function.socket-accept.php http://www.php.net/manual/en/function.socket-connect.php

Если вы используете это в *nix, я бы настоятельно рекомендовал использовать AF_UNIX в качестве домена. Это очень эффективно, и довольно много приложений используют его для IPC.

Плюсы: Очень надежное решение - Высокая эффективность - Мгновенное (или как можно более близкое) общение

Минусы: - Довольно сложно реализовать

Не Так Здорово (Но Все Равно Хорошо)

Просто используйте файлы для передачи информации. Пусть ваш скрипт бота проверяет файл каждые 15 секунд на наличие изменений. Я бы предложил использовать XML для данных (поскольку простой xml делает обработку xml в php хорошо... простой)

Вещи, которые вам нужно учитывать, были бы: Как бы он отреагировал при получении 2 сообщения одновременно? (Если вы просто используете плоский файл или не учитываете наличие нескольких записей, это станет проблемой). Как вы узнаете, является ли сообщение новым (я бы удалил/очистил файл сразу после прочтения. Примечание: Не после обработки, так как кто-то может отправить сообщение в скрипт формы, пока вы обрабатываете/отправляете сообщение)

Ссылки: Как использовать простой xml http://php.net/manual/en/simplexml.examples-basic.php http://au2.php.net/manual/en/book.simplexml.php

Файл, связанный http://au2.php.net/manual/en/function.file-put-contents.php http://au2.php.net/manual/en/function.file-get-contents.php

С учетом сказанного, вы также можете использовать MySQL/Postgres или какую-либо другую серверную часть базы данных для обработки потока данных между сценариями.

Плюсы: - Простота реализации

Минусы: - Медленная передача данных (проверяет файлы с заданными интервалами) - Использует внешние файлы, которые могут быть удалены/изменены моими внешними приложениями/пользователями

 2
Author: Ricky Cook, 2010-11-19 00:26:37