Exemple #1
0
        async IAsyncEnumerable <ParsedImage> IImageParsingStrategy.ParseAsync(ParseRequest request, IProgress <ParseProgress> progress)
        {
            if (request is null)
            {
                ThrowHelper.ArgumentNull(nameof(request));
            }

            if (request.EstimatedCount < 1)
            {
                ThrowHelper.ArgumentOutOfRange(nameof(request.EstimatedCount), request.EstimatedCount, "Value must be 1 or greater!");
            }


            var imagesPerCategory = (double)request.EstimatedCount / request.Categories.Count();
            var capacity          = (int)Math.Ceiling(imagesPerCategory / _pageSize) * request.Categories.Sum(x => x.Keywords.Count());

            var throttler    = new SemaphoreSlim(MaxThreads);
            var currentCount = 0;

            foreach (var category in request.Categories)
            {
                var keywordsCount    = category.Keywords.Count();
                var imagesPerKeyword = (int)Math.Ceiling(imagesPerCategory / keywordsCount);

                var allTasks     = new List <Task>();
                var parsedImages = new List <ParsedImage>(imagesPerKeyword);

                var total = (int)Math.Ceiling((double)imagesPerKeyword / _pageSize);
                var pages = Enumerable.Range(_startFrom, total);

                var disposables = new List <IDisposable>();
                foreach (var keyword in category.Keywords)
                {
                    await throttler.WaitAsync();

                    allTasks.Add(
                        Task.Run(async() =>
                    {
                        try
                        {
                            var uri = new Uri(_url).AddParameter("query", keyword);

                            foreach (var page in pages)
                            {
                                var pageUri = uri.AddParameter("per_page", _pageSize)
                                              .AddParameter("page", page);

                                var take = imagesPerKeyword - (page - 1) * _pageSize;

                                var response = await _httpClient.GetAsync <Response>(pageUri);
                                disposables.Add(response.Disposable);
                                var results = response.Result.Results.Take(take);

                                foreach (var result in results)
                                {
                                    var download    = await _httpClient.GetAsync(result.Links.Download);
                                    var stream      = await download.Content.ReadAsStreamAsync();
                                    var image       = Image.FromStream(stream);
                                    var parsedImage = new ParsedImage
                                    {
                                        Category = category.Name,
                                        Image    = image,
                                        Keyword  = keyword
                                    };
                                    parsedImages.Add(parsedImage);
                                    disposables.Add(download);
                                    disposables.Add(stream);
                                }
                            }
                        }
                        finally
                        {
                            throttler.Release();
                        }
                    }));
                }
                await Task.WhenAll(allTasks);

                foreach (var parsedImage in parsedImages)
                {
                    var data = new ParseProgress
                    {
                        CurrentCount   = ++currentCount,
                        EstimatedCount = request.EstimatedCount
                    };
                    progress?.Report(data);
                    yield return(parsedImage);
                }

                foreach (var disposable in disposables)
                {
                    disposable.Dispose();
                }
            }
        }
Exemple #2
0
    private Task PrintResponse(AvatarLocation location, Context ctx, PKMember target, ParsedImage avatar,
                               MemberGuildSettings?targetGuildData)
    {
        var typeFrag = location switch
        {
            AvatarLocation.Server => "server avatar",
            AvatarLocation.Member => "avatar",
            _ => throw new ArgumentOutOfRangeException(nameof(location))
        };

        var serverFrag = location switch
        {
            AvatarLocation.Server =>
            $" This avatar will now be used when proxying in this server (**{ctx.Guild.Name}**).",
            AvatarLocation.Member when targetGuildData?.AvatarUrl != null =>
            $"\n{Emojis.Note} Note that this member *also* has a server-specific avatar set in this server (**{ctx.Guild.Name}**), and thus changing the global avatar will have no effect here.",
            _ => ""
        };

        var msg = avatar.Source switch
        {
            AvatarSource.User =>
            $"{Emojis.Success} Member {typeFrag} changed to {avatar.SourceUser?.Username}'s avatar!{serverFrag}\n{Emojis.Warn} If {avatar.SourceUser?.Username} changes their avatar, the member's avatar will need to be re-set.",
            AvatarSource.Url =>
            $"{Emojis.Success} Member {typeFrag} changed to the image at the given URL.{serverFrag}",
            AvatarSource.Attachment =>
            $"{Emojis.Success} Member {typeFrag} changed to attached image.{serverFrag}\n{Emojis.Warn} If you delete the message containing the attachment, the avatar will stop working.",
            _ => throw new ArgumentOutOfRangeException()
        };

        // The attachment's already right there, no need to preview it.
        var hasEmbed = avatar.Source != AvatarSource.Attachment;

        return(hasEmbed
            ? ctx.Reply(msg, new EmbedBuilder().Image(new Embed.EmbedImage(avatar.Url)).Build())
            : ctx.Reply(msg));
    }