示例#1
0
        /// <summary>
        /// Gets or creates a set of statistics for a given user.
        /// </summary>
        /// <param name="discordUser">The user.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserStatistics> > GetOrCreateUserStatisticsAsync
        (
            IUser discordUser
        )
        {
            var existingStatistics = await _database.UserStatistics.AsQueryable().FirstOrDefaultAsync
                                     (
                s => s.User.DiscordID == (long)discordUser.Id
                                     );

            if (!(existingStatistics is null))
            {
                return(existingStatistics);
            }

            var getUser = await _users.GetOrRegisterUserAsync(discordUser);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <UserStatistics> .FromError(getUser));
            }

            var user = getUser.Entity;

            var newStatistics = _database.CreateProxy <UserStatistics>(user);

            _database.UserStatistics.Update(newStatistics);
            await _database.SaveChangesAsync();

            return(newStatistics);
        }
        /// <summary>
        /// Gets or creates a set of statistics for a given user.
        /// </summary>
        /// <param name="discordUser">The user.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserStatistics> > GetOrCreateUserStatisticsAsync
        (
            IUser discordUser,
            CancellationToken ct = default
        )
        {
            var statistics = await _database.UserStatistics.ServersideQueryAsync
                             (
                q => q
                .Where(s => s.User.DiscordID == (long)discordUser.Id)
                .SingleOrDefaultAsync(ct)
                             );

            if (!(statistics is null))
            {
                return(statistics);
            }

            var getUser = await _users.GetOrRegisterUserAsync(discordUser, ct);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <UserStatistics> .FromError(getUser));
            }

            var user = getUser.Entity;

            var newStatistics = _database.CreateProxy <UserStatistics>(user);

            _database.UserStatistics.Update(newStatistics);
            await _database.SaveChangesAsync(ct);

            return(newStatistics);
        }
        /// <summary>
        /// Gets or creates a set of per-channel statistics for a given user.
        /// </summary>
        /// <param name="discordUser">The user.</param>
        /// <param name="discordChannel">The channel.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserChannelStatistics> > GetOrCreateUserChannelStatisticsAsync
        (
            IGuildUser discordUser,
            ITextChannel discordChannel,
            CancellationToken ct = default
        )
        {
            var getServerStats = await GetOrCreateUserServerStatisticsAsync(discordUser, ct);

            if (!getServerStats.IsSuccess)
            {
                return(CreateEntityResult <UserChannelStatistics> .FromError(getServerStats));
            }

            var serverStats   = getServerStats.Entity;
            var existingStats = serverStats.ChannelStatistics.FirstOrDefault
                                (
                s => s.ChannelID == (long)discordChannel.Id
                                );

            if (!(existingStats is null))
            {
                return(existingStats);
            }

            var newStats = _database.CreateProxy <UserChannelStatistics>(discordChannel);

            _database.Update(newStats);
            serverStats.ChannelStatistics.Add(newStats);

            await _database.SaveChangesAsync(ct);

            return(newStats);
        }
示例#4
0
        /// <summary>
        /// Creates a new character role from the given Discord role and access condition.
        /// </summary>
        /// <param name="role">The discord role.</param>
        /// <param name="access">The access conditions.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <CharacterRole> > CreateCharacterRoleAsync
        (
            IRole role,
            RoleAccess access,
            CancellationToken ct = default
        )
        {
            var getExistingRoleResult = await GetCharacterRoleAsync(role, ct);

            if (getExistingRoleResult.IsSuccess)
            {
                return(CreateEntityResult <CharacterRole> .FromError
                       (
                           "That role is already registered as a character role."
                       ));
            }

            var getServerResult = await _servers.GetOrRegisterServerAsync(role.Guild, ct);

            if (!getServerResult.IsSuccess)
            {
                return(CreateEntityResult <CharacterRole> .FromError(getServerResult));
            }

            var server = getServerResult.Entity;

            var characterRole = _database.CreateProxy <CharacterRole>(server, (long)role.Id, access);

            _database.CharacterRoles.Update(characterRole);
            await _database.SaveChangesAsync(ct);

            return(characterRole);
        }
