IRC相关帮助

时间:2010-11-18 23:53:09

标签: php irc

现在我有机器人在机器人加入时发送消息。但是,如何制作一个可以发布数据的表单,以便机器人将消息发送到频道?

这是我的剧本(Rewamped):

<?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;
         }

      }
   }
}
?>

E.g。制作一个将数据发送到IRC频道的表单。输出将是“wget file info port”&lt; - 这将是发送到IRC频道的文本。

以下是相关部分:

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

希望有人可以提供帮助。

2 个答案:

答案 0 :(得分:3)

好的,这是一个更好的答案。第一部分仍然有效。每次要启动新脚本时都会调用一个新的PHP进程。因此,您需要一些方法来进行IPC。

以下是在PHP中使用* nix(但不是windows)的方法:

<强>接收器:

<?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; 
         } 

      } 
   } 
} 
?> 

答案 1 :(得分:2)

基本上,此脚本将一直运行。 PHP的工作方式是,对于每个正在运行的脚本,都会创建一个新的PHP进程。脚本可以同时运行多次,但是它们无法直接通信。

您需要创建另一个脚本(或者至少是这个脚本的全部新功能)来接受post变量,然后将它们发送到此脚本的运行版本。

(注意:我将提供2个解决方案,因为1非常困难。另外,我刚刚发现了Semaphore,但我不确定这是否符合我们的需求,因为我对它几乎一无所知{{ 3}})

最佳(但高级)

我能想到的最佳方式是使用套接字(特别是在* nix上,因为套接字对于IPC [进程间通信]来说非常棒)。这有点困难,因为你基本上只是为了传达细节而创建一个客户端/服务器,那么你需要为你的IPC提出某种协议。

我不会在这里编写任何代码,但与此相关的链接是 http://php.net/manual/en/book.sem.php http://www.php.net/manual/en/function.socket-bind.php http://www.php.net/manual/en/function.socket-create.php http://www.php.net/manual/en/function.socket-accept.php http://www.php.net/manual/en/function.socket-listen.php

如果在* nix上使用此功能,我强烈建议您使用AF_UNIX作为域名。它非常有效,而且很多应用程序都将它用于IPC。

优点: 非常强大的解决方   - 高效   - 即时(或尽可能接近)沟通

缺点:   - 很难实施

不太好(但仍然很好)

只需使用文件来传达信息。让您的机器人脚本每15秒检查一次文件是否有变化。我建议使用XML作为数据(因为简单的xml使php中的xml处理很简单......)

您需要考虑的事情是: 如果同时收到2个帖子会有什么反应? (如果您只是使用平面文件或不考虑有多个条目,这将成为一个问题)。 如何判断消息是否是新消息(我在阅读后立即删除/删除文件。注意:处理后没有,因为有人可以在处理/发送消息时发布到表单脚本)

链接: 如何使用简单的xml http://www.php.net/manual/en/function.socket-connect.php http://au2.php.net/manual/en/book.simplexml.php

文件相关 http://php.net/manual/en/simplexml.examples-basic.php http://au2.php.net/manual/en/function.file-get-contents.php

话虽如此,您还可以使用MySQL / Postgres或其他一些数据库后端来处理脚本之间的数据流。

优点:   - 易于实施

缺点:   - 缓慢传输数据(按给定间隔检查文件)   - 使用外部文件,可以删除/修改我的外部应用程序/用户