public void RequestAuthorizationUrl_Scopes_UrlContainsSpaceDelimitedScopes()
        {
            // arrange
            const string state = "abc123";

            string[] scopes = new[]
            {
                "user-modify-playback-state",
                "user-read-playback-state",
                "playlist-read-collaborative",
                "playlist-modify-public",
                "playlist-modify-private",
                "playlist-read-private",
                "user-read-email"
            };

            var config = new MockConfiguration().Object;
            var http   = new HttpClient();
            //var tokenStore = new MockRefreshTokenStore(UserHash, config).Object;
            var service = new UserAccountsService(http, config);

            // act
            string url = service.AuthorizeUrl(state, scopes);

            // assert
            Assert.IsTrue(url.Contains(string.Join("%20", scopes)), "url should contain %20 (space) delimited user scopes");
            Trace.WriteLine("RequestAuthorizationUrl_Scopes_UrlContainsSpaceDelimitedScopes url =");
            Trace.WriteLine(url);
        }
Example #2
0
 public ProfileModule(UserAccountsService userAccounts, ILogger <ProfileModule> logger, PairsService pairs, DiscordSocketClient client)
 {
     _userAccounts = userAccounts;
     _logger       = logger;
     _pairs        = pairs;
     _console      = client.GetChannel(ulong.Parse(_pairs.GetString("CONSOLE_CHANNEL_ID"))) as SocketTextChannel;
 }
Example #3
0
        public async Task PlayContext_SpotifyUri_SpotifyApiErrorException()
        {
            // arrange
            const string userHash   = "E11AC28538A7C0A827A726DD9B30B710FC1FCAFFFE2E86FCA853AB90E7C710D2";
            const string spotifyUri = "spotify:user:palsvensson:playlist:2iL5fr6OmN8f4yoQvvuWSf";

            var http   = new HttpClient();
            var config = TestsHelper.GetLocalConfig();

            var accounts = new UserAccountsService(http, config, new MockRefreshTokenStore(userHash).Object, null);
            var api      = new PlayerApi(http, accounts);

            // act
            //try
            //{
            await api.PlayContext(userHash, spotifyUri);

            //}
            //catch (SpotifyApiErrorException ex)
            //{
            //Trace.WriteLine(ex.Message);

            //}

            // assert
        }
Example #4
0
        public async Task GetUserAccessToken_TokenNotExpired_ReturnsCurrentToken()
        {
            // arrange
            var currentToken = new BearerAccessToken
            {
                AccessToken = "abcd1234",
                ExpiresIn   = 3600,
                Expires     = DateTime.UtcNow.AddSeconds(3600)
            };

            var http             = new MockHttpClient().HttpClient;
            var bearerTokenStore = new Mock <IBearerTokenStore>();

            bearerTokenStore.Setup(s => s.Get(It.IsAny <string>())).ReturnsAsync(currentToken);

            var config = new MockConfiguration().Object;

            var refreshTokenStore = new MockRefreshTokenStore(UserHash, config).Object;
            var service           = new UserAccountsService(http, config, refreshTokenStore, bearerTokenStore.Object);

            // act
            var token = await service.GetUserAccessToken(UserHash);

            // assert
            Assert.AreEqual(currentToken, token);
        }
Example #5
0
        public RssJob(ILogger <ReminderJob> logger, DiscordSocketClient client, UserAccountsService accounts)
        {
            _logger      = logger;
            _client      = client;
            _accounts    = accounts;
            _channels    = new Dictionary <ulong, SocketTextChannel>();
            _lastUpdates = new Dictionary <FeedConfig, DateTime?>();
            _webClient   = new WebClient();

            _configs = JsonConvert.DeserializeObject <List <FeedConfig> >(File.ReadAllText("Config/feeds.json"));

            foreach (var config in _configs)
            {
                foreach (var channelId in config.ChannelIds)
                {
                    if (_channels.ContainsKey(channelId))
                    {
                        continue;
                    }
                    _channels.Add(channelId, client.GetChannel(channelId) as SocketTextChannel);
                }
            }

            foreach (var feedConfig in _configs)
            {
                _lastUpdates.Add(feedConfig, null);
            }
        }