示例#5
0
        /// <summary>
        /// Creates a new autorole configuration.
        /// </summary>
        /// <param name="discordRole">The role to create the configuration for.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <AutoroleConfiguration> > CreateAutoroleAsync
        (
            IRole discordRole,
            CancellationToken ct = default
        )
        {
            if (await HasAutoroleAsync(discordRole, ct))
            {
                return(CreateEntityResult <AutoroleConfiguration> .FromError
                       (
                           "That role already has an autorole configuration."
                       ));
            }

            var getServer = await _servers.GetOrRegisterServerAsync(discordRole.Guild, ct);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <AutoroleConfiguration> .FromError(getServer));
            }

            var server = getServer.Entity;

            var autorole = _database.CreateProxy <AutoroleConfiguration>(server, discordRole);

            _database.Autoroles.Update(autorole);
            await _database.SaveChangesAsync(ct);

            return(autorole);
        }
示例#6
0
        /// <summary>
        /// Packs the given stream into a base64-encoded string, type-prefixed string.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="ct">The cancellation token for this operation.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public static async Task <CreateEntityResult <string> > PackImageAsync
        (
            Stream stream,
            CancellationToken ct = default
        )
        {
            await using var memoryStream = new MemoryStream();

            await stream.CopyToAsync(memoryStream, ct);

            var imageData = memoryStream.ToArray();

            string?mediaType = null;

            if (imageData.IsPNG())
            {
                mediaType = "png";
            }
            else if (imageData.IsJPG())
            {
                mediaType = "jpeg";
            }
            else if (imageData.IsGIF())
            {
                mediaType = "gif";
            }

            if (mediaType is null)
            {
                return(CreateEntityResult <string> .FromError("Unknown or unsupported image format."));
            }

            return($"data:image/{mediaType};base64,{Convert.ToBase64String(imageData)}");
        }
示例#7
0
        /// <summary>
        /// Creates a new dossier with the given title, summary, and data.
        /// </summary>
        /// <param name="title">The title of the dossier.</param>
        /// <param name="summary">The summary of the dossier.</param>
        /// <returns>A creation task which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <Dossier> > CreateDossierAsync
        (
            string title,
            string summary
        )
        {
            var dossier        = new Dossier(title, summary);
            var setTitleResult = await SetDossierTitleAsync(dossier, title);

            if (!setTitleResult.IsSuccess)
            {
                return(CreateEntityResult <Dossier> .FromError(setTitleResult));
            }

            var setSummary = await SetDossierSummaryAsync(dossier, summary);

            if (!setSummary.IsSuccess)
            {
                return(CreateEntityResult <Dossier> .FromError(setSummary));
            }

            await _database.Dossiers.AddAsync(dossier);

            await _database.SaveChangesAsync();

            return(CreateEntityResult <Dossier> .FromSuccess((await GetDossierByTitleAsync(title)).Entity));
        }
        /// <summary>
        /// Registers the given permission type, making it available to the system.
        /// </summary>
        /// <param name="permissionType">The permission type.</param>
        /// <param name="services">The application's services.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public CreateEntityResult <IPermission> RegisterPermission
        (
            Type permissionType,
            IServiceProvider services
        )
        {
            if (_registeredPermissions.ContainsKey(permissionType))
            {
                return(CreateEntityResult <IPermission> .FromError("The given permission has already been registered."));
            }

            IPermission permissionInstance;

            try
            {
                permissionInstance = (IPermission)ActivatorUtilities.CreateInstance(services, permissionType);
            }
            catch (Exception e)
            {
                return(CreateEntityResult <IPermission> .FromError(e));
            }

            if (_registeredPermissions.Values.Any(p => p.UniqueIdentifier == permissionInstance.UniqueIdentifier))
            {
                return(CreateEntityResult <IPermission> .FromError
                       (
                           "A permission with that identifier has already been registered."
                       ));
            }

            _registeredPermissions.Add(permissionType, permissionInstance);
            return(CreateEntityResult <IPermission> .FromSuccess(permissionInstance));
        }
