# Very simple Twitch IRC Bot failing

**URL:** <https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748>\
**Category:** Chat and IRC\
**Created:** [October 23, 2020, 4:06pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748 "2020-10-23T16:06:53Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shadow\_4\_IT](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/shadow_4_it/32/10528_2.png) [@Shadow\_4\_IT](https://discuss.dev.twitch.com/u/Shadow_4_IT)\
**Post date:** [October 23, 2020, 4:06pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/1 "2020-10-23T16:06:53Z")

</div>

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](http://irc.chat.twitch.tv) and [irc.twitch.tv](http://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";
```

---

<div class="post-metadata">

**Author:** ![Freddy](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/freddy/32/111_2.png) [@Freddy](https://discuss.dev.twitch.com/u/Freddy)\
**Post date:** [October 23, 2020, 10:04pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/2 "2020-10-23T22:04:34Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Shadow\_4\_IT](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/shadow_4_it/32/10528_2.png) [@Shadow\_4\_IT](https://discuss.dev.twitch.com/u/Shadow_4_IT)\
**Post date:** [October 23, 2020, 11:05pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/3 "2020-10-23T23:05:30Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [October 24, 2020, 1:40pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/4 "2020-10-24T13:40:29Z")

</div>

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

> **[GitHub - pear/Net\_SmartIRC](https://github.com/pear/Net_SmartIRC)**
>
> Contribute to pear/Net\_SmartIRC development by creating an account on GitHub.

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

Or follow a more recent guide

> **[Creating a Twitch / IRC Chatbot in PHP with Minicli](https://dev.to/erikaheidi/creating-a-twitch-irc-chatbot-in-php-with-minicli-45mo)**
>
> In this guide, I'll share how I implemented a Twitch Chatbot in PHP using Minicli, a dependency-free framework for PHP in the command line. I'll also share how I incorporated that into my live stream setup.

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

---

<div class="post-metadata">

**Author:** ![Shadow\_4\_IT](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/shadow_4_it/32/10528_2.png) [@Shadow\_4\_IT](https://discuss.dev.twitch.com/u/Shadow_4_IT)\
**Post date:** [October 25, 2020, 12:43pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/5 "2020-10-25T12:43:01Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [October 25, 2020, 12:47pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/6 "2020-10-25T12:47:40Z")

</div>

Here is one I wrote and use as my basis

> **[BarryCarlyon/twitch\_misc](https://github.com/BarryCarlyon/twitch_misc/tree/main/chat)**
>
> main/chat

It only uses ws as a dependency.

I usually add redis and mysql as needed

---

<div class="post-metadata">

**Author:** ![tetyys](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/tetyys/32/7804_2.png) [@tetyys](https://discuss.dev.twitch.com/u/tetyys)\
**Post date:** [October 28, 2020, 9:55pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/7 "2020-10-28T21:55:23Z")

</div>

did you try to connect with justinfan1?

---

<div class="post-metadata">

**Author:** ![kappakappa](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@kappakappa](https://discuss.dev.twitch.com/u/kappakappa)\
**Post date:** [October 28, 2020, 11:15pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/8 "2020-10-28T23:15:37Z")

</div>

> [@Shadow\_4\_IT](#):
>
> I do not appear to ever successfully join the channel - I never see my bot in the list of the channel’s users.

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).

---

<div class="post-metadata">

**Author:** ![Dist](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/dist/32/7192_2.png) [@Dist](https://discuss.dev.twitch.com/u/Dist)\
**Post date:** [October 28, 2020, 11:21pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/9 "2020-10-28T23:21:34Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![kappakappa](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@kappakappa](https://discuss.dev.twitch.com/u/kappakappa)\
**Post date:** [October 29, 2020, 5:32pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/10 "2020-10-29T17:32:45Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![BarryCarlyon](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/barrycarlyon/32/253_2.png) [@BarryCarlyon](https://discuss.dev.twitch.com/u/BarryCarlyon)\
**Post date:** [October 29, 2020, 5:39pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/11 "2020-10-29T17:39:07Z")

</div>

> [@kappakappa](#):
>
> Agreed but what happens when the client sends a message before they are technically joined.

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

> [@tetyys](#):
>
> did you try to connect with justinfan1?

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

> [@kappakappa](#):
>
> I’ve seen it take upward of 5 _minutes_ before the JOIN completes (messages are batched on their end but keepalive is still required).

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.

---

<div class="post-metadata">

**Author:** ![kappakappa](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@kappakappa](https://discuss.dev.twitch.com/u/kappakappa)\
**Post date:** [October 29, 2020, 5:42pm UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/12 "2020-10-29T17:42:42Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Shadow\_4\_IT](https://d3ovvz0v2ajtpu.cloudfront.net/user_avatar/discuss.dev.twitch.com/shadow_4_it/32/10528_2.png) [@Shadow\_4\_IT](https://discuss.dev.twitch.com/u/Shadow_4_IT)\
**Post date:** [November 12, 2020, 12:50am UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/13 "2020-11-12T00:50:42Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![system](https://d2opxh93rbxzdn.cloudfront.net/original/2X/0/05909729875cce3b53e59d5561c4d23bb14948fc.png) [@system](https://discuss.dev.twitch.com/u/system)\
**Post date:** [December 12, 2020, 12:50am UTC](https://discuss.dev.twitch.com/t/very-simple-twitch-irc-bot-failing/28748/14 "2020-12-12T00:50:45Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
