Skip to content
This repository was archived by the owner on Dec 26, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
04c5de6
:sparkles: new example with an Image generator
drawbu Nov 14, 2021
3f7bee5
Merge pull request #1 from Pincer-org/main
drawbu Nov 15, 2021
01f4a82
Merge remote-tracking branch 'origin/main'
drawbu Nov 15, 2021
0bbe208
Merge branch 'Pincer-org:main' into main
drawbu Nov 17, 2021
f70f7e5
Merge remote-tracking branch 'origin/main'
drawbu Nov 17, 2021
caf79e7
Merge branch 'Pincer-org:main' into main
drawbu Nov 20, 2021
ee4e5df
Merge remote-tracking branch 'origin/main'
drawbu Nov 20, 2021
ff22f93
Merge branch 'Pincer-org:main' into main
drawbu Nov 20, 2021
5f72a0a
Merge remote-tracking branch 'origin/main'
drawbu Nov 20, 2021
2b17668
:lipstick: changed raw user ping to an nice `@ping` thing
drawbu Nov 20, 2021
1482075
:recycle: download avatar with Pincer method
drawbu Nov 20, 2021
72cd529
:heavy_minus_sign: unused dependencies: `io`, `urllib.request`
drawbu Nov 20, 2021
c325485
:bug: argument were not passed
Sigmanificient Nov 20, 2021
a60d18e
Update examples/tweet_generator.py
Sigmanificient Nov 20, 2021
2a0f4e0
Update examples/tweet_generator.py
Sigmanificient Nov 20, 2021
8356852
:art: fixing formatting
drawbu Nov 20, 2021
83cef97
moved everything in a subfolder and the resources use _ instead of sp…
drawbu Nov 20, 2021
7cad52e
Merge branch 'Pincer-org:main' into main
drawbu Nov 21, 2021
c1ec274
Update examples/tweet_generator/tweet_generator.py
Sigmanificient Nov 21, 2021
5f3eb2d
Update examples/tweet_generator/tweet_generator.py
Sigmanificient Nov 21, 2021
0fbfbaf
Update examples/tweet_generator/tweet_generator.py
Sigmanificient Nov 21, 2021
7984bcc
Update examples/tweet_generator/tweet_generator.py
Sigmanificient Nov 21, 2021
7db46ac
Update examples/tweet_generator/tweet_generator.py
Sigmanificient Nov 21, 2021
43e56d6
Revert "Update examples/tweet_generator/tweet_generator.py"
Sigmanificient Nov 21, 2021
75be6bd
:bug: changed to font used
drawbu Nov 28, 2021
1110ff6
:ambulance: hide my token
drawbu Nov 28, 2021
7a945f2
Merge branch 'Pincer-org:main' into main
drawbu Nov 28, 2021
5b00ca2
:fire: delete `name=twitter` line requested by Endercheif
drawbu Nov 28, 2021
20e3696
:art: using f-string
drawbu Nov 28, 2021
441bc40
:bug: using composite commands
drawbu Nov 28, 2021
9b8e8ce
:fire: re-hide my token...
drawbu Nov 28, 2021
ca90b4f
:art: requested changes in `trans_paste` requested by Lunarmagpie
drawbu Nov 28, 2021
a17b8c6
:see_no_evil: improve syntax
drawbu Nov 28, 2021
345d018
:art: extract the full tweet creation to another method to shorter th…
drawbu Nov 28, 2021
efb9259
:art: each parameter on a separate line, the line's too long https://…
drawbu Nov 28, 2021
c23b4d5
:art: merge into 1 line https://github.com/Pincer-org/Pincer/pull/241…
drawbu Nov 28, 2021
b6dc77c
:art: simplified list's square brackets usage
drawbu Nov 28, 2021
f009ec5
Update examples/tweet_generator/tweet_generator.py
drawbu Nov 28, 2021
46c4979
Update examples/tweet_generator/tweet_generator.py
drawbu Nov 28, 2021
3bb5ca8
Update examples/tweet_generator/tweet_generator.py
drawbu Nov 28, 2021
8379414
:art: split into multiple lines, the line's too long https://github.c…
drawbu Nov 28, 2021
112ed8d
:art: split into multiple lines https://github.com/Pincer-org/Pincer/…
drawbu Nov 28, 2021
9756eab
Update examples/tweet_generator/tweet_generator.py
drawbu Nov 28, 2021
9350a92
:wheelchair: add a print statement with the instructions if the user …
drawbu Nov 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@ MANIFEST
.coverage

# IDE Ext's
.history/
.history/

