{
use HasFactory;
+ public function getCurrentEpisode() {
+ return $this->episodes()
+ ->where('start', '<', now()->subMinutes(10))
+ ->orderBy('start', 'DESC')
+ ->first();
+ }
+
public function episodes() {
return $this->belongsToMany(Episode::class)
->using(Restream::class)
}
protected $casts = [
+ 'chat_commands' => 'array',
'languages' => 'array',
];
return $this->belongsTo(User::class);
}
+ public function getName() {
+ if (!empty($this->name_override)) {
+ return $this->name_override;
+ }
+ if ($this->user) {
+ if (!empty($this->user->nickname)) {
+ return $this->user->nickname;
+ }
+ if (!empty($this->user->username)) {
+ return $this->user->username;
+ }
+ }
+ return '';
+ }
+
+ public function getStreamLink() {
+ if (!empty($this->stream_override)) {
+ return $this->stream_override;
+ }
+ if ($this->user && !empty($this->user->stream_link)) {
+ return $this->user->stream_link;
+ }
+ return '';
+ }
+
protected $casts = [
'confirmed' => 'boolean',
'user_id' => 'string',
return $this->belongsTo(User::class);
}
+ public function getName() {
+ if (!empty($this->name_override)) {
+ return $this->name_override;
+ }
+ if ($this->user) {
+ if (!empty($this->user->nickname)) {
+ return $this->user->nickname;
+ }
+ if (!empty($this->user->username)) {
+ return $this->user->username;
+ }
+ }
+ return '';
+ }
+
+ public function getStreamLink() {
+ if (!empty($this->stream_override)) {
+ return $this->stream_override;
+ }
+ if ($this->user && !empty($this->user->stream_link)) {
+ return $this->user->stream_link;
+ }
+ return '';
+ }
+
protected $casts = [
'user_id' => 'string',
];
--- /dev/null
+<?php
+
+namespace App\TwitchBot;
+
+use App\Models\Channel;
+
+abstract class ChatCommand {
+
+ public static function create(TwitchBot $bot, Channel $channel, $config) {
+ $cmd = null;
+ switch ($config['command']) {
+ case 'crew':
+ $cmd = new CrewCommand();
+ break;
+ case 'runner':
+ $cmd = new RunnerCommand();
+ break;
+ default:
+ throw new \Exception('command '.$str.' not found');
+ }
+ $cmd->bot = $bot;
+ $cmd->channel = $channel;
+ $cmd->config = $config;
+ return $cmd;
+ }
+
+ public abstract function execute($args);
+
+ protected function getBooleanConfig($name, $default = false) {
+ return array_key_exists($name, $this->config) ? $this->config[$name] : $default;
+ }
+
+ protected function messageChannel($str) {
+ $msg = IRCMessage::privmsg($this->channel->twitch_chat, $str);
+ $this->bot->sendIRCMessage($msg);
+ }
+
+ protected $bot;
+ protected $channel;
+ protected $config;
+
+}
+
+?>
--- /dev/null
+<?php
+
+namespace App\TwitchBot;
+
+class CrewCommand extends ChatCommand {
+
+ public function execute($args) {
+ $episode = $this->channel->getCurrentEpisode();
+ if (!$episode) return;
+ $links = [];
+ foreach ($episode->crew as $crew) {
+ $link = $crew->getStreamLink();
+ if (empty($link)) {
+ $link = $crew->getName();
+ }
+ if (!empty($link)) {
+ if (!isset($links[$crew->role])) {
+ $links[$crew->role] = [];
+ }
+ $links[$crew->role][] = $link;
+ }
+ }
+ $parts = [];
+ if (!empty($links['commentary']) && $this->getBooleanConfig('commentary', true)) {
+ $parts[] = 'Kommentar: '.implode(' ', $links['commentary']);
+ }
+ if (!empty($links['tracking']) && $this->getBooleanConfig('tracking', true)) {
+ $parts[] = 'Tracking: '.implode(' ', $links['tracking']);
+ }
+ if (!empty($links['setup']) && $this->getBooleanConfig('setup', false)) {
+ $parts[] = 'Setup: '.implode(' ', $links['setup']);
+ }
+ if (!empty($parts)) {
+ $message = implode(' ', $parts);
+ $this->messageChannel($message);
+ }
+ }
+
+}
+
+?>
return $msg;
}
+ public static function privmsg($target, $message) {
+ $msg = new IRCMessage();
+ $msg->command = 'PRIVMSG';
+ $msg->params[] = $target;
+ $msg->params[] = $message;
+ return $msg;
+ }
+
public function getPrivMsgTarget() {
if (!empty($this->params)) {
return $this->params[0];
--- /dev/null
+<?php
+
+namespace App\TwitchBot;
+
+class RunnerCommand extends ChatCommand {
+
+ public function execute($args) {
+ $episode = $this->channel->getCurrentEpisode();
+ if (!$episode) return;
+ $links = [];
+ foreach ($episode->players as $player) {
+ $link = $player->getStreamLink();
+ if (empty($link)) {
+ $link = $player->getName();
+ }
+ if (!empty($link)) {
+ $links[] = $link;
+ }
+ }
+ $message = 'Runner: '.implode(' ', $links);
+ $this->messageChannel($message);
+ }
+
+}
+
+?>
public function __construct() {
$this->logger = new Logger('TwitchBot');
- $this->logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));
+ $this->logger->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
$this->token = TwitchToken::firstWhere('nick', 'localhorsttv');
if (!$this->token) {
if ($text[0] != '!') return;
$channel = Channel::firstWhere('twitch_chat', '=', $target);
if (!$channel) return;
- $this->logger->info('got command '.$text.' on channel '.$channel->title);
+ $this->handleChatCommand($channel, $msg);
+ }
+
+ public function handleChatCommand(Channel $channel, IRCMessage $msg) {
+ $cmd = explode(' ', ltrim($msg->getText(), '!'), 2);
+ if (!isset($channel->chat_commands[$cmd[0]])) return;
+ $config = $channel->chat_commands[$cmd[0]];
+ $this->logger->info('got command '.$cmd[0].' on channel '.$channel->title);
+ try {
+ $command = ChatCommand::create($this, $channel, $config);
+ $command->execute($cmd[1] ?? '');
+ } catch (\Exception $e) {
+ $this->logger->warning('error executing command '.$cmd[0].' on channel '.$channel->title.': '.$e->getMessage());
+ }
}
public function login() {
*/
public function down()
{
- Schema::table('events', function(Blueprint $table) {
+ Schema::table('channels', function(Blueprint $table) {
$table->dropColumn('twitch_chat');
});
}
--- /dev/null
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::table('channels', function(Blueprint $table) {
+ $table->text('chat_commands')->default('{}');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('channels', function(Blueprint $table) {
+ $table->dropColumn('chat_commands');
+ });
+ }
+};