Skip to content

Commit e8f91a6

Browse files
authored
Merge pull request #217 from kyb3r/perms
v2.18.0 - new permission system
2 parents 2125dd2 + 48571b7 commit e8f91a6

File tree

9 files changed

+680
-218
lines changed

9 files changed

+680
-218
lines changed

CHANGELOG.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,52 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
8+
# v2.18.0
9+
10+
### New Permissions System
11+
12+
- A brand new permission system! Replacing the old guild-based permissions (ie. manage channels, manage messages), the new system enables you to customize your desired permission level specific to a command or a group of commands for a role or user.
13+
- There are five permission groups/levels:
14+
- Owner [5]
15+
- Administrator [4]
16+
- Moderator [3]
17+
- Supporter [2]
18+
- Regular [1]
19+
20+
You may add a role or user to a permission group through any of the following methods:
21+
- `?permissions add level owner @role`
22+
- `?permissions add level supporter member-name`
23+
- `?permissions add level moderator everyone`
24+
- `?permissions add level moderator @member#1234`
25+
- `?permissions add level administrator 78912384930291853`
26+
27+
The same applies to individual commands permissions:
28+
- `?permissions add command-name @member#1234`
29+
- ... and the other methods listed above.
30+
31+
To revoke permission, use `remove` instead of `add`.
32+
33+
To view all roles and users with permission for a permission group or command do:
34+
- `?permissions get command command-name`
35+
- `?permissions get level owner`
36+
37+
By default, all newly set up Modmail will have `OWNER` set to the owner of the bot, and `EGULAR` set to @everyone.
38+
39+
### Breaking
40+
41+
When updating to this version, all prior permission settings with guild-based permissions will be invalidated. You will need to convert to the above system.
42+
`OWNERS` will also get removed, you will need to set owners through `?permissions add level owner 212931293123129` or any way listed above.
43+
44+
### New Command
45+
46+
- A `?delete` command, which is an alternative to manually deleting a message. This command is created to no longer require manage messages permission to recall thread messages.
47+
48+
### Changed
49+
50+
- The help message no longer conceals inaccessible commands due to check failures.
51+
52+
753
# v2.17.2
854

955
### Changed

