Ejemplo n.º 1
0
 public static SystemPatch WithAllPrivacy(this SystemPatch system, PrivacyLevel level)
 {
     foreach (var subject in Enum.GetValues(typeof(SystemPrivacySubject)))
     {
         WithPrivacy(system, (SystemPrivacySubject)subject, level);
     }
     return(system);
 }
Ejemplo n.º 2
0
        private async Task <string> MakeAndSetNewToken(PKSystem system)
        {
            var patch = new SystemPatch {
                Token = StringUtils.GenerateToken()
            };

            system = await _db.Execute(conn => conn.UpdateSystem(system.Id, patch));

            return(system.Token);
        }
Ejemplo n.º 3
0
        public async Task Color(Context ctx)
        {
            ctx.CheckSystem();

            if (await ctx.MatchClear())
            {
                var patch = new SystemPatch {
                    Color = Partial <string> .Null()
                };
                await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, patch));

                await ctx.Reply($"{Emojis.Success} System color cleared.");
            }
            else if (!ctx.HasNext())
            {
                if (ctx.System.Color == null)
                {
                    await ctx.Reply(
                        $"Your system does not have a color set. To set one, type `pk;system color <color>`.");
                }
                else
                {
                    await ctx.Reply(embed : new EmbedBuilder()
                                    .Title("System color")
                                    .Color(ctx.System.Color.ToDiscordColor())
                                    .Thumbnail(new($"https://fakeimg.pl/256x256/{ctx.System.Color}/?text=%20"))
                                    .Description($"Your system's color is **#{ctx.System.Color}**. To clear it, type `pk;s color -clear`.")
                                    .Build());
                }
            }
            else
            {
                var color = ctx.RemainderOrNull();

                if (color.StartsWith("#"))
                {
                    color = color.Substring(1);
                }
                if (!Regex.IsMatch(color, "^[0-9a-fA-F]{6}$"))
                {
                    throw Errors.InvalidColorError(color);
                }

                var patch = new SystemPatch {
                    Color = Partial <string> .Present(color.ToLowerInvariant())
                };
                await _db.Execute(conn => _repo.UpdateSystem(conn, ctx.System.Id, patch));

                await ctx.Reply(embed : new EmbedBuilder()
                                .Title($"{Emojis.Success} System color changed.")
                                .Color(color.ToDiscordColor())
                                .Thumbnail(new($"https://fakeimg.pl/256x256/{color}/?text=%20"))
                                .Build());
            }
        }
Ejemplo n.º 4
0
        public async Task Description(Context ctx)
        {
            ctx.CheckSystem();

            if (ctx.MatchClear())
            {
                var patch = new SystemPatch {
                    Description = null
                };
                await _db.Execute(conn => conn.UpdateSystem(ctx.System.Id, patch));

                await ctx.Reply($"{Emojis.Success} System description cleared.");

                return;
            }

            var newDescription = ctx.RemainderOrNull()?.NormalizeLineEndSpacing();

            if (newDescription == null)
            {
                if (ctx.System.Description == null)
                {
                    await ctx.Reply("Your system does not have a description set. To set one, type `pk;s description <description>`.");
                }
                else if (ctx.MatchFlag("r", "raw"))
                {
                    await ctx.Reply($"```\n{ctx.System.Description}\n```");
                }
                else
                {
                    await ctx.Reply(embed : new DiscordEmbedBuilder()
                                    .WithTitle("System description")
                                    .WithDescription(ctx.System.Description)
                                    .WithFooter("To print the description with formatting, type `pk;s description -raw`. To clear it, type `pk;s description -clear`. To change it, type `pk;s description <new description>`.")
                                    .Build());
                }
            }
            else
            {
                if (newDescription.Length > Limits.MaxDescriptionLength)
                {
                    throw Errors.DescriptionTooLongError(newDescription.Length);
                }

                var patch = new SystemPatch {
                    Description = newDescription
                };
                await _db.Execute(conn => conn.UpdateSystem(ctx.System.Id, patch));

                await ctx.Reply($"{Emojis.Success} System description changed.");
            }
        }
    public async Task <PKSystem> UpdateSystem(SystemId id, SystemPatch patch, IPKConnection?conn = null)
    {
        _logger.Information("Updated {SystemId}: {@SystemPatch}", id, patch);
        var query = patch.Apply(new Query("systems").Where("id", id));
        var res   = await _db.QueryFirst <PKSystem>(conn, query, "returning *");

        _ = _dispatch.Dispatch(id, new UpdateDispatchData
        {
            Event     = DispatchEvent.UPDATE_SYSTEM,
            EventData = patch.ToJson(),
        });

        return(res);
    }
