Ejemplo n.º 1
0
        public override int GetHashCode()
        {
            int hash = Name.GetHashCode();

            if (Icon != null)
            {
                hash ^= Icon.GetHashCode();
            }
            hash ^= IsRepeatable.GetHashCode();
            hash ^= RequiredLevel.GetHashCode();
            hash ^= XpLevel.GetHashCode();
            hash ^= Difficulty.GetHashCode();
            hash ^= CanAbandon.GetHashCode();
            hash ^= IsHidden.GetHashCode();
            hash ^= IsClassQuest.GetHashCode();
            hash ^= IsBonus.GetHashCode();
            hash ^= BonusShareable.GetHashCode();
            hash ^= Category.GetHashCode();
            foreach (var x in Branches)
            {
                hash ^= x.GetHashCode();
            }
            foreach (var x in Classes)
            {
                hash ^= x.Id.GetHashCode();
            }
            return(hash);
        }
Ejemplo n.º 2
0
        private async Task UpdateXp(SocketMessage message, IGuildChannel channel)
        {
            if (!await _config.XpGainEnabled(channel.Id))
            {
                return;
            }

            using IServiceScope scope = _scopeFactory.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService <RokiContext>();

            GuildConfig guildConfig = await _config.GetGuildConfigAsync(channel.GuildId);

            UserData data = await context.UserData.AsQueryable().Where(x => x.UserId == message.Author.Id && x.GuildId == channel.GuildId).SingleOrDefaultAsync();

            if (data == null)
            {
                if (await context.Users.AsNoTracking().AnyAsync(x => x.Id == message.Author.Id))
                {
                    data = new UserData(message.Author.Id, channel.GuildId);
                }
                else
                {
                    data = new UserData(message.Author.Id, channel.GuildId)
                    {
                        User = new User(message.Author.Username, message.Author.Discriminator, message.Author.AvatarId)
                    };
                }

                await context.UserData.AddAsync(data);
            }

            // temp
            // these are always false
            bool doubleXp = data.Xp < 0;
            bool fastXp   = data.Xp < 0;

            var oldXp = new XpLevel(data.Xp);

            DateTime now = DateTime.UtcNow;

            if (fastXp && now - data.LastXpGain >= TimeSpan.FromSeconds(guildConfig.XpFastCooldown))
            {
                data.Xp += doubleXp ? guildConfig.XpPerMessage * 2 : guildConfig.XpPerMessage;
            }
            else if (DateTime.UtcNow - data.LastXpGain >= TimeSpan.FromSeconds(guildConfig.XpCooldown))
            {
                data.Xp += doubleXp ? guildConfig.XpPerMessage * 2 : guildConfig.XpPerMessage;
            }
            else
            {
                return;
            }

            data.LastXpGain = now;
            var newXp = new XpLevel(data.Xp);

            if (oldXp.Level == newXp.Level)
            {
                await context.SaveChangesAsync();

                return;
            }

            data.LastLevelUp = now;

            await SendNotification(data, message, newXp.Level).ConfigureAwait(false);

            List <XpReward> rewards = await context.XpRewards.AsNoTracking().Where(x => x.GuildId == channel.GuildId && x.Level == newXp.Level).ToListAsync();

            if (rewards.Count > 0)
            {
                var sb = new StringBuilder();
                foreach (XpReward reward in rewards)
                {
                    string[] parsed = reward.Details.Split(';');
                    if (parsed.Length < 2)
                    {
                        continue;
                    }

                    switch (parsed[0])
                    {
                    case "currency":
                    {
                        long amount = long.Parse(parsed[1]);
                        await _currency.AddCurrencyAsync(data.UserId, data.GuildId, channel.Id, message.Id, $"#{reward.Id} XP Level {reward.Level} Reward", amount);

                        sb.AppendLine($"+ `{amount:N0}` {guildConfig.CurrencyIcon}");
                        break;
                    }

                    case "role":
                    {
                        SocketRole role = (channel.Guild as SocketGuild)?.GetRole(ulong.Parse(parsed[1]));
                        if (role == null)
                        {
                            continue;
                        }
                        var guildUser = (IGuildUser)message.Author;
                        await guildUser.AddRoleAsync(role).ConfigureAwait(false);

                        sb.AppendLine(reward.Description);
                        break;
                    }
                    }
                }

                IDMChannel dm = await message.Author.GetOrCreateDMChannelAsync().ConfigureAwait(false);

                try
                {
                    await dm.EmbedAsync(new EmbedBuilder().WithOkColor()
                                        .WithTitle($"Level `{newXp.Level}` Rewards - {channel.Guild.Name}")
                                        .WithDescription("Here are your rewards:\n" + sb))
                    .ConfigureAwait(false);

                    await dm.CloseAsync().ConfigureAwait(false);
                }
                catch
                {
                    // unable to send dm to user
                    // ignored
                }
            }

            await context.SaveChangesAsync();
        }
