Getting emoji object to unicode - python

Right now im my journey of discordbot making, I'm tackling reaction roles! I think I have most everything setup, but I can't seem to find a way to get from an emoji object to an emoji unicode, so I can compare them and add the reaction. Here's what I have so far:
#bot.event
async def on_raw_reaction_add(payload):
print(payload)
channel = bot.get_channel(payload.channel_id)
emoji = payload.emoji
print(emoji.id)
#bot.command(pass_context=True)
async def reactionrole(ctx, title:str, description:str, name:str, value:str):
title = ''.join(title)
description = ''.join(description)
name = ''.join(name)
value = ''.join(value)
embed = discord.Embed(colour = discord.Colour.teal(), title = title, description = description)
embed.add_field(name = name, value = value, inline=False)
message = await ctx.send(embed = embed)
with open("reactionroles.json", 'r') as f:
data = json.load(f)
addon = {"guild-id" : ctx.guild.id}, {"message-id" : message.id}, {"roles" : []}, {"emojis" : []}
data[ctx.guild.id] = addon
with open("reactionroles.json", 'w') as f:
json.dump(data, f)
#bot.command(pass_context=True)
async def reactionadd(ctx, emoji, *role:str):
role = ''.join(role)
with open("reactionroles.json", 'r') as f:
data = json.load(f)
message_id = data[str(ctx.guild.id)][1]['message-id']
message_id = int(message_id)
message = await ctx.channel.fetch_message(message_id)
await message.add_reaction(emoji)
role = discord.utils.get(ctx.guild.roles, name=role)
data[str(ctx.guild.id)][3]['emojis'].append(emoji)
print(role)
data[str(ctx.guild.id)][2]['roles'].append(str(role))
with open("reactionroles.json", 'w') as f:
json.dump(data, f, indent=4)
So the command reactionrole creates the embed, and writes some placeholder data into a json file. Afterwards, the reactionadd command adds the emoji unicode to a json array, and the role to a different json array. When on a reaction add, in on_raw_reaction_add(payload), payload only has the name of the emoji, and not the unicode. Because of this, I', not able to compare the two to see what role goes to what emoji. I can't save the origional, in reactionadd because I would run into problems in on_reaction_add. I'm lost on getting the unicode from the payload this is my final reach out. Here's what's inside payload:
<RawReactionActionEvent message_id=759903170721087508 user_id=146348630926819328 channel_id=754904403710050375 guild_id=665787149513261057 emoji=<PartialEmoji animated=False name='�😋' id=Non
event_type='REACTION_ADD' member=<Member id=146348630926819328 name='Chai' discriminator='6396' bot=False nick=None guild=<Guild id=665787149513261057 name="ChaiBot's Playground" shard_id=None chunked=True member_count=34>>>

From an Emoji object you can get the unicode character from emoji.name, or if you are looking for the unicode name you can use the python unicodedata library:
import unicodedata
unicodedata.name(emoji.name)

I have realized my error! I was able to compare the unicode from reactionadd to payload.emoji the entire time! I was not able to see originally though, that vs code shows the unicode as an emoji (in terminal), and not as the string. That makes much more sense now! Thanks to all they helped!

Related

Adding Roles In Slash Commands (Discord.Py)

#tree.command(name = 'redeem', description = 'Redeems A Members Key')
async def redeem(interaction: discord.Interaction, key: str, member:discord.Member):
with open("bkeys.txt") as f:
if key in f.read():
em = discord.Embed(color=0xff0000)
em.add_field(name="Invalid Key", value="Sorry, this key has been blacklisted")
await interaction.response.send_message(embed=em)
return 0
with open("keys.txt") as f:
if key in f.read():
role = interaction.guild.get_role(1071561081685811210)
await member.add_roles(member, role)
em = discord.Embed(color=0x008525)
em.add_field(name="Key Redeemed", value="Key has now been redeemed")
await interaction.response.send_message(embed=em)
f = open("ukeys.txt", "w")
f.write(key)
f.write('\n')
else:
em = discord.Embed(color=0xff0000)
em.add_field(name="Invalid Key", value="Inputed key has already been used!")
await interaction.response.send_message(embed=em)
Error
**This has been a command I have been trying to work on its just the add roles will not work, btw im new to python so I don't know much sorry, so if anyone could just drop the code please.
**
I tried changing the (1071561081685811210) to my role name ("Buyer") and asking for help but I didn't understand.
like bruh has said you should change
member.add_roles(member,role)
to
member.add_roles(role)