Example #6
0
        public async Task GetUserAccessToken_TokenExpired_ReturnsNewToken()
        {
            // arrange
            var expiredToken = new BearerAccessToken
            {
                AccessToken = "abcd1234",
                ExpiresIn   = 3600,
                Expires     = new DateTime(2018, 7, 28, 9, 18, 0, DateTimeKind.Utc)
            };

            const string json = @"{
""access_token"": ""NgCXRKc...MzYjw"",
""token_type"": ""bearer"",
""expires_in"": 3600,
}";

            var mockHttp = new MockHttpClient();

            mockHttp.SetupSendAsync(json);
            var http = mockHttp.HttpClient;

            var bearerTokenStore = new Mock <IBearerTokenStore>();

            bearerTokenStore.Setup(s => s.Get(It.IsAny <string>())).ReturnsAsync(expiredToken);
            var config            = new MockConfiguration().Object;
            var refreshTokenStore = new MockRefreshTokenStore(UserHash, config).Object;
            var service           = new UserAccountsService(http, config, refreshTokenStore, bearerTokenStore.Object);

            // act
            var token = await service.GetUserAccessToken(UserHash);

            // assert
            Assert.AreNotEqual(expiredToken, token);
        }
Example #7
0
 public AdminModule(ILogger <AdminModule> logger, DiscordSocketClient client, PairsService pairs,
                    UserAccountsService accounts)
 {
     _logger   = logger;
     _client   = client;
     _pairs    = pairs;
     _accounts = accounts;
 }
Example #8
0
        public AssignPointsModule(UserAccountsService accounts, PairsService pairs, ILogger <AssignPointsModule> logger, DiscordSocketClient client)
        {
            _accounts = accounts;
            _pairs    = pairs;
            _logger   = logger;
            _client   = client;

            _webClient = new WebClient();

            // KubĂ­k, Hajgrando, and H3G1
            _authorizedUsers = new ulong[] { 408675740633268226, 213659030244163585, 688157416407302161 };
        }
        public void AuthorizeUrl_StateParam_UrlContainsState()
        {
            // arrange
            const string state  = "abc123";
            var          http   = new MockHttpClient().HttpClient;
            var          config = new MockConfiguration().Object;
            //var tokenStore = new MockRefreshTokenStore(UserHash, config).Object;
            var service = new UserAccountsService(http, config);

            // act
            string url = service.AuthorizeUrl(state, null);

            // assert
            Assert.IsTrue(url.Contains(state), "url result should contain state param");
        }
        public async Task GetUsersProfile_NoUserId_DeserializedResponse()
        {
            // arrange
            var config      = TestsHelper.GetLocalConfig();
            var accessToken = config["SpotifyUserBearerAccessToken"];
            var http        = new HttpClient();
            var accounts    = new UserAccountsService(http, config);

            var api = new UsersProfileApi(http, accounts);

            // act
            // must use a User Access Token for this call
            var response = await api.GetCurrentUsersProfile(accessToken : accessToken);

            Assert.IsNotNull(response);
        }
        public IActionResult AuthorizeSpotify(RoomVM roomVM)
        {
            var accountService = new UserAccountsService(new HttpClient(), _config);

            var    roomId = roomVM.SyncAuthorization ? $"{roomVM.CurrentRoom.Id}-sync" : roomVM.CurrentRoom.Id.ToString();
            string url    = accountService
                            .AuthorizeUrl(
                roomId,
                new[] { "user-read-playback-state streaming user-read-private user-read-email playlist-read-private user-library-read playlist-modify-public playlist-modify-private" });

            if (roomVM.SyncAuthorization)
            {
                return(Ok(url));
            }

            return(Redirect(url));
        }
