Пример #1
0
        /// <summary>
        /// Formats a notification string with the necessary parameters
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static string GetNotificationMessage(ILiveBotStream stream, StreamSubscription subscription, ILiveBotUser user = null, ILiveBotGame game = null)
        {
            string RoleMention = "";

            if (subscription.DiscordRole != null)
            {
                if (subscription.DiscordRole.Name == "@everyone")
                {
                    RoleMention = "@everyone";
                }
                else
                {
                    RoleMention = MentionUtils.MentionRole(subscription.DiscordRole.DiscordId);
                }
            }

            var tempUser = user ?? stream.User;
            var tempGame = game ?? stream.Game;

            return(subscription.Message
                   .Replace("{Name}", EscapeSpecialDiscordCharacters(tempUser.DisplayName), ignoreCase: true, culture: CultureInfo.CurrentCulture)
                   .Replace("{Username}", EscapeSpecialDiscordCharacters(tempUser.DisplayName), ignoreCase: true, culture: CultureInfo.CurrentCulture)
                   .Replace("{Game}", EscapeSpecialDiscordCharacters(tempGame.Name), ignoreCase: true, culture: CultureInfo.CurrentCulture)
                   .Replace("{Title}", EscapeSpecialDiscordCharacters(stream.Title), ignoreCase: true, culture: CultureInfo.CurrentCulture)
                   .Replace("{URL}", stream.StreamURL ?? "", ignoreCase: true, culture: CultureInfo.CurrentCulture)
                   .Replace("{Role}", RoleMention, ignoreCase: true, culture: CultureInfo.CurrentCulture)
                   .Trim());
        }
Пример #2
0
        /// <summary>
        /// Generates a Discord Embed for the given <paramref name="stream"/>
        /// </summary>
        /// <param name="stream"></param>
        /// <returns>Discord Embed with Stream Information</returns>
        public static Embed GetStreamEmbed(ILiveBotStream stream, ILiveBotUser user, ILiveBotGame game)
        {
            // Build the Author of the Embed
            EmbedAuthorBuilder authorBuilder = new EmbedAuthorBuilder();

            authorBuilder.WithName(user.DisplayName);
            authorBuilder.WithIconUrl(user.AvatarURL);
            authorBuilder.WithUrl(user.ProfileURL);

            // Build the Footer of the Embed
            EmbedFooterBuilder footerBuilder = new EmbedFooterBuilder();

            footerBuilder.WithText("Stream start time");

            // Add Basic information to EmbedBuilder
            EmbedBuilder builder = new EmbedBuilder();

            builder.WithColor(Color.DarkPurple);

            builder.WithAuthor(authorBuilder);
            builder.WithFooter(footerBuilder);

            builder.WithTimestamp(stream.StartTime);
            builder.WithDescription(stream.Title);
            builder.WithUrl(stream.StreamURL);
            builder.WithThumbnailUrl(user.AvatarURL);

            // Add Status Field
            //EmbedFieldBuilder statusBuilder = new EmbedFieldBuilder();
            //statusBuilder.WithIsInline(false);
            //statusBuilder.WithName("Status");
            //statusBuilder.WithValue("");
            //builder.AddField(statusBuilder);

            // Add Game field
            EmbedFieldBuilder gameBuilder = new EmbedFieldBuilder();

            gameBuilder.WithIsInline(true);
            gameBuilder.WithName("Game");
            gameBuilder.WithValue(game.Name);
            builder.AddField(gameBuilder);

            // Add Stream URL field
            EmbedFieldBuilder streamURLField = new EmbedFieldBuilder();

            streamURLField.WithIsInline(true);
            streamURLField.WithName("Stream");
            streamURLField.WithValue(stream.StreamURL);
            builder.AddField(streamURLField);

            return(builder.Build());
        }
Пример #3
0
        public async Task CheckStream(ILiveBotUser user)
        {
            ILiveBotMonitor monitor = _GetServiceMonitor(user);
            ILiveBotStream  stream  = await monitor.GetStream(user);

            if (stream == null)
            {
                await ReplyAsync($"Doesn't look like the user {user.DisplayName} is live on {user.ServiceType}");

                return;
            }
            Embed streamEmbed = NotificationHelpers.GetStreamEmbed(stream: stream, user: stream.User, game: stream.Game);
            StreamSubscription bogusSubscription = new StreamSubscription()
            {
                Message = Defaults.NotificationMessage
            };
            string notificationMessage = NotificationHelpers.GetNotificationMessage(stream, bogusSubscription);

            await ReplyAsync(message : $"Service: `{stream.ServiceType}`\n{notificationMessage}", embed : streamEmbed);
        }
