Skip to content

Instantly share code, notes, and snippets.

@AdhTri001
Created July 24, 2021 09:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AdhTri001/cee97086fbcea93a39ca2e0706cd2eef to your computer and use it in GitHub Desktop.
Save AdhTri001/cee97086fbcea93a39ca2e0706cd2eef to your computer and use it in GitHub Desktop.
This command is for `discord.py` bot that creates a fake discord message snap and sends to the channel
import discord
from discord.ext import commands
from PIL import Image, ImageFont, ImageDraw
from pilmoji import Pilmoji
CHANNEL_regex= re.compile('<#(\d{16,22})>')
ROLE_regex= re.compile('(<@&\d{16,22}>)')
MENTION_regex= re.compile('<@(?:!)?(\d{16,22})>')
ITALICS_regex= re.compile('((?:_[^_]+?_(?!\w)|$)|(?:\*[^\*]+?\*(?=(?:\*\*)+|[^\*]+|$)))')
BOLD_regex= re.compile('(\*\*.+?\*{2,})')
MD_regex= re.compile('(`[^`]+`)')
URL_regex= re.compile("(https?://\S\S+)")
# These regex helps us to split message in different nodes.
DISC_fnt= ImageFont.truetype(f'{os.path.dirname(__file__)}/images/OpenSans-Light.ttf',28)
DISC_IT_fnt= ImageFont.truetype(f'{os.path.dirname(__file__)}/images/OpenSans-LightItalic.ttf',28)
DISC_BLD_fnt= ImageFont.truetype(f'{os.path.dirname(__file__)}/images/OpenSans-SemiBold.ttf',28)
DISC_BLD_IT_fnt= ImageFont.truetype(f'{os.path.dirname(__file__)}/images/OpenSans-SemiBoldItalic.ttf',28)
DISC_TS_fnt= ImageFont.truetype(f'{os.path.dirname(__file__)}/images/OpenSans-Light.ttf',20)
DISC_MONO_fnt= ImageFont.truetype(f'{os.path.dirname(__file__)}/images/Inconsolata-Medium.ttf', 30)
# Download these fonts here:
# Open Sans --- https://fonts.google.com/specimen/Open+Sans?query=Open+Sans
# Inconsolata - https://fonts.google.com/specimen/Inconsolata?query=Inconsolata
# This flattens a list:
'''
[[1,2],3,[4,3.1]] -> [1,2,3,4,3,1]
'''
def flatten(matrix):
result = []
for el in matrix:
if hasattr(el, "__iter__") and not isinstance(el, str):
result.extend(flatten(el))
else:
result.append(el)
return result
class Images(commands.Cog):
def __init__(self, client):
# ARGHH! U can do this right?
@commands.command(
aliases= ["snap"],
help= "Make a fake discord message snap to troll ur friends.",
description= "U may use user id/mention if u don't want member not found error. This command has the font and styling that android uses!")
async def mimic(self, ctx: commands.Context, member: Union[discord.Member, discord.User, str]= None, *, message= None):
if not member and not message: return await ctx.send('You haven\'t provided me any argument.')
if isinstance(member, str):
message= member + ' ' + (message if message else '')
member= ctx.author
if not message:
return await ctx.send(f'No message was given to mimic for **{member}**')
async with ctx.channel.typing():
emojies= EMOJI_regex.findall(message)
if len(emojies)>3:
return await ctx.reply('More than three emojies failed to parse.')
if len(message)>1000:
await ctx.reply('This is not accepted, word limit is 1000 characters.')
return
mentions= MENTION_regex.findall(message)
channel_mentions= CHANNEL_regex.findall(message)
blurple_mentions= []
for mention in mentions:
newstr= ''
for mem in ctx.message.mentions:
if int(mention) == mem.id:
newstr= f'@{mem.display_name}'
break
blurple_mentions.append(newstr)
message= message.replace(f'<@!{mention}>', newstr).replace(f'<@{mention}>', newstr)
for mention in channel_mentions:
newstr= ''
for mem in ctx.message.channel_mentions:
if int(mention) == mem.id:
newstr= f'#{mem.name}'
break
blurple_mentions.append(newstr)
message= message.replace(f'<#{mention}>', newstr)
if len(blurple_mentions)>6:
await ctx.send('Not more than 6 mentions (both member and channel) per message.')
return
for emote in emojies:
message= message.replace(f'<{":".join(emote)}>', f'<:e_:{emojies.index(emote)}>')
lines= []
for line in message.split('\n'):
if len(line)>85:
for wrapped in wrap(line,85):
lines.append(wrapped)
else:
lines.append(line)
proplines= []
for line in lines:
for emote in emojies:
line= line.replace(f'<:e_:{emojies.index(emote)}>', f'<{":".join(emote)}>')
proplines.append(line)
img= Image.new('RGBA', (1200, 1200), color= (54,57,63))
parser= Pilmoji(img)
img_bin= BytesIO()
if isinstance(member, discord.Member):
uname= member.display_name
else:
uname= member.name
if isinstance(member, discord.Member):
parser.text((100, 13), uname, font= DISC_BLD_fnt, fill= member.color.to_rgb() if member.color.to_rgb() != (0,0,0) else (255,255,255))
else:
parser.text((100, 13), uname, font= DISC_BLD_fnt, fill= (255,255,255))
h, w= parser.getsize(uname, font= DISC_BLD_fnt)
titlelen= 300+h
if len(proplines)==1:
vert_crop= 110
else:
vert_crop= 120+(w*len(proplines[2:]))
time= datetime.utcnow().strftime("Today at %H:%M")
parser.text((110+h, 20), time, font= DISC_TS_fnt, fill=(114, 118, 125))
draw= ImageDraw.Draw(img)
boxes= []
italics= False
bolded= False
code_block= False
i= 1
for line in proplines:
if line.strip():
nodes= BOLD_regex.split(line)
nodes= [ITALICS_regex.split(node) for node in nodes if node]
nodes= flatten(nodes)
nodes= [MD_regex.split(node) for node in nodes if node]
nodes= flatten(nodes)
nodes= [URL_regex.split(node) for node in nodes if node]
nodes= flatten(nodes)
else:
nodes= line
last_node_len= 0
fnt= None
for node in nodes:
boxes= []
pntnode= node
if node.startswith('**'):
bolded= not bolded
pntnode= pntnode[2:]
if node.endswith('**') and len(node)>4:
pntnode= pntnode[:-2]
elif (node.startswith('_') or (node.startswith('*') and not node.startswith('**'))):
italics= True
pntnode= pntnode[1:]
if node.endswith('_') or (node.endswith('*') and not node.endswith('**')):
pntnode= pntnode[:-1]
elif node.startswith('`') and node.endswith('`'):
code_block= True
pntnode= pntnode[1:-1]
if bolded and italics and not code_block:
fnt= DISC_BLD_IT_fnt
elif bolded and not italics and not code_block:
fnt= DISC_BLD_fnt
elif italics and not bolded and not code_block:
fnt= DISC_IT_fnt
elif code_block:
fnt= DISC_MONO_fnt
temp_width= parser.getsize(pntnode, font= fnt)[0]
code_box= (last_node_len+100, 32+(28*i), temp_width+last_node_len+100, 55+(28*i))
draw.rectangle(code_box, (40,40,40))
else:
fnt= DISC_fnt
if blurple_mentions:
for mention in blurple_mentions:
subnodes= pntnode.split(mention)
if len(subnodes) == 1:
continue
box= []
hmen,wmen= parser.getsize(mention.replace('\u200b', ''), font= fnt)
for subnode in subnodes[::2]:
h,w= parser.getsize(subnode, font= fnt)
box.append(100+last_node_len+h)
box.append(32+(28*i))
box.append(102+last_node_len+h+hmen)
box.append(32+(28*i)+wmen)
boxes.append(tuple(box))
box=[]
pntnode= pntnode.replace(mention, mention.replace('\u200b', ''))
if boxes:
for box in boxes:
draw.rounded_rectangle(box, 5, (80, 105, 191, 190))
if pntnode:
parser.text((100+last_node_len, 25+(28*i)),
pntnode,
font= fnt, fill= (255,255,255) if not URL_regex.match(node) else (88, 152, 196),
stroke_fill= (255,255,255), stroke_width= 1 if bolded else 0)
if node.endswith('**') and len(node)>4:
bolded= False
elif node.endswith('_') or (node.endswith('*') and not node.endswith('**')):
italics= False
last_node_len+= parser.getsize(pntnode, font= fnt)[0]
if titlelen< last_node_len+100:
titlelen= last_node_len+115
i+=1
f2= Image.open(BytesIO(await member.avatar_url_as(format= 'png', size= 64).read())).convert('RGBA')
mask= Image.new("L", f2.size, 0)
draw= ImageDraw.Draw(mask)
draw.ellipse((0, 0, 65, 65), fill=255)
tempf2= f2.copy()
tempf2.putalpha(mask)
f2.paste(tempf2, mask= f2)
f2.thumbnail((64,64), Image.ANTIALIAS)
img.paste(f2, (20, 20), f2)
img= img.crop((0, 0, titlelen, vert_crop))
img.save(img_bin, 'PNG')
img_bin.seek(0)
file= discord.File(img_bin, f'BULLY.png')
await ctx.reply(file=file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment