Beispiel #1
0
                public async Task <RuntimeResult> AddConditionAsync
                (
                    AutoroleConfiguration autorole,
                    [OverrideTypeReader(typeof(UncachedMessageTypeReader <IMessage>))]
                    IMessage message,
                    IEmote emote
                )
                {
                    var condition = _autoroles.CreateConditionProxy <ReactionCondition>
                                    (
                        message,
                        emote
                                    );

                    if (condition is null)
                    {
                        return(RuntimeCommandResult.FromError("Failed to create a condition object. Yikes!"));
                    }

                    var addCondition = await _autoroles.AddConditionAsync(autorole, condition);

                    if (!addCondition.IsSuccess)
                    {
                        return(addCondition.ToRuntimeResult());
                    }

                    return(RuntimeCommandResult.FromSuccess("Condition added."));
                }
        public async Task <RuntimeResult> CreateRoleplayAsync
        (
            string roleplayName,
            string roleplaySummary = "No summary set.",
            bool isNSFW            = false,
            bool isPublic          = true
        )
        {
            if (!(this.Context.User is IGuildUser guildUser))
            {
                return(RuntimeCommandResult.FromError("The current user isn't a guild user."));
            }

            var result = await _discordRoleplays.CreateRoleplayAsync
                         (
                guildUser,
                roleplayName,
                roleplaySummary,
                isNSFW,
                isPublic
                         );

            if (!result.IsSuccess)
            {
                return(result.ToRuntimeResult());
            }

            return(RuntimeCommandResult.FromSuccess($"Roleplay \"{result.Entity.Name}\" created."));
        }
        public async Task <RuntimeResult> ShowKinksByPreferenceAsync
        (
            IUser otherUser,
            [OverrideTypeReader(typeof(HumanizerEnumTypeReader <KinkPreference>))]
            KinkPreference preference
        )
        {
            var getUserKinksResult = await _kinks.GetUserKinksAsync(otherUser);

            if (!getUserKinksResult.IsSuccess)
            {
                return(getUserKinksResult.ToRuntimeResult());
            }

            var userKinks = getUserKinksResult.Entity;

            var withPreference = userKinks.Where(k => k.Preference == preference).ToList();

            if (!withPreference.Any())
            {
                return(RuntimeCommandResult.FromError("The user doesn't have any kinks with that preference."));
            }

            var paginatedKinkPages = _kinks.BuildPaginatedUserKinkEmbeds(withPreference);
            var paginatedMessage   = new PaginatedEmbed(_feedback, _interactivity, this.Context.User)
                                     .WithPages(paginatedKinkPages);

            await _interactivity.SendPrivateInteractiveMessageAsync(this.Context, _feedback, paginatedMessage);

            return(RuntimeCommandResult.FromSuccess());
        }
        public async Task <RuntimeResult> IncludePreviousMessagesAsync
        (
            [RequireEntityOwnerOrPermission(typeof(EditRoleplay), PermissionTarget.Other)]
            Roleplay roleplay,
            [OverrideTypeReader(typeof(UncachedMessageTypeReader <IMessage>))]
            IMessage startMessage,
            [OverrideTypeReader(typeof(UncachedMessageTypeReader <IMessage>))]
            IMessage?finalMessage = null
        )
        {
            finalMessage ??= this.Context.Message;

            if (startMessage.Channel != finalMessage.Channel)
            {
                return(RuntimeCommandResult.FromError("The messages are not in the same channel."));
            }

            var addedOrUpdatedMessageCount = 0;

            var latestMessage = startMessage;

            while (latestMessage.Timestamp < finalMessage.Timestamp)
            {
                var messages = (await this.Context.Channel.GetMessagesAsync
                                (
                                    latestMessage, Direction.After
                                ).FlattenAsync()).OrderBy(m => m.Timestamp).ToList();

                latestMessage = messages.Last();

                foreach (var message in messages)
                {
                    // Jump out if we've passed the final message
                    if (message.Timestamp > finalMessage.Timestamp)
                    {
                        break;
                    }

                    if (!(message is IUserMessage userMessage))
                    {
                        continue;
                    }

                    var modifyResult = await _discordRoleplays.ConsumeMessageAsync(userMessage);

                    if (modifyResult.IsSuccess)
                    {
                        ++addedOrUpdatedMessageCount;
                    }
                }
            }

            return(RuntimeCommandResult.FromSuccess
                   (
                       $"{addedOrUpdatedMessageCount} messages added to \"{roleplay.Name}\"."
                   ));
        }
        public async Task <RuntimeResult> ShowAvailablePronounFamiliesAsync()
        {
            EmbedFieldBuilder CreatePronounField(IPronounProvider pronounProvider)
            {
                var ef = new EmbedFieldBuilder();

                ef.WithName(pronounProvider.Family);

                var value = $"{pronounProvider.GetSubjectForm()} ate {pronounProvider.GetPossessiveAdjectiveForm()} " +
                            $"pie that {pronounProvider.GetSubjectForm()} brought with " +
                            $"{pronounProvider.GetReflexiveForm()}.";

                value = value.Transform(To.SentenceCase);

                ef.WithValue($"*{value}*");

                return(ef);
            }

            var pronounProviders = _pronouns.GetAvailablePronounProviders().ToList();

            if (!pronounProviders.Any())
            {
                return(RuntimeCommandResult.FromError("There doesn't seem to be any pronouns available."));
            }

            var fields      = pronounProviders.Select(CreatePronounField);
            var description = "Each field below represents a pronoun that can be used with a character. The title of " +
                              "each field is the pronoun family that you use when selecting the pronoun, and below it" +
                              "is a short example of how it might be used.";

            var paginatedEmbedPages = PageFactory.FromFields
                                      (
                fields,
                description: description
                                      );

            var paginatedEmbed = new PaginatedEmbed(_feedback, _interactivity, this.Context.User).WithPages
                                 (
                paginatedEmbedPages.Select
                (
                    p => p.WithColor(Color.DarkPurple).WithTitle("Available pronouns")
                )
                                 );

            await _interactivity.SendInteractiveMessageAndDeleteAsync
            (
                this.Context.Channel,
                paginatedEmbed,
                TimeSpan.FromMinutes(5.0)
            );

            return(RuntimeCommandResult.FromSuccess());
        }
        public async Task <RuntimeResult> UpdateKinkDatabaseAsync()
        {
            await _feedback.SendConfirmationAsync(this.Context, "Updating kinks...");

            var updatedKinkCount = 0;

            // Get the latest JSON from F-list
            string json;

            using (var web = new HttpClient())
            {
                web.Timeout = TimeSpan.FromSeconds(3);

                var cts = new CancellationTokenSource();
                cts.CancelAfter(web.Timeout);

                try
                {
                    using var response = await web.GetAsync
                                         (
                              new Uri ("https://www.f-list.net/json/api/kink-list.php"),
                              cts.Token
                                         );

                    json = await response.Content.ReadAsStringAsync();
                }
                catch (OperationCanceledException)
                {
                    return(RuntimeCommandResult.FromError("Could not connect to F-list: Operation timed out."));
                }
            }

            var kinkCollection = JsonConvert.DeserializeObject <KinkCollection>(json);

            if (kinkCollection.KinkCategories is null)
            {
                return(RuntimeCommandResult.FromError($"Received an error from F-List: {kinkCollection.Error}"));
            }

            foreach (var kinkSection in kinkCollection.KinkCategories)
            {
                if (!Enum.TryParse <KinkCategory>(kinkSection.Key, out var kinkCategory))
                {
                    return(RuntimeCommandResult.FromError("Failed to parse kink category."));
                }

                updatedKinkCount += await _kinks.UpdateKinksAsync(kinkSection.Value.Kinks.Select
                                                                  (
                                                                      k => new Kink(k.Name, k.Description, k.KinkId, kinkCategory)
                                                                  ));
            }

            return(RuntimeCommandResult.FromSuccess($"Done. {updatedKinkCount} kinks updated."));
        }
        public async Task <RuntimeResult> ContactUserAsync(IUser discordUser)
        {
            if (this.Context.User is IGuildUser guildUser && !guildUser.GuildPermissions.MentionEveryone)
            {
                return(RuntimeCommandResult.FromError("You need to be able to mention everyone to do that."));
            }

            if (discordUser.Id == this.Context.Client.CurrentUser.Id)
            {
                return(RuntimeCommandResult.FromError
                       (
                           "That's a splendid idea - at least then, I'd get an intelligent reply."
                       ));
            }

            if (discordUser.IsBot)
            {
                return(RuntimeCommandResult.FromError("I could do that, but I doubt I'd get a reply."));
            }

            var contactMessage = $"Hello there, {discordUser.Mention}. I've been instructed to initiate... " +
                                 $"negotiations... with you. \nA good place to start would be the \"!help <topic>\" " +
                                 $"command.";

            var eb = _feedback.CreateFeedbackEmbed
                     (
                discordUser,
                Color.DarkPurple,
                contactMessage
                     );

            var userDMChannel = await discordUser.GetOrCreateDMChannelAsync();

            try
            {
                await userDMChannel.SendMessageAsync(string.Empty, false, eb);
            }
            catch (HttpException hex) when(hex.WasCausedByDMsNotAccepted())
            {
                return(RuntimeCommandResult.FromError(hex.Message));
            }
            finally
            {
                await userDMChannel.CloseAsync();
            }

            return(RuntimeCommandResult.FromSuccess("User contacted."));
        }
        public async Task <RuntimeResult> ListOwnedRoleplaysAsync(IGuildUser?discordUser = null)
        {
            if (discordUser is null)
            {
                var authorUser = this.Context.User;
                if (!(authorUser is IGuildUser guildUser))
                {
                    return(RuntimeCommandResult.FromError("The owner isn't a guild user."));
                }

                discordUser = guildUser;
            }

            var getUserRoleplays = await _discordRoleplays.GetUserRoleplaysAsync(discordUser);

            if (!getUserRoleplays.IsSuccess)
            {
                return(getUserRoleplays.ToRuntimeResult());
            }

            var roleplays = getUserRoleplays.Entity.ToList();

            var appearance = PaginatedAppearanceOptions.Default;

            appearance.Title  = "Your roleplays";
            appearance.Author = discordUser;

            var paginatedEmbed = PaginatedEmbedFactory.SimpleFieldsFromCollection
                                 (
                _feedback,
                _interactivity,
                this.Context.User,
                roleplays,
                r => r.Name,
                r => r.Summary,
                "You don't have any roleplays.",
                appearance
                                 );

            await _interactivity.SendInteractiveMessageAndDeleteAsync
            (
                this.Context.Channel,
                paginatedEmbed,
                TimeSpan.FromMinutes(5.0)
            );

            return(RuntimeCommandResult.FromSuccess());
        }
            public async Task <RuntimeResult> SetCharacterRoleAsync
            (
                [RequireEntityOwnerOrPermission(typeof(EditCharacter), PermissionTarget.Other)]
                Character character,
                IRole discordRole
            )
            {
                var getRoleResult = await _characterRoles.GetCharacterRoleAsync(discordRole);

                if (!getRoleResult.IsSuccess)
                {
                    return(getRoleResult.ToRuntimeResult());
                }

                var commandInvoker = (IGuildUser)this.Context.User;

                var role = getRoleResult.Entity;

                if (role.Access == RoleAccess.Restricted)
                {
                    if (!commandInvoker.GuildPermissions.ManageRoles)
                    {
                        return(RuntimeCommandResult.FromError
                               (
                                   "That role is restricted, and you must be able to manage roles to use it."
                               ));
                    }
                }

                var owner = await this.Context.Guild.GetUserAsync((ulong)character.Owner.DiscordID);

                if (owner is null)
                {
                    return(RuntimeCommandResult.FromError("Failed to get the owner as a guild user."));
                }

                var setRoleResult = await _characterRoles.SetCharacterRoleAsync(owner, character, role);

                if (!setRoleResult.IsSuccess)
                {
                    return(setRoleResult.ToRuntimeResult());
                }

                return(RuntimeCommandResult.FromSuccess("Character role set."));
            }
                public async Task <RuntimeResult> AddConditionAsync(AutoroleConfiguration autorole, ITextChannel channel, long count)
                {
                    var condition = _autoroles.CreateConditionProxy <MessageCountInChannelCondition>(channel, count);

                    if (condition is null)
                    {
                        return(RuntimeCommandResult.FromError("Failed to create a condition object. Yikes!"));
                    }

                    var addCondition = await _autoroles.AddConditionAsync(autorole, condition);

                    if (!addCondition.IsSuccess)
                    {
                        return(addCondition.ToRuntimeResult());
                    }

                    return(RuntimeCommandResult.FromSuccess("Condition added."));
                }
        public async Task <RuntimeResult> RefreshRoleplayAsync(Roleplay roleplay)
        {
            var isOwner       = roleplay.IsOwner(this.Context.User);
            var isParticipant = roleplay.HasJoined(this.Context.User);

            if (!(isOwner || isParticipant))
            {
                return(RuntimeCommandResult.FromError("You don't own that roleplay, nor are you a participant."));
            }

            var refreshResult = await _discordRoleplays.RefreshRoleplayAsync(roleplay);

            if (!refreshResult.IsSuccess)
            {
                return(refreshResult.ToRuntimeResult());
            }

            return(RuntimeCommandResult.FromSuccess("Timeout refreshed."));
        }
            public async Task <RuntimeResult> SetCharacterDescriptionAsync
            (
                [RequireEntityOwnerOrPermission(typeof(EditCharacter), PermissionTarget.Other)]
                Character character,
                string?newCharacterDescription = null
            )
            {
                if (newCharacterDescription is null)
                {
                    if (!this.Context.Message.Attachments.Any())
                    {
                        return(RuntimeCommandResult.FromError
                               (
                                   "You need to attach a plaintext document or provide an in-message description."
                               ));
                    }

                    var newDescription            = this.Context.Message.Attachments.First();
                    var getAttachmentStreamResult = await _discord.GetAttachmentStreamAsync(newDescription);

                    if (!getAttachmentStreamResult.IsSuccess)
                    {
                        return(getAttachmentStreamResult.ToRuntimeResult());
                    }

                    using var sr            = new StreamReader(getAttachmentStreamResult.Entity);
                    newCharacterDescription = await sr.ReadToEndAsync();
                }

                var setDescriptionResult = await _characters.SetCharacterDescriptionAsync
                                           (
                    character,
                    newCharacterDescription
                                           );

                if (!setDescriptionResult.IsSuccess)
                {
                    return(setDescriptionResult.ToRuntimeResult());
                }

                return(RuntimeCommandResult.FromSuccess("Character description set."));
            }
