使用 Minicli 在 PHP 中创建 Twitch / IRC 聊天机器人

2025-06-05

使用 Minicli 在 PHP 中创建 Twitch / IRC 聊天机器人

你们中的一些人可能知道,我已经在 Twitch 上进行了几个月的实时编码,到目前为止,我已经能够使用我的OBS设置进行许多实验并尝试许多不同的设置。

Twitch 是一个有趣的平台,有很多功能和细节,我还在慢慢适应。我原本想在我的直播中加入实时聊天功能,让它融入到视频中,但在搜索了一些现成的解决方案后,我发现 Linux 版 OBS 并不具备其他平台的所有功能。当然,这并没有阻止我实现它!我总能找到办法 ;)

在本指南中,我将分享如何使用Minicli(一个无依赖的 PHP 命令行框架)在 PHP 中实现 Twitch 聊天机器人。我还会分享如何将其融入到我的直播设置中。

此实现基于Twitch 聊天机器人指南

如果您只想克隆一个 repo 并尝试一下,请检查 Minichat 的github 存储库下载 0.1.0 版本

关于 Twitch 的直播聊天

Twitch 使用 IRC 服务器进行所有聊天。您的直播聊天实际上是一个与您的 Twitch 用户名同名的频道。聊天机器人将连接到 Twitch 的 IRC 服务器,进行身份验证,然后加入直播频道。从那里,您可以阅读其他用户发送的消息并将其打印到终端,或者执行更高级的操作。

先决条件

为了跟进,您需要:

  • php-cli、7.2 或更高版本
  • Composer 创建一个新的 Minicli 项目
  • Twitch 帐户

步骤 1:引导应用程序

使用 Composer 基于 Minicli 引导一个新项目:

composer create-project --prefer-dist minicli/application
Enter fullscreen mode Exit fullscreen mode

现在访问新创建的目录:

cd minichat
Enter fullscreen mode Exit fullscreen mode

如果你查看minichat目录,你会发现以下内容:

app  composer.json  composer.lock  LICENSE  minicli  README.md  vendor
Enter fullscreen mode Exit fullscreen mode

重要目录和文件:

  • app:您的自定义应用程序文件应该位于此处。默认情况下,Commands 文件夹位于此处。
  • minicli:minicli 脚本是你将从命令行调用的可执行文件。应用程序就是在这里引导的。

你可以将minicli脚本重命名为任何你想要的名称。这通常是应用程序的名称,因此我们将其重命名为minichat

mv minicli minichat
Enter fullscreen mode Exit fullscreen mode

运行help命令以确保一切按预期工作:

./minichat help
Enter fullscreen mode Exit fullscreen mode

您应该看到如下输出:

Available Commands

help
└──table
└──test
Enter fullscreen mode Exit fullscreen mode

该应用程序附带三个演示命令。您可以在此处找到每个命令控制器:

  • helpapp/Command/Help/DefaultController.php
  • help tableapp/Command/Help/TableController.php
  • help testapp/Command/Help/TestController.php

这让您了解命令自动加载如何与 Minicli 配合使用。

我们现在将创建一个名为 的新命令。首先,我们将创建一个名为insidetwitch的目录Twitchapp/Command

mkdir app/Command/Twitch
Enter fullscreen mode Exit fullscreen mode

在此文件夹中打开一个名为的新文件DefaultController.php。将以下引导内容放入其中:

<?php
#label app/Command/Twitch/DefaultController.php

namespace App\Command\Twitch;

use Minicli\Command\CommandController;

class DefaultController extends CommandController
{
    public function handle()
    {
        $this->getPrinter()->info("Starting Minichat...");
    }
}
Enter fullscreen mode Exit fullscreen mode

保存文件后,您可以使用以下命令运行新命令:

./minichat twitch
Enter fullscreen mode Exit fullscreen mode

handle这将显示我们在命令控制器类中的方法中定义的信息文本。

第 2 步:获取 Twitch OAuth 密钥

oauth 令牌用作密码在 Twitch 的 IRC 服务器中进行身份验证并允许您访问流聊天。

要快速获取您帐户的令牌,请使用此Twitch Chat OAuth 密码生成器(由 Twitch 提供)。

获取 oauth 令牌后,打开minichat位于应用程序文件夹根目录中的脚本,并包含两个配置项,我们稍后将从命令控制器访问它们 -twitch_usertwitch_oauth

#!/usr/bin/php
<?php

if (php_sapi_name() !== 'cli') {
    exit;
}

require __DIR__ . '/vendor/autoload.php';

