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 相关帮助的主要内容,如果未能解决你的问题,请参考以下文章