示例#9
0
 /// <inheritdoc/>
 protected override async Task <CreateEntityResult <IUserMessage> > OnDisplayAsync(IMessageChannel channel)
 {
     return(CreateEntityResult <IUserMessage> .FromSuccess
            (
                await channel.SendMessageAsync(string.Empty, embed: _loadingEmbed)
            ));
 }
示例#10
0
        /// <summary>
        /// Creates a new autorole configuration.
        /// </summary>
        /// <param name="discordRole">The role to create the configuration for.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <AutoroleConfiguration> > CreateAutoroleAsync(IRole discordRole)
        {
            if (await HasAutoroleAsync(discordRole))
            {
                return(CreateEntityResult <AutoroleConfiguration> .FromError
                       (
                           "That role already has an autorole configuration."
                       ));
            }

            var getServer = await _servers.GetOrRegisterServerAsync(discordRole.Guild);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <AutoroleConfiguration> .FromError(getServer));
            }

            var server = getServer.Entity;

            var autorole = _database.CreateProxy <AutoroleConfiguration>(server, discordRole);

            if (autorole is null)
            {
                return(CreateEntityResult <AutoroleConfiguration> .FromError
                       (
                           "Failed to create a valid proxy for the autorole."
                       ));
            }

            _database.Autoroles.Update(autorole);
            await _database.SaveChangesAsync();

            return(autorole);
        }
示例#11
0
        public static async Task <CreateEntityResult <Appearance> > CreateDefaultAsync
        (
            [NotNull] Character character,
            [NotNull] TransformationService transformations
        )
        {
            var getSpeciesResult = await transformations.GetSpeciesByNameAsync("template");

            if (!getSpeciesResult.IsSuccess)
            {
                return(CreateEntityResult <Appearance> .FromError("Could not find the default species."));
            }

            var templateSpecies         = getSpeciesResult.Entity;
            var templateTransformations = new List <Transformation>();
            var templateParts           = new List <Bodypart> {
                Head, Body, Arms, Legs
            };

            // Explode the composite parts into their components
            templateParts = templateParts.SelectMany(p => p.GetComposingParts()).Distinct().ToList();

            foreach (var part in templateParts)
            {
                var getTFResult = await transformations.GetTransformationsByPartAndSpeciesAsync(part, templateSpecies);

                if (!getTFResult.IsSuccess)
                {
                    // Allow skipping of missing composing parts - a composite part might not have all of them in a TF.
                    if (part.IsComposingPart())
                    {
                        continue;
                    }

                    return(CreateEntityResult <Appearance> .FromError(getTFResult));
                }

                templateTransformations.AddRange(getTFResult.Entity);
            }

            var templateComponents = new List <AppearanceComponent>();

            foreach (var tf in templateTransformations)
            {
                if (tf.Part.IsChiral())
                {
                    templateComponents.AddRange(AppearanceComponent.CreateFromChiral(tf));
                }
                else
                {
                    templateComponents.Add(AppearanceComponent.CreateFrom(tf));
                }
            }

            var appearance = new Appearance(character);

            appearance.Components.AddRange(templateComponents);

            return(CreateEntityResult <Appearance> .FromSuccess(appearance));
        }
        /// <summary>
        /// Creates a new dossier with the given title, summary, and data.
        /// </summary>
        /// <param name="title">The title of the dossier.</param>
        /// <param name="summary">The summary of the dossier.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation task which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <Dossier> > CreateDossierAsync
        (
            string title,
            string summary,
            CancellationToken ct = default
        )
        {
            var dossier = _database.CreateProxy <Dossier>(title, summary);

            _database.Dossiers.Update(dossier);

            var setTitleResult = await SetDossierTitleAsync(dossier, title, ct);

            if (!setTitleResult.IsSuccess)
            {
                return(CreateEntityResult <Dossier> .FromError(setTitleResult));
            }

            var setSummary = await SetDossierSummaryAsync(dossier, summary, ct);

            if (!setSummary.IsSuccess)
            {
                return(CreateEntityResult <Dossier> .FromError(setSummary));
            }

            await _database.SaveChangesAsync(ct);

            return(dossier);
        }