Beispiel #13
0
                public async Task <RuntimeResult> SetAffirmationNotificationChannel(IChannel channel)
                {
                    if (!(channel is ITextChannel textChannel))
                    {
                        return(RuntimeCommandResult.FromError("That's not a text channel."));
                    }

                    var setResult = await _autoroles.SetAffirmationNotificationChannelAsync
                                    (
                        this.Context.Guild,
                        textChannel
                                    );

                    if (!setResult.IsSuccess)
                    {
                        return(setResult.ToRuntimeResult());
                    }

                    return(RuntimeCommandResult.FromSuccess("Channel set."));
                }
            public async Task <RuntimeResult> SetCharacterAvatarAsync
            (
                [RequireEntityOwnerOrPermission(typeof(EditCharacter), PermissionTarget.Other)]
                Character character,
                string?newCharacterAvatarUrl = null
            )
            {
                if (newCharacterAvatarUrl is null)
                {
                    if (!this.Context.Message.Attachments.Any())
                    {
                        return(RuntimeCommandResult.FromError("You need to attach an image or provide a url."));
                    }

                    var newAvatar = this.Context.Message.Attachments.First();
                    newCharacterAvatarUrl = newAvatar.Url;
                }

                var galleryImage = character.Images.FirstOrDefault
                                   (
                    i => i.Name.ToLower().Equals(newCharacterAvatarUrl.ToLower())
                                   );

                if (!(galleryImage is null))
                {
                    newCharacterAvatarUrl = galleryImage.Url;
                }

                var result = await _characters.SetCharacterAvatarAsync
                             (
                    character,
                    newCharacterAvatarUrl ?? throw new ArgumentNullException(nameof(newCharacterAvatarUrl))
                             );

                if (!result.IsSuccess)
                {
                    return(result.ToRuntimeResult());
                }

                return(RuntimeCommandResult.FromSuccess("Character avatar set."));
            }
        public async Task <RuntimeResult> LeaveRoleplayAsync(Roleplay roleplay)
        {
            if (!(this.Context.User is IGuildUser guildUser))
            {
                return(RuntimeCommandResult.FromError("The current user isn't a guild user."));
            }

            var removeUserResult = await _discordRoleplays.RemoveUserFromRoleplayAsync(roleplay, guildUser);

            if (!removeUserResult.IsSuccess)
            {
                return(removeUserResult.ToRuntimeResult());
            }

            var roleplayOwnerUser = await this.Context.Guild.GetUserAsync((ulong)roleplay.Owner.DiscordID);

            return(RuntimeCommandResult.FromSuccess
                   (
                       $"Left {roleplayOwnerUser.Mention}'s roleplay \"{roleplay.Name}\""
                   ));
        }
                public async Task <RuntimeResult> AddConditionAsync(AutoroleConfiguration autorole, TimeSpan time)
                {
                    var condition = _autoroles.CreateConditionProxy <TimeSinceLastActivityCondition>
                                    (
                        time
                                    );

                    if (condition is null)
                    {
                        return(RuntimeCommandResult.FromError("Failed to create a condition object. Yikes!"));
                    }

                    var addCondition = await _autoroles.AddConditionAsync(autorole, condition);

                    if (!addCondition.IsSuccess)
                    {
                        return(addCondition.ToRuntimeResult());
                    }

                    return(RuntimeCommandResult.FromSuccess("Condition added."));
                }
        public async Task <RuntimeResult> ShowRoleplayAsync()
        {
            if (!(this.Context.Channel is ITextChannel textChannel))
            {
                return(RuntimeCommandResult.FromError("This channel isn't a text channel."));
            }

            var getCurrentRoleplayResult = await _discordRoleplays.GetActiveRoleplayAsync(textChannel);

            if (!getCurrentRoleplayResult.IsSuccess)
            {
                return(getCurrentRoleplayResult.ToRuntimeResult());
            }

            var roleplay = getCurrentRoleplayResult.Entity;
            var eb       = await CreateRoleplayInfoEmbedAsync(roleplay);

            await _feedback.SendEmbedAsync(this.Context.Channel, eb);

            return(RuntimeCommandResult.FromSuccess());
        }
        public async Task <RuntimeResult> DroneAsync(IGuildUser user)
        {
            if (!(this.Context.User is IGuildUser target))
            {
                return(RuntimeCommandResult.FromError("The target user wasn't a guild user."));
            }

            var droneMessage = user == target
                ? _content.GetRandomSelfDroneMessage()
                : _content.GetRandomTurnTheTablesMessage();

            await _feedback.SendConfirmationAsync(this.Context, droneMessage);

            var droneResult = await _drone.DroneUserAsync(target);

            if (!droneResult.IsSuccess)
            {
                return(droneResult.ToRuntimeResult());
            }

            return(RuntimeCommandResult.FromSuccess(_content.GetRandomConfirmationMessage()));
        }
        public async Task <RuntimeResult> HideRoleplayAsync(Roleplay roleplay)
        {
            var getDedicatedChannelResult = await _dedicatedChannels.GetDedicatedChannelAsync
                                            (
                this.Context.Guild,
                roleplay
                                            );

            if (!getDedicatedChannelResult.IsSuccess)
            {
                return(RuntimeCommandResult.FromError
                       (
                           "The given roleplay doesn't have a dedicated channel."
                       ));
            }

            var user             = this.Context.User;
            var dedicatedChannel = getDedicatedChannelResult.Entity;
            await _dedicatedChannels.SetChannelVisibilityForUserAsync(dedicatedChannel, user, false);

            return(RuntimeCommandResult.FromSuccess("Roleplay hidden."));
        }
        public async Task <RuntimeResult> ExportRoleplayAsync
        (
            [RequireEntityOwnerOrPermission(typeof(ExportRoleplay), PermissionTarget.Other)]
            Roleplay roleplay,
            [OverrideTypeReader(typeof(HumanizerEnumTypeReader <ExportFormat>))]
            ExportFormat format = ExportFormat.PDF
        )
        {
            IRoleplayExporter exporter;

            switch (format)
            {
            case ExportFormat.PDF:
            {
                exporter = new PDFRoleplayExporter(this.Context.Guild);
                break;
            }

            case ExportFormat.Plaintext:
            {
                exporter = new PlaintextRoleplayExporter(this.Context.Guild);
                break;
            }

            default:
            {
                return(RuntimeCommandResult.FromError("That export format hasn't been implemented yet."));
            }
            }

            await _feedback.SendConfirmationAsync(this.Context, "Compiling the roleplay...");

            using var output = await exporter.ExportAsync(roleplay);

            await this.Context.Channel.SendFileAsync(output.Data, $"{output.Title}.{output.Format.GetFileExtension()}");

            return(RuntimeCommandResult.FromSuccess());
        }
        public async Task <RuntimeResult> ViewRoleplayAsync(Roleplay roleplay)
        {
            var getDedicatedChannelResult = await _dedicatedChannels.GetDedicatedChannelAsync
                                            (
                this.Context.Guild,
                roleplay
                                            );

            if (!getDedicatedChannelResult.IsSuccess)
            {
                return(RuntimeCommandResult.FromError
                       (
                           "The given roleplay doesn't have a dedicated channel. Try using \"!rp export\" instead."
                       ));
            }

            var user = this.Context.User;

            if (!roleplay.IsPublic && roleplay.ParticipatingUsers.All(p => p.User.DiscordID != (long)user.Id))
            {
                return(RuntimeCommandResult.FromError
                       (
                           "You don't have permission to view that roleplay."
                       ));
            }

            var dedicatedChannel = getDedicatedChannelResult.Entity;
            await _dedicatedChannels.SetChannelVisibilityForUserAsync(dedicatedChannel, user, true);

            var channelMention = MentionUtils.MentionChannel(dedicatedChannel.Id);

            return(RuntimeCommandResult.FromSuccess
                   (
                       $"The roleplay \"{roleplay.Name}\" is now visible in {channelMention}."
                   ));
        }
        public async Task <RuntimeResult> MoveRoleplayIntoChannelAsync(string newName, params IGuildUser[] participants)
        {
            if (!(this.Context.User is IGuildUser guildUser))
            {
                return(RuntimeCommandResult.FromError("The current user isn't a guild user."));
            }

            var createRoleplayAsync = await _discordRoleplays.CreateRoleplayAsync
                                      (
                guildUser,
                newName,
                "No summary set.",
                false,
                true
                                      );

            if (!createRoleplayAsync.IsSuccess)
            {
                return(createRoleplayAsync.ToRuntimeResult());
            }

            var roleplay = createRoleplayAsync.Entity;

            foreach (var participant in participants)
            {
                if (participant == this.Context.User)
                {
                    // Already added
                    continue;
                }

                var addParticipantAsync = await _discordRoleplays.AddUserToRoleplayAsync(roleplay, participant);

                if (addParticipantAsync.IsSuccess)
                {
                    continue;
                }

                var message =
                    $"I couldn't add {participant.Mention} to the roleplay ({addParticipantAsync.ErrorReason}. " +
                    $"Please try to invite them manually.";

                await _feedback.SendWarningAsync
                (
                    this.Context,
                    message
                );
            }

            var participantMessages = new List <IMessage>();

            // Copy the last messages from the participants
            foreach (var participant in participants)
            {
                // Find the last message in the current channel from the user
                var channel      = this.Context.Channel;
                var messageBatch = await channel.GetMessagesAsync(this.Context.Message, Direction.Before)
                                   .FlattenAsync();

                foreach (var message in messageBatch)
                {
                    if (message.Author != participant)
                    {
                        continue;
                    }

                    participantMessages.Add(message);
                    break;
                }
            }

            var getDedicatedChannel = await _dedicatedChannels.GetDedicatedChannelAsync(this.Context.Guild, roleplay);

            if (!getDedicatedChannel.IsSuccess)
            {
                return(getDedicatedChannel.ToRuntimeResult());
            }

            var dedicatedChannel = getDedicatedChannel.Entity;

            foreach (var participantMessage in participantMessages.OrderByDescending(m => m.Timestamp))
            {
                var messageLink = participantMessage.GetJumpUrl();
                await dedicatedChannel.SendMessageAsync(messageLink);
            }

            var startRoleplayAsync = await _discordRoleplays.StartRoleplayAsync
                                     (
                (ITextChannel)this.Context.Channel,
                roleplay
                                     );

            if (!startRoleplayAsync.IsSuccess)
            {
                return(startRoleplayAsync.ToRuntimeResult());
            }

            var joinedUsers    = roleplay.JoinedUsers.Select(async p => await this.Context.Client.GetUserAsync((ulong)p.User.DiscordID));
            var joinedMentions = joinedUsers.Select(async u => (await u).Mention);

            var participantList = (await Task.WhenAll(joinedMentions)).Humanize();
            await dedicatedChannel.SendMessageAsync($"Calling {participantList}!");

            return(RuntimeCommandResult.FromSuccess
                   (
                       $"All done! Your roleplay is now available in {MentionUtils.MentionChannel(dedicatedChannel.Id)}."
                   ));
        }