Пример #4
0
        public async Task Consume(ConsumeContext <IStreamOnline> context)
        {
            ILiveBotStream  stream  = context.Message.Stream;
            ILiveBotMonitor monitor = _monitors.Where(i => i.ServiceType == stream.ServiceType).FirstOrDefault();

            if (monitor == null)
            {
                return;
            }

            ILiveBotUser user = stream.User ?? await monitor.GetUserById(stream.UserId);

            ILiveBotGame game = stream.Game ?? await monitor.GetGame(stream.GameId);

            Expression <Func <StreamGame, bool> > templateGamePredicate = (i => i.ServiceType == stream.ServiceType && i.SourceId == "0");
            var templateGame = await _work.GameRepository.SingleOrDefaultAsync(templateGamePredicate);

            var streamUser = await _work.UserRepository.SingleOrDefaultAsync(i => i.ServiceType == stream.ServiceType && i.SourceID == user.Id);

            var streamSubscriptions = await _work.SubscriptionRepository.FindAsync(i => i.User == streamUser);

            StreamGame streamGame;

            if (game.Id == "0" || string.IsNullOrEmpty(game.Id))
            {
                if (templateGame == null)
                {
                    StreamGame newStreamGame = new StreamGame
                    {
                        ServiceType  = stream.ServiceType,
                        SourceId     = "0",
                        Name         = "[Not Set]",
                        ThumbnailURL = ""
                    };
                    await _work.GameRepository.AddOrUpdateAsync(newStreamGame, templateGamePredicate);

                    templateGame = await _work.GameRepository.SingleOrDefaultAsync(templateGamePredicate);
                }
                streamGame = templateGame;
            }
            else
            {
                StreamGame newStreamGame = new StreamGame
                {
                    ServiceType  = stream.ServiceType,
                    SourceId     = game.Id,
                    Name         = game.Name,
                    ThumbnailURL = game.ThumbnailURL
                };
                await _work.GameRepository.AddOrUpdateAsync(newStreamGame, i => i.ServiceType == stream.ServiceType && i.SourceId == stream.GameId);

                streamGame = await _work.GameRepository.SingleOrDefaultAsync(i => i.ServiceType == stream.ServiceType && i.SourceId == stream.GameId);
            }

            if (streamSubscriptions.Count() == 0)
            {
                return;
            }

            foreach (StreamSubscription streamSubscription in streamSubscriptions)
            {
                if (streamSubscription.DiscordGuild == null || streamSubscription.DiscordChannel == null)
                {
                    await _work.SubscriptionRepository.RemoveAsync(streamSubscription.Id);

                    continue;
                }

                var discordChannel = streamSubscription.DiscordChannel;
                var discordRole    = streamSubscription.DiscordRole;
                var discordGuild   = streamSubscription.DiscordGuild;

                var guild = _client.GetGuild(streamSubscription.DiscordGuild.DiscordId);
                SocketTextChannel channel = (SocketTextChannel)_client.GetChannel(streamSubscription.DiscordChannel.DiscordId);;

                string notificationMessage = NotificationHelpers.GetNotificationMessage(stream: stream, subscription: streamSubscription, user: user, game: game);
                Embed  embed = NotificationHelpers.GetStreamEmbed(stream: stream, user: user, game: game);

                StreamNotification newStreamNotification = new StreamNotification
                {
                    ServiceType = stream.ServiceType,
                    Success     = false,
                    Message     = notificationMessage,

                    User_SourceID    = streamUser.SourceID,
                    User_Username    = streamUser.Username,
                    User_DisplayName = streamUser.DisplayName,
                    User_AvatarURL   = streamUser.AvatarURL,
                    User_ProfileURL  = streamUser.ProfileURL,

                    Stream_SourceID     = stream.Id,
                    Stream_Title        = stream.Title,
                    Stream_StartTime    = stream.StartTime,
                    Stream_ThumbnailURL = stream.ThumbnailURL,
                    Stream_StreamURL    = stream.StreamURL,

                    Game_SourceID     = streamGame?.SourceId,
                    Game_Name         = streamGame?.Name,
                    Game_ThumbnailURL = streamGame?.ThumbnailURL,

                    DiscordGuild_DiscordId = discordGuild.DiscordId,
                    DiscordGuild_Name      = discordGuild.Name,

                    DiscordChannel_DiscordId = discordChannel.DiscordId,
                    DiscordChannel_Name      = discordChannel.Name,

                    DiscordRole_DiscordId = discordRole == null ? 0 : discordRole.DiscordId,
                    DiscordRole_Name      = discordRole?.Name
                };

                Expression <Func <StreamNotification, bool> > notificationPredicate = (i =>
                                                                                       i.User_SourceID == newStreamNotification.User_SourceID &&
                                                                                       i.Stream_SourceID == newStreamNotification.Stream_SourceID &&
                                                                                       i.Stream_StartTime == newStreamNotification.Stream_StartTime &&
                                                                                       i.DiscordGuild_DiscordId == newStreamNotification.DiscordGuild_DiscordId &&
                                                                                       i.DiscordChannel_DiscordId == newStreamNotification.DiscordChannel_DiscordId &&
                                                                                       i.Game_SourceID == newStreamNotification.Game_SourceID
                                                                                       );

                Expression <Func <StreamNotification, bool> > previousNotificationPredicate = (i =>
                                                                                               i.User_SourceID == streamUser.SourceID &&
                                                                                               i.DiscordGuild_DiscordId == discordGuild.DiscordId &&
                                                                                               i.DiscordChannel_DiscordId == discordChannel.DiscordId
                                                                                               );

                var previousNotifications = await _work.NotificationRepository.FindAsync(previousNotificationPredicate);

                previousNotifications = previousNotifications.Where(i =>
                                                                    stream.StartTime.Subtract(i.Stream_StartTime).TotalMinutes <= 60 && // If within an hour of their last start time
                                                                    i.Success == true // Only pull Successful notifications
                                                                    );

                // If there is already 1 or more notifications that were successful in the past hour
                // mark this current one as a success
                if (previousNotifications.Count() > 0)
                {
                    newStreamNotification.Success = true;
                }

                // Do some checks to see if the channel can be found. If not, just mark as a success
                // and move on
                int channelCheckCount = 0;
                while (channel == null && _client.LoginState == LoginState.LoggedIn)
                {
                    if (channelCheckCount >= 12) // Ends up being 10 seconds
                    {
                        string errorMessage = $"Unable to get a Discord Channel for {streamSubscription.DiscordChannel.DiscordId} after {channelCheckCount} attempts";
                        Log.Error(errorMessage);
                        newStreamNotification.Success = true;
                        var streamSubscriptionJSON = JsonConvert.SerializeObject(streamSubscription);
                        newStreamNotification.LogMessage = $"{errorMessage}\n{streamSubscriptionJSON}";
                        break;
                    }
                    channel            = (SocketTextChannel)_client.GetChannel(streamSubscription.DiscordChannel.DiscordId);
                    channelCheckCount += 1;
                    await Task.Delay(TimeSpan.FromSeconds(5)); // Delay check for 5 seconds
                }

                await _work.NotificationRepository.AddOrUpdateAsync(newStreamNotification, notificationPredicate);

                StreamNotification streamNotification = await _work.NotificationRepository.SingleOrDefaultAsync(notificationPredicate);

                // If the current notification was marked as a success, end processing
                if (streamNotification.Success == true)
                {
                    continue;
                }

                try
                {
                    var discordMessage = await channel.SendMessageAsync(text : notificationMessage, embed : embed);

                    streamNotification.DiscordMessage_DiscordId = discordMessage.Id;
                    streamNotification.Success = true;
                    await _work.NotificationRepository.UpdateAsync(streamNotification);
                }
                catch (Exception e)
                {
                    if (e is HttpException)
                    {
                        HttpException discordError = (HttpException)e;
                        // You lack permissions to perform that action
                        if (discordError.DiscordCode == 50013 || discordError.DiscordCode == 50001)
                        {
                            // I'm tired of seeing errors for Missing Permissions
                            continue;
                        }
                    }
                    else
                    {
                        Log.Error($"Error sending notification for {streamNotification.Id} {streamNotification.ServiceType} {streamNotification.User_Username} {streamNotification.DiscordGuild_DiscordId} {streamNotification.DiscordChannel_DiscordId} {streamNotification.DiscordRole_DiscordId} {streamNotification.Message}\n{e}");
                    }
                }
            }
        }