示例#13
0
        /// <summary>
        /// Creates the settings for the given Discord guild.
        /// </summary>
        /// <param name="discordServer">The server.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <ServerModerationSettings> > CreateServerSettingsAsync
        (
            IGuild discordServer
        )
        {
            var existingEntity = await GetServerSettingsAsync(discordServer);

            if (existingEntity.IsSuccess)
            {
                return(CreateEntityResult <ServerModerationSettings> .FromError("That server already has settings."));
            }

            var getServer = await _servers.GetOrRegisterServerAsync(discordServer);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <ServerModerationSettings> .FromError(getServer));
            }

            var server   = getServer.Entity;
            var settings = new ServerModerationSettings(server);

            _database.ServerSettings.Update(settings);
            await _database.SaveChangesAsync();

            return(settings);
        }
示例#14
0
        public async Task <CreateEntityResult <CharacterRole> > CreateCharacterRoleAsync
        (
            [NotNull] IRole role,
            RoleAccess access
        )
        {
            var getExistingRoleResult = await GetCharacterRoleAsync(role);

            if (getExistingRoleResult.IsSuccess)
            {
                return(CreateEntityResult <CharacterRole> .FromError
                       (
                           "That role is already registered as a character role."
                       ));
            }

            var getServerResult = await _servers.GetOrRegisterServerAsync(role.Guild);

            if (!getServerResult.IsSuccess)
            {
                return(CreateEntityResult <CharacterRole> .FromError(getServerResult));
            }

            var server = getServerResult.Entity;

            var characterRole = new CharacterRole(server, (long)role.Id, access);

            _database.CharacterRoles.Update(characterRole);
            await _database.SaveChangesAsync();

            return(CreateEntityResult <CharacterRole> .FromSuccess(characterRole));
        }
示例#15
0
        /// <summary>
        /// Packs the given stream into a base64-encoded string, type-prefixed string.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="ct">The cancellation token for this operation.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public static async Task <CreateEntityResult <Optional <string?> > > PackImageAsync
        (
            Optional <Stream?> stream,
            CancellationToken ct = default
        )
        {
            Optional <string?> imageData = default;

            if (!stream.HasValue)
            {
                return(imageData);
            }

            if (stream.Value is null)
            {
                imageData = new Optional <string?>(null);
            }
            else
            {
                var packImage = await PackImageAsync(stream.Value, ct);

                if (!packImage.IsSuccess)
                {
                    return(CreateEntityResult <Optional <string?> > .FromError(packImage));
                }

                imageData = packImage.Entity;
            }

            return(imageData);
        }
示例#16
0
        /// <summary>
        /// Creates a note for the given user.
        /// </summary>
        /// <param name="authorUser">The author of the note.</param>
        /// <param name="guildUser">The user.</param>
        /// <param name="content">The content of the note.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserNote> > CreateNoteAsync
        (
            IUser authorUser,
            IGuildUser guildUser,
            string content
        )
        {
            var getServer = await _servers.GetOrRegisterServerAsync(guildUser.Guild);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(getServer));
            }

            var server = getServer.Entity;

            var getUser = await _users.GetOrRegisterUserAsync(guildUser);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(getUser));
            }

            var user = getUser.Entity;

            var getAuthor = await _users.GetOrRegisterUserAsync(authorUser);

            if (!getAuthor.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(getAuthor));
            }

            var author = getAuthor.Entity;

            var note = new UserNote(server, user, author, string.Empty);

            var setContent = await SetNoteContentsAsync(note, content);

            if (!setContent.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(setContent));
            }

            _database.UserNotes.Update(note);

            await _database.SaveChangesAsync();

            // Requery the database
            var getNote = await GetNoteAsync(guildUser.Guild, note.ID);

            if (!getNote.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(getNote));
            }

            return(CreateEntityResult <UserNote> .FromSuccess(getNote.Entity));
        }
