Very simple Twitch IRC Bot failing

Hi, I am trying to write my own simple IRC bot in PHP, and I’m having issues right at the start. I have registered the bot as an application and written code to obtain an OAuth token. I’m able to validate the token and see that it has the scopes I have set:
{“client_id”:"",“scopes”:[“chat:edit”,“chat:read”],“expires_in”:4419762}

Also, I receive a login error if I give an invalid token, and no login error when I provide the correct token.

I also receive feedback from the CAP REQ commands:
Received :tmi.twitch.tv CAP * ACK :twitch.tv/commands
Received :tmi.twitch.tv CAP * ACK :twitch.tv/tags

Unfortunately, my 2 simple messages never appear in the stream’s chat. (I have actually tried connecting to a few other channels as well). I’ve tried connecting to both irc.chat.twitch.tv and irc.twitch.tv, have tried 3 ports (6667, 80 and 443) and have tried with multiple new tokens. I do not appear to ever successfully join the channel - I never see my bot in the list of the channel’s users.

Any insight you can provide I would greatly appreciate.

My code is as follows:
<?php

// Set nickname and password 
$server = "irc.chat.twitch.tv";
$port = 6667;
$nick = "bot_in_the_shadows";
$password = "OAuth:<my auth token here>";
$chan = "#shadow_4_it";

// Connect to the server and join the channel
$fp = fsockopen($server, $port, $errno, $errstr) or die("Count not connect");
if (!$fp) {echo "Error: $errno - $errstr\n"; exit;}
fwrite($fp, "PASS ".$password."\r\n") or die("Password not accepted.");
fwrite($fp, "USER ".$nick."\r\n") or die("Could not enter nick");
fwrite($fp, "CAP REQ :twitch.tv/commands\r\n");
fwrite($fp, "CAP REQ :twitch.tv/tags\r\n");
sleep(1);
fwrite($fp, "JOIN $chan\r\n") or die ("Could not join channel ".$chan);

// Look for any responses.  The first 2 should be from our CAP REQ commands.
$read = fgets($fp);
echo "Received " . $read . "\n";
$read = fgets($fp);
echo "Received " . $read . "\n";

// Attempt to write to the channel with 2 messages
sleep(2);
fwrite($fp, "PRIVMSG $chan :Hi everyone\r\n");
sleep(2);
fwrite($fp, "PRIVMSG $chan :Bye everyone.\r\n");

// Close the stream 
fclose($fp);

echo "Attempt complete.\n";

As far as I can tell you’re literally attempting to join the channel $chan. So

“JOIN $chan\r\n”

should be

“JOIN “.$chan.”\r\n”

or

“JOIN {$chan}\r\n”

The same for both of your PRIVMSG

Freddy,
Thank you for your reply. I modified the script as you suggested, and as a second run I removed the variable entirely, as shown below:
fwrite($fp, “JOIN “.$chan.”\r\n”) or die ("Could not join channel ".$chan);
fwrite($fp, “PRIVMSG “.$chan.” Hi everyone\r\n”);
fwrite($fp, “PRIVMSG “.$chan.” Bye everyone.\r\n”);

fwrite($fp, “JOIN #shadow_4_it\r\n”) or die ("Could not join channel ".$chan);
fwrite($fp, “PRIVMSG #shadow_4_it :Hi everyone\r\n”);
fwrite($fp, “PRIVMSG #shadow_4_it :Bye everyone.\r\n”);

Unfortunately, both trials (and some other combinations and escaping attempts) were unsuccessful at writing to the chat, and I still cannot see my bot as a user in the chat. Any other suggestions?

You may want to consider using SmartIRC library instead.

Might need a little massaging to work better in newer versions of PHP but it should still work

I might have a ircV3 parsing version of that still kicking about too

Or follow a more recent guide

It’s been a while since I did bots in PHP, I moved to node myself.

Initially I don’t see anything obvious wrong, but it’s been too long since I’ve been doing fun shit with sockets in PHP

Thank you for the information.

tbh, I am not married to PHP…I need a language that natively supports database connectivity and PHP fits the bill well. I’d be open to trying anything, but my solution needs to be very lightweight - my future plans require integration into some complex structures and I can’t afford a solution that requires hundreds (or thousands) of files to operate. Is there a specific node.js example that you’d recommend?

Also, where my script seems to fall apart is joining the channel. I’m using scopes chat:read and chat:edit in my oauth request, but are there scopes for chat:join or chat:login that I am missing?

Here is one I wrote and use as my basis

It only uses ws as a dependency.

I usually add redis and mysql as needed

did you try to connect with justinfan1?

How long are you waiting and what are you using to determine the bot has joined or not? Twitch uses a severely decapitated version of IRC, fact that clients can connect at all is somewhat amazing. I’ve seen it take upward of 5 minutes before the JOIN completes (messages are batched on their end but keepalive is still required).

You should also wait between commands, even better would be waiting on a response where possible (CAP and login for example).

Twitch chat is IRC compatible, not compliant, meaning there’s connectivity for traditional IRC clients but it’s not always going to follow the IRC spec, and implements functionality based on the needs of the site rather than ensuring all new features can be supported by old IRC clients.

Joining a channel should be relatively quick, it’s just that the notifications for joins sent on TMI are batched (and not sent at all for channels over 1,000 users). Things like channel list are also cached, just like every other API endpoint, so some delay as to when that list will be updated is expected.

Agreed but what happens when the client sends a message before they are technically joined. In a real IRC network those messages would either be rejected unless the channel is set -n or queued like a split.

Last time I checked, you don’t have to be in a room/channel to send to it.
You only have to be connected to TMI, you don’t have to JOIN any rooms.

But at this point the thread has just been derailed from OP’s original problem.

Which was for the most part a PHP syntax error/fun with PHP Sockets

Not relevant to the thread, since using own tokens, see line 5/6 of the source file attached. Using bot_in_the_shadows

If you are looking at JOIN/PARTS via the relevant capability, it may be quicker than the userlist.
If you are looking at the Userlist, then the userlist is also heavily cached, not just a problem of JOIN-ing but the caching on the endpoint at the HTTP level (not just the delayed processing of the events at the TMI level)

But again off topic to OP’s original issue.

Topic is literally about IRC and it’s offtopic?? Sure. Have fun.

Hi everyone, thanks for the enthusiasm around this topic.

The only resolution I’ve found so far is to switch languages from PHP (which is based on Perl that I’ve used for years) to node.js (which I do not know) in order to use tmi.js for connectivity. This has worked well on my local machine. As I’m still generating my authorization token in the same manner, I’m not sure why PHP was giving me issues and node.js is not, but at since I’ve been successful I’m moving forward this way. .I am concerned about the effort it will take to migrate this script to my application space in Azure (which I plan to do over my December holiday break)…hopefully I won’t run into significant issues there.

I’ve actually moved most of my programming logic to a MSSQL stored procedure, and am getting better performance this way than trying to handle the same messaging commands in node.js. I’m able to connect to a channel instantly, send messages and commands using tmi.js, and process the messages the way I had intended. I have a long way to go, but I am now moving forward and have been using the bot live in stream for a couple of weeks.

Thanks again for everyone’s insight.

1 Like