예제 #1
0
    public async Task <Result <FeedbackMessage> > HideRoleplayAsync
    (
        [AutocompleteProvider("roleplay::any")]
        Roleplay roleplay
    )
    {
        var getDedicatedChannelResult = DedicatedChannelService.GetDedicatedChannel
                                        (
            roleplay
                                        );

        if (!getDedicatedChannelResult.IsSuccess)
        {
            return(Result <FeedbackMessage> .FromError(getDedicatedChannelResult));
        }

        var dedicatedChannel = getDedicatedChannelResult.Entity;
        var setVisibility    = await _dedicatedChannels.SetChannelVisibilityForUserAsync
                               (
            dedicatedChannel,
            _context.User.ID,
            false
                               );

        return(!setVisibility.IsSuccess
            ? Result <FeedbackMessage> .FromError(setVisibility)
            : new FeedbackMessage("Roleplay hidden.", _feedback.Theme.Secondary));
    }
 /// <summary>
 /// Initializes a new instance of the <see cref="SetCommands"/> class.
 /// </summary>
 /// <param name="discordRoleplays">The roleplay service.</param>
 /// <param name="dedicatedChannels">The dedicated channel service.</param>
 public SetCommands
 (
     RoleplayDiscordService discordRoleplays,
     DedicatedChannelService dedicatedChannels
 )
 {
     _discordRoleplays  = discordRoleplays;
     _dedicatedChannels = dedicatedChannels;
 }
