diff --git a/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs b/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs index 92e14b69..f809bc52 100644 --- a/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs @@ -1,348 +1,288 @@ -//using Discord.Commands; -//using NadekoBot.Classes; -//using Newtonsoft.Json.Linq; -//using System; -//using System.Collections.Concurrent; -//using System.Linq; -//using System.Threading.Tasks; -//using Discord; -//using NadekoBot.Services; -//using System.Threading; +using Discord.Commands; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using NadekoBot.Services; +using System.Threading; +using NadekoBot.Services.Database; +using System.Collections.Generic; +using NadekoBot.Services.Database.Models; +using System.Net.Http; +using Discord.WebSocket; +using NadekoBot.Attributes; -//todo DB -//namespace NadekoBot.Modules.Searches -//{ -// public partial class Searches -// { -// [Group] -// public class StreamNotificationCommands -// { -// private readonly Timer checkTimer; -// private ConcurrentDictionary> cachedStatuses = new ConcurrentDictionary>(); -// private bool FirstPass { get; set; } = true; +namespace NadekoBot.Modules.Searches +{ + public partial class Searches + { + [Group] + public class StreamNotificationCommands + { + private Timer checkTimer { get; } + private ConcurrentDictionary> cachedStatuses = new ConcurrentDictionary>(); + private bool FirstPass { get; set; } = true; -// public StreamNotifications(DiscordModule module) -// { -// checkTimer = new Timer(async (state) => -// { -// cachedStatuses.Clear(); -// try -// { -// var streams = SpecificConfigurations.Default.AllConfigs.SelectMany(c => c.ObservingStreams); -// if (!streams.Any()) return; -// foreach (var stream in streams) -// { -// Tuple data; -// try -// { -// data = await GetStreamStatus(stream).ConfigureAwait(false); -// } -// catch -// { -// continue; -// } + public StreamNotificationCommands() + { + checkTimer = new Timer(async (state) => + { + cachedStatuses.Clear(); + try + { + IEnumerable streams; + using (var uow = DbHandler.UnitOfWork()) + { + streams = uow.GuildConfigs.GetAllFollowedStreams(); + } + foreach (var stream in streams) + { + Tuple data; + try + { + data = await GetStreamStatus(stream).ConfigureAwait(false); + } + catch + { + continue; + } -// if (data.Item1 != stream.LastStatus) -// { -// stream.LastStatus = data.Item1; -// if (FirstPass) -// continue; -// var server = NadekoBot.Client.GetServer(stream.ServerId); -// var channel = server?.GetChannel(stream.ChannelId); -// if (channel == null) -// continue; -// var msg = $"`{stream.Username}`'s stream is now " + -// $"**{(data.Item1 ? "ONLINE" : "OFFLINE")}** with " + -// $"**{data.Item2}** viewers."; -// if (stream.LastStatus) -// if (stream.Type == StreamNotificationConfig.StreamType.Hitbox) -// msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】"; -// else if (stream.Type == StreamNotificationConfig.StreamType.Twitch) -// msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】"; -// else if (stream.Type == StreamNotificationConfig.StreamType.Beam) -// msg += $"\n`Here is the Link:`【 http://www.beam.pro/{stream.Username}/ 】"; -// else if (stream.Type == StreamNotificationConfig.StreamType.YoutubeGaming) -// msg += $"\n`Here is the Link:`【 not implemented yet - {stream.Username} 】"; -// await channel.SendMessageAsync(msg).ConfigureAwait(false); -// } -// } -// FirstPass = false; -// } -// catch { } -// }, null, TimeSpan.Zero, TimeSpan.FromSeconds(15)); -// } + if (data.Item1 != stream.LastStatus) + { + stream.LastStatus = data.Item1; + if (FirstPass) + continue; + var server = NadekoBot.Client.GetGuild(stream.GuildId); + var channel = server?.GetTextChannel(stream.ChannelId); + if (channel == null) + continue; + var msg = $"`{stream.Username}`'s stream is now " + + $"**{(data.Item1 ? "ONLINE" : "OFFLINE")}** with " + + $"**{data.Item2}** viewers."; + if (stream.LastStatus) + if (stream.Type == FollowedStream.FollowedStreamType.Hitbox) + msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】"; + else if (stream.Type == FollowedStream.FollowedStreamType.Twitch) + msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】"; + else if (stream.Type == FollowedStream.FollowedStreamType.Beam) + msg += $"\n`Here is the Link:`【 http://www.beam.pro/{stream.Username}/ 】"; + //else if (stream.Type == FollowedStream.FollowedStreamType.YoutubeGaming) + // msg += $"\n`Here is the Link:`【 not implemented yet - {stream.Username} 】"; + await channel.SendMessageAsync(msg).ConfigureAwait(false); + } + } + FirstPass = false; + } + catch { } + }, null, TimeSpan.Zero, TimeSpan.FromSeconds(15)); + } -// public StreamNotifications(ILocalization loc, CommandService cmds, IBotConfiguration config, DiscordSocketClient client) : base(loc, cmds, config, client) -// { -// } + private async Task> GetStreamStatus(FollowedStream stream, bool checkCache = true) + { + bool isLive; + string response; + JObject data; + Tuple result; + switch (stream.Type) + { + case FollowedStream.FollowedStreamType.Hitbox: + var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}"; + if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result)) + return result; + using (var http = new HttpClient()) + { + response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false); + } + data = JObject.Parse(response); + isLive = data["media_is_live"].ToString() == "1"; + result = new Tuple(isLive, data["media_views"].ToString()); + cachedStatuses.TryAdd(hitboxUrl, result); + return result; + case FollowedStream.FollowedStreamType.Twitch: + var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}"; + if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result)) + return result; + using (var http = new HttpClient()) + { + response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false); + } + data = JObject.Parse(response); + isLive = !string.IsNullOrWhiteSpace(data["stream"].ToString()); + result = new Tuple(isLive, isLive ? data["stream"]["viewers"].ToString() : "0"); + cachedStatuses.TryAdd(twitchUrl, result); + return result; + case FollowedStream.FollowedStreamType.Beam: + var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}"; + if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result)) + return result; + using (var http = new HttpClient()) + { + response = await http.GetStringAsync(beamUrl).ConfigureAwait(false); + } + data = JObject.Parse(response); + isLive = data["online"].ToObject() == true; + result = new Tuple(isLive, data["viewersCurrent"].ToString()); + cachedStatuses.TryAdd(beamUrl, result); + return result; + default: + break; + } + return new Tuple(false, "0"); + } -// private async Task> GetStreamStatus(StreamNotificationConfig stream, bool checkCache = true) -// { -// bool isLive; -// string response; -// JObject data; -// Tuple result; -// switch (stream.Type) -// { -// case StreamNotificationConfig.StreamType.Hitbox: -// var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}"; -// if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result)) -// return result; -// response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false); -// data = JObject.Parse(response); -// isLive = data["media_is_live"].ToString() == "1"; -// result = new Tuple(isLive, data["media_views"].ToString()); -// cachedStatuses.TryAdd(hitboxUrl, result); -// return result; -// case StreamNotificationConfig.StreamType.Twitch: -// var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}"; -// if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result)) -// return result; -// response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false); -// data = JObject.Parse(response); -// isLive = !string.IsNullOrWhiteSpace(data["stream"].ToString()); -// result = new Tuple(isLive, isLive ? data["stream"]["viewers"].ToString() : "0"); -// cachedStatuses.TryAdd(twitchUrl, result); -// return result; -// case StreamNotificationConfig.StreamType.Beam: -// var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}"; -// if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result)) -// return result; -// response = await http.GetStringAsync(beamUrl).ConfigureAwait(false); -// data = JObject.Parse(response); -// isLive = data["online"].ToObject() == true; -// result = new Tuple(isLive, data["viewersCurrent"].ToString()); -// cachedStatuses.TryAdd(beamUrl, result); -// return result; -// default: -// break; -// } -// return new Tuple(false, "0"); -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageMessages)] + public async Task Hitbox(IUserMessage msg, [Remainder] string username) => + await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Hitbox) + .ConfigureAwait(false); -// internal override void Init(CommandGroupBuilder cgb) -// { -// cgb.CreateCommand(Module.Prefix + "hitbox") -// .Alias(Module.Prefix + "hb") -// .Description("Notifies this channel when a certain user starts streaming." + -// $" | `{Prefix}hitbox SomeStreamer`") -// .Parameter("username", ParameterType.Unparsed) -// .AddCheck(SimpleCheckers.ManageServer()) -// .Do(TrackStream(StreamNotificationConfig.StreamType.Hitbox)); + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageMessages)] + public async Task Twitch(IUserMessage msg, [Remainder] string username) => + await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Twitch) + .ConfigureAwait(false); -// cgb.CreateCommand(Module.Prefix + "twitch") -// .Alias(Module.Prefix + "tw") -// .Description("Notifies this channel when a certain user starts streaming." + -// $" | `{Prefix}twitch SomeStreamer`") -// .AddCheck(SimpleCheckers.ManageServer()) -// .Parameter("username", ParameterType.Unparsed) -// .Do(TrackStream(StreamNotificationConfig.StreamType.Twitch)); + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.ManageMessages)] + public async Task Beam(IUserMessage msg, [Remainder] string username) => + await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Beam) + .ConfigureAwait(false); -// cgb.CreateCommand(Module.Prefix + "beam") -// .Alias(Module.Prefix + "bm") -// .Description("Notifies this channel when a certain user starts streaming." + -// $" | `{Prefix}beam SomeStreamer`") -// .AddCheck(SimpleCheckers.ManageServer()) -// .Parameter("username", ParameterType.Unparsed) -// .Do(TrackStream(StreamNotificationConfig.StreamType.Beam)); + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task ListStreams(IUserMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; -// cgb.CreateCommand(Module.Prefix + "checkhitbox") -// .Alias(Module.Prefix + "chhb") -// .Description("Checks if a certain user is streaming on the hitbox platform." + -// $" | `{Prefix}chhb SomeStreamer`") -// .Parameter("username", ParameterType.Unparsed) -// .AddCheck(SimpleCheckers.ManageServer()) -// .Do(async e => -// { -// var stream = username?.Trim(); -// if (string.IsNullOrWhiteSpace(stream)) -// return; -// try -// { -// var streamStatus = (await GetStreamStatus(new StreamNotificationConfig -// { -// Username = stream, -// Type = StreamNotificationConfig.StreamType.Hitbox -// })); -// if (streamStatus.Item1) -// { -// await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`"); -// } -// } -// catch -// { -// await channel.SendMessageAsync("No channel found."); -// } -// }); + IEnumerable streams; + using (var uow = DbHandler.UnitOfWork()) + { + streams = uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams; + } -// cgb.CreateCommand(Module.Prefix + "checktwitch") -// .Alias(Module.Prefix + "chtw") -// .Description("Checks if a certain user is streaming on the twitch platform." + -// $" | `{Prefix}chtw SomeStreamer`") -// .AddCheck(SimpleCheckers.ManageServer()) -// .Parameter("username", ParameterType.Unparsed) -// .Do(async e => -// { -// var stream = username?.Trim(); -// if (string.IsNullOrWhiteSpace(stream)) -// return; -// try -// { -// var streamStatus = (await GetStreamStatus(new StreamNotificationConfig -// { -// Username = stream, -// Type = StreamNotificationConfig.StreamType.Twitch -// })); -// if (streamStatus.Item1) -// { -// await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`"); -// } -// } -// catch -// { -// await channel.SendMessageAsync("No channel found."); -// } -// }); + if (!streams.Any()) + { + await channel.SendMessageAsync("You are not following any streams on this server.").ConfigureAwait(false); + return; + } -// cgb.CreateCommand(Module.Prefix + "checkbeam") -// .Alias(Module.Prefix + "chbm") -// .Description("Checks if a certain user is streaming on the beam platform." + -// $" | `{Prefix}chbm SomeStreamer`") -// .AddCheck(SimpleCheckers.ManageServer()) -// .Parameter("username", ParameterType.Unparsed) -// .Do(async e => -// { -// var stream = username?.Trim(); -// if (string.IsNullOrWhiteSpace(stream)) -// return; -// try -// { -// var streamStatus = (await GetStreamStatus(new StreamNotificationConfig -// { -// Username = stream, -// Type = StreamNotificationConfig.StreamType.Beam -// })); -// if (streamStatus.Item1) -// { -// await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`"); -// } -// } -// catch -// { -// await channel.SendMessageAsync("No channel found."); -// } -// }); + var text = string.Join("\n", streams.Select(snc => + { + return $"`{snc.Username}`'s stream on **{channel.Guild.GetTextChannel(snc.ChannelId)?.Name}** channel. 【`{snc.Type.ToString()}`】"; + })); -// cgb.CreateCommand(Module.Prefix + "removestream") -// .Alias(Module.Prefix + "rms") -// .Description("Removes notifications of a certain streamer on this channel." + -// $" | `{Prefix}rms SomeGuy`") -// .AddCheck(SimpleCheckers.ManageServer()) -// .Parameter("username", ParameterType.Unparsed) -// .Do(async e => -// { -// var username = username?.ToLower().Trim(); -// if (string.IsNullOrWhiteSpace(username)) -// return; + await channel.SendMessageAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false); + } -// var config = SpecificConfigurations.Default.Of(e.Server.Id); + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task RemoveStream(IUserMessage msg, [Remainder] string username) + { + var channel = (ITextChannel)msg.Channel; -// var toRemove = config.ObservingStreams -// .FirstOrDefault(snc => snc.ChannelId == e.Channel.Id && -// snc.Username.ToLower().Trim() == username); -// if (toRemove == null) -// { -// await channel.SendMessageAsync(":anger: No such stream.").ConfigureAwait(false); -// return; -// } + username = username.ToUpperInvariant().Trim(); -// config.ObservingStreams.Remove(toRemove); -// await ConfigHandler.SaveConfig().ConfigureAwait(false); -// await channel.SendMessageAsync($":ok: Removed `{toRemovumsg.Authorname}`'s stream from notifications.").ConfigureAwait(false); -// }); + FollowedStream toRemove; + using (var uow = DbHandler.UnitOfWork()) + { + var config = uow.GuildConfigs.For(channel.Guild.Id); + var streams = config.FollowedStreams; + toRemove = streams.Where(fs => fs.ChannelId == channel.Id && fs.Username.ToUpperInvariant() == username).FirstOrDefault(); + if (toRemove != null) + { + config.FollowedStreams = streams.Except(new[] { toRemove }).ToList(); + await uow.CompleteAsync(); + } + } + if (toRemove == null) + { + await channel.SendMessageAsync(":anger: No such stream.").ConfigureAwait(false); + return; + } + await channel.SendMessageAsync($":ok: Removed `{toRemove.Username}`'s stream ({toRemove.Type}) from notifications.").ConfigureAwait(false); + } -// cgb.CreateCommand(Module.Prefix + "liststreams") -// .Alias(Module.Prefix + "ls") -// .Description("Lists all streams you are following on this server." + -// $" | `{Prefix}ls`") -// .Do(async e => -// { + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task CheckStream(IUserMessage imsg, FollowedStream.FollowedStreamType platform, [Remainder] string username) + { + var channel = (ITextChannel)imsg.Channel; -// var config = SpecificConfigurations.Default.Of(e.Server.Id); + var stream = username?.Trim(); + if (string.IsNullOrWhiteSpace(stream)) + return; + try + { + var streamStatus = (await GetStreamStatus(new FollowedStream + { + Username = stream, + Type = platform + })); + if (streamStatus.Item1) + { + await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`"); + } + } + catch + { + await channel.SendMessageAsync("No channel found."); + } + } -// var streams = config.ObservingStreams.Where(snc => -// snc.ServerId == e.Server.Id); - -// var streamsArray = streams as StreamNotificationConfig[] ?? streams.ToArray(); - -// if (streamsArray.Length == 0) -// { -// await channel.SendMessageAsync("You are not following any streams on this server.").ConfigureAwait(false); -// return; -// } - -// var text = string.Join("\n", streamsArray.Select(snc => -// { -// try -// { -// return $"`{snc.Username}`'s stream on **{e.Server.GetChannel(e.Channel.Id).Name}** channel. 【`{snc.Type.ToString()}`】"; -// } -// catch { } -// return ""; -// })); - -// await channel.SendMessageAsync($"You are following **{streamsArray.Length}** streams on this server.\n\n" + text).ConfigureAwait(false); -// }); -// } - -// private Func TrackStream(StreamNotificationConfig.StreamType type) => -// async e => -// { -// var username = username?.ToLowerInvariant(); -// if (string.IsNullOrWhiteSpace(username)) -// return; - -// var config = SpecificConfigurations.Default.Of(e.Server.Id); - -// var stream = new StreamNotificationConfig -// { -// ServerId = e.Server.Id, -// ChannelId = e.Channel.Id, -// Username = username, -// Type = type, -// }; -// var exists = config.ObservingStreams.Contains(stream); -// if (exists) -// { -// await channel.SendMessageAsync(":anger: I am already notifying that stream on this channel.").ConfigureAwait(false); -// return; -// } -// Tuple data; -// try -// { -// data = await GetStreamStatus(stream).ConfigureAwait(false); -// } -// catch -// { -// await channel.SendMessageAsync(":anger: Stream probably doesn't exist.").ConfigureAwait(false); -// return; -// } -// var msg = $"Stream is currently **{(data.Item1 ? "ONLINE" : "OFFLINE")}** with **{data.Item2}** viewers"; -// if (data.Item1) -// if (type == StreamNotificationConfig.StreamType.Hitbox) -// msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】"; -// else if (type == StreamNotificationConfig.StreamType.Twitch) -// msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】"; -// else if (type == StreamNotificationConfig.StreamType.Beam) -// msg += $"\n`Here is the Link:`【 https://beam.pro/{stream.Username}/ 】"; -// else if (type == StreamNotificationConfig.StreamType.YoutubeGaming) -// msg += $"\n`Here is the Link:` not implemented yet - {stream.Username}"; -// stream.LastStatus = data.Item1; -// if (!exists) -// msg = $":ok: I will notify this channel when status changes.\n{msg}"; -// await channel.SendMessageAsync(msg).ConfigureAwait(false); -// config.ObservingStreams.Add(stream); -// }; -// } -// } -//} \ No newline at end of file + private async Task TrackStream(ITextChannel channel, string username, FollowedStream.FollowedStreamType type) + { + username = username.ToUpperInvariant().Trim(); + var stream = new FollowedStream + { + GuildId = channel.Guild.Id, + ChannelId = channel.Id, + Username = username, + Type = type, + }; + bool exists; + using (var uow = DbHandler.UnitOfWork()) + { + exists = uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams.Where(fs => fs.ChannelId == channel.Id && fs.Username.ToUpperInvariant().Trim() == username).Any(); + } + if (exists) + { + await channel.SendMessageAsync($":anger: I am already following `{username}` ({type}) stream on this channel.").ConfigureAwait(false); + return; + } + Tuple data; + try + { + data = await GetStreamStatus(stream).ConfigureAwait(false); + } + catch + { + await channel.SendMessageAsync(":anger: Stream probably doesn't exist.").ConfigureAwait(false); + return; + } + var msg = $"Stream is currently **{(data.Item1 ? "ONLINE" : "OFFLINE")}** with **{data.Item2}** viewers"; + if (data.Item1) + if (type == FollowedStream.FollowedStreamType.Hitbox) + msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】"; + else if (type == FollowedStream.FollowedStreamType.Twitch) + msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】"; + else if (type == FollowedStream.FollowedStreamType.Beam) + msg += $"\n`Here is the Link:`【 https://beam.pro/{stream.Username}/ 】"; + //else if (type == FollowedStream.FollowedStreamType.YoutubeGaming) + // msg += $"\n`Here is the Link:` not implemented yet - {stream.Username}"; + stream.LastStatus = data.Item1; + using (var uow = DbHandler.UnitOfWork()) + { + uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams.Add(stream); + await uow.CompleteAsync(); + } + msg = $":ok: I will notify this channel when status changes.\n{msg}"; + await channel.SendMessageAsync(msg).ConfigureAwait(false); + } + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/Database/Models/FollowedStream.cs b/src/NadekoBot/Services/Database/Models/FollowedStream.cs new file mode 100644 index 00000000..8bab223e --- /dev/null +++ b/src/NadekoBot/Services/Database/Models/FollowedStream.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Database.Models +{ + public class FollowedStream : DbEntity + { + public ulong ChannelId { get; set; } + public string Username { get; set; } + public FollowedStreamType Type { get; set; } + public bool LastStatus { get; set; } + public ulong GuildId { get; set; } + + public enum FollowedStreamType + { + Twitch, Hitbox, Beam + } + } +} diff --git a/src/NadekoBot/Services/Database/Models/GuildConfig.cs b/src/NadekoBot/Services/Database/Models/GuildConfig.cs index 470d2396..62d2ead8 100644 --- a/src/NadekoBot/Services/Database/Models/GuildConfig.cs +++ b/src/NadekoBot/Services/Database/Models/GuildConfig.cs @@ -33,5 +33,9 @@ namespace NadekoBot.Services.Database.Models public bool AutoDeleteSelfAssignedRoleMessages { get; set; } public float DefaultMusicVolume { get; set; } = 1.0f; public bool VoicePlusTextEnabled { get; set; } + + + //stream notifications + public List FollowedStreams { get; set; } = new List(); } } diff --git a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs index 70e602f7..82767a80 100644 --- a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs @@ -11,5 +11,6 @@ namespace NadekoBot.Services.Database.Repositories public interface IGuildConfigRepository : IRepository { GuildConfig For(ulong guildId); + IEnumerable GetAllFollowedStreams(); } } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs index 13f05404..2bca9cbd 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs @@ -20,7 +20,8 @@ namespace NadekoBot.Services.Database.Repositories.Impl /// public GuildConfig For(ulong guildId) { - var config = _set.FirstOrDefault(c => c.GuildId == guildId); + var config = _set.Include(gc=>gc.FollowedStreams) + .FirstOrDefault(c => c.GuildId == guildId); if (config == null) { @@ -32,5 +33,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl } return config; } + + public IEnumerable GetAllFollowedStreams() => + _set.Include(gc => gc.FollowedStreams) + .SelectMany(gc => gc.FollowedStreams) + .ToList(); } }