PHP irc bot定期向通道发送消息


php irc bot with periodic messages to the channel

我遵循一些教程从头开始创建bot,基本功能工作良好,就像我可以连接一样,它响应命令,并输出到网页。

我想要的是周期性地发送消息与更新到频道,我从一些网站curl。

$irc和$curl只是带有设置的数组,date('s')是返回更新的函数。当然我有一个旋度函数。$irc['delay']被设置为10,所以使用sleep(1),它应该每10秒发送一次更新。

问题是,在第一分钟左右,它每10秒发送当前秒数,但它不听我设置的任何命令。它在第一个初始延迟之后执行命令,我不是它来自哪里
然后,只有当有人在频道上讲话时,它才发送当前秒数(if条件)。我猜它在等待这128字节?但它确实可以立即听取命令。

while(1) {
    while($data = fgets($socket, 128)) {
        echo nl2br($data);
        flush();
        if ($curl['delay'] <= $d) { fputs($socket, "PRIVMSG ".$irc['channel']." :".date('s')."'n"); $d=0; };
        $d+=1;
        sleep(1);
        $ex = explode(' ', $data);
        if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."'n");
        $command = str_replace(array(chr(10), chr(13)), '', $ex[3]);
        switch ($command) {
            case ":!say" : fputs($socket, "PRIVMSG ".$ex[2]." :Hello!'n"); break;
            case ":!off" : break 3;
        };
    };
}

我希望它既能响应命令,又能周期性地自动传递提取的数据。但我不明白它的行为,甚至不确定我想要的是可能与php



就像Ranty建议的那样
没有打破:它会显示一次日期,然后下一次报告至少需要一分钟。如果我输入任何命令,它会进一步延迟。

[10:39]电影我来了
[10:39]梦剧场39:24
[10:40]电影40:26

[10:41]电影《我来了》
[10:41]电影41:05
[10:41]格雷戈斯,说出来
[10:41]莫妮卡:你好!
[10:41]格雷戈斯,说出来
[10:41]莫妮卡:你好!
[10:42]梦剧场42:51

在它发送第二条消息后,我第一次在网页上得到输出,并且每隔61秒发送一次下一个报告,而不是10秒。

[10:42]梦剧场42:51
[10:43]电影43:52
[10:44]电影44:53

如果我在内循环中添加break:在第一分钟,我每10秒收到一次报告,但是所有发送的命令都在第一分钟结束时触发,就像以前一样。在此之后,命令工作,但再次报告每61秒。

也许是我的服务器配置有问题?

我猜问题是你在while($data = fgets($socket, 128))循环内拥有所有逻辑。如果你想一下,你的逻辑被执行,如果有一些在聊天发生。因此,当您启动脚本时,它执行正常,因为它读取了那里的数据(我假设是这样),但在读取数据之后,它只对新数据执行。

现在它只在chat上打印秒数,因为它等待了128字节的10次(你想要的10秒),因为只有当内部while循环条件总是为真(如果它每秒执行一次),它才会是10秒。

可以尝试将一些逻辑移到while循环的内部之外。我还为你改变了旋度计时-你让它睡眠1秒,并在计数器上加1 -这是不可靠的。您可以简单地将当前时间与上次请求的时间进行比较。

while(1) {
    flush();
    if ($curl['next_request'] <= time()) {
        fputs($socket, "PRIVMSG ".$irc['channel']." :".date('s')."'n");
        $curl['next_request'] = time() + $curl['delay'];
    };
    while($data = fgets($socket, 128)) {
        echo nl2br($data);
        $ex = explode(' ', $data);
        if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."'n");
        $command = str_replace(array(chr(10), chr(13)), '', $ex[3]);
        switch ($command) {
            case ":!say" : fputs($socket, "PRIVMSG ".$ex[2]." :Hello!'n"); break;
            case ":!off" : break 3;
        };
    };
    sleep(1);
}

它可能会同时响应所有命令,而不是每秒一个,如果你想改变这一点,你可以尝试在内部while的末尾添加一个break。

好了,经过一天的痛苦,我终于找到了愚蠢的原因和解决办法。1分钟延迟的主要原因是fget命令while($data = fgets($socket, 128));
解决方法是设置stream_set_timeout($socket,1);在循环之前。我还设置了nginx服务器,而不是apache。我不确定这是否有帮助。
也我认为我可以只是设置时间在stream_set_timeout($socket,1);控制发送消息的最小间隔时间。

$next=time();
stream_set_timeout($socket,1);
while(1) {
    $data = fgets($socket, 128);
    echo nl2br($data);
    $ex = explode(' ', $data);
    if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."'n");
    if (isset($ex[3])) $command = str_replace(array(chr(10), chr(13)), '', $ex[3]);
    switch ($command) {
        case ":!sayit" : 
            $msg = NULL; for ($i = 4; $i < count($ex); $i++) { $msg .= $ex[$i] . ' '; }
            fputs($socket, "PRIVMSG ".$ex[2]." :".$msg."'n"); 
            break;
        case ":!off" :
          fputs($socket, "PRIVMSG ".$irc['channel']." : Bye'n");
          fputs($socket,"QUIT Client Disconnected!'n");
          die('Exited!');
    };
    if ($next <= time()) {
        fputs($socket, "PRIVMSG ".$irc['channel']." :".date('H:i:s')."'n");
        echo "PRIVMSG ".$irc['channel']." :".date('H:i:s')."<br />";
        $next = time() + $curl['delay']; 
    };
    flush(); 
};

它不包括所有的连接设置。