Created
July 24, 2021 09:14
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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