Exemple #1
0
 public UserController(NamikoDbContext context)
 {
     _context = context;
 }
Exemple #2
0
        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);
        }
Exemple #3
0
        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.");
                }
            }
        }
Exemple #4
0
 public async static Task <int> ExecuteSQL(string query)
 {
     using var db = new NamikoDbContext();
     return(await db.Database.ExecuteSqlRawAsync(query));
 }
Exemple #5
0
        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);
                });
            }
        }
Exemple #6
0
        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}.");
                    }
                }
            }
        }
Exemple #7
0
        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;
                }
        }
Exemple #8
0
        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.");
        }
Exemple #9
0
 public RedirectController(NamikoDbContext context)
 {
     _context = context;
 }