Example #1
0
    public async Task DerpiTagsNoLink()
    {
        // Trigger "user is typing..." message.
        await Context.Channel.TriggerTypingAsync();

        // Check if an a "~derpi" search has been made in this channel yet.
        if (Global.LastDerpiID.ContainsKey(Context.Channel.Id))
        {
            // Handmade link + the channel ID to get the last stored ID.
            string builtLink = "https://derpibooru.org/api/v1/json/search/images?q=id%3A" + Global.LastDerpiID[Context.Channel.Id] + "&filter_id=56027";
            // Retrieves JSON and saves as string.
            string JSONresponse = Get.Derpibooru(builtLink).Result;
            // Finally makes the derpibooru object to leverage DerpiTagsDisplay().
            DerpiRoot DerpiResponse = JsonConvert.DeserializeObject <DerpiRoot>(JSONresponse);

            // Check if the ID existed or yielded any results.
            if (DerpiResponse.images.Count < 1)
            {
                await ReplyAsync("No results found, please call `~derpi` again or post another link!");
            }
            else
            {
                await DerpiTagsDisplay(DerpiResponse.images[0]);
            }
        }
        else
        {
            await ReplyAsync("You need to call `~derpi` (`~d` for short) or post a link before I can hoof over the tags!");
        }
    }
Example #2
0
    public async Task DerpiTags([Remainder] string search)
    {
        // Broadcasts "User is typing..." message to Discord channel.
        await Context.Channel.TriggerTypingAsync();

        // Image ID placeholder.
        int imageID;

        // First, check if search term is an image ID. An integer.
        if (int.TryParse(search, out imageID))
        {
            // Continue as normal, imageID is stored in the variable.
        }
        // Second, if not an integer, test if it is a valid Booru URL.
        else if (Global.IsBooruUrl(search))
        {
            // 1. Attempt to parse Integer ID from Booru URL.
            imageID = Global.ExtractBooruId(search);
            // 2a. Unparseable, quit early and apologize to user.
            if (imageID == -1)
            {
                await ReplyAsync("Sorry, I couldn't understand the URL you gave me. Please try again with another URL, or contact Hoovier if something is wrong.");
                await ReplyAsync("If you think this was in error, please contact Hoovier with the request you made.");

                return;
            }
            // 2b. Continue as normal, imageID is stored in the variable.
        }
        // Lastly, if not a valid Booru URL or ID, output a gentle error message.
        else
        {
            await ReplyAsync("Sorry, I couldn't understand the URL you gave me. Please try again with another URL, or contact Hoovier if something is wrong.");

            return;
        }

        // If you reach here, the "else" return case didn't happen and we can query Derpibooru.
        // We can use imageID to uniformly query DerpiBooru.
        string requestUrl = DerpiHelper.BuildDerpiUrl(this.baseURL, new Dictionary <string, string>()
        {
            { "filter_id", "56027" },
            { "q", $"id:{imageID}" },
        });
        string    DerpiJson     = Get.Derpibooru(requestUrl).Result;
        DerpiRoot DerpiResponse = JsonConvert.DeserializeObject <DerpiRoot>(DerpiJson);

        if (DerpiResponse.images.Count == 0)
        {
            await ReplyAsync("No results! The ID or URL provided might have had a typo or is deleted no longer exists.");
            await ReplyAsync("If you think this was in error, please contact Hoovier with the request you made.");
        }
        else
        {
            await DerpiTagsDisplay(DerpiResponse.images[0]);
        }
    }