示例#17
0
        /// <summary>
        /// Displays the message in the given channel.
        /// </summary>
        /// <param name="channel">The channel.</param>
        /// <returns>The displayed message.</returns>
        private async Task <CreateEntityResult <IUserMessage> > DisplayAsync(IMessageChannel channel)
        {
            if (this.IsDeleting)
            {
                return(CreateEntityResult <IUserMessage> .FromError("The message is being deleted."));
            }

            return(await OnDisplayAsync(channel));
        }
        /// <summary>
        /// Registers the given permission type, making it available to the system.
        /// </summary>
        /// <param name="services">The application's services.</param>
        /// <typeparam name="TPermission">The permission type.</typeparam>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public CreateEntityResult <TPermission> RegisterPermission <TPermission>(IServiceProvider services)
            where TPermission : class, IPermission
        {
            var permissionType           = typeof(TPermission);
            var registerPermissionResult = RegisterPermission(permissionType, services);

            if (!registerPermissionResult.IsSuccess)
            {
                return(CreateEntityResult <TPermission> .FromError(registerPermissionResult));
            }

            return(CreateEntityResult <TPermission> .FromSuccess((TPermission)registerPermissionResult.Entity));
        }
示例#19
0
        /// <summary>
        /// Adds the given user to the given roleplay.
        /// </summary>
        /// <param name="roleplay">The roleplay to add the user to.</param>
        /// <param name="newUser">The user to add to the roleplay.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>An execution result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <RoleplayParticipant> > AddUserToRoleplayAsync
        (
            Roleplay roleplay,
            User newUser,
            CancellationToken ct = default
        )
        {
            newUser = _database.NormalizeReference(newUser);

            if (roleplay.HasJoined(newUser))
            {
                return(CreateEntityResult <RoleplayParticipant> .FromError("The user is already in that roleplay."));
            }

            if (roleplay.IsKicked(newUser))
            {
                return(CreateEntityResult <RoleplayParticipant> .FromError
                       (
                           "The user has been kicked from that roleplay, and can't rejoin unless invited."
                       ));
            }

            // Check the invite list for nonpublic roleplays.
            if (!roleplay.IsPublic && !roleplay.IsInvited(newUser))
            {
                return(CreateEntityResult <RoleplayParticipant> .FromError
                       (
                           "The user hasn't been invited to that roleplay."
                       ));
            }

            var participantEntry = roleplay.ParticipatingUsers.FirstOrDefault(p => p.User == newUser);

            if (participantEntry is null)
            {
                participantEntry = _database.CreateProxy <RoleplayParticipant>(roleplay, newUser);
                _database.Update(participantEntry);

                participantEntry.Status = ParticipantStatus.Joined;
                roleplay.ParticipatingUsers.Add(participantEntry);
            }
            else
            {
                participantEntry.Status = ParticipantStatus.Joined;
            }

            await _database.SaveChangesAsync(ct);

            return(participantEntry);
        }
示例#20
0
        /// <inheritdoc />
        protected override async Task <CreateEntityResult <IUserMessage> > OnDisplayAsync(IMessageChannel channel)
        {
            if (!(this.Message is null))
            {
                return(CreateEntityResult <IUserMessage> .FromError("The wizard is already active in a channel."));
            }

            _categories = (await _kinks.GetKinkCategoriesAsync()).ToList();
            _state      = KinkWizardState.CategorySelection;

            var message = await channel.SendMessageAsync(string.Empty, embed : _loadingEmbed);

            return(CreateEntityResult <IUserMessage> .FromSuccess(message));
        }
示例#21
0
        /// <summary>
        /// Creates a note for the given user.
        /// </summary>
        /// <param name="authorUser">The author of the note.</param>
        /// <param name="guildUser">The user.</param>
        /// <param name="content">The content of the note.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserNote> > CreateNoteAsync
        (
            IUser authorUser,
            IGuildUser guildUser,
            string content,
            CancellationToken ct = default
        )
        {
            var getServer = await _servers.GetOrRegisterServerAsync(guildUser.Guild, ct);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(getServer));
            }

            var server = getServer.Entity;

            var getUser = await _users.GetOrRegisterUserAsync(guildUser, ct);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(getUser));
            }

            var user = getUser.Entity;

            var getAuthor = await _users.GetOrRegisterUserAsync(authorUser, ct);

            if (!getAuthor.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(getAuthor));
            }

            var author = getAuthor.Entity;

            var note = _database.CreateProxy <UserNote>(server, user, author, string.Empty);

            _database.UserNotes.Update(note);

            var setContent = await SetNoteContentsAsync(note, content, ct);

            if (!setContent.IsSuccess)
            {
                return(CreateEntityResult <UserNote> .FromError(setContent));
            }

            await _database.SaveChangesAsync(ct);

            return(note);
        }
