Octobot has various moderation commands such as /ban, /mute, /kick.
These commands add multiple features to Discord's built-in functions
(such as durations and logging). Some admins may want to force their
users to use Octobot's commands instead of Discord UI functions.
However, due to the current design, they can't take away the permissions
as that remove access to the respective command.
This PR adds the `ModeratorRole` option which allows anyone who has
`ManageMessages` permission and the role to perform any moderator
action.
If the role is not set, the Discord permissions are checked instead. If
the user doesn't have the role, but has the permission, they can still
run the command.
---------
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
This feature will improve the debugging experience for developers by
providing the information about *where exactly* a result has failed
---------
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
Originally, these classes were services because I thought that all
DI-resolvable classes need to be services. However, this is not true, so
we can make these classes (notably Utility and GuildDataService) not
extend anything. `UtilityService` was renamed to `Utility` for
simplicity
---------
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
ReSharper inspections have been updated, causing new warnings to appear
in the codebase. This time, the "Use collection expressions" inspection
has been enabled for usecases where the collection is not empty. This PR
fixes the check failures caused by this inspection.
This PR adds an extension method to make it easier to pass Result<Embed> to CreateMessageAsync
---------
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com>
This PR fixes an issue that caused REST errors to occur in
MemberUpdateService if the bot tries to interact with a member it can't
interact with. The issue is fixed by returning from TickMemberDataAsync
early if the member cannot be interacted with. An error message was
planned, but it requires adding a lot of services and severely
increasing the complexity. Contributors may feel free to add one if they
deem so necessary.
This PR splits the extension methods contained in `Extensions.cs` into
separate classes in the `Octobot.Extensions` namespace. This was done
for multiple reasons:
1) The `Extensions.cs` violates SRP (Single Responsibility Principle) -
it takes upon itself every extension method for many types
2) Having a separate class for each extended type is a standard practice
- take a look at
[Remora.Discord](https://github.com/Remora/Remora.Discord/tree/main/Backend/Remora.Discord.Rest/Extensions)
or [osu!](https://github.com/ppy/osu/tree/master/osu.Game/Extensions)
3) Having all extension methods in one file makes it hard to find the
method you want
This PR makes it so that roles in MemberData are updated only in
MemberUpdateService. This reduces possible points of failures,
maintenance burden and reliance on gateway events
We're moving!
---------
Signed-off-by: Macintosh II <mctaylxrs@outlook.com>
Signed-off-by: Macintosh II <95250141+mctaylors@users.noreply.github.com>
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com>
Flipping `>` to `<=` changed null handling semantics within the
operator, causing the unban/unmute code to always run
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
If a user was muted using the `MuteRole` method and then banned, the
UnknownMember warning will flood your logs when `DateTimeOffset.UtcNow >
data.MutedUntil` becomes true, because there is no user in the server to
unmute.
---------
Signed-off-by: Macintosh II <95250141+mctaylors@users.noreply.github.com>
- Added support for `MuteRole`, now if you add any role to this setting,
then try to mute a member, all his roles will be removed except for the
one you set in this setting.
- Fixed `/unmute`, that tried to set target's display name to unmute
reason.
---------
Signed-off-by: Macintosh II <mctaylxrs@outlook.com>
This PR closes #105
This PR fixes exceptions caused by changing a collection's contents
while it is being enumerated. This can often happen with Guild- and
MemberDatas. By using `ToArray()` on these global collections and using
it in the `foreach` loop, we create a new copy of the collection,
preventing any modification to it.
While this does introduce a lot of memory allocations, there is no
fixing that. Usually, the fix to these exceptions would be to convert
the `foreach` to a reverse-`for`. However, because indices cannot be
used on these collections, that is not possible.
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
GuildUpdateService is a service that contains way too many
responsibilities with everything strictly coupled to each other. The
code is buggy, hard to refactor and swallows errors. This prompted me to
make this PR, which splits it into three independant services:
- SongUpdateService (responsible for changing songs presence);
- MemberUpdateService (responsible for updating member datas: unbanning
users, adding the default role, sending reminders, filtering nicknames);
- ScheduledEventUpdateService (responsible for updating scheduled
events: sending notifications, automatically starting events).
All of these services and their methods use Results to push errors all
the way up in the stack, making sure no error is missed. To make logging
and debugging easier, an extension method for `ILogger` was created -
`LogResult`. The method checks if the result was successful or if its
failure was caused by a user or environment error before logging
anything - providing cleaner code and logs. `ExceptionError`s will also
have their exception stacktrace and type logged (except in Remora code).
This PR also fixes an issue that prevented banned users from being
unbanned when their punishment was over.
---------
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>