Ejemplo n.º 3
0
        public static MemoryStream GenerateXpBar(Stream avatar, XpLevel xp, string rank,
                                                 string username, string discriminator, DateTime date, bool doubleXp, bool fastXp)
        {
            using Image image = Image.Load("data/xp/roki_xp_half.png");

            var transparentGray = new Rgba32(211, 211, 211, 220);

            var grayBackground = new RectangleF(PfpOutlineX + (PfpLength + 10) / 2, 7.5f, 680, 185);

            var pfpBackground = new RectangleF(PfpOutlineX, PfpOutlineY, PfpLength + 10, PfpLength + 10);
            var pfpOutline    = new RectangleF(PfpOutlineX, PfpOutlineY, PfpLength + 10, PfpLength + 10);

            var xpBarOutline = new RectangleF(XpBarX, XpBarY, XpBarLength, XpBarHeight);

            image.Mutate(x => x
                         .Fill(new Color(transparentGray), grayBackground)
                         // profile pic
                         .Fill(Color.White, pfpBackground)
                         .Draw(Color.WhiteSmoke, 3.5f, pfpOutline)
                         .Fill(Color.HotPink, new RectangleF(37, 25, 150, 150)) // profile pic

                                                                                // xp bar
                         .Draw(Color.HotPink, 2.5f, xpBarOutline));

            if (xp.TotalXp != 0)
            {
                var xpBarProgress = new RectangleF(XpBarX + 2.5f, XpBarY + 2.5f, (XpBarLength - 5) * ((float)xp.ProgressXp / xp.RequiredXp), XpBarHeight - 5);
                image.Mutate(x => x.Fill(Color.HotPink, xpBarProgress));
            }

            using (Image pfp = Image.Load(avatar))
            {
                pfp.Mutate(x => x.Resize(new Size(PfpLength, PfpLength)));
                image.Mutate(x => x.DrawImage(pfp, new Point(PfpOutlineX + 5, PfpOutlineY + 5), 1));
            }

            var fonts = new FontCollection();

            fonts.Install("data/xp/DIN_REG.ttf");
            fonts.Install("data/xp/DIN_MED.ttf");
            Font usernameFont      = fonts.CreateFont("DIN", 30);
            Font discriminatorFont = fonts.CreateFont("DIN", 21);
            Font xpFont            = fonts.CreateFont("DIN", 30);
            Font headerFont        = fonts.CreateFont("DIN Medium", 20);
            Font bodyFont          = fonts.CreateFont("DIN", 25);

            image.Mutate(x => x
                         .DrawUsername(usernameFont, discriminatorFont, username, $"#{discriminator}", new PointF(XpBarX, 50)) // username + discrim
                         .DrawText(new TextGraphicsOptions {
                TextOptions = { HorizontalAlignment = HorizontalAlignment.Center }
            },
                                   $"XP: {xp.TotalXp:N0} / {xp.TotalRequiredXp:N0}", xpFont, Color.DarkSlateGray, new PointF(XpBarX + XpBarLength / 2, 66)) // xp progress
                         .DrawStats(headerFont, bodyFont, $"#{rank}", xp.Level.ToString("N0"), (xp.TotalRequiredXp - xp.TotalXp).ToString("N0"), date)
                         .DrawBoosts(doubleXp, fastXp));

            var stream = new MemoryStream();

            image.SaveAsPng(stream);
            stream.Position = 0;
            return(stream);
        }
Ejemplo n.º 4
0
        public async Task Experience(IUser user = null)
        {
            if (user == null || user.IsBot)
            {
                user = Context.User;
            }

            await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);

            long seconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

            RedisValue image = await _cache.StringGetAsync($"xp:image:{user.Id}:{Context.Guild.Id}");

            if (image.HasValue)
            {
                await using var stream = new MemoryStream((byte[])image);
                await Context.Channel.SendFileAsync(stream, $"xp-{user.Username}-{seconds}.png").ConfigureAwait(false);

                return;
            }

            Stream avatar;

            using (HttpClient http = _http.CreateClient())
            {
                try
                {
                    // handle gif avatars in future
                    string avatarUrl = user.GetAvatarUrl(ImageFormat.Png) ?? user.GetDefaultAvatarUrl();
                    avatar = await http.GetStreamAsync(avatarUrl).ConfigureAwait(false);
                }
                catch (Exception)
                {
                    Log.Error("Error downloading avatar");
                    return;
                }
            }

            var data = await _context.UserData.AsNoTracking()
                       .AsQueryable()
                       .Where(x => x.UserId == user.Id && x.GuildId == Context.Guild.Id)
                       .Select(x => new { x.Xp, x.LastLevelUp, x.LastXpGain })
                       .SingleAsync();

            var xp   = new XpLevel(data.Xp);
            int rank = await GetUserXpRank(user.Id, Context.Guild.Id);

            bool doubleXp = await _context.Subscriptions.AsNoTracking()
                            .AnyAsync(x => x.UserId == user.Id && x.GuildId == Context.Guild.Id && x.Item.Details == "doublexp");

            bool fastXp = await _context.Subscriptions.AsNoTracking()
                          .AnyAsync(x => x.UserId == user.Id && x.GuildId == Context.Guild.Id && x.Item.Details == "fastxp");

            await using MemoryStream xpImage = XpDrawExtensions.GenerateXpBar(avatar, xp, $"{rank}",
                                                                              user.Username, user.Discriminator, data.LastLevelUp, doubleXp, fastXp);
            await avatar.DisposeAsync();

            await _cache.StringSetAsync($"xp:image:{user.Id}:{Context.Guild.Id}", xpImage.ToArray(), TimeSpan.FromMinutes(5), flags : CommandFlags.FireAndForget);

            await Context.Channel.SendFileAsync(xpImage, $"xp-{user.Username}-{seconds}.png").ConfigureAwait(false);
        }