Discord Py - Appending info to an external file but program can't read the last entry (altho info gets saved)

New to programming. I'm creating a bot for moderators to view and add to a filter trigger word list, which is saved as an external text file. When the command to add a word is evoked, it gets added to the text file. But when I make the command to view the list in the server, the printed list doesn't get updated and the last entry just made is not there.
with open('triggers.txt', 'r') as x:
global triggerlist
trig = x.read()
triggerlist = trig.split()
#client.command(aliases = ["viewlist", "viewtriggers"]) #view
#has_permissions(ban_members = True)
async def viewblocklist(ctx):
channel = client.get_channel(LOG_CHANNEL_ID)
await ctx.message.add_reaction(emoji_thumbsup)
printformat = '\n'.join(triggerlist)
await channel.send(printformat)
#client.command(aliases = ["addlist", "addtrigger"]) #add/append
#has_permissions(ban_members = True)
async def addblocklist(ctx, *, arg):
with open('triggers.txt', 'a+') as x:
x.write(arg.strip().lower()+'\n')
x.flush()
x.close()
await ctx.message.add_reaction(emoji_thumbsup)
return

Discord Py Bot - json file is being written to but does not save after reload

I have a json load/save/dump function to count how many time a single word is said in a specific channel. It works great, but I lose the data after reboot of the bot. Below is my code.
def load_counters():
with open('cup.json', 'r') as f:
counters = json.load(f)
return counters
def save_counters(counters):
with open('cup.json', 'w') as f:
json.dump(counters, f)
if message.channel.id == 709551578612498453:
if message.content == ('cup'):
counters = load_counters()
counters["cup"] += 1
save_counters(counters)
return
else:
cup_meta = client.get_channel(709984510678269982)
cup_channel = client.get_channel(709551578612498453)
await cup_meta.send(message.author.mention + ' has violated the sacred rules of Cup')
await message.delete()
await cup_channel.send('cup')
return
with open('cup.json', 'r') as f:
counters1 = json.load(f) # Open and load the file
totalcup = counters1['cup']
if message.content == ('!totalcup'):
await message.channel.send(f"Cup has been said {totalcup} times since Bender reset me.")
Here is the json file - right now if I were to run !totalcup, the bot spits out '13' but the file says 0. Not sure if I am missing something as I am new to code.
{
"cup": 0
}
I just figured it out. The code does work as intended, it is a problem with how my host (Heroku) operates. There isn't anything I can do until I find a new hosting situation.

discord.py Changing file size to add custom emoji