예제 #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SetCommands"/> class.
 /// </summary>
 /// <param name="discordRoleplays">The roleplay service.</param>
 /// <param name="feedback">The user feedback service.</param>
 /// <param name="dedicatedChannels">The dedicated channel service.</param>
 public SetCommands
 (
     RoleplayDiscordService discordRoleplays,
     UserFeedbackService feedback,
     DedicatedChannelService dedicatedChannels
 )
 {
     _discordRoleplays  = discordRoleplays;
     _feedback          = feedback;
     _dedicatedChannels = dedicatedChannels;
 }
        private async Task <OperationResult> ArchiveRoleplayAsync
        (
            SocketGuild guild,
            ServerService serverService,
            RoleplayDiscordService roleplayService,
            DedicatedChannelService dedicatedChannels,
            RoleplayServerSettingsService serverSettings,
            Roleplay roleplay
        )
        {
            if (roleplay.DedicatedChannelID is null)
            {
                return(OperationResult.FromError("The roleplay doesn't have a dedicated channel."));
            }

            if (roleplay.IsPublic)
            {
                var postResult = await PostArchivedRoleplayAsync(guild, serverService, serverSettings, roleplay);

                if (!postResult.IsSuccess)
                {
                    return(OperationResult.FromError(postResult));
                }
            }

            var dedicatedChannel = guild.GetTextChannel((ulong)roleplay.DedicatedChannelID);

            if (dedicatedChannel is null)
            {
                // Something's gone wrong in the database. Who the f**k knows why. We'll do an extra delete to be
                // on the safe side.
                await dedicatedChannels.DeleteChannelAsync(guild, roleplay);

                return(OperationResult.FromSuccess());
            }

            // Ensure the messages are all caught up
            foreach (var message in await dedicatedChannel.GetMessagesAsync().FlattenAsync())
            {
                if (!(message is IUserMessage userMessage))
                {
                    continue;
                }

                // We don't care about the results here.
                await roleplayService.ConsumeMessageAsync(userMessage);
            }

            await dedicatedChannels.DeleteChannelAsync(guild, roleplay);

            return(OperationResult.FromSuccess());
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="RoleplayCommands"/> class.
 /// </summary>
 /// <param name="discordRoleplays">The roleplay service.</param>
 /// <param name="feedback">The user feedback service.</param>
 /// <param name="interactivity">The interactivity service.</param>
 /// <param name="dedicatedChannels">The dedicated channel service.</param>
 public RoleplayCommands
 (
     RoleplayDiscordService discordRoleplays,
     UserFeedbackService feedback,
     InteractivityService interactivity,
     DedicatedChannelService dedicatedChannels
 )
 {
     _discordRoleplays  = discordRoleplays;
     _feedback          = feedback;
     _interactivity     = interactivity;
     _dedicatedChannels = dedicatedChannels;
 }
예제 #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RoleplayCommands"/> class.
 /// </summary>
 /// <param name="discordRoleplays">The roleplay service.</param>
 /// <param name="feedback">The user feedback service.</param>
 /// <param name="dedicatedChannels">The dedicated channel service.</param>
 /// <param name="context">The command context.</param>
 /// <param name="channelAPI">The channel API.</param>
 /// <param name="services">The available services.</param>
 public RoleplayCommands
 (
     RoleplayDiscordService discordRoleplays,
     FeedbackService feedback,
     DedicatedChannelService dedicatedChannels,
     ICommandContext context,
     IDiscordRestChannelAPI channelAPI,
     IServiceProvider services
 )
 {
     _discordRoleplays  = discordRoleplays;
     _feedback          = feedback;
     _dedicatedChannels = dedicatedChannels;
     _context           = context;
     _channelAPI        = channelAPI;
     _services          = services;
 }
예제 #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RoleplayDiscordService"/> class.
 /// </summary>
 /// <param name="roleplays">The roleplay service.</param>
 /// <param name="dedicatedChannels">The dedicated channel service.</param>
 /// <param name="users">The user service.</param>
 /// <param name="servers">The server service.</param>
 /// <param name="guildAPI">The guild API.</param>
 /// <param name="channelAPI">The channel API.</param>
 public RoleplayDiscordService
 (
     RoleplayService roleplays,
     DedicatedChannelService dedicatedChannels,
     UserService users,
     ServerService servers,
     IDiscordRestGuildAPI guildAPI,
     IDiscordRestChannelAPI channelAPI
 )
 {
     _roleplays         = roleplays;
     _dedicatedChannels = dedicatedChannels;
     _users             = users;
     _servers           = servers;
     _guildAPI          = guildAPI;
     _channelAPI        = channelAPI;
 }
예제 #8
0
    public async Task <Result <FeedbackMessage> > ViewRoleplayAsync
    (
        [AutocompleteProvider("roleplay::any")] Roleplay roleplay
    )
    {
        var getDedicatedChannelResult = DedicatedChannelService.GetDedicatedChannel(roleplay);

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

        if (!roleplay.IsPublic && roleplay.ParticipatingUsers.All(p => p.User.DiscordID != _context.User.ID))
        {
            return(new UserError
                   (
                       "You don't have permission to view that roleplay."
                   ));
        }

        var dedicatedChannel = getDedicatedChannelResult.Entity;
        var setVisibility    = await _dedicatedChannels.SetChannelVisibilityForUserAsync
                               (
            dedicatedChannel,
            _context.User.ID,
            true
                               );

        if (!setVisibility.IsSuccess)
        {
            return(Result <FeedbackMessage> .FromError(setVisibility));
        }

        return(new FeedbackMessage
               (
                   $"The roleplay \"{roleplay.Name}\" is now visible in <#{dedicatedChannel}>.",
                   _feedback.Theme.Secondary
               ));
    }
    private static async Task <Result> ArchiveRoleplayAsync
    (
        IServiceProvider services,
        FeedbackService feedback,
        RoleplayDiscordService roleplayService,
        DedicatedChannelService dedicatedChannels,
        RoleplayServerSettingsService serverSettings,
        Roleplay roleplay
    )
    {
        if (roleplay.DedicatedChannelID is null)
        {
            return(new UserError("The roleplay doesn't have a dedicated channel."));
        }

        var ensureLogged = await roleplayService.EnsureAllMessagesAreLoggedAsync(roleplay);

        if (!ensureLogged.IsSuccess)
        {
            return(Result.FromError(ensureLogged));
        }

        if (!roleplay.IsPublic)
        {
            return(await dedicatedChannels.DeleteChannelAsync(roleplay));
        }

        var postResult = await PostArchivedRoleplayAsync(services, feedback, serverSettings, roleplay);

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

        return(await dedicatedChannels.DeleteChannelAsync(roleplay));
    }
예제 #10
0
    public async Task <Result> MoveRoleplayIntoChannelAsync(string newName, params IUser[] participants)
    {
        var createRoleplayAsync = await _discordRoleplays.CreateRoleplayAsync
                                  (
            _context.GuildID.Value,
            _context.User.ID,
            newName,
            "No summary set.",
            false,
            true
                                  );

        if (!createRoleplayAsync.IsSuccess)
        {
            return(Result.FromError(createRoleplayAsync));
        }

        var roleplay = createRoleplayAsync.Entity;

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

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

            if (addParticipantAsync.IsSuccess)
            {
                continue;
            }

            var message =
                $"I couldn't add <@{participant.ID}> to the roleplay ({addParticipantAsync.Error.Message}. " +
                "Please try to invite them manually.";

            var sendWarning = await _feedback.SendContextualWarningAsync
                              (
                message,
                _context.User.ID
                              );

            if (!sendWarning.IsSuccess)
            {
                return(Result.FromError(sendWarning));
            }
        }

        // Copy the last messages from the participants
        var before = _context switch
        {
            MessageContext messageContext => messageContext.MessageID,
            InteractionContext interactionContext => interactionContext.ID,
            _ => throw new ArgumentOutOfRangeException(nameof(_context))
        };

        var getMessageBatch = await _channelAPI.GetChannelMessagesAsync(_context.ChannelID, before : before);

        if (!getMessageBatch.IsSuccess)
        {
            return(Result.FromError(getMessageBatch));
        }

        var messageBatch = getMessageBatch.Entity;

        var participantMessages = participants
                                  .Select(participant => messageBatch.FirstOrDefault(m => m.Author.ID == participant.ID))
                                  .Where(message => message is not null)
                                  .Select(m => m !)
                                  .ToList();

        var getDedicatedChannel = DedicatedChannelService.GetDedicatedChannel(roleplay);

        if (!getDedicatedChannel.IsSuccess)
        {
            return(Result.FromError(getDedicatedChannel));
        }

        var dedicatedChannel = getDedicatedChannel.Entity;

        foreach (var participantMessage in participantMessages.OrderByDescending(m => m.Timestamp))
        {
            var messageLink = "https://discord.com/channels/" +
                              $"{_context.GuildID.Value}/{_context.ChannelID}/{participantMessage.ID}";

            var send = await _channelAPI.CreateMessageAsync(dedicatedChannel, messageLink);

            if (!send.IsSuccess)
            {
                return(Result.FromError(send));
            }
        }

        var start = await StartRoleplayAsync(roleplay);

        return(start.IsSuccess
            ? Result.FromSuccess()
            : Result.FromError(start));
    }
}
예제 #11
0
    public async Task <Result <FeedbackMessage> > ShowOrCreateDedicatedRoleplayChannel
    (
        [RequireEntityOwner]
        [AutocompleteProvider("roleplay::owned")]
        Roleplay roleplay
    )
    {
        var getDedicatedChannelResult = DedicatedChannelService.GetDedicatedChannel(roleplay);

        if (getDedicatedChannelResult.IsSuccess)
        {
            var existingDedicatedChannel = getDedicatedChannelResult.Entity;
            var message = $"\"{roleplay.Name}\" has a dedicated channel at " +
                          $"<#{existingDedicatedChannel}>";

            return(new FeedbackMessage(message, _feedback.Theme.Secondary));
        }

        var workingMessage = new Embed
        {
            Colour      = _feedback.Theme.Secondary,
            Description = "Setting up dedicated channel..."
        };

        var send = await _feedback.SendContextualEmbedAsync(workingMessage);

        if (!send.IsSuccess)
        {
            return(Result <FeedbackMessage> .FromError(send));
        }

        // The roleplay either doesn't have a channel, or the one it has has been deleted or is otherwise invalid.
        var result = await _dedicatedChannels.CreateDedicatedChannelAsync(roleplay);

        if (!result.IsSuccess)
        {
            return(Result <FeedbackMessage> .FromError(result));
        }

        var dedicatedChannel = result.Entity;

        if (!roleplay.IsActive || roleplay.ActiveChannelID == dedicatedChannel.ID)
        {
            return(new FeedbackMessage
                   (
                       $"All done! Your roleplay now has a dedicated channel at <#{dedicatedChannel}>.",
                       _feedback.Theme.Secondary
                   ));
        }

        var stopResult = await StopRoleplayAsync(roleplay);

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

        var startResult = await StartRoleplayAsync(roleplay);

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

        return(new FeedbackMessage
               (
                   $"All done! Your roleplay now has a dedicated channel at <#{dedicatedChannel}>.",
                   _feedback.Theme.Secondary
               ));
    }