Ejemplo n.º 6
0
    public static SystemPatch WithPrivacy(this SystemPatch system, SystemPrivacySubject subject, PrivacyLevel level)
    {
        // what do you mean switch expressions can't be statements >.>
        _ = subject switch
        {
            SystemPrivacySubject.Description => system.DescriptionPrivacy   = level,
            SystemPrivacySubject.Front => system.FrontPrivacy               = level,
            SystemPrivacySubject.FrontHistory => system.FrontHistoryPrivacy = level,
            SystemPrivacySubject.MemberList => system.MemberListPrivacy     = level,
            SystemPrivacySubject.GroupList => system.GroupListPrivacy       = level,
            _ => throw new ArgumentOutOfRangeException($"Unknown privacy subject {subject}")
        };

        return(system);
    }
Ejemplo n.º 7
0
        public async Task Name(Context ctx)
        {
            ctx.CheckSystem();

            if (ctx.MatchClear())
            {
                var clearPatch = new SystemPatch {
                    Name = null
                };
                await _db.Execute(conn => conn.UpdateSystem(ctx.System.Id, clearPatch));

                await ctx.Reply($"{Emojis.Success} System name cleared.");

                return;
            }

            var newSystemName = ctx.RemainderOrNull();

            if (newSystemName == null)
            {
                if (ctx.System.Name != null)
                {
                    await ctx.Reply($"Your system's name is currently **{ctx.System.Name}**. Type `pk;system name -clear` to clear it.");
                }
                else
                {
                    await ctx.Reply("Your system currently does not have a name. Type `pk;system name <name>` to set one.");
                }
                return;
            }

            if (newSystemName != null && newSystemName.Length > Limits.MaxSystemNameLength)
            {
                throw Errors.SystemNameTooLongError(newSystemName.Length);
            }

            var patch = new SystemPatch {
                Name = newSystemName
            };
            await _db.Execute(conn => conn.UpdateSystem(ctx.System.Id, patch));

            await ctx.Reply($"{Emojis.Success} System name changed.");
        }
Ejemplo n.º 8
0
        public async Task Tag(Context ctx)
        {
            ctx.CheckSystem();

            if (ctx.MatchClear())
            {
                var patch = new SystemPatch {
                    Tag = null
                };
                await _db.Execute(conn => conn.UpdateSystem(ctx.System.Id, patch));

                await ctx.Reply($"{Emojis.Success} System tag cleared.");
            }
            else if (!ctx.HasNext(skipFlags: false))
            {
                if (ctx.System.Tag == null)
                {
                    await ctx.Reply($"You currently have no system tag. To set one, type `pk;s tag <tag>`.");
                }
                else
                {
                    await ctx.Reply($"Your current system tag is `{ctx.System.Tag}`. To change it, type `pk;s tag <tag>`. To clear it, type `pk;s tag -clear`.");
                }
            }
            else
            {
                var newTag = ctx.RemainderOrNull(skipFlags: false);
                if (newTag != null)
                {
                    if (newTag.Length > Limits.MaxSystemTagLength)
                    {
                        throw Errors.SystemNameTooLongError(newTag.Length);
                    }
                }

                var patch = new SystemPatch {
                    Tag = newTag
                };
                await _db.Execute(conn => conn.UpdateSystem(ctx.System.Id, patch));

                await ctx.Reply($"{Emojis.Success} System tag changed. Member names will now end with `{newTag}` when proxied.");
            }
        }
Ejemplo n.º 9
0
        public static SystemPatch ToSystemPatch(JObject o)
        {
            var patch = new SystemPatch();

            if (o.ContainsKey("name"))
            {
                patch.Name = o.Value <string>("name").NullIfEmpty().BoundsCheckField(Limits.MaxSystemNameLength, "System name");
            }
            if (o.ContainsKey("description"))
            {
                patch.Description = o.Value <string>("description").NullIfEmpty().BoundsCheckField(Limits.MaxDescriptionLength, "System description");
            }
            if (o.ContainsKey("tag"))
            {
                patch.Tag = o.Value <string>("tag").NullIfEmpty().BoundsCheckField(Limits.MaxSystemTagLength, "System tag");
            }
            if (o.ContainsKey("avatar_url"))
            {
                patch.AvatarUrl = o.Value <string>("avatar_url").NullIfEmpty().BoundsCheckField(Limits.MaxUriLength, "System avatar URL");
            }
            if (o.ContainsKey("tz"))
            {
                patch.UiTz = o.Value <string>("tz") ?? "UTC";
            }

            if (o.ContainsKey("description_privacy"))
            {
                patch.DescriptionPrivacy = o.Value <string>("description_privacy").ParsePrivacy("description");
            }
            if (o.ContainsKey("member_list_privacy"))
            {
                patch.MemberListPrivacy = o.Value <string>("member_list_privacy").ParsePrivacy("member list");
            }
            if (o.ContainsKey("front_privacy"))
            {
                patch.FrontPrivacy = o.Value <string>("front_privacy").ParsePrivacy("front");
            }
            if (o.ContainsKey("front_history_privacy"))
            {
                patch.FrontHistoryPrivacy = o.Value <string>("front_history_privacy").ParsePrivacy("front history");
            }
            return(patch);
        }
