В настоящее время я создаю событие роли реакции. Там вы можете установить роль реакции с помощью команды. Формат: >reactionss @role messageID emote
. Затем бот добавит реакцию на данное сообщение.
(Вы реагируете данной эмоцией на сообщение и получаете роль. Если вы не отреагируете, она будет удалена.)
Поэтому я сохранил все в файле JSON. Формат можно увидеть в коде. Он отлично работает. После перезапуска бота все вроде не сохраняется/ничего не происходит, когда я нажимаю на реакцию. Однако все, кажется, все еще хранится в файле JSON, но он не используется.
Мой код до сих пор:
class ReactionRoles(commands.Cog):
"""
This instance handles all reaction role events.
"""
def __init__(self, bot):
super().__init__()
self.bot = bot
self.reaction_roles = []
@commands.command(name = "Reaction", aliases=["reactionss"])
async def set_reaction(self, ctx, role: discord.Role = None, msg: discord.Message = None, emoji=None):
with open('reaction_roles.json', 'r', encoding='utf-8') as f:
reaction_roles = json.load(f)
try:
reaction_roles[f"{role.id}, {msg.id}"] = emoji
except KeyError:
new = {ctx.message.id: role.id}
reaction_roles.update(new)
if role is not None and msg is not None and emoji is not None:
await msg.add_reaction(emoji)
self.reaction_roles.append((role.id, msg.id, str(emoji.encode("utf-8"))))
with open('reaction_roles.json', 'w', encoding='utf-8') as f:
json.dump(reaction_roles, f, indent=2)
await ctx.channel.send("**Reaction has been set.**")
@commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
for role_id, msg_id, emoji in self.reaction_roles:
if msg_id == payload.message_id and emoji == str(payload.emoji.name.encode("utf-8")):
await payload.member.add_roles(self.bot.get_guild(payload.guild_id).get_role(role_id))
@commands.Cog.listener()
async def on_raw_reaction_remove(self, payload):
for role_id, msg_id, emoji in self.reaction_roles:
if msg_id == payload.message_id and emoji == str(payload.emoji.name.encode("utf-8")):
guild = self.bot.get_guild(payload.guild_id)
await guild.get_member(payload.user_id).remove_roles(guild.get_role(role_id))```
Причина, по которой он не работает после сброса, заключается в том, что каждый раз, когда он сбрасывается, он переопределяет список reaction_roles
и устанавливает его пустым.
def __init__(self, bot):
super().__init__()
self.bot = bot
self.reaction_roles = [] # Whenever code reloads, this is set here, and is empty
Ваши on_raw_reaction_add
и on_raw_reaction_remove
используют этот список для определения реакций и ролей, а не файл JSON.
Вы можете сделать что-то подобное, используя dicts и только файл JSON. JSON не поддерживает целые числа в качестве ключей, поэтому при работе с msg.id используйте str(msg.id)
# Not really necessary, but we need to read the file multiple times
# If you ever relocate it, you will only need to edit it once
def json_open(): #you can rename it, just remember to change the rest as well
with open('reaction_roles.json', 'r', encoding='utf-8') as f:
reaction_roles = json.load(f)
return reaction_roles
class Reactions(commands.Cog):
"""
This instance handles all reaction role events.
"""
def __init__(self, bot):
super().__init__()
self.bot = bot
@commands.command(name = "Reaction", aliases=["reactionss"])
async def set_reaction(self, ctx, role: discord.Role = None, msg: discord.Message = None, emoji=None):
reaction_roles = json_open() # Open the json file
# First time registering emoji to msg will give error since msg is not in dict
try:
role_dict = reaction_roles[str(msg.id)]
except:
role_dict = {}
role_dict[emoji] = role.id
reaction_roles[str(msg.id)]=role_dict
if role is not None and msg is not None and emoji is not None:
await msg.add_reaction(emoji)
with open('reaction_roles.json', 'w', encoding='utf-8') as f:
json.dump(reaction_roles, f, indent=2, ensure_ascii=False)
# setting ensure_ascii=False --> We can have actual emojis in json
await ctx.channel.send("**Reaction has been set.**")
# Next two steps are same, except one is remove and one is add
@commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
if payload.user_id == 775390992777216040: # Bot wont accidentally get any roles
return
reaction_roles = json_open() # Open JSON
if str(payload.message_id) in list(reaction_roles.keys()): # If msg matches
role_dict = reaction_roles[str(payload.message_id)] # If reaction matches
if payload.emoji.name in list(role_dict.keys()):
role_id = role_dict[payload.emoji.name]
guild = self.client.get_guild(payload.guild_id)
role = guild.get_role(role_id)
await guild.get_member(payload.user_id).add_roles(role)
@commands.Cog.listener()
async def on_raw_reaction_remove(self, payload):
if payload.user_id == 775390992777216040:
return
reaction_roles = json_open()
if str(payload.message_id) in list(reaction_roles.keys()):
role_dict = reaction_roles[str(payload.message_id)]
if payload.emoji.name in list(role_dict.keys()):
role_id = role_dict[payload.emoji.name]
guild = self.client.get_guild(payload.guild_id)
role = guild.get_role(role_id)
await guild.get_member(payload.user_id).remove_roles(role)
Файл JSON в конечном итоге будет выглядеть так
{
"msg1_id": {
"😈": role1_id,
"😅": role2_id
},
"msg2_id": {
"🌀": role3_id
}
}
@Доминик, тебе не нужно ничего с этим делать. Причина, по которой я поместил его туда, заключается в том, что когда нам нужно открыть файл reaction_roles.json
(мы открываем его три раза только в этом фрагменте кода), мы можем сделать reaction_roles = json_open()
. Поскольку json_open()
— это функция, каждый раз, когда она вызывается, она открывает файл json и возвращает reaction_roles
, с которым мы можем работать. Я определяю его перед классом, в самом верху кода. Теперь, если вы измените имя файла или местоположение, вам нужно будет отредактировать его вверху только один раз, а не три раза в коде.
Спасибо, что нам нужно сделать для "json_open", так как я работаю с командами? Я просто устанавливаю следующее:
reaction_roles= self.bot.json_open()
?