use Minicli\App;

$app = new App([
    'app_path' => __DIR__ . '/app/Command',

    #Twitch
    'twitch_user' => 'YOUR_TWITCH_USERNAME',
    'twitch_oauth' => 'YOUR_TWITCH_OAUTH_TOKEN'
]);

$app->setSignature("Minichat for Twitch.\n./minichat twitch");
$app->runCommand($argv);

Enter fullscreen mode Exit fullscreen mode

有了这些凭证,您现在就可以继续连接到服务器。

步骤 3:使用套接字连接到服务器

要连接到 Twitch 的 IRC 服务器,我们将使用套接字。使用套接字与使用文件非常相似,不同之处在于您将与特定端口上的远程服务器建立连接。以下是我们将要使用的方法:

以下类提供了通过套接字连接到 Twitch IRC 服务器的方法,使用提供的昵称和 OAuth 密码进行身份验证,并加入直播频道。它可以从服务器读取消息或向服务器写入消息:

<?php
#app/TwitchChatClient.php

namespace App;

class TwitchChatClient
{
    protected $socket;
    protected $nick;
    protected $oauth;

    static $host = "irc.chat.twitch.tv";
    static $port = "6667";

    public function __construct($nick, $oauth)
    {
        $this->nick = $nick;
        $this->oauth = $oauth;
    }

    public function connect()
    {
        $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if (socket_connect($this->socket, self::$host, self::$port) === FALSE) {
            return null;
        }

        $this->authenticate();
        $this->setNick();
        $this->joinChannel($this->nick);
    }

    public function authenticate()
    {
        $this->send(sprintf("PASS %s", $this->oauth));
    }

    public function setNick()
    {
        $this->send(sprintf("NICK %s", $this->nick));
    }

    public function joinChannel($channel)
    {
        $this->send(sprintf("JOIN #%s", $channel));
    }

    public function getLastError()
    {
        return socket_last_error($this->socket);
    }

    public function isConnected()
    {
        return !is_null($this->socket);
    }

    public function read($size = 256)
    {
        if (!$this->isConnected()) {
            return null;
        }

        return socket_read($this->socket, $size);
    }

    public function send($message)
    {
        if (!$this->isConnected()) {
            return null;
        }

        return socket_write($this->socket, $message . "\n");
    }

    public function close()
    {
        socket_close($this->socket);
    }
}
Enter fullscreen mode Exit fullscreen mode

TwitchChatClient.php将此类保存在文件夹内命名的文件中app

我们现在将使用TwitchChatClient控制器中处理twitch命令的类:

<?php
# app/Command/Twitch/DefaultController.php

namespace App\Command\Twitch;

use App\TwitchChatClient;
use Minicli\Command\CommandController;

