diff --git a/src/NadekoBot/Classes/SearchHelper.cs b/src/NadekoBot/Classes/SearchHelper.cs index 3b30a205..1339c9d8 100644 --- a/src/NadekoBot/Classes/SearchHelper.cs +++ b/src/NadekoBot/Classes/SearchHelper.cs @@ -133,13 +133,6 @@ namespace NadekoBot.Classes token = JObject.Parse(content)["access_token"].ToString(); } - public static async Task ValidateQuery(Discord.Channel ch, string query) - { - if (!string.IsNullOrEmpty(query.Trim())) return true; - await ch.Send("Please specify search parameters.").ConfigureAwait(false); - return false; - } - public static async Task FindYoutubeUrlByKeywords(string keywords) { if (string.IsNullOrWhiteSpace(keywords)) @@ -249,10 +242,7 @@ namespace NadekoBot.Classes return toReturn; } - - - public static async Task ShortenUrl(string url) { if (string.IsNullOrWhiteSpace(NadekoBot.Creds.GoogleAPIKey)) return url; diff --git a/src/NadekoBot/Modules/NSFW/NSFWModule.cs b/src/NadekoBot/Modules/NSFW/NSFWModule.cs index 037fff63..a91bc0bf 100644 --- a/src/NadekoBot/Modules/NSFW/NSFWModule.cs +++ b/src/NadekoBot/Modules/NSFW/NSFWModule.cs @@ -190,22 +190,6 @@ namespace NadekoBot.Modules.NSFW } } - public static async Task GetSafebooruImageLink(string tag) - { - var rng = new Random(); - var url = - $"http://safebooru.org/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}"; - using (var http = new HttpClient()) - { - var webpage = await http.GetStringAsync(url).ConfigureAwait(false); - var matches = Regex.Matches(webpage, "file_url=\"(?.*?)\""); - if (matches.Count == 0) - return null; - var match = matches[rng.Next(0, matches.Count)]; - return matches[rng.Next(0, matches.Count)].Groups["url"].Value; - } - } - public static async Task GetRule34ImageLink(string tag) { var rng = new Random(); diff --git a/src/NadekoBot/_Modules/Searches/Commands/ConverterCommand.cs b/src/NadekoBot/Modules/Searches/Commands/ConverterCommand.cs similarity index 100% rename from src/NadekoBot/_Modules/Searches/Commands/ConverterCommand.cs rename to src/NadekoBot/Modules/Searches/Commands/ConverterCommand.cs diff --git a/src/NadekoBot/_Modules/Searches/Commands/EvalCommand.cs b/src/NadekoBot/Modules/Searches/Commands/EvalCommand.cs similarity index 100% rename from src/NadekoBot/_Modules/Searches/Commands/EvalCommand.cs rename to src/NadekoBot/Modules/Searches/Commands/EvalCommand.cs diff --git a/src/NadekoBot/_Modules/Searches/Commands/IMDB/ImdbMovie.cs b/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbMovie.cs similarity index 100% rename from src/NadekoBot/_Modules/Searches/Commands/IMDB/ImdbMovie.cs rename to src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbMovie.cs diff --git a/src/NadekoBot/_Modules/Searches/Commands/IMDB/ImdbScraper.cs b/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs similarity index 100% rename from src/NadekoBot/_Modules/Searches/Commands/IMDB/ImdbScraper.cs rename to src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs diff --git a/src/NadekoBot/_Modules/Searches/Commands/LoLCommands.cs b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs similarity index 98% rename from src/NadekoBot/_Modules/Searches/Commands/LoLCommands.cs rename to src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs index d5e11c92..612634c9 100644 --- a/src/NadekoBot/_Modules/Searches/Commands/LoLCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs @@ -92,7 +92,7 @@ namespace NadekoBot.Modules.Searches.Commands await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); return; } - var allData = JArray.Parse(await Classes.SearchHelper.GetResponseStringAsync($"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.Creds.LOLAPIKey}").ConfigureAwait(false)); JToken data = null; if (role != null) { @@ -132,7 +132,7 @@ namespace NadekoBot.Modules.Searches.Commands if (roles[i] == role) roles[i] = ">" + roles[i] + "<"; } - var general = JArray.Parse(await SearchHelper.GetResponseStringAsync($"http://api.champion.gg/stats/" + + var general = JArray.Parse(await http.GetStringAsync($"http://api.champion.gg/stats/" + $"champs/{name}?api_key={NadekoBot.Creds.LOLAPIKey}") .ConfigureAwait(false)) .FirstOrDefault(jt => jt["role"].ToString() == role)?["general"]; diff --git a/src/NadekoBot/_Modules/Searches/Commands/MemegenCommands.cs b/src/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs similarity index 94% rename from src/NadekoBot/_Modules/Searches/Commands/MemegenCommands.cs rename to src/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs index 62c4779c..e7993940 100644 --- a/src/NadekoBot/_Modules/Searches/Commands/MemegenCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs @@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Searches.Commands { int i = 0; await channel.SendMessageAsync("`List Of Commands:`\n```xl\n" + - string.Join("\n", JsonConvert.DeserializeObject>(await SearchHelper.GetResponseStringAsync("http://memegen.link/templates/")) + string.Join("\n", JsonConvert.DeserializeObject>(await http.GetStringAsync("http://memegen.link/templates/")) .Select(kvp => Path.GetFileName(kvp.Value)) .GroupBy(item => (i++) / 4) .Select(ig => string.Concat(ig.Select(el => $"{el,-17}")))) diff --git a/src/NadekoBot/_Modules/Searches/Commands/OsuCommands.cs b/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs similarity index 97% rename from src/NadekoBot/_Modules/Searches/Commands/OsuCommands.cs rename to src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs index 94251751..19724576 100644 --- a/src/NadekoBot/_Modules/Searches/Commands/OsuCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/OsuCommands.cs @@ -73,7 +73,7 @@ namespace NadekoBot.Modules.Searches.Commands { 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 SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false))[0]; + 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"]}"), 2); var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss"); @@ -114,12 +114,12 @@ namespace NadekoBot.Modules.Searches.Commands } 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 SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false)); + 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 SearchHelper.GetResponseStringAsync(mapReqString).ConfigureAwait(false))[0]; + var map = JArray.Parse(await http.GetStringAsync(mapReqString).ConfigureAwait(false))[0]; var pp = Math.Round(Double.Parse($"{item["pp"]}"), 2); var acc = CalculateAcc(item, m); var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}")); diff --git a/src/NadekoBot/_Modules/Searches/Commands/PokemonSearchCommands.cs b/src/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs similarity index 100% rename from src/NadekoBot/_Modules/Searches/Commands/PokemonSearchCommands.cs rename to src/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs diff --git a/src/NadekoBot/_Modules/Searches/Commands/RedditCommand.cs b/src/NadekoBot/Modules/Searches/Commands/RedditCommand.cs similarity index 100% rename from src/NadekoBot/_Modules/Searches/Commands/RedditCommand.cs rename to src/NadekoBot/Modules/Searches/Commands/RedditCommand.cs diff --git a/src/NadekoBot/_Modules/Searches/Commands/StreamNotifications.cs b/src/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs similarity index 98% rename from src/NadekoBot/_Modules/Searches/Commands/StreamNotifications.cs rename to src/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs index 936ad52c..59a20dbc 100644 --- a/src/NadekoBot/_Modules/Searches/Commands/StreamNotifications.cs +++ b/src/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs @@ -85,7 +85,7 @@ namespace NadekoBot.Modules.Searches.Commands var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}"; if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result)) return result; - response = await SearchHelper.GetResponseStringAsync(hitboxUrl).ConfigureAwait(false); + response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false); data = JObject.Parse(response); isLive = data["media_is_live"].ToString() == "1"; result = new Tuple(isLive, data["media_views"].ToString()); @@ -95,7 +95,7 @@ namespace NadekoBot.Modules.Searches.Commands var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}"; if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result)) return result; - response = await SearchHelper.GetResponseStringAsync(twitchUrl).ConfigureAwait(false); + response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false); data = JObject.Parse(response); isLive = !string.IsNullOrWhiteSpace(data["stream"].ToString()); result = new Tuple(isLive, isLive ? data["stream"]["viewers"].ToString() : "0"); @@ -105,7 +105,7 @@ namespace NadekoBot.Modules.Searches.Commands var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}"; if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result)) return result; - response = await SearchHelper.GetResponseStringAsync(beamUrl).ConfigureAwait(false); + response = await http.GetStringAsync(beamUrl).ConfigureAwait(false); data = JObject.Parse(response); isLive = data["online"].ToObject() == true; result = new Tuple(isLive, data["viewersCurrent"].ToString()); diff --git a/src/NadekoBot/_Modules/Searches/Commands/WowJokes.cs b/src/NadekoBot/Modules/Searches/Commands/WowJokes.cs similarity index 100% rename from src/NadekoBot/_Modules/Searches/Commands/WowJokes.cs rename to src/NadekoBot/Modules/Searches/Commands/WowJokes.cs diff --git a/src/NadekoBot/Modules/Searches/SearchesModule.cs b/src/NadekoBot/Modules/Searches/SearchesModule.cs new file mode 100644 index 00000000..bf18d845 --- /dev/null +++ b/src/NadekoBot/Modules/Searches/SearchesModule.cs @@ -0,0 +1,584 @@ +ο»Ώusing Discord; +using Discord.Commands; +using NadekoBot.Modules.Searches.Commands.IMDB; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using NadekoBot.Services; +using System.Threading.Tasks; +using NadekoBot.Attributes; +using NadekoBot.Extensions; +using Discord.API; +using System.Text.RegularExpressions; + +namespace NadekoBot.Modules.Searches +{ + [Module("~", AppendSpace = false)] + public class SearchesModule : DiscordModule + { + private readonly Random rng; + + public SearchesModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client) + { + rng = new Random(); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Weather(IMessage imsg, string city, string country) + { + var channel = imsg.Channel as IGuildChannel; + city = city.Replace(" ", ""); + country = city.Replace(" ", ""); + string response; + using (var http = new HttpClient()) + response = await http.GetStringAsync($"http://api.lawlypopzz.xyz/nadekobot/weather/?city={city}&country={country}").ConfigureAwait(false); + + var obj = JObject.Parse(response)["weather"]; + + await imsg.Channel.SendMessageAsync( +$@"🌍 **Weather for** 【{obj["target"]}】 +πŸ“ **Lat,Long:** ({obj["latitude"]}, {obj["longitude"]}) ☁ **Condition:** {obj["condition"]} +πŸ˜“ **Humidity:** {obj["humidity"]}% πŸ’¨ **Wind Speed:** {obj["windspeedk"]}km/h / {obj["windspeedm"]}mph +πŸ”† **Temperature:** {obj["centigrade"]}Β°C / {obj["fahrenheit"]}Β°F πŸ”† **Feels like:** {obj["feelscentigrade"]}Β°C / {obj["feelsfahrenheit"]}Β°F +πŸŒ„ **Sunrise:** {obj["sunrise"]} πŸŒ‡ **Sunset:** {obj["sunset"]}").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Youtube(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; + var link = await FindYoutubeUrlByKeywords(query).ConfigureAwait(false); + if (string.IsNullOrWhiteSpace(link)) + { + await imsg.Channel.SendMessageAsync("No results found for that query."); + return; + } + var shortUrl = await link.ShortenUrl().ConfigureAwait(false); + await imsg.Channel.SendMessageAsync(shortUrl).ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Anime(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; + string result; + try + { + result = (await GetAnimeData(query).ConfigureAwait(false)).ToString(); + } + catch + { + await imsg.Channel.SendMessageAsync("Failed to find that anime.").ConfigureAwait(false); + return; + } + + await imsg.Channel.SendMessageAsync(result.ToString()).ConfigureAwait(false); + } + + + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Manga(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; + string result; + try + { + result = (await GetMangaData(query).ConfigureAwait(false)).ToString(); + } + catch + { + await imsg.Channel.SendMessageAsync("Failed to find that manga.").ConfigureAwait(false); + return; + } + await imsg.Channel.SendMessageAsync(result).ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Imdb(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + if (!(await ValidateQuery(imsg.Channel as ITextChannel, query).ConfigureAwait(false))) return; + await e.Channel.SendIsTyping().ConfigureAwait(false); + string result; + try + { + var movie = ImdbScraper.ImdbScrape(query, true); + if (movie.Status) result = movie.ToString(); + else result = "Failed to find that movie."; + } + catch + { + await imsg.Channel.SendMessageAsync("Failed to find that movie.").ConfigureAwait(false); + return; + } + + await imsg.Channel.SendMessageAsync(result.ToString()).ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task RandomCat(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + using (var http = new HttpClient()) + { + await imsg.Channel.SendMessageAsync(JObject.Parse( + await http.GetStringAsync("http://www.random.cat/meow").ConfigureAwait(false))["file"].ToString()) + .ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task RandomDog(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + using (var http = new HttpClient()) + { + await imsg.Channel.SendMessageAsync("http://random.dog/" + await http.GetStringAsync("http://random.dog/woof").ConfigureAwait(false)).ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task I(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + if (string.IsNullOrWhiteSpace(query)) + return; + try + { + using (var http = new HttpClient()) + { + var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(query)}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&fields=items%2Flink&key={NadekoBot.Credentials.GoogleApiKey}"; + var obj = JObject.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false)); + await imsg.Channel.SendMessageAsync(obj["items"][0]["link"].ToString()).ConfigureAwait(false); + } + } + catch (HttpRequestException exception) + { + if (exception.Message.Contains("403 (Forbidden)")) + { + await imsg.Channel.SendMessageAsync("Daily limit reached!"); + } + else + { + await imsg.Channel.SendMessageAsync("Something went wrong."); + } + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Ir(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + if (string.IsNullOrWhiteSpace(query)) + return; + try + { + using (var http = new HttpClient()) + { + var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(query)}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Credentials.GoogleApiKey}"; + var obj = JObject.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false)); + var items = obj["items"] as JArray; + await imsg.Channel.SendMessageAsync(items[0]["link"].ToString()).ConfigureAwait(false); + } + } + catch (HttpRequestException exception) + { + if (exception.Message.Contains("403 (Forbidden)")) + { + await imsg.Channel.SendMessageAsync("Daily limit reached!"); + } + else + { + await imsg.Channel.SendMessageAsync("Something went wrong."); + } + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Lmgtfy(IMessage imsg, [Remainder] string ffs) + { + var channel = imsg.Channel as IGuildChannel; + + + if (string.IsNullOrWhiteSpace(ffs)) + return; + + await imsg.Channel.SendMessageAsync(await $"".ShortenUrl()) + .ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Google(IMessage imsg, [Remainder] string terms) + { + var channel = imsg.Channel as IGuildChannel; + + + terms = terms?.Trim(); + if (string.IsNullOrWhiteSpace(terms)) + return; + await imsg.Channel.SendMessageAsync($"https://google.com/search?q={ HttpUtility.UrlEncode(terms).Replace(' ', '+') }") + .ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Hearthstone(IMessage imsg, [Remainder] string name) + { + var channel = imsg.Channel as IGuildChannel; + var arg = e.GetArg("name"); + if (string.IsNullOrWhiteSpace(arg)) + { + await imsg.Channel.SendMessageAsync("πŸ’’ Please enter a card name to search for.").ConfigureAwait(false); + return; + } + await imsg.Channel.TriggerTypingAsync().ConfigureAwait(false); + string response = ""; + using (var http = new HttpClient()) + { + http.DefaultRequestHeaders.Clear(); + http.DefaultRequestHeaders.Add("X-Mashape-Key", NadekoBot.Credentials.MashapeKey); + response = await http.GetStringAsync($"https://omgvamp-hearthstone-v1.p.mashape.com/cards/search/{Uri.EscapeUriString(arg)}", headers) + .ConfigureAwait(false); + try + { + var items = JArray.Parse(response); + var images = new List(); + if (items == null) + throw new KeyNotFoundException("Cannot find a card by that name"); + var cnt = 0; + items.Shuffle(); + foreach (var item in items.TakeWhile(item => cnt++ < 4).Where(item => item.HasValues && item["img"] != null)) + { + images.Add( + Image.FromStream(await http.GetStreamAsync(item["img"].ToString()).ConfigureAwait(false))); + } + if (items.Count > 4) + { + await imsg.Channel.SendMessageAsync("⚠ Found over 4 images. Showing random 4.").ConfigureAwait(false); + } + await e.Channel.SendFile(arg + ".png", (await images.MergeAsync()).ToStream(System.Drawing.Imaging.ImageFormat.Png)) + .ConfigureAwait(false); + } + catch (Exception ex) + { + await imsg.Channel.SendMessageAsync($"πŸ’’ Error {ex.Message}").ConfigureAwait(false); + } + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task UrbanDictionary(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + var arg = query; + if (string.IsNullOrWhiteSpace(arg)) + { + await imsg.Channel.SendMessageAsync("πŸ’’ Please enter a search term.").ConfigureAwait(false); + return; + } + await imsg.Channel.TriggerTypingAsync().ConfigureAwait(false); + using (var http = new HttpClient()) + { + http.DefaultRequestHeaders.Clear(); + http.DefaultRequestHeaders.Add("X-Mashape-Key", NadekoBot.Credentials.MashapeKey); + var res = await http.GetStringAsync($"https://mashape-community-urban-dictionary.p.mashape.com/define?term={Uri.EscapeUriString(arg)}", headers).ConfigureAwait(false); + try + { + var items = JObject.Parse(res); + 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)}>"); + await imsg.Channel.SendMessageAsync(sb.ToString()); + } + catch + { + await imsg.Channel.SendMessageAsync("πŸ’’ Failed finding a definition for that term.").ConfigureAwait(false); + } + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Hashtag(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + var arg = query; + if (string.IsNullOrWhiteSpace(arg)) + { + await imsg.Channel.SendMessageAsync("πŸ’’ Please enter a search term.").ConfigureAwait(false); + return; + } + await imsg.Channel.TriggerTypingAsync().ConfigureAwait(false); + string res = ""; + using (var http = new HttpClient()) + { + http.DefaultRequestHeaders.Clear(); + http.DefaultRequestHeaders.Add("X-Mashape-Key", NadekoBot.Credentials.MashapeKey); + res = await http.GetStringAsync($"https://tagdef.p.mashape.com/one.{Uri.EscapeUriString(arg)}.json").ConfigureAwait(false); + } + + try + { + 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)}>"); + await imsg.Channel.SendMessageAsync(str); + } + catch + { + await imsg.Channel.SendMessageAsync("πŸ’’ Failed finidng a definition for that tag.").ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Quote(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + + var quote = NadekoBot.Config.Quotes[rng.Next(0, NadekoBot.Config.Quotes.Count)].ToString(); + await imsg.Channel.SendMessageAsync(quote).ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Catfact(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + using (var http = new HttpClient()) + { + var response = await http.GetStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false); + if (response == null) + return; + await imsg.Channel.SendMessageAsync($"🐈 `{JObject.Parse(response)["facts"][0].ToString()}`").ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Yomama(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + using (var http = new HttpClient()) + { + var response = await http.GetStringAsync("http://api.yomomma.info/").ConfigureAwait(false); + await imsg.Channel.SendMessageAsync("`" + JObject.Parse(response)["joke"].ToString() + "` πŸ˜†").ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Randjoke(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + using (var http = new HttpClient()) + { + var response = await http.GetStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false); + await imsg.Channel.SendMessageAsync("`" + JObject.Parse(response)["joke"].ToString() + "` πŸ˜†").ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task ChuckNorris(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + using (var http = new HttpClient()) + { + var response = await http.GetStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false); + await imsg.Channel.SendMessageAsync("`" + JObject.Parse(response)["joke"].ToString() + "` πŸ˜†").ConfigureAwait(false); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task MagicItem(IMessage imsg) + { + var channel = imsg.Channel as IGuildChannel; + + var magicItems = JsonConvert.DeserializeObject>(File.ReadAllText("data/magicitems.json")); + var item = magicItems[rng.Next(0, magicItems.Count)].ToString(); + + await imsg.Channel.SendMessageAsync(item).ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Revav(IMessage imsg, [Remainder] string arg) + { + var channel = imsg.Channel as IGuildChannel; + var usrStr = arg?.Trim().ToUpperInvariant(); + + if (string.IsNullOrWhiteSpace(usrStr)) + return; + + var usr = (await channel.Guild.GetUsersAsync()).Where(u=>u.Username.ToUpperInvariant() == usrStr).FirstOrDefault(); + + if (usr == null || string.IsNullOrWhiteSpace(usr.AvatarUrl)) + return; + await imsg.Channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Revimg(IMessage imsg, [Remainder] string imageLink) + { + var channel = imsg.Channel as IGuildChannel; + imageLink = imageLink?.Trim() ?? ""; + + if (string.IsNullOrWhiteSpace(imageLink)) + return; + await imsg.Channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={imageLink}").ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Safebooru(IMessage imsg, [Remainder] string tag) + { + var channel = imsg.Channel as IGuildChannel; + + tag = tag?.Trim() ?? ""; + var link = await GetSafebooruImageLink(tag).ConfigureAwait(false); + if (link == null) + await imsg.Channel.SendMessageAsync("`No results.`"); + else + await imsg.Channel.SendMessageAsync(link).ConfigureAwait(false); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Wiki(IMessage imsg, [Remainder] string query) + { + var channel = imsg.Channel as IGuildChannel; + + query = query?.Trim(); + if (string.IsNullOrWhiteSpace(query)) + return; + using (var http = new HttpClient()) + { + var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query)); + var data = JsonConvert.DeserializeObject(result); + if (data.Query.Pages[0].Missing) + await imsg.Channel.SendMessageAsync("`That page could not be found.`"); + else + await imsg.Channel.SendMessageAsync(data.Query.Pages[0].FullUrl); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Clr(IMessage imsg, [Remainder] string color) + { + var channel = imsg.Channel as IGuildChannel; + + var arg1 = e.GetArg("color")?.Trim()?.Replace("#", ""); + if (string.IsNullOrWhiteSpace(arg1)) + return; + var img = new Bitmap(50, 50); + + var red = Convert.ToInt32(arg1.Substring(0, 2), 16); + var green = Convert.ToInt32(arg1.Substring(2, 2), 16); + var blue = Convert.ToInt32(arg1.Substring(4, 2), 16); + var brush = new SolidBrush(System.Drawing.Color.FromArgb(red, green, blue)); + + using (Graphics g = Graphics.FromImage(img)) + { + g.FillRectangle(brush, 0, 0, 50, 50); + g.Flush(); + } + + await imsg.Channel.SendFileAsync("arg1.png", img.ToStream()); + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Videocall(IMessage imsg, [Remainder] string arg) + { + var channel = imsg.Channel as IGuildChannel; + + try + { + var allUsrs = imsg.MentionedUsers.Append(imsg.Author); + var allUsrsArray = allUsrs.ToArray(); + var str = allUsrsArray.Aggregate("http://appear.in/", (current, usr) => current + Uri.EscapeUriString(usr.Name[0].ToString())); + str += new Random().Next(); + foreach (var usr in allUsrsArray) + { + await (await (usr as IGuildUser).CreateDMChannelAsync()).SendMessageAsync(str).ConfigureAwait(false); + } + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + + [LocalizedCommand, LocalizedDescription, LocalizedSummary] + [RequireContext(ContextType.Guild)] + public async Task Avatar(IMessage imsg, [Remainder] string mention) + { + var channel = imsg.Channel as IGuildChannel; + + var usr = imsg.MentionedUsers.FirstOrDefault(); + if (usr == null) + { + await imsg.Channel.SendMessageAsync("Invalid user specified.").ConfigureAwait(false); + return; + } + await imsg.Channel.SendMessageAsync(await usr.AvatarUrl.ShortenUrl()).ConfigureAwait(false); + } + + public static async Task GetSafebooruImageLink(string tag) + { + var rng = new Random(); + var url = + $"http://safebooru.org/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}"; + using (var http = new HttpClient()) + { + var webpage = await http.GetStringAsync(url).ConfigureAwait(false); + var matches = Regex.Matches(webpage, "file_url=\"(?.*?)\""); + if (matches.Count == 0) + return null; + var match = matches[rng.Next(0, matches.Count)]; + return matches[rng.Next(0, matches.Count)].Groups["url"].Value; + } + } + + public static async Task ValidateQuery(ITextChannel ch, string query) + { + if (!string.IsNullOrEmpty(query.Trim())) return true; + await ch.SendMessageAsync("Please specify search parameters.").ConfigureAwait(false); + return false; + } + } +} + diff --git a/src/NadekoBot/_Modules/Translator/Helpers/GoogleTranslator.cs b/src/NadekoBot/Modules/Translator/Helpers/GoogleTranslator.cs similarity index 100% rename from src/NadekoBot/_Modules/Translator/Helpers/GoogleTranslator.cs rename to src/NadekoBot/Modules/Translator/Helpers/GoogleTranslator.cs diff --git a/src/NadekoBot/_Modules/Translator/TranslateCommand.cs b/src/NadekoBot/Modules/Translator/TranslateCommand.cs similarity index 100% rename from src/NadekoBot/_Modules/Translator/TranslateCommand.cs rename to src/NadekoBot/Modules/Translator/TranslateCommand.cs diff --git a/src/NadekoBot/_Modules/Translator/TranslatorModule.cs b/src/NadekoBot/Modules/Translator/TranslatorModule.cs similarity index 100% rename from src/NadekoBot/_Modules/Translator/TranslatorModule.cs rename to src/NadekoBot/Modules/Translator/TranslatorModule.cs diff --git a/src/NadekoBot/_Modules/Translator/ValidLanguagesCommand.cs b/src/NadekoBot/Modules/Translator/ValidLanguagesCommand.cs similarity index 100% rename from src/NadekoBot/_Modules/Translator/ValidLanguagesCommand.cs rename to src/NadekoBot/Modules/Translator/ValidLanguagesCommand.cs diff --git a/src/NadekoBot/Modules/Utility/UtilityModule.cs b/src/NadekoBot/Modules/Utility/UtilityModule.cs index 1e87e91f..3ecf01ae 100644 --- a/src/NadekoBot/Modules/Utility/UtilityModule.cs +++ b/src/NadekoBot/Modules/Utility/UtilityModule.cs @@ -19,6 +19,7 @@ namespace NadekoBot.Modules.Utility { public UtilityModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client) { + } [LocalizedCommand, LocalizedDescription, LocalizedSummary] diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index c9eb20b3..dce15100 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -16,8 +16,9 @@ namespace NadekoBot { public static CommandService Commands { get; private set; } public static DiscordSocketClient Client { get; private set; } - public BotConfiguration Config { get; private set; } - public Localization Localizer { get; private set; } + public static BotConfiguration Config { get; private set; } + public static Localization Localizer { get; private set; } + public static BotCredentials Credentials { get; private set; } public async Task RunAsync(string[] args) { @@ -34,6 +35,7 @@ namespace NadekoBot Commands = new CommandService(); Config = new BotConfiguration(); Localizer = new Localization(); + Credentials = new BotCredentials(); //setup DI var depMap = new DependencyMap(); diff --git a/src/NadekoBot/Services/IBotCredentials.cs b/src/NadekoBot/Services/IBotCredentials.cs new file mode 100644 index 00000000..efd3c9db --- /dev/null +++ b/src/NadekoBot/Services/IBotCredentials.cs @@ -0,0 +1,14 @@ +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services +{ + public interface IBotCredentials + { + string Token { get; } + string GoogleApiKey { get; } + } +} diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs new file mode 100644 index 00000000..061a3f3b --- /dev/null +++ b/src/NadekoBot/Services/Impl/BotCredentials.cs @@ -0,0 +1,23 @@ +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Impl +{ + public class BotCredentials : IBotCredentials + { + public string GoogleApiKey { + get { + throw new NotImplementedException(); + } + } + + public string Token { + get { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 1b08c734..aa0dc7e5 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -1,7 +1,9 @@ ο»Ώusing Discord; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -47,5 +49,38 @@ namespace NadekoBot.Extensions return list.ToArray(); } + 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; + } + } + } } \ No newline at end of file diff --git a/src/NadekoBot/_Modules/Music/Classes/Song.cs b/src/NadekoBot/_Modules/Music/Classes/Song.cs index d235776a..2d808736 100644 --- a/src/NadekoBot/_Modules/Music/Classes/Song.cs +++ b/src/NadekoBot/_Modules/Music/Classes/Song.cs @@ -324,7 +324,7 @@ namespace NadekoBot.Modules.Music.Classes string file = null; try { - file = await SearchHelper.GetResponseStringAsync(query).ConfigureAwait(false); + file = await http.GetStringAsync(query).ConfigureAwait(false); } catch { diff --git a/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs b/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs index e743fa5c..ed829adb 100644 --- a/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs +++ b/src/NadekoBot/_Modules/Music/Classes/SoundCloud.cs @@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Music.Classes if (string.IsNullOrWhiteSpace(NadekoBot.Creds.SoundCloudClientID)) throw new ArgumentNullException(nameof(NadekoBot.Creds.SoundCloudClientID)); - var response = await SearchHelper.GetResponseStringAsync($"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.Creds.SoundCloudClientID}").ConfigureAwait(false); var responseObj = Newtonsoft.Json.JsonConvert.DeserializeObject(response); if (responseObj?.Kind != "track") @@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Music.Classes if (string.IsNullOrWhiteSpace(NadekoBot.Creds.SoundCloudClientID)) throw new ArgumentNullException(nameof(NadekoBot.Creds.SoundCloudClientID)); - var response = await SearchHelper.GetResponseStringAsync($"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.Creds.SoundCloudClientID}").ConfigureAwait(false); var responseObj = JsonConvert.DeserializeObject(response).Where(s => s.Streamable).FirstOrDefault(); if (responseObj?.Kind != "track") diff --git a/src/NadekoBot/_Modules/Music/MusicModule.cs b/src/NadekoBot/_Modules/Music/MusicModule.cs index 1c4a010a..e89094d2 100644 --- a/src/NadekoBot/_Modules/Music/MusicModule.cs +++ b/src/NadekoBot/_Modules/Music/MusicModule.cs @@ -333,7 +333,7 @@ namespace NadekoBot.Modules.Music if (string.IsNullOrWhiteSpace(pl)) return; - var scvids = JObject.Parse(await SearchHelper.GetResponseStringAsync($"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.Creds.SoundCloudClientID}").ConfigureAwait(false))["tracks"].ToObject(); await QueueSong(e.User, e.Channel, e.User.VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false); MusicPlayer mp; diff --git a/src/NadekoBot/_Modules/Programming/Commands/HaskellRepl.cs b/src/NadekoBot/_Modules/Programming/Commands/HaskellRepl.cs deleted file mode 100644 index f8c1f78d..00000000 --- a/src/NadekoBot/_Modules/Programming/Commands/HaskellRepl.cs +++ /dev/null @@ -1,92 +0,0 @@ -using Discord; -using Discord.Commands; -using NadekoBot.Classes; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -/// -/// I have no idea what am i doing -/// -namespace NadekoBot.Modules.Programming.Commands -{ - class HaskellRepl : DiscordCommand - { - ConcurrentQueue> commandQueue = new ConcurrentQueue>(); - - Thread haskellThread; - - public HaskellRepl(DiscordModule module) : base(module) - { - //start haskell interpreter - - haskellThread = new Thread(new ThreadStart(() => - { - var p = Process.Start(new ProcessStartInfo - { - FileName = "stack", //shouldn't use repl, but a Language.Haskell.Interpreter somehow - Arguments = "repl", - UseShellExecute = false, - RedirectStandardInput = true, - RedirectStandardOutput = true, - CreateNoWindow = true, - }); - - Task.Run(async () => - { - while (true) - { - while (commandQueue.Count == 0) - await Task.Delay(100); - - //read from queue - KeyValuePair com; - if (!commandQueue.TryDequeue(out com)) - { - await Task.Delay(100); - continue; - } - //var bytes = Encoding.ASCII.GetBytes(com.Key); - - //send the command to the process - p.StandardInput.WriteLine(com.Key); - - //wait 50 ms for execution - await Task.Delay(50); - - //read everything from the output - var outBuffer = new byte[1500]; - - p.StandardOutput.BaseStream.Read(outBuffer, 0, 1500); - - var outStr = Encoding.ASCII.GetString(outBuffer); - //send to channel - await com.Value.SendMessage($"```hs\nPrelude> {com.Key}\n" + outStr + "\n```"); - } - }); - - })); - haskellThread.Start(); - - } - - internal override void Init(CommandGroupBuilder cgb) - { - cgb.CreateCommand(Module.Prefix + "hs") - .Description("Executes a haskell express with LAMBDABOT") - .Parameter("command", ParameterType.Unparsed) - .Do(e => - { - var com = e.GetArg("command")?.Trim(); - if (string.IsNullOrWhiteSpace(com)) - return; - - //send a command and a channel to the queue - commandQueue.Enqueue(new KeyValuePair(com, e.Channel)); - }); - } - } -} diff --git a/src/NadekoBot/_Modules/Programming/ProgrammingModule.cs b/src/NadekoBot/_Modules/Programming/ProgrammingModule.cs deleted file mode 100644 index feb3c4e2..00000000 --- a/src/NadekoBot/_Modules/Programming/ProgrammingModule.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Discord.Modules; -using NadekoBot.Extensions; -using NadekoBot.Modules.Permissions.Classes; -using NadekoBot.Modules.Programming.Commands; - -namespace NadekoBot.Modules.Programming -{ - class ProgrammingModule : DiscordModule - { - public override string Prefix => NadekoBot.Config.CommandPrefixes.Programming; - - public ProgrammingModule() - { - commands.Add(new HaskellRepl(this)); - } - - public override void Install(ModuleManager manager) - { - manager.CreateCommands("", cgb => - { - cgb.AddCheck(PermissionChecker.Instance); - commands.ForEach(c => c.Init(cgb)); - }); - } - } -} diff --git a/src/NadekoBot/_Modules/Searches/SearchesModule.cs b/src/NadekoBot/_Modules/Searches/SearchesModule.cs deleted file mode 100644 index 8280c0e2..00000000 --- a/src/NadekoBot/_Modules/Searches/SearchesModule.cs +++ /dev/null @@ -1,521 +0,0 @@ -ο»Ώusing Discord; -using Discord.Commands; -using Discord.Modules; -using NadekoBot.Classes; -using NadekoBot.Classes.JSONModels; -using NadekoBot.Extensions; -using NadekoBot.Modules.Permissions.Classes; -using NadekoBot.Modules.Searches.Commands; -using NadekoBot.Modules.Searches.Commands.IMDB; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Web; - -namespace NadekoBot.Modules.Searches -{ - internal class SearchesModule : DiscordModule - { - private readonly Random rng; - public SearchesModule() - { - commands.Add(new LoLCommands(this)); - commands.Add(new StreamNotifications(this)); - commands.Add(new ConverterCommand(this)); - commands.Add(new RedditCommand(this)); - commands.Add(new WowJokeCommand(this)); - commands.Add(new CalcCommand(this)); - commands.Add(new OsuCommands(this)); - commands.Add(new PokemonSearchCommands(this)); - commands.Add(new MemegenCommands(this)); - rng = new Random(); - } - - public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Searches; - - public override void Install(ModuleManager manager) - { - manager.CreateCommands("", cgb => - { - - cgb.AddCheck(PermissionChecker.Instance); - - commands.ForEach(cmd => cmd.Init(cgb)); - - cgb.CreateCommand(Prefix + "we") - .Description($"Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | `{Prefix}we Moscow RF`") - .Parameter("city", ParameterType.Required) - .Parameter("country", ParameterType.Required) - .Do(async e => - { - var city = e.GetArg("city").Replace(" ", ""); - var country = e.GetArg("country").Replace(" ", ""); - var response = await SearchHelper.GetResponseStringAsync($"http://api.lawlypopzz.xyz/nadekobot/weather/?city={city}&country={country}").ConfigureAwait(false); - - var obj = JObject.Parse(response)["weather"]; - - await channel.SendMessageAsync( -$@"🌍 **Weather for** 【{obj["target"]}】 -πŸ“ **Lat,Long:** ({obj["latitude"]}, {obj["longitude"]}) ☁ **Condition:** {obj["condition"]} -πŸ˜“ **Humidity:** {obj["humidity"]}% πŸ’¨ **Wind Speed:** {obj["windspeedk"]}km/h / {obj["windspeedm"]}mph -πŸ”† **Temperature:** {obj["centigrade"]}Β°C / {obj["fahrenheit"]}Β°F πŸ”† **Feels like:** {obj["feelscentigrade"]}Β°C / {obj["feelsfahrenheit"]}Β°F -πŸŒ„ **Sunrise:** {obj["sunrise"]} πŸŒ‡ **Sunset:** {obj["sunset"]}").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "yt") - .Parameter("query", ParameterType.Unparsed) - .Description($"Searches youtubes and shows the first result | `{Prefix}yt query`") - .Do(async e => - { - if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return; - var link = await SearchHelper.FindYoutubeUrlByKeywords(e.GetArg("query")).ConfigureAwait(false); - if (string.IsNullOrWhiteSpace(link)) - { - await channel.SendMessageAsync("No results found for that query."); - return; - } - var shortUrl = await SearchHelper.ShortenUrl(link).ConfigureAwait(false); - await channel.SendMessageAsync(shortUrl).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "ani") - .Alias(Prefix + "anime", Prefix + "aq") - .Parameter("query", ParameterType.Unparsed) - .Description($"Queries anilist for an anime and shows the first result. | `{Prefix}aq aquarion evol`") - .Do(async e => - { - if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return; - string result; - try - { - result = (await SearchHelper.GetAnimeData(e.GetArg("query")).ConfigureAwait(false)).ToString(); - } - catch - { - await channel.SendMessageAsync("Failed to find that anime.").ConfigureAwait(false); - return; - } - - await channel.SendMessageAsync(result.ToString()).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "imdb") - .Parameter("query", ParameterType.Unparsed) - .Description($"Queries imdb for movies or series, show first result. | `{Prefix}imdb Batman vs Superman`") - .Do(async e => - { - if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return; - await e.Channel.SendIsTyping().ConfigureAwait(false); - string result; - try - { - var movie = ImdbScraper.ImdbScrape(e.GetArg("query"), true); - if (movie.Status) result = movie.ToString(); - else result = "Failed to find that movie."; - } - catch - { - await channel.SendMessageAsync("Failed to find that movie.").ConfigureAwait(false); - return; - } - - await channel.SendMessageAsync(result.ToString()).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "mang") - .Alias(Prefix + "manga").Alias(Prefix + "mq") - .Parameter("query", ParameterType.Unparsed) - .Description($"Queries anilist for a manga and shows the first result. | `{Prefix}mq Shingeki no kyojin`") - .Do(async e => - { - if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return; - string result; - try - { - result = (await SearchHelper.GetMangaData(e.GetArg("query")).ConfigureAwait(false)).ToString(); - } - catch - { - await channel.SendMessageAsync("Failed to find that anime.").ConfigureAwait(false); - return; - } - await channel.SendMessageAsync(result).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "randomcat") - .Alias(Prefix + "meow") - .Description($"Shows a random cat image. | `{Prefix}meow`") - .Do(async e => - { - await channel.SendMessageAsync(JObject.Parse( - await SearchHelper.GetResponseStringAsync("http://www.random.cat/meow").ConfigureAwait(false))["file"].ToString()) - .ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "randomdog") - .Alias(Prefix + "woof") - .Description($"Shows a random dog image. | `{Prefix}woof`") - .Do(async e => - { - await channel.SendMessageAsync("http://random.dog/" + await SearchHelper.GetResponseStringAsync("http://random.dog/woof").ConfigureAwait(false)).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "i") - .Description($"Pulls the first image found using a search parameter. Use ~ir for different results. | `{Prefix}i cute kitten`") - .Parameter("query", ParameterType.Unparsed) - .Do(async e => - { - if (string.IsNullOrWhiteSpace(e.GetArg("query"))) - return; - try - { - var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(e.GetArg("query"))}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&fields=items%2Flink&key={NadekoBot.Creds.GoogleAPIKey}"; - var obj = JObject.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false)); - await channel.SendMessageAsync(obj["items"][0]["link"].ToString()).ConfigureAwait(false); - } - catch (HttpRequestException exception) - { - if (exception.Message.Contains("403 (Forbidden)")) - { - await channel.SendMessageAsync("Daily limit reached!"); - } - else - { - await channel.SendMessageAsync("Something went wrong."); - } - } - }); - - cgb.CreateCommand(Prefix + "ir") - .Description($"Pulls a random image using a search parameter. | `{Prefix}ir cute kitten`") - .Parameter("query", ParameterType.Unparsed) - .Do(async e => - { - if (string.IsNullOrWhiteSpace(e.GetArg("query"))) - return; - try - { - var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(e.GetArg("query"))}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Creds.GoogleAPIKey}"; - var obj = JObject.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false)); - var items = obj["items"] as JArray; - await channel.SendMessageAsync(items[0]["link"].ToString()).ConfigureAwait(false); - } - catch (HttpRequestException exception) - { - if (exception.Message.Contains("403 (Forbidden)")) - { - await channel.SendMessageAsync("Daily limit reached!"); - } - else - { - await channel.SendMessageAsync("Something went wrong."); - } - } - }); - - cgb.CreateCommand(Prefix + "lmgtfy") - .Description($"Google something for an idiot. | `{Prefix}lmgtfy query`") - .Parameter("ffs", ParameterType.Unparsed) - .Do(async e => - { - if (e.GetArg("ffs") == null || e.GetArg("ffs").Length < 1) return; - await channel.SendMessageAsync(await $"http://lmgtfy.com/?q={ Uri.EscapeUriString(e.GetArg("ffs").ToString()) }".ShortenUrl()) - .ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "google") - .Alias(Prefix + "g") - .Description($"Get a google search link for some terms. | `{Prefix}google query`") - .Parameter("terms", ParameterType.Unparsed) - .Do(async e => - { - var terms = e.GetArg("terms")?.Trim(); - if (string.IsNullOrWhiteSpace(terms)) - return; - await channel.SendMessageAsync($"https://google.com/search?q={ HttpUtility.UrlEncode(terms).Replace(' ', '+') }") - .ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "hs") - .Description($"Searches for a Hearthstone card and shows its image. Takes a while to complete. | `{Prefix}hs Ysera`") - .Parameter("name", ParameterType.Unparsed) - .Do(async e => - { - var arg = e.GetArg("name"); - if (string.IsNullOrWhiteSpace(arg)) - { - await channel.SendMessageAsync("πŸ’’ Please enter a card name to search for.").ConfigureAwait(false); - return; - } - await e.Channel.SendIsTyping().ConfigureAwait(false); - var headers = new Dictionary { { "X-Mashape-Key", NadekoBot.Creds.MashapeKey } }; - var res = await SearchHelper.GetResponseStringAsync($"https://omgvamp-hearthstone-v1.p.mashape.com/cards/search/{Uri.EscapeUriString(arg)}", headers) - .ConfigureAwait(false); - try - { - var items = JArray.Parse(res); - var images = new List(); - if (items == null) - throw new KeyNotFoundException("Cannot find a card by that name"); - var cnt = 0; - items.Shuffle(); - foreach (var item in items.TakeWhile(item => cnt++ < 4).Where(item => item.HasValues && item["img"] != null)) - { - images.Add( - Image.FromStream(await SearchHelper.GetResponseStreamAsync(item["img"].ToString()).ConfigureAwait(false))); - } - if (items.Count > 4) - { - await channel.SendMessageAsync("⚠ Found over 4 images. Showing random 4.").ConfigureAwait(false); - } - await e.Channel.SendFile(arg + ".png", (await images.MergeAsync()).ToStream(System.Drawing.Imaging.ImageFormat.Png)) - .ConfigureAwait(false); - } - catch (Exception ex) - { - await channel.SendMessageAsync($"πŸ’’ Error {ex.Message}").ConfigureAwait(false); - } - }); - - cgb.CreateCommand(Prefix + "ud") - .Description($"Searches Urban Dictionary for a word. | `{Prefix}ud Pineapple`") - .Parameter("query", ParameterType.Unparsed) - .Do(async e => - { - var arg = e.GetArg("query"); - if (string.IsNullOrWhiteSpace(arg)) - { - await channel.SendMessageAsync("πŸ’’ Please enter a search term.").ConfigureAwait(false); - return; - } - await e.Channel.SendIsTyping().ConfigureAwait(false); - var headers = new Dictionary { { "X-Mashape-Key", NadekoBot.Creds.MashapeKey } }; - var res = await SearchHelper.GetResponseStringAsync($"https://mashape-community-urban-dictionary.p.mashape.com/define?term={Uri.EscapeUriString(arg)}", headers).ConfigureAwait(false); - try - { - var items = JObject.Parse(res); - 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)}>"); - await channel.SendMessageAsync(sb.ToString()); - } - catch - { - await channel.SendMessageAsync("πŸ’’ Failed finding a definition for that term.").ConfigureAwait(false); - } - }); - // thanks to Blaubeerwald - cgb.CreateCommand(Prefix + "#") - .Description($"Searches Tagdef.com for a hashtag. | `{Prefix}# ff`") - .Parameter("query", ParameterType.Unparsed) - .Do(async e => - { - var arg = e.GetArg("query"); - if (string.IsNullOrWhiteSpace(arg)) - { - await channel.SendMessageAsync("πŸ’’ Please enter a search term.").ConfigureAwait(false); - return; - } - await e.Channel.SendIsTyping().ConfigureAwait(false); - var headers = new Dictionary { { "X-Mashape-Key", NadekoBot.Creds.MashapeKey } }; - var res = await SearchHelper.GetResponseStringAsync($"https://tagdef.p.mashape.com/one.{Uri.EscapeUriString(arg)}.json", headers).ConfigureAwait(false); - try - { - var items = JObject.Parse(res); - var sb = new System.Text.StringBuilder(); - sb.AppendLine($"`Hashtag:` {items["defs"]["def"]["hashtag"].ToString()}"); - sb.AppendLine($"`Definition:` {items["defs"]["def"]["text"].ToString()}"); - sb.Append($"`Link:` <{await items["defs"]["def"]["uri"].ToString().ShortenUrl().ConfigureAwait(false)}>"); - await channel.SendMessageAsync(sb.ToString()); - } - catch - { - await channel.SendMessageAsync("πŸ’’ Failed finidng a definition for that tag.").ConfigureAwait(false); - } - }); - - cgb.CreateCommand(Prefix + "quote") - .Description($"Shows a random quote. | `{Prefix}quote`") - .Do(async e => - { - var quote = NadekoBot.Config.Quotes[rng.Next(0, NadekoBot.Config.Quotes.Count)].ToString(); - await channel.SendMessageAsync(quote).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "catfact") - .Description($"Shows a random catfact from | `{Prefix}catfact`") - .Do(async e => - { - var response = await SearchHelper.GetResponseStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false); - if (response == null) - return; - await channel.SendMessageAsync($"🐈 `{JObject.Parse(response)["facts"][0].ToString()}`").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "yomama") - .Alias(Prefix + "ym") - .Description($"Shows a random joke from | `{Prefix}ym`") - .Do(async e => - { - var response = await SearchHelper.GetResponseStringAsync("http://api.yomomma.info/").ConfigureAwait(false); - await channel.SendMessageAsync("`" + JObject.Parse(response)["joke"].ToString() + "` πŸ˜†").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "randjoke") - .Alias(Prefix + "rj") - .Description($"Shows a random joke from | `{Prefix}rj`") - .Do(async e => - { - var response = await SearchHelper.GetResponseStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false); - await channel.SendMessageAsync("`" + JObject.Parse(response)["joke"].ToString() + "` πŸ˜†").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "chucknorris") - .Alias(Prefix + "cn") - .Description($"Shows a random chucknorris joke from | `{Prefix}cn`") - .Do(async e => - { - var response = await SearchHelper.GetResponseStringAsync("http://api.icndb.com/jokes/random/").ConfigureAwait(false); - await channel.SendMessageAsync("`" + JObject.Parse(response)["value"]["joke"].ToString() + "` πŸ˜†").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "magicitem") - .Alias(Prefix + "mi") - .Description($"Shows a random magicitem from | `{Prefix}mi`") - .Do(async e => - { - var magicItems = JsonConvert.DeserializeObject>(File.ReadAllText("data/magicitems.json")); - var item = magicItems[rng.Next(0, magicItems.Count)].ToString(); - - await channel.SendMessageAsync(item).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "revav") - .Description($"Returns a google reverse image search for someone's avatar. | `{Prefix}revav \"@SomeGuy\"`") - .Parameter("user", ParameterType.Unparsed) - .Do(async e => - { - var usrStr = e.GetArg("user")?.Trim(); - - if (string.IsNullOrWhiteSpace(usrStr)) - return; - - var usr = e.Server.FindUsers(usrStr).FirstOrDefault(); - - if (usr == null || string.IsNullOrWhiteSpace(usr.AvatarUrl)) - return; - await channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "revimg") - .Description($"Returns a google reverse image search for an image from a link. | `{Prefix}revav Image link`") - .Parameter("image", ParameterType.Unparsed) - .Do(async e => - { - var imgLink = e.GetArg("image")?.Trim(); - - if (string.IsNullOrWhiteSpace(imgLink)) - return; - await channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={imgLink}").ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "safebooru") - .Description($"Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `{Prefix}safebooru yuri+kissing`") - .Parameter("tag", ParameterType.Unparsed) - .Do(async e => - { - var tag = e.GetArg("tag")?.Trim() ?? ""; - var link = await SearchHelper.GetSafebooruImageLink(tag).ConfigureAwait(false); - if (link == null) - await channel.SendMessageAsync("`No results.`"); - else - await channel.SendMessageAsync(link).ConfigureAwait(false); - }); - - cgb.CreateCommand(Prefix + "wiki") - .Description($"Gives you back a wikipedia link | `{Prefix}wiki query`") - .Parameter("query", ParameterType.Unparsed) - .Do(async e => - { - var query = e.GetArg("query"); - var result = await SearchHelper.GetResponseStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query)); - var data = JsonConvert.DeserializeObject(result); - if (data.Query.Pages[0].Missing) - await channel.SendMessageAsync("`That page could not be found.`"); - else - await channel.SendMessageAsync(data.Query.Pages[0].FullUrl); - }); - - cgb.CreateCommand(Prefix + "clr") - .Description($"Shows you what color corresponds to that hex. | `{Prefix}clr 00ff00`") - .Parameter("color", ParameterType.Unparsed) - .Do(async e => - { - var arg1 = e.GetArg("color")?.Trim()?.Replace("#", ""); - if (string.IsNullOrWhiteSpace(arg1)) - return; - var img = new Bitmap(50, 50); - - var red = Convert.ToInt32(arg1.Substring(0, 2), 16); - var green = Convert.ToInt32(arg1.Substring(2, 2), 16); - var blue = Convert.ToInt32(arg1.Substring(4, 2), 16); - var brush = new SolidBrush(System.Drawing.Color.FromArgb(red, green, blue)); - - using (Graphics g = Graphics.FromImage(img)) - { - g.FillRectangle(brush, 0, 0, 50, 50); - g.Flush(); - } - - await e.Channel.SendFile("arg1.png", img.ToStream()); - }); - - - cgb.CreateCommand(Prefix + "videocall") - .Description($"Creates a private video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `{Prefix}videocall \"@SomeGuy\"`") - .Parameter("arg", ParameterType.Unparsed) - .Do(async e => - { - try - { - var allUsrs = e.Message.MentionedUsers.Union(new User[] { e.User }); - var allUsrsArray = allUsrs as User[] ?? allUsrs.ToArray(); - var str = allUsrsArray.Aggregate("http://appear.in/", (current, usr) => current + Uri.EscapeUriString(usr.Name[0].ToString())); - str += new Random().Next(); - foreach (var usr in allUsrsArray) - { - await usr.SendMessage(str).ConfigureAwait(false); - } - } - catch (Exception ex) - { - Console.WriteLine(ex); - } - }); - - cgb.CreateCommand(Prefix + "av") - .Alias(Prefix + "avatar") - .Parameter("mention", ParameterType.Required) - .Description($"Shows a mentioned person's avatar. | `{Prefix}av \"@SomeGuy\"`") - .Do(async e => - { - var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault(); - if (usr == null) - { - await channel.SendMessageAsync("Invalid user specified.").ConfigureAwait(false); - return; - } - await channel.SendMessageAsync(await usr.AvatarUrl.ShortenUrl()).ConfigureAwait(false); - }); - - }); - } - } -} -