Example #3
0
    public async Task ArtistNoLink()
    {
        await Context.Channel.TriggerTypingAsync();

        // Get last Derpibooru Image ID from global cache.
        int imageID;

        // Check if an a "~derpi" search has been made in this channel yet.
        if (!Global.LastDerpiID.ContainsKey(Context.Channel.Id))
        {
            await ReplyAsync("You need to call `~derpi` (`~d` for short) to get some results before I can hoof you over more silly!");

            return;
        }

        // Try to parse the global cache into an integer ID.
        if (int.TryParse(Global.LastDerpiID[Context.Channel.Id], out imageID))
        {
            string requestUrl = DerpiHelper.BuildDerpiUrl(this.baseURL, new Dictionary <string, string>()
            {
                { "filter_id", "178065" },
                { "q", $"id:{imageID}" },
            });
            string    DerpiJson     = Get.Derpibooru(requestUrl).Result;
            DerpiRoot DerpiResponse = JsonConvert.DeserializeObject <DerpiRoot>(DerpiJson);

            if (DerpiResponse.images.Count == 0)
            {
                // Given ID does not exist.
                await ReplyAsync("No results! The tag may be misspelled, or the results could be filtered out due to channel!");
            }
            else
            {
                // Get artist Tag Link(s) and print image URL as well.
                bool   safeOnly    = !DBTransaction.isChannelWhitelisted(Context.Channel.Id) && !Context.IsPrivate;
                string artistLinks = DerpiHelper.BuildArtistTags(DerpiResponse.images[0], true, !safeOnly);
                await ReplyAsync($"https://derpibooru.org/{imageID}\n{artistLinks}");
            }
        }
        else
        {
            // Can't get an ID from cache.
            await ReplyAsync("No results! The tag may be misspelled, or the results could be filtered out due to channel!");
        }
    }
Example #4
0
    public async Task DerpistAsync([Remainder] string search)
    {
        await Context.Channel.TriggerTypingAsync();

        // Same base query as ~derpi, discounting sorting and asking for less results.
        Dictionary <string, string> queryParams = new Dictionary <string, string>()
        {
            { "filter_id", "178065" },
            { "per_page", "1" },
            { "page", "1" },
            { "q", search },
        };

        // Build the full request URL.
        string requestUrl = DerpiHelper.BuildDerpiUrl(this.baseURL, queryParams);

        // Make the request, and parse the JSON into a C#-friendly object.
        DerpiRoot results = JsonConvert.DeserializeObject <DerpiRoot>(Get.Derpibooru(requestUrl).Result);

        await ReplyAsync($"Total results: {results.total}");
    }
Example #5
0
    public async Task DerpiLuckyMulti(int num, [Remainder] string search)
    {
        // Broadcasts "User is typing..." message to Discord channel.
        await Context.Channel.TriggerTypingAsync();

        // Limit ~lucky amounts.
        if (num < 1 || num > 5)
        {
            await ReplyAsync("You need to pick a number bigger than 0 and no more than 5");

            return;
        }

        // Set up the base query parameters.
        // Sorted randomly, gets "num" amount of items!
        Dictionary <string, string> queryParams = new Dictionary <string, string>()
        {
            { "filter_id", "178065" },
            { "sf", "random" },
            { "sd", "desc" },
            { "per_page", num.ToString() },
            { "page", "1" },
        };

        // If the channel is not on the list of NSFW enabled channels do not allow NSFW results.
        // the second part checks if the command was executed in DMS, DM channels do not have to be added to the NSFW enabled list.
        // In DMs the first check will fail, and so will the second, allowing for nsfw results to be displayed.
        bool safeOnly = !DBTransaction.isChannelWhitelisted(Context.Channel.Id) && !Context.IsPrivate;

        // Add search to the parameters list, with "AND safe" if it failed the NSFW check.
        queryParams.Add("q", safeOnly ? $"{search}+AND+safe" : search);

        // Build the full request URL.
        string requestUrl = DerpiHelper.BuildDerpiUrl(this.baseURL, queryParams);

        // Deserialize (from JSON to DerpibooruResponse.RootObject) the Derpibooru search results.
        DerpiRoot DerpiResponse = JsonConvert.DeserializeObject <DerpiRoot>(Get.Derpibooru(requestUrl).Result);

        // Actual request an. Try-catch to softly catch exceptions.
        try {
            if (DerpiResponse.images.Count == 0)
            {
                await ReplyAsync("No results! The tag may be misspelled, or the results could be filtered out due to channel!");

                return;
            }
            else if (DerpiResponse.images.Count < num)
            {
                await ReplyAsync($"Not enough results to post {num}, but here is what we have found!");
            }

            // Print all results of the search!
            // Sorted randomly by Derpibooru already, and will be between 1-5 elements.
            string message = $"Listing {DerpiResponse.images.Count} results\n";
            message += String.Join("\n",
                                   DerpiResponse.images.Select(
                                       element => element.representations.full));

            await ReplyAsync(message);
        } catch {
            await ReplyAsync("Sorry! Something went wrong, your search terms are probably incorrect.");

            return;
        }
    }
