使用 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
现在访问新创建的目录:
cd minichat
如果你查看minichat
目录,你会发现以下内容:
app composer.json composer.lock LICENSE minicli README.md vendor
重要目录和文件:
app
:您的自定义应用程序文件应该位于此处。默认情况下,Commands 文件夹位于此处。minicli
:minicli 脚本是你将从命令行调用的可执行文件。应用程序就是在这里引导的。
你可以将minicli
脚本重命名为任何你想要的名称。这通常是应用程序的名称,因此我们将其重命名为minichat
:
mv minicli minichat
运行help
命令以确保一切按预期工作:
./minichat help
您应该看到如下输出:
Available Commands
help
└──table
└──test
该应用程序附带三个演示命令。您可以在此处找到每个命令控制器:
help
:app/Command/Help/DefaultController.php
help table
:app/Command/Help/TableController.php
help test
:app/Command/Help/TestController.php
这让您了解命令自动加载如何与 Minicli 配合使用。
我们现在将创建一个名为 的新命令。首先,我们将创建一个名为insidetwitch
的目录:Twitch
app/Command
mkdir app/Command/Twitch
在此文件夹中打开一个名为的新文件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...");
}
}
保存文件后,您可以使用以下命令运行新命令:
./minichat twitch
handle
这将显示我们在命令控制器类中的方法中定义的信息文本。
第 2 步:获取 Twitch OAuth 密钥
oauth 令牌用作密码在 Twitch 的 IRC 服务器中进行身份验证并允许您访问流聊天。
要快速获取您帐户的令牌,请使用此Twitch Chat OAuth 密码生成器(由 Twitch 提供)。
获取 oauth 令牌后,打开minichat
位于应用程序文件夹根目录中的脚本,并包含两个配置项,我们稍后将从命令控制器访问它们 -twitch_user
和twitch_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);
有了这些凭证,您现在就可以继续连接到服务器。
步骤 3:使用套接字连接到服务器
要连接到 Twitch 的 IRC 服务器,我们将使用套接字。使用套接字与使用文件非常相似,不同之处在于您将与特定端口上的远程服务器建立连接。以下是我们将要使用的方法:
- socket_create:使用方法调用中提供的地址和端口创建一个新的套接字。
- socket_read:从套接字读取。
- socket_write:写入套接字。
- socket_last_error:从套接字获取最后一个错误。
- socket_close:关闭套接字。
以下类提供了通过套接字连接到 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);
}
}
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);
}
}
}
当您twitch
再次运行该命令时,您应该能够连接到您的聊天并打印来自它的消息:
./minichat twitch
您将获得如下输出:
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
现在,如果您访问Twitch 上的Stream Manager(在创作者仪表板内)并在聊天窗口中发送消息,您将收到如下消息:
我们不需要所有这些信息,因此在下一步中我们将在输出之前开始解析消息。
如果你让它保持打开状态一段时间,你还会注意到,服务器会定期向你发送PING
消息,为了保持连接,你必须回复PONG
。我们也会在下一步中实现这一点。
步骤4:解析消息
解析消息对于以下方面很重要:
- 知道谁发送了消息(用于识别、忽略用户和主持聊天等)
- 识别某些字符串并在必要时以不同的方式处理消息(例如,执行机器人命令)
让我们看一下发送到聊天的新消息产生的输出:
:erikaheidi!erikaheidi@erikaheidi.tmi.twitch.tv PRIVMSG #erikaheidi :testing minichat
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();
}
}
更新控制器后,./minichat twitch
再次运行该命令,您将只看到格式正确的实际聊天消息。记得返回 Twitch 上的 Stream Manager 并在聊天中发送一些消息。
这是在我的终端上显示的样子(使用 ZSH):
从这里,您可以改进消息的解析,以便为常客实现聊天命令、忽略列表和识别。
步骤5:创建OBS覆盖
现在您的终端上已经运行了聊天,您可以使用OBS Studio 上的窗口源来创建覆盖。
我通常会创建一个场景,其中包含直播背景和一些我想要修复的元素,例如聊天窗口,可能还有网络摄像头。你可能需要调整终端窗口的大小以及终端主题和字体大小等设置,使其在直播中看起来美观。
我所做的是为聊天窗口创建自定义配置文件,这样我就可以拥有完全透明的背景和更加自定义的字体。
希望您喜欢本教程,并欢迎提出您希望看到的新调整和 OBS 技巧 :)
文章来源:https://dev.to/erikaheidi/creating-a-twitch-irc-chatbot-in-php-with-minicli-45mo