示例#22
0
        /// <summary>
        /// Creates a roleplay with the given parameters.
        /// </summary>
        /// <param name="owner">The user that owns the roleplay.</param>
        /// <param name="server">The server that the roleplay is associated with.</param>
        /// <param name="roleplayName">The name of the roleplay.</param>
        /// <param name="roleplaySummary">The summary of the roleplay.</param>
        /// <param name="isNSFW">Whether or not the roleplay is NSFW.</param>
        /// <param name="isPublic">Whether or not the roleplay is public.</param>
        /// <returns>A creation result which may or may not have been successful.</returns>
        public async Task <CreateEntityResult <Roleplay> > CreateRoleplayAsync
        (
            User owner,
            Server server,
            string roleplayName,
            string roleplaySummary,
            bool isNSFW,
            bool isPublic
        )
        {
            owner  = _database.NormalizeReference(owner);
            server = _database.NormalizeReference(server);

            // Use a dummy name, since we'll be setting it using the service.
            var roleplay = _database.CreateProxy <Roleplay>(server, owner, string.Empty, string.Empty);

            _database.Attach(roleplay);

            var ownerParticipant = _database.CreateProxy <RoleplayParticipant>(roleplay, owner);

            ownerParticipant.Status = ParticipantStatus.Joined;

            roleplay.ParticipatingUsers.Add(ownerParticipant);

            var setNameResult = await SetRoleplayNameAsync(roleplay, roleplayName);

            if (!setNameResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(setNameResult));
            }

            var setSummaryResult = await SetRoleplaySummaryAsync(roleplay, roleplaySummary);

            if (!setSummaryResult.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(setSummaryResult));
            }

            roleplay.IsNSFW   = isNSFW;
            roleplay.IsPublic = isPublic;

            _database.Roleplays.Update(roleplay);

            await _database.SaveChangesAsync();

            return(roleplay);
        }
        /// <inheritdoc />
        public async Task <CreateEntityResult <Image> > AddImageToCharacterAsync
        (
            Character character,
            string imageName,
            string imageUrl,
            string?imageCaption  = null,
            bool isNSFW          = false,
            CancellationToken ct = default
        )
        {
            var isImageNameUnique = !character.Images.Any(i => string.Equals(i.Name.ToLower(), imageName.ToLower()));

            if (!isImageNameUnique)
            {
                return(CreateEntityResult <Image> .FromError("The character already has an image with that name."));
            }

            if (imageName.IsNullOrWhitespace())
            {
                return(CreateEntityResult <Image> .FromError("You need to specify a name."));
            }

            if (imageCaption.IsNullOrWhitespace())
            {
                imageCaption = "No caption set.";
            }

            if (!Uri.IsWellFormedUriString(imageUrl, UriKind.RelativeOrAbsolute))
            {
                return(CreateEntityResult <Image> .FromError
                       (
                           $"That URL doesn't look valid. Please check \"{imageUrl}\" for errors."
                       ));
            }

            var image = _database.CreateProxy <Image>(imageName, imageUrl, imageCaption);

            _database.Images.Update(image);

            image.IsNSFW = isNSFW;
            character.Images.Add(image);

            await _database.SaveChangesAsync(ct);

            return(image);
        }
        /// <summary>
        /// Creates a new roleplay with the given owner and parameters.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="name">The name of the roleplay.</param>
        /// <param name="summary">A short summary.</param>
        /// <param name="isNSFW">Whether the roleplay is NSFW.</param>
        /// <param name="isPublic">Whether the roleplay is public.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <Roleplay> > CreateRoleplayAsync
        (
            IGuildUser owner,
            string name,
            string summary,
            bool isNSFW,
            bool isPublic
        )
        {
            var getUser = await _users.GetOrRegisterUserAsync(owner);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(getUser));
            }

            var user = getUser.Entity;

            var getServer = await _servers.GetOrRegisterServerAsync(owner.Guild);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(getServer));
            }

            var server = getServer.Entity;

            var createRoleplay = await _roleplays.CreateRoleplayAsync(user, server, name, summary, isNSFW, isPublic);

            if (!createRoleplay.IsSuccess)
            {
                return(createRoleplay);
            }

            var roleplay = createRoleplay.Entity;

            var createChannel = await _dedicatedChannels.CreateDedicatedChannelAsync(owner.Guild, roleplay);

            if (!createChannel.IsSuccess)
            {
                return(CreateEntityResult <Roleplay> .FromError(createChannel));
            }

            return(roleplay);
        }