# tweet_generator example
examples/tweet_generator/*.ttf
180 changes: 180 additions & 0 deletions examples/tweet_generator/tweet_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import re
import textwrap
import os
import sys
from datetime import datetime
from PIL import Image, ImageFont, ImageDraw, ImageOps
from pincer import command, Client
from pincer.commands import CommandArg, Description
from pincer.objects import Message, Embed, MessageContext


# you need to manually download the font files and put them into the folder
# ./examples/tweet_generator/ to make the script works using this link:
# https://fonts.google.com/share?selection.family=Noto%20Sans:wght@400;700
if not all(font in os.listdir() for font in ["NotoSans-Regular.ttf", "NotoSans-Bold.ttf"]):
sys.exit()


class Bot(Client):
@Client.event
async def on_ready(self):
print(
f"Started client on {self.bot}\n"
f"Registered commands: {', '.join(self.chat_commands)}"
)

@command(
description="to create fake tweets",
)
async def twitter(
self, ctx: MessageContext, content: CommandArg[str, Description["The content of the message"]]
):
await ctx.interaction.ack()

for text_match, user_id in re.findall(
re.compile(r"(<@!(\d+)>)"), content
):
content = content.replace(
text_match, f"@{await self.get_user(user_id)}"
)

if len(content) > 280:
return "A tweet can be at maximum 280 characters long"

# download the profile picture and convert it into Image object
avatar = (await ctx.author.user.get_avatar()).resize((128, 128))
avatar = circular_avatar(avatar)

# create the tweet by pasting the profile picture into a white image
tweet = trans_paste(
avatar,
Image.new("RGBA", (800, 250 + 50 * len(textwrap.wrap(content, 38))), (255, 255, 255)),
box=(15, 15),
)

# add the fonts
font_normal = ImageFont.truetype("NotoSans-Regular.ttf", 40)
font_small = ImageFont.truetype("NotoSans-Regular.ttf", 30)
font_bold = ImageFont.truetype("NotoSans-Bold.ttf", 40)

# write the name and username on the Image
draw = ImageDraw.Draw(tweet)
draw.text(
(180, 20), str(ctx.author.user),
fill=(0, 0, 0), font=font_bold
)
draw.text(
(180, 70),
f"@{ctx.author.user.username}",
fill=(120, 120, 120), font=font_normal,
)

content = add_color_to_mentions(content)

# write the text
tweet = draw_multicolored_text(tweet, content, font_normal)

# write the footer
draw.text(
(30, tweet.size[1] - 60),
datetime.now().strftime(
"%I:%M %p · %d %b. %Y · Twitter for Discord"
),
fill=(120, 120, 120),
font=font_small,
)

return Message(
embeds=[
Embed(title="Twitter for Discord", description="").set_image(
url="attachment://image0.png"
)
],
attachments=[tweet],
)


def trans_paste(fg_img, bg_img, box=(0, 0)):
"""
https://stackoverflow.com/a/53663233/15485584
paste an image into one another
"""
fg_img_trans = Image.new("RGBA", fg_img.size)
fg_img_trans = Image.blend(fg_img_trans, fg_img, 1.0)
bg_img.paste(fg_img_trans, box, fg_img_trans)
return bg_img


def circular_avatar(avatar):
mask = Image.new("L", (128, 128), 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0, 128, 128), fill=255)
avatar = ImageOps.fit(avatar, mask.size, centering=(0.5, 0.5))
avatar.putalpha(mask)
return avatar


def add_color_to_mentions(message):
"""
generate a dict to set were the text need to be in different colors.
if a word starts with '@' it will be write in blue.

Parameters
----------
message: the text

Returns
-------
a list with all colors selected
example:
[
{'color': (0, 0, 0), 'text': 'hello world '},
{'color': (0, 154, 234), 'text': '@drawbu'}
]

"""
message = textwrap.wrap(message, 38)
message = "\n".join(message).split(" ")
result = []
for word in message:
for index, text in enumerate(word.splitlines()):

text += "\n" if index != len(word.split("\n")) - 1 else " "

if not result:
result.append({"color": (0, 0, 0), "text": text})
continue

if not text.startswith("@"):
if result[-1:][0]["color"] == (0, 0, 0):
result[-1:][0]["text"] += text
continue

result.append({"color": (0, 0, 0), "text": text})
continue

result.append({"color": (0, 154, 234), "text": text})
return result


def draw_multicolored_text(image, message, font):
draw = ImageDraw.Draw(image)
x = 30
y = 170
for text in message:
y -= font.getsize(" ")[1]
for l_index, line in enumerate(text["text"].splitlines()):
if l_index:
x = 30
y += font.getsize(" ")[1]
draw.text((x, y), line, fill=text["color"], font=font)
x += font.getsize(line)[0]
return image


if __name__ == "__main__":
# Of course we have to run our client, you can replace the
# XXXYOURBOTTOKENHEREXXX with your token, or dynamically get it
# through a dotenv/env.
Bot("XXXYOURBOTTOKENHEREXXX").run()
14 changes: 8 additions & 6 deletions pincer/objects/user/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ def premium(self) -> APINullable[PremiumTypes]:
user their premium type in a usable enum.
"""
return (
MISSING if self.premium_type is MISSING else PremiumTypes(
self.premium_type)
MISSING
if self.premium_type is MISSING
else PremiumTypes(self.premium_type)
)

@property
Expand Down Expand Up @@ -179,7 +180,9 @@ async def get_avatar(self, size: int = 512, ext: str = "png") -> Image:
:class: Image
The user's avatar as a Pillow image.
"""
async with ClientSession().get(url=self.get_avatar_url()) as resp:
async with ClientSession().get(
url=self.get_avatar_url(size, ext)
) as resp:
avatar = io.BytesIO(await resp.read())
return Image.open(avatar).convert("RGBA")

Expand Down Expand Up @@ -221,9 +224,8 @@ async def get_dm_channel(self) -> channel.Channel:
construct_client_dict(
self._client,
await self._http.post(
"/users/@me/channels",
data={"recipient_id": self.id}
)
"/users/@me/channels", data={"recipient_id": self.id}
),
)
)

Expand Down