public UserController(NamikoDbContext context) { _context = context; }
public static async Task <Premium> RedeemCode(string id, ulong userId, ulong guildId) { var db = new NamikoDbContext(); var res = await db.PremiumCodes .Include(x => x.Uses.Where(x => x.UserId == userId || x.GuildId == guildId)) .FirstOrDefaultAsync(x => x.Id == id && (x.ExpiresAt == null || x.ExpiresAt > DateTime.Now) && x.UsesLeft > 0); if (res == null) { throw new NamikoException("Code invalid"); } bool used = res.Type switch { ProType.Guild => res.Uses.Any(x => x.GuildId == guildId), ProType.GuildPlus => res.Uses.Any(x => x.GuildId == guildId), ProType.Pro => res.Uses.Any(x => x.UserId == guildId), ProType.ProPlus => res.Uses.Any(x => x.UserId == guildId), _ => throw new ArgumentException("Unknown pro type") }; if (used) { throw new NamikoException("Code already redeemed on this account/server"); } bool active = res.Type switch { ProType.Guild => PremiumDb.IsPremium(guildId, res.Type), ProType.GuildPlus => PremiumDb.IsPremium(guildId, res.Type), ProType.Pro => PremiumDb.IsPremium(userId, res.Type), ProType.ProPlus => PremiumDb.IsPremium(userId, res.Type), _ => throw new ArgumentException("Unknown pro type") }; if (active) { throw new NamikoException($"{res.Type.ToString()} already active"); } var premium = new Premium { GuildId = guildId, UserId = userId, Type = res.Type, ClaimDate = System.DateTime.Now, ExpireSent = false, ExpiresAt = DateTime.Now.AddDays(res.DurationDays) }; var use = new PremiumCodeUse { GuildId = guildId, UserId = userId, PremiumCode = res, PremiumCodeId = res.Id, ClaimedAt = DateTime.Now }; res.UsesLeft--; db.PremiumCodeUses.Add(use); db.Premiums.Add(premium); db.Update(res); await db.SaveChangesAsync(); return(premium); }
public static async Task Timer_RequestSauce(object sender, ElapsedEventArgs e) { Waifu waifu = null; List <Embed> embeds = new List <Embed>(); SauceRequest req = null; if (sender != null && sender is SauceRequest) { req = sender as SauceRequest; waifu = req.Waifu; } try { using var db = new NamikoDbContext(); if (waifu != null) { waifu = await db.Waifus.AsQueryable().FirstOrDefaultAsync(x => x.Source.Equals(waifu.Source) && x.ImageSource.Equals("missing")); } if (waifu == null) { waifu = await db.Waifus.AsQueryable().OrderBy(x => Guid.NewGuid()).FirstOrDefaultAsync(x => x.ImageSource.Equals("missing")); if (waifu == null) { await WebhookClients.SauceRequestChannel.SendMessageAsync("`No unknown sauces. Idling...`"); return; } } embeds.Add(WaifuUtil.WaifuEmbedBuilder(waifu).Build()); var res = await WebUtil.SauceNETSearchAsync(waifu.HostImageUrl); if (res.Message.Contains("limit exceeded", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("Sauce limit exceeded"); } else { embeds.Add(WebUtil.SauceEmbed(res, waifu.HostImageUrl).Build()); } var family = await db.Waifus.AsQueryable().Where(x => x.Source.Equals(waifu.Source) && !(x.ImageSource == null || x.ImageSource.Equals("retry") || x.ImageSource.Equals("missing"))).ToListAsync(); family = family.DistinctBy(x => x.ImageSource).ToList(); string familySauces = ""; foreach (var w in family) { string add = $"**{w.Name}** - {w.ImageSource}\n"; if ((familySauces + add).Length < 1900) { familySauces += add; } } if (familySauces != "") { var eb = new EmbedBuilderPrepared(); eb.WithTitle("Possible sauces"); eb.WithDescription($"Image sauces of waifus from **{waifu.Source}**:\n{familySauces}"); embeds.Add(eb.Build()); } if (req == null || req.Channel == null) { await WebhookClients.SauceRequestChannel.SendMessageAsync("Missing waifu image sauce", embeds : embeds); } else { foreach (var embed in embeds) { await req.Channel.SendMessageAsync(embed : embed); } } } catch (Exception ex) { SentrySdk.WithScope(scope => { if (waifu != null) { scope.SetExtras(waifu.GetProperties()); } SentrySdk.CaptureException(ex); }); if (req == null || req.Channel == null) { await WebhookClients.SauceRequestChannel.SendMessageAsync($"Broke on **{waifu.Name}** - please find source manually."); } else { await req.Channel.SendMessageAsync($"Broke on **{waifu.Name}** - please find source manually."); } } }
public async static Task <int> ExecuteSQL(string query) { using var db = new NamikoDbContext(); return(await db.Database.ExecuteSqlRawAsync(query)); }
private static async void Timer_GetSauce(object sender, ElapsedEventArgs e) { if (!NullSource && !RetrySource) { return; } Waifu waifu = null; try { using var db = new NamikoDbContext(); if (NullSource) { waifu = await db.Waifus.AsQueryable().FirstOrDefaultAsync(x => x.ImageSource == null); Console.WriteLine(DateTime.Now + " New sauce - " + waifu?.Name); } if (RetrySource && waifu == null) { NullSource = false; waifu = await db.Waifus.AsQueryable().AsQueryable().FirstOrDefaultAsync(x => x.ImageSource.Equals("retry")); Console.WriteLine(DateTime.Now + " Retrying - " + waifu?.Name); } if (waifu == null) { RetrySource = false; await WebhookClients.SauceChannel.SendMessageAsync("`No missing sauces. Idling...`"); return; } var res = await WebUtil.SauceNETSearchAsync(waifu.HostImageUrl); if (res.Message.Contains("limit exceeded", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("Sauce limit exceeded"); return; } foreach (var result in res.Results.OrderByDescending(x => Double.Parse(x.Similarity))) { if (Double.Parse(result.Similarity) > 80) { waifu.ImageSource = result.SourceURL; await WebhookClients.SauceChannel.SendMessageAsync($"<:TickYes:577838859107303424> **{waifu.Name}** - {result.DatabaseName} {result.Similarity}% ({result.SourceURL})"); break; } else if ((result.DatabaseName == "Pixiv" || result.DatabaseName == "Danbooru" || result.DatabaseName == "Gelbooru" || result.DatabaseName == "AniDb" || result.DatabaseName == "Twitter") && Double.Parse(result.Similarity) > 60) { waifu.ImageSource = result.SourceURL; await WebhookClients.SauceChannel.SendMessageAsync($":question: **{waifu.Name}** - {result.DatabaseName} {result.Similarity}% ({result.SourceURL})\n" + $"Verify: *{waifu.Source}* ({waifu.HostImageUrl})", embeds : new List <Embed> { WebUtil.SauceEmbed(res, waifu.HostImageUrl).Build() }); break; } else if (result.DatabaseName == "AniDb" && Double.Parse(result.Similarity) > 40) { waifu.ImageSource = result.SourceURL; await WebhookClients.SauceChannel.SendMessageAsync($":question: **{waifu.Name}** - {result.DatabaseName} {result.Similarity}% ({result.SourceURL})\n" + $"Verify: *{waifu.Source}* ({waifu.HostImageUrl})", embeds : new List <Embed> { WebUtil.SauceEmbed(res, waifu.HostImageUrl).Build() }); break; } } if (waifu.ImageSource == null || waifu.ImageSource == "") { waifu.ImageSource = "retry"; } else if (waifu.ImageSource == "retry") { waifu.ImageSource = "missing"; await WebhookClients.SauceChannel.SendMessageAsync($"<:TickNo:577838859077943306> **{waifu.Name}** - missing sauce."); } db.Waifus.Update(waifu); await db.SaveChangesAsync(); } catch (Exception ex) { SentrySdk.WithScope(scope => { if (waifu != null) { scope.SetExtras(waifu.GetProperties()); } SentrySdk.CaptureException(ex); }); } }
public static async void Timer_CleanData(object sender, ElapsedEventArgs e) { try { var watch = new Stopwatch(); watch.Start(); int s = 0; int r; using (var db = new NamikoDbContext()) { var ids = db.Servers .AsQueryable() .Where(x => x.LeaveDate != null && x.LeaveDate.Value.AddDays(3) < DateTime.Now) .OrderBy(x => x.LeaveDate) .Select(x => x.GuildId) .Skip(CleanSkip) .Take(CleanTake) .ToHashSet(); s = ids.Count; db.RemoveRange(db.Teams.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.Dailies.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.Servers.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.Weeklies.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.Toasties.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.Marriages.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.ShopRoles.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.PublicRoles.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.WaifuWishlist.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.FeaturedWaifus.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.UserInventories.AsQueryable().Where(x => ids.Contains(x.GuildId))); db.RemoveRange(db.SpecialChannels.AsQueryable().Where(x => ids.Contains(x.GuildId))); var shops = db.WaifuShops.AsQueryable().Where(x => ids.Contains(x.GuildId)); db.ShopWaifus.RemoveRange(db.ShopWaifus.AsQueryable().Where(x => shops.Any(y => y.Id == x.WaifuShop.Id))); db.WaifuShops.RemoveRange(shops); r = await db.SaveChangesAsync(); } watch.Stop(); if (s > 0 || r > 0) { Console.WriteLine($"[TIMER] Namiko cleared {s} servers. {r} rows affected. It took her {watch.ElapsedMilliseconds} ms."); await WebhookClients.NamikoLogChannel.SendMessageAsync($"[TIMER] Namiko cleared {s} servers. {r} rows affected. It took her {watch.ElapsedMilliseconds} ms."); } CleanTake = 100; if (!(sender is bool)) { await Task.Delay(TimeSpan.FromMinutes(20)); Timer_CleanData(false, null); await Task.Delay(TimeSpan.FromMinutes(20)); Timer_CleanData(false, null); } } catch (Exception ex) { SentrySdk.CaptureException(ex); if (CleanTake > 1) { CleanTake /= 2; } else { CleanSkip++; using (var db = new NamikoDbContext()) { var id = db.Servers.AsQueryable().Where(x => x.LeaveDate != null && x.LeaveDate.Value.AddDays(3) < DateTime.Now).Select(x => x.GuildId).FirstOrDefault(); await WebhookClients.NamikoLogChannel.SendMessageAsync($"[TIMER] Skipping clean of guild {id}."); } } } }
public async Task LeaveInactiveGuilds(int days, int newDays, int delay) { if (days < 14) { await Context.Channel.SendMessageAsync("Less than 14 days illegal"); return; } string desc = ""; using (var statsdb = new StatsDbContext()) using (var db = new NamikoDbContext()) { var now = DateTime.Now; var newServers = db.Servers.AsQueryable().Where(x => x.JoinDate > now.AddDays(-newDays)).Select(x => x.GuildId).Distinct().ToHashSet(); desc += $"New servers: {newServers.Count}\n" + $"AMFWT: {newServers.Contains(417064769309245471)}\n" + $"Personal: {newServers.Contains(231113616911237120)}\n" + $"NTR: {newServers.Contains(418900885079588884)}\n\n"; var active = statsdb.CommandLogs.AsQueryable().Where(x => x.Date > now.AddDays(-days)).Select(x => x.GuildId).Distinct().ToHashSet(); desc += $"Active servers: {active.Count}\n" + $"AMFWT: {active.Contains(417064769309245471)}\n" + $"Personal: {active.Contains(231113616911237120)}\n" + $"NTR: {active.Contains(418900885079588884)}\n\n"; var guilds = Program.GetClient().Guilds.ToList(); desc += $"Joined servers: {guilds.Count}\n" + $"AMFWT: {guilds.Any(x => x.Id == 417064769309245471)}\n" + $"Personal: {guilds.Any(x => x.Id == 231113616911237120)}\n" + $"NTR: {guilds.Any(x => x.Id == 418900885079588884)}\n\n"; guilds = guilds.Where(x => !active.Contains(x.Id) && !newServers.Contains(x.Id)).ToList(); desc += $"Filtered servers: {guilds.Count}\n" + $"AMFWT: {guilds.Any(x => x.Id == 417064769309245471)}\n" + $"Personal: {guilds.Any(x => x.Id == 231113616911237120)}\n" + $"NTR: {guilds.Any(x => x.Id == 418900885079588884)}\n\n"; desc += "Leaving filtered guilds..."; await Context.Channel.SendMessageAsync(desc); Program.GuildLeaveEvent = false; if (guilds.Count >= Program.GetClient().Guilds.Count) { await Context.Channel.SendMessageAsync("Filtered same or higher than all. Cancelling."); return; } int s = 0; int f = 0; int dm = 0; foreach (var guild in guilds) { try { await guild.Owner.SendMessageAsync($"I am leaving **{guild.Name}** due to {days}+ days of inactivity. All data like user balances related to that server will be deleted in 3 days.\n" + $"You can re-invite me using this link: {LinkHelper.BotInvite}"); dm++; } catch { } try { await guild.LeaveAsync(); s++; } catch { } if ((s + f) % 100 == 0) { try { _ = Context.Channel.SendMessageAsync($"Left: {s}\n" + $"Failed: {f}\n" + $"Dms: {dm}\n" + $"Remaining: {guilds.Count - s - f}"); } catch { } } await Task.Delay(delay); } await Context.Channel.SendMessageAsync($"Left: {s}\n" + $"Failed: {f}\n" + $"Dms: {dm}\n" + $"Done."); Program.GuildLeaveEvent = true; } }
public async Task CreateCommandSchema([Remainder] string str = "") { var cmds = Program.GetCommands(); var modules = new List <Model.Module>(); foreach (var module in cmds.Modules) { var m = new Model.Module { Name = module.Name, Commands = new List <Command>() }; foreach (var command in module.Commands) { var cmd = new Model.Command(); var split = command.Summary == null ? null : command.Summary.Split(new string[] { "\n**Usage**:" }, StringSplitOptions.None); cmd.ModuleName = module.Name; cmd.Name = Regex.Replace(command.Name, "[a-z][A-Z]", m => $"{m.Value[0]} {m.Value[1]}");; cmd.Aliases = command.Aliases.Aggregate((x, y) => x + ',' + y); cmd.Conditions = ""; if (split != null && split.Count() > 0) { cmd.Description = split[0]; if (split.Count() > 1) { cmd.Example = split[1].Replace("`", ""); } } foreach (var x in command.Preconditions) { if (x is RequireUserPermissionAttribute) { var prec = x as RequireUserPermissionAttribute; cmd.Conditions += prec.ChannelPermission != null ? $"{prec.ChannelPermission}," : ""; cmd.Conditions += prec.GuildPermission != null ? $"{prec.GuildPermission}," : ""; } else if (x is CustomPrecondition) { var prec = x as CustomPrecondition; cmd.Conditions += $"{prec.GetName()},"; } } cmd.Conditions = cmd.Conditions.Trim(','); m.Commands.Add(cmd); } modules.Add(m); } using var db = new NamikoDbContext(); db.Modules.RemoveRange(db.Modules.Include(x => x.Commands)); var res = await db.SaveChangesAsync(); db.Modules.AddRange(modules); res += await db.SaveChangesAsync(); await ReplyAsync($"Updated db command list. {res} rows affected."); }
public RedirectController(NamikoDbContext context) { _context = context; }