]> git.localhorst.tv Git - alttp.git/blob - app/Console/Commands/SyncRacetime.php
racetime sync
[alttp.git] / app / Console / Commands / SyncRacetime.php
1 <?php
2
3 namespace App\Console\Commands;
4
5 use App\Models\Event;
6 use App\Models\Episode;
7 use Carbon\Carbon;
8 use Illuminate\Console\Command;
9 use Illuminate\Database\Eloquent\Builder;
10 use Illuminate\Support\Facades\Http;
11
12 class SyncRacetime extends Command {
13
14         /**
15          * The name and signature of the console command.
16          *
17          * @var string
18          */
19         protected $signature = 'sync:racetime';
20
21         /**
22          * The console command description.
23          *
24          * @var string
25          */
26         protected $description = 'Link racetime rooms with episodes';
27
28         /**
29          * Execute the console command.
30          *
31          * @return int
32          */
33         public function handle() {
34                 $events = Event::whereNotNull('racetime_category')
35                         ->where(function (Builder $query) {
36                                 $query->whereNull('end');
37                                 $query->orWhere('end', '>', now());
38                         })
39                         ->get();
40
41                 foreach ($events as $event) {
42                         try {
43                                 $this->line('syncing '.$event->name);
44                                 $this->syncEvent($event);
45                         } catch (\Exception $e) {
46                                 $this->error('error syncing event '.$event->name.': '.$e->getMessage());
47                         }
48                 }
49
50                 return Command::SUCCESS;
51         }
52
53         private function syncEvent(Event $event) {
54                 $episodes = $event->episodes()->whereBetween('start', [now()->sub(1, 'hour'), now()->add(30, 'minute')])->get();
55                 if ($episodes->isEmpty()) return;
56                 $racerooms = $this->getRacetime($event->racetime_category);
57                 foreach ($episodes as $episode) {
58                         $rooms = $this->filterID($episode, $racerooms);
59                         if (count($rooms) > 1) {
60                                 $rooms = $this->filterStartTime($episode, $rooms);
61                         }
62                         if (count($rooms) > 1) {
63                                 $rooms = $this->filterPlayerNames($episode, $rooms);
64                         }
65                         if (count($rooms) == 1) {
66                                 $this->line(' - linking episode '.$episode->id.' with room '.$rooms[0]['name']);
67                                 $episode->raceroom = 'https://racetime.gg'.$rooms[0]['url'];
68                                 $episode->save();
69                         }
70                 }
71         }
72
73         private function getRacetime($category) {
74                 if (isset($this->cat_cache[$category])) {
75                         return $this->cat_cache[$category];
76                 }
77                 $category_data = HTTP::get('https://racetime.gg/'.$category.'/data');
78                 $races_data = HTTP::get('https://racetime.gg/'.$category.'/races/data');
79                 $this->cat_cache[$category] = array_merge(array_values($category_data['current_races']), array_values($races_data['races']));
80                 return $this->cat_cache[$category];
81         }
82
83         private function filterID(Episode $episode, $racerooms) {
84                 if (empty($episode->ext_id) || substr($episode->ext_id, 0, 3) != 'sg:') {
85                         return $racerooms;
86                 }
87                 $rooms = [];
88                 $id = substr($episode->ext_id, 3);
89                 foreach ($racerooms as $room) {
90                         if (strpos($room['info'], $id) !== false) {
91                                 $rooms[] = $room;
92                         }
93                 }
94                 return empty($rooms) ? $racerooms : $rooms;
95         }
96
97         private function filterStartTime(Episode $episode, $racerooms) {
98                 if (empty($episode->start)) {
99                         return $racerooms;
100                 }
101                 $rooms = [];
102                 $from = Carbon::createFromFormat('Y-m-d H:i:s', $episode->start, 'UTC')->sub(1, 'hour');
103                 $till = Carbon::createFromFormat('Y-m-d H:i:s', $episode->start, 'UTC')->add(1, 'hour');
104                 foreach ($racerooms as $room) {
105                         $created = Carbon::createFromFormat('Y-m-d\TH:i:s.uP', $room['opened_at']);
106                         if ($created->isAfter($from) && $created->isBefore($till)) {
107                                 $rooms[] = $room;
108                         }
109                 }
110                 return empty($rooms) ? $racerooms : $rooms;
111         }
112
113         private function filterPlayerNames(Episode $episode, $racerooms) {
114                 $pnames = [];
115                 foreach ($episode->players as $player) {
116                         $pname = trim($player->getName());
117                         if (!empty($pname)) {
118                                 $pnames[] = $pname;
119                         }
120                 }
121                 if (empty($pnames)) {
122                         return $racerooms;
123                 }
124                 $rooms = [];
125                 foreach ($racerooms as $room) {
126                         $missing = false;
127                         foreach ($pnames as $pname) {
128                                 if (stripos($room['info'], $pname) === false) {
129                                         $missing = true;
130                                         break;
131                                 }
132                         }
133                         if (!$missing) {
134                                 $rooms[] = $room;
135                         }
136                 }
137                 return empty($rooms) ? $racerooms : $rooms;
138         }
139
140         private $cat_cache = [];
141
142 }