From 5e4628ec10f3b0cd312e6ab9e39105961040a2b2 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 21 Aug 2016 16:16:11 +0200 Subject: [PATCH 1/4] Renamed to google service and using urlshortner api lib too. .roles are ordered by position now. --- .../Searches/Commands/Models/ImdbMovie.cs | 2 +- src/NadekoBot/Modules/Searches/Searches.cs | 16 ++++----- src/NadekoBot/Modules/Utility/Utility.cs | 4 +-- src/NadekoBot/NadekoBot.cs | 2 +- ...YoutubeService.cs => IGoogleApiService.cs} | 4 ++- ...{YoutubeService.cs => GoogleApiService.cs} | 28 +++++++++++----- src/NadekoBot/_Extensions/Extensions.cs | 33 ------------------- src/NadekoBot/project.json | 1 + src/NadekoBot/project.lock.json | 32 ++++++++++++++++++ 9 files changed, 68 insertions(+), 54 deletions(-) rename src/NadekoBot/Services/{IYoutubeService.cs => IGoogleApiService.cs} (82%) rename src/NadekoBot/Services/Impl/{YoutubeService.cs => GoogleApiService.cs} (79%) diff --git a/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs b/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs index 64f819ab..f4fa1770 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs +++ b/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs @@ -26,7 +26,7 @@ $@"`Title:` {WebUtility.HtmlDecode(Title)} {(string.IsNullOrEmpty(OriginalTitle) `Genre:` {GenresAsString} `Link:` <{ImdbURL}> `Plot:` {System.Net.WebUtility.HtmlDecode(Plot.TrimTo(500))} -`img:` " + Poster.ShortenUrl().Result; +`img:` " + Poster; public string GenresAsString => string.Join(", ", Genres); } diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index 76d4bdb8..f8a0bec1 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -20,11 +20,11 @@ namespace NadekoBot.Modules.Searches [Module("~", AppendSpace = false)] public partial class Searches : DiscordModule { - private IYoutubeService _yt { get; } + private IGoogleApiService _google { get; } - public Searches(ILocalization loc, CommandService cmds, IBotConfiguration config, DiscordSocketClient client, IYoutubeService youtube) : base(loc, cmds, config, client) + public Searches(ILocalization loc, CommandService cmds, IBotConfiguration config, DiscordSocketClient client, IGoogleApiService youtube) : base(loc, cmds, config, client) { - _yt = youtube; + _google = youtube; } [LocalizedCommand, LocalizedDescription, LocalizedSummary] @@ -54,7 +54,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 { var channel = imsg.Channel as ITextChannel; if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; - var result = (await _yt.FindVideosByKeywordsAsync(query, 1)).FirstOrDefault(); + var result = (await _google.FindVideosByKeywordsAsync(query, 1)).FirstOrDefault(); if (string.IsNullOrWhiteSpace(result)) { await channel.SendMessageAsync("No results found for that query."); @@ -183,7 +183,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 if (string.IsNullOrWhiteSpace(ffs)) return; - await channel.SendMessageAsync(await $"".ShortenUrl()) + await channel.SendMessageAsync(await _google.ShortenUrl($"")) .ConfigureAwait(false); } @@ -270,7 +270,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 var sb = new System.Text.StringBuilder(); sb.AppendLine($"`Term:` {items["list"][0]["word"].ToString()}"); sb.AppendLine($"`Definition:` {items["list"][0]["definition"].ToString()}"); - sb.Append($"`Link:` <{await items["list"][0]["permalink"].ToString().ShortenUrl().ConfigureAwait(false)}>"); + sb.Append($"`Link:` <{await _google.ShortenUrl(items["list"][0]["permalink"].ToString()).ConfigureAwait(false)}>"); await channel.SendMessageAsync(sb.ToString()); } catch @@ -306,7 +306,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 var items = JObject.Parse(res); var str = $@"`Hashtag:` {items["defs"]["def"]["hashtag"].ToString()} `Definition:` {items["defs"]["def"]["text"].ToString()} -`Link:` <{await items["defs"]["def"]["uri"].ToString().ShortenUrl().ConfigureAwait(false)}>"; +`Link:` <{await _google.ShortenUrl(items["defs"]["def"]["uri"].ToString()).ConfigureAwait(false)}>"; await channel.SendMessageAsync(str); } catch @@ -463,7 +463,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 await channel.SendMessageAsync("Invalid user specified.").ConfigureAwait(false); return; } - await channel.SendMessageAsync(await usr.AvatarUrl.ShortenUrl()).ConfigureAwait(false); + await channel.SendMessageAsync(await _google.ShortenUrl(usr.AvatarUrl).ConfigureAwait(false)).ConfigureAwait(false); } public static async Task GetSafebooruImageLink(string tag) diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs index 166c9eb5..587debef 100644 --- a/src/NadekoBot/Modules/Utility/Utility.cs +++ b/src/NadekoBot/Modules/Utility/Utility.cs @@ -121,11 +121,11 @@ namespace NadekoBot.Modules.Utility var guild = (msg.Channel as ITextChannel).Guild; if (target != null) { - await msg.Reply($"`List of roles for **{target.Username}**:` \nβ€’ " + string.Join("\nβ€’ ", target.Roles.Except(new[] { guild.EveryoneRole }))); + await msg.Reply($"`List of roles for **{target.Username}**:` \nβ€’ " + string.Join("\nβ€’ ", target.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r => r.Position))); } else { - await msg.Reply("`List of roles:` \nβ€’ " + string.Join("\nβ€’ ", (msg.Channel as ITextChannel).Guild.Roles.Except(new[] { guild.EveryoneRole }))); + await msg.Reply("`List of roles:` \nβ€’ " + string.Join("\nβ€’ ", (msg.Channel as ITextChannel).Guild.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r=>r.Position))); } } diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index f5719829..4b0f9c3c 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -53,7 +53,7 @@ namespace NadekoBot depMap.Add(Config); depMap.Add(Client); depMap.Add(Commands); - depMap.Add(Youtube); + depMap.Add(Youtube); //connect await Client.LoginAsync(TokenType.Bot, Credentials.Token); diff --git a/src/NadekoBot/Services/IYoutubeService.cs b/src/NadekoBot/Services/IGoogleApiService.cs similarity index 82% rename from src/NadekoBot/Services/IYoutubeService.cs rename to src/NadekoBot/Services/IGoogleApiService.cs index bf511f00..c872b96e 100644 --- a/src/NadekoBot/Services/IYoutubeService.cs +++ b/src/NadekoBot/Services/IGoogleApiService.cs @@ -3,10 +3,12 @@ using System.Threading.Tasks; namespace NadekoBot.Services { - public interface IYoutubeService + public interface IGoogleApiService { Task> FindVideosByKeywordsAsync(string keywords, int count = 1); Task> FindPlaylistIdsByKeywordsAsync(string keywords, int count = 1); Task> FindRelatedVideosAsync(string url, int count = 1); + + Task ShortenUrl(string url); } } diff --git a/src/NadekoBot/Services/Impl/YoutubeService.cs b/src/NadekoBot/Services/Impl/GoogleApiService.cs similarity index 79% rename from src/NadekoBot/Services/Impl/YoutubeService.cs rename to src/NadekoBot/Services/Impl/GoogleApiService.cs index 94290894..7a27c785 100644 --- a/src/NadekoBot/Services/Impl/YoutubeService.cs +++ b/src/NadekoBot/Services/Impl/GoogleApiService.cs @@ -5,26 +5,29 @@ using System.Threading.Tasks; using Google.Apis.YouTube.v3; using Google.Apis.Services; using System.Text.RegularExpressions; -using System.Diagnostics.Contracts; +using Google.Apis.Urlshortener.v1; +using Google.Apis.Urlshortener.v1.Data; namespace NadekoBot.Services.Impl { - public class YoutubeService : IYoutubeService + public class GoogleApiService : IGoogleApiService { private YouTubeService yt; + private UrlshortenerService sh; - public YoutubeService() + public GoogleApiService() { - yt = new YouTubeService(new BaseClientService.Initializer { + var bcs = new BaseClientService.Initializer + { ApplicationName = "Nadeko Bot", ApiKey = NadekoBot.Credentials.GoogleApiKey - }); + }; + + yt = new YouTubeService(bcs); + sh = new UrlshortenerService(bcs); } public async Task> FindPlaylistIdsByKeywordsAsync(string keywords, int count = 1) { - //Contract.Requires(!string.IsNullOrWhiteSpace(keywords)); - //Contract.Requires(count > 0); - if (string.IsNullOrWhiteSpace(keywords)) throw new ArgumentNullException(nameof(keywords)); @@ -77,5 +80,14 @@ namespace NadekoBot.Services.Impl query.Type = "video"; return (await query.ExecuteAsync()).Items.Select(i => "http://www.youtube.com/watch?v=" + i.Id.VideoId); } + + public async Task ShortenUrl(string url) + { + if (string.IsNullOrWhiteSpace(url)) + throw new ArgumentNullException(nameof(url)); + + var response = await sh.Url.Insert(new Url { LongUrl = url }).ExecuteAsync(); + return response.Id; + } } } diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index aef5da9b..4128fe38 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -81,39 +81,6 @@ namespace NadekoBot.Extensions return ch.SendTableAsync("", items, howToPrint, columns); } - public static async Task ShortenUrl(this string url) - { - if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleApiKey)) return url; - try - { - var httpWebRequest = - (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/urlshortener/v1/url?key=" + - NadekoBot.Credentials.GoogleApiKey); - httpWebRequest.ContentType = "application/json"; - httpWebRequest.Method = "POST"; - - using (var streamWriter = new StreamWriter(await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false))) - { - var json = "{\"longUrl\":\"" + Uri.EscapeDataString(url) + "\"}"; - streamWriter.Write(json); - } - - var httpResponse = (await httpWebRequest.GetResponseAsync().ConfigureAwait(false)) as HttpWebResponse; - var responseStream = httpResponse.GetResponseStream(); - using (var streamReader = new StreamReader(responseStream)) - { - var responseText = await streamReader.ReadToEndAsync().ConfigureAwait(false); - return Regex.Match(responseText, @"""id"": ?""(?.+)""").Groups["id"].Value; - } - } - catch (Exception ex) - { - Console.WriteLine("Shortening of this url failed: " + url); - Console.WriteLine(ex.ToString()); - return url; - } - } - /// /// returns an IEnumerable with randomized element order /// diff --git a/src/NadekoBot/project.json b/src/NadekoBot/project.json index a4e9e9f9..75b7a326 100644 --- a/src/NadekoBot/project.json +++ b/src/NadekoBot/project.json @@ -22,6 +22,7 @@ "Discord.Net.Commands": "1.0.0-dev", "System.Resources.ResourceWriter": "4.0.0-beta-22816", "Google.Apis.YouTube.v3": "1.15.0.582", + "Google.Apis.Urlshortener.v1": "1.15.0.138", "System.Diagnostics.Contracts": "4.0.1", "NLog": "4.4.0-betaV15" }, diff --git a/src/NadekoBot/project.lock.json b/src/NadekoBot/project.lock.json index 316e9f09..430c2ca3 100644 --- a/src/NadekoBot/project.lock.json +++ b/src/NadekoBot/project.lock.json @@ -88,6 +88,19 @@ "lib/netstandard1.3/Google.Apis.Core.dll": {} } }, + "Google.Apis.Urlshortener.v1/1.15.0.138": { + "type": "package", + "dependencies": { + "Google.Apis": "1.15.0", + "Google.Apis.Auth": "1.15.0" + }, + "compile": { + "lib/netstandard1.3/Google.Apis.Urlshortener.v1.dll": {} + }, + "runtime": { + "lib/netstandard1.3/Google.Apis.Urlshortener.v1.dll": {} + } + }, "Google.Apis.YouTube.v3/1.15.0.582": { "type": "package", "dependencies": { @@ -2654,6 +2667,24 @@ "lib/portable-net45+sl50+netcore45+wpa81+wp8/Google.Apis.Core.xml" ] }, + "Google.Apis.Urlshortener.v1/1.15.0.138": { + "sha512": "67USnpqrk8tWO3LAgaK9qDQT6h8A7i7eUIOKm+OISThZoQuHiLCn6dbg46FVb597LUh57AxClSSbhnweYcYC3Q==", + "type": "package", + "path": "Google.Apis.Urlshortener.v1/1.15.0.138", + "files": [ + "Google.Apis.Urlshortener.v1.1.15.0.138.nupkg.sha512", + "Google.Apis.Urlshortener.v1.nuspec", + "lib/netstandard1.3/Google.Apis.Urlshortener.v1.dll", + "lib/netstandard1.3/Google.Apis.Urlshortener.v1.pdb", + "lib/netstandard1.3/Google.Apis.Urlshortener.v1.xml", + "lib/portable-net40+sl50+netcore45+wpa81+wp8/Google.Apis.Urlshortener.v1.dll", + "lib/portable-net40+sl50+netcore45+wpa81+wp8/Google.Apis.Urlshortener.v1.pdb", + "lib/portable-net40+sl50+netcore45+wpa81+wp8/Google.Apis.Urlshortener.v1.xml", + "lib/portable-net45+netcore45+wpa81+wp8/Google.Apis.Urlshortener.v1.dll", + "lib/portable-net45+netcore45+wpa81+wp8/Google.Apis.Urlshortener.v1.pdb", + "lib/portable-net45+netcore45+wpa81+wp8/Google.Apis.Urlshortener.v1.xml" + ] + }, "Google.Apis.YouTube.v3/1.15.0.582": { "sha512": "isR8FdI417PKLgLlNdOVDhduO+8yqPJ+vfID1Zx0MjAa/y3q655Plk2E/KNmsrjvXkqSSWwDCQHPz/Q1fat4tA==", "type": "package", @@ -7855,6 +7886,7 @@ "": [ "Discord.Net >= 1.0.0-dev", "Discord.Net.Commands >= 1.0.0-dev", + "Google.Apis.Urlshortener.v1 >= 1.15.0.138", "Google.Apis.YouTube.v3 >= 1.15.0.582", "Microsoft.Extensions.DependencyInjection >= 1.0.0", "Microsoft.Extensions.DependencyInjection.Abstractions >= 1.0.0", From 4317e97113a122a8c9d2a01ca3006a25031a5b90 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 21 Aug 2016 18:00:03 +0200 Subject: [PATCH 2/4] Some replacements, osu commands converted --- src/NadekoBot/Classes/NadekoStats.cs | 6 +- src/NadekoBot/Classes/SearchHelper.cs | 18 +- .../Administration/AdministrationModule.cs | 10 +- .../Commands/CrossServerTextChannel.cs | 2 +- .../Administration/Commands/LogCommand.cs | 2 +- .../Commands/MessageRepeater.cs | 4 +- .../Administration/Commands/PlayingRotate.cs | 4 +- .../Commands/SelfAssignedRolesCommand.cs | 6 +- .../Commands/ServerGreetCommand.cs | 8 +- .../Modules/Gambling/Commands/DrawCommand.cs | 2 +- .../Gambling/Commands/FlipCoinCommand.cs | 8 +- .../Games/Commands/PlantAndPickCommands.cs | 2 +- .../Games/Commands/SpeedTypingCommands.cs | 4 +- src/NadekoBot/Modules/NSFW/NSFW.cs | 9 +- .../Searches/Commands/ConverterCommands.cs | 6 +- .../Modules/Searches/Commands/EvalCommand.cs | 2 +- .../Modules/Searches/Commands/LoLCommands.cs | 8 +- .../Modules/Searches/Commands/OsuCommands.cs | 504 +++++++++--------- .../Commands/StreamNotificationCommands.cs | 10 +- src/NadekoBot/Modules/Searches/Searches.cs | 3 +- src/NadekoBot/Modules/Trello/Trello.cs | 10 +- .../Modules/Utility/Commands/Remind.cs | 10 +- src/NadekoBot/NadekoBot.cs | 4 +- src/NadekoBot/_Extensions/Extensions.cs | 8 + .../CustomReactions/CustomReactions.cs | 2 +- .../_Modules/Music/Classes/SoundCloud.cs | 14 +- src/NadekoBot/_Modules/Music/MusicModule.cs | 42 +- .../Commands/FilterInvitesCommand.cs | 6 +- .../Commands/FilterWordsCommand.cs | 10 +- .../_Modules/Permissions/PermissionsModule.cs | 104 ++-- 30 files changed, 420 insertions(+), 408 deletions(-) diff --git a/src/NadekoBot/Classes/NadekoStats.cs b/src/NadekoBot/Classes/NadekoStats.cs index ae83dc3b..49038e98 100644 --- a/src/NadekoBot/Classes/NadekoStats.cs +++ b/src/NadekoBot/Classes/NadekoStats.cs @@ -115,13 +115,13 @@ namespace NadekoBot HttpClient carbonClient = new HttpClient(); private async Task SendUpdateToCarbon() { - if (string.IsNullOrWhiteSpace(NadekoBot.Creds.CarbonKey)) + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.CarbonKey)) return; try { using (var content = new FormUrlEncodedContent(new Dictionary { { "servercount", NadekoBot.Client.Servers.Count().ToString() }, - { "key", NadekoBot.Creds.CarbonKey } + { "key", NadekoBot.Credentials.CarbonKey } })) { content.Headers.Clear(); @@ -155,7 +155,7 @@ namespace NadekoBot sb.AppendLine($"`Bot Version: {BotVersion}`"); sb.AppendLine($"`Bot id: {NadekoBot.Client.CurrentUser.Id}`"); sb.Append("`Owners' Ids:` "); - sb.AppendLine("`" + String.Join(", ", NadekoBot.Creds.OwnerIds) + "`"); + sb.AppendLine("`" + String.Join(", ", NadekoBot.Credentials.OwnerIds) + "`"); sb.AppendLine($"`Uptime: {GetUptimeString()}`"); sb.Append($"`Servers: {ServerCount}"); sb.Append($" | TextChannels: {TextChannelsCount}"); diff --git a/src/NadekoBot/Classes/SearchHelper.cs b/src/NadekoBot/Classes/SearchHelper.cs index 1339c9d8..8b434786 100644 --- a/src/NadekoBot/Classes/SearchHelper.cs +++ b/src/NadekoBot/Classes/SearchHelper.cs @@ -147,14 +147,14 @@ namespace NadekoBot.Classes return $"https://www.youtube.com/watch?v={match.Groups["id"].Value}"; } - if (string.IsNullOrWhiteSpace(NadekoBot.Creds.GoogleAPIKey)) + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey)) throw new InvalidCredentialException("Google API Key is missing."); var response = await GetResponseStringAsync( $"https://www.googleapis.com/youtube/v3/search?" + $"part=snippet&maxResults=1" + $"&q={Uri.EscapeDataString(keywords)}" + - $"&key={NadekoBot.Creds.GoogleAPIKey}").ConfigureAwait(false); + $"&key={NadekoBot.Credentials.GoogleAPIKey}").ConfigureAwait(false); JObject obj = JObject.Parse(response); var data = JsonConvert.DeserializeObject(response); @@ -181,7 +181,7 @@ namespace NadekoBot.Classes $"https://www.googleapis.com/youtube/v3/search?" + $"part=snippet&maxResults={count}&type=video" + $"&relatedToVideoId={id}" + - $"&key={NadekoBot.Creds.GoogleAPIKey}").ConfigureAwait(false); + $"&key={NadekoBot.Credentials.GoogleAPIKey}").ConfigureAwait(false); JObject obj = JObject.Parse(response); var data = JsonConvert.DeserializeObject(response); @@ -191,7 +191,7 @@ namespace NadekoBot.Classes public static async Task GetPlaylistIdByKeyword(string query) { - if (string.IsNullOrWhiteSpace(NadekoBot.Creds.GoogleAPIKey)) + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey)) throw new ArgumentNullException(nameof(query)); var match = new Regex("(?:youtu\\.be\\/|list=)(?[\\da-zA-Z\\-_]*)").Match(query); if (match.Length > 1) @@ -201,7 +201,7 @@ namespace NadekoBot.Classes var link = "https://www.googleapis.com/youtube/v3/search?part=snippet" + "&maxResults=1&type=playlist" + $"&q={Uri.EscapeDataString(query)}" + - $"&key={NadekoBot.Creds.GoogleAPIKey}"; + $"&key={NadekoBot.Credentials.GoogleAPIKey}"; var response = await GetResponseStringAsync(link).ConfigureAwait(false); var data = JsonConvert.DeserializeObject(response); @@ -212,7 +212,7 @@ namespace NadekoBot.Classes public static async Task> GetVideoIDs(string playlist, int number = 50) { - if (string.IsNullOrWhiteSpace(NadekoBot.Creds.GoogleAPIKey)) + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey)) { throw new ArgumentNullException(nameof(playlist)); } @@ -231,7 +231,7 @@ namespace NadekoBot.Classes $"https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails" + $"&maxResults={toGet}" + $"&playlistId={playlist}" + - $"&key={NadekoBot.Creds.GoogleAPIKey}"; + $"&key={NadekoBot.Credentials.GoogleAPIKey}"; if (!string.IsNullOrWhiteSpace(nextPageToken)) link += $"&pageToken={nextPageToken}"; var response = await GetResponseStringAsync(link).ConfigureAwait(false); @@ -245,12 +245,12 @@ namespace NadekoBot.Classes public static async Task ShortenUrl(string url) { - if (string.IsNullOrWhiteSpace(NadekoBot.Creds.GoogleAPIKey)) return url; + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey)) return url; try { var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/urlshortener/v1/url?key=" + - NadekoBot.Creds.GoogleAPIKey); + NadekoBot.Credentials.GoogleAPIKey); httpWebRequest.ContentType = "application/json"; httpWebRequest.Method = "POST"; diff --git a/src/NadekoBot/Modules/Administration/AdministrationModule.cs b/src/NadekoBot/Modules/Administration/AdministrationModule.cs index b6f14069..387d3d78 100644 --- a/src/NadekoBot/Modules/Administration/AdministrationModule.cs +++ b/src/NadekoBot/Modules/Administration/AdministrationModule.cs @@ -494,10 +494,10 @@ namespace NadekoBot.Modules.Administration //{ // var channel = imsg.Channel as ITextChannel; - // if (string.IsNullOrWhiteSpace(e.GetArg("img"))) + // if (string.IsNullOrWhiteSpace(img)) // return; // // Gather user provided URL. - // var avatarAddress = e.GetArg("img"); + // var avatarAddress = img; // var imageStream = await SearchHelper.GetResponseStreamAsync(avatarAddress).ConfigureAwait(false); // var image = System.Drawing.Image.FromStream(imageStream); // await client.CurrentUser.Edit("", avatar: image.ToStream()).ConfigureAwait(false); @@ -515,7 +515,7 @@ namespace NadekoBot.Modules.Administration // game = game ?? ""; - // client.SetGame(e.GetArg("set_game")); + // client.SetGame(set_game); //} ////todo owner only @@ -570,8 +570,8 @@ namespace NadekoBot.Modules.Administration //public async Task Donadd(IMessage imsg, IUser donator, int amount) //{ // var channel = imsg.Channel as ITextChannel; - // var donator = channel.Guild.FindUsers(e.GetArg("donator")).FirstOrDefault(); - // var amount = int.Parse(e.GetArg("amount")); + // var donator = channel.Guild.FindUsers(donator).FirstOrDefault(); + // var amount = int.Parse(amount); // if (donator == null) return; // try // { diff --git a/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs b/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs index 66f31d8f..81343c62 100644 --- a/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs +++ b/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs @@ -86,7 +86,7 @@ // .Do(async e => // { // int token; -// if (!int.TryParse(e.GetArg("token"), out token)) +// if (!int.TryParse(token, out token)) // return; // HashSet set; // if (!Subscribers.TryGetValue(token, out set)) diff --git a/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs b/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs index 498621c6..a2ba8b43 100644 --- a/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs +++ b/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs @@ -456,7 +456,7 @@ // { // var config = SpecificConfigurations.Default.Of(e.Server.Id); -// if (e.GetArg("all")?.ToLower() == "all") +// if (all?.ToLower() == "all") // { // foreach (var voiceChannel in e.Server.VoiceChannels) // { diff --git a/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs b/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs index 6192ea95..0be2230e 100644 --- a/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs +++ b/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs @@ -80,8 +80,8 @@ // .AddCheck(SimpleCheckers.ManageMessages()) // .Do(async e => // { -// var minutesStr = e.GetArg("minutes"); -// var msg = e.GetArg("msg"); +// var minutesStr = minutes; +// var msg = msg; // // if both null, disable // if (string.IsNullOrWhiteSpace(msg) && string.IsNullOrWhiteSpace(minutesStr)) diff --git a/src/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs b/src/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs index 6b105a37..d1537e50 100644 --- a/src/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs +++ b/src/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs @@ -109,7 +109,7 @@ // .AddCheck(SimpleCheckers.OwnerOnly()) // .Do(async e => // { -// var arg = e.GetArg("text"); +// var arg = text; // if (string.IsNullOrWhiteSpace(arg)) // return; // await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); @@ -149,7 +149,7 @@ // .AddCheck(SimpleCheckers.OwnerOnly()) // .Do(async e => // { -// var arg = e.GetArg("number"); +// var arg = number; // int num; // string str; // await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs b/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs index 7bb9235a..7171a63d 100644 --- a/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs +++ b/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs @@ -49,7 +49,7 @@ // .AddCheck(SimpleCheckers.CanManageRoles) // .Do(async e => // { -// var roleName = e.GetArg("role")?.Trim(); +// var roleName = role?.Trim(); // if (string.IsNullOrWhiteSpace(roleName)) // return; // var role = e.Server.FindRoles(roleName).FirstOrDefault(); @@ -116,7 +116,7 @@ // .Parameter("role", ParameterType.Unparsed) // .Do(async e => // { -// var roleName = e.GetArg("role")?.Trim(); +// var roleName = role?.Trim(); // if (string.IsNullOrWhiteSpace(roleName)) // return; // var role = e.Server.FindRoles(roleName).FirstOrDefault(); @@ -172,7 +172,7 @@ // .Parameter("role", ParameterType.Unparsed) // .Do(async e => // { -// var roleName = e.GetArg("role")?.Trim(); +// var roleName = role?.Trim(); // if (string.IsNullOrWhiteSpace(roleName)) // return; // var role = e.Server.FindRoles(roleName).FirstOrDefault(); diff --git a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs index 4fa51a62..ccd20a36 100644 --- a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs +++ b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs @@ -240,14 +240,14 @@ // { // if (!imsg.Author.ServerPermissions.ManageServer) return; // var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); -// if (string.IsNullOrWhiteSpace(e.GetArg("msg"))) +// if (string.IsNullOrWhiteSpace(msg)) // { // await channel.SendMessageAsync("`Current greet message:` " + ann.GreetText); // return; // } -// ann.GreetText = e.GetArg("msg"); +// ann.GreetText = msg; // await channel.SendMessageAsync("New greet message set.").ConfigureAwait(false); // if (!ann.Greet) // await channel.SendMessageAsync("Enable greet messsages by typing `.greet`").ConfigureAwait(false); @@ -273,13 +273,13 @@ // { // if (!imsg.Author.ServerPermissions.ManageServer) return; // var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id)); -// if (string.IsNullOrWhiteSpace(e.GetArg("msg"))) +// if (string.IsNullOrWhiteSpace(msg)) // { // await channel.SendMessageAsync("`Current bye message:` " + ann.ByeText); // return; // } -// ann.ByeText = e.GetArg("msg"); +// ann.ByeText = msg; // await channel.SendMessageAsync("New bye message set.").ConfigureAwait(false); // if (!ann.Bye) // await channel.SendMessageAsync("Enable bye messsages by typing `.bye`.").ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Gambling/Commands/DrawCommand.cs b/src/NadekoBot/Modules/Gambling/Commands/DrawCommand.cs index c2744de7..75939c89 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/DrawCommand.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/DrawCommand.cs @@ -53,7 +53,7 @@ // try // { // var num = 1; -// var isParsed = int.TryParse(e.GetArg("count"), out num); +// var isParsed = int.TryParse(count, out num); // if (!isParsed || num < 2) // { // var c = cards.DrawACard(); diff --git a/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs b/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs index 32e2f938..3b0b9401 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs @@ -34,9 +34,9 @@ // public Func BetFlipCoinFunc() => async e => // { -// var amountstr = e.GetArg("amount").Trim(); +// var amountstr = amount.Trim(); -// var guessStr = e.GetArg("guess").Trim().ToUpperInvariant(); +// var guessStr = guess.Trim().ToUpperInvariant(); // if (guessStr != "H" && guessStr != "T" && guessStr != "HEADS" && guessStr != "TAILS") // return; @@ -82,7 +82,7 @@ // public Func FlipCoinFunc() => async e => // { -// if (e.GetArg("count") == "") +// if (count == "") // { // if (rng.Next(0, 2) == 1) // await e.Channel.SendFile("heads.png", Properties.Resources.heads.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false); @@ -92,7 +92,7 @@ // else // { // int result; -// if (int.TryParse(e.GetArg("count"), out result)) +// if (int.TryParse(count, out result)) // { // if (result > 10) // result = 10; diff --git a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs index 9262678b..b670c633 100644 --- a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs @@ -131,7 +131,7 @@ // .Parameter("cd", ParameterType.Unparsed) // .Do(async e => // { -// var cdStr = e.GetArg("cd"); +// var cdStr = cd; // int cd = 2; // if (!int.TryParse(cdStr, out cd) || cd < 0) // { diff --git a/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs b/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs index cd561349..eb5e8a9f 100644 --- a/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs @@ -181,11 +181,11 @@ // .Parameter("text", ParameterType.Unparsed) // .Do(async e => // { -// if (!NadekoBot.IsOwner(imsg.Author.Id) || string.IsNullOrWhiteSpace(e.GetArg("text"))) return; +// if (!NadekoBot.IsOwner(imsg.Author.Id) || string.IsNullOrWhiteSpace(text)) return; // DbHandler.Instance.Connection.Insert(new TypingArticle // { -// Text = e.GetArg("text"), +// Text = text, // DateAdded = DateTime.Now // }); diff --git a/src/NadekoBot/Modules/NSFW/NSFW.cs b/src/NadekoBot/Modules/NSFW/NSFW.cs index 269ce7ce..b3977f5a 100644 --- a/src/NadekoBot/Modules/NSFW/NSFW.cs +++ b/src/NadekoBot/Modules/NSFW/NSFW.cs @@ -11,6 +11,7 @@ using System.Text.RegularExpressions; using System.Xml.Linq; using System.Net; using Discord.WebSocket; +using NadekoBot.Extensions; namespace NadekoBot.Modules.NSFW { @@ -173,9 +174,7 @@ namespace NadekoBot.Modules.NSFW { using (var http = new HttpClient()) { - http.DefaultRequestHeaders.Clear(); - http.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1"); - http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); + http.AddFakeHeaders(); var webpage = await http.GetStringAsync("http://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=100&tags="+ tag.Replace(" ", "_")).ConfigureAwait(false); var matches = Regex.Matches(webpage, "file_url=\"(?.*?)\""); @@ -211,9 +210,7 @@ namespace NadekoBot.Modules.NSFW { using (var http = new HttpClient()) { - http.DefaultRequestHeaders.Clear(); - http.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1"); - http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); + http.AddFakeHeaders(); var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + Uri.EscapeUriString(tags) + "%20order:random&limit=1"); var doc = XDocument.Load(data); return doc.Descendants("file_url").FirstOrDefault().Value; diff --git a/src/NadekoBot/Modules/Searches/Commands/ConverterCommands.cs b/src/NadekoBot/Modules/Searches/Commands/ConverterCommands.cs index 14651abb..52a6d157 100644 --- a/src/NadekoBot/Modules/Searches/Commands/ConverterCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/ConverterCommands.cs @@ -72,11 +72,11 @@ // { // await e.Channel.SendIsTyping().ConfigureAwait(false); -// string from = e.GetArg("from-to").ToLowerInvariant().Split('>')[0]; -// string to = e.GetArg("from-to").ToLowerInvariant().Split('>')[1]; +// string from = from-to.ToLowerInvariant().Split('>')[0]; +// string to = from-to.ToLowerInvariant().Split('>')[1]; // float quantity = 1.0f; -// if (!float.TryParse(e.GetArg("quantity"), out quantity)) +// if (!float.TryParse(quantity, out quantity)) // { // quantity = 1.0f; // } diff --git a/src/NadekoBot/Modules/Searches/Commands/EvalCommand.cs b/src/NadekoBot/Modules/Searches/Commands/EvalCommand.cs index 617682d2..5c8e45ad 100644 --- a/src/NadekoBot/Modules/Searches/Commands/EvalCommand.cs +++ b/src/NadekoBot/Modules/Searches/Commands/EvalCommand.cs @@ -27,7 +27,7 @@ // private CustomParser parser = new CustomParser(); // private Func EvalFunc() => async e => // { -// string expression = e.GetArg("expression")?.Trim(); +// string expression = expression?.Trim(); // if (string.IsNullOrWhiteSpace(expression)) // { // return; diff --git a/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs index dfc25b3e..1a4a5de9 100644 --- a/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs @@ -124,9 +124,9 @@ namespace NadekoBot.Modules.Searches // try // { // //get role -// var role = ResolvePos(e.GetArg("position")); +// var role = ResolvePos(position); // var resolvedRole = role; -// var name = e.GetArg("champ").Replace(" ", "").ToLower(); +// var name = champ.Replace(" ", "").ToLower(); // CachedChampion champ = null; // if (CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ)) @@ -136,7 +136,7 @@ namespace NadekoBot.Modules.Searches // await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); // return; // } -// var allData = JArray.Parse(await Classes.http.GetStringAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.Creds.LOLAPIKey}").ConfigureAwait(false)); +// var allData = JArray.Parse(await Classes.http.GetStringAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.Credentials.LOLAPIKey}").ConfigureAwait(false)); // JToken data = null; // if (role != null) // { @@ -177,7 +177,7 @@ namespace NadekoBot.Modules.Searches // roles[i] = ">" + roles[i] + "<"; // } // var general = JArray.Parse(await http.GetStringAsync($"http://api.champion.gg/stats/" + -// $"champs/{name}?api_key={NadekoBot.Creds.LOLAPIKey}") +// $"champs/{name}?api_key={NadekoBot.Credentials.LOLAPIKey}") // .ConfigureAwait(false)) // .FirstOrDefault(jt => jt["role"].ToString() == role)?["general"]; // if (general == null) diff --git a/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs b/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs index 3731ff8c..19479696 100644 --- a/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs @@ -1,269 +1,277 @@ -ο»Ώ//using Discord.Commands; -//using NadekoBot.Classes; -//using Newtonsoft.Json.Linq; -//using System; -//using System.IO; -//using System.Net; -//using System.Text.RegularExpressions; +ο»Ώusing Discord; +using Discord.Commands; +using NadekoBot.Attributes; +using NadekoBot.Classes; +using NadekoBot.Extensions; +using Newtonsoft.Json.Linq; +using NLog; +using System; +using System.Globalization; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; -//todo DI into partials -//namespace NadekoBot.Modules.Searches -//{ -// internal class OsuCommands : DiscordCommand -// { -// public OsuCommands(DiscordModule module) : base(module) -// { -// } +namespace NadekoBot.Modules.Searches +{ + public partial class Searches + { + [Group] + public class OsuCommands + { + private Logger _log; -// internal override void Init(CommandGroupBuilder cgb) -// { -// cgb.CreateCommand(Module.Prefix + "osu") -// .Description($"Shows osu stats for a player. | `{Prefix}osu Name` or `{Prefix}osu Name taiko`") -// .Parameter("usr", ParameterType.Required) -// .Parameter("mode", ParameterType.Unparsed) -// .Do(async e => -// { -// if (string.IsNullOrWhiteSpace(e.GetArg("usr"))) -// return; + public OsuCommands() + { + _log = LogManager.GetCurrentClassLogger(); + } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Osu(IMessage imsg, string usr, string mode) + { + var channel = imsg.Channel as ITextChannel; -// using (WebClient cl = new WebClient()) -// { -// try -// { -// var m = 0; -// if (!string.IsNullOrWhiteSpace(e.GetArg("mode"))) -// { -// m = ResolveGameMode(e.GetArg("mode")); -// } + if (string.IsNullOrWhiteSpace(usr)) + return; -// cl.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore); -// cl.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (Windows NT 6.2; Win64; x64)"); -// cl.DownloadDataAsync(new Uri($"http://lemmmy.pw/osusig/sig.php?uname={ e.GetArg("usr") }&flagshadow&xpbar&xpbarhex&pp=2&mode={m}")); -// cl.DownloadDataCompleted += async (s, cle) => -// { -// try -// { -// await e.Channel.SendFile($"{e.GetArg("usr")}.png", new MemoryStream(cle.Result)).ConfigureAwait(false); -// await channel.SendMessageAsync($"`Profile Link:`https://osu.ppy.sh/u/{Uri.EscapeDataString(e.GetArg("usr"))}\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false); -// } -// catch { } -// }; -// } -// catch -// { -// await channel.SendMessageAsync("πŸ’’ Failed retrieving osu signature :\\").ConfigureAwait(false); -// } -// } -// }); + using (HttpClient http = new HttpClient()) + { + try + { + var m = 0; + if (!string.IsNullOrWhiteSpace(mode)) + { + m = ResolveGameMode(mode); + } + http.AddFakeHeaders(); + var res = await http.GetStreamAsync(new Uri($"http://lemmmy.pw/osusig/sig.php?uname={ usr }&flagshadow&xpbar&xpbarhex&pp=2&mode={m}")).ConfigureAwait(false); -// cgb.CreateCommand(Module.Prefix + "osu b") -// .Description($"Shows information about an osu beatmap. |`{Prefix}osu b` https://osu.ppy.sh/s/127712`") -// .Parameter("map", ParameterType.Unparsed) -// .Do(async e => -// { -// if (string.IsNullOrWhiteSpace(NadekoBot.Creds.OsuAPIKey)) -// { -// await channel.SendMessageAsync("πŸ’’ An osu! API key is required.").ConfigureAwait(false); -// return; -// } + res.Position = 0; + await channel.SendFileAsync(res, $"{usr}.png").ConfigureAwait(false); + await channel.SendMessageAsync($"`Profile Link:`https://osu.ppy.sh/u/{Uri.EscapeDataString(usr)}\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false); + } + catch (Exception ex) + { + await channel.SendMessageAsync("πŸ’’ Failed retrieving osu signature :\\").ConfigureAwait(false); + _log.Warn(ex, "Osu command failed"); + } + } + } -// if (string.IsNullOrWhiteSpace(e.GetArg("map"))) -// return; + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Osub(IMessage imsg, [Remainder] string map) + { + var channel = imsg.Channel as ITextChannel; -// try -// { -// var mapId = ResolveMap(e.GetArg("map")); -// var reqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&{mapId}"; -// var obj = JArray.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false))[0]; -// var sb = new System.Text.StringBuilder(); -// var starRating = Math.Round(Double.Parse($"{obj["difficultyrating"]}", CultureInfo.InvariantCulture), 2); -// var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss"); -// sb.AppendLine($"{obj["artist"]} - {obj["title"]}, mapped by {obj["creator"]}. https://osu.ppy.sh/s/{obj["beatmapset_id"]}"); -// sb.AppendLine($"{starRating} stars, {obj["bpm"]} BPM | AR{obj["diff_approach"]}, CS{obj["diff_size"]}, OD{obj["diff_overall"]} | Length: {time}"); -// await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false); -// } -// catch -// { -// await channel.SendMessageAsync("Something went wrong."); -// } -// }); + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey)) + { + await channel.SendMessageAsync("πŸ’’ An osu! API key is required.").ConfigureAwait(false); + return; + } -// cgb.CreateCommand(Module.Prefix + "osu top5") -// .Description($"Displays a user's top 5 plays. |`{Prefix}osu top5 Name`") -// .Parameter("usr", ParameterType.Required) -// .Parameter("mode", ParameterType.Unparsed) -// .Do(async e => -// { -// if (string.IsNullOrWhiteSpace(NadekoBot.Creds.OsuAPIKey)) -// { -// await channel.SendMessageAsync("πŸ’’ An osu! API key is required.").ConfigureAwait(false); -// return; -// } + if (string.IsNullOrWhiteSpace(map)) + return; -// if (string.IsNullOrWhiteSpace(e.GetArg("usr"))) -// { -// await channel.SendMessageAsync("πŸ’’ Please provide a username.").ConfigureAwait(false); -// return; -// } + try + { + using (var http = new HttpClient()) + { + var mapId = ResolveMap(map); + var reqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Credentials.OsuApiKey}&{mapId}"; + var obj = JArray.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false))[0]; + var sb = new System.Text.StringBuilder(); + var starRating = Math.Round(Double.Parse($"{obj["difficultyrating"]}", CultureInfo.InvariantCulture), 2); + var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss"); + sb.AppendLine($"{obj["artist"]} - {obj["title"]}, mapped by {obj["creator"]}. https://osu.ppy.sh/s/{obj["beatmapset_id"]}"); + sb.AppendLine($"{starRating} stars, {obj["bpm"]} BPM | AR{obj["diff_approach"]}, CS{obj["diff_size"]}, OD{obj["diff_overall"]} | Length: {time}"); + await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false); + } + } + catch (Exception ex) + { + await channel.SendMessageAsync("Something went wrong."); + _log.Warn(ex, "Osub command failed"); + } + } -// try -// { -// var m = 0; -// if (!string.IsNullOrWhiteSpace(e.GetArg("mode"))) -// { -// m = ResolveGameMode(e.GetArg("mode")); -// } + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Osu5(IMessage imsg, string user, [Remainder] string mode) + { + var channel = imsg.Channel as ITextChannel; + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey)) + { + await channel.SendMessageAsync("πŸ’’ An osu! API key is required.").ConfigureAwait(false); + return; + } -// var reqString = $"https://osu.ppy.sh/api/get_user_best?k={NadekoBot.Creds.OsuAPIKey}&u={Uri.EscapeDataString(e.GetArg("usr"))}&type=string&limit=5&m={m}"; -// var obj = JArray.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false)); -// var sb = new System.Text.StringBuilder($"`Top 5 plays for {e.GetArg("usr")}:`\n```xl" + Environment.NewLine); -// foreach (var item in obj) -// { -// var mapReqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&b={item["beatmap_id"]}"; -// var map = JArray.Parse(await http.GetStringAsync(mapReqString).ConfigureAwait(false))[0]; -// var pp = Math.Round(Double.Parse($"{item["pp"]}", CultureInfo.InvariantCulture), 2); -// var acc = CalculateAcc(item, m); -// var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}")); -// if (mods != "+") -// sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | **{mods,-10}** | /b/{item["beatmap_id"]}"); -// else -// sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | /b/{item["beatmap_id"]}"); -// } -// sb.Append("```"); -// await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false); -// } -// catch -// { -// await channel.SendMessageAsync("Something went wrong."); -// } -// }); -// } + if (string.IsNullOrWhiteSpace(user)) + { + await channel.SendMessageAsync("πŸ’’ Please provide a username.").ConfigureAwait(false); + return; + } + using (var http = new HttpClient()) + { + try + { + var m = 0; + if (!string.IsNullOrWhiteSpace(mode)) + { + m = ResolveGameMode(mode); + } -// //https://osu.ppy.sh/wiki/Accuracy -// private static Double CalculateAcc(JToken play, int mode) -// { -// if (mode == 0) -// { -// var hitPoints = Double.Parse($"{play["count50"]}") * 50 + Double.Parse($"{play["count100"]}") * 100 + Double.Parse($"{play["count300"]}") * 300; -// var totalHits = Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countmiss"]}"); -// totalHits *= 300; -// return Math.Round(hitPoints / totalHits * 100, 2); -// } -// else if (mode == 1) -// { -// var hitPoints = Double.Parse($"{play["countmiss"]}") * 0 + Double.Parse($"{play["count100"]}") * 0.5 + Double.Parse($"{play["count300"]}") * 1; -// var totalHits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}"); -// hitPoints *= 300; -// totalHits *= 300; -// return Math.Round(hitPoints / totalHits * 100, 2); -// } -// else if (mode == 2) -// { -// var fruitsCaught = Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}"); -// var totalFruits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countkatu"]}"); -// return Math.Round(fruitsCaught / totalFruits * 100, 2); -// } -// else -// { -// var hitPoints = Double.Parse($"{play["count50"]}") * 50 + Double.Parse($"{play["count100"]}") * 100 + Double.Parse($"{play["countkatu"]}") * 200 + (Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countgeki"]}")) * 300; -// var totalHits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["countkatu"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countgeki"]}"); -// totalHits *= 300; -// return Math.Round(hitPoints / totalHits * 100, 2); -// } -// } + var reqString = $"https://osu.ppy.sh/api/get_user_best?k={NadekoBot.Credentials.OsuApiKey}&u={Uri.EscapeDataString(user)}&type=string&limit=5&m={m}"; + var obj = JArray.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false)); + var sb = new System.Text.StringBuilder($"`Top 5 plays for {user}:`\n```xl" + Environment.NewLine); + foreach (var item in obj) + { + var mapReqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Credentials.OsuApiKey}&b={item["beatmap_id"]}"; + var map = JArray.Parse(await http.GetStringAsync(mapReqString).ConfigureAwait(false))[0]; + var pp = Math.Round(Double.Parse($"{item["pp"]}", CultureInfo.InvariantCulture), 2); + var acc = CalculateAcc(item, m); + var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}")); + if (mods != "+") + sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | **{mods,-10}** | /b/{item["beatmap_id"]}"); + else + sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | /b/{item["beatmap_id"]}"); + } + sb.Append("```"); + await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false); + } + catch (Exception ex) + { + await channel.SendMessageAsync("Something went wrong."); + _log.Warn(ex, "Osu5 command failed"); + } -// private static string ResolveMap(string mapLink) -// { -// Match s = new Regex(@"osu.ppy.sh\/s\/", RegexOptions.IgnoreCase).Match(mapLink); -// Match b = new Regex(@"osu.ppy.sh\/b\/", RegexOptions.IgnoreCase).Match(mapLink); -// Match p = new Regex(@"osu.ppy.sh\/p\/", RegexOptions.IgnoreCase).Match(mapLink); -// Match m = new Regex(@"&m=", RegexOptions.IgnoreCase).Match(mapLink); -// if (s.Success) -// { -// var mapId = mapLink.Substring(mapLink.IndexOf("/s/") + 3); -// return $"s={mapId}"; -// } -// else if (b.Success) -// { -// if (m.Success) -// return $"b={mapLink.Substring(mapLink.IndexOf("/b/") + 3, mapLink.IndexOf("&m") - (mapLink.IndexOf("/b/") + 3))}"; -// else -// return $"b={mapLink.Substring(mapLink.IndexOf("/b/") + 3)}"; -// } -// else if (p.Success) -// { -// if (m.Success) -// return $"b={mapLink.Substring(mapLink.IndexOf("?b=") + 3, mapLink.IndexOf("&m") - (mapLink.IndexOf("?b=") + 3))}"; -// else -// return $"b={mapLink.Substring(mapLink.IndexOf("?b=") + 3)}"; -// } -// else -// { -// return $"s={mapLink}"; //just a default incase an ID number was provided by itself (non-url)? -// } -// } + } + } -// private static int ResolveGameMode(string mode) -// { -// switch (mode.ToLower()) -// { -// case "std": -// case "standard": -// return 0; -// case "taiko": -// return 1; -// case "ctb": -// case "catchthebeat": -// return 2; -// case "mania": -// case "osu!mania": -// return 3; -// default: -// return 0; -// } -// } + //https://osu.ppy.sh/wiki/Accuracy + private static Double CalculateAcc(JToken play, int mode) + { + if (mode == 0) + { + var hitPoints = Double.Parse($"{play["count50"]}") * 50 + Double.Parse($"{play["count100"]}") * 100 + Double.Parse($"{play["count300"]}") * 300; + var totalHits = Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countmiss"]}"); + totalHits *= 300; + return Math.Round(hitPoints / totalHits * 100, 2); + } + else if (mode == 1) + { + var hitPoints = Double.Parse($"{play["countmiss"]}") * 0 + Double.Parse($"{play["count100"]}") * 0.5 + Double.Parse($"{play["count300"]}") * 1; + var totalHits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}"); + hitPoints *= 300; + totalHits *= 300; + return Math.Round(hitPoints / totalHits * 100, 2); + } + else if (mode == 2) + { + var fruitsCaught = Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}"); + var totalFruits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countkatu"]}"); + return Math.Round(fruitsCaught / totalFruits * 100, 2); + } + else + { + var hitPoints = Double.Parse($"{play["count50"]}") * 50 + Double.Parse($"{play["count100"]}") * 100 + Double.Parse($"{play["countkatu"]}") * 200 + (Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countgeki"]}")) * 300; + var totalHits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["countkatu"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countgeki"]}"); + totalHits *= 300; + return Math.Round(hitPoints / totalHits * 100, 2); + } + } -// //https://github.com/ppy/osu-api/wiki#mods -// private static string ResolveMods(int mods) -// { -// var modString = $"+"; + private static string ResolveMap(string mapLink) + { + Match s = new Regex(@"osu.ppy.sh\/s\/", RegexOptions.IgnoreCase).Match(mapLink); + Match b = new Regex(@"osu.ppy.sh\/b\/", RegexOptions.IgnoreCase).Match(mapLink); + Match p = new Regex(@"osu.ppy.sh\/p\/", RegexOptions.IgnoreCase).Match(mapLink); + Match m = new Regex(@"&m=", RegexOptions.IgnoreCase).Match(mapLink); + if (s.Success) + { + var mapId = mapLink.Substring(mapLink.IndexOf("/s/") + 3); + return $"s={mapId}"; + } + else if (b.Success) + { + if (m.Success) + return $"b={mapLink.Substring(mapLink.IndexOf("/b/") + 3, mapLink.IndexOf("&m") - (mapLink.IndexOf("/b/") + 3))}"; + else + return $"b={mapLink.Substring(mapLink.IndexOf("/b/") + 3)}"; + } + else if (p.Success) + { + if (m.Success) + return $"b={mapLink.Substring(mapLink.IndexOf("?b=") + 3, mapLink.IndexOf("&m") - (mapLink.IndexOf("?b=") + 3))}"; + else + return $"b={mapLink.Substring(mapLink.IndexOf("?b=") + 3)}"; + } + else + { + return $"s={mapLink}"; //just a default incase an ID number was provided by itself (non-url)? + } + } -// if (IsBitSet(mods, 0)) -// modString += "NF"; -// if (IsBitSet(mods, 1)) -// modString += "EZ"; -// if (IsBitSet(mods, 8)) -// modString += "HT"; + private static int ResolveGameMode(string mode) + { + switch (mode.ToLower()) + { + case "std": + case "standard": + return 0; + case "taiko": + return 1; + case "ctb": + case "catchthebeat": + return 2; + case "mania": + case "osu!mania": + return 3; + default: + return 0; + } + } -// if (IsBitSet(mods, 3)) -// modString += "HD"; -// if (IsBitSet(mods, 4)) -// modString += "HR"; -// if (IsBitSet(mods, 6) && !IsBitSet(mods, 9)) -// modString += "DT"; -// if (IsBitSet(mods, 9)) -// modString += "NC"; -// if (IsBitSet(mods, 10)) -// modString += "FL"; + //https://github.com/ppy/osu-api/wiki#mods + private static string ResolveMods(int mods) + { + var modString = $"+"; -// if (IsBitSet(mods, 5)) -// modString += "SD"; -// if (IsBitSet(mods, 14)) -// modString += "PF"; + if (IsBitSet(mods, 0)) + modString += "NF"; + if (IsBitSet(mods, 1)) + modString += "EZ"; + if (IsBitSet(mods, 8)) + modString += "HT"; -// if (IsBitSet(mods, 7)) -// modString += "RX"; -// if (IsBitSet(mods, 11)) -// modString += "AT"; -// if (IsBitSet(mods, 12)) -// modString += "SO"; -// return modString; -// } + if (IsBitSet(mods, 3)) + modString += "HD"; + if (IsBitSet(mods, 4)) + modString += "HR"; + if (IsBitSet(mods, 6) && !IsBitSet(mods, 9)) + modString += "DT"; + if (IsBitSet(mods, 9)) + modString += "NC"; + if (IsBitSet(mods, 10)) + modString += "FL"; -// private static bool IsBitSet(int mods, int pos) -// { -// return (mods & (1 << pos)) != 0; -// } + if (IsBitSet(mods, 5)) + modString += "SD"; + if (IsBitSet(mods, 14)) + modString += "PF"; -// } -//} + if (IsBitSet(mods, 7)) + modString += "RX"; + if (IsBitSet(mods, 11)) + modString += "AT"; + if (IsBitSet(mods, 12)) + modString += "SO"; + return modString; + } + + private static bool IsBitSet(int mods, int pos) => + (mods & (1 << pos)) != 0; + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs b/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs index 9b915794..529d7fe3 100644 --- a/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs @@ -154,7 +154,7 @@ // .AddCheck(SimpleCheckers.ManageServer()) // .Do(async e => // { -// var stream = e.GetArg("username")?.Trim(); +// var stream = username?.Trim(); // if (string.IsNullOrWhiteSpace(stream)) // return; // try @@ -183,7 +183,7 @@ // .Parameter("username", ParameterType.Unparsed) // .Do(async e => // { -// var stream = e.GetArg("username")?.Trim(); +// var stream = username?.Trim(); // if (string.IsNullOrWhiteSpace(stream)) // return; // try @@ -212,7 +212,7 @@ // .Parameter("username", ParameterType.Unparsed) // .Do(async e => // { -// var stream = e.GetArg("username")?.Trim(); +// var stream = username?.Trim(); // if (string.IsNullOrWhiteSpace(stream)) // return; // try @@ -241,7 +241,7 @@ // .Parameter("username", ParameterType.Unparsed) // .Do(async e => // { -// var username = e.GetArg("username")?.ToLower().Trim(); +// var username = username?.ToLower().Trim(); // if (string.IsNullOrWhiteSpace(username)) // return; @@ -298,7 +298,7 @@ // private Func TrackStream(StreamNotificationConfig.StreamType type) => // async e => // { -// var username = e.GetArg("username")?.ToLowerInvariant(); +// var username = username?.ToLowerInvariant(); // if (string.IsNullOrWhiteSpace(username)) // return; diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index f8a0bec1..ea571a23 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -8,7 +8,6 @@ using System.Net.Http; using NadekoBot.Services; using System.Threading.Tasks; using NadekoBot.Attributes; -using NadekoBot.Extensions; using System.Text.RegularExpressions; using System.Net; using Discord.WebSocket; @@ -206,7 +205,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 //public async Task Hearthstone(IMessage imsg, [Remainder] string name = null) //{ // var channel = imsg.Channel as ITextChannel; - // var arg = e.GetArg("name"); + // var arg = name; // if (string.IsNullOrWhiteSpace(arg)) // { // await channel.SendMessageAsync("πŸ’’ Please enter a card name to search for.").ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Trello/Trello.cs b/src/NadekoBot/Modules/Trello/Trello.cs index b62c9a55..820b0379 100644 --- a/src/NadekoBot/Modules/Trello/Trello.cs +++ b/src/NadekoBot/Modules/Trello/Trello.cs @@ -26,7 +26,7 @@ // TrelloConfiguration.Deserializer = serializer; // TrelloConfiguration.JsonFactory = new ManateeFactory(); // TrelloConfiguration.RestClientProvider = new Manatee.Trello.WebApi.WebApiClientProvider(); -// TrelloAuthorization.Default.AppKey = NadekoBot.Creds.TrelloAppKey; +// TrelloAuthorization.Default.AppKey = NadekoBot.Credentials.TrelloAppKey; // //TrelloAuthorization.Default.UserToken = "[your user token]"; // Discord.Channel bound = null; @@ -80,7 +80,7 @@ // try // { // bound = e.Channel; -// board = new Board(e.GetArg("board_id").Trim()); +// board = new Board(board_id.Trim()); // board.Refresh(); // await channel.SendMessageAsync("Successfully bound to this channel and board " + board.Name); // t.Start(); @@ -121,15 +121,15 @@ // .Do(async e => // { // if (!NadekoBot.IsOwner(imsg.Author.Id)) return; -// if (bound == null || board == null || bound != e.Channel || e.GetArg("list_name") == null) return; +// if (bound == null || board == null || bound != e.Channel || list_name == null) return; // int num; -// var success = int.TryParse(e.GetArg("list_name"), out num); +// var success = int.TryParse(list_name, out num); // List list = null; // if (success && num <= board.Lists.Count() && num > 0) // list = board.Lists[num - 1]; // else -// list = board.Lists.FirstOrDefault(l => l.Name == e.GetArg("list_name")); +// list = board.Lists.FirstOrDefault(l => l.Name == list_name); // if (list != null) diff --git a/src/NadekoBot/Modules/Utility/Commands/Remind.cs b/src/NadekoBot/Modules/Utility/Commands/Remind.cs index be814fea..f6c67748 100644 --- a/src/NadekoBot/Modules/Utility/Commands/Remind.cs +++ b/src/NadekoBot/Modules/Utility/Commands/Remind.cs @@ -94,7 +94,7 @@ // .Parameter("message", ParameterType.Unparsed) // .Do(async e => // { -// var meorchStr = e.GetArg("meorchannel").ToUpperInvariant(); +// var meorchStr = meorchannel.ToUpperInvariant(); // Channel ch; // bool isPrivate = false; // if (meorchStr == "ME") @@ -117,7 +117,7 @@ // return; // } -// var timeStr = e.GetArg("time"); +// var timeStr = time; // var m = regex.Match(timeStr); @@ -167,7 +167,7 @@ // ChannelId = (long)ch.Id, // IsPrivate = isPrivate, // When = time, -// Message = e.GetArg("message"), +// Message = message, // UserId = (long)imsg.Author.Id, // ServerId = (long)e.Server.Id // }; @@ -175,7 +175,7 @@ // reminders.Add(StartNewReminder(rem)); -// await channel.SendMessageAsync($"⏰ I will remind \"{ch.Name}\" to \"{e.GetArg("message").ToString()}\" in {output}. ({time:d.M.yyyy.} at {time:HH:mm})").ConfigureAwait(false); +// await channel.SendMessageAsync($"⏰ I will remind \"{ch.Name}\" to \"{message.ToString()}\" in {output}. ({time:d.M.yyyy.} at {time:HH:mm})").ConfigureAwait(false); // }); // cgb.CreateCommand(Module.Prefix + "remindmsg") // .Description("Sets message for when the remind is triggered. " + @@ -185,7 +185,7 @@ // .AddCheck(SimpleCheckers.OwnerOnly()) // .Do(async e => // { -// var arg = e.GetArg("msg")?.Trim(); +// var arg = msg?.Trim(); // if (string.IsNullOrWhiteSpace(arg)) // return; diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index 4b0f9c3c..c20aa1fb 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -23,7 +23,7 @@ namespace NadekoBot public static Localization Localizer { get; private set; } public static BotCredentials Credentials { get; private set; } - private static YoutubeService Youtube { get; set; } + private static GoogleApiService Youtube { get; set; } public static StatsService Stats { get; private set; } public async Task RunAsync(string[] args) @@ -43,7 +43,7 @@ namespace NadekoBot Commands = new CommandService(); Config = new BotConfiguration(); Localizer = new Localization(); - Youtube = new YoutubeService(); + Youtube = new GoogleApiService(); Stats = new StatsService(Client); _log = LogManager.GetCurrentClassLogger(); diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 4128fe38..d9265ce3 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -14,6 +15,13 @@ namespace NadekoBot.Extensions { public static class Extensions { + public static void AddFakeHeaders(this HttpClient http) + { + http.DefaultRequestHeaders.Clear(); + http.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1"); + http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); + } + public static async Task SendMessageAsync(this IGuildUser user, string message, bool isTTS = false) => await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(message, isTTS).ConfigureAwait(false); diff --git a/src/NadekoBot/_Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/_Modules/CustomReactions/CustomReactions.cs index d7c6008d..af36cd94 100644 --- a/src/NadekoBot/_Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/_Modules/CustomReactions/CustomReactions.cs @@ -32,7 +32,7 @@ namespace NadekoBot.Modules.CustomReactions } }, {new Regex("%mention%"), (e,m) => NadekoBot.BotMention }, {new Regex("%user%"), (e,m) => imsg.Author.Mention }, - {new Regex("%target%"), (e,m) => e.GetArg("args")?.Trim() ?? "" }, + {new Regex("%target%"), (e,m) => args?.Trim() ?? "" }, }; } diff --git a/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs b/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs index ed829adb..9cab3fcf 100644 --- a/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs +++ b/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs @@ -18,10 +18,10 @@ namespace NadekoBot.Modules.Music.Classes { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); - if (string.IsNullOrWhiteSpace(NadekoBot.Creds.SoundCloudClientID)) - throw new ArgumentNullException(nameof(NadekoBot.Creds.SoundCloudClientID)); + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.SoundCloudClientID)) + throw new ArgumentNullException(nameof(NadekoBot.Credentials.SoundCloudClientID)); - var response = await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={url}&client_id={NadekoBot.Creds.SoundCloudClientID}").ConfigureAwait(false); + var response = await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={url}&client_id={NadekoBot.Credentials.SoundCloudClientID}").ConfigureAwait(false); var responseObj = Newtonsoft.Json.JsonConvert.DeserializeObject(response); if (responseObj?.Kind != "track") @@ -37,10 +37,10 @@ namespace NadekoBot.Modules.Music.Classes { if (string.IsNullOrWhiteSpace(query)) throw new ArgumentNullException(nameof(query)); - if (string.IsNullOrWhiteSpace(NadekoBot.Creds.SoundCloudClientID)) - throw new ArgumentNullException(nameof(NadekoBot.Creds.SoundCloudClientID)); + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.SoundCloudClientID)) + throw new ArgumentNullException(nameof(NadekoBot.Credentials.SoundCloudClientID)); - var response = await http.GetStringAsync($"http://api.soundcloud.com/tracks?q={Uri.EscapeDataString(query)}&client_id={NadekoBot.Creds.SoundCloudClientID}").ConfigureAwait(false); + var response = await http.GetStringAsync($"http://api.soundcloud.com/tracks?q={Uri.EscapeDataString(query)}&client_id={NadekoBot.Credentials.SoundCloudClientID}").ConfigureAwait(false); var responseObj = JsonConvert.DeserializeObject(response).Where(s => s.Streamable).FirstOrDefault(); if (responseObj?.Kind != "track") @@ -62,7 +62,7 @@ namespace NadekoBot.Modules.Music.Classes [JsonProperty("permalink_url")] public string TrackLink { get; set; } = ""; [JsonIgnore] - public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Creds.SoundCloudClientID}"; + public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Credentials.SoundCloudClientID}"; } public class SoundCloudUser { diff --git a/src/NadekoBot/_Modules/Music/MusicModule.cs b/src/NadekoBot/_Modules/Music/MusicModule.cs index ea9d136e..49308c94 100644 --- a/src/NadekoBot/_Modules/Music/MusicModule.cs +++ b/src/NadekoBot/_Modules/Music/MusicModule.cs @@ -105,7 +105,7 @@ namespace NadekoBot.Modules.Music .Parameter("query", ParameterType.Unparsed) .Do(async e => { - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, e.GetArg("query")).ConfigureAwait(false); + await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, query).ConfigureAwait(false); if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages) { await Task.Delay(10000).ConfigureAwait(false); @@ -120,7 +120,7 @@ namespace NadekoBot.Modules.Music .Parameter("query", ParameterType.Unparsed) .Do(async e => { - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, e.GetArg("query"), musicType: MusicType.Soundcloud).ConfigureAwait(false); + await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false); if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages) { await Task.Delay(10000).ConfigureAwait(false); @@ -142,7 +142,7 @@ namespace NadekoBot.Modules.Music } int page; - if (!int.TryParse(e.GetArg("page"), out page) || page <= 0) + if (!int.TryParse(page, out page) || page <= 0) { page = 1; } @@ -192,7 +192,7 @@ namespace NadekoBot.Modules.Music return; if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) return; - var arg = e.GetArg("val"); + var arg = val; int volume; if (!int.TryParse(arg, out volume)) { @@ -210,7 +210,7 @@ namespace NadekoBot.Modules.Music .Parameter("val", ParameterType.Required) .Do(async e => { - var arg = e.GetArg("val"); + var arg = val; float volume; if (!float.TryParse(arg, out volume) || volume < 0 || volume > 100) { @@ -285,7 +285,7 @@ namespace NadekoBot.Modules.Music .Parameter("playlist", ParameterType.Unparsed) .Do(async e => { - var arg = e.GetArg("playlist"); + var arg = playlist; if (string.IsNullOrWhiteSpace(arg)) return; if (imsg.Author.VoiceChannel?.Server != e.Server) @@ -328,12 +328,12 @@ namespace NadekoBot.Modules.Music .Parameter("pl", ParameterType.Unparsed) .Do(async e => { - var pl = e.GetArg("pl")?.Trim(); + var pl = pl?.Trim(); if (string.IsNullOrWhiteSpace(pl)) return; - var scvids = JObject.Parse(await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Creds.SoundCloudClientID}").ConfigureAwait(false))["tracks"].ToObject(); + var scvids = JObject.Parse(await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Credentials.SoundCloudClientID}").ConfigureAwait(false))["tracks"].ToObject(); await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false); MusicPlayer mp; @@ -364,7 +364,7 @@ namespace NadekoBot.Modules.Music .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => { - var arg = e.GetArg("directory"); + var arg = directory; if (string.IsNullOrWhiteSpace(arg)) return; try @@ -398,7 +398,7 @@ namespace NadekoBot.Modules.Music await channel.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false); return; } - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, e.GetArg("radio_link"), musicType: MusicType.Radio).ConfigureAwait(false); + await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false); if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages) { await Task.Delay(10000).ConfigureAwait(false); @@ -413,10 +413,10 @@ namespace NadekoBot.Modules.Music .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => { - var arg = e.GetArg("path"); + var arg = path; if (string.IsNullOrWhiteSpace(arg)) return; - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, e.GetArg("path"), musicType: MusicType.Local).ConfigureAwait(false); + await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "move") @@ -437,7 +437,7 @@ namespace NadekoBot.Modules.Music .Parameter("num", ParameterType.Required) .Do(async e => { - var arg = e.GetArg("num"); + var arg = num; MusicPlayer musicPlayer; if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) { @@ -475,7 +475,7 @@ namespace NadekoBot.Modules.Music { return; } - var fromto = e.GetArg("fromto").Trim(); + var fromto = fromto.Trim(); var fromtoArr = fromto.Split('>'); int n1; @@ -512,7 +512,7 @@ namespace NadekoBot.Modules.Music return; } - var sizeStr = e.GetArg("size")?.Trim(); + var sizeStr = size?.Trim(); uint size = 0; if (string.IsNullOrWhiteSpace(sizeStr) || !uint.TryParse(sizeStr, out size)) { @@ -576,7 +576,7 @@ namespace NadekoBot.Modules.Music .Parameter("name", ParameterType.Unparsed) .Do(async e => { - var name = e.GetArg("name")?.Trim(); + var name = name?.Trim(); if (string.IsNullOrWhiteSpace(name) || name.Length > 20 || @@ -636,7 +636,7 @@ namespace NadekoBot.Modules.Music await textCh.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.").ConfigureAwait(false); return; } - var name = e.GetArg("name")?.Trim().ToLowerInvariant(); + var name = name?.Trim().ToLowerInvariant(); if (string.IsNullOrWhiteSpace(name)) return; @@ -690,7 +690,7 @@ namespace NadekoBot.Modules.Music .Do(e => { int num = 0; - int.TryParse(e.GetArg("num"), out num); + int.TryParse(num, out num); if (num < 0) return; var result = DbHandler.Instance.GetPlaylistData(num); @@ -706,7 +706,7 @@ namespace NadekoBot.Modules.Music .Parameter("pl", ParameterType.Required) .Do(async e => { - var pl = e.GetArg("pl").Trim().Split('-')[1]; + var pl = pl.Trim().Split('-')[1]; if (string.IsNullOrWhiteSpace(pl)) return; var plnum = int.Parse(pl); @@ -722,7 +722,7 @@ namespace NadekoBot.Modules.Music .Parameter("time") .Do(async e => { - var skipToStr = e.GetArg("time")?.Trim(); + var skipToStr = time?.Trim(); MusicPlayer musicPlayer; if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return; @@ -764,7 +764,7 @@ namespace NadekoBot.Modules.Music if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return; int index; - string arg = e.GetArg("index")?.Trim(); + string arg = index?.Trim(); if (!string.IsNullOrEmpty(arg) && int.TryParse(arg, out index)) { diff --git a/src/NadekoBot/_Modules/Permissions/Commands/FilterInvitesCommand.cs b/src/NadekoBot/_Modules/Permissions/Commands/FilterInvitesCommand.cs index 8109ca2b..7b9b1dc1 100644 --- a/src/NadekoBot/_Modules/Permissions/Commands/FilterInvitesCommand.cs +++ b/src/NadekoBot/_Modules/Permissions/Commands/FilterInvitesCommand.cs @@ -62,8 +62,8 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var chanStr = e.GetArg("channel"); + var state = PermissionHelper.ValidateBool(bool); + var chanStr = channel; if (chanStr?.ToLowerInvariant().Trim() != "all") { @@ -101,7 +101,7 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var state = PermissionHelper.ValidateBool(bool); await PermissionsHandler.SetServerFilterInvitesPermission(e.Server, state).ConfigureAwait(false); await channel.SendMessageAsync($"Invite Filter has been **{(state ? "enabled" : "disabled")}** for this server.") .ConfigureAwait(false); diff --git a/src/NadekoBot/_Modules/Permissions/Commands/FilterWordsCommand.cs b/src/NadekoBot/_Modules/Permissions/Commands/FilterWordsCommand.cs index deb3920b..781faa93 100644 --- a/src/NadekoBot/_Modules/Permissions/Commands/FilterWordsCommand.cs +++ b/src/NadekoBot/_Modules/Permissions/Commands/FilterWordsCommand.cs @@ -60,8 +60,8 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var chanStr = e.GetArg("channel")?.ToLowerInvariant().Trim(); + var state = PermissionHelper.ValidateBool(bool); + var chanStr = channel?.ToLowerInvariant().Trim(); if (chanStr != "all") { @@ -95,7 +95,7 @@ namespace NadekoBot.Modules.Permissions { try { - var word = e.GetArg("word"); + var word = word; if (string.IsNullOrWhiteSpace(word)) return; await PermissionsHandler.AddFilteredWord(e.Server, word.ToLowerInvariant().Trim()).ConfigureAwait(false); @@ -117,7 +117,7 @@ namespace NadekoBot.Modules.Permissions { try { - var word = e.GetArg("word"); + var word = word; if (string.IsNullOrWhiteSpace(word)) return; await PermissionsHandler.RemoveFilteredWord(e.Server, word.ToLowerInvariant().Trim()).ConfigureAwait(false); @@ -158,7 +158,7 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var state = PermissionHelper.ValidateBool(bool); await PermissionsHandler.SetServerWordPermission(e.Server, state).ConfigureAwait(false); await channel.SendMessageAsync($"Word filtering has been **{(state ? "enabled" : "disabled")}** on this server.") .ConfigureAwait(false); diff --git a/src/NadekoBot/_Modules/Permissions/PermissionsModule.cs b/src/NadekoBot/_Modules/Permissions/PermissionsModule.cs index 37374687..b0cdbe87 100644 --- a/src/NadekoBot/_Modules/Permissions/PermissionsModule.cs +++ b/src/NadekoBot/_Modules/Permissions/PermissionsModule.cs @@ -37,13 +37,13 @@ namespace NadekoBot.Modules.Permissions .Parameter("role", ParameterType.Unparsed) .Do(async e => { - if (string.IsNullOrWhiteSpace(e.GetArg("role"))) + if (string.IsNullOrWhiteSpace(role)) { await channel.SendMessageAsync($"Current permissions role is `{PermissionsHandler.GetServerPermissionsRoleName(e.Server)}`").ConfigureAwait(false); return; } - var arg = e.GetArg("role"); + var arg = role; Discord.Role role = null; try { @@ -65,7 +65,7 @@ namespace NadekoBot.Modules.Permissions .Parameter("from_to", ParameterType.Unparsed) .Do(async e => { - var arg = e.GetArg("from_to")?.Trim(); + var arg = from_to?.Trim(); if (string.IsNullOrWhiteSpace(arg) || !arg.Contains('~')) return; var args = arg.Split('~').Select(a => a.Trim()).ToArray(); @@ -93,7 +93,7 @@ namespace NadekoBot.Modules.Permissions .Parameter("from_to", ParameterType.Unparsed) .Do(async e => { - var arg = e.GetArg("from_to")?.Trim(); + var arg = from_to?.Trim(); if (string.IsNullOrWhiteSpace(arg) || !arg.Contains('~')) return; var args = arg.Split('~').Select(a => a.Trim()).ToArray(); @@ -121,7 +121,7 @@ namespace NadekoBot.Modules.Permissions .Parameter("from_to", ParameterType.Unparsed) .Do(async e => { - var arg = e.GetArg("from_to")?.Trim(); + var arg = from_to?.Trim(); if (string.IsNullOrWhiteSpace(arg) || !arg.Contains('~')) return; var args = arg.Split('~').Select(a => a.Trim()).ToArray(); @@ -150,7 +150,7 @@ namespace NadekoBot.Modules.Permissions .Parameter("arg", ParameterType.Required) .Do(async e => { - var arg = e.GetArg("arg"); + var arg = arg; var val = PermissionHelper.ValidateBool(arg); await PermissionsHandler.SetVerbosity(e.Server, val).ConfigureAwait(false); await channel.SendMessageAsync($"Verbosity set to {val}.").ConfigureAwait(false); @@ -173,7 +173,7 @@ namespace NadekoBot.Modules.Permissions .Parameter("role", ParameterType.Unparsed) .Do(async e => { - var arg = e.GetArg("role"); + var arg = role; var role = e.Server.EveryoneRole; if (!string.IsNullOrWhiteSpace(arg)) try @@ -199,7 +199,7 @@ namespace NadekoBot.Modules.Permissions .Parameter("channel", ParameterType.Unparsed) .Do(async e => { - var arg = e.GetArg("channel"); + var arg = channel; var channel = e.Channel; if (!string.IsNullOrWhiteSpace(arg)) try @@ -225,10 +225,10 @@ namespace NadekoBot.Modules.Permissions .Do(async e => { var user = imsg.Author; - if (!string.IsNullOrWhiteSpace(e.GetArg("user"))) + if (!string.IsNullOrWhiteSpace(user)) try { - user = PermissionHelper.ValidateUser(e.Server, e.GetArg("user")); + user = PermissionHelper.ValidateUser(e.Server, user); } catch (Exception ex) { @@ -251,8 +251,8 @@ namespace NadekoBot.Modules.Permissions { try { - var module = PermissionHelper.ValidateModule(e.GetArg("module")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var module = PermissionHelper.ValidateModule(module); + var state = PermissionHelper.ValidateBool(bool); await PermissionsHandler.SetServerModulePermission(e.Server, module, state).ConfigureAwait(false); await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false); @@ -275,8 +275,8 @@ namespace NadekoBot.Modules.Permissions { try { - var command = PermissionHelper.ValidateCommand(e.GetArg("command")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var command = PermissionHelper.ValidateCommand(command); + var state = PermissionHelper.ValidateBool(bool); await PermissionsHandler.SetServerCommandPermission(e.Server, command, state).ConfigureAwait(false); await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false); @@ -300,10 +300,10 @@ namespace NadekoBot.Modules.Permissions { try { - var module = PermissionHelper.ValidateModule(e.GetArg("module")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var module = PermissionHelper.ValidateModule(module); + var state = PermissionHelper.ValidateBool(bool); - if (e.GetArg("role")?.ToLower() == "all") + if (role?.ToLower() == "all") { foreach (var role in e.Server.Roles) { @@ -313,7 +313,7 @@ namespace NadekoBot.Modules.Permissions } else { - var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role")); + var role = PermissionHelper.ValidateRole(e.Server, role); await PermissionsHandler.SetRoleModulePermission(role, module, state).ConfigureAwait(false); await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false); @@ -338,10 +338,10 @@ namespace NadekoBot.Modules.Permissions { try { - var command = PermissionHelper.ValidateCommand(e.GetArg("command")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var command = PermissionHelper.ValidateCommand(command); + var state = PermissionHelper.ValidateBool(bool); - if (e.GetArg("role")?.ToLower() == "all") + if (role?.ToLower() == "all") { foreach (var role in e.Server.Roles) { @@ -351,7 +351,7 @@ namespace NadekoBot.Modules.Permissions } else { - var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role")); + var role = PermissionHelper.ValidateRole(e.Server, role); await PermissionsHandler.SetRoleCommandPermission(role, command, state).ConfigureAwait(false); await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false); @@ -376,9 +376,9 @@ namespace NadekoBot.Modules.Permissions { try { - var module = PermissionHelper.ValidateModule(e.GetArg("module")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var channelArg = e.GetArg("channel"); + var module = PermissionHelper.ValidateModule(module); + var state = PermissionHelper.ValidateBool(bool); + var channelArg = channel; if (channelArg?.ToLower() == "all") { foreach (var channel in e.Server.TextChannels) @@ -419,10 +419,10 @@ namespace NadekoBot.Modules.Permissions { try { - var command = PermissionHelper.ValidateCommand(e.GetArg("command")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var command = PermissionHelper.ValidateCommand(command); + var state = PermissionHelper.ValidateBool(bool); - if (e.GetArg("channel")?.ToLower() == "all") + if (channel?.ToLower() == "all") { foreach (var channel in e.Server.TextChannels) { @@ -432,7 +432,7 @@ namespace NadekoBot.Modules.Permissions } else { - var channel = PermissionHelper.ValidateChannel(e.Server, e.GetArg("channel")); + var channel = PermissionHelper.ValidateChannel(e.Server, channel); await PermissionsHandler.SetChannelCommandPermission(channel, command, state).ConfigureAwait(false); await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false); @@ -457,9 +457,9 @@ namespace NadekoBot.Modules.Permissions { try { - var module = PermissionHelper.ValidateModule(e.GetArg("module")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var user = PermissionHelper.ValidateUser(e.Server, e.GetArg("user")); + var module = PermissionHelper.ValidateModule(module); + var state = PermissionHelper.ValidateBool(bool); + var user = PermissionHelper.ValidateUser(e.Server, user); await PermissionsHandler.SetUserModulePermission(user, module, state).ConfigureAwait(false); await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**.").ConfigureAwait(false); @@ -483,9 +483,9 @@ namespace NadekoBot.Modules.Permissions { try { - var command = PermissionHelper.ValidateCommand(e.GetArg("command")); - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var user = PermissionHelper.ValidateUser(e.Server, e.GetArg("user")); + var command = PermissionHelper.ValidateCommand(command); + var state = PermissionHelper.ValidateBool(bool); + var user = PermissionHelper.ValidateUser(e.Server, user); await PermissionsHandler.SetUserCommandPermission(user, command, state).ConfigureAwait(false); await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**.").ConfigureAwait(false); @@ -507,7 +507,7 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); + var state = PermissionHelper.ValidateBool(bool); foreach (var module in NadekoBot.Client.GetService().Modules) { @@ -533,8 +533,8 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var module = PermissionHelper.ValidateModule(e.GetArg("module")); + var state = PermissionHelper.ValidateBool(bool); + var module = PermissionHelper.ValidateModule(module); foreach (var command in NadekoBot.Client.GetService().AllCommands.Where(c => c.Category == module)) { @@ -560,8 +560,8 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var chArg = e.GetArg("channel"); + var state = PermissionHelper.ValidateBool(bool); + var chArg = channel; var channel = string.IsNullOrWhiteSpace(chArg) ? e.Channel : PermissionHelper.ValidateChannel(e.Server, chArg); foreach (var module in NadekoBot.Client.GetService().Modules) { @@ -589,9 +589,9 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var module = PermissionHelper.ValidateModule(e.GetArg("module")); - var channel = PermissionHelper.ValidateChannel(e.Server, e.GetArg("channel")); + var state = PermissionHelper.ValidateBool(bool); + var module = PermissionHelper.ValidateModule(module); + var channel = PermissionHelper.ValidateChannel(e.Server, channel); foreach (var command in NadekoBot.Client.GetService().AllCommands.Where(c => c.Category == module)) { await PermissionsHandler.SetChannelCommandPermission(channel, command.Text, state).ConfigureAwait(false); @@ -616,8 +616,8 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role")); + var state = PermissionHelper.ValidateBool(bool); + var role = PermissionHelper.ValidateRole(e.Server, role); foreach (var module in NadekoBot.Client.GetService().Modules) { await PermissionsHandler.SetRoleModulePermission(role, module.Name, state).ConfigureAwait(false); @@ -644,9 +644,9 @@ namespace NadekoBot.Modules.Permissions { try { - var state = PermissionHelper.ValidateBool(e.GetArg("bool")); - var module = PermissionHelper.ValidateModule(e.GetArg("module")); - if (e.GetArg("role")?.ToLower() == "all") + var state = PermissionHelper.ValidateBool(bool); + var module = PermissionHelper.ValidateModule(module); + if (role?.ToLower() == "all") { foreach (var role in e.Server.Roles) { @@ -659,7 +659,7 @@ namespace NadekoBot.Modules.Permissions } else { - var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role")); + var role = PermissionHelper.ValidateRole(e.Server, role); foreach (var command in NadekoBot.Client.GetService().AllCommands.Where(c => c.Category == module)) { @@ -755,7 +755,7 @@ namespace NadekoBot.Modules.Permissions { await Task.Run(async () => { - var arg = e.GetArg("server")?.Trim(); + var arg = server?.Trim(); if (string.IsNullOrWhiteSpace(arg)) return; var server = NadekoBot.Client.Servers.FirstOrDefault(s => s.Id.ToString() == arg) ?? @@ -788,8 +788,8 @@ namespace NadekoBot.Modules.Permissions { try { - var command = PermissionHelper.ValidateCommand(e.GetArg("command")); - var secsStr = e.GetArg("secs").Trim(); + var command = PermissionHelper.ValidateCommand(command); + var secsStr = secs.Trim(); int secs; if (!int.TryParse(secsStr, out secs) || secs < 0 || secs > 3600) throw new ArgumentOutOfRangeException("secs", "Invalid second parameter. (Must be a number between 0 and 3600)"); From c218d1da968047a857d54072cf9c0a7fb33f8444 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Mon, 22 Aug 2016 00:37:39 +0200 Subject: [PATCH 3/4] Replacements. Converted music, not tested. --- .../Administration/AdministrationModule.cs | 60 +- .../Administration/Commands/AutoAssignRole.cs | 2 +- .../Commands/RatelimitCommand.cs | 4 +- .../Administration/Commands/SelfCommands.cs | 2 +- .../Modules/ClashOfClans/ClashOfClans.cs | 22 +- .../Modules/Gambling/Commands/AnimalRacing.cs | 4 +- .../Gambling/Commands/DiceRollCommand.cs | 4 +- src/NadekoBot/Modules/Gambling/Gambling.cs | 14 +- .../Modules/Games/Commands/LeetCommands.cs | 2 +- .../Modules/Games/Commands/PollCommands.cs | 4 +- .../Modules/Games/Commands/TriviaCommands.cs | 6 +- src/NadekoBot/Modules/Games/Games.cs | 8 +- src/NadekoBot/Modules/Help/Help.cs | 10 +- .../Music/Classes/MusicControls.cs | 20 +- .../Music/Classes/PlaylistFullException.cs | 0 .../Music/Classes/Song.cs | 17 +- .../Music/Classes/SongBuffer.cs | 0 .../Music/Classes/SoundCloud.cs | 26 +- src/NadekoBot/Modules/Music/MusicModule.cs | 724 ++++++++++++++ src/NadekoBot/Modules/NSFW/NSFW.cs | 16 +- src/NadekoBot/Modules/Pokemon/Pokemon.cs | 2 +- .../Searches/Commands/AnimeSearchCommands.cs | 4 +- .../Modules/Searches/Commands/JokeCommands.cs | 10 +- .../Modules/Searches/Commands/LoLCommands.cs | 2 +- .../Searches/Commands/MemegenCommands.cs | 4 +- .../Modules/Searches/Commands/OsuCommands.cs | 6 +- .../Commands/PokemonSearchCommands.cs | 4 +- src/NadekoBot/Modules/Searches/Searches.cs | 44 +- .../Modules/Translator/Translator.cs | 4 +- src/NadekoBot/Modules/Utility/Utility.cs | 6 +- src/NadekoBot/NadekoBot.cs | 6 +- src/NadekoBot/Services/IGoogleApiService.cs | 7 +- src/NadekoBot/Services/Impl/BotCredentials.cs | 9 +- .../Services/Impl/GoogleApiService.cs | 38 +- src/NadekoBot/_Extensions/Extensions.cs | 2 + .../_Modules/Music/Classes/PoopyBuffer.cs | 131 --- src/NadekoBot/_Modules/Music/MusicModule.cs | 900 ------------------ src/NadekoBot/project.json | 12 +- src/NadekoBot/project.lock.json | 82 +- 39 files changed, 1027 insertions(+), 1191 deletions(-) rename src/NadekoBot/{_Modules => Modules}/Music/Classes/MusicControls.cs (92%) rename src/NadekoBot/{_Modules => Modules}/Music/Classes/PlaylistFullException.cs (100%) rename src/NadekoBot/{_Modules => Modules}/Music/Classes/Song.cs (95%) rename src/NadekoBot/{_Modules => Modules}/Music/Classes/SongBuffer.cs (100%) rename src/NadekoBot/{_Modules => Modules}/Music/Classes/SoundCloud.cs (86%) create mode 100644 src/NadekoBot/Modules/Music/MusicModule.cs delete mode 100644 src/NadekoBot/_Modules/Music/Classes/PoopyBuffer.cs delete mode 100644 src/NadekoBot/_Modules/Music/MusicModule.cs diff --git a/src/NadekoBot/Modules/Administration/AdministrationModule.cs b/src/NadekoBot/Modules/Administration/AdministrationModule.cs index 387d3d78..1d849a3b 100644 --- a/src/NadekoBot/Modules/Administration/AdministrationModule.cs +++ b/src/NadekoBot/Modules/Administration/AdministrationModule.cs @@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task Restart(IMessage imsg) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // await channel.SendMessageAsync("`Restarting in 2 seconds...`"); // await Task.Delay(2000); @@ -42,7 +42,7 @@ namespace NadekoBot.Modules.Administration //[RequirePermission(GuildPermission.ManageGuild)] //public async Task Delmsgoncmd(IMessage imsg) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var conf = SpecificConfigurations.Default.Of(channel.Guild.Id); // conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand; @@ -58,7 +58,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageRoles)] public async Task Setrole(IMessage imsg, IGuildUser usr, [Remainder] IRole role) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { await usr.AddRolesAsync(role).ConfigureAwait(false); @@ -76,7 +76,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageRoles)] public async Task Removerole(IMessage imsg, IGuildUser usr, [Remainder] IRole role) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { await usr.RemoveRolesAsync(role).ConfigureAwait(false); @@ -93,7 +93,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageRoles)] public async Task RenameRole(IMessage imsg, IRole roleToEdit, string newname) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { if (roleToEdit.Position > (await channel.Guild.GetCurrentUserAsync().ConfigureAwait(false)).Roles.Max(r => r.Position)) @@ -115,7 +115,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageRoles)] public async Task RemoveAllRoles(IMessage imsg, [Remainder] IGuildUser user) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { @@ -133,7 +133,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageRoles)] public async Task CreateRole(IMessage imsg, [Remainder] string roleName = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(roleName)) @@ -154,7 +154,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageRoles)] public async Task RoleColor(IMessage imsg, params string[] args) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (args.Count() != 2 && args.Count() != 4) { @@ -192,7 +192,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.BanMembers)] public async Task Ban(IMessage imsg, IGuildUser user) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var msg = ""; @@ -219,7 +219,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.BanMembers)] public async Task Softban(IMessage imsg, IGuildUser user, [Remainder] string msg = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!string.IsNullOrWhiteSpace(msg)) { @@ -244,7 +244,7 @@ namespace NadekoBot.Modules.Administration [RequireContext(ContextType.Guild)] public async Task Kick(IMessage imsg, IGuildUser user, [Remainder] string msg = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (user == null) { @@ -273,7 +273,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.MuteMembers)] public async Task Mute(IMessage imsg, params IGuildUser[] users) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!users.Any()) return; @@ -296,7 +296,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.MuteMembers)] public async Task Unmute(IMessage imsg, params IGuildUser[] users) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!users.Any()) return; @@ -319,7 +319,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.DeafenMembers)] public async Task Deafen(IMessage imsg, params IGuildUser[] users) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!users.Any()) return; @@ -342,7 +342,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.DeafenMembers)] public async Task UnDeafen(IMessage imsg, params IGuildUser[] users) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!users.Any()) return; @@ -374,7 +374,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageChannels)] public async Task CreatVoiChanl(IMessage imsg, [Remainder] string channelName) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; //todo actually print info about created channel await channel.Guild.CreateVoiceChannelAsync(channelName).ConfigureAwait(false); await channel.SendMessageAsync($"Created voice channel **{channelName}**.").ConfigureAwait(false); @@ -394,7 +394,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageChannels)] public async Task CreaTxtChanl(IMessage imsg, [Remainder] string channelName) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; //todo actually print info about created channel var txtCh = await channel.Guild.CreateTextChannelAsync(channelName).ConfigureAwait(false); await channel.SendMessageAsync($"Added text channel **{channelName}**.").ConfigureAwait(false); @@ -405,7 +405,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageChannels)] public async Task SetTopic(IMessage imsg, [Remainder] string topic = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; topic = topic ?? ""; await (channel as ITextChannel).ModifyAsync(c => c.Topic = topic); //await (channel).ModifyAsync(c => c).ConfigureAwait(false); @@ -417,7 +417,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.ManageChannels)] public async Task SetChanlName(IMessage imsg, [Remainder] string name) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.ModifyAsync(c => c.Name = name).ConfigureAwait(false); await channel.SendMessageAsync(":ok: **New channel name set.**").ConfigureAwait(false); @@ -429,7 +429,7 @@ namespace NadekoBot.Modules.Administration [RequireContext(ContextType.Guild)] public async Task Prune(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var user = await channel.Guild.GetCurrentUserAsync(); @@ -471,7 +471,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task Die(IMessage imsg) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // await channel.SendMessageAsync("`Shutting down.`").ConfigureAwait(false); // await Task.Delay(2000).ConfigureAwait(false); @@ -483,7 +483,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task Setname(IMessage imsg, [Remainder] string newName = null) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; //} @@ -492,7 +492,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task NewAvatar(IMessage imsg, [Remainder] string img = null) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // if (string.IsNullOrWhiteSpace(img)) // return; @@ -511,7 +511,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task SetGame(IMessage imsg, [Remainder] string game = null) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // game = game ?? ""; @@ -523,7 +523,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task Send(IMessage imsg, string where, [Remainder] string msg = null) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // if (string.IsNullOrWhiteSpace(msg)) // return; @@ -569,7 +569,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task Donadd(IMessage imsg, IUser donator, int amount) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var donator = channel.Guild.FindUsers(donator).FirstOrDefault(); // var amount = int.Parse(amount); // if (donator == null) return; @@ -592,7 +592,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task Announce(IMessage imsg, [Remainder] string message) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // foreach (var ch in (await _client.GetGuildsAsync().ConfigureAwait(false)).Select(async g => await g.GetDefaultChannelAsync().ConfigureAwait(false))) // { @@ -607,7 +607,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task SaveChat(IMessage imsg, int cnt) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // ulong? lastmsgId = null; // var sb = new StringBuilder(); @@ -640,7 +640,7 @@ namespace NadekoBot.Modules.Administration [RequirePermission(GuildPermission.MentionEveryone)] public async Task MentionRole(IMessage imsg, params IRole[] roles) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; string send = $"--{imsg.Author.Mention} has invoked a mention on the following roles--"; foreach (var role in roles) @@ -665,7 +665,7 @@ namespace NadekoBot.Modules.Administration //[RequireContext(ContextType.Guild)] //public async Task Donators(IMessage imsg) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var rows = DbHandler.Instance.GetAllRows(); // var donatorsOrdered = rows.OrderByDescending(d => d.Amount); diff --git a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs index 75a12f99..b171b632 100644 --- a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs +++ b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs @@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Administration //[RequirePermission(GuildPermission.ManageRoles)] //public async Task AutoAssignRole(IMessage imsg, IRole role) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var config = SpecificConfigurations.Default.Of(e.Server.Id); diff --git a/src/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs b/src/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs index c7864d46..5e3a55ed 100644 --- a/src/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs +++ b/src/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs @@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Administration _client.MessageReceived += async (imsg) => { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (channel == null || await imsg.IsAuthor()) return; @@ -55,7 +55,7 @@ namespace NadekoBot.Modules.Administration [RequireContext(ContextType.Guild)] public async Task Slowmode(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; ConcurrentDictionary throwaway; if (RatelimitingChannels.TryRemove(channel.Id, out throwaway)) diff --git a/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs b/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs index 79ace8a1..e7cb5744 100644 --- a/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs @@ -24,7 +24,7 @@ // [RequireContext(ContextType.Guild)] // public async Task Leave(IMessage imsg, [Remainder] string guildStr) // { -// var channel = imsg.Channel as ITextChannel; +// var channel = (ITextChannel)imsg.Channel; // guildStr = guildStr.ToUpperInvariant(); // var server = _client.GetGuilds().FirstOrDefault(g => g.Id.ToString() == guildStr) ?? _client.GetGuilds().FirstOrDefault(g => g.Name.ToUpperInvariant() == guildStr); diff --git a/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs b/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs index 413f672b..3ec97d5d 100644 --- a/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs +++ b/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs @@ -40,7 +40,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task CreateWar(IMessage imsg, int size, [Remainder] string enemyClan = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!(imsg.Author as IGuildUser).GuildPermissions.ManageChannels) return; @@ -73,7 +73,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task StartWar(IMessage imsg, [Remainder] string number = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; int num = 0; int.TryParse(number, out num); @@ -100,7 +100,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task ListWar(IMessage imsg, [Remainder] string number = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; // if number is null, print all wars in a short way if (string.IsNullOrWhiteSpace(number)) @@ -143,7 +143,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task Claim(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var warsInfo = GetWarInfo(imsg, number); if (warsInfo == null || warsInfo.Item1.Count == 0) { @@ -170,7 +170,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task ClaimFinish1(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await FinishClaim(imsg, number, baseNumber, other_name, 1); } @@ -178,7 +178,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task ClaimFinish2(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await FinishClaim(imsg, number, baseNumber, other_name, 2); } @@ -186,7 +186,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task ClaimFinish(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await FinishClaim(imsg, number, baseNumber, other_name); } @@ -194,7 +194,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task EndWar(IMessage imsg, int number) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var warsInfo = GetWarInfo(imsg,number); if (warsInfo == null) @@ -213,7 +213,7 @@ namespace NadekoBot.Modules.ClashOfClans [RequireContext(ContextType.Guild)] public async Task Unclaim(IMessage imsg, int number, [Remainder] string otherName = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var warsInfo = GetWarInfo(imsg, number); if (warsInfo == null || warsInfo.Item1.Count == 0) @@ -239,7 +239,7 @@ namespace NadekoBot.Modules.ClashOfClans private async Task FinishClaim(IMessage imsg, int number, int baseNumber, [Remainder] string other_name, int stars = 3) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var warInfo = GetWarInfo(imsg, number); if (warInfo == null || warInfo.Item1.Count == 0) { @@ -265,7 +265,7 @@ namespace NadekoBot.Modules.ClashOfClans private static Tuple, int> GetWarInfo(IMessage imsg, int num) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; //check if there are any wars List wars = null; ClashWars.TryGetValue(channel.Guild.Id, out wars); diff --git a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs index b5e36bb7..380b11c2 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs @@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Gambling [RequireContext(ContextType.Guild)] public async Task Race(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var ar = new AnimalRace(channel.Guild.Id, channel); @@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Gambling [RequireContext(ContextType.Guild)] public async Task JoinRace(IMessage imsg, int amount = 0) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (amount < 0) amount = 0; diff --git a/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs b/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs index 6f613c94..e281ed7a 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs @@ -26,7 +26,7 @@ namespace NadekoBot.Modules.Gambling // InternalRoll(imsg, arg, false); //private async Task InternalRoll(IMessage imsg, string arg, bool ordered) { - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var r = new Random(); // if (string.IsNullOrWhiteSpace(arg)) // { @@ -110,7 +110,7 @@ namespace NadekoBot.Modules.Gambling [RequireContext(ContextType.Guild)] public async Task NRoll(IMessage imsg, [Remainder] string range) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index 59e8833f..72d72fb4 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Gambling [RequireContext(ContextType.Guild)] public async Task Raffle(IMessage imsg, [Remainder] IRole role = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; role = role ?? channel.Guild.EveryoneRole; @@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Gambling //[RequireContext(ContextType.Guild)] //public async Task Cash(IMessage imsg, [Remainder] string arg) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var usr = e.Message.MentionedUsers.FirstOrDefault() ?? imsg.Author; // var pts = GetUserFlowers(usr.Id); @@ -52,7 +52,7 @@ namespace NadekoBot.Modules.Gambling //[RequireContext(ContextType.Guild)] //public async Task Give(IMessage imsg, long amount, [Remainder] IUser receiver) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // if (amount <= 0) // return; // var userFlowers = GetUserFlowers(imsg.Author.Id); @@ -81,7 +81,7 @@ namespace NadekoBot.Modules.Gambling //[RequireContext(ContextType.Guild)] //public async Task Award(IMessage imsg, long amount, [Remainder] ulong usrId) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // if (amount <= 0) // return; @@ -102,7 +102,7 @@ namespace NadekoBot.Modules.Gambling //[RequireContext(ContextType.Guild)] //public async Task Take(IMessage imsg, long amount, [Remainder] ulong usrId) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // if (amount <= 0) // return; @@ -115,7 +115,7 @@ namespace NadekoBot.Modules.Gambling //[RequireContext(ContextType.Guild)] //public async Task BetRoll(IMessage imsg, int amount) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // if (amount < 1) // return; @@ -160,7 +160,7 @@ namespace NadekoBot.Modules.Gambling // [RequireContext(ContextType.Guild)] // public async Task Leaderboard(IMessage imsg) // { -// var channel = imsg.Channel as ITextChannel; +// var channel = (ITextChannel)imsg.Channel; // var richestTemp = DbHandler.Instance.GetTopRichest(); // var richest = richestTemp as CurrencyState[] ?? richestTemp.ToArray(); diff --git a/src/NadekoBot/Modules/Games/Commands/LeetCommands.cs b/src/NadekoBot/Modules/Games/Commands/LeetCommands.cs index dd660876..a17bc3d3 100644 --- a/src/NadekoBot/Modules/Games/Commands/LeetCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/LeetCommands.cs @@ -16,7 +16,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Leet(IMessage imsg, int level, [Remainder] string text = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; text = text.Trim(); if (string.IsNullOrWhiteSpace(text)) diff --git a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs index 0f3d1721..95900dcc 100644 --- a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs @@ -19,7 +19,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Poll(IMessage imsg, [Remainder] string arg = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!(imsg.Author as IGuildUser).GuildPermissions.ManageChannels) return; @@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Pollend(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!(imsg.Author as IGuildUser).GuildPermissions.ManageChannels) return; diff --git a/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs b/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs index 956b40fa..e2c7c347 100644 --- a/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs @@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Trivia(IMessage imsg, string[] args) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; TriviaGame trivia; if (!RunningTrivias.TryGetValue(channel.Guild.Id, out trivia)) @@ -48,7 +48,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Tl(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; TriviaGame trivia; if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia)) @@ -61,7 +61,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Tq(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; TriviaGame trivia; if (RunningTrivias.TryRemove(channel.Guild.Id, out trivia)) diff --git a/src/NadekoBot/Modules/Games/Games.cs b/src/NadekoBot/Modules/Games/Games.cs index bf9a3413..861d4697 100644 --- a/src/NadekoBot/Modules/Games/Games.cs +++ b/src/NadekoBot/Modules/Games/Games.cs @@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Choose(IMessage imsg, [Remainder] string list = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(list)) return; var listArr = list.Split(';'); @@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task _8Ball(IMessage imsg, [Remainder] string question = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(question)) return; @@ -52,7 +52,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Rps(IMessage imsg, string input) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; Func GetRPSPick = (p) => { @@ -102,7 +102,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Linux(IMessage imsg, string guhnoo, string loonix) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.SendMessageAsync( $@"I'd just like to interject for moment. What you're refering to as {loonix}, is in fact, {guhnoo}/{loonix}, or as I've recently taken to calling it, {guhnoo} plus {loonix}. {loonix} is not an operating system unto itself, but rather another free component of a fully functioning {guhnoo} system made useful by the {guhnoo} corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX. diff --git a/src/NadekoBot/Modules/Help/Help.cs b/src/NadekoBot/Modules/Help/Help.cs index 2d38e4dd..68e9cca4 100644 --- a/src/NadekoBot/Modules/Help/Help.cs +++ b/src/NadekoBot/Modules/Help/Help.cs @@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Help [RequireContext(ContextType.Guild)] public async Task Modules(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.SendMessageAsync("`List of modules:` \nβ€’ " + string.Join("\nβ€’ ", _commands.Modules.Select(m => m.Name)) + $"\n`Type \"-commands module_name\" to get a list of commands in that module.`") .ConfigureAwait(false); @@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Help [RequireContext(ContextType.Guild)] public async Task Commands(IMessage imsg, [Remainder] string module = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; module = module?.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(module)) @@ -69,7 +69,7 @@ namespace NadekoBot.Modules.Help [RequireContext(ContextType.Guild)] public async Task H(IMessage imsg, [Remainder] string comToFind = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; comToFind = comToFind?.ToLowerInvariant(); if (string.IsNullOrWhiteSpace(comToFind)) @@ -117,7 +117,7 @@ namespace NadekoBot.Modules.Help [RequireContext(ContextType.Guild)] public async Task Guide(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.SendMessageAsync( @"**LIST OF COMMANDS**: @@ -128,7 +128,7 @@ namespace NadekoBot.Modules.Help [RequireContext(ContextType.Guild)] public async Task Donate(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.SendMessageAsync( $@"You can support the project on patreon. or diff --git a/src/NadekoBot/_Modules/Music/Classes/MusicControls.cs b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs similarity index 92% rename from src/NadekoBot/_Modules/Music/Classes/MusicControls.cs rename to src/NadekoBot/Modules/Music/Classes/MusicControls.cs index e13239cf..03aaccef 100644 --- a/src/NadekoBot/_Modules/Music/Classes/MusicControls.cs +++ b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs @@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Music.Classes public event EventHandler OnCompleted = delegate { }; public event EventHandler OnStarted = delegate { }; - public Channel PlaybackVoiceChannel { get; private set; } + public IVoiceChannel PlaybackVoiceChannel { get; private set; } private bool Destroyed { get; set; } = false; public bool RepeatSong { get; private set; } = false; @@ -54,12 +54,10 @@ namespace NadekoBot.Modules.Music.Classes private ConcurrentQueue actionQueue { get; set; } = new ConcurrentQueue(); - public MusicPlayer(Channel startingVoiceChannel, float? defaultVolume) + public MusicPlayer(IVoiceChannel startingVoiceChannel, float? defaultVolume) { if (startingVoiceChannel == null) throw new ArgumentNullException(nameof(startingVoiceChannel)); - if (startingVoiceChannel.Type != ChannelType.Voice) - throw new ArgumentException("Channel must be of type voice"); Volume = defaultVolume ?? 1.0f; PlaybackVoiceChannel = startingVoiceChannel; @@ -101,9 +99,9 @@ namespace NadekoBot.Modules.Music.Classes { try { - if (audioClient?.State != ConnectionState.Connected) + if (audioClient?.ConnectionState != ConnectionState.Connected) { - audioClient = await PlaybackVoiceChannel.JoinAudio(); + audioClient = await PlaybackVoiceChannel.ConnectAsync().ConfigureAwait(false); continue; } @@ -246,7 +244,7 @@ namespace NadekoBot.Modules.Music.Classes public void Destroy() { - actionQueue.Enqueue(() => + actionQueue.Enqueue(async () => { RepeatPlaylist = false; RepeatSong = false; @@ -254,16 +252,16 @@ namespace NadekoBot.Modules.Music.Classes playlist.Clear(); if (!SongCancelSource.IsCancellationRequested) SongCancelSource.Cancel(); - audioClient.Disconnect(); + await audioClient.DisconnectAsync(); }); } - internal Task MoveToVoiceChannel(Channel voiceChannel) + internal Task MoveToVoiceChannel(IVoiceChannel voiceChannel) { - if (audioClient?.State != ConnectionState.Connected) + if (audioClient?.ConnectionState != ConnectionState.Connected) throw new InvalidOperationException("Can't move while bot is not connected to voice channel."); PlaybackVoiceChannel = voiceChannel; - return PlaybackVoiceChannel.JoinAudio(); + return PlaybackVoiceChannel.ConnectAsync(); } internal bool ToggleRepeatSong() => this.RepeatSong = !this.RepeatSong; diff --git a/src/NadekoBot/_Modules/Music/Classes/PlaylistFullException.cs b/src/NadekoBot/Modules/Music/Classes/PlaylistFullException.cs similarity index 100% rename from src/NadekoBot/_Modules/Music/Classes/PlaylistFullException.cs rename to src/NadekoBot/Modules/Music/Classes/PlaylistFullException.cs diff --git a/src/NadekoBot/_Modules/Music/Classes/Song.cs b/src/NadekoBot/Modules/Music/Classes/Song.cs similarity index 95% rename from src/NadekoBot/_Modules/Music/Classes/Song.cs rename to src/NadekoBot/Modules/Music/Classes/Song.cs index 2d808736..4e0d0184 100644 --- a/src/NadekoBot/_Modules/Music/Classes/Song.cs +++ b/src/NadekoBot/Modules/Music/Classes/Song.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.Contracts; using System.IO; using System.Linq; +using System.Net.Http; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -104,6 +105,9 @@ namespace NadekoBot.Modules.Music.Classes sw.Stop(); Console.WriteLine("Prebuffering successfully completed in "+ sw.Elapsed); + + var outStream = voiceClient.CreatePCMStream(3840); + const int blockSize = 3840; byte[] buffer = new byte[blockSize]; while (!cancelToken.IsCancellationRequested) @@ -130,7 +134,6 @@ namespace NadekoBot.Modules.Music.Classes break; if (attempt++ == 20) { - voiceClient.Wait(); MusicPlayer.SongCancelSource.Cancel(); break; } @@ -147,13 +150,12 @@ namespace NadekoBot.Modules.Music.Classes await Task.Delay(200, cancelToken).ConfigureAwait(false); buffer = AdjustVolume(buffer, MusicPlayer.Volume); - voiceClient.Send(buffer, 0, read); + await outStream.WriteAsync(buffer, 0, read); } } finally { await bufferTask; - await Task.Run(() => voiceClient.Clear()); if(inStream != null) inStream.Dispose(); Console.WriteLine("l"); @@ -285,10 +287,10 @@ namespace NadekoBot.Modules.Music.Classes }); } - var link = await SearchHelper.FindYoutubeUrlByKeywords(query).ConfigureAwait(false); + var link = (await NadekoBot.Google.GetVideosByKeywordsAsync(query).ConfigureAwait(false)).FirstOrDefault(); if (string.IsNullOrWhiteSpace(link)) throw new OperationCanceledException("Not a valid youtube query."); - var allVideos = await Task.Factory.StartNew(async () => await YouTube.Default.GetAllVideosAsync(link).ConfigureAwait(false)).Unwrap().ConfigureAwait(false); + var allVideos = await Task.Run(async () => await YouTube.Default.GetAllVideosAsync(link).ConfigureAwait(false)).ConfigureAwait(false); var videos = allVideos.Where(v => v.AdaptiveKind == AdaptiveKind.Audio); var video = videos .Where(v => v.AudioBitrate < 192) @@ -324,7 +326,10 @@ namespace NadekoBot.Modules.Music.Classes string file = null; try { - file = await http.GetStringAsync(query).ConfigureAwait(false); + using (var http = new HttpClient()) + { + file = await http.GetStringAsync(query).ConfigureAwait(false); + } } catch { diff --git a/src/NadekoBot/_Modules/Music/Classes/SongBuffer.cs b/src/NadekoBot/Modules/Music/Classes/SongBuffer.cs similarity index 100% rename from src/NadekoBot/_Modules/Music/Classes/SongBuffer.cs rename to src/NadekoBot/Modules/Music/Classes/SongBuffer.cs diff --git a/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs b/src/NadekoBot/Modules/Music/Classes/SoundCloud.cs similarity index 86% rename from src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs rename to src/NadekoBot/Modules/Music/Classes/SoundCloud.cs index 9cab3fcf..88c5bdbe 100644 --- a/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs +++ b/src/NadekoBot/Modules/Music/Classes/SoundCloud.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using System; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; namespace NadekoBot.Modules.Music.Classes @@ -18,10 +19,17 @@ namespace NadekoBot.Modules.Music.Classes { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); - if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.SoundCloudClientID)) - throw new ArgumentNullException(nameof(NadekoBot.Credentials.SoundCloudClientID)); + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.SoundCloudClientId)) + throw new ArgumentNullException(nameof(NadekoBot.Credentials.SoundCloudClientId)); - var response = await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={url}&client_id={NadekoBot.Credentials.SoundCloudClientID}").ConfigureAwait(false); + string response = ""; + + using (var http = new HttpClient()) + { + response = await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={url}&client_id={NadekoBot.Credentials.SoundCloudClientId}").ConfigureAwait(false); + + } + var responseObj = Newtonsoft.Json.JsonConvert.DeserializeObject(response); if (responseObj?.Kind != "track") @@ -37,10 +45,14 @@ namespace NadekoBot.Modules.Music.Classes { if (string.IsNullOrWhiteSpace(query)) throw new ArgumentNullException(nameof(query)); - if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.SoundCloudClientID)) - throw new ArgumentNullException(nameof(NadekoBot.Credentials.SoundCloudClientID)); + if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.SoundCloudClientId)) + throw new ArgumentNullException(nameof(NadekoBot.Credentials.SoundCloudClientId)); - var response = await http.GetStringAsync($"http://api.soundcloud.com/tracks?q={Uri.EscapeDataString(query)}&client_id={NadekoBot.Credentials.SoundCloudClientID}").ConfigureAwait(false); + var response = ""; + using (var http = new HttpClient()) + { + await http.GetStringAsync($"http://api.soundcloud.com/tracks?q={Uri.EscapeDataString(query)}&client_id={NadekoBot.Credentials.SoundCloudClientId}").ConfigureAwait(false); + } var responseObj = JsonConvert.DeserializeObject(response).Where(s => s.Streamable).FirstOrDefault(); if (responseObj?.Kind != "track") @@ -62,7 +74,7 @@ namespace NadekoBot.Modules.Music.Classes [JsonProperty("permalink_url")] public string TrackLink { get; set; } = ""; [JsonIgnore] - public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Credentials.SoundCloudClientID}"; + public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Credentials.SoundCloudClientId}"; } public class SoundCloudUser { diff --git a/src/NadekoBot/Modules/Music/MusicModule.cs b/src/NadekoBot/Modules/Music/MusicModule.cs new file mode 100644 index 00000000..48ae23c2 --- /dev/null +++ b/src/NadekoBot/Modules/Music/MusicModule.cs @@ -0,0 +1,724 @@ +ο»Ώusing Discord.Commands; +using NadekoBot.Modules.Music.Classes; +using System.Collections.Concurrent; +using Discord.WebSocket; +using NadekoBot.Services; +using System.IO; +using Discord; +using System.Threading.Tasks; +using NadekoBot.Attributes; +using System; +using System.Linq; +using NadekoBot.Extensions; +using System.Net.Http; +using Newtonsoft.Json.Linq; +using System.Collections.Generic; + +namespace NadekoBot.Modules.Music +{ + [Module("!!", AppendSpace = false)] + public partial class MusicModule : DiscordModule + { + public static ConcurrentDictionary MusicPlayers = new ConcurrentDictionary(); + + public const string MusicDataPath = "data/musicdata"; + private IGoogleApiService _google; + + public MusicModule(ILocalization loc, CommandService cmds, IBotConfiguration config, DiscordSocketClient client, IGoogleApiService google) : base(loc, cmds, config, client) + { + //it can fail if its currenctly opened or doesn't exist. Either way i don't care + try { Directory.Delete(MusicDataPath, true); } catch { } + + Directory.CreateDirectory(MusicDataPath); + + _google = google; + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Next(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; + if (musicPlayer.PlaybackVoiceChannel == ((IGuildUser)imsg.Author).VoiceChannel) + musicPlayer.Next(); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Stop(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; + if (((IGuildUser)imsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel) + { + musicPlayer.Autoplay = false; + musicPlayer.Stop(); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Destroy(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + + MusicPlayer musicPlayer; + if (!MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer)) return; + if (((IGuildUser)imsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel) + musicPlayer.Destroy(); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Pause(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; + if (((IGuildUser)imsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) + return; + musicPlayer.TogglePause(); + if (musicPlayer.Paused) + await channel.SendMessageAsync("🎡`Music Player paused.`").ConfigureAwait(false); + else + await channel.SendMessageAsync("🎡`Music Player unpaused.`").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Queue(IMessage imsg, [Remainder] string query) + { + var channel = (ITextChannel)imsg.Channel; + + await QueueSong(((IGuildUser)imsg.Author), channel, ((IGuildUser)imsg.Author).VoiceChannel, query).ConfigureAwait(false); + if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages) + { + await Task.Delay(10000).ConfigureAwait(false); + await imsg.DeleteAsync().ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task SoundCloudQueue(IMessage imsg, [Remainder] string query) + { + var channel = (ITextChannel)imsg.Channel; + + await QueueSong(((IGuildUser)imsg.Author), channel, ((IGuildUser)imsg.Author).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false); + if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages) + { + await Task.Delay(10000).ConfigureAwait(false); + await imsg.DeleteAsync().ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task ListQueue(IMessage imsg, int page = 1) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + { + await channel.SendMessageAsync("🎡 No active music player.").ConfigureAwait(false); + return; + } + if (page <= 0) + return; + + var currentSong = musicPlayer.CurrentSong; + if (currentSong == null) + return; + var toSend = $"🎡`Now Playing` {currentSong.PrettyName} " + $"{currentSong.PrettyCurrentTime()}\n"; + if (musicPlayer.RepeatSong) + toSend += "πŸ”‚"; + else if (musicPlayer.RepeatPlaylist) + toSend += "πŸ”"; + toSend += $" **{musicPlayer.Playlist.Count}** `tracks currently queued. Showing page {page}` "; + if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize) + toSend += "**Song queue is full!**\n"; + else + toSend += "\n"; + const int itemsPerPage = 15; + int startAt = itemsPerPage * (page - 1); + var number = 1 + startAt; + await channel.SendMessageAsync(toSend + string.Join("\n", musicPlayer.Playlist.Skip(startAt).Take(15).Select(v => $"`{number++}.` {v.PrettyName}"))).ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task NowPlaying(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + var currentSong = musicPlayer.CurrentSong; + if (currentSong == null) + return; + await channel.SendMessageAsync($"🎡`Now Playing` {currentSong.PrettyName} " + + $"{currentSong.PrettyCurrentTime()}").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Volume(IMessage imsg, int val) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + if (((IGuildUser)imsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) + return; + if (val < 0) + return; + var volume = musicPlayer.SetVolume(val); + await channel.SendMessageAsync($"🎡 `Volume set to {volume}%`").ConfigureAwait(false); + } + ////todo DB + //[LocalizedCommand, LocalizedDescription, LocalizedSummary] + //[RequireContext(ContextType.Guild)] + //public async Task Defvol(IMessage imsg, [Remainder] int val) + //{ + // var channel = (ITextChannel)imsg.Channel; + // var arg = val; + // float volume; + // if (!float.TryParse(arg, out volume) || volume < 0 || volume > 100) + // { + // await channel.SendMessageAsync("Volume number invalid.").ConfigureAwait(false); + // return; + // } + // var conf = SpecificConfigurations.Default.Of(channel.Guild.Id); + // conf.DefaultMusicVolume = volume / 100; + // await channel.SendMessageAsync($"🎡 `Default volume set to {volume}%`").ConfigureAwait(false); + //} + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Mute(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + if (((IGuildUser)imsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) + return; + musicPlayer.SetVolume(0); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Max(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + if (((IGuildUser)imsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) + return; + musicPlayer.SetVolume(100); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Shuffle(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + if (((IGuildUser)imsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) + return; + if (musicPlayer.Playlist.Count < 2) + { + await channel.SendMessageAsync("πŸ’’ Not enough songs in order to perform the shuffle.").ConfigureAwait(false); + return; + } + + musicPlayer.Shuffle(); + await channel.SendMessageAsync("🎡 `Songs shuffled.`").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Playlist(IMessage imsg, [Remainder] string playlist) + { + var channel = (ITextChannel)imsg.Channel; + var arg = playlist; + if (string.IsNullOrWhiteSpace(arg)) + return; + if (((IGuildUser)imsg.Author).VoiceChannel?.Guild != channel.Guild) + { + await channel.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false); + return; + } + var plId = (await _google.GetPlaylistIdsByKeywordsAsync(arg).ConfigureAwait(false)).FirstOrDefault(); + if (plId == null) + { + await channel.SendMessageAsync("No search results for that query."); + return; + } + var ids = await _google.GetPlaylistTracksAsync(plId, 500).ConfigureAwait(false); + if (!ids.Any()) + { + await channel.SendMessageAsync($"🎡 `Failed to find any songs.`").ConfigureAwait(false); + return; + } + var idArray = ids as string[] ?? ids.ToArray(); + var count = idArray.Length; + var msg = + await channel.SendMessageAsync($"🎡 `Attempting to queue {count} songs".SnPl(count) + "...`").ConfigureAwait(false); + foreach (var id in idArray) + { + try + { + await QueueSong(((IGuildUser)imsg.Author), channel, ((IGuildUser)imsg.Author).VoiceChannel, id, true).ConfigureAwait(false); + } + catch (PlaylistFullException) + { break; } + catch { } + } + await msg.ModifyAsync(m => m.Content = "🎡 `Playlist queue complete.`").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task SoundCloudPl(IMessage imsg, [Remainder] string pl) + { + var channel = (ITextChannel)imsg.Channel; + pl = pl?.Trim(); + + if (string.IsNullOrWhiteSpace(pl)) + return; + + using (var http = new HttpClient()) + { + var scvids = JObject.Parse(await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Credentials.SoundCloudClientId}").ConfigureAwait(false))["tracks"].ToObject(); + await QueueSong(((IGuildUser)imsg.Author), channel, ((IGuildUser)imsg.Author).VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false); + + MusicPlayer mp; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out mp)) + return; + + foreach (var svideo in scvids.Skip(1)) + { + try + { + mp.AddSong(new Song(new Classes.SongInfo + { + Title = svideo.FullName, + Provider = "SoundCloud", + Uri = svideo.StreamLink, + ProviderType = MusicType.Normal, + Query = svideo.TrackLink, + }), ((IGuildUser)imsg.Author).Username); + } + catch (PlaylistFullException) { break; } + } + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task LocalPl(IMessage imsg, [Remainder] string directory) + { + var channel = (ITextChannel)imsg.Channel; + var arg = directory; + if (string.IsNullOrWhiteSpace(arg)) + return; + try + { + var fileEnum = new DirectoryInfo(arg).GetFiles() + .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System)); + foreach (var file in fileEnum) + { + try + { + await QueueSong(((IGuildUser)imsg.Author), channel, ((IGuildUser)imsg.Author).VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false); + } + catch (PlaylistFullException) + { + break; + } + catch { } + } + await channel.SendMessageAsync("🎡 `Directory queue complete.`").ConfigureAwait(false); + } + catch { } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Radio(IMessage imsg, string radio_link) + { + var channel = (ITextChannel)imsg.Channel; + if (((IGuildUser)imsg.Author).VoiceChannel?.Guild != channel.Guild) + { + await channel.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false); + return; + } + await QueueSong(((IGuildUser)imsg.Author), channel, ((IGuildUser)imsg.Author).VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false); + if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages) + { + await Task.Delay(10000).ConfigureAwait(false); + await imsg.DeleteAsync().ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Local(IMessage imsg, [Remainder] string path) + { + var channel = (ITextChannel)imsg.Channel; + var arg = path; + if (string.IsNullOrWhiteSpace(arg)) + return; + await QueueSong(((IGuildUser)imsg.Author), channel, ((IGuildUser)imsg.Author).VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false); + + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Move(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + var voiceChannel = ((IGuildUser)imsg.Author).VoiceChannel; + if (voiceChannel == null || voiceChannel.Guild != channel.Guild || !MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + musicPlayer.MoveToVoiceChannel(voiceChannel); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Remove(IMessage imsg, int num) + { + var channel = (ITextChannel)imsg.Channel; + + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + { + return; + } + if (((IGuildUser)imsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) + return; + if (num <= 0 || num > musicPlayer.Playlist.Count) + return; + var song = (musicPlayer.Playlist as List)?[num - 1]; + musicPlayer.RemoveSongAt(num - 1); + await channel.SendMessageAsync($"🎡**Track {song.PrettyName} at position `#{num}` has been removed.**").ConfigureAwait(false); + } + //todo fix + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Remove(IMessage imsg, string all) + { + var channel = (ITextChannel)imsg.Channel; + + if (all.Trim().ToUpperInvariant() != "ALL") + return; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; + musicPlayer.ClearQueue(); + await channel.SendMessageAsync($"🎡`Queue cleared!`").ConfigureAwait(false); + return; + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task MoveSong(IMessage imsg, [Remainder] string fromto) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + { + return; + } + fromto = fromto?.Trim(); + var fromtoArr = fromto.Split('>'); + + int n1; + int n2; + + var playlist = musicPlayer.Playlist as List ?? musicPlayer.Playlist.ToList(); + + if (fromtoArr.Length != 2 || !int.TryParse(fromtoArr[0], out n1) || + !int.TryParse(fromtoArr[1], out n2) || n1 < 1 || n2 < 1 || n1 == n2 || + n1 > playlist.Count || n2 > playlist.Count) + { + await channel.SendMessageAsync("`Invalid input.`").ConfigureAwait(false); + return; + } + + var s = playlist[n1 - 1]; + playlist.Insert(n2 - 1, s); + var nn1 = n2 < n1 ? n1 : n1 - 1; + playlist.RemoveAt(nn1); + + await channel.SendMessageAsync($"🎡`Moved` {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false); + + + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task SetMaxQueue(IMessage imsg, uint size) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + { + return; + } + musicPlayer.MaxQueueSize = size; + await channel.SendMessageAsync($"🎡 `Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}`"); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task ReptCurSong(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + var currentSong = musicPlayer.CurrentSong; + if (currentSong == null) + return; + var currentValue = musicPlayer.ToggleRepeatSong(); + await channel.SendMessageAsync(currentValue ? + $"πŸŽ΅πŸ”‚`Repeating track:`{currentSong.PrettyName}" : + $"πŸŽ΅πŸ”‚`Current track repeat stopped.`") + .ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task RepeatPl(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + var currentValue = musicPlayer.ToggleRepeatPlaylist(); + await channel.SendMessageAsync($"πŸŽ΅πŸ”`Repeat playlist {(currentValue ? "enabled" : "disabled")}`").ConfigureAwait(false); + } + + /// + //[LocalizedCommand, LocalizedDescription, LocalizedSummary] + //[RequireContext(ContextType.Guild)] + //public async Task Save(IMessage imsg, [Remainder] string name) + //{ + // var channel = (ITextChannel)imsg.Channel; + + //} + + //[LocalizedCommand, LocalizedDescription, LocalizedSummary] + //[RequireContext(ContextType.Guild)] + //public async Task Load(IMessage imsg, [Remainder] string name) + //{ + // var channel = (ITextChannel)imsg.Channel; + + //} + + //[LocalizedCommand, LocalizedDescription, LocalizedSummary] + //[RequireContext(ContextType.Guild)] + //public async Task Playlists(IMessage imsg, [Remainder] string num) + //{ + // var channel = (ITextChannel)imsg.Channel; + + //} + + //[LocalizedCommand, LocalizedDescription, LocalizedSummary] + //[RequireContext(ContextType.Guild)] + //public async Task DeletePlaylist(IMessage imsg, [Remainder] string pl) + //{ + // var channel = (ITextChannel)imsg.Channel; + + //} + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Goto(IMessage imsg, int time) + { + var channel = (ITextChannel)imsg.Channel; + + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + if (((IGuildUser)imsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) + return; + + if (time < 0) + return; + + var currentSong = musicPlayer.CurrentSong; + + if (currentSong == null) + return; + + //currentSong.PrintStatusMessage = false; + var gotoSong = currentSong.Clone(); + gotoSong.SkipTo = time; + musicPlayer.AddSong(gotoSong, 0); + musicPlayer.Next(); + + var minutes = (time / 60).ToString(); + var seconds = (time % 60).ToString(); + + if (minutes.Length == 1) + minutes = "0" + minutes; + if (seconds.Length == 1) + seconds = "0" + seconds; + + await channel.SendMessageAsync($"`Skipped to {minutes}:{seconds}`").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task GetLink(IMessage imsg, int index = 0) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + + if (index < 0) + return; + + if (index > 0) + { + + var selSong = musicPlayer.Playlist.DefaultIfEmpty(null).ElementAtOrDefault(index - 1); + if (selSong == null) + { + await channel.SendMessageAsync("Could not select song, likely wrong index"); + + } + else + { + await channel.SendMessageAsync($"🎢`Selected song {selSong.SongInfo.Title}:` <{selSong.SongInfo.Query}>").ConfigureAwait(false); + } + } + else + { + var curSong = musicPlayer.CurrentSong; + if (curSong == null) + return; + await channel.SendMessageAsync($"🎢`Current song:` <{curSong.SongInfo.Query}>").ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Autoplay(IMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) + return; + + if (!musicPlayer.ToggleAutoplay()) + await channel.SendMessageAsync("🎢`Autoplay disabled.`").ConfigureAwait(false); + else + await channel.SendMessageAsync("🎢`Autoplay enabled.`").ConfigureAwait(false); + } + + public static async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal) + { + if (voiceCh == null || voiceCh.Guild != textCh.Guild) + { + if (!silent) + await textCh.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.").ConfigureAwait(false); + throw new ArgumentNullException(nameof(voiceCh)); + } + if (string.IsNullOrWhiteSpace(query) || query.Length < 3) + throw new ArgumentException("πŸ’’ Invalid query for queue song.", nameof(query)); + + var musicPlayer = MusicPlayers.GetOrAdd(textCh.Guild.Id, server => + { + //todo DB + float vol = 100;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume; + var mp = new MusicPlayer(voiceCh, vol); + + + IMessage playingMessage = null; + IMessage lastFinishedMessage = null; + mp.OnCompleted += async (s, song) => + { + if (song.PrintStatusMessage) + { + try + { + if (lastFinishedMessage != null) + await lastFinishedMessage.DeleteAsync().ConfigureAwait(false); + if (playingMessage != null) + await playingMessage.DeleteAsync().ConfigureAwait(false); + lastFinishedMessage = await textCh.SendMessageAsync($"🎡`Finished`{song.PrettyName}").ConfigureAwait(false); + if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube") + { + await QueueSong(queuer.Guild.GetCurrentUser(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + }; + mp.OnStarted += async (s, song) => + { + if (song.PrintStatusMessage) + { + var sender = s as MusicPlayer; + if (sender == null) + return; + + try + { + + var msgTxt = $"🎡`Playing`{song.PrettyName} `Vol: {(int)(sender.Volume * 100)}%`"; + playingMessage = await textCh.SendMessageAsync(msgTxt).ConfigureAwait(false); + } + catch { } + } + }; + return mp; + }); + Song resolvedSong; + try + { + musicPlayer.ThrowIfQueueFull(); + resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false); + + musicPlayer.AddSong(resolvedSong, queuer.Username); + } + catch (PlaylistFullException) + { + await textCh.SendMessageAsync($"🎡 `Queue is full at {musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}.` "); + throw; + } + if (!silent) + { + var queuedMessage = await textCh.SendMessageAsync($"🎡`Queued`{resolvedSong.PrettyName} **at** `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false); +#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + Task.Run(async () => + { + await Task.Delay(10000).ConfigureAwait(false); + try + { + await queuedMessage.DeleteAsync().ConfigureAwait(false); + } + catch { } + }).ConfigureAwait(false); +#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + } + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/NSFW/NSFW.cs b/src/NadekoBot/Modules/NSFW/NSFW.cs index b3977f5a..3fb08633 100644 --- a/src/NadekoBot/Modules/NSFW/NSFW.cs +++ b/src/NadekoBot/Modules/NSFW/NSFW.cs @@ -26,7 +26,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task Hentai(IMessage imsg, [Remainder] string tag = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; tag = tag?.Trim() ?? ""; @@ -45,7 +45,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task Danbooru(IMessage imsg, [Remainder] string tag = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; tag = tag?.Trim() ?? ""; var link = await GetDanbooruImageLink(tag).ConfigureAwait(false); @@ -59,7 +59,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task Gelbooru(IMessage imsg, [Remainder] string tag = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; tag = tag?.Trim() ?? ""; var link = await GetRule34ImageLink(tag).ConfigureAwait(false); @@ -73,7 +73,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task Rule34(IMessage imsg, [Remainder] string tag = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; tag = tag?.Trim() ?? ""; var link = await GetGelbooruImageLink(tag).ConfigureAwait(false); @@ -87,7 +87,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task E621(IMessage imsg, [Remainder] string tag = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; tag = tag?.Trim() ?? ""; var link = await GetE621ImageLink(tag).ConfigureAwait(false); @@ -101,7 +101,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task Cp(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.SendMessageAsync("http://i.imgur.com/MZkY1md.jpg").ConfigureAwait(false); } @@ -110,7 +110,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task Boobs(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { JToken obj; @@ -130,7 +130,7 @@ namespace NadekoBot.Modules.NSFW [RequireContext(ContextType.Guild)] public async Task Butts(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { diff --git a/src/NadekoBot/Modules/Pokemon/Pokemon.cs b/src/NadekoBot/Modules/Pokemon/Pokemon.cs index d5624c15..fef39c40 100644 --- a/src/NadekoBot/Modules/Pokemon/Pokemon.cs +++ b/src/NadekoBot/Modules/Pokemon/Pokemon.cs @@ -19,7 +19,7 @@ namespace NadekoBot.Modules.Games [RequireContext(ContextType.Guild)] public async Task Poke(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; } diff --git a/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs b/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs index f9b309d8..de6bf340 100644 --- a/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs @@ -15,7 +15,7 @@ // [RequireContext(ContextType.Guild)] // public async Task Anime(IMessage imsg, [Remainder] string query = null) // { -// var channel = imsg.Channel as ITextChannel; +// var channel = (ITextChannel)imsg.Channel; // if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; // string result; @@ -36,7 +36,7 @@ // [RequireContext(ContextType.Guild)] // public async Task Manga(IMessage imsg, [Remainder] string query = null) // { -// var channel = imsg.Channel as ITextChannel; +// var channel = (ITextChannel)imsg.Channel; // if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; // string result; diff --git a/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs b/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs index c9c89d33..450c126b 100644 --- a/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs @@ -46,7 +46,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Yomama(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; using (var http = new HttpClient()) { var response = await http.GetStringAsync("http://api.yomomma.info/").ConfigureAwait(false); @@ -58,7 +58,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Randjoke(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; using (var http = new HttpClient()) { var response = await http.GetStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false); @@ -70,7 +70,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task ChuckNorris(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; using (var http = new HttpClient()) { var response = await http.GetStringAsync("http://api.icndb.com/jokes/random/").ConfigureAwait(false); @@ -82,7 +82,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task WowJoke(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!wowJokes.Any()) { @@ -94,7 +94,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task MagicItem(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var rng = new Random(); var item = magicItems[rng.Next(0, magicItems.Count)].ToString(); diff --git a/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs index 1a4a5de9..7ff589a3 100644 --- a/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs @@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Lolban(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; diff --git a/src/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs b/src/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs index d551655c..b6ce9b79 100644 --- a/src/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs @@ -19,7 +19,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Memelist(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; using (var http = new HttpClient()) { var data = JsonConvert.DeserializeObject>(await http.GetStringAsync("http://memegen.link/templates/")) @@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Memegen(IMessage imsg, string meme, string topText, string botText) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var top = Uri.EscapeDataString(topText.Replace(' ', '-')); var bot = Uri.EscapeDataString(botText.Replace(' ', '-')); diff --git a/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs b/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs index 19479696..1f77ba04 100644 --- a/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs @@ -30,7 +30,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Osu(IMessage imsg, string usr, string mode) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(usr)) return; @@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Osub(IMessage imsg, [Remainder] string map) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey)) { @@ -100,7 +100,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Osu5(IMessage imsg, string user, [Remainder] string mode) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey)) { await channel.SendMessageAsync("πŸ’’ An osu! API key is required.").ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs b/src/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs index 48789faf..9a5e0d3a 100644 --- a/src/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs @@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Pokemon(IMessage imsg, [Remainder] string pokemon = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; pokemon = pokemon?.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(pokemon)) @@ -64,7 +64,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task PokemonAbility(IMessage imsg, [Remainder] string ability = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; ability = ability?.Trim().ToUpperInvariant().Replace(" ", ""); if (string.IsNullOrWhiteSpace(ability)) diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index ea571a23..1f587161 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -30,7 +30,7 @@ namespace NadekoBot.Modules.Searches [RequireContext(ContextType.Guild)] public async Task Weather(IMessage imsg, string city, string country) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; city = city.Replace(" ", ""); country = city.Replace(" ", ""); string response; @@ -51,9 +51,9 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Youtube(IMessage imsg, [Remainder] string query = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; - var result = (await _google.FindVideosByKeywordsAsync(query, 1)).FirstOrDefault(); + var result = (await _google.GetVideosByKeywordsAsync(query, 1)).FirstOrDefault(); if (string.IsNullOrWhiteSpace(result)) { await channel.SendMessageAsync("No results found for that query."); @@ -66,7 +66,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Imdb(IMessage imsg, [Remainder] string query = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; await imsg.Channel.TriggerTypingAsync().ConfigureAwait(false); @@ -90,7 +90,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task RandomCat(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; using (var http = new HttpClient()) { await channel.SendMessageAsync(JObject.Parse( @@ -103,7 +103,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task RandomDog(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; using (var http = new HttpClient()) { await channel.SendMessageAsync("http://random.dog/" + await http.GetStringAsync("http://random.dog/woof").ConfigureAwait(false)).ConfigureAwait(false); @@ -114,7 +114,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task I(IMessage imsg, [Remainder] string query = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(query)) return; @@ -144,7 +144,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Ir(IMessage imsg, [Remainder] string query = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(query)) return; @@ -176,7 +176,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Lmgtfy(IMessage imsg, [Remainder] string ffs = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; if (string.IsNullOrWhiteSpace(ffs)) @@ -190,7 +190,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Google(IMessage imsg, [Remainder] string terms = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; terms = terms?.Trim(); @@ -204,7 +204,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 //[RequireContext(ContextType.Guild)] //public async Task Hearthstone(IMessage imsg, [Remainder] string name = null) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var arg = name; // if (string.IsNullOrWhiteSpace(arg)) // { @@ -249,7 +249,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Ud(IMessage imsg, [Remainder] string query = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var arg = query; if (string.IsNullOrWhiteSpace(arg)) @@ -283,7 +283,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Hashtag(IMessage imsg, [Remainder] string query = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var arg = query; if (string.IsNullOrWhiteSpace(arg)) @@ -318,7 +318,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 //[RequireContext(ContextType.Guild)] //public async Task Quote(IMessage imsg) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // var quote = NadekoBot.Config.Quotes[rng.Next(0, NadekoBot.Config.Quotes.Count)].ToString(); // await channel.SendMessageAsync(quote).ConfigureAwait(false); @@ -328,7 +328,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Catfact(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; using (var http = new HttpClient()) { var response = await http.GetStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false); @@ -342,7 +342,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Revav(IMessage imsg, [Remainder] string arg = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var usrStr = arg?.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(usrStr)) @@ -359,7 +359,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Revimg(IMessage imsg, [Remainder] string imageLink = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; imageLink = imageLink?.Trim() ?? ""; if (string.IsNullOrWhiteSpace(imageLink)) @@ -371,7 +371,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Safebooru(IMessage imsg, [Remainder] string tag = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; tag = tag?.Trim() ?? ""; var link = await GetSafebooruImageLink(tag).ConfigureAwait(false); @@ -385,7 +385,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Wiki(IMessage imsg, [Remainder] string query = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; query = query?.Trim(); if (string.IsNullOrWhiteSpace(query)) @@ -406,7 +406,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 //[RequireContext(ContextType.Guild)] //public async Task Clr(IMessage imsg, [Remainder] string color = null) //{ - // var channel = imsg.Channel as ITextChannel; + // var channel = (ITextChannel)imsg.Channel; // color = color?.Trim().Replace("#", ""); // if (string.IsNullOrWhiteSpace((string)color)) @@ -431,7 +431,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Videocall(IMessage imsg, [Remainder] string arg = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { @@ -454,7 +454,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 [RequireContext(ContextType.Guild)] public async Task Avatar(IMessage imsg, [Remainder] string mention = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var usr = imsg.MentionedUsers.FirstOrDefault(); if (usr == null) diff --git a/src/NadekoBot/Modules/Translator/Translator.cs b/src/NadekoBot/Modules/Translator/Translator.cs index c6833b4c..a53e0eb6 100644 --- a/src/NadekoBot/Modules/Translator/Translator.cs +++ b/src/NadekoBot/Modules/Translator/Translator.cs @@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Translator [RequireContext(ContextType.Guild)] public async Task Translate(IMessage imsg, string langs, [Remainder] string text = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; try { @@ -48,7 +48,7 @@ namespace NadekoBot.Modules.Translator [RequireContext(ContextType.Guild)] public async Task Translangs(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.SendTableAsync(GoogleTranslator.Instance.Languages, str => str, columns: 4); } diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs index 587debef..a9f9ecbb 100644 --- a/src/NadekoBot/Modules/Utility/Utility.cs +++ b/src/NadekoBot/Modules/Utility/Utility.cs @@ -27,7 +27,7 @@ namespace NadekoBot.Modules.Utility [RequireContext(ContextType.Guild)] public async Task WhoPlays(IMessage imsg, [Remainder] string game = null) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; game = game.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(game)) return; @@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Utility { if (string.IsNullOrWhiteSpace(roles)) return; - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; var arg = roles.Split(',').Select(r => r.Trim().ToUpperInvariant()); string send = _l["`Here is a list of users in a specfic role:`"]; foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str) && str != "@EVERYONE" && str != "EVERYONE")) @@ -133,7 +133,7 @@ namespace NadekoBot.Modules.Utility [RequireContext(ContextType.Guild)] public async Task Stats(IMessage imsg) { - var channel = imsg.Channel as ITextChannel; + var channel = (ITextChannel)imsg.Channel; await channel.SendMessageAsync(await NadekoBot.Stats.Print()); } diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index c20aa1fb..d71c5364 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -23,7 +23,7 @@ namespace NadekoBot public static Localization Localizer { get; private set; } public static BotCredentials Credentials { get; private set; } - private static GoogleApiService Youtube { get; set; } + public static GoogleApiService Google { get; set; } public static StatsService Stats { get; private set; } public async Task RunAsync(string[] args) @@ -43,7 +43,7 @@ namespace NadekoBot Commands = new CommandService(); Config = new BotConfiguration(); Localizer = new Localization(); - Youtube = new GoogleApiService(); + Google = new GoogleApiService(); Stats = new StatsService(Client); _log = LogManager.GetCurrentClassLogger(); @@ -53,7 +53,7 @@ namespace NadekoBot depMap.Add(Config); depMap.Add(Client); depMap.Add(Commands); - depMap.Add(Youtube); + depMap.Add(Google); //connect await Client.LoginAsync(TokenType.Bot, Credentials.Token); diff --git a/src/NadekoBot/Services/IGoogleApiService.cs b/src/NadekoBot/Services/IGoogleApiService.cs index c872b96e..43d0f4da 100644 --- a/src/NadekoBot/Services/IGoogleApiService.cs +++ b/src/NadekoBot/Services/IGoogleApiService.cs @@ -5,9 +5,10 @@ namespace NadekoBot.Services { public interface IGoogleApiService { - Task> FindVideosByKeywordsAsync(string keywords, int count = 1); - Task> FindPlaylistIdsByKeywordsAsync(string keywords, int count = 1); - Task> FindRelatedVideosAsync(string url, int count = 1); + Task> GetVideosByKeywordsAsync(string keywords, int count = 1); + Task> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1); + Task> GetRelatedVideosAsync(string url, int count = 1); + Task> GetPlaylistTracksAsync(string playlistId, int count = 50); Task ShortenUrl(string url); } diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs index d06a0cbb..f2515391 100644 --- a/src/NadekoBot/Services/Impl/BotCredentials.cs +++ b/src/NadekoBot/Services/Impl/BotCredentials.cs @@ -24,6 +24,8 @@ namespace NadekoBot.Services.Impl public ulong[] OwnerIds { get; } public string LoLApiKey { get; } + public string OsuApiKey { get; } + public string SoundCloudClientId { get; } public BotCredentials() { @@ -36,17 +38,22 @@ namespace NadekoBot.Services.Impl LoLApiKey = cm.LoLApiKey; GoogleApiKey = cm.GoogleApiKey; MashapeKey = cm.MashapeKey; + OsuApiKey = cm.OsuApiKey; + SoundCloudClientId = cm.SoundCloudClientId; } else _log.Fatal("credentials.json is missing. Failed to start."); } - private class CredentialsModel { + private class CredentialsModel + { public string Token { get; set; } public ulong[] OwnerIds { get; set; } public string LoLApiKey { get; set; } public string GoogleApiKey { get; set; } public string MashapeKey { get; set; } + public string OsuApiKey { get; set; } + public string SoundCloudClientId { get; set; } } public bool IsOwner(IUser u) => OwnerIds.Contains(u.Id); diff --git a/src/NadekoBot/Services/Impl/GoogleApiService.cs b/src/NadekoBot/Services/Impl/GoogleApiService.cs index 7a27c785..4d74e290 100644 --- a/src/NadekoBot/Services/Impl/GoogleApiService.cs +++ b/src/NadekoBot/Services/Impl/GoogleApiService.cs @@ -26,7 +26,7 @@ namespace NadekoBot.Services.Impl yt = new YouTubeService(bcs); sh = new UrlshortenerService(bcs); } - public async Task> FindPlaylistIdsByKeywordsAsync(string keywords, int count = 1) + public async Task> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1) { if (string.IsNullOrWhiteSpace(keywords)) throw new ArgumentNullException(nameof(keywords)); @@ -46,7 +46,7 @@ namespace NadekoBot.Services.Impl return (await query.ExecuteAsync()).Items.Select(i => i.Id.PlaylistId); } - public async Task> FindRelatedVideosAsync(string id, int count = 1) + public async Task> GetRelatedVideosAsync(string id, int count = 1) { if (string.IsNullOrWhiteSpace(id)) throw new ArgumentNullException(nameof(id)); @@ -66,7 +66,7 @@ namespace NadekoBot.Services.Impl return (await query.ExecuteAsync()).Items.Select(i => "http://www.youtube.com/watch?v=" + i.Id.VideoId); } - public async Task> FindVideosByKeywordsAsync(string keywords, int count = 1) + public async Task> GetVideosByKeywordsAsync(string keywords, int count = 1) { if (string.IsNullOrWhiteSpace(keywords)) throw new ArgumentNullException(nameof(keywords)); @@ -89,5 +89,37 @@ namespace NadekoBot.Services.Impl var response = await sh.Url.Insert(new Url { LongUrl = url }).ExecuteAsync(); return response.Id; } + + public async Task> GetPlaylistTracksAsync(string playlistId, int count = 50) + { + if (string.IsNullOrWhiteSpace(playlistId)) + throw new ArgumentNullException(nameof(playlistId)); + + if (count <= 0) + throw new ArgumentOutOfRangeException(nameof(count)); + + string nextPageToken = null; + + List toReturn = new List(count); + + do + { + var toGet = count > 50 ? 50 : count; + count -= toGet; + + var query = yt.PlaylistItems.List("contentDetails"); + query.MaxResults = count; + query.PlaylistId = playlistId; + query.PageToken = nextPageToken; + + var data = await query.ExecuteAsync(); + + toReturn.AddRange(data.Items.Select(i => i.ContentDetails.VideoId)); + nextPageToken = data.NextPageToken; + } + while (count > 0 && !string.IsNullOrWhiteSpace(nextPageToken)); + + return toReturn; + } } } diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index d9265ce3..5e574c07 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -22,6 +22,8 @@ namespace NadekoBot.Extensions http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); } + public static double UnixTimestamp(this DateTime dt) => dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + public static async Task SendMessageAsync(this IGuildUser user, string message, bool isTTS = false) => await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(message, isTTS).ConfigureAwait(false); diff --git a/src/NadekoBot/_Modules/Music/Classes/PoopyBuffer.cs b/src/NadekoBot/_Modules/Music/Classes/PoopyBuffer.cs deleted file mode 100644 index c4a95daa..00000000 --- a/src/NadekoBot/_Modules/Music/Classes/PoopyBuffer.cs +++ /dev/null @@ -1,131 +0,0 @@ -ο»Ώusing System; -using System.Threading; -using System.Threading.Tasks; - -namespace NadekoBot.Modules.Music.Classes -{ - - /// - /// πŸ’© - /// - public class PoopyBuffer - { - - private readonly byte[] ringBuffer; - - public int WritePosition { get; private set; } = 0; - public int ReadPosition { get; private set; } = 0; - - public int ContentLength => (WritePosition >= ReadPosition ? - WritePosition - ReadPosition : - (BufferSize - ReadPosition) + WritePosition); - - public int BufferSize { get; } - - private readonly SemaphoreSlim readWriteLock = new SemaphoreSlim(1, 1); - - public PoopyBuffer(int size) - { - if (size <= 0) - throw new ArgumentException(); - BufferSize = size; - ringBuffer = new byte[size]; - } - - public Task ReadAsync(byte[] buffer, int count) - { - return Task.Run(async () => - { - if (buffer.Length < count) - throw new ArgumentException(); - //Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***"); - await readWriteLock.WaitAsync().ConfigureAwait(false); - try - { - //read as much as you can if you're reading too much - if (count > ContentLength) - count = ContentLength; - //if nothing to read, return 0 - if (WritePosition == ReadPosition) - return 0; - // if buffer is in the "normal" state, just read - if (WritePosition > ReadPosition) - { - Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count); - ReadPosition += count; - //Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]"); - return count; - } - //else ReadPos buffer.Length) - throw new ArgumentException(); - while (ContentLength + count > BufferSize) - { - await Task.Delay(20, cancelToken).ConfigureAwait(false); - if (cancelToken.IsCancellationRequested) - return; - } - await Task.Run(async () => - { - //the while above assures that i cannot write past readposition with my write, so i don't have to check - // *unless its multithreaded or task is not awaited - await readWriteLock.WaitAsync().ConfigureAwait(false); - try - { - // if i can just write without hitting buffer.length, do it - if (WritePosition + count < BufferSize) - { - Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count); - WritePosition += count; - //Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]"); - return; - } - // otherwise, i have to write to the end, then write the rest from the start - - var wroteNormaly = BufferSize - WritePosition; - Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, wroteNormaly); - - //Console.WriteLine($"Wrote normally {wroteNormaly}[{WritePosition} to {BufferSize}]"); - - var wroteFromStart = count - wroteNormaly; - Buffer.BlockCopy(buffer, wroteNormaly, ringBuffer, 0, wroteFromStart); - - //Console.WriteLine($"and from start {wroteFromStart} [0 to {wroteFromStart}"); - - WritePosition = wroteFromStart; - } - finally { readWriteLock.Release(); } - }); - } - } -} diff --git a/src/NadekoBot/_Modules/Music/MusicModule.cs b/src/NadekoBot/_Modules/Music/MusicModule.cs deleted file mode 100644 index 49308c94..00000000 --- a/src/NadekoBot/_Modules/Music/MusicModule.cs +++ /dev/null @@ -1,900 +0,0 @@ -ο»Ώusing Discord; -using Discord.Commands; -using Discord.Modules; -using NadekoBot.Classes; -using NadekoBot.DataModels; -using NadekoBot.Extensions; -using NadekoBot.Modules.Music.Classes; -using NadekoBot.Modules.Permissions.Classes; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace NadekoBot.Modules.Music -{ - internal class MusicModule : DiscordModule - { - public static ConcurrentDictionary MusicPlayers = new ConcurrentDictionary(); - - public const string MusicDataPath = "data/musicdata"; - - public MusicModule() - { - //it can fail if its currenctly opened or doesn't exist. Either way i don't care - try { Directory.Delete(MusicDataPath, true); } catch { } - - Directory.CreateDirectory(MusicDataPath); - } - - public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Music; - - public override void Install(ModuleManager manager) - { - var client = NadekoBot.Client; - - manager.CreateCommands("", cgb => - { - - cgb.AddCheck(PermissionChecker.Instance); - - commands.ForEach(cmd => cmd.Init(cgb)); - - cgb.CreateCommand(Prefix + "next") - .Alias(Prefix + "n") - .Alias(Prefix + "skip") - .Description($"Goes to the next song in the queue. You have to be in the same voice channel as the bot. | `{Prefix}n`") - .Do(e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return; - if (musicPlayer.PlaybackVoiceChannel == imsg.Author.VoiceChannel) - musicPlayer.Next(); - }); - - cgb.CreateCommand(Prefix + "stop") - .Alias(Prefix + "s") - .Description($"Stops the music and clears the playlist. Stays in the channel. | `{Prefix}s`") - .Do(e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return; - if (imsg.Author.VoiceChannel == musicPlayer.PlaybackVoiceChannel) - { - musicPlayer.Autoplay = false; - musicPlayer.Stop(); - } - }); - - cgb.CreateCommand(Prefix + "destroy") - .Alias(Prefix + "d") - .Description("Completely stops the music and unbinds the bot from the channel. " + - $"(may cause weird behaviour) | `{Prefix}d`") - .Do(e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryRemove(e.Server, out musicPlayer)) return; - if (imsg.Author.VoiceChannel == musicPlayer.PlaybackVoiceChannel) - musicPlayer.Destroy(); - }); - - cgb.CreateCommand(Prefix + "pause") - .Alias(Prefix + "p") - .Description($"Pauses or Unpauses the song. | `{Prefix}p`") - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return; - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - musicPlayer.TogglePause(); - if (musicPlayer.Paused) - await channel.SendMessageAsync("🎡`Music Player paused.`").ConfigureAwait(false); - else - await channel.SendMessageAsync("🎡`Music Player unpaused.`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "queue") - .Alias(Prefix + "q") - .Alias(Prefix + "yq") - .Description("Queue a song using keywords or a link. Bot will join your voice channel." + - $"**You must be in a voice channel**. | `{Prefix}q Dream Of Venice`") - .Parameter("query", ParameterType.Unparsed) - .Do(async e => - { - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, query).ConfigureAwait(false); - if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages) - { - await Task.Delay(10000).ConfigureAwait(false); - await e.Message.Delete().ConfigureAwait(false); - } - }); - - cgb.CreateCommand(Prefix + "soundcloudqueue") - .Alias(Prefix + "sq") - .Description("Queue a soundcloud song using keywords. Bot will join your voice channel." + - $"**You must be in a voice channel**. | `{Prefix}sq Dream Of Venice`") - .Parameter("query", ParameterType.Unparsed) - .Do(async e => - { - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false); - if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages) - { - await Task.Delay(10000).ConfigureAwait(false); - await e.Message.Delete().ConfigureAwait(false); - } - }); - - cgb.CreateCommand(Prefix + "listqueue") - .Alias(Prefix + "lq") - .Description($"Lists 15 currently queued songs per page. Default page is 1. | `{Prefix}lq` or `{Prefix}lq 2`") - .Parameter("page", ParameterType.Optional) - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - { - await channel.SendMessageAsync("🎡 No active music player.").ConfigureAwait(false); - return; - } - - int page; - if (!int.TryParse(page, out page) || page <= 0) - { - page = 1; - } - - var currentSong = musicPlayer.CurrentSong; - if (currentSong == null) - return; - var toSend = $"🎡`Now Playing` {currentSong.PrettyName} " + $"{currentSong.PrettyCurrentTime()}\n"; - if (musicPlayer.RepeatSong) - toSend += "πŸ”‚"; - else if (musicPlayer.RepeatPlaylist) - toSend += "πŸ”"; - toSend += $" **{musicPlayer.Playlist.Count}** `tracks currently queued. Showing page {page}` "; - if (musicPlayer.MaxQueueSize != 0 && musicPlayer.Playlist.Count >= musicPlayer.MaxQueueSize) - toSend += "**Song queue is full!**\n"; - else - toSend += "\n"; - const int itemsPerPage = 15; - int startAt = itemsPerPage * (page - 1); - var number = 1 + startAt; - await channel.SendMessageAsync(toSend + string.Join("\n", musicPlayer.Playlist.Skip(startAt).Take(15).Select(v => $"`{number++}.` {v.PrettyName}"))).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "nowplaying") - .Alias(Prefix + "np") - .Description($"Shows the song currently playing. | `{Prefix}np`") - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - var currentSong = musicPlayer.CurrentSong; - if (currentSong == null) - return; - await channel.SendMessageAsync($"🎡`Now Playing` {currentSong.PrettyName} " + - $"{currentSong.PrettyCurrentTime()}").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "volume") - .Alias(Prefix + "vol") - .Description($"Sets the music volume 0-100% | `{Prefix}vol 50`") - .Parameter("val", ParameterType.Required) - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - var arg = val; - int volume; - if (!int.TryParse(arg, out volume)) - { - await channel.SendMessageAsync("Volume number invalid.").ConfigureAwait(false); - return; - } - volume = musicPlayer.SetVolume(volume); - await channel.SendMessageAsync($"🎡 `Volume set to {volume}%`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "defvol") - .Alias(Prefix + "dv") - .Description("Sets the default music volume when music playback is started (0-100)." + - $" Persists through restarts. | `{Prefix}dv 80`") - .Parameter("val", ParameterType.Required) - .Do(async e => - { - var arg = val; - float volume; - if (!float.TryParse(arg, out volume) || volume < 0 || volume > 100) - { - await channel.SendMessageAsync("Volume number invalid.").ConfigureAwait(false); - return; - } - var conf = SpecificConfigurations.Default.Of(e.Server.Id); - conf.DefaultMusicVolume = volume / 100; - await channel.SendMessageAsync($"🎡 `Default volume set to {volume}%`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "mute") - .Alias(Prefix + "min") - .Description($"Sets the music volume to 0% | `{Prefix}min`") - .Do(e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - musicPlayer.SetVolume(0); - }); - - cgb.CreateCommand(Prefix + "max") - .Description($"Sets the music volume to 100%. | `{Prefix}max`") - .Do(e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - musicPlayer.SetVolume(100); - }); - - cgb.CreateCommand(Prefix + "half") - .Description($"Sets the music volume to 50%. | `{Prefix}half`") - .Do(e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - musicPlayer.SetVolume(50); - }); - - cgb.CreateCommand(Prefix + "shuffle") - .Alias(Prefix + "sh") - .Description($"Shuffles the current playlist. | `{Prefix}sh`") - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - if (musicPlayer.Playlist.Count < 2) - { - await channel.SendMessageAsync("πŸ’’ Not enough songs in order to perform the shuffle.").ConfigureAwait(false); - return; - } - - musicPlayer.Shuffle(); - await channel.SendMessageAsync("🎡 `Songs shuffled.`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "playlist") - .Alias(Prefix + "pl") - .Description($"Queues up to 500 songs from a youtube playlist specified by a link, or keywords. | `{Prefix}pl playlist link or name`") - .Parameter("playlist", ParameterType.Unparsed) - .Do(async e => - { - var arg = playlist; - if (string.IsNullOrWhiteSpace(arg)) - return; - if (imsg.Author.VoiceChannel?.Server != e.Server) - { - await channel.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false); - return; - } - var plId = await SearchHelper.GetPlaylistIdByKeyword(arg).ConfigureAwait(false); - if (plId == null) - { - await channel.SendMessageAsync("No search results for that query."); - return; - } - var ids = await SearchHelper.GetVideoIDs(plId, 500).ConfigureAwait(false); - if (ids == null || ids.Count == 0) - { - await channel.SendMessageAsync($"🎡 `Failed to find any songs.`").ConfigureAwait(false); - return; - } - var idArray = ids as string[] ?? ids.ToArray(); - var count = idArray.Length; - var msg = - await channel.SendMessageAsync($"🎡 `Attempting to queue {count} songs".SnPl(count) + "...`").ConfigureAwait(false); - foreach (var id in idArray) - { - try - { - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, id, true).ConfigureAwait(false); - } - catch (PlaylistFullException) - { break; } - catch { } - } - await msg.Edit("🎡 `Playlist queue complete.`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "soundcloudpl") - .Alias(Prefix + "scpl") - .Description($"Queue a soundcloud playlist using a link. | `{Prefix}scpl https://soundcloud.com/saratology/sets/symphony`") - .Parameter("pl", ParameterType.Unparsed) - .Do(async e => - { - var pl = pl?.Trim(); - - if (string.IsNullOrWhiteSpace(pl)) - return; - - var scvids = JObject.Parse(await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Credentials.SoundCloudClientID}").ConfigureAwait(false))["tracks"].ToObject(); - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false); - - MusicPlayer mp; - if (!MusicPlayers.TryGetValue(e.Server, out mp)) - return; - - foreach (var svideo in scvids.Skip(1)) - { - try - { - mp.AddSong(new Song(new Classes.SongInfo - { - Title = svideo.FullName, - Provider = "SoundCloud", - Uri = svideo.StreamLink, - ProviderType = MusicType.Normal, - Query = svideo.TrackLink, - }), imsg.Author.Username); - } - catch (PlaylistFullException) { break; } - } - }); - - cgb.CreateCommand(Prefix + "localplaylst") - .Alias(Prefix + "lopl") - .Description($"Queues all songs from a directory. **Bot Owner Only!** | `{Prefix}lopl C:/music/classical`") - .Parameter("directory", ParameterType.Unparsed) - .AddCheck(SimpleCheckers.OwnerOnly()) - .Do(async e => - { - var arg = directory; - if (string.IsNullOrWhiteSpace(arg)) - return; - try - { - var fileEnum = new DirectoryInfo(arg).GetFiles() - .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System)); - foreach (var file in fileEnum) - { - try - { - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false); - } - catch (PlaylistFullException) - { - break; - } - catch { } - } - await channel.SendMessageAsync("🎡 `Directory queue complete.`").ConfigureAwait(false); - } - catch { } - }); - - cgb.CreateCommand(Prefix + "radio").Alias(Prefix + "ra") - .Description($"Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf (Usage Video: ) | `{Prefix}ra radio link here`") - .Parameter("radio_link", ParameterType.Required) - .Do(async e => - { - if (imsg.Author.VoiceChannel?.Server != e.Server) - { - await channel.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false); - return; - } - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false); - if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages) - { - await Task.Delay(10000).ConfigureAwait(false); - await e.Message.Delete().ConfigureAwait(false); - } - }); - - cgb.CreateCommand(Prefix + "local") - .Alias(Prefix + "lo") - .Description($"Queues a local file by specifying a full path. **Bot Owner Only!** | `{Prefix}lo C:/music/mysong.mp3`") - .Parameter("path", ParameterType.Unparsed) - .AddCheck(SimpleCheckers.OwnerOnly()) - .Do(async e => - { - var arg = path; - if (string.IsNullOrWhiteSpace(arg)) - return; - await QueueSong(imsg.Author, e.Channel, imsg.Author.VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "move") - .Alias(Prefix + "mv") - .Description($"Moves the bot to your voice channel. (works only if music is already playing) | `{Prefix}mv`") - .Do(e => - { - MusicPlayer musicPlayer; - var voiceChannel = imsg.Author.VoiceChannel; - if (voiceChannel == null || voiceChannel.Server != e.Server || !MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - musicPlayer.MoveToVoiceChannel(voiceChannel); - }); - - cgb.CreateCommand(Prefix + "remove") - .Alias(Prefix + "rm") - .Description($"Remove a song by its # in the queue, or 'all' to remove whole queue. | `{Prefix}rm 5`") - .Parameter("num", ParameterType.Required) - .Do(async e => - { - var arg = num; - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - { - return; - } - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - if (arg?.ToLower() == "all") - { - musicPlayer.ClearQueue(); - await channel.SendMessageAsync($"🎡`Queue cleared!`").ConfigureAwait(false); - return; - } - int num; - if (!int.TryParse(arg, out num)) - { - return; - } - if (num <= 0 || num > musicPlayer.Playlist.Count) - return; - var song = (musicPlayer.Playlist as List)?[num - 1]; - musicPlayer.RemoveSongAt(num - 1); - await channel.SendMessageAsync($"🎡**Track {song.PrettyName} at position `#{num}` has been removed.**").ConfigureAwait(false); - }); - - //var msRegex = new Regex(@"(?\d+)>(?\d+)", RegexOptions.Compiled); - cgb.CreateCommand(Prefix + "movesong") - .Alias(Prefix + "ms") - .Description($"Moves a song from one position to another. | `{Prefix} ms` 5>3") - .Parameter("fromto") - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - { - return; - } - var fromto = fromto.Trim(); - var fromtoArr = fromto.Split('>'); - - int n1; - int n2; - - var playlist = musicPlayer.Playlist as List ?? musicPlayer.Playlist.ToList(); - - if (fromtoArr.Length != 2 || !int.TryParse(fromtoArr[0], out n1) || - !int.TryParse(fromtoArr[1], out n2) || n1 < 1 || n2 < 1 || n1 == n2 || - n1 > playlist.Count || n2 > playlist.Count) - { - await channel.SendMessageAsync("`Invalid input.`").ConfigureAwait(false); - return; - } - - var s = playlist[n1 - 1]; - playlist.Insert(n2 - 1, s); - var nn1 = n2 < n1 ? n1 : n1 - 1; - playlist.RemoveAt(nn1); - - await channel.SendMessageAsync($"🎡`Moved` {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false); - - }); - - cgb.CreateCommand(Prefix + "setmaxqueue") - .Alias(Prefix + "smq") - .Description($"Sets a maximum queue size. Supply 0 or no argument to have no limit. | `{Prefix}smq` 50 or `{Prefix}smq`") - .Parameter("size", ParameterType.Unparsed) - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - { - return; - } - - var sizeStr = size?.Trim(); - uint size = 0; - if (string.IsNullOrWhiteSpace(sizeStr) || !uint.TryParse(sizeStr, out size)) - { - size = 0; - } - - musicPlayer.MaxQueueSize = size; - await channel.SendMessageAsync($"🎡 `Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}`"); - }); - - cgb.CreateCommand(Prefix + "cleanup") - .Description($"Cleans up hanging voice connections. **Bot Owner Only!** | `{Prefix}cleanup`") - .AddCheck(SimpleCheckers.OwnerOnly()) - .Do(e => - { - foreach (var kvp in MusicPlayers) - { - var songs = kvp.Value.Playlist; - var currentSong = kvp.Value.CurrentSong; - if (songs.Count == 0 && currentSong == null) - { - MusicPlayer throwaway; - MusicPlayers.TryRemove(kvp.Key, out throwaway); - throwaway.Destroy(); - } - } - }); - - cgb.CreateCommand(Prefix + "reptcursong") - .Alias(Prefix + "rcs") - .Description($"Toggles repeat of current song. | `{Prefix}rcs`") - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - var currentSong = musicPlayer.CurrentSong; - if (currentSong == null) - return; - var currentValue = musicPlayer.ToggleRepeatSong(); - await channel.SendMessageAsync(currentValue ? - $"πŸŽ΅πŸ”‚`Repeating track:`{currentSong.PrettyName}" : - $"πŸŽ΅πŸ”‚`Current track repeat stopped.`") - .ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "rpeatplaylst") - .Alias(Prefix + "rpl") - .Description($"Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `{Prefix}rpl`") - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - var currentValue = musicPlayer.ToggleRepeatPlaylist(); - await channel.SendMessageAsync($"πŸŽ΅πŸ”`Repeat playlist {(currentValue ? "enabled" : "disabled")}`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "save") - .Description($"Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes. | `{Prefix}save classical1`") - .Parameter("name", ParameterType.Unparsed) - .Do(async e => - { - var name = name?.Trim(); - - if (string.IsNullOrWhiteSpace(name) || - name.Length > 20 || - name.Contains("-")) - return; - - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - - //to avoid concurrency issues - var currentPlaylist = new List(musicPlayer.Playlist); - var curSong = musicPlayer.CurrentSong; - if (curSong != null) - currentPlaylist.Insert(0, curSong); - - if (!currentPlaylist.Any()) - return; - - - var songInfos = currentPlaylist.Select(s => new DataModels.SongInfo - { - Provider = s.SongInfo.Provider, - ProviderType = (int)s.SongInfo.ProviderType, - Title = s.SongInfo.Title, - Uri = s.SongInfo.Uri, - Query = s.SongInfo.Query, - }).ToList(); - - var playlist = new MusicPlaylist - { - CreatorId = (long)imsg.Author.Id, - CreatorName = imsg.Author.Username, - Name = name.ToLowerInvariant(), - }; - DbHandler.Instance.SaveAll(songInfos); - DbHandler.Instance.Save(playlist); - DbHandler.Instance.Connection.InsertAll(songInfos.Select(s => new PlaylistSongInfo - { - PlaylistId = playlist.Id.Value, - SongInfoId = s.Id.Value - }), typeof(PlaylistSongInfo)); - - await channel.SendMessageAsync($"🎡 `Saved playlist as {name}-{playlist.Id}`").ConfigureAwait(false); - - }); - - cgb.CreateCommand(Prefix + "load") - .Description($"Loads a playlist under a certain name. | `{Prefix}load classical-1`") - .Parameter("name", ParameterType.Unparsed) - .Do(async e => - { - var voiceCh = imsg.Author.VoiceChannel; - var textCh = e.Channel; - if (voiceCh == null || voiceCh.Server != textCh.Server) - { - await textCh.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.").ConfigureAwait(false); - return; - } - var name = name?.Trim().ToLowerInvariant(); - - if (string.IsNullOrWhiteSpace(name)) - return; - - var parts = name.Split('-'); - if (parts.Length != 2) - return; - var playlistName = parts[0]; - - int playlistNumber; - if (!int.TryParse(parts[1], out playlistNumber)) - return; - - var playlist = DbHandler.Instance.FindOne( - p => p.Id == playlistNumber); - - if (playlist == null) - { - await channel.SendMessageAsync("Can't find playlist under that name.").ConfigureAwait(false); - return; - } - - var psis = DbHandler.Instance.FindAll(psi => - psi.PlaylistId == playlist.Id); - - var songInfos = psis.Select(psi => DbHandler.Instance - .FindOne(si => si.Id == psi.SongInfoId)); - - await channel.SendMessageAsync($"`Attempting to load {songInfos.Count()} songs`").ConfigureAwait(false); - foreach (var si in songInfos) - { - try - { - await QueueSong(imsg.Author, textCh, voiceCh, si.Query, true, (MusicType)si.ProviderType).ConfigureAwait(false); - } - catch (PlaylistFullException) - { - break; - } - catch (Exception ex) - { - Console.WriteLine($"Failed QueueSong in load playlist. {ex}"); - } - } - }); - - cgb.CreateCommand(Prefix + "playlists") - .Alias(Prefix + "pls") - .Description($"Lists all playlists. Paginated. 20 per page. Default page is 0. |`{Prefix}pls 1`") - .Parameter("num", ParameterType.Optional) - .Do(e => - { - int num = 0; - int.TryParse(num, out num); - if (num < 0) - return; - var result = DbHandler.Instance.GetPlaylistData(num); - if (result.Count == 0) - channel.SendMessageAsync($"`No saved playlists found on page {num}`").ConfigureAwait(false); - else - channel.SendMessageAsync($"```js\n--- List of saved playlists ---\n\n" + string.Join("\n", result.Select(r => $"'{r.Name}-{r.Id}' by {r.Creator} ({r.SongCnt} songs)")) + $"\n\n --- Page {num} ---```").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "deleteplaylist") - .Alias(Prefix + "delpls") - .Description($"Deletes a saved playlist. Only if you made it or if you are the bot owner. | `{Prefix}delpls animu-5`") - .Parameter("pl", ParameterType.Required) - .Do(async e => - { - var pl = pl.Trim().Split('-')[1]; - if (string.IsNullOrWhiteSpace(pl)) - return; - var plnum = int.Parse(pl); - if (NadekoBot.IsOwner(imsg.Author.Id)) - DbHandler.Instance.Delete(plnum); - else - DbHandler.Instance.DeleteWhere(mp => mp.Id == plnum && (long)imsg.Author.Id == mp.CreatorId); - await channel.SendMessageAsync("`Ok.` :ok:").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "goto") - .Description($"Goes to a specific time in seconds in a song. | `{Prefix}goto 30`") - .Parameter("time") - .Do(async e => - { - var skipToStr = time?.Trim(); - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - if (imsg.Author.VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; - int skipTo; - if (!int.TryParse(skipToStr, out skipTo) || skipTo < 0) - return; - - var currentSong = musicPlayer.CurrentSong; - - if (currentSong == null) - return; - - //currentSong.PrintStatusMessage = false; - var gotoSong = currentSong.Clone(); - gotoSong.SkipTo = skipTo; - musicPlayer.AddSong(gotoSong, 0); - musicPlayer.Next(); - - var minutes = (skipTo / 60).ToString(); - var seconds = (skipTo % 60).ToString(); - - if (minutes.Length == 1) - minutes = "0" + minutes; - if (seconds.Length == 1) - seconds = "0" + seconds; - - await channel.SendMessageAsync($"`Skipped to {minutes}:{seconds}`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "getlink") - .Alias(Prefix + "gl") - .Description($"Shows a link to the song in the queue by index, or the currently playing song by default. | `{Prefix}gl`") - .Parameter("index", ParameterType.Optional) - .Do(async e => - { - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - int index; - string arg = index?.Trim(); - if (!string.IsNullOrEmpty(arg) && int.TryParse(arg, out index)) - { - - var selSong = musicPlayer.Playlist.DefaultIfEmpty(null).ElementAtOrDefault(index - 1); - if (selSong == null) - { - await channel.SendMessageAsync("Could not select song, likely wrong index"); - - } - else - { - await channel.SendMessageAsync($"🎢`Selected song {selSong.SongInfo.Title}:` <{selSong.SongInfo.Query}>").ConfigureAwait(false); - } - } - else - { - var curSong = musicPlayer.CurrentSong; - if (curSong == null) - return; - await channel.SendMessageAsync($"🎢`Current song:` <{curSong.SongInfo.Query}>").ConfigureAwait(false); - } - - }); - - cgb.CreateCommand(Prefix + "autoplay") - .Alias(Prefix + "ap") - .Description($"Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty) | `{Prefix}ap`") - .Do(async e => - { - - MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) - return; - - if (!musicPlayer.ToggleAutoplay()) - await channel.SendMessageAsync("🎢`Autoplay disabled.`").ConfigureAwait(false); - else - await channel.SendMessageAsync("🎢`Autoplay enabled.`").ConfigureAwait(false); - }); - }); - } - - public static async Task QueueSong(User queuer, Channel textCh, Channel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal) - { - if (voiceCh == null || voiceCh.Server != textCh.Server) - { - if (!silent) - await textCh.SendMessageAsync("πŸ’’ You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.").ConfigureAwait(false); - throw new ArgumentNullException(nameof(voiceCh)); - } - if (string.IsNullOrWhiteSpace(query) || query.Length < 3) - throw new ArgumentException("πŸ’’ Invalid query for queue song.", nameof(query)); - - var musicPlayer = MusicPlayers.GetOrAdd(textCh.Server, server => - { - float vol = SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume; - var mp = new MusicPlayer(voiceCh, vol); - - - Message playingMessage = null; - Message lastFinishedMessage = null; - mp.OnCompleted += async (s, song) => - { - if (song.PrintStatusMessage) - { - try - { - if (lastFinishedMessage != null) - await lastFinishedMessage.Delete().ConfigureAwait(false); - if (playingMessage != null) - await playingMessage.Delete().ConfigureAwait(false); - lastFinishedMessage = await textCh.SendMessageAsync($"🎡`Finished`{song.PrettyName}").ConfigureAwait(false); - if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube") - { - await QueueSong(queuer.Server.CurrentUser, textCh, voiceCh, (await SearchHelper.GetRelatedVideoIds(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false); - } - } - catch (Exception e) - { - Console.WriteLine(e); - } - } - }; - mp.OnStarted += async (s, song) => - { - if (song.PrintStatusMessage) - { - var sender = s as MusicPlayer; - if (sender == null) - return; - - try - { - - var msgTxt = $"🎡`Playing`{song.PrettyName} `Vol: {(int)(sender.Volume * 100)}%`"; - playingMessage = await textCh.SendMessageAsync(msgTxt).ConfigureAwait(false); - } - catch { } - } - }; - return mp; - }); - Song resolvedSong; - try - { - musicPlayer.ThrowIfQueueFull(); - resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false); - - musicPlayer.AddSong(resolvedSong, queuer.Name); - } - catch (PlaylistFullException) - { - await textCh.SendMessageAsync($"🎡 `Queue is full at {musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}.` "); - throw; - } - if (!silent) - { - var queuedMessage = await textCh.SendMessageAsync($"🎡`Queued`{resolvedSong.PrettyName} **at** `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false); -#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed - Task.Run(async () => - { - await Task.Delay(10000).ConfigureAwait(false); - try - { - await queuedMessage.Delete().ConfigureAwait(false); - } - catch { } - }).ConfigureAwait(false); -#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed - } - } - } -} diff --git a/src/NadekoBot/project.json b/src/NadekoBot/project.json index 75b7a326..329311cc 100644 --- a/src/NadekoBot/project.json +++ b/src/NadekoBot/project.json @@ -5,9 +5,11 @@ "copyright": "Kwoth", "buildOptions": { "emitEntryPoint": true, + "allowUnsafe": true, "compile": { "exclude": [ "_Models", "Classes", "_Modules" ] - } + }, + "define": [] }, "dependencies": { "Microsoft.NETCore.App": { @@ -24,12 +26,16 @@ "Google.Apis.YouTube.v3": "1.15.0.582", "Google.Apis.Urlshortener.v1": "1.15.0.138", "System.Diagnostics.Contracts": "4.0.1", - "NLog": "4.4.0-betaV15" + "NLog": "4.4.0-betaV15", + "VideoLibrary": "1.3.4" }, "frameworks": { "netcoreapp1.0": { - "imports": "dnxcore50" + "imports": [ + "dnxcore50", + "portable-net45+win8+wpa81" + ] } } } diff --git a/src/NadekoBot/project.lock.json b/src/NadekoBot/project.lock.json index 430c2ca3..4fb84727 100644 --- a/src/NadekoBot/project.lock.json +++ b/src/NadekoBot/project.lock.json @@ -680,6 +680,9 @@ }, "compile": { "ref/netstandard1.3/System.Collections.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Collections.Concurrent/4.0.12": { @@ -884,6 +887,9 @@ }, "compile": { "ref/netstandard1.3/System.Diagnostics.Debug.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Diagnostics.DiagnosticSource/4.0.0": { @@ -994,6 +1000,9 @@ }, "compile": { "ref/netstandard1.0/System.Diagnostics.Tools.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Diagnostics.TraceSource/4.0.0": { @@ -1032,6 +1041,9 @@ }, "compile": { "ref/netstandard1.5/System.Diagnostics.Tracing.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wpa81/_._": {} } }, "System.Dynamic.Runtime/4.0.11": { @@ -1069,6 +1081,9 @@ }, "compile": { "ref/netstandard1.3/System.Globalization.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Globalization.Calendars/4.0.1": { @@ -1118,6 +1133,9 @@ }, "compile": { "ref/netstandard1.5/System.IO.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.IO.Compression/4.1.0": { @@ -1141,6 +1159,9 @@ "compile": { "ref/netstandard1.3/System.IO.Compression.dll": {} }, + "runtime": { + "lib/portable-net45+win8+wpa81/_._": {} + }, "runtimeTargets": { "runtimes/unix/lib/netstandard1.3/System.IO.Compression.dll": { "assetType": "runtime", @@ -1400,6 +1421,9 @@ "compile": { "ref/netstandard1.3/System.Net.Http.dll": {} }, + "runtime": { + "lib/portable-net45+win8+wpa81/_._": {} + }, "runtimeTargets": { "runtimes/unix/lib/netstandard1.6/System.Net.Http.dll": { "assetType": "runtime", @@ -1453,6 +1477,9 @@ }, "compile": { "ref/netstandard1.3/System.Net.Primitives.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Net.Requests/4.0.11": { @@ -1475,6 +1502,9 @@ "compile": { "ref/netstandard1.3/System.Net.Requests.dll": {} }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} + }, "runtimeTargets": { "runtimes/unix/lib/netstandard1.3/System.Net.Requests.dll": { "assetType": "runtime", @@ -1650,6 +1680,9 @@ }, "compile": { "ref/netstandard1.5/System.Reflection.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Reflection.DispatchProxy/4.0.1": { @@ -1728,6 +1761,9 @@ }, "compile": { "ref/netstandard1.0/System.Reflection.Extensions.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Reflection.Metadata/1.3.0": { @@ -1765,6 +1801,9 @@ }, "compile": { "ref/netstandard1.0/System.Reflection.Primitives.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Reflection.TypeExtensions/4.1.0": { @@ -1807,6 +1846,9 @@ }, "compile": { "ref/netstandard1.0/System.Resources.ResourceManager.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Resources.ResourceWriter/4.0.0-beta-22816": { @@ -1830,6 +1872,9 @@ }, "compile": { "ref/netstandard1.5/System.Runtime.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp80+wpa81/_._": {} } }, "System.Runtime.Extensions/4.1.0": { @@ -1841,6 +1886,9 @@ }, "compile": { "ref/netstandard1.5/System.Runtime.Extensions.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Runtime.Handles/4.0.1": { @@ -1866,6 +1914,9 @@ }, "compile": { "ref/netstandard1.5/System.Runtime.InteropServices.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wpa81/_._": {} } }, "System.Runtime.InteropServices.RuntimeInformation/4.0.0": { @@ -2218,6 +2269,9 @@ }, "compile": { "ref/netstandard1.3/System.Text.Encoding.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Text.Encoding.CodePages/4.0.1": { @@ -2256,6 +2310,9 @@ }, "compile": { "ref/netstandard1.3/System.Text.Encoding.Extensions.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Text.RegularExpressions/4.1.0": { @@ -2319,6 +2376,9 @@ }, "compile": { "ref/netstandard1.3/System.Threading.Tasks.dll": {} + }, + "runtime": { + "lib/portable-net45+win8+wp8+wpa81/_._": {} } }, "System.Threading.Tasks.Dataflow/4.6.0": { @@ -2522,6 +2582,15 @@ "lib/netstandard1.3/_._": {} } }, + "VideoLibrary/1.3.4": { + "type": "package", + "compile": { + "lib/portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10/libvideo.dll": {} + }, + "runtime": { + "lib/portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10/libvideo.dll": {} + } + }, "Discord.Net/1.0.0-dev": { "type": "project", "framework": ".NETStandard,Version=v1.3", @@ -7871,6 +7940,16 @@ "ref/xamarinwatchos10/_._" ] }, + "VideoLibrary/1.3.4": { + "sha512": "HZ2RAE9xx/sjJGnwm8etawoJXYluaYGas4bAFpE14S62NFodNKzUf7Cm9TQ+JFJxAdY+1g1FEKk1b6FPSv9aMg==", + "type": "package", + "path": "VideoLibrary/1.3.4", + "files": [ + "VideoLibrary.1.3.4.nupkg.sha512", + "VideoLibrary.nuspec", + "lib/portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10/libvideo.dll" + ] + }, "Discord.Net/1.0.0-dev": { "type": "project", "path": "../../discord.net/src/Discord.Net/project.json", @@ -7895,7 +7974,8 @@ "NLog >= 4.4.0-betaV15", "Newtonsoft.Json >= 9.0.1", "System.Diagnostics.Contracts >= 4.0.1", - "System.Resources.ResourceWriter >= 4.0.0-beta-22816" + "System.Resources.ResourceWriter >= 4.0.0-beta-22816", + "VideoLibrary >= 1.3.4" ], ".NETCoreApp,Version=v1.0": [] }, From 90a1aa45a93f538341eaf74c4d2cfbd8846da5cf Mon Sep 17 00:00:00 2001 From: Kwoth Date: Mon, 22 Aug 2016 00:47:06 +0200 Subject: [PATCH 4/4] Fixed some broken command strings --- src/NadekoBot/Modules/Music/Classes/Song.cs | 2 +- .../Music/{MusicModule.cs => Music.cs} | 4 +- .../Resources/CommandStrings.Designer.cs | 134 +++++++++--------- src/NadekoBot/Resources/CommandStrings.resx | 28 ++-- 4 files changed, 84 insertions(+), 84 deletions(-) rename src/NadekoBot/Modules/Music/{MusicModule.cs => Music.cs} (99%) diff --git a/src/NadekoBot/Modules/Music/Classes/Song.cs b/src/NadekoBot/Modules/Music/Classes/Song.cs index 4e0d0184..db4b06ea 100644 --- a/src/NadekoBot/Modules/Music/Classes/Song.cs +++ b/src/NadekoBot/Modules/Music/Classes/Song.cs @@ -75,7 +75,7 @@ namespace NadekoBot.Modules.Music.Classes internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { - var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); + var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); SongBuffer sb = new SongBuffer(filename, SongInfo, skipTo); var bufferTask = sb.BufferSong(cancelToken).ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Music/MusicModule.cs b/src/NadekoBot/Modules/Music/Music.cs similarity index 99% rename from src/NadekoBot/Modules/Music/MusicModule.cs rename to src/NadekoBot/Modules/Music/Music.cs index 48ae23c2..4d773f5f 100644 --- a/src/NadekoBot/Modules/Music/MusicModule.cs +++ b/src/NadekoBot/Modules/Music/Music.cs @@ -17,14 +17,14 @@ using System.Collections.Generic; namespace NadekoBot.Modules.Music { [Module("!!", AppendSpace = false)] - public partial class MusicModule : DiscordModule + public partial class Music : DiscordModule { public static ConcurrentDictionary MusicPlayers = new ConcurrentDictionary(); public const string MusicDataPath = "data/musicdata"; private IGoogleApiService _google; - public MusicModule(ILocalization loc, CommandService cmds, IBotConfiguration config, DiscordSocketClient client, IGoogleApiService google) : base(loc, cmds, config, client) + public Music(ILocalization loc, CommandService cmds, IBotConfiguration config, DiscordSocketClient client, IGoogleApiService google) : base(loc, cmds, config, client) { //it can fail if its currenctly opened or doesn't exist. Either way i don't care try { Directory.Delete(MusicDataPath, true); } catch { } diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index bf1f80b2..e925fecc 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -3734,27 +3734,27 @@ namespace NadekoBot.Resources { /// /// Looks up a localized string similar to Queues all songs from a directory. **Bot Owner Only!**. /// - public static string localplaylst_desc { + public static string localpl_desc { get { - return ResourceManager.GetString("localplaylst_desc", resourceCulture); + return ResourceManager.GetString("localpl_desc", resourceCulture); } } /// /// Looks up a localized string similar to `!!lopl C:/music/classical`. /// - public static string localplaylst_summary { + public static string localpl_summary { get { - return ResourceManager.GetString("localplaylst_summary", resourceCulture); + return ResourceManager.GetString("localpl_summary", resourceCulture); } } /// /// Looks up a localized string similar to localplaylst. /// - public static string localplaylst_text { + public static string localpl_text { get { - return ResourceManager.GetString("localplaylst_text", resourceCulture); + return ResourceManager.GetString("localpl_text", resourceCulture); } } @@ -4352,57 +4352,57 @@ namespace NadekoBot.Resources { } } - /// - /// Looks up a localized string similar to Shows information about an osu beatmap.. - /// - public static string osubeatmap_desc { - get { - return ResourceManager.GetString("osubeatmap_desc", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to `~osu b https://osu.ppy.sh/s/127712`. - /// - public static string osubeatmap_summary { - get { - return ResourceManager.GetString("osubeatmap_summary", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to osu b. - /// - public static string osubeatmap_text { - get { - return ResourceManager.GetString("osubeatmap_text", resourceCulture); - } - } - /// /// Looks up a localized string similar to Displays a user's top 5 plays.. /// - public static string osutop5_desc { + public static string osu5_desc { get { - return ResourceManager.GetString("osutop5_desc", resourceCulture); + return ResourceManager.GetString("osu5_desc", resourceCulture); } } /// /// Looks up a localized string similar to `~osu top5 Name`. /// - public static string osutop5_summary { + public static string osu5_summary { get { - return ResourceManager.GetString("osutop5_summary", resourceCulture); + return ResourceManager.GetString("osu5_summary", resourceCulture); } } /// - /// Looks up a localized string similar to osu top5. + /// Looks up a localized string similar to osu5. /// - public static string osutop5_text { + public static string osu5_text { get { - return ResourceManager.GetString("osutop5_text", resourceCulture); + return ResourceManager.GetString("osu5_text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shows information about an osu beatmap.. + /// + public static string osub_desc { + get { + return ResourceManager.GetString("osub_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `~osu b https://osu.ppy.sh/s/127712`. + /// + public static string osub_summary { + get { + return ResourceManager.GetString("osub_summary", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to osub. + /// + public static string osub_text { + get { + return ResourceManager.GetString("osub_text", resourceCulture); } } @@ -5189,6 +5189,33 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue).. + /// + public static string repeatpl_desc { + get { + return ResourceManager.GetString("repeatpl_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `!!rpl`. + /// + public static string repeatpl_summary { + get { + return ResourceManager.GetString("repeatpl_summary", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to rpeatplaylst. + /// + public static string repeatpl_text { + get { + return ResourceManager.GetString("repeatpl_text", resourceCulture); + } + } + /// /// Looks up a localized string similar to Toggles repeat of current song.. /// @@ -5594,33 +5621,6 @@ namespace NadekoBot.Resources { } } - /// - /// Looks up a localized string similar to Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue).. - /// - public static string rpeatplaylst_desc { - get { - return ResourceManager.GetString("rpeatplaylst_desc", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to `!!rpl`. - /// - public static string rpeatplaylst_summary { - get { - return ResourceManager.GetString("rpeatplaylst_summary", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to rpeatplaylst. - /// - public static string rpeatplaylst_text { - get { - return ResourceManager.GetString("rpeatplaylst_text", resourceCulture); - } - } - /// /// Looks up a localized string similar to Play a game of rocket paperclip scissors with Nadeko.. /// diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index e33eeace..ef9e269b 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -1773,13 +1773,13 @@ `!!scpl soundcloudseturl` - + localplaylst - + Queues all songs from a directory. **Bot Owner Only!** - + `!!lopl C:/music/classical` @@ -1854,13 +1854,13 @@ `!!rcs` - + rpeatplaylst - + Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). - + `!!rpl` @@ -2061,22 +2061,22 @@ `~osu Name` or `~osu Name taiko` - - osu b + + osub - + Shows information about an osu beatmap. - + `~osu b https://osu.ppy.sh/s/127712` - - osu top5 + + osu5 - + Displays a user's top 5 plays. - + `~osu top5 Name`