【问题标题】:php irc bot with periodic messages to the channelphp irc bot 定期向频道发送消息
【发布时间】:2013-02-27 12:34:21
【问题描述】:

我按照一些教程从头开始创建机器人,基本功能运行良好,比如我可以连接,它响应命令,并输出到网页。

我想要的是定期向频道发送带有更新的消息,这些消息是我通过 curl 从某个网站获得的。

$irc 和 $curl 只是带有设置的数组,而 date('s') 可以说是返回更新的函数。当然,我有为此工作的 curl 功能。 $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 Moninal 我来了
10:39 Moninal 39:24
10:40 Moninal 40:26

10:41 Moninal 我来了
10:41 Moninal 41:05
10:41 Gregos !sayit
10:41 Moninal 你好!
10:41 Gregos !sayit
10:41 Moninal 你好!
10:42 Moninal 42:51

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

10:42 Moninal 42:51
10:43 Moninal 43:52
10:44 Moninal 44:53

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

也许这与我的服务器配置有关?

【问题讨论】:

    标签: php bots irc


    【解决方案1】:

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

    现在它只在聊天中打印秒数,因为它会等待 10 次 128 字节(你的意思是 10 秒),因为只有当内部 while 循环条件始终为真时才会等待 10 秒(如果它每隔第二)。

    您可以尝试将一些逻辑移到内部 while 循环之外。我还为您更改了 curl 时间 - 让它休眠 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);
    }
    

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

    【讨论】:

    • 感谢您的快速回复,但不,我将编辑我的主要帖子以说明会发生什么?因为有限制。
    • 单独调试 curl 块。它现在是分开的,所以这是可能的。回显变量以查看问题所在。它是有线的,它不会时不时地回显秒数。
    【解决方案2】:

    好吧,经过一天的痛苦,我终于找到了愚蠢的原因和解决方案。基本上延迟 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(); 
    };
    

    嗯,它不包括所有的连接设置。这很容易找到怎么做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 2021-01-10
      • 2011-05-12
      • 2016-08-11
      • 2015-11-17
      • 2022-01-05
      相关资源
      最近更新 更多