Search code examples
pythondiscorddiscord.py

How would I convert a mention to a string in d.py?


I created a custom event for a twitter feed on my server. It works great so far, but I keep running into one issue: whenever a user mentions someone, the text outputs it as the <@1234...> format, which, to be fair, is expected. However, I'm trying to program it to just show the server nickname.

Here is my code so far. Please note it is in a cog:


import discord
from discord.ext import commands
from PIL import Image, ImageDraw, ImageFont, ImageOps
import aiohttp
import textwrap
from textwrap import wrap
import datetime
from datetime import datetime, timedelta
import asyncio
import json
import pytz

...

    @commands.Cog.listener()
    async def on_message(self, message):
        nickname = message.author.nick
        if nickname is None: 
          nickname = message.author.name 
        if message.author.bot:
          return
        elif message.channel.id == 1065325485506170891:
          await message.delete()
          avatar_url = str(message.author.avatar.url)
          async with self.session.get(avatar_url) as resp:
            avatar_data = await resp.read()
          with open("pfp.png", "wb") as f:
            f.write(avatar_data)
          pfp = Image.open("pfp.png").convert("RGBA")
          size = (75, 75)
          mask = Image.new("L", size, 0)
          draw = ImageDraw.Draw(mask)
          draw.ellipse((0, 0) + size, fill=255)
          pfp = ImageOps.fit(pfp, mask.size, centering=(0.5,0.5))
          pfp.putalpha(mask)
          pfp = pfp.resize(size, Image.LANCZOS)
          img = Image.open('Tweet_Template.png') 
          draw = ImageDraw.Draw(img)
          img.paste(pfp, (15, 70), pfp)
          font2 = ImageFont.truetype('cogs/Cantarell-Regular.ttf', 20)
          font5 = ImageFont.truetype('cogs/Cantarell-Bold.ttf', 20)
          draw = ImageDraw.Draw(img)
          message_tweet = str(message.content)
          if message.attachments:
            wrapped = textwrap.wrap(message_tweet, width=40)
          else:
            wrapped = textwrap.wrap(message_tweet, width= 60)
          wrapped_message = '\n'.join(wrapped)
          draw.text((90, 140), wrapped_message, box_width=50, fill='black',font=font2)
          draw.text((111, 111), message.author.name, fill='gray', font=font2)
          draw.text((95, 85), nickname, fill='black', font=font5)
          timezone = pytz.timezone('America/New_York')
          timestamp = datetime.now()
          est = str(timestamp.astimezone(timezone).strftime("%I:%M:%S %p EST • %B %d"))
          draw.text((20, 230), est, fill='gray', font=font2)
          if message.attachments:
            attachment = message.attachments[0]
            url = attachment.url
            async with self.session.get(url) as resp:
              attachment_data = await resp.read()
            with open("attachment.png", "wb") as f:
              f.write(attachment_data)     
            attachment = Image.open("attachment.png")
            attachment = attachment.resize((200, 175), Image.LANCZOS)
            img.paste(attachment, (400, 75), attachment)
          img.save('Tweet.png')
          react_here = await message.channel.send(file=discord.File('Tweet.png'))
          await react_here.add_reaction("❤️")
          await react_here.add_reaction("↪️")

...

I've attempted to use the member.guild.name attribute, but I am unsure where I would place it in order to make it work. I've also attempted to use .replace.


Solution

  • Using Mesage.mentions, and str.replace, we can write a function like so:

    def format_mentions(message: discord.Message) -> str:
        mentions = message.mentions
        output = message.content
    
        for member in mentions:
            # Replace does not modify, it returns a new string.
            output = output.replace(f"<@{member.id}>", f"@{member.global_name}")
       
        return output
    

    Note: This uses Member.global_name, which will ignore server-specific nicknames. You should use Member.display_name to prioritise server-specific nicknames.