Ejemplo n.º 1
0
        public async Task AuthenticateUserAsync(string clientId,
                                                string clientSecret,
                                                string localIp,
                                                SemaphoreSlim semaphore,
                                                CancellationToken cancellationToken)
        {
            await semaphore.WaitAsync();

            cancellationToken.ThrowIfCancellationRequested();
            logger.LogInformation("Starting authentication process.");

            // If we're authenticating for the first time, we want to clear out our tokens if they exist.
            using (var context = contextProvider.GenerateContext <ISpotifyContext>(scopeFactory))
            {
                foreach (var token in context.Tokens)
                {
                    context.Tokens.Remove(token);
                }

                await context.SaveChangesAsync(cancellationToken);
            }

            Scope[] scopes = new Scope[] {
                Scope.UserLibraryModify,
                Scope.UserReadPrivate,
                Scope.UserReadEmail,
                Scope.UserLibraryRead,
                Scope.PlaylistModifyPublic
            };

            // Wrapper class for AuthorizationCodeAuth - Works better with inability to open a browser on pi.
            Auth = new SpotifyAuthorizationCodeAuth(
                clientId,
                clientSecret,
                $"http://{localIp}:4002",
                $"http://{localIp}:4002",
                scopes
                );

            logger.LogInformation($"id - {clientId}\n secret - {clientSecret}\n localIp - {localIp}\n scopes - {scopes}");

            // Delegate for when the endpoint has been accessed/approved by user.
            Auth.AuthReceived += async(sender, payload) =>
            {
                logger.LogInformation("Authentication received. Creating api object.");
                Auth.Stop();

                Token = await Auth.ExchangeCode(payload.Code);

                RefreshToken = Token.RefreshToken;

                // We got a new token, we save it.
                using (var scope = scopeFactory.CreateScope())
                {
                    var context = scope.ServiceProvider.GetService <ISpotifyContext>();
                    context.Tokens.Add((SpotifyToken)Token);
                    await context.SaveChangesAsync(cancellationToken);
                }

                // Denotes that we can refresh the token in the future.
                IsAuthenticated = true;

                semaphore.Release();
            };

            // Starts to listen using the auth endpoint.
            Auth.Start();

            var authString = Auth.CreateUri();

            // This will do for now, but I'd like to have a better way of doing this.
            // Logging it as an error makes it email the code to the provided user.
            logger.LogError($"Spotify user is not authenticated. Please visit this link to authenticate:\n {authString}");
        }