]> git.localhorst.tv Git - alttp.git/blob - app/Http/Controllers/ChannelController.php
endpoint for twitch leaderboard
[alttp.git] / app / Http / Controllers / ChannelController.php
1 <?php
2
3 namespace App\Http\Controllers;
4
5 use App\Models\Channel;
6 use App\Models\TwitchBotCommand;
7 use Illuminate\Database\Eloquent\Builder;
8 use Illuminate\Http\Request;
9 use Illuminate\Support\Collection;
10 use Illuminate\Support\Facades\Gate;
11
12 class ChannelController extends Controller {
13
14         public function search(Request $request) {
15                 $validatedData = $request->validate([
16                         'joinable' => 'boolean|nullable',
17                         'manageable' => 'boolean|nullable',
18                         'phrase' => 'string|nullable',
19                 ]);
20
21                 $channels = Channel::query();
22                 if (isset($validatedData['joinable']) && $validatedData['joinable']) {
23                         $channels = $channels->where('twitch_chat', '!=', '');
24                 }
25                 if (isset($validatedData['manageable']) && $validatedData['manageable']) {
26                         $user = $request->user();
27                         if (!$user) {
28                                 return [];
29                         }
30                         $channels = $channels->whereHas('crews', function (Builder $query) use ($user) {
31                                 $query->where('user_id', '=', $user->id);
32                         });
33                 }
34                 if (!empty($validatedData['phrase'])) {
35                         $channels = $channels->where('title', 'LIKE', '%'.$validatedData['phrase'].'%')
36                                 ->orWhere('short_name', 'LIKE', '%'.$validatedData['phrase'].'%');
37                 }
38                 $channels = $channels->limit(5);
39                 return $this->sendChannels($channels->get());
40         }
41
42         public function single(Request $request, Channel $channel) {
43                 $this->authorize('view', $channel);
44                 return $this->sendChannel($channel);
45         }
46
47         public function chat(Request $request, Channel $channel) {
48                 if (!$channel->twitch_chat) {
49                         throw new \Exception('channel has no twitch chat set');
50                 }
51                 $validatedData = $request->validate([
52                         'bot_nick' => 'string',
53                         'text' => 'string|required',
54                 ]);
55                 $this->authorize('editRestream', $channel);
56                 $nick = empty($validatedData['bot_nick']) ? 'localhorsttv' : $validatedData['bot_nick'];
57                 TwitchBotCommand::chat($channel->twitch_chat, $validatedData['text'], $request->user(), $nick);
58                 return $this->sendChannel($channel);
59         }
60
61         public function chatSettings(Request $request, Channel $channel) {
62                 if (!$channel->twitch_chat) {
63                         throw new \Exception('channel has no twitch chat set');
64                 }
65                 $validatedData = $request->validate([
66                         'wait_msgs_min' => 'integer|min:1',
67                         'wait_msgs_max' => 'integer',
68                         'wait_time_min' => 'integer',
69                         'wait_time_max' => 'integer',
70                 ]);
71                 $this->authorize('editRestream', $channel);
72                 $channel->chat_settings = $validatedData;
73                 $channel->save();
74                 return $this->sendChannel($channel);
75         }
76
77         public function join(Request $request, Channel $channel) {
78                 if (!$channel->twitch_chat) {
79                         throw new \Exception('channel has no twitch chat set');
80                 }
81                 $validatedData = $request->validate([
82                         'bot_nick' => 'string',
83                 ]);
84                 $this->authorize('editRestream', $channel);
85                 $nick = empty($validatedData['bot_nick']) ? 'localhorsttv' : $validatedData['bot_nick'];
86                 if ($nick == 'localhorsttv') {
87                         $channel->join = true;
88                 } else if ($nick == 'horstiebot') {
89                         $channel->chat = true;
90                 }
91                 $channel->save();
92                 TwitchBotCommand::join($channel->twitch_chat, $request->user(), $nick);
93                 return $this->sendChannel($channel);
94         }
95
96         public function part(Request $request, Channel $channel) {
97                 if (!$channel->twitch_chat) {
98                         throw new \Exception('channel has no twitch chat set');
99                 }
100                 $validatedData = $request->validate([
101                         'bot_nick' => 'string',
102                 ]);
103                 $this->authorize('editRestream', $channel);
104                 $nick = empty($validatedData['bot_nick']) ? 'localhorsttv' : $validatedData['bot_nick'];
105                 if ($nick == 'localhorsttv') {
106                         $channel->join = false;
107                 } else if ($nick == 'horstiebot') {
108                         $channel->chat = false;
109                 }
110                 $channel->save();
111                 TwitchBotCommand::part($channel->twitch_chat, $request->user(), $nick);
112                 return $this->sendChannel($channel);
113         }
114
115         public function deleteCommand(Channel $channel, $command) {
116                 $this->authorize('editRestream', $channel);
117                 if (isset($channel->chat_commands[$command])) {
118                         $cmds = $channel->chat_commands;
119                         unset($cmds[$command]);
120                         $channel->chat_commands = $cmds;
121                         $channel->save();
122                 }
123                 return $this->sendChannel($channel);
124         }
125
126         public function saveCommand(Request $request, Channel $channel, $command) {
127                 $this->authorize('editRestream', $channel);
128
129                 $validatedData = $request->validate([
130                         'command' => 'string',
131                         'restrict' => 'string',
132                         'type' => 'string',
133                 ]);
134
135                 $cmds = $channel->chat_commands;
136                 $cmds[$command] = $validatedData;
137                 $channel->chat_commands = $cmds;
138                 $channel->save();
139
140                 return $this->sendChannel($channel);
141         }
142
143         public function controlGuessingGame(Request $request, Channel $channel, $name) {
144                 $this->authorize('editRestream', $channel);
145
146                 $validatedData = $request->validate([
147                         'action' => 'required|in:cancel,solve,start,stop',
148                         'solution' => '',
149                 ]);
150
151                 switch ($validatedData['action']) {
152                         case 'cancel':
153                                 $channel->clearGuessing();
154                                 $msg = $channel->getGuessingSetting('cancel_message');
155                                 if (!empty($msg)) {
156                                         TwitchBotCommand::chat($channel->twitch_chat, $msg);
157                                 }
158                                 break;
159                         case 'solve':
160                                 if ($channel->hasActiveGuessing() && $channel->isValidGuess($validatedData['solution'])) {
161                                         $winners = $channel->solveGuessing($validatedData['solution']);
162                                         $names = [];
163                                         foreach ($winners as $winner) {
164                                                 if ($winner->score > 0) {
165                                                         $names[] = $winner->uname;
166                                                 }
167                                         }
168                                         if (empty($names)) {
169                                                 $msg = $channel->getGuessingSetting('no_winners_message');
170                                         } else {
171                                                 $msg = $channel->getGuessingSetting('winners_message');
172                                                 $msg = str_replace('{names}', $channel->listAnd($names), $msg);
173                                         }
174                                         if (!empty($msg)) {
175                                                 TwitchBotCommand::chat($channel->twitch_chat, $msg);
176                                         }
177                                         $channel->clearGuessing();
178                                 }
179                                 break;
180                         case 'start':
181                                 if (!$channel->hasActiveGuessing()) {
182                                         $channel->startGuessing($name);
183                                         $msg = $channel->getGuessingSetting('start_message');
184                                         if (!empty($msg)) {
185                                                 TwitchBotCommand::chat($channel->twitch_chat, $msg);
186                                         }
187                                 }
188                                 break;
189                         case 'stop':
190                                 if ($channel->hasActiveGuessing()) {
191                                         $channel->stopGuessing();
192                                         $msg = $channel->getGuessingSetting('stop_message');
193                                         if (!empty($msg)) {
194                                                 TwitchBotCommand::chat($channel->twitch_chat, $msg);
195                                         }
196                                 }
197                                 break;
198                 }
199
200                 return $this->sendChannel($channel);
201         }
202
203         public function getGuessingGame(Channel $channel, $name) {
204                 $this->authorize('editRestream', $channel);
205
206                 $cutoff = $channel->guessing_start;
207                 if (is_null($cutoff)) {
208                         $last = $channel->winners()->latest()->first();
209                         $cutoff = $last->pod;
210                 }
211                 $guesses = $channel->guesses()->where('created_at', '>=', $cutoff)->orderBy('created_at')->get();
212                 $winners = $channel->winners()->where('created_at', '>=', $cutoff)->orderBy('created_at')->get();
213                 return [
214                         'guesses' => $guesses->toArray(),
215                         'winners' => $winners->toArray(),
216                 ];
217         }
218
219         public function getGuessingGameLeaderboard(Channel $channel, $type) {
220                 return [
221                         'all' => $channel->getGuessingLeaderboard(),
222                 ];
223         }
224
225         public function getGuessingGameMonitor($key) {
226                 $channel = Channel::where('access_key', '=', $key)->firstOrFail();
227
228                 $cutoff = $channel->guessing_start;
229                 if (is_null($cutoff)) {
230                         $last = $channel->winners()->latest()->first();
231                         $cutoff = $last->pod;
232                 }
233                 $guesses = $channel->guesses()->where('created_at', '>=', $cutoff)->orderBy('created_at')->get();
234                 $winners = $channel->winners()->where('created_at', '>=', $cutoff)->orderBy('created_at')->get();
235                 return [
236                         'channel' => $channel->toArray(),
237                         'guesses' => $guesses->toArray(),
238                         'winners' => $winners->toArray(),
239                 ];
240         }
241
242         public function saveGuessingGame(Request $request, Channel $channel, $name) {
243                 $this->authorize('editRestream', $channel);
244
245                 $validatedData = $request->validate([
246                         'active_message' => 'string',
247                         'cancel_message' => 'string',
248                         'invalid_solution_message' => 'string',
249                         'no_winners_message' => 'string',
250                         'not_active_message' => 'string',
251                         'points_exact_first' => 'numeric|min:1|max:5',
252                         'points_exact_other' => 'numeric|min:0|max:5',
253                         'points_close_first' => 'numeric|min:0|max:5',
254                         'points_close_max' => 'integer|min:0',
255                         'points_close_other' => 'numeric|min:0|max:5',
256                         'start_message' => 'string',
257                         'stop_message' => 'string',
258                         'winners_message' => 'string',
259                 ]);
260
261                 $settings = $channel->guessing_settings;
262                 $settings[$name] = $validatedData;
263                 $channel->guessing_settings = $settings;
264                 $channel->save();
265
266                 return $this->sendChannel($channel);
267         }
268
269         protected function sendChannel(Channel $channel) {
270                 if (Gate::allows('editRestream', $channel)) {
271                         $this->unhideChannel($channel);
272                 }
273                 return $channel->toJson();
274         }
275
276         protected function sendChannels(Collection $channels) {
277                 foreach ($channels as $channel) {
278                         if (Gate::allows('editRestream', $channel)) {
279                                 $this->unhideChannel($channel);
280                         }
281                 }
282                 return $channels->toJson();
283         }
284
285         private function unhideChannel(Channel $channel) {
286                 $channel->makeVisible([
287                         'access_key',
288                         'chat',
289                         'chat_commands',
290                         'chat_settings',
291                         'guessing_settings',
292                         'join',
293                         'twitch_chat',
294                 ]);
295         }
296
297 }