| Conditions | 53 |
| Paths | 2 |
| Total Lines | 213 |
| Code Lines | 125 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 187 | function run() { |
||
| 188 | if($this->command === null) { |
||
| 189 | throw new \LogicException('This message has no command'); |
||
| 190 | } |
||
| 191 | |||
| 192 | return (new \React\Promise\Promise(function (callable $resolve, callable $reject) { |
||
| 193 | $promises = array(); |
||
| 194 | |||
| 195 | // Obtain the member if we don't have it |
||
| 196 | if($this->message->guild !== null && !$this->message->guild->members->has($this->message->author->id) && $this->message->webhookID === null) { |
||
| 197 | $promises[] = $this->message->guild->fetchMember($this->message->author->id); |
||
| 198 | } |
||
| 199 | |||
| 200 | // Obtain the member for the client user if we don't have it |
||
| 201 | if($this->message->guild !== null && $this->message->guild->me === null) { |
||
| 202 | $promises[] = $this->message->guild->fetchMember($this->client->user->id); |
||
| 203 | } |
||
| 204 | |||
| 205 | if($this->command->guildOnly && $this->message->guild === null) { |
||
| 206 | $this->client->emit('commandBlocked', $this, 'guildOnly'); |
||
| 207 | return $this->client->dispatcher->throttleNegativeResponseMessage($this, 'The `'.$this->command->name.'` command must be used in a server channel.', $resolve, $reject); |
||
| 208 | } |
||
| 209 | |||
| 210 | if($this->command->nsfw && !($this->message->channel->nsfw ?? true)) { |
||
| 211 | $this->client->emit('commandBlocked', $this, 'nsfw'); |
||
| 212 | return $this->client->dispatcher->throttleNegativeResponseMessage($this, 'The `'.$this->command->name.'` command must be used in NSFW channels.', $resolve, $reject); |
||
| 213 | } |
||
| 214 | |||
| 215 | $perms = $this->command->hasPermission($this); |
||
| 216 | if($perms === false || \is_string($perms)) { |
||
| 217 | $this->client->emit('commandBlocked', $this, 'permission'); |
||
| 218 | |||
| 219 | if($this->patternMatches !== null && !((bool) $this->client->getOption('commandBlockedMessagePattern', true))) { |
||
| 220 | return $resolve(); |
||
| 221 | } |
||
| 222 | |||
| 223 | if($perms === false) { |
||
| 224 | $perms = 'You do not have permission to use the `'.$this->command->name.'` command.'; |
||
| 225 | } |
||
| 226 | |||
| 227 | return $this->client->dispatcher->throttleNegativeResponseMessage($this, $perms, $resolve, $reject); |
||
| 228 | } |
||
| 229 | |||
| 230 | // Ensure the client user has the required permissions |
||
| 231 | if( |
||
| 232 | $this->message->channel instanceof \CharlotteDunois\Yasmin\Interfaces\GuildChannelInterface && |
||
| 233 | $this->message->channel->guild !== null && |
||
| 234 | !empty($this->command->clientPermissions) |
||
| 235 | ) { |
||
| 236 | $perms = $this->message->channel->permissionsFor($this->message->guild->me); |
||
| 237 | |||
| 238 | $missing = array(); |
||
| 239 | foreach($this->command->clientPermissions as $perm) { |
||
| 240 | if($perms->missing($perm)) { |
||
| 241 | $missing[] = $perm; |
||
| 242 | } |
||
| 243 | } |
||
| 244 | |||
| 245 | if(\count($missing) > 0) { |
||
| 246 | $this->client->emit('commandBlocked', $this, 'clientPermissions'); |
||
| 247 | |||
| 248 | if($this->patternMatches !== null && !((bool) $this->client->getOption('commandBlockedMessagePattern', true))) { |
||
| 249 | return $resolve(); |
||
| 250 | } |
||
| 251 | |||
| 252 | if(\count($missing) === 1) { |
||
| 253 | $msg = 'I need the permissions `'.$missing[0].'` permission for the `'.$this->command->name.'` command to work.'; |
||
| 254 | } else { |
||
| 255 | $missing = \implode(', ', \array_map(function ($perm) { |
||
| 256 | return '`'.\CharlotteDunois\Yasmin\Models\Permissions::resolveToName($perm).'`'; |
||
| 257 | }, $missing)); |
||
| 258 | $msg = 'I need the following permissions for the `'.$this->command->name.'` command to work:'.\PHP_EOL.$missing; |
||
| 259 | } |
||
| 260 | |||
| 261 | return $this->client->dispatcher->throttleNegativeResponseMessage($this, $msg, $resolve, $reject); |
||
| 262 | } |
||
| 263 | } |
||
| 264 | |||
| 265 | // Throttle the command |
||
| 266 | $throttle = $this->command->throttle($this->message->author->id); |
||
| 267 | if($throttle && ($throttle['usages'] + 1) > ($this->command->throttling['usages'])) { |
||
| 268 | $remaining = $throttle['start'] + $this->command->throttling['duration'] - \time(); |
||
| 269 | $this->client->emit('commandBlocked', $this, 'throttling'); |
||
| 270 | |||
| 271 | if($this->patternMatches !== null && !((bool) $this->client->getOption('commandThrottlingMessagePattern', true))) { |
||
| 272 | return $resolve(); |
||
| 273 | } |
||
| 274 | |||
| 275 | return $this->client->dispatcher->throttleNegativeResponseMessage( |
||
| 276 | $this, |
||
| 277 | 'You may not use the `'.$this->command->name.'` command again for another '.$remaining.' seconds.', |
||
| 278 | $resolve, |
||
| 279 | $reject |
||
| 280 | ); |
||
| 281 | } |
||
| 282 | |||
| 283 | // Figure out the command arguments |
||
| 284 | $args = $this->patternMatches; |
||
| 285 | $argmsgs = array(); |
||
| 286 | $countArgs = \count($this->command->args); |
||
| 287 | |||
| 288 | if(!$args && $countArgs > 0) { |
||
| 289 | $count = (!empty($this->command->args[($countArgs - 1)]['infinite']) ? \INF : $countArgs); |
||
| 290 | $provided = self::parseArgs($this->argString, $count, $this->command->argsSingleQuotes); |
||
| 291 | |||
| 292 | $promises[] = $this->command->argsCollector->obtain($this, $provided)->then(function ($result) use (&$args, &$argmsgs) { |
||
| 293 | if($result['cancelled']) { |
||
| 294 | if(\count($result['prompts']) === 0) { |
||
| 295 | throw new \CharlotteDunois\Livia\Exceptions\CommandFormatException($this); |
||
| 296 | } |
||
| 297 | |||
| 298 | $argmsgs = $result['prompts']; |
||
| 299 | $this->client->emit('commandCancelled', $this, $result['cancelled']); |
||
| 300 | |||
| 301 | throw new \CharlotteDunois\Livia\Exceptions\FriendlyException('Cancelled Command.'); |
||
| 302 | } |
||
| 303 | |||
| 304 | $args = $result['values']; |
||
| 305 | $argmsgs = $result['prompts']; |
||
| 306 | |||
| 307 | if(!$args) { |
||
| 308 | $args = $this->parseCommandArgs(); |
||
| 309 | } |
||
| 310 | |||
| 311 | $args = new \ArrayObject(((array) $args), \ArrayObject::ARRAY_AS_PROPS); |
||
| 312 | }); |
||
| 313 | } else { |
||
| 314 | $args = new \ArrayObject(((array) $args), \ArrayObject::ARRAY_AS_PROPS); |
||
| 315 | } |
||
| 316 | |||
| 317 | // Run the command |
||
| 318 | if($throttle) { |
||
| 319 | $this->command->updateThrottle($this->message->author->id); |
||
| 320 | } |
||
| 321 | |||
| 322 | $typingCount = $this->message->channel->typingCount(); |
||
| 323 | |||
| 324 | \React\Promise\all($promises)->then(function () use (&$args, &$argmsgs) { |
||
| 325 | $promise = $this->command->run($this, $args, ($this->patternMatches !== null)); |
||
| 326 | |||
| 327 | if(!($promise instanceof \React\Promise\PromiseInterface)) { |
||
| 328 | $promise = \React\Promise\resolve($promise); |
||
| 329 | } |
||
| 330 | |||
| 331 | $this->client->emit('commandRun', $this->command, $promise, $this, $args, ($this->patternMatches !== null)); |
||
| 332 | |||
| 333 | return $promise->then(function ($response) use (&$argmsgs) { |
||
| 334 | if(!( |
||
| 335 | $response instanceof \CharlotteDunois\Yasmin\Models\Message || |
||
| 336 | $response instanceof \CharlotteDunois\Collect\Collection || |
||
| 337 | \is_array($response) || |
||
| 338 | $response === null |
||
| 339 | )) { |
||
| 340 | throw new \RuntimeException('Command '.$this->command->name.'\'s run() resolved with an unknown type ('.\gettype($response).'). Command run methods must return a Promise that resolve with a Message, an array of Messages, a Collection of Messages, or null.'); |
||
| 341 | } |
||
| 342 | |||
| 343 | if(!\is_array($response) && !($response instanceof \CharlotteDunois\Collect\Collection)) { |
||
| 344 | if($response instanceof \CharlotteDunois\Yasmin\Models\Message) { |
||
| 345 | $argmsgs[] = $response; |
||
| 346 | } |
||
| 347 | |||
| 348 | return $argmsgs; |
||
| 349 | } |
||
| 350 | |||
| 351 | foreach($response as &$val) { |
||
| 352 | if(!($val instanceof \React\Promise\PromiseInterface)) { |
||
| 353 | $val = \React\Promise\resolve($val); |
||
| 354 | } |
||
| 355 | } |
||
| 356 | |||
| 357 | return \React\Promise\all($response)->then(function ($msgs) use (&$argmsgs) { |
||
| 358 | return \array_merge($argmsgs, $msgs); |
||
| 359 | }); |
||
| 360 | }); |
||
| 361 | })->then(null, function (\Throwable $error) use (&$args, $typingCount, &$argmsgs) { |
||
| 362 | if($this->message->channel->typingCount() > $typingCount) { |
||
| 363 | $this->message->channel->stopTyping(); |
||
| 364 | } |
||
| 365 | |||
| 366 | if($error instanceof \CharlotteDunois\Livia\Exceptions\FriendlyException) { |
||
| 367 | return $this->reply($error->getMessage())->then(function (\CharlotteDunois\Yasmin\Models\Message $msg) use (&$argmsgs) { |
||
| 368 | $argmsgs[] = $msg; |
||
| 369 | return $argmsgs; |
||
| 370 | }); |
||
| 371 | } |
||
| 372 | |||
| 373 | $this->client->emit('commandError', $this->command, $error, $this, $args, ($this->patternMatches !== null)); |
||
| 374 | |||
| 375 | $owners = $this->client->owners; |
||
| 376 | $ownersLength = \count($owners); |
||
| 377 | |||
| 378 | if($ownersLength > 0) { |
||
| 379 | $index = 0; |
||
| 380 | $owners = \array_map(function ($user) use (&$index, $ownersLength) { |
||
| 381 | $or = ($ownersLength > 1 && $index === ($ownersLength - 1) ? 'or ' : ''); |
||
| 382 | $index++; |
||
| 383 | |||
| 384 | return $or.\CharlotteDunois\Yasmin\Utils\MessageHelpers::escapeMarkdown($user->tag); |
||
| 385 | }, $owners); |
||
| 386 | |||
| 387 | $owners = \implode((\count($owners) > 2 ? ', ' : ' '), $owners); |
||
| 388 | } else { |
||
| 389 | $owners = 'the bot owner'; |
||
| 390 | } |
||
| 391 | |||
| 392 | return $this->reply('An error occurred while running the command: `'.\get_class($error).': '.\str_replace('`', '', $error->getMessage()).'`'.\PHP_EOL. |
||
| 393 | 'You shouldn\'t ever receive an error like this.'.\PHP_EOL. |
||
| 394 | 'Please contact '.$owners.($this->client->getOption('invite') ? ' in this server: '.$this->client->getOption('invite') : '.')) |
||
| 395 | ->then(function (\CharlotteDunois\Yasmin\Models\Message $msg) use (&$argmsgs) { |
||
| 396 | $argmsgs[] = $msg; |
||
| 397 | return $argmsgs; |
||
| 398 | }); |
||
| 399 | })->done($resolve, $reject); |
||
| 400 | })); |
||
| 721 |