Esempio n. 1
0
        private async Task RequestSpotifyAuthForUser(MBUser user, Message message, ILogger logger)
        {
            if (message.Chat.Type != ChatType.Private)
            {
                await TelegramClient.SendTextMessageAsync(
                    message.Chat.Id,
                    $"Sure thing... Sending you a message shortly to get us connected to Spotify");
            }

            var state = new AuthorizationState()
            {
                Message = message,
                UserId  = user.Id,
            };

            await TelegramClient.SendTextMessageAsync(
                user.ServiceId,
                $"OK, in order to continue, I need to connect to your Spotify so I can add you to the fun. Click the button below to get started.",
                replyMarkup : new InlineKeyboardMarkup(
                    new InlineKeyboardButton()
            {
                Text = "Connect Spotify Account",
                Url  = SpotifyService.GetAuthorizationUri(user, state, GetNetSpotifyScopesRequired(user)).ToString()
            }));
        }
Esempio n. 2
0
        private async Task <bool> TryHandleRequiresSpotifyConnection(MBUser user, ILogger logger, Message message, bool isAuthorizationCallback = false)
        {
            if (RequiresSpotify && UserIsMissingSpotify(user))
            {
                logger.LogInformation("User {user} was missing spotify authorization for command {command}", user, this);
                await RequestSpotifyAuthForUser(user, message, logger);

                return(true);
            }

            if (RequiresSpotify && UserIsMissingScopes(user))
            {
                logger.LogInformation("User {user} was missing scopes {scopes} for command {command}", user, string.Join(" ", ScopesRequired), this);
                await ProcessMissingScopes(user, message, isAuthorizationCallback, logger);

                return(true);
            }

            if (RequiresSpotify && RequiresSpotifyPremium)
            {
                var client = await SpotifyService.GetClientAsync(user);

                try
                {
                    var profile = await client.UserProfile.Current();

                    if (profile.Product != "premium")
                    {
                        logger.LogInformation("User {user} tried to use command requiring spotify premium, but found {product}", user, profile.Product);
                        await TelegramClient.SendTextMessageAsync(
                            message.Chat.Id,
                            $"Sorry {user.ToTelegramUserLink()} but you need spotify premium to use this command. Consider upgrading your account and try again.",
                            ParseMode.Html);

                        return(true);
                    }
                }
                catch (SpotifyAPI.Web.APIException ex)
                {
                    if (ex.Response.StatusCode == HttpStatusCode.BadRequest)
                    {
                        var error = JsonConvert.DeserializeObject <SpotifyError>(ex.Response.Body as string);
                        if (error.ErrorDescription == "Refresh token revoked")
                        {
                            // TODO: Make this more language natural.. currently acts like a new user
                            logger.LogWarning("User {user} revoked Spotify credentials", user);
                            await RequestSpotifyAuthForUser(user, message, logger);

                            return(true);
                        }
                    }

                    throw;
                }
            }

            return(false);
        }
Esempio n. 3
0
        private async Task ProcessMissingScopes(MBUser user, Message message, bool isAuthorizationCallback, ILogger log)
        {
            var scopesRequierd = GetNetSpotifyScopesRequired(user);
            var missingScopes  = scopesRequierd.Except(user.SpotifyScopesList);

            if (isAuthorizationCallback)
            {
                // User already setup, this is an auth callback.. they must have denied scopes?
                // TODO: Send through error state from auth call

                log.LogWarning("User {user} denied scopes {scopes} for commmand {command}", user, string.Join(" ", missingScopes), this);

                await TelegramClient.SendTextMessageAsync(
                    message.Chat.Id,
                    $@"Sorry {user.ToTelegramUserLink()} but you need to grant additional permissions in order for us to run this command.",
                    ParseMode.Html);

                return;
            }

            // Request additional scopes
            var state = new AuthorizationState()
            {
                Message = message,
                UserId  = user.Id
            };

            log.LogInformation("User {user} needs to grant additional scopes for {command} ({misingScopes})", user, this, string.Join(' ', missingScopes));

            if (message.Chat.Id != message.From.Id)
            {
                await TelegramClient.SendTextMessageAsync(
                    message.Chat.Id,
                    $"Sure thing {user.ToTelegramUserLink()}... we need a few more permissions from you first. Check your private messages.",
                    ParseMode.Html
                    );
            }

            var response = string.IsNullOrWhiteSpace(user.SpotifyId)
                ? $"Sure! lets get you connected first. Click this link and authorize me to manage your Spotify player."
                : $"We need additional Spotify permissions from you to run the command {this.Command}. Please click this link and we'll get that sorted";

            await TelegramClient.SendTextMessageAsync(
                message.From.Id,
                response,
                ParseMode.Html,
                replyMarkup : new InlineKeyboardMarkup(
                    new InlineKeyboardButton()
            {
                Text = "Connect Account",
                Url  = SpotifyService.GetAuthorizationUri(user, state, GetNetSpotifyScopesRequired(user)).ToString()
            })
                );
        }