Ejemplo n.º 10
0
    public async Task <ActionResult <JObject> > EditSystem([FromBody] JObject changes)
    {
        var system = await _repo.GetSystem(User.CurrentSystem());

        var patch = SystemPatch.FromJSON(changes);

        patch.AssertIsValid();
        if (patch.Errors.Count > 0)
        {
            var err = patch.Errors[0];
            if (err is FieldTooLongError)
            {
                return(BadRequest($"Field {err.Key} is too long "
                                  + $"({(err as FieldTooLongError).ActualLength} > {(err as FieldTooLongError).MaxLength})."));
            }

            return(BadRequest($"Field {err.Key} is invalid."));
        }

        system = await _repo.UpdateSystem(system !.Id, patch);

        return(Ok(system.ToJson(User.ContextFor(system))));
    }
Ejemplo n.º 11
0
    public async Task <IActionResult> DoSystemPatch(string systemRef, [FromBody] JObject data)
    {
        var system = await ResolveSystem(systemRef);

        if (system == null)
        {
            throw Errors.SystemNotFound;
        }
        if (ContextFor(system) != LookupContext.ByOwner)
        {
            throw Errors.GenericMissingPermissions;
        }
        var patch = SystemPatch.FromJSON(data);

        patch.AssertIsValid();
        if (patch.Errors.Count > 0)
        {
            throw new ModelParseError(patch.Errors);
        }

        var newSystem = await _repo.UpdateSystem(system.Id, patch);

        return(Ok(newSystem.ToJson(LookupContext.ByOwner)));
    }
Ejemplo n.º 12
0
    private async Task <ImportResultNew> ImportPluralKit(JObject importFile)
    {
        var patch = SystemPatch.FromJSON(importFile, isImport: true);

        patch.AssertIsValid();
        if (patch.Errors.Count > 0)
        {
            var err = patch.Errors[0];
            if (err is FieldTooLongError)
            {
                throw new ImportException($"Field {err.Key} in export file is too long "
                                          + $"({(err as FieldTooLongError).ActualLength} > {(err as FieldTooLongError).MaxLength}).");
            }
            if (err.Text != null)
            {
                throw new ImportException(err.Text);
            }
            throw new ImportException($"Field {err.Key} in export file is invalid.");
        }

        await _repo.UpdateSystem(_system.Id, patch, _conn);

        if (importFile.ContainsKey("config"))
        {
            var configPatch = SystemConfigPatch.FromJson(importFile.Value <JObject>("config"));

            if (importFile.ContainsKey("timezone"))
            {
                configPatch.UiTz = importFile.Value <string>("timezone");
            }

            configPatch.AssertIsValid();
            if (configPatch.Errors.Count > 0)
            {
                throw new ImportException($"Field config.{patch.Errors[0].Key} in export file is invalid.");
            }

            await _repo.UpdateSystemConfig(_system.Id, configPatch, _conn);
        }

        var members  = importFile.Value <JArray>("members");
        var switches = importFile.Value <JArray>("switches");
        var groups   = importFile.Value <JArray>("groups");

        var newMembers = members.Count(m =>
        {
            var(found, _) = TryGetExistingMember(m.Value <string>("id"), m.Value <string>("name"));
            return(found == null);
        });

        await AssertMemberLimitNotReached(newMembers);

        if (groups != null)
        {
            var newGroups = groups.Count(g =>
            {
                var(found, _) = TryGetExistingGroup(g.Value <string>("id"), g.Value <string>("name"));
                return(found == null);
            });
            await AssertGroupLimitNotReached(newGroups);
        }

        foreach (JObject member in members)
        {
            await ImportMember(member);
        }

        if (groups != null)
        {
            foreach (JObject group in groups)
            {
                await ImportGroup(group);
            }
        }

        if (switches.Any(sw =>
                         sw.Value <JArray>("members").Any(m => !_knownMemberIdentifiers.ContainsKey((string)m))))
        {
            throw new ImportException("One or more switches include members that haven't been imported.");
        }

        await ImportSwitches(switches);

        return(_result);
    }