Completed
Push — master ( 8e9579...805a94 )
by Cody
08:08 queued 05:54
created

SetupCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
crap 1
1
<?php
2
3
namespace NotificationChannels\Discord\Commands;
4
5
use Exception;
6
use WebSocket\Client;
7
use Illuminate\Support\Arr;
8
use Illuminate\Console\Command;
9
use GuzzleHttp\Client as HttpClient;
10
11
class SetupCommand extends Command
12
{
13
    protected $signature = 'discord:setup';
14
15
    protected $description = "Add the bot to your server(s) and identify it with Discord's gateway.";
16
17
    /**
18
     * @var \GuzzleHttp\Client
19
     */
20
    protected $guzzle;
21
22
    /**
23
     * @var string
24
     */
25
    protected $token = null;
26
27
    /**
28
     * @var string
29
     */
30
    protected $gateway = 'wss://gateway.discord.gg';
31
32 6
    public function __construct(HttpClient $guzzle, $token = null)
33
    {
34 6
        parent::__construct();
35
36 6
        $this->guzzle = $guzzle;
37 6
        $this->token = $token;
38 6
    }
39
40 4
    public function handle()
41
    {
42 4
        if (! $this->token) {
43 1
            $this->error('You must paste your Discord token (App Bot User token) into your `services.php` config file.');
44 1
            $this->error('View the README for more info: https://github.com/laravel-notification-channels/discord#installation');
45
46 1
            return -1;
47
        }
48
49 3
        if (! $this->confirm('Is the bot already added to your server?')) {
50 1
            $clientId = $this->ask('What is your Discord app client ID?');
51
52 1
            $this->warn('Add the bot to your server by visiting this link: https://discordapp.com/oauth2/authorize?&client_id='.$clientId.'&scope=bot&permissions=0');
53
54 1
            if (! $this->confirm('Continue?', true)) {
55 1
                return -1;
56
            }
57
        }
58
59 2
        $this->warn("Attempting to identify the bot with Discord's websocket gateway...");
60
61 2
        $this->gateway = $this->getGateway();
62
63 2
        $this->warn("Connecting to '$this->gateway'...");
64
65 2
        $client = $this->getSocket($this->gateway);
66
67
        // Discord requires all bots to connect via a websocket connection and
68
        // identify at least once before any HTTP API requests are allowed.
69
        // https://discordapp.com/developers/docs/topics/gateway#gateway-identify
70 2
        $client->send(json_encode([
71 2
            'op' => 2,
72
            'd' => [
73 2
                'token' => $this->token,
74 2
                'v' => 3,
75 2
                'compress' => false,
76
                'properties' => [
77 2
                    '$os' => PHP_OS,
78 2
                    '$browser' => 'laravel-notification-channels-discord',
79 2
                    '$device' => 'laravel-notification-channels-discord',
80 2
                    '$referrer' => '',
81 2
                    '$referring_domain' => '',
82 2
                ],
83 2
            ],
84 2
        ]));
85
86 2
        $response = $client->receive();
87 2
        $identified = Arr::get(json_decode($response, true), 't') === 'READY';
88
89 2
        if (! $identified) {
90 1
            $this->error("Discord responded with an error while trying to identify the bot: $response");
91
92 1
            return -1;
93
        }
94
95 1
        $this->info('Your bot has been identified by Discord and can now send API requests!');
96 1
    }
97
98
    public function getSocket($gateway)
99
    {
100
        return new Client($gateway);
101
    }
102
103 2
    public function getGateway()
104
    {
105 2
        $gateway = $this->gateway;
106
107
        try {
108 2
            $response = $this->guzzle->get('https://discordapp.com/api/gateway', [
109
                'headers' => [
110 2
                    'Authorization' => 'Bot '.$this->token,
111 2
                ],
112 2
            ]);
113
114 1
            $gateway = Arr::get(json_decode($response->getBody(), true), 'url', $gateway);
115 2
        } catch (Exception $e) {
116 1
            $this->warn("Could not get a websocket gateway address, defaulting to '{$gateway}'.");
117
        }
118
119 2
        return $gateway;
120
    }
121
}
122