Esempio n. 4
0
        private async Task <bool> TryHandleRequiresBotConnection(MBUser user, ILogger logger, Message message)
        {
            if (RequiresBotConnection && UserIsNotConnected(user))
            {
                logger.LogInformation("User {user} wasn't connected, starting connection process", user);
                await RequestTelegramAuthForUser(user, message, logger);

                return(true);
            }

            return(false);
        }
Esempio n. 5
0
        public async Task Process(MBUser user, CallbackQuery callback, ILogger logger)
        {
            if (await TryHandleRequiresBotConnection(user, logger, callback.Message))
            {
                return;
            }
            if (await TryHandleRequiresSpotifyConnection(user, logger, callback.Message))
            {
                return;
            }

            await ProcessInternalAsync(user, callback, logger);
        }
Esempio n. 6
0
        private async Task RequestTelegramAuthForUser(MBUser user, Message message, ILogger logger)
        {
            logger.LogInformation("Having user {user} auth with Telegram (chat: {chatid})", user, message.Chat.Id);
            var state = message.Base64Encode();
            await TelegramClient.SendTextMessageAsync(
                message.Chat.Id,
                $"Sure thing... First click this link to allow me to chat with you directly.",
                replyMarkup : new InlineKeyboardMarkup(
                    new InlineKeyboardButton()
            {
                Text     = "Connect Account",
                LoginUrl = new LoginUrl()
                {
                    RequestWriteAccess = true,
                    Url = $"{Config.BaseUrl}/auth/telegram?state={state}"
                }
            }));

            return;
        }
Esempio n. 7
0
        private string[] GetNetSpotifyScopesRequired(MBUser user)
        {
            var result = user.SpotifyScopesList ?? new List <string>();

            foreach (var scope in ScopesRequired)
            {
                if (!result.Contains(scope))
                {
                    result.Add(scope);
                }
            }

            if (RequiresSpotifyPremium && !result.Contains(Scopes.UserReadPrivate))
            {
                // So we can verify they have spotify premium
                // see Product property:
                // https://developer.spotify.com/documentation/web-api/reference/users-profile/get-current-users-profile/#user-object-private
                result.Add(Scopes.UserReadPrivate);
            }

            return(result.ToArray());
        }
Esempio n. 8
0
        public async Task Process(MBUser user, Message message, ILogger logger, bool isAuthorizationCallback = false)
        {
            if (!SupportedChatTypes.Contains(message.Chat.Type))
            {
                logger.LogDebug("Command {command} does not support chat type {type}", this, message.Chat.Type);
                await TelegramClient.SendTextMessageAsync(
                    message.Chat.Id,
                    $"Sorry, that command isn't supported in this type of chat. That command can only be used in {string.Join(", ", SupportedChatTypes.Select(x => $"{x}s".ToLower()))}");

                return;
            }

            if (await TryHandleRequiresBotConnection(user, logger, message))
            {
                return;
            }
            if (await TryHandleRequiresSpotifyConnection(user, logger, message, isAuthorizationCallback))
            {
                return;
            }

            await ProcessInternalAsync(user, message, logger, isAuthorizationCallback);
        }
Esempio n. 9
0
 protected override Task ProcessInternalAsync(MBUser user, CallbackQuery callback, ILogger logger)
 {
     // Shouldn't be anything to do here... ever
     return(Task.CompletedTask);
 }
Esempio n. 10
0
 protected override async Task ProcessInternalAsync(MBUser user, Message message, ILogger logger, bool isAuthorizationCallback = false)
 {
     await TelegramClient.SendTextMessageAsync(message.Chat.Id, $"I'm not sure how to deal with this: '{message.Text}'");
 }
Esempio n. 11
0
 protected abstract Task ProcessInternalAsync(MBUser user, CallbackQuery callback, ILogger logger);
Esempio n. 12
0
 protected abstract Task ProcessInternalAsync(MBUser user, Message message, ILogger logger, bool isAuthorizationCallback = false);
Esempio n. 13
0
 private bool UserIsMissingScopes(MBUser user)
 {
     return(!GetNetSpotifyScopesRequired(user)
            .All(scope => user.SpotifyScopes?.Contains(scope) ?? false));
 }
Esempio n. 14
0
 private bool UserIsNotConnected(MBUser user)
 {
     return(!user.ServiceAuthDate.HasValue);
 }
Esempio n. 15
0
 private bool UserIsMissingSpotify(MBUser user)
 {
     return(string.IsNullOrWhiteSpace(user.SpotifyId));
 }