public async Task <(Entities.Sankaku.Image Information, byte[] Data)> GetImage(DiscordChannel channel, int skip = 0) { using var sankakuContext = new SankakuContext(); var channelIDLong = Convert.ToInt64(channel.Id); var startDate = DateTime.Now - TimeSpan.FromDays(90); if (!_cachedImages.ContainsKey(channelIDLong)) { Console.WriteLine($"Couldn't find cached Images for Channel {channelIDLong}"); throw new Exception("Couldn't find cached Images for Channel."); } var images = _cachedImages[Convert.ToInt64(channelIDLong)]; async Task RemoveImage(long image) { images.Remove(image); var sankakuImage = await sankakuContext.Image.FirstOrDefaultAsync(); if (sankakuImage != null) { sankakuImage.IsAvailableBool = false; await sankakuContext.SaveChangesAsync(); } } var hasImage = images.Where(cImg => !_postedImages.Contains(cImg)).Skip(skip).Any(); if (hasImage == false) { await Console.Error.WriteLineAsync("Could not find a suitable Sankaku Image"); throw new Exception("Could not find a suitable Sankaku Image."); } Uri imageUri = null; int attempt = 0; Entities.Sankaku.Image imgToPost = null; while (imageUri == null && attempt < 10) { var imgToPostID = images.Where(cImg => !_postedImages.Contains(cImg)).Skip(skip).FirstOrDefault(); if (imgToPostID == default) { await Console.Error.WriteLineAsync("Could not find a suitable Sankaku Image in loop."); throw new Exception("Could not find a suitable Sankaku Image in loop."); } imgToPost = await GetOriginalImage(imgToPostID); if (imgToPost == null || imgToPost.Status != Entities.Sankaku.Status.Active || imgToPost.FileUrl == null || imgToPost.FileSize > 8_000_000) { if (imgToPost == null) { await Console.Error.WriteLineAsync($"Could not retrieve image with nr. {imgToPost.Id}"); } else if (imgToPost.Status != Entities.Sankaku.Status.Active) { await Console.Error.WriteLineAsync($"Cannot send image with nr. {imgToPost.Id} because its Status is not \"Active\""); } else if (imgToPost.FileUrl == null) { await Console.Error.WriteLineAsync($"Cannot send image with nr. {imgToPost.Id} because its FileUrl is null"); } else if (imgToPost.FileSize > 8_000_000) { await Console.Error.WriteLineAsync($"Cannot send image with nr. {imgToPost.Id} because it's too big"); } await RemoveImage(imgToPost.Id); await Task.Delay(100); } else { imageUri = imgToPost.FileUrl; break; } attempt++; } if (imageUri == null) { await Console.Error.WriteLineAsync($"Attempt {attempt} of retrieving sankaku Image has not succeeded."); throw new Exception($"Attempt {attempt} of retrieving sankaku Image has not succeeded."); } var link = HttpUtility.HtmlDecode(imageUri.AbsoluteUri); HttpResponseMessage response = null; try { response = await _httpClient.GetAsync(link); } catch (Exception) { } if (response.StatusCode != HttpStatusCode.OK) { await Console.Error.WriteLineAsync($"Could not get Image Link for {imgToPost}").ConfigureAwait(false); await RemoveImage(imgToPost.Id); throw new Exception($"Could not get Image Link."); } return(imgToPost, await response.Content.ReadAsByteArrayAsync()); }
private async Task UpdateCache() { Stopwatch sw = new Stopwatch(); Console.WriteLine("SankakuBot: Updating Cache"); using var sankakuContext = new SankakuContext(30, 1); using var discordContext = new DiscordContext(); sw.Start(); var minTime = DateTime.Now - TimeSpan.FromDays(90); foreach (var setting in discordContext.SabrinaSettings.Where(ss => ss.FeetChannel != null).ToArray()) { var channel = setting.FeetChannel.Value; var channelParam = new SqlParameter("@channel", System.Data.SqlDbType.BigInt) { Value = channel }; var dateParam = new SqlParameter("@minDate", minTime); var minScoreParam = new SqlParameter("@minScore", _minScore); var minWhiteWeightParam = new SqlParameter("@minWhiteWeight", _minWhiteWeight); using SqlConnection conn = new SqlConnection(Config.AdminConnectionString); var cmd = conn.CreateCommand(); cmd.CommandTimeout = 360; cmd.CommandText = @"SELECT TOP(100) [id], [score], [rating], [ratingcount], [isavailable] FROM sankaku.dbo.[image] mainImg WHERE (SELECT Sum(weight) FROM sankaku.dbo.[imagetag] JOIN discord.dbo.[sankaku_tagwhitelist] ON discord.dbo.[sankaku_tagwhitelist].tagid = sankaku.dbo.[imagetag].tagid WHERE sankaku.dbo.[imagetag].imageid = mainImg.id AND discord.dbo.[sankaku_tagwhitelist].channelid = @channel) > @minWhiteWeight AND (SELECT Count(*) FROM sankaku.dbo.[imagetag] JOIN discord.dbo.[sankaku_tagblacklist] ON discord.dbo.[sankaku_tagblacklist].tagid = sankaku.dbo.[imagetag].tagid WHERE sankaku.dbo.[imagetag].imageid = mainImg.id AND discord.dbo.[sankaku_tagblacklist].channelid = @channel) = 0 AND ( (SELECT Count(1) Date FROM discord.dbo.[sankakupost] WHERE discord.dbo.[sankakupost].imageid = mainImg.id) = 0 OR (SELECT TOP(1) date FROM discord.dbo.[sankakupost] WHERE discord.dbo.[sankakupost].imageid = mainImg.id ORDER BY date DESC) < @minDate ) AND mainImg.score > @minScore AND mainImg.isavailable = 1" ; cmd.Parameters.Add(channelParam); cmd.Parameters.Add(dateParam); cmd.Parameters.Add(minScoreParam); cmd.Parameters.Add(minWhiteWeightParam); await conn.OpenAsync(); var reader = await cmd.ExecuteReaderAsync(); List <Image> cachedImages = new List <Image>(); while (await reader.ReadAsync()) { cachedImages.Add(new Image() { Id = reader.GetInt64(0), Score = reader.GetInt32(1), Rating = reader.GetInt32(2), RatingCount = reader.GetInt32(3), IsAvailable = reader.GetInt16(4) }); } await conn.CloseAsync(); if (!_cachedImages.ContainsKey(channel)) { _cachedImages.Add(channel, new List <long>()); } else { _cachedImages[channel].Clear(); } _cachedImages[channel] = cachedImages.Select(img => img.Id).ToList(); } _postedImages.Clear(); sankakuContext.Dispose(); Console.WriteLine($"Finished updating Sankaku Cache after {sw.Elapsed}"); }