class DefaultController extends CommandController
{
    public function handle()
    {
        $this->getPrinter()->info("Starting Minichat...");

        $app = $this->getApp();
        #obtains twitch credentials from app config
        $twitch_user = $app->config->twitch_user;
        $twitch_oauth = $app->config->twitch_oauth;

        if (!$twitch_user OR !$twitch_oauth) {
            $this->getPrinter()->error("Missing 'twitch_user' and/or 'twitch_oauth' config settings.");
            return;
        }

        $client = new TwitchChatClient($twitch_user, $twitch_oauth);
        $client->connect();

        if (!$client->isConnected()) {
            $this->getPrinter()->error("It was not possible to connect.");
            return;
        }

        $this->getPrinter()->info("Connected.\n");

        while (true) {
            $content = $client->read(512);
            $this->getPrinter()->out($content . "\n", "dim");
            sleep(5);
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

当您twitch再次运行该命令时,您应该能够连接到您的聊天并打印来自它的消息:

./minichat twitch
Enter fullscreen mode Exit fullscreen mode

您将获得如下输出:

Starting Minichat...

Connected.

:tmi.twitch.tv 001 erikaheidi :Welcome, GLHF!
:tmi.twitch.tv 002 erikaheidi :Your host is tmi.twitch.tv
:tmi.twitch.tv 003 erikaheidi :This server is rather new
:tmi.twitch.tv 004 erikaheidi :-
:tmi.twitch.tv 375 erikaheidi :-
:tmi.twitch.tv 372 erikaheidi :You are in a maze of twisty passages, all alike.
:tmi.twitch.tv 376 erikaheidi :>

:erikaheidi!erikaheidi@erikaheidi.tmi.twitch.tv JOIN #erikaheidi
:erikaheidi.tmi.twitch.tv 353 erikaheidi = #erikaheidi :erikaheidi
:erikaheidi.tmi.twitch.tv 366 erikaheidi #erikaheidi :End of /NAMES list

Enter fullscreen mode Exit fullscreen mode

现在,如果您访问Twitch 上的Stream Manager(在创作者仪表板内)并在聊天窗口中发送消息,您将收到如下消息:

终端聊天输出
要退出,您必须点击CTRL+C

我们不需要所有这些信息,因此在下一步中我们将在输出之前开始解析消息。

如果你让它保持打开状态一段时间,你还会注意到,服务器会定期向你发送PING消息,为了保持连接,你必须回复PONG。我们也会在下一步中实现这一点。

步骤4:解析消息

解析消息对于以下方面很重要:

  • 知道发送了消息(用于识别、忽略用户和主持聊天等)
  • 识别某些字符串并在必要时以不同的方式处理消息(例如,执行机器人命令)

让我们看一下发送到聊天的新消息产生的输出:

:erikaheidi!erikaheidi@erikaheidi.tmi.twitch.tv PRIVMSG #erikaheidi :testing minichat
Enter fullscreen mode Exit fullscreen mode

PRIVMSG有两点很重要:如果我们在文本中查找字符串,就能识别出不是来自服务器的消息,例如“PING” 。此外,我们可以使用字符串中的特殊字符:和来过滤掉这些消息,并获取昵称+消息。!

这是更新后的控制器,现在有额外的方法来很好地打印消息:

<?php
#app/Command/Twitch/DefaultController.php

namespace App\Command\Twitch;

use App\TwitchChatClient;
use Minicli\Command\CommandController;

class DefaultController extends CommandController
{
    public function handle()
    {
        $this->getPrinter()->info("Starting Minichat...");

        $app = $this->getApp();

        $twitch_user = $app->config->twitch_user;
        $twitch_oauth = $app->config->twitch_oauth;

        if (!$twitch_user OR !$twitch_oauth) {
            $this->getPrinter()->error("Missing 'twitch_user' and/or 'twitch_oauth' config settings.");
            return;
        }

        $client = new TwitchChatClient($twitch_user, $twitch_oauth);
        $client->connect();

        if (!$client->isConnected()) {
            $this->getPrinter()->error("It was not possible to connect.");
            return;
        }

        $this->getPrinter()->info("Connected.\n");

        while (true) {
            $content = $client->read(512);

            //is it a ping?
            if (strstr($content, 'PING')) {
                $client->send('PONG :tmi.twitch.tv');
                continue;
            }

            //is it an actual msg?
            if (strstr($content, 'PRIVMSG')) {
                $this->printMessage($content);
                continue;
            }

            sleep(5);
        }
    }

    public function printMessage($raw_message)
    {
        $parts = explode(":", $raw_message, 3);
        $nick_parts = explode("!", $parts[1]);

        $nick = $nick_parts[0];
        $message = $parts[2];

        $style_nick = "info";

        if ($nick === $this->getApp()->config->twitch_user) {
            $style_nick = "info_alt";
        }

        $this->getPrinter()->out($nick, $style_nick);
        $this->getPrinter()->out(': ');
        $this->getPrinter()->out($message);
        $this->getPrinter()->newline();
    }
}
Enter fullscreen mode Exit fullscreen mode

更新控制器后,./minichat twitch再次运行该命令,您将只看到格式正确的实际聊天消息。记得返回 Twitch 上的 Stream Manager 并在聊天中发送一些消息。

这是在我的终端上显示的样子(使用 ZSH):

用颜色输出聊天

从这里,您可以改进消息的解析,以便为常客实现聊天命令、忽略列表和识别。

步骤5:创建OBS覆盖

现在您的终端上已经运行了聊天,您可以使用OBS Studio 上的窗口源来创建覆盖。

我通常会创建一个场景,其中包含直播背景和一些我想要修复的元素,例如聊天窗口,可能还有网络摄像头。你可能需要调整终端窗口的大小以及终端主题和字体大小等设置,使其在直播中看起来美观。

向 OBS 添加窗口源

我所做的是为聊天窗口创建自定义配置文件,这样我就可以拥有完全透明的背景和更加自定义的字体。

希望您喜欢本教程,并欢迎提出您希望看到的新调整和 OBS 技巧 :)

文章来源:https://dev.to/erikaheidi/creating-a-twitch-irc-chatbot-in-php-with-minicli-45mo
PREV
文档 101:为你的软件项目创建一个好的 README
NEXT
Bootstrapping a CLI PHP application in Vanilla PHP