IRC 相关帮助

Posted

技术标签:

【中文标题】IRC 相关帮助【英文标题】:IRC related help 【发布时间】:2010-11-18 23:53:08 【问题描述】:

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

这是我的脚本(改版):

<?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 file info port”

以下是相关部分:

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

希望有人能帮忙。

【问题讨论】:

所以你正在寻找的是当机器人正在运行时,你可以在网络服务器上拥有一个用户可以提交数据的表单,并且机器人会向 IRC 吐出一些格式化信息频道,对吗? 基本上,一个向IRC主频道发送命令的简单表格。例如。表格 = 主持人 + 时间 + 提交按钮。如果我输入 127.0.0.1 作为主机,时间输入 100。IRC 主频道上的输出将是 127.0.0.1 100 【参考方案1】:

好的,这是一个更好的答案。第一部分仍然存在。每次您想要启动一个新脚本时,都会调用一个新的 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; 
          

       
    
 
?> 

【讨论】:

你能把它转换成简单的 php,我不需要它来高级。将命令发送到 irc 主频道的基本形式和东西。 这是最基本的。如果您使用 $_POST 作为要发送给机器人的数据并将接收器放在 while 循环中的某个位置进行处理,那么您的接收器将从您的表单中获取所有发布数据。 我刚刚添加了与您的脚本相关的更具体的说明。这绝对是我能做到的最简单的事情。也就是说,我没有通过解释器运行它,所以它可能会引发错误。但我已经有点过了;它应该工作! 谢谢,你能编辑最后一部分,当我发布数据时,PRIVMSG 应该获取数据并发送回主 IRC chan?如果你能做那部分,我可以做表格等。谢谢队友。【参考方案2】:

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

您将需要创建另一个脚本(或至少该脚本的一个全新函数)来接受 post 变量,然后将它们发送到该脚本的运行版本。

(注意:我将提供 2 个解决方案,因为第 1 个解决方案要困难得多。另外,我刚刚找到了 Semaphore,但是我不确定这是否适合我们的需求,因为我对此几乎一无所知 @987654321 @)

最佳(但高级)

我能想到的最佳方法是使用套接字(特别是在 *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 使得 php 中的 xml 处理很好......简单)

您需要考虑的事项是: 当同时收到 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 个脚本之间交换信息。文件是我能想到的最简单的方法。套接字是高级的,但文件应该相当简单。 我只需要 PHP 脚本向 IRC 频道发送命令。一个基本的表单 + 提交按钮。 基本上,一个向IRC主频道发送命令的简单表格。例如。表格 = 主持人 + 时间 + 提交按钮。如果我输入 127.0.0.1 作为主机,时间输入 100。IRC 主频道上的输出将是 127.0.0.1 100 是的,但您不能在主脚本中接受来自帖子的数据。当您发布新数据时,PHP 会启动一个新进程,因此您需要一种方法从您的脚本中获取数据,该脚本接受发布到您的发送 IRC 消息的脚本。当然,除非您让机器人仅在发布新消息时加入(在这种情况下,您需要打开 irc 套接字、连接、发送消息、断开连接、关闭 irc 套接字) 话虽如此,我假设(考虑到 while 循环)您希望您的机器人脚本 24/7 全天候运行,而不仅仅是当有人发布消息时。

以上是关于IRC 相关帮助的主要内容,如果未能解决你的问题,请参考以下文章

浏览器 JavaScript 应用 IRC 连接

IRC使用

C# IRC 和 Twitch 空闲断开连接?

用 Java 构建一个 IRC 机器人

git帮助和小结

我如何在 python 中编写一个简单的 IRC 机器人?