]> git.localhorst.tv Git - alttp.git/blobdiff - app/TwitchBot/TwitchBot.php
fix some twitch bot stuff
[alttp.git] / app / TwitchBot / TwitchBot.php
index fd283789b9878187907ef60baed3cc30bc3d350b..3ca2db9283e6651e521fa2fe4aeaa596d94f9e2e 100644 (file)
@@ -1,7 +1,9 @@
 <?php
 
 namespace App\TwitchBot;
-use Illuminate\Support\Facades\Http;
+
+use App\Models\Channel;
+use App\Models\TwitchToken;
 use Monolog\Handler\StreamHandler;
 use Monolog\Logger;
 use Ratchet\Client\Connector;
@@ -13,9 +15,12 @@ class TwitchBot {
 
        public function __construct() {
                $this->logger = new Logger('TwitchBot');
-               $this->logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
+               $this->logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));
 
-               $this->fetchToken();
+               $this->token = TwitchToken::firstWhere('nick', 'localhorsttv');
+               if (!$this->token) {
+                       throw new \Exception('unable to find access token');
+               }
 
                $this->connector = new Connector();
                $this->connect();
@@ -30,30 +35,18 @@ class TwitchBot {
        }
 
        public function run() {
+               $this->shutting_down = false;
                $this->getLoop()->run();
        }
 
        public function stop() {
+               $this->logger->info('shutting down');
+               $this->shutting_down = true;
                $this->disconnect();
                $this->getLoop()->stop();
        }
 
 
-       public function fetchToken() {
-               $this->logger->info('acquiring token');
-               $rsp = Http::post('https://id.twitch.tv/oauth2/token', [
-                       'client_id' => config('twitch.client_id'),
-                       'client_secret' => config('twitch.client_secret'),
-                       'code' => config('twitch.code'),
-                       'grant_type' => 'authorization_code',
-                       'redirect_uri' => config('twitch.redirect_uri'),
-               ]);
-               var_dump($rsp);
-               var_dump($rsp->body());
-               $this->token = $rsp->json();
-       }
-
-
        public function connect() {
                ($this->connector)('wss://irc-ws.chat.twitch.tv:443')->done(
                        [$this, 'handleWsConnect'],
@@ -66,14 +59,13 @@ class TwitchBot {
        }
 
        public function handleWsConnect(WebSocket $ws) {
-               $this->logger->info('websocket connection estblished');
+               $this->logger->info('websocket connection established');
                $this->ws = $ws;
-        $ws->on('message', [$this, 'handleWsMessage']);
-        $ws->on('close', [$this, 'handleWsClose']);
-        $ws->on('error', [$this, 'handleWsError']);
+               $ws->on('message', [$this, 'handleWsMessage']);
+               $ws->on('close', [$this, 'handleWsClose']);
+               $ws->on('error', [$this, 'handleWsError']);
                $ws->send('CAP REQ :twitch.tv/tags twitch.tv/commands');
-               $ws->send('PASS oauth:'.$this->token->access_token);
-               $ws->send('NICK localhorsttv');
+               $this->login();
        }
 
        public function handleWsConnectError(WebSocket $ws) {
@@ -81,26 +73,90 @@ class TwitchBot {
        }
 
        public function handleWsMessage(Message $message, WebSocket $ws) {
-               $this->logger->info('websocket message received');
-               var_dump($message->getPayload());
+               $irc_messages = explode("\r\n", rtrim($message->getPayload(), "\r\n"));
+               foreach ($irc_messages as $irc_message) {
+                       $this->logger->debug('received IRC message '.$irc_message);
+                       $this->handleIRCMessage(IRCMessage::fromString($irc_message));
+               }
        }
 
-    public function handleWsClose(int $op, string $reason) {
+       public function handleWsClose(int $op, string $reason) {
                $this->logger->info('websocket connection closed: '.$reason.' ['.$op.']');
+               if (!$this->shutting_down) {
+                       $this->logger->info('reconnecting in 10 seconds');
+                       Loop::addTimer(10, [$this, 'connect']);
+               }
        }
 
-    public function handleWsError(\Exception $e, WebSocket $ws) {
+       public function handleWsError(\Exception $e, WebSocket $ws) {
                $this->logger->error('websocket error '.$e->getMessage());
        }
 
 
+       public function handleIRCMessage(IRCMessage $msg) {
+               if ($msg->isPrivMsg()) {
+                       $this->handlePrivMsg($msg);
+                       return;
+               }
+               if ($msg->isPing()) {
+                       $this->sendIRCMessage($msg->makePong());
+                       return;
+               }
+               if ($msg->isNotice() && $msg->getText() == 'Login authentication failed') {
+                       $this->logger->notice('login failed, refreshing access token');
+                       $this->token->refresh();
+                       $this->login();
+                       return;
+               }
+               if ($msg->command == '001') {
+                       // successful login
+                       $this->joinChannels();
+                       return;
+               }
+       }
+
+       public function handlePrivMsg(IRCMessage $msg) {
+               $target = $msg->getPrivMsgTarget();
+               if ($target[0] != '#') return;
+               $text = $msg->getText();
+               if ($text[0] != '!') return;
+               $channel = Channel::firstWhere('twitch_chat', '=', $target);
+               if (!$channel) return;
+               $this->logger->info('got command '.$text.' on channel '.$channel->title);
+       }
+
+       public function login() {
+               $this->ws->send('PASS oauth:'.$this->token->access);
+               $this->ws->send('NICK localhorsttv');
+       }
+
+       public function joinChannels() {
+               $this->logger->info('joining channels');
+               $channels = Channel::where('twitch_chat', '!=', '')->get();
+               $names = [];
+               foreach ($channels as $channel) {
+                       $names[] = $channel->twitch_chat;
+               }
+               $chunks = array_chunk($names, 10);
+               foreach ($chunks as $chunk) {
+                       $this->sendIRCMessage(IRCMessage::join($chunk));
+               }
+       }
+
+       public function sendIRCMessage(IRCMessage $msg) {
+               $irc_message = $msg->encode();
+               $this->logger->debug('sending IRC message '.$irc_message);
+               $this->ws->send($irc_message);
+       }
+
+
        private $logger;
-       private $loop;
 
        private $token;
 
        private $connector;
        private $ws;
+       private $shutting_down = false;
 
 }