NULL, "client_secret" => NULL, "grant_type" => "authorization_code", "code" => NULL, "redirect_uri" => NULL, "scope" => null ]; /** * UserService constructor. */ public function __construct() { $this->tokenData['client_id'] = config('larascord.client_id'); $this->tokenData['client_secret'] = config('larascord.client_secret'); $this->tokenData['grant_type'] = config('larascord.grant_type'); $this->tokenData['redirect_uri'] = config('larascord.redirect_uri'); $this->tokenData['scope'] = config('larascord.scopes'); } /** * Handles the Discord OAuth2 callback and returns the access token. * * @throws RequestException */ public function getAccessTokenFromCode(string $code): AccessToken { $this->tokenData['code'] = $code; $response = Http::asForm()->post($this->tokenURL, $this->tokenData); $response->throw(); return new AccessToken(json_decode($response->body())); } /** * Get access token from refresh token. * * @throws RequestException */ public function refreshAccessToken(string $refreshToken): AccessToken { $response = Http::asForm()->post($this->tokenURL, [ 'client_id' => config('larascord.client_id'), 'client_secret' => config('larascord.client_secret'), 'grant_type' => 'refresh_token', 'refresh_token' => $refreshToken, ]); $response->throw(); return new AccessToken(json_decode($response->body())); } /** * Authenticates the user with the access token and returns the user data. * * @throws RequestException */ public function getCurrentUser(AccessToken $accessToken): \Jakyeru\Larascord\Types\User { $response = Http::withToken($accessToken->access_token)->get($this->baseApi . '/users/@me'); $response->throw(); return new \Jakyeru\Larascord\Types\User(json_decode($response->body())); } /** * Get the user's guilds. * * @throws RequestException * @throws Exception */ public function getCurrentUserGuilds(AccessToken $accessToken, bool $withCounts = false): array { if (!$accessToken->hasScope('guilds')) throw new Exception(config('larascord.error_messages.missing_guilds_scope.message')); $endpoint = '/users/@me/guilds'; if ($withCounts) { $endpoint .= '?with_counts=true'; } $response = Http::withToken($accessToken->access_token, $accessToken->token_type)->get($this->baseApi . $endpoint); $response->throw(); return array_map(function ($guild) { return new \Jakyeru\Larascord\Types\Guild($guild); }, json_decode($response->body())); } /** * Get the Guild Member object for a user. * * @throws RequestException * @throws Exception */ public function getGuildMember(AccessToken $accessToken, string $guildId): GuildMember { if (!$accessToken->hasScopes(['guilds', 'guilds.members.read'])) throw new Exception(config('larascord.error_messages.missing_guilds_members_read_scope.message')); $response = Http::withToken($accessToken->access_token, $accessToken->token_type)->get($this->baseApi . '/users/@me/guilds/' . $guildId . '/member'); $response->throw(); return new GuildMember(json_decode($response->body())); } /** * Get the User's connections. * * @throws RequestException * @throws Exception */ public function getCurrentUserConnections(AccessToken $accessToken): array { if (!$accessToken->hasScope('connections')) throw new Exception('The "connections" scope is required.'); $response = Http::withToken($accessToken->access_token, $accessToken->token_type)->get($this->baseApi . '/users/@me/connections'); $response->throw(); return array_map(function ($connection) { return new \Jakyeru\Larascord\Types\Connection($connection); }, json_decode($response->body())); } /** * Join a guild. * * @throws RequestException * @throws Exception */ public function joinGuild(AccessToken $accessToken, User $user, string $guildId, array $options = []): GuildMember { if (!config('larascord.access_token')) throw new Exception(config('larascord.error_messages.missing_access_token.message')); if (!$accessToken->hasScope('guilds.join')) throw new Exception('The "guilds" and "guilds.join" scopes are required.'); $response = Http::withToken(config('larascord.access_token'), 'Bot')->put($this->baseApi . '/guilds/' . $guildId . '/members/' . $user->id, array_merge([ 'access_token' => $accessToken->access_token, ], $options)); $response->throw(); if ($response->status() === 204) return throw new Exception('User is already in the guild.'); return new GuildMember(json_decode($response->body())); } /** * Create or update a user in the database. * * @throws Exception */ public function createOrUpdateUser(\Jakyeru\Larascord\Types\User $user): User { if (!$user->getAccessToken()) { throw new Exception('User access token is missing.'); } $forgottenUser = User::where('email', '=', $user->email)->where('id', '!=', $user->id)->first(); if ($forgottenUser) { // This case should never happen (TM) - The discord id changed // The user probably re-created their discord account with the same email // Delete Playlist $playlists = Playlist::where('user_id', $forgottenUser->id)->get(); foreach($playlists as $playlist) { PlaylistEpisode::where('playlist_id', $playlist->id)->forceDelete(); $playlist->forceDelete(); } // Update comments to deleted user DB::table('comments')->where('commenter_id', '=', $forgottenUser->id)->update(['commenter_id' => 1]); $forgottenUser->forceDelete(); } return User::updateOrCreate( [ 'id' => $user->id, ], $user->toArray(), ); } /** * Verify if the user is in the specified guild(s). */ public function isUserInGuilds(array $guilds): bool { // Verify if the user is in all the specified guilds if strict mode is enabled. if (config('larascord.guilds_strict')) { return empty(array_diff(config('larascord.guilds'), array_column($guilds, 'id'))); } // Verify if the user is in any of the specified guilds if strict mode is disabled. return !empty(array_intersect(config('larascord.guilds'), array_column($guilds, 'id'))); } /** * Verify if the user has the specified role(s) in the specified guild. */ public function hasRoleInGuild(GuildMember $guildMember, array $roles): bool { // Verify if the user has any of the specified roles. return !empty(array_intersect($roles, $guildMember->roles)); } /** * Updates the user's roles in the database. */ public function updateUserRoles(User $user, GuildMember $guildMember, int $guildId): void { // Updating the user's roles in the database. $updatedRoles = $user->roles; $updatedRoles[$guildId] = $guildMember->roles; $user->roles = $updatedRoles; $user->save(); } /** * Revoke the user's access token. * * @throws RequestException */ public function revokeAccessToken(string $accessToken): object { $response = Http::asForm()->post($this->tokenURL . '/revoke', [ 'token' => $accessToken, 'client_id' => config('larascord.client_id'), 'client_secret' => config('larascord.client_secret'), ]); $response->throw(); return json_decode($response->body()); } }