--- /dev/null
+<?php
+
+namespace App\Console\Commands;
+
+use App\Models\Episode;
+use App\Models\Event;
+use App\Models\StepLadderMode;
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Support\Facades\Http;
+
+
+class SyncLadder extends Command {
+
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'sync:stepladder';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Synchronize Step Ladder schedule';
+
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle() {
+ $events = Event::where('external_schedule', 'LIKE', 'stepladder')
+ ->where(function (Builder $query) {
+ $query->whereNull('end');
+ $query->orWhere('end', '>', now());
+ })
+ ->get();
+
+ foreach ($events as $event) {
+ try {
+ $this->line('syncing '.$event->name);
+ $this->syncEvent($event);
+ } catch (\Exception $e) {
+ $this->error('error syncing event '.$event->name.': '.$e->getMessage());
+ }
+ }
+ }
+
+ private function syncEvent(Event $event) {
+ $ladderSchedule = Http::get('https://alttpr.racing/api/v1/upcoming')->json();
+ foreach ($ladderSchedule as $ladderEntry) {
+ try {
+ $this->syncSchedule($event, $ladderEntry);
+ } catch (\Exception $e) {
+ $this->error('error syncing episode '.$ladderEntry['id'].': '.$e->getMessage());
+ }
+ }
+ }
+
+ private function syncSchedule(Event $event, $ladderEntry) {
+ $ext_id = 'stepladder:'.$ladderEntry['id'];
+ $episode = Episode::firstWhere('ext_id', '=', $ext_id);
+ if (!$episode) {
+ $episode = new Episode();
+ $episode->ext_id = $ext_id;
+ }
+ $mode = $this->getMode($ladderEntry);
+ $episode->event()->associate($event);
+ $episode->title = $mode->name;
+ $episode->start = Carbon::createFromTimestamp($ladderEntry['time']);
+ $episode->estimate = 2 * 60 * 60;
+ $episode->confirmed = true;
+ $episode->save();
+ }
+
+ private function getMode($ladderEntry) {
+ $ext_id = 'stepladder:'.$ladderEntry['mode'];
+ $mode = StepLadderMode::firstWhere('ext_id', '=', $ext_id);
+ if (!$mode) {
+ $ladderMode = Http::get('https://alttpr.racing/api/v1/modes/'.$ladderEntry['mode'])->json();
+ $mode = new StepLadderMode();
+ $mode->ext_id = $ext_id;
+ $mode->name = $ladderMode['name'];
+ $mode->last_sync = Carbon::now();
+ $mode->save();
+ }
+ return $mode;
+ }
+
+}
--- /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.
+ */
+ public function up(): void
+ {
+ Schema::create('step_ladder_modes', function (Blueprint $table) {
+ $table->id();
+ $table->string('ext_id');
+ $table->string('name');
+ $table->timestamps();
+ $table->timestamp('last_sync')->nullable()->default(null);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('step_ladder_modes');
+ }
+};