0

So I am currently trying to create a Discord bot that creates a custom welcome image when someone joins the server. However, there is no output on the image selected and there are no error outputs whenever I run the bot. I assumed I did not enable Privileged Intents but I have so I am stuck as to why it is not outputting anything when I log into my test server using my test account! You can find my code below :

#importing dependencies

import numpy as np
import logging
import discord
import PIL
import asyncio
import os

#importing commands from above dependencies

from discord import client
from discord.ext import commands
from PIL import Image, ImageFont, ImageDraw
from discord.member import Member

#enabling privileged intents

intents = discord.Intents.default()
intents.members = True
intents.presences = True
client = discord.Client(intents=intents)

#for custom image welcome message

@client.event
async def on_member_join(ctx, member: discord.Member = None):

    if member == None:
        member = ctx.author
    channel = client.get_channel("TOKEN")

    #-----------------------------------------------------------------------------#   

    #transforming user's avatar into a circle

    # Open the input image as numpy array, convert to RGB
    img=Image.open(member.avatar_url).convert("RGB")
    npImage=np.array(img)
    h,w=img.size

    # Create same size alpha layer with circle
    alpha = Image.new('L', img.size,0)
    draw = ImageDraw.Draw(alpha)
    draw.pieslice([0,0,h,w],0,360,fill=255)

    # Convert alpha Image to numpy array
    npAlpha=np.array(alpha)

    # Add alpha layer to RGB
    npImage=np.dstack((npImage,npAlpha))

    # Save with alpha
    Image.fromarray(npImage).save("D:\Coding\Python\Projects\discord_moderation_bot\imgs\result.png")
    
    #-----------------------------------------------------------------------------#
    
    #pasting user avatar into welcome banner
    
    img = Image.open("D:\Coding\Python\Projects\discord_moderation_bot\imgs\welcome_banner.png")
    pfp = Image.open("D:\Coding\Python\Projects\discord_moderation_bot\imgs\result.png")
    
    pfp = pfp.resize ((167, 167))

    img.paste(pfp, (120, 104))

    img.save("D:\Coding\Python\Projects\discord_moderation_bot\imgs\welcome.jpg")

    await ctx.send(file = discord.File("welcome.jpg"))


client.run("TOKEN")

Thanks in advance!

  • 1
    Please remove your token from the code, it should not be visible. Can you please also reduce the code a bit? Only to the necessary area, if you can. – Dominik May 08 '21 at 12:29
  • @Dominik I have removed any and all tokens from the code and I have just shortened it to what I've imported and the actual code. Please forgive me for not sticking to the Terms of Use of Stack Overflow. – Adarsh Nair May 08 '21 at 12:53
  • Remove `default()` from the end of intents and add `all()` in replacement. Also remove the two lines under it. And try once more. – Bhavyadeep Yadav May 08 '21 at 12:54
  • Your token was posted publicly, and *is still viewable* in the edit history. Please make sure to regenerate your bot's token as soon as possible. – CrazyChucky May 08 '21 at 13:13
  • @CrazyChucky I have regenerated my bot's token. Thank you for pointing that out, I'm still new to this hub. Do I have to do anything in regards to my channel tokens? – Adarsh Nair May 08 '21 at 13:28
  • @BhavyadeepYadav Thanks for the suggestion man! I did as you said but it still isn't outputting any image at all. – Adarsh Nair May 08 '21 at 13:28
  • @AdarshNair I see that your image is coming from your own device. I not sure but this can be the issue. I would suggest that you use website like: `Imgur` or `giphy` or `discord` itself. Send the image in any chat and copy its link and then use it in the code accordingly. It might actually save your time – Bhavyadeep Yadav May 08 '21 at 13:50
  • As I understand it, channels don't have secret tokens like bots. Simply having a channel's id number shouldn't enable any malicious activity. – CrazyChucky May 08 '21 at 16:05

1 Answers1

0