bot.py

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
SOFTWARE.
2323
"""
2424

25-
__version__ = '2.17.2'
25+
__version__ = '2.18.0'
2626

2727
import asyncio
2828
import logging
@@ -49,11 +49,10 @@
4949
from core.clients import SelfHostedClient, PluginDatabaseClient
5050
from core.config import ConfigManager
5151
from core.utils import info, error
52-
from core.models import Bot
52+
from core.models import Bot, PermissionLevel
5353
from core.thread import ThreadManager
5454
from core.time import human_timedelta
5555

56-
5756
init()
5857

5958
logger = logging.getLogger('Modmail')
@@ -189,11 +188,6 @@ def _load_extensions(self):
189188
except Exception:
190189
logger.exception(error(f'Failed to load {cog}'))
191190

192-
async def is_owner(self, user):
193-
allowed = {int(x) for x in
194-
str(self.config.get('owners', '0')).split(',')}
195-
return user.id in allowed
196-
197191
def run(self, *args, **kwargs):
198192
try:
199193
self.loop.run_until_complete(self.start(self.token))
@@ -478,7 +472,8 @@ async def process_modmail(self, message):
478472
except isodate.ISO8601Error:
479473
logger.warning('The account age limit needs to be a '
480474
'ISO-8601 duration formatted duration string '
481-
f'greater than 0 days, not "%s".', str(account_age))
475+
f'greater than 0 days, not "%s".',
476+
str(account_age))
482477
del self.config.cache['account_age']
483478
await self.config.update()
484479
account_age = isodate.duration.Duration()
@@ -533,7 +528,7 @@ async def process_modmail(self, message):
533528
await self.config.update()
534529
else:
535530
reaction = sent_emoji
536-
531+
537532
if reaction != 'disable':
538533
try:
539534
await message.add_reaction(reaction)
@@ -586,6 +581,27 @@ async def get_context(self, message, *, cls=commands.Context):
586581

587582
return ctx
588583

584+
async def update_perms(self, name, value, add=True):
585+
if isinstance(name, PermissionLevel):
586+
permissions = self.config.level_permissions
587+
name = name.name
588+
else:
589+
permissions = self.config.command_permissions
590+
if name not in permissions:
591+
if add:
592+
permissions[name] = [value]
593+
else:
594+
if add:
595+
if value not in permissions[name]:
596+
permissions[name].append(value)
597+
else:
598+
if value in permissions[name]:
599+
permissions[name].remove(value)
600+
logger.info(
601+
info(f'Updating permissions for {name}, {value} (add={add}).')
602+
)
603+
await self.config.update()
604+
589605
async def on_message(self, message):
590606
if message.type == discord.MessageType.pins_add and \
591607
message.author == self.user:
@@ -622,7 +638,7 @@ async def on_message(self, message):
622638

623639
async def on_typing(self, channel, user, _):
624640
if user.bot:
625-
return
641+
return
626642
if isinstance(channel, discord.DMChannel):
627643
if not self.config.get('user_typing'):
628644
return
@@ -635,7 +651,7 @@ async def on_typing(self, channel, user, _):
635651
thread = await self.threads.find(channel=channel)
636652
if thread and thread.recipient:
637653
await thread.recipient.trigger_typing()
638-
654+
639655
async def on_raw_reaction_add(self, payload):
640656

641657
user = self.get_user(payload.user_id)
@@ -655,12 +671,14 @@ async def on_raw_reaction_add(self, payload):
655671
message = await channel.get_message(payload.message_id)
656672
reaction = payload.emoji
657673

658-
close_emoji = await self.convert_emoji(self.config.get('close_emoji', '🔒'))
674+
close_emoji = await self.convert_emoji(
675+
self.config.get('close_emoji', '🔒')
676+
)
659677

660678
if isinstance(channel, discord.DMChannel) and str(reaction) == str(close_emoji): # closing thread
661679
thread = await self.threads.find(recipient=user)
662680
ts = message.embeds[0].timestamp if message.embeds else None
663-
if thread and ts == thread.channel.created_at:
681+
if thread and ts == thread.channel.created_at:
664682
# the reacted message is the corresponding thread creation embed
665683
if not self.config.get('disable_recipient_thread_close'):
666684
await thread.close(closer=user)
@@ -706,24 +724,24 @@ async def on_guild_channel_delete(self, channel):
706724
return
707725

708726
await thread.close(closer=mod, silent=True, delete_channel=False)
709-
727+
710728
async def on_member_remove(self, member):
711729
thread = await self.threads.find(recipient=member)
712730
if thread:
713-
em = discord.Embed(
731+
embed = discord.Embed(
714732
description='The recipient has left the server.',
715733
color=discord.Color.red()
716-
)
717-
await thread.channel.send(embed=em)
718-
734+
)
735+
await thread.channel.send(embed=embed)
736+
719737
async def on_member_join(self, member):
720738
thread = await self.threads.find(recipient=member)
721739
if thread:
722-
em = discord.Embed(
740+
embed = discord.Embed(
723741
description='The recipient has joined the server.',
724742
color=self.mod_color
725-
)
726-
await thread.channel.send(embed=em)
743+
)
744+
await thread.channel.send(embed=embed)
727745

728746
async def on_message_delete(self, message):
729747
"""Support for deleting linked messages"""
@@ -786,7 +804,7 @@ def overwrites(ctx):
786804
}
787805

788806
for role in ctx.guild.roles:
789-
if role.permissions.manage_guild:
807+
if role.permissions.administrator:
790808
overwrites[role] = discord.PermissionOverwrite(
791809
read_messages=True
792810
)
@@ -833,8 +851,9 @@ async def autoupdate_loop(self):
833851
embed.set_author(name=user['username'] + ' - Updating Bot',
834852
icon_url=user['avatar_url'],
835853
url=user['url'])
836-
embed.set_footer(text=f"Updating Modmail v{self.version} "
837-
f"-> v{latest.version}")
854+
855+
embed.set_footer(text=f'Updating Modmail v{self.version} '
856+
f'-> v{latest.version}')
838857

839858
embed.description = latest.description
840859
for name, value in latest.fields.items():
@@ -888,6 +907,7 @@ async def metadata_loop(self):
888907
if __name__ == '__main__':
889908
if os.name != 'nt':
890909
import uvloop
910+
891911
uvloop.install()
892912
bot = ModmailBot()
893913
bot.run()

0 commit comments

Comments
 (0)