예제 #12
0
    /// <summary>
    /// Starts the given roleplay in the current channel, or the dedicated channel if one exists.
    /// </summary>
    /// <param name="currentChannelID">The current channel.</param>
    /// <param name="roleplay">The roleplay.</param>
    /// <returns>A modification result which may or may not have succeeded.</returns>
    public async Task <Result> StartRoleplayAsync(Snowflake currentChannelID, Roleplay roleplay)
    {
        var getDedicatedChannelResult = DedicatedChannelService.GetDedicatedChannel(roleplay);

        // Identify the channel to start the RP in. Preference is given to the roleplay's dedicated channel.
        var channelID  = getDedicatedChannelResult.IsSuccess ? getDedicatedChannelResult.Entity : currentChannelID;
        var getChannel = await _channelAPI.GetChannelAsync(channelID);

        if (!getChannel.IsSuccess)
        {
            return(Result.FromError(getChannel));
        }

        var channel = getChannel.Entity;

        if (roleplay.IsNSFW && !(channel.IsNsfw.HasValue && channel.IsNsfw.Value))
        {
            return(new UserError
                   (
                       "This channel is not marked as NSFW, while your roleplay is... naughty!"
                   ));
        }

        var getHasActiveRoleplay = await HasActiveRoleplayAsync(channelID);

        if (!getHasActiveRoleplay.IsSuccess)
        {
            return(Result.FromError(getHasActiveRoleplay));
        }

        if (getHasActiveRoleplay.Entity)
        {
            var currentRoleplayResult = await GetActiveRoleplayAsync(channelID);

            if (!currentRoleplayResult.IsSuccess)
            {
                return(Result.FromError(currentRoleplayResult));
            }

            var currentRoleplay   = currentRoleplayResult.Entity;
            var timeOfLastMessage = currentRoleplay.Messages.Last().Timestamp;
            var currentTime       = DateTimeOffset.UtcNow;

            if (timeOfLastMessage < currentTime.AddHours(-4))
            {
                currentRoleplay.IsActive = false;
            }
            else
            {
                return(new UserError("There's already a roleplay active in this channel."));
            }
        }

        var start = await _roleplays.StartRoleplayAsync(roleplay, channelID);

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

        // If the channel in question is the roleplay's dedicated channel, enable it
        if (!roleplay.DedicatedChannelID.HasValue)
        {
            return(Result.FromSuccess());
        }

        var enableChannel = await _dedicatedChannels.UpdateParticipantPermissionsAsync(roleplay);

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

        var joinedUsers = roleplay.JoinedUsers.Select
                          (
            u => $"<@{u.User.DiscordID}>"
                          );

        var participantList = joinedUsers.Humanize();

        var send = await _channelAPI.CreateMessageAsync
                   (
            roleplay.ActiveChannelID !.Value,
            $"Calling {participantList}!"
                   );

        return(!send.IsSuccess
            ? Result.FromError(send)
            : Result.FromSuccess());
    }