When troubleshooting code that interacts with an external app like this, it's a good idea to test your own part first, as a standalone script. In this case, if I test your image manipulation code alone, it fails because the final image is in paletted mode (P), and you try to save it as a JPEG, which needs to be RGB. This can be fixed by converting the mode first. But there are some other issues, namely:

  • You have the signature for on_member_join wrong. It accepts only a single argument, the member in question.
  • You pick a channel, but then attempt to send the message from ctx instead.
  • member.avatar_url is a URL, which Pillow can't open directly. This answer handily shows how to do so, however. Note that you'll need to install Requests.
  • Using NumPy here works, but you don't actually need it, since this can all be accomplished through Pillow.
  • You don't need to save and reopen the cropped avatar; use the object you're already working with.
  • Perhaps you need it for other things your bot is doing, but for this, you don't need the presences intent, only members.
  • It's not causing a problem with the code, but I think you're a little confused about import statements. You don't need to import a module first just to then import specific parts of it; that is, you can do from x import y without first doing import x. And there's no need for from x import y if you plan to reference it as x.y in your code.
  • I'd recommend using pathlib. It's very convenient for working with file paths.

Here's a rewritten version that works for me:

from pathlib import Path

import discord
import requests
from PIL import Image, ImageDraw

# Enabling privileged intents
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)

# When using pathlib, use forward slashes, even on Windows.
img_dir = Path("D:/Coding/Python/Projects/discord_moderation_bot/imgs")

@client.event
async def on_member_join(member):
    """Display custom welcome message banner."""
    # Open the input image, convert to RGB
    avatar_bytes = requests.get(member.avatar_url, stream=True).raw
    avatar = Image.open(avatar_bytes).convert("RGB")

    # Create same size alpha layer with circle, and apply to avatar
    alpha = Image.new("L", avatar.size, 0)
    draw = ImageDraw.Draw(alpha)
    draw.ellipse([(0, 0), avatar.size], fill=255)
    avatar.putalpha(alpha)

    avatar = avatar.resize((167, 167))

    # Open banner and alpha-composite avatar onto it
    banner = Image.open(img_dir / "welcome_banner.png").convert("RGBA")
    overlay = Image.new("RGBA", banner.size, 0)
    overlay.paste(avatar, (120, 104))
    banner.alpha_composite(overlay)

    # Convert to RGB mode to save as JPG. Append user name, so that we
    # don't upload the wrong image if two users join at almost the same
    # time.
    welcome_file_path = img_dir / f"welcome_{member.name}.jpg"
    banner.convert("RGB").save(welcome_file_path)

    # Post the image.
    channel = client.get_channel("CHANNEL ID")
    await channel.send(file=discord.File(welcome_file_path))

client.run("TOKEN")
CrazyChucky
  • 3,263
  • 4
  • 11
  • 25
  • Worked perfectly. Thank you for helping me out! Also, is there any way to make this a separate file that the main file can access through because I intend on adding a few more functions and it would seem to better organize things. – Adarsh Nair May 08 '21 at 18:02
  • @AdarshNair You might want to look into [cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html). If you have further questions about cogs and/or source file management (that you are unable to answer through research and experimentation), I'd recommend asking them as separate questions here on Stack Overflow. – CrazyChucky May 08 '21 at 18:19
  • thank you for the help. I was wondering how you were able to condense my original code to what you wrote and how do I improve my skills? – Adarsh Nair May 08 '21 at 18:32
  • @AdarshNair The two most important skills you can learn are: 1) [debugging](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) your code. Just putting `print` statements (and for Pillow, `image.show()`) at various spots to check that things are what you expect will save you hours of headaches. And break large problems into small problems to find the bugs. And 2) finding information, whether from [documentation](https://discordpy.readthedocs.io/en/stable/) or search engines. As an example, I didn't even know about cogs until you asked me and I Googled "discord.py separate files". – CrazyChucky May 08 '21 at 18:55