What I'm trying to do: I have an on_message event for a 'global chat' command that I have created. This would send messages to any server that was in the json, currently supporting images, multiple lines of text, and custom emojis (as long as the bot shared a server with said emoji).
My problem: As you can see in the image above, one person, 'S o u p', has their profile picture replaced with a duck emoji. For context's sake, their avatar is not that of a duck emoji. However, if you were to look at the most recent message, the profile picture is shown. I believe that the problem lies in the size of the message.author's avatar. The PIL library may be a good solution, but I do not want to save the image.
Code I have tried:
avatar_bytes = await message.author.avatar_url.read()
guildem = client.get_guild(738285544911405107)
try:
em = await guildem.create_custom_emoji(name=f'{message.author.name}', image=avatar_bytes)
except:
em = '🦆'
The code above is the one I had used in the image example I had provided.
avatar = message.author.avatar_url_as(size=128) # resize avatar
avatar_bytes = await avatar.read() # then read as bytes?
Above code gives exact same results. Avatars are turned into duck emojis.
Others I have looked at:
How to crop an image to a shape for eg. circle using Pillow in Discord.py?: Messages did not send when using the code here. I assumed that using the PIL library would help reduce the file size significantly one way or the other without saving the image.
How to reduce the image file size using PIL: All the answers required saving the image, which I do not want to do. I tried tweaking the code a little bit, but caused all avatars to be turned into duck emojis.
If necessary, I will include the entire on_message event. However, this does not feel relevant nor necessary to include since the emojis are only a small portion of said event.
Edit: Here is the code to the entire on_message event.
#client.event
async def on_message(message):
if message.author == client.user: # stop bot from replying to self
return
else:
if not message.guild: # prevent errors when messaging in bot dm's
return
f = open("global text.json") # existing json
"""
{
"747061937673732097": 765059798131539988,
"724783642546536458": 818707151122989119,
"761524419003809832": 813963773295591485,
"755309786232258630": 760381389685784587,
"738285544911405107": 738285544911405110
}
"""
data = json.load(f)
for i in data:
if str(i) == str(message.guild.id):
if data[str(message.guild.id)] == message.channel.id:
avatar_bytes = await message.author.avatar_url.read()
guildem = client.get_guild(738285544911405107) # guild to upload emojis to
try:
em = await guildem.create_custom_emoji(name=f'{message.author.name}', image=avatar_bytes) # create emoji using avatar_bytes in guildem server
except:
em = '🦆'
### functions ###
def censor(text): # censor words for safety
banned = ["test"] # bad words were here, removed for stackoverflow reasons
text = text.split()
nearly = []
for word in text:
if any(item in word.lower() for item in banned):
word = word.lower()
replaced = word.replace(word, ('#'*(len(word))))
nearly.append(replaced)
else:
nearly.append(word)
message = ' '.join(nearly)
return message
def parag(string): # check for \n
length = [string]
if string in ["", " ", " ", " "]:
return "<:transparent:774136812813811713>"
final_list = []
if '\n' in string:
length = string.split('\n')
for item in length:
thing = censor(item)
final_list.append(thing)
return paragger(final_list)
def paragger(list: list): # returns original message with \n
message = ""
for item in list:
message += f"> {item}\n"
return message
msg = parag(message.content)
### attachment handling ###
embed_list = []
if message.attachments:
if len(message.attachments) == 1:
embed = discord.Embed(title=f"{message.author}'s file", color=0xc39ce6)
for file in message.attachments:
embed.set_image(url=file.url)
embed_list.append(embed)
else:
count = 1
for file in message.attachments:
embed = discord.Embed(title=f"{message.author}'s file {count}")
embed.set_image(url=file.url)
embed_list.append(embed)
for i in data:
if str(i) != str(message.guild.id):
channel = client.get_channel(data[str(i)])
try:
await channel.send(f"{em} {message.author} \n{msg}", allowed_mentions=allowed_mentions)
if len(embed_list) > 0:
for embed in embed_list:
await channel.send(embed=embed)
except:
await channel.send(f"{em} {message.author} \n> {em}", allowed_mentions=allowed_mentions) # only happens if message is larger than 2000 char
if em != '🦆':
await em.delete() # delete the custom emoji to make space for more emojis later on
break
await client.process_commands(message) # process, prevent commands breaking
Your issue is here:
em = await guildem.create_custom_emoji(name=f'{message.author.name}', image=avatar_bytes)
You see, discord.py is looking for an emoji name with alphanumeric characters or underscores. S o a p does not fit this requirement, hence the error you have gotten. The following fixes the issue by replacing said characters with an underscore.
avatar_bytes = await message.author.avatar_url_as(size=128).read() # size=128 makes the size smaller for emojis
name = message.author.name.replace('-', '_').replace(' ', '_') # Replace the erroring characters
try:
em = await guildem.create_custom_emoji(name=f'{name}', image=avatar_bytes)
except:
em = '🦆'
EDIT: After taking another look, the problem wasn't what I thought after all, the issue with the user named S o a p was that it had non alphanumeric characters, I've updated my answer to fix this.
You don't need to save image. This is how you send images to discord without saving it:
import io
import PIL
image = PIL.Image.new("RGB", (200, 200), (255, 255, 255))
bytes_io = io.BytesIO()
image.save(bytes_io, format="png")
bytes_io.seek(0)
file = discord.File(bytes_io, "white.png")
#now you can send this file to discord
await ctx.send(file=file)

How to make a number alignment in JSON?

I am working on a command list command in JSON and I am having troubles with making a number alignment in the code.
#client.command()
async def command_list(ctx):
with open("commands.json", "r") as f:
y = json.load(f)
embed = discord.Embed(description="\n".join(y[str(ctx.guild.id)]),
colour=discord.Colour())
embed.set_author(name=ctx.author, icon_url=ctx.author.avatar_url)
await ctx.send(embed=embed)
I want it to be sent like this:
1. <1stcommandname>
2. <2ndcommandname>
3. <3rdcommandname>
...

Categories

Resources