Example #12
0
        //[TestMethod]
        public async Task Usage2()
        {
            // Get a list of a User's devices
            // This requires User authentication and authorization.
            // A `UserAccountsService` is provided to help with this.

            // HttpClient and UserAccountsService can be reused.
            // Tokens can be cached by your code
            var http     = new HttpClient();
            var accounts = new UserAccountsService(http, TestsHelper.GetLocalConfig());

            // See https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
            //  for an explanation of the Authorization code flow

            // Generate a random state value to use in the Auth request
            string state = Guid.NewGuid().ToString("N");
            // Accounts service will derive the Auth URL for you
            string url = accounts.AuthorizeUrl(state, new[] { "user-read-playback-state" });

            /*
             *  Redirect the user to `url` and when they have auth'ed Spotify will redirect to your reply URL
             *  The response will include two query parameters: `state` and `code`.
             *  For a full working example see `SpotifyApi.NetCore.Samples`.
             */
            var query = new Dictionary <string, string>();

            // Check that the request has not been tampered with by checking the `state` value matches
            if (state != query["state"])
            {
                throw new ArgumentException();
            }

            // Use the User accounts service to swap `code` for a Refresh token
            BearerAccessRefreshToken token = await accounts.RequestAccessRefreshToken(query["code"]);

            // Use the Bearer (Access) Token to call the Player API
            var player = new PlayerApi(http, accounts);

            Device[] devices = await player.GetDevices(accessToken : token.AccessToken);

            foreach (Device device in devices)
            {
                Trace.WriteLine($"Device {device.Name} Status = {device.Type} Active = {device.IsActive}");
            }
        }
        //TODO: Something is up - the first error is not being thrown to the test runner...
        //[TestMethod]
        public async Task TwoCompetingUserAccessTokenRequestsGetConsistentResults()
        {
            const string userHash   = "E11AC28538A7C0A827A726DD9B30B710FC1FCAFFFE2E86FCA853AB90E7C710D2";
            const string spotifyUri = "spotify:user:palsvensson:playlist:2iL5fr6OmN8f4yoQvvuWSf";

            var store = new MockRefreshTokenStore(userHash).Object;

            var http1     = new HttpClient();
            var accounts1 = new UserAccountsService(http1, TestsHelper.GetLocalConfig(), store);
            var player1   = new PlayerApi(http1, accounts1);

            var http2     = new HttpClient();
            var accounts2 = new UserAccountsService(http2, TestsHelper.GetLocalConfig(), store);
            var player2   = new PlayerApi(http2, accounts2);

            // act
            //try
            //{
            //TODO: Call Device method instead
            await player1.PlayContext(userHash, spotifyUri);

            //}
            //catch (SpotifyApiErrorException ex)
            //{
            //Trace.WriteLine(ex.Message);
            //}

            //try
            //{
            await player2.PlayContext(userHash, spotifyUri);

            //}
            //catch (SpotifyApiErrorException ex)
            //{
            //  Trace.WriteLine(ex.Message);
            //}

            // assert
            // no error
        }
Example #14
0
 public void Initialize()
 {
     //_refreshTokenProvider = new MockRefreshTokenStore(UserHash).Object;
     _accounts = new UserAccountsService(new HttpClient(), TestsHelper.GetLocalConfig());
 }
Example #15
0
 public LeaderboardModule(UserAccountsService userAccounts, PairsService pairs)
 {
     _userAccounts    = userAccounts;
     _pairs           = pairs;
     _leaderboardSize = 15;
 }
Example #16
0
        public async Task <TokenResponse> Authorize(ITurnContext turnContext, CancellationToken cancellationToken)
        {
            var    info   = RingoBotHelper.NormalizedConversationInfo(turnContext);
            string userId = RingoBotHelper.ChannelUserId(turnContext);

            TokenResponse token = await GetAccessToken(userId);

            if (token != null)
            {
                return(token);
            }

            // User is not authorized by Spotify
            if (BotHelper.IsGroup(turnContext))
            {
                // Don't start authorisation dance in Group chat
                await turnContext.SendActivityAsync(
                    $"Before you play or join with Ringo you need to authorize Spotify. DM (direct message) the word `\"{RingoBotCommands.AuthCommand[0]}\"` to @{info.BotName} to continue.",
                    cancellationToken : cancellationToken);

                return(null);
            }

            _logger.LogInformation($"Requesting Spotify Authorization for UserId {userId}");

            await _userData.CreateUserIfNotExists(info);

            // create state token
            string state = $"{RingoBotStatePrefix}{Guid.NewGuid().ToString("N")}".ToLower();

            // validate state token
            if (!RingoBotStateRegex.IsMatch(state))
            {
                throw new InvalidOperationException("Generated state token does not match RingoBotStateRegex");
            }

            // save state token
            await _userStateData.SaveStateToken(userId, state);

            await _userData.SaveStateToken(userId, state);

            // get URL
            string url = UserAccountsService.AuthorizeUrl(
                state,
                new[] { "user-read-playback-state", "user-modify-playback-state" },
                _config["SpotifyApiClientId"],
                _config["SpotifyAuthRedirectUri"]);

            var message = MessageFactory.Attachment(
                new Attachment
            {
                ContentType = HeroCard.ContentType,
                Content     = new HeroCard
                {
                    Text    = "Authorize Ringo bot to use your Spotify account",
                    Buttons = new[]
                    {
                        new CardAction
                        {
                            Title = "Authorize",
                            Text  = "Click to Authorize. (Opens in your browser)",
                            Value = url,
                            Type  = ActionTypes.OpenUrl,
                        },
                    },
                },
            },
                text: "To play music, Ringo needs to be authorized to use your Spotify Account.");

            await turnContext.SendActivityAsync(message, cancellationToken);

            return(null);
        }