Example #6
0
    // "Master" Derpibooru/~derpi searching method. Not a discord-accessible method.
    private async Task DerpiMaster(bool artistAsLink, int Sort, string search)
    {
        // Broadcasts "User is typing..." message to Discord channel.
        await Context.Channel.TriggerTypingAsync();

        // Validate that a valid sorting option was chosen.
        if (Sort < 0 || Sort >= this.sortingOptions.Length)
        {
            await ReplyAsync("Invalid sorting option: " + Sort + ". Please try again");

            return;
        }
        // Choose sorting method from the available list.
        string sortParam = this.sortingOptions[Sort];

        // Set up the base query parameters.
        // "q" is our search terms
        // "filter_id" is the filter against content banned by Discord TOS.
        Dictionary <string, string> queryParams = new Dictionary <string, string>()
        {
            { "filter_id", "178065" },
            { "sf", sortParam },
            { "sd", "desc" },
            { "per_page", "50" },
            { "page", "1" },
        };

        // If the channel is not on the list of NSFW enabled channels do not allow NSFW results.
        // the second part checks if the command was executed in DMS, DM channels do not have to be added to the NSFW enabled list.
        // In DMs the first check will fail, and so will the second, allowing for nsfw results to be displayed.
        bool safeOnly = !DBTransaction.isChannelWhitelisted(Context.Channel.Id) && !Context.IsPrivate;

        // Add search to the parameters list, with "AND safe" if it failed the NSFW check.
        queryParams.Add("q", safeOnly ? $"{search}+AND+safe" : search);

        // Build the full request URL.
        string requestUrl = DerpiHelper.BuildDerpiUrl(this.baseURL, queryParams);

        // Global.DerpiSearchCache is a dictionary-based cache with the last search result in that channel, if applicable.
        // Always stores results globally for other commands like ~next to keep track.
        Global.DerpiSearchCache[Context.Channel.Id] = Get.Derpibooru(requestUrl).Result;

        // Deserialize (from JSON to DerpibooruResponse.RootObject) the Derpibooru search results.
        DerpiRoot DerpiResponse = JsonConvert.DeserializeObject <DerpiRoot>(Global.DerpiSearchCache[Context.Channel.Id]);

        // Actual request an. Try-catch to softly catch exceptions.
        try {
            // Convert Search Array to a List, to use List functionality.
            List <DerpiSearch> imageList = DerpiResponse.images;
            if (imageList.Count == 0)
            {
                await ReplyAsync("No results! The tag may be misspelled, or the results could be filtered out due to channel!");

                return;
            }
            // Get random number generator and random entry.
            var rng  = new Random();
            int rand = rng.Next(imageList.Count);
            Global.DerpibooruSearchIndex[Context.Channel.Id] = rand + 1;
            DerpiSearch randomElement = imageList.ElementAt(rand);

            // Add image ID to Global.links.
            // TODO: Describe where this is used better?
            Global.LastDerpiID[Context.Channel.Id] = randomElement.id.ToString();
            RestUserMessage msg = await Context.Channel.SendMessageAsync(
                DerpiHelper.BuildDiscordResponse(randomElement, artistAsLink, !safeOnly)
                );

            await msg.AddReactionAsync(new Emoji("▶"));

            //set random info for running ~enext through emoji reactions.
            Global.derpiContext[Context.Channel.Id]        = Context;
            Global.derpiMessageToTrack[Context.Channel.Id] = msg.Id;
        } catch {
            await ReplyAsync("Sorry! Something went wrong, your search terms are probably incorrect.");

            return;
        }
    }