public async Task GetMonitorService(string serviceName) { ServiceEnum serviceEnum = (ServiceEnum)Enum.Parse(typeof(ServiceEnum), serviceName.ToUpper()); ILiveBotMonitor monitor = _monitors.Where(m => m.ServiceType == serviceEnum).First(); await ReplyAsync($"Loaded: {monitor.ServiceType}"); }
public async Task <RuntimeResult> MonitorStop_RequestURL() { string profileURL = await _RequestStreamUser(); if (profileURL == null) { return(MonitorResult.FromError($"{Context.Message.Author.Mention}, Please provide a valid Stream URL for me to stop monitoring")); } ILiveBotMonitor monitor = _GetServiceMonitor(profileURL); ILiveBotUser user = await monitor.GetUser(profileURL : profileURL); return(await MonitorStop(user)); }
public async Task <RuntimeResult> MonitorStop(ILiveBotUser user) { ILiveBotMonitor monitor = _GetServiceMonitor(user); DiscordGuild discordGuild = new DiscordGuild { DiscordId = Context.Guild.Id, Name = Context.Guild.Name, IconUrl = Context.Guild.IconUrl }; await _work.GuildRepository.AddOrUpdateAsync(discordGuild, g => g.DiscordId == Context.Guild.Id); discordGuild = await _work.GuildRepository.SingleOrDefaultAsync(g => g.DiscordId == Context.Guild.Id); StreamUser streamUser = new StreamUser() { ServiceType = user.ServiceType, SourceID = user.Id, Username = user.Username, DisplayName = user.DisplayName, AvatarURL = user.AvatarURL, ProfileURL = user.ProfileURL }; await _work.UserRepository.AddOrUpdateAsync(streamUser, (i => i.ServiceType == user.ServiceType && i.SourceID == user.Id)); streamUser = await _work.UserRepository.SingleOrDefaultAsync(i => i.ServiceType == user.ServiceType && i.SourceID == user.Id); Expression <Func <StreamSubscription, bool> > streamSubscriptionPredicate = (i => i.User == streamUser && i.DiscordGuild == discordGuild ); IEnumerable <StreamSubscription> streamSubscriptions = await _work.SubscriptionRepository.FindAsync(streamSubscriptionPredicate); try { foreach (StreamSubscription streamSubscription in streamSubscriptions) { await _work.SubscriptionRepository.RemoveAsync(streamSubscription.Id); } await ReplyAsync($"{Context.Message.Author.Mention}, I have removed the Subscription for {user.DisplayName}"); return(MonitorResult.FromSuccess()); } catch (Exception e) { Log.Error($"Error running MonitorStop for {Context.Message.Author.Id} {Context.Message.Author.Username}#{Context.Message.Author.Discriminator} GuildID: {Context.Guild.Id} ChannelID: {Context.Channel.Id}\n{e}"); return(MonitorResult.FromSuccess($"{Context.Message.Author.Mention}, I couldn't remove the Subscription for user {user.DisplayName}. Please try again or contact my owner")); } }
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); }
/// <inheritdoc/> public override async Task <TypeReaderResult> ReadAsync(ICommandContext Context, string Input, IServiceProvider Services) { ILiveBotUser liveBotUser; Input = Input.Trim(); const string URLPattern = "^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\'\\/\\\\\\+&%\\$#_]*)?$"; Regex URLRegex = new Regex(URLPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); // Check if Valid URL if (Regex.IsMatch(Input, URLPattern)) { Match URLMatch = URLRegex.Match(Input); IEnumerable <ILiveBotMonitor> monitors = Services.GetServices <ILiveBotMonitor>(); ILiveBotMonitor monitor = monitors.Where(m => m.IsValid(URLMatch.Groups[0].ToString())).FirstOrDefault(); if (monitor == null) { return(TypeReaderResult.FromError(CommandError.Unsuccessful, $"{Context.Message.Author.Mention}, I couldn't process the link you provided. Please check the link and try again.")); } liveBotUser = await monitor.GetUser(profileURL : Input); } else { return(TypeReaderResult.FromError(CommandError.ParseFailed, $"{Context.Message.Author.Mention}, you must provide a valid link to the stream you want to monitor.")); } if (liveBotUser == null) { return(TypeReaderResult.FromError(CommandError.ParseFailed, $"{Context.Message.Author.Mention}, I couldn't determine what type of stream that was.")); } return(TypeReaderResult.FromSuccess(liveBotUser)); }
public async Task <RuntimeResult> MonitorStart(ILiveBotUser user) { ILiveBotMonitor monitor = _GetServiceMonitor(user); DiscordGuild discordGuild = new DiscordGuild { DiscordId = Context.Guild.Id, Name = Context.Guild.Name, IconUrl = Context.Guild.IconUrl }; await _work.GuildRepository.AddOrUpdateAsync(discordGuild, g => g.DiscordId == Context.Guild.Id); discordGuild = await _work.GuildRepository.SingleOrDefaultAsync(g => g.DiscordId == Context.Guild.Id); // Get Notification Channel DiscordChannel discordChannel = await _RequestNotificationChannel(discordGuild); if (discordChannel == null) { return(MonitorResult.FromError($"{Context.Message.Author.Mention}, Please re-run the command and be sure to mention a channel.")); } // Get Notification Message string notificationMessage = await _RequestNotificationMessage(); if (notificationMessage == null) { return(MonitorResult.FromError($"{Context.Message.Author.Mention}, Please re-run the command and provide a valid message for notifications")); } // Get Notification Role DiscordRole discordRole = await _RequestNotificationRole(discordGuild); // Process their answers StreamUser streamUser = new StreamUser() { ServiceType = user.ServiceType, SourceID = user.Id, Username = user.Username, DisplayName = user.DisplayName, AvatarURL = user.AvatarURL, ProfileURL = user.ProfileURL }; await _work.UserRepository.AddOrUpdateAsync(streamUser, (i => i.ServiceType == user.ServiceType && i.SourceID == user.Id)); streamUser = await _work.UserRepository.SingleOrDefaultAsync(i => i.ServiceType == user.ServiceType && i.SourceID == user.Id); Expression <Func <StreamSubscription, bool> > streamSubscriptionPredicate = (i => i.User == streamUser && i.DiscordGuild == discordGuild ); StreamSubscription newSubscription = new StreamSubscription() { User = streamUser, DiscordGuild = discordGuild, DiscordChannel = discordChannel, DiscordRole = discordRole, Message = notificationMessage }; try { StreamSubscription existingSubscription = await _work.SubscriptionRepository.SingleOrDefaultAsync(streamSubscriptionPredicate); if (existingSubscription != null) { existingSubscription.DiscordGuild = newSubscription.DiscordGuild; existingSubscription.DiscordChannel = newSubscription.DiscordChannel; existingSubscription.DiscordRole = newSubscription.DiscordRole; existingSubscription.Message = newSubscription.Message; await _work.SubscriptionRepository.UpdateAsync(existingSubscription); } else { await _work.SubscriptionRepository.AddOrUpdateAsync(newSubscription, streamSubscriptionPredicate); } StreamSubscription streamSubscription = await _work.SubscriptionRepository.SingleOrDefaultAsync(streamSubscriptionPredicate); monitor.AddChannel(user); string escapedMessage = NotificationHelpers.EscapeSpecialDiscordCharacters(streamSubscription.Message); await ReplyAsync($"{Context.Message.Author.Mention}, I have setup a subscription for {user.DisplayName} on {user.ServiceType} with message {escapedMessage}"); return(MonitorResult.FromSuccess()); } catch (Exception e) { Log.Error($"Error running MonitorStart for {Context.Message.Author.Id} {Context.Message.Author.Username}#{Context.Message.Author.Discriminator} GuildID: {Context.Guild.Id} ChannelID: {Context.Channel.Id}\n{e}"); return(MonitorResult.FromError($"{Context.Message.Author.Mention}, I wasn't able to create a subscription for the user {user.DisplayName} on {user.ServiceType}. Please try again or contact my owner")); } }
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}"); } } } }
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 }); } }