Пример #5
0
        public async Task Consume(ConsumeContext <IStreamUpdate> context)
        {
            ILiveBotStream  stream  = context.Message.Stream;
            ILiveBotMonitor monitor = _monitors.Where(i => i.ServiceType == stream.ServiceType).FirstOrDefault();

            if (monitor == null)
            {
                return;
            }

            ILiveBotUser user = stream.User ?? await monitor.GetUserById(stream.UserId);

            ILiveBotGame game = stream.Game ?? await monitor.GetGame(stream.GameId);

            Expression <Func <StreamGame, bool> > templateGamePredicate = (i => i.ServiceType == stream.ServiceType && i.SourceId == "0");
            var templateGame = await _work.GameRepository.SingleOrDefaultAsync(templateGamePredicate);

            var streamUser = await _work.UserRepository.SingleOrDefaultAsync(i => i.ServiceType == stream.ServiceType && i.SourceID == user.Id);

            var streamSubscriptions = await _work.SubscriptionRepository.FindAsync(i => i.User == streamUser);

            StreamGame streamGame;

            if (game.Id == "0" || string.IsNullOrEmpty(game.Id))
            {
                if (templateGame == null)
                {
                    StreamGame newStreamGame = new StreamGame
                    {
                        ServiceType  = stream.ServiceType,
                        SourceId     = "0",
                        Name         = "[Not Set]",
                        ThumbnailURL = ""
                    };
                    await _work.GameRepository.AddOrUpdateAsync(newStreamGame, templateGamePredicate);

                    templateGame = await _work.GameRepository.SingleOrDefaultAsync(templateGamePredicate);
                }
                streamGame = templateGame;
            }
            else
            {
                StreamGame newStreamGame = new StreamGame
                {
                    ServiceType  = stream.ServiceType,
                    SourceId     = game.Id,
                    Name         = game.Name,
                    ThumbnailURL = game.ThumbnailURL
                };
                await _work.GameRepository.AddOrUpdateAsync(newStreamGame, i => i.ServiceType == stream.ServiceType && i.SourceId == stream.GameId);

                streamGame = await _work.GameRepository.SingleOrDefaultAsync(i => i.ServiceType == stream.ServiceType && i.SourceId == stream.GameId);
            }

            if (streamSubscriptions.Count() == 0)
            {
                return;
            }

            List <StreamSubscription> unsentSubscriptions = new List <StreamSubscription>();

            foreach (StreamSubscription streamSubscription in streamSubscriptions)
            {
                if (streamSubscription.DiscordGuild == null || streamSubscription.DiscordChannel == null)
                {
                    await _work.SubscriptionRepository.RemoveAsync(streamSubscription.Id);

                    continue;
                }

                var discordChannel = streamSubscription.DiscordChannel;
                var discordRole    = streamSubscription.DiscordRole;
                var discordGuild   = streamSubscription.DiscordGuild;

                Expression <Func <StreamNotification, bool> > previousNotificationPredicate = (i =>
                                                                                               i.User_SourceID == streamUser.SourceID &&
                                                                                               i.DiscordGuild_DiscordId == discordGuild.DiscordId &&
                                                                                               i.DiscordChannel_DiscordId == discordChannel.DiscordId &&
                                                                                               i.Stream_StartTime == stream.StartTime &&
                                                                                               i.Stream_SourceID == stream.Id &&
                                                                                               i.Success == true
                                                                                               );

                var previousNotifications = await _work.NotificationRepository.FindAsync(previousNotificationPredicate);

                if (previousNotifications.Count() > 0)
                {
                    continue;
                }

                unsentSubscriptions.Add(streamSubscription);
            }

            if (unsentSubscriptions.Count() > 0)
            {
                await _bus.Publish <IStreamOnline>(new { Stream = stream });
            }
        }