示例#25
0
        public async Task <CreateEntityResult <string> > GenerateCharacterDescriptionAsync(Character character)
        {
            var getCurrentAppearance = await GetOrCreateCurrentAppearanceAsync
                                       (
                character
                                       );

            if (!getCurrentAppearance.IsSuccess)
            {
                return(CreateEntityResult <string> .FromError(getCurrentAppearance));
            }

            var currentAppearance = getCurrentAppearance.Entity;

            var visualDescription = _descriptionBuilder.BuildVisualDescription(currentAppearance);

            return(CreateEntityResult <string> .FromSuccess(visualDescription));
        }
示例#26
0
        /// <summary>
        /// Gets or creates a set of per-server statistics for a given user.
        /// </summary>
        /// <param name="discordUser">The user.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserServerStatistics> > GetOrCreateUserServerStatisticsAsync
        (
            IGuildUser discordUser
        )
        {
            var getStatistics = await GetOrCreateUserStatisticsAsync(discordUser);

            if (!getStatistics.IsSuccess)
            {
                return(CreateEntityResult <UserServerStatistics> .FromError(getStatistics));
            }

            var statistics = getStatistics.Entity;
            var existingServerStatistics = statistics.ServerStatistics.FirstOrDefault
                                           (
                s => s.Server.DiscordID == (long)discordUser.Guild.Id
                                           );

            if (!(existingServerStatistics is null))
            {
                return(existingServerStatistics);
            }

            var getServer = await _servers.GetOrRegisterServerAsync(discordUser.Guild);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <UserServerStatistics> .FromError(getServer));
            }

            var server = getServer.Entity;

            // Since we're adding to the database indirectly, an attach is required here.
            _database.Attach(server);

            var newServerStatistics = _database.CreateProxy <UserServerStatistics>(server);

            statistics.ServerStatistics.Add(newServerStatistics);
            await _database.SaveChangesAsync();

            return(newServerStatistics);
        }
        /// <summary>
        /// Gets or creates a set of per-server statistics for a given user.
        /// </summary>
        /// <param name="discordUser">The user.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <UserServerStatistics> > GetOrCreateUserServerStatisticsAsync
        (
            IGuildUser discordUser,
            CancellationToken ct = default
        )
        {
            var getStatistics = await GetOrCreateUserStatisticsAsync(discordUser, ct);

            if (!getStatistics.IsSuccess)
            {
                return(CreateEntityResult <UserServerStatistics> .FromError(getStatistics));
            }

            var statistics = getStatistics.Entity;
            var existingServerStatistics = statistics.ServerStatistics.FirstOrDefault
                                           (
                s => s.Server.DiscordID == (long)discordUser.Guild.Id
                                           );

            if (!(existingServerStatistics is null))
            {
                return(existingServerStatistics);
            }

            var getServer = await _servers.GetOrRegisterServerAsync(discordUser.Guild, ct);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <UserServerStatistics> .FromError(getServer));
            }

            var server = getServer.Entity;

            var newServerStatistics = _database.CreateProxy <UserServerStatistics>(server);

            _database.Update(newServerStatistics);
            statistics.ServerStatistics.Add(newServerStatistics);

            await _database.SaveChangesAsync(ct);

            return(newServerStatistics);
        }
        /// <summary>
        /// Creates a character with the given parameters.
        /// </summary>
        /// <param name="guildUser">The owner of the character..</param>
        /// <param name="name">The name of the character.</param>
        /// <param name="avatarUrl">The character's avatar url.</param>
        /// <param name="nickname">The nickname that should be applied to the user when the character is active.</param>
        /// <param name="summary">The summary of the character.</param>
        /// <param name="description">The full description of the character.</param>
        /// <param name="pronounFamily">The pronoun family of the character.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A creation result which may or may not have been successful.</returns>
        public async Task <CreateEntityResult <Character> > CreateCharacterAsync
        (
            IGuildUser guildUser,
            string name,
            string?avatarUrl     = null,
            string?nickname      = null,
            string?summary       = null,
            string?description   = null,
            string?pronounFamily = null,
            CancellationToken ct = default
        )
        {
            var getUser = await _users.GetOrRegisterUserAsync(guildUser, ct);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <Character> .FromError(getUser));
            }

            var getServer = await _servers.GetOrRegisterServerAsync(guildUser.Guild, ct);

            if (!getServer.IsSuccess)
            {
                return(CreateEntityResult <Character> .FromError(getServer));
            }

            var user   = getUser.Entity;
            var server = getServer.Entity;

            return(await _characters.CreateCharacterAsync
                   (
                       user,
                       server,
                       name,
                       avatarUrl,
                       nickname,
                       summary,
                       description,
                       pronounFamily,
                       ct
                   ));
        }
        /// <inheritdoc/>
        protected override async Task <CreateEntityResult <IUserMessage> > OnDisplayAsync(IMessageChannel channel)
        {
            if (!this.Pages.Any())
            {
                return(CreateEntityResult <IUserMessage> .FromError("The pager is empty."));
            }

            var embed = BuildEmbed(_currentPage - 1);

            var message = await channel.SendMessageAsync(string.Empty, embed : embed);

            if (this.Pages.Count > 1)
            {
                await message.AddReactionAsync(this.Appearance.First);

                await message.AddReactionAsync(this.Appearance.Back);

                await message.AddReactionAsync(this.Appearance.Next);

                await message.AddReactionAsync(this.Appearance.Last);

                var manageMessages = await CanManageMessages();

                var canJump =
                    this.Appearance.JumpDisplayCondition == JumpDisplayCondition.Always ||
                    (this.Appearance.JumpDisplayCondition == JumpDisplayCondition.WithManageMessages && manageMessages);

                if (canJump)
                {
                    await message.AddReactionAsync(this.Appearance.Jump);
                }

                if (this.Appearance.DisplayInformationIcon)
                {
                    await message.AddReactionAsync(this.Appearance.Help);
                }
            }

            await message.AddReactionAsync(this.Appearance.Stop);

            return(CreateEntityResult <IUserMessage> .FromSuccess(message));
        }
        /// <summary>
        /// Adds the given user to the given roleplay.
        /// </summary>
        /// <param name="roleplay">The roleplay.</param>
        /// <param name="discordUser">The discord user.</param>
        /// <returns>A creation result which may or may not have succeeded.</returns>
        public async Task <CreateEntityResult <RoleplayParticipant> > AddUserToRoleplayAsync
        (
            Roleplay roleplay,
            IGuildUser discordUser
        )
        {
            var getUser = await _users.GetOrRegisterUserAsync(discordUser);

            if (!getUser.IsSuccess)
            {
                return(CreateEntityResult <RoleplayParticipant> .FromError(getUser));
            }

            var user = getUser.Entity;

            var addUserAsync = await _roleplays.AddUserToRoleplayAsync(roleplay, user);

            if (!addUserAsync.IsSuccess)
            {
                return(addUserAsync);
            }

            if (!roleplay.DedicatedChannelID.HasValue)
            {
                return(addUserAsync);
            }

            var updatePermissions = await _dedicatedChannels.UpdateParticipantPermissionsAsync
                                    (
                discordUser.Guild,
                roleplay
                                    );

            if (!updatePermissions.IsSuccess)
            {
                return(CreateEntityResult <RoleplayParticipant> .FromError(updatePermissions));
            }

            return(addUserAsync);
        }