merged dev
This commit is contained in:
		| @@ -12,6 +12,9 @@ using Discord.WebSocket; | ||||
| using NadekoBot.Services; | ||||
| using NadekoBot.Services.Database.Models; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System.Collections.Immutable; | ||||
| using NadekoBot.DataStructures; | ||||
| using NLog; | ||||
|  | ||||
| namespace NadekoBot.Modules.Administration | ||||
| { | ||||
| @@ -25,8 +28,11 @@ namespace NadekoBot.Modules.Administration | ||||
|  | ||||
|             private static readonly object _locker = new object(); | ||||
|  | ||||
|             private new static readonly Logger _log; | ||||
|  | ||||
|             static SelfCommands() | ||||
|             { | ||||
|                 _log = LogManager.GetCurrentClassLogger(); | ||||
|                 using (var uow = DbHandler.UnitOfWork()) | ||||
|                 { | ||||
|                     var config = uow.BotConfig.GetOrCreate(); | ||||
| @@ -36,7 +42,7 @@ namespace NadekoBot.Modules.Administration | ||||
|  | ||||
|                 var _ = Task.Run(async () => | ||||
|                 { | ||||
|                     while(!NadekoBot.Ready) | ||||
|                     while (!NadekoBot.Ready) | ||||
|                         await Task.Delay(1000); | ||||
|  | ||||
|                     foreach (var cmd in NadekoBot.BotConfig.StartupCommands) | ||||
| @@ -113,7 +119,7 @@ namespace NadekoBot.Modules.Administration | ||||
| {Format.Code(GetText("channel"))}: {x.ChannelName}/{x.ChannelId} | ||||
| {Format.Code(GetText("command_text"))}: {x.CommandText}"; | ||||
|                         return str; | ||||
|                     })),footer: GetText("page", page + 1)) | ||||
|                     })), footer: GetText("page", page + 1)) | ||||
|                          .ConfigureAwait(false); | ||||
|                 } | ||||
|             } | ||||
| @@ -123,7 +129,7 @@ namespace NadekoBot.Modules.Administration | ||||
|             public async Task Wait(int miliseconds) | ||||
|             { | ||||
|                 if (miliseconds <= 0) | ||||
|                     return;                 | ||||
|                     return; | ||||
|                 Context.Message.DeleteAfter(0); | ||||
|                 try | ||||
|                 { | ||||
| @@ -157,7 +163,7 @@ namespace NadekoBot.Modules.Administration | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if(cmd == null) | ||||
|                 if (cmd == null) | ||||
|                     await ReplyErrorLocalized("scrm_fail").ConfigureAwait(false); | ||||
|                 else | ||||
|                     await ReplyConfirmLocalized("scrm").ConfigureAwait(false); | ||||
| @@ -215,9 +221,9 @@ namespace NadekoBot.Modules.Administration | ||||
|  | ||||
|             } | ||||
|  | ||||
|             public static async Task HandleDmForwarding(IUserMessage msg, List<IDMChannel> ownerChannels) | ||||
|             public static async Task HandleDmForwarding(IUserMessage msg, ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels) | ||||
|             { | ||||
|                 if (_forwardDMs && ownerChannels.Any()) | ||||
|                 if (_forwardDMs && ownerChannels.Length > 0) | ||||
|                 { | ||||
|                     var title = GetTextStatic("dm_from", | ||||
|                                     NadekoBot.Localization.DefaultCultureInfo, | ||||
| @@ -238,26 +244,39 @@ namespace NadekoBot.Modules.Administration | ||||
|  | ||||
|                     if (_forwardDMsToAllOwners) | ||||
|                     { | ||||
|                         await Task.WhenAll(ownerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id) | ||||
|                             .Select(ch => ch.SendConfirmAsync(title, toSend))).ConfigureAwait(false); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         var firstOwnerChannel = ownerChannels.First(); | ||||
|                         if (firstOwnerChannel.Recipient.Id != msg.Author.Id) | ||||
|                         var allOwnerChannels = await Task.WhenAll(ownerChannels | ||||
|                             .Select(x => x.Value)) | ||||
|                             .ConfigureAwait(false); | ||||
|  | ||||
|                         foreach (var ownerCh in allOwnerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id)) | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 await firstOwnerChannel.SendConfirmAsync(title, toSend).ConfigureAwait(false); | ||||
|                                 await ownerCh.SendConfirmAsync(title, toSend).ConfigureAwait(false); | ||||
|                             } | ||||
|                             catch | ||||
|                             { | ||||
|                                 // ignored | ||||
|                                 _log.Warn("Can't contact owner with id {0}", ownerCh.Recipient.Id); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                             var firstOwnerChannel = await ownerChannels[0]; | ||||
|                             if (firstOwnerChannel.Recipient.Id != msg.Author.Id) | ||||
|                             { | ||||
|                                 try | ||||
|                                 { | ||||
|                                     await firstOwnerChannel.SendConfirmAsync(title, toSend).ConfigureAwait(false); | ||||
|                                 } | ||||
|                                 catch | ||||
|                                 { | ||||
|                                     // ignored | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|             [NadekoCommand, Usage, Description, Aliases] | ||||
|   | ||||
| @@ -36,10 +36,7 @@ namespace NadekoBot.Modules.Games | ||||
|  | ||||
|             static PlantPickCommands() | ||||
|             { | ||||
|  | ||||
| #if !GLOBAL_NADEKO | ||||
|                 NadekoBot.Client.MessageReceived += PotentialFlowerGeneration; | ||||
| #endif | ||||
|                 generationChannels = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs | ||||
|                     .SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId))); | ||||
|             } | ||||
|   | ||||
| @@ -8,59 +8,55 @@ namespace NadekoBot.Modules.Searches.Models | ||||
|     { | ||||
|         public OverwatchPlayer Player { get; set; } | ||||
|  | ||||
|         public class OverwatchResponse | ||||
|         { | ||||
|             public object _request; | ||||
|             public OverwatchPlayer Eu { get; set; } | ||||
|             public OverwatchPlayer Kr { get; set; } | ||||
|             public OverwatchPlayer Us { get; set; } | ||||
|         } | ||||
|         public class OverwatchPlayer | ||||
|         { | ||||
|             public Data data { get; set; } | ||||
|             public class Data | ||||
|             { | ||||
|                 public bool Missing { get; set; } = false; | ||||
|                 public string username { get; set; } | ||||
|                 public int level { get; set; } | ||||
|                 public string avatar { get; set; } | ||||
|                 public string levelFrame { get; set; } | ||||
|                 public string star { get; set; } | ||||
|                 [JsonProperty("games")] | ||||
|                 public OverwatchGames Games { get; set; } | ||||
|                 [JsonProperty("playtime")] | ||||
|                 public OverwatchPlaytime Playtime { get; set; } | ||||
|                 [JsonProperty("competitive")] | ||||
|                 public OverwatchCompetitive Competitive { get; set; } | ||||
|                 public class OverwatchGames | ||||
|                 { | ||||
|                     [JsonProperty("quick")] | ||||
|                     public OverwatchQG Quick { get; set; } | ||||
|                     [JsonProperty("competitive")] | ||||
|                     public OverwatchCOMP Competitive { get; set; } | ||||
|  | ||||
|                     public class OverwatchQG | ||||
|                     { | ||||
|                         public string wins { get; set; } | ||||
|                     } | ||||
|                     public class OverwatchCOMP | ||||
|                     { | ||||
|                         public string wins { get; set; } | ||||
|                         public int lost { get; set; } | ||||
|                         public string played { get; set; } | ||||
|                     } | ||||
|                 } | ||||
|                 public class OverwatchCompetitive | ||||
|                 { | ||||
|                     public string rank { get; set; } | ||||
|                     public string rank_img { get; set; } | ||||
|                 } | ||||
|                 public class OverwatchPlaytime | ||||
|                 { | ||||
|                     public string quick { get; set; } | ||||
|                     public string competitive { get; set; } | ||||
|                 } | ||||
|             } | ||||
|             public StatsField Stats { get; set; } | ||||
|         } | ||||
|         //This is to strip the html from patch notes content | ||||
|         internal static string StripHTML(string input) | ||||
|  | ||||
|         public class StatsField | ||||
|         { | ||||
|             var re = Regex.Replace(input, "<.*?>", String.Empty); | ||||
|             re = Regex.Replace(re, " ", $@" "); | ||||
|             return re; | ||||
|             public Stats Quickplay { get; set; } | ||||
|             public Stats Competitive { get; set; } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public class Stats | ||||
|         { | ||||
|             [JsonProperty("overall_stats")] | ||||
|             public OverallStats OverallStats { get; set; } | ||||
|             [JsonProperty("game_stats")] | ||||
|             public GameStats GameStats { get; set; } | ||||
|         } | ||||
|  | ||||
|         public class OverallStats | ||||
|         { | ||||
|             public int? comprank; | ||||
|             public int level; | ||||
|             public int prestige; | ||||
|             public string avatar; | ||||
|             public int wins; | ||||
|             public int losses; | ||||
|             public int games; | ||||
|             public string rank_image; | ||||
|         } | ||||
|  | ||||
|         public class GameStats | ||||
|         { | ||||
|             [JsonProperty("time_played")] | ||||
|             public float timePlayed; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public class Competitive | ||||
|         { | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -15,61 +15,67 @@ namespace NadekoBot.Modules.Searches | ||||
|         [Group] | ||||
|         public class OverwatchCommands : NadekoSubmodule | ||||
|         { | ||||
|             public enum Region | ||||
|             { | ||||
|                 Eu, | ||||
|                 Us, | ||||
|                 Kr | ||||
|             } | ||||
|  | ||||
|             [NadekoCommand, Usage, Description, Aliases] | ||||
|             public async Task Overwatch(string region, [Remainder] string query = null) | ||||
|             public async Task Overwatch(Region region, [Remainder] string query = null) | ||||
|             { | ||||
|                 if (string.IsNullOrWhiteSpace(query)) | ||||
|                     return; | ||||
|                 var battletag = query.Replace("#", "-"); | ||||
|  | ||||
|                 await Context.Channel.TriggerTypingAsync().ConfigureAwait(false); | ||||
|                 try | ||||
|                 var model = (await GetProfile(region, battletag))?.Stats; | ||||
|  | ||||
|                 if (model != null) | ||||
|                 { | ||||
|                     await Context.Channel.TriggerTypingAsync().ConfigureAwait(false); | ||||
|                     var model = await GetProfile(region, battletag); | ||||
|  | ||||
|                     var rankimg = model.Competitive.rank_img; | ||||
|                     var rank = model.Competitive.rank; | ||||
|  | ||||
|                     if (string.IsNullOrWhiteSpace(rank)) | ||||
|                     if (model.Competitive == null) | ||||
|                     { | ||||
|                         var qp = model.Quickplay; | ||||
|                         var embed = new EmbedBuilder() | ||||
|                             .WithAuthor(eau => eau.WithName($"{model.username}") | ||||
|                             .WithAuthor(eau => eau.WithName(query) | ||||
|                             .WithUrl($"https://www.overbuff.com/players/pc/{battletag}") | ||||
|                             .WithIconUrl($"{model.avatar}")) | ||||
|                             .WithThumbnailUrl("https://cdn.discordapp.com/attachments/155726317222887425/255653487512256512/YZ4w2ey.png") | ||||
|                             .AddField(fb => fb.WithName(GetText("level")).WithValue($"{model.level}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_wins")).WithValue($"{model.Games.Quick.wins}").WithIsInline(true)) | ||||
|                             .WithIconUrl("https://cdn.discordapp.com/attachments/155726317222887425/255653487512256512/YZ4w2ey.png")) | ||||
|                             .WithThumbnailUrl(qp.OverallStats.avatar) | ||||
|                             .AddField(fb => fb.WithName(GetText("level")).WithValue((qp.OverallStats.level + (qp.OverallStats.prestige * 100)).ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_wins")).WithValue(qp.OverallStats.wins.ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_rank")).WithValue("0").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_playtime")).WithValue($"{model.Playtime.quick}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_playtime")).WithValue($"{qp.GameStats.timePlayed}hrs").WithIsInline(true)) | ||||
|                             .WithOkColor(); | ||||
|                         await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         var qp = model.Quickplay; | ||||
|                         var compet = model.Competitive; | ||||
|                         var embed = new EmbedBuilder() | ||||
|                             .WithAuthor(eau => eau.WithName($"{model.username}") | ||||
|                             .WithUrl($"https://www.overbuff.com/players/pc/{battletag}") | ||||
|                             .WithIconUrl($"{model.avatar}")) | ||||
|                             .WithThumbnailUrl(rankimg) | ||||
|                             .AddField(fb => fb.WithName(GetText("level")).WithValue($"{model.level}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_wins")).WithValue($"{model.Games.Quick.wins}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_wins")).WithValue($"{model.Games.Competitive.wins}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_loses")).WithValue($"{model.Games.Competitive.lost}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_played")).WithValue($"{model.Games.Competitive.played}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_rank")).WithValue(rank).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_playtime")).WithValue($"{model.Playtime.competitive}").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_playtime")).WithValue($"{model.Playtime.quick}").WithIsInline(true)) | ||||
|                             .WithAuthor(eau => eau.WithName(query) | ||||
|                                 .WithUrl($"https://www.overbuff.com/players/pc/{battletag}") | ||||
|                                 .WithIconUrl(compet.OverallStats.rank_image)) | ||||
|                             .WithThumbnailUrl(compet.OverallStats.avatar) | ||||
|                             .AddField(fb => fb.WithName(GetText("level")).WithValue((qp.OverallStats.level + (qp.OverallStats.prestige * 100)).ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_wins")).WithValue(qp.OverallStats.wins.ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_wins")).WithValue(compet.OverallStats.wins.ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_loses")).WithValue(compet.OverallStats.losses.ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_played")).WithValue(compet.OverallStats.games.ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_rank")).WithValue(compet.OverallStats.comprank.ToString()).WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("compet_playtime")).WithValue(compet.GameStats.timePlayed + "hrs").WithIsInline(true)) | ||||
|                             .AddField(fb => fb.WithName(GetText("quick_playtime")).WithValue(qp.GameStats.timePlayed.ToString("F1") + "hrs").WithIsInline(true)) | ||||
|                             .WithColor(NadekoBot.OkColor); | ||||
|                         await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); | ||||
|                     } | ||||
|                 } | ||||
|                 catch | ||||
|                 else | ||||
|                 { | ||||
|                     await ReplyErrorLocalized("ow_user_not_found").ConfigureAwait(false); | ||||
|                 } | ||||
|             } | ||||
|             public async Task<OverwatchApiModel.OverwatchPlayer.Data> GetProfile(string region, string battletag) | ||||
|             public async Task<OverwatchApiModel.OverwatchPlayer> GetProfile(Region region, string battletag) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
| @@ -78,11 +84,20 @@ namespace NadekoBot.Modules.Searches | ||||
|                         handler.ServerCertificateCustomValidationCallback = (x, y, z, e) => true; | ||||
|                         using (var http = new HttpClient(handler)) | ||||
|                         { | ||||
|                             var url = | ||||
|                                 await http.GetStringAsync( | ||||
|                                     $"https://api.lootbox.eu/pc/{region.ToLower()}/{battletag}/profile"); | ||||
|                             var model = JsonConvert.DeserializeObject<OverwatchApiModel.OverwatchPlayer>(url); | ||||
|                             return model.data; | ||||
|                             http.AddFakeHeaders(); | ||||
|                             var url = $"https://owapi.nadekobot.me/api/v3/u/{battletag}/stats"; | ||||
|                             System.Console.WriteLine(url); | ||||
|                             var res = await http.GetStringAsync($"https://owapi.nadekobot.me/api/v3/u/{battletag}/stats"); | ||||
|                             var model = JsonConvert.DeserializeObject<OverwatchApiModel.OverwatchResponse>(res); | ||||
|                             switch (region) | ||||
|                             { | ||||
|                                 case Region.Eu: | ||||
|                                     return model.Eu; | ||||
|                                 case Region.Kr: | ||||
|                                     return model.Kr; | ||||
|                                 default: | ||||
|                                     return model.Us; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
| @@ -17,6 +17,8 @@ using NadekoBot.Modules.Games; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Threading; | ||||
| using NadekoBot.DataStructures; | ||||
| using System.Diagnostics; | ||||
| using System.Collections.Immutable; | ||||
|  | ||||
| namespace NadekoBot.Services | ||||
| { | ||||
| @@ -34,7 +36,7 @@ namespace NadekoBot.Services | ||||
|         private readonly CommandService _commandService; | ||||
|         private readonly Logger _log; | ||||
|  | ||||
|         private List<IDMChannel> OwnerChannels { get; set; } = new List<IDMChannel>(); | ||||
|         private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels { get; set; } = new ImmutableArray<AsyncLazy<IDMChannel>>(); | ||||
|  | ||||
|         public event Func<IUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; }; | ||||
|  | ||||
| @@ -84,28 +86,15 @@ namespace NadekoBot.Services | ||||
|             var _ = Task.Run(async () => | ||||
|             { | ||||
|                 await Task.Delay(5000).ConfigureAwait(false); | ||||
|                 OwnerChannels = (await Task.WhenAll(_client.Guilds.SelectMany(g => g.Users) | ||||
|                         .Where(u => NadekoBot.Credentials.OwnerIds.Contains(u.Id)) | ||||
|                         .Distinct(new GuildUserComparer()) | ||||
|                         .Select(async u => | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 return await u.CreateDMChannelAsync(); | ||||
|                             } | ||||
|                             catch | ||||
|                             { | ||||
|                                 return null; | ||||
|                             } | ||||
|                         }))) | ||||
|                     .Where(ch => ch != null) | ||||
|                     .OrderBy(x => NadekoBot.Credentials.OwnerIds.IndexOf(x.Id)) | ||||
|                     .ToList(); | ||||
|  | ||||
|                 if (!OwnerChannels.Any()) | ||||
|                 _client.GetGuilds().SelectMany(g => g.Users); | ||||
|  | ||||
|                 LoadOwnerChannels(); | ||||
|  | ||||
|                 if (!ownerChannels.Any()) | ||||
|                     _log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file."); | ||||
|                 else | ||||
|                     _log.Info($"Created {OwnerChannels.Count} out of {NadekoBot.Credentials.OwnerIds.Length} owner message channels."); | ||||
|                     _log.Info($"Created {ownerChannels.Length} out of {NadekoBot.Credentials.OwnerIds.Length} owner message channels."); | ||||
|             }); | ||||
|  | ||||
|             _client.MessageReceived += MessageReceivedHandler; | ||||
| @@ -133,6 +122,36 @@ namespace NadekoBot.Services | ||||
|             return Task.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         private void LoadOwnerChannels() | ||||
|         { | ||||
|             var hs = new HashSet<ulong>(NadekoBot.Credentials.OwnerIds); | ||||
|             var channels = new Dictionary<ulong, AsyncLazy<IDMChannel>>(); | ||||
|  | ||||
|             foreach (var s in _client.Shards) | ||||
|             { | ||||
|                 if(hs.Count == 0) | ||||
|                     break; | ||||
|                     foreach (var g in s.Guilds) | ||||
|                     { | ||||
|                         if(hs.Count == 0) | ||||
|                             break; | ||||
|  | ||||
|                         foreach (var u in g.Users) | ||||
|                         { | ||||
|                             if(hs.Remove(u.Id)) | ||||
|                             { | ||||
|                                 channels.Add(u.Id, new AsyncLazy<IDMChannel>(async () => await u.CreateDMChannelAsync())); | ||||
|                                 if(hs.Count == 0)    | ||||
|                                         break; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|             } | ||||
|  | ||||
|             ownerChannels = channels.OrderBy(x => NadekoBot.Credentials.OwnerIds.IndexOf(x.Key)) | ||||
|                     .Select(x => x.Value) | ||||
|                     .ToImmutableArray(); | ||||
|         } | ||||
|         private async Task<bool> TryRunCleverbot(IUserMessage usrMsg, SocketGuild guild) | ||||
|         { | ||||
|             if (guild == null) | ||||
| @@ -427,7 +446,7 @@ namespace NadekoBot.Services | ||||
|  | ||||
|                     await usrMsg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false); | ||||
|  | ||||
|                     await SelfCommands.HandleDmForwarding(usrMsg, OwnerChannels).ConfigureAwait(false); | ||||
|                     await SelfCommands.HandleDmForwarding(usrMsg, ownerChannels).ConfigureAwait(false); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user