diff --git a/CHANGELOG.md b/CHANGELOG.md
index 17bf827..b450308 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -43,4 +43,13 @@
- Addition of `test_sandbox_card3` in Tester class to test sandbox.
- Addition of more examples in Examples Folder.
+
+
+## 0.6.0
+
+- Custom Canvas in Sandbox mode.
+- README.md documentation updated.
+- Addition of `test_sandbox_custom_canvas` in Tester class to test sandbox.
+- Addition of more examples in Examples Folder.
+
\ No newline at end of file
diff --git a/DiscordLevelingCard/sandbox.py b/DiscordLevelingCard/sandbox.py
index 4d7ea32..a1eff2f 100644
--- a/DiscordLevelingCard/sandbox.py
+++ b/DiscordLevelingCard/sandbox.py
@@ -1,5 +1,5 @@
from io import BytesIO
-from typing import Optional, Union
+from typing import Optional, Union, List
from aiohttp import ClientSession
from PIL import Image, ImageDraw, ImageFont, ImageColor
@@ -51,6 +51,8 @@ class Sandbox:
-------
- `custom_card1`
Creates a rank card with the first design
+ - `custom_canvas`
+ A blank canvas to make whatever you want!
Raises
------
@@ -212,15 +214,17 @@ async def custom_card1(
return image
- async def custom_card3(
+ async def custom_canvas(
self,
- resize:int = 100,
- senstivity:int = 200,
- card_colour: str = "black",
+ has_background: bool = True,
+ background_colour: str = "black",
+
+ canvas_size: tuple = (1000, 333),
+
+ resize:int = 100,
- border_width: int = 25,
- border_height: int = 25,
+ overlay: Union[None, List] = [[(1000-50, 333-50),(25, 25), "black", 200]],
avatar_frame: str = "curvedborder",
avatar_size: int = 260,
@@ -236,31 +240,40 @@ async def custom_card3(
exp_position: tuple = (775,130),
exp_font_size: int = 50,
+ bar_exp: Union[None, int] = None,
+
+ exp_bar_width: int = 619,
+ exp_bar_height: int = 50,
+ exp_bar_background_colour: Union[str, tuple] = "white",
+ exp_bar_position:tuple = (330, 235),
+ exp_bar_curve: int = 30,
+ extra_text: Union[List, None] = None
+
+
)-> Union[None, bytes]:
"""
Sandbox for third type of card which returns "BytesIO"
Parameters
----------
+ has_background: :class:`bool`
+ Whether to use a background image or not. Default is True
+
+ background_colour: :class:`str`
+ The colour of the background, only used if has_background is set to False. Default is black.
+
+ canvas_size: :class:`tuple`
+ The size of the canvas. Default is (1000, 333)
+
resize: :class:`int`
The percentage to resize the image to. Default is 100
-
- senstivity: :class:`int`
- Change the transparency of the black box over the background image.
- Default is 200.range - [0,255]
+
+ overlay: :class:`list`
+ A list of overlays to be placed on the background. Default is [[(1000-50, 333-50),(25, 25), "black", 200]].
- border_width: :class:`int`
- width of the border. default is 25
-
- border_height: :class:`int`
- height of the border. default is 25
-
avatar_frame: :class:`str`
`circle` `square` `curvedborder` `hexagon` or path to a self created mask.
- card_colour: :class:`str`
- colour of the translucent overlay. Default is black.
-
text_font: :class:`str`
Default is `levelfont.otf` or path to a custom otf or ttf file type font.
@@ -287,15 +300,37 @@ async def custom_card3(
exp_font_size: :class:`int`
font size of the exp. Default is 50.
+
+ exp_bar_width: :class:`int`
+ width of the exp bar. Default is 619.
+
+ exp_bar_height: :class:`int`
+ height of the exp bar. Default is 50.
+
+ exp_bar_background_colour: :class:`str`
+ colour of the exp bar. Default is white.
+
+ exp_bar_position: :class:`tuple`
+ pixel position of the exp bar to be placed at. Default is (330, 235)
+ exp_bar_curve: :class:`int`
+ curve of the exp bar. Default is 30.
+
+ extra_text: :class:`list`
+ list of tuples containing text and position of the text to be placed on the card. Default is None. eg ["string", (x-position, y-position), font-size, "colour"]
+
+ exp_bar: :class:`int`
+ The calculated exp of the user. Default is None.
+
+
Attributes
----------
+ - `has_background`
+ - `background_colour`
+ - `canvas_size`
- `resize`
- - `senstivity`
- - `border_width`
- - `border_height`
+ - `overlay`
- `avatar_frame`
- - `card_colour`
- `text_font`
- `avatar_size`
- `avatar_position`
@@ -305,6 +340,13 @@ async def custom_card3(
- `level_font_size`
- `exp_position`
- `exp_font_size`
+ - `exp_bar_width`
+ - `exp_bar_height`
+ - `exp_bar_background_colour`
+ - `exp_bar_position`
+ - `exp_bar_curve`
+ - `extra_text`
+ - `exp_bar`
"""
path = str(Path(__file__).parent)
@@ -317,9 +359,14 @@ async def custom_card3(
else:
raise TypeError(f"avatar must be a url, not {type(self.avatar)}")
- background = self.background.resize((1000, 333))
- cut = Image.new("RGBA", (1000-(border_width*2), 333-(border_height*2)) , ImageColor.getcolor(card_colour, "RGB")+(senstivity,))
- background.paste(cut, (border_width, border_height) ,cut)
+ if has_background:
+ background = self.background.resize(canvas_size)
+ else:
+ background = Image.new("RGBA", canvas_size, ImageColor.getcolor(background_colour, "RGB"))
+ if overlay is not None:
+ for x in overlay:
+ cut = Image.new("RGBA", x[0] , ImageColor.getcolor(x[2], "RGB")+(x[3],))
+ background.paste(cut, x[1] ,cut)
avatar = self.avatar.resize((avatar_size, avatar_size))
@@ -360,20 +407,30 @@ async def custom_card3(
draw.text(level_position, combined,font=ImageFont.truetype(fontname,level_font_size), fill=self.text_color,stroke_width=1,stroke_fill=(0, 0, 0))
draw.text(username_position, self.username,font=ImageFont.truetype(fontname,username_font_size), fill=self.text_color,stroke_width=1,stroke_fill=(0, 0, 0))
+ if extra_text is not None and type(extra_text) == list:
+ for x in extra_text:
+ draw.text(x[1], x[0],font=ImageFont.truetype(fontname,x[2]), fill=(ImageColor.getcolor(x[3], "RGBA") if type(x[3]) != tuple else extra_text),stroke_width=1,stroke_fill=(0, 0, 0))
+
exp = f"{self._convert_number(self.current_exp)}/{self._convert_number(self.max_exp)}"
draw.text(exp_position, exp,font=ImageFont.truetype(fontname,exp_font_size), fill=self.text_color,stroke_width=1,stroke_fill=(0, 0, 0))
- bar_exp = (self.current_exp/self.max_exp)*619
+ if bar_exp == None:
+ bar_exp = (self.current_exp/self.max_exp)*exp_bar_width
+ exp_bar_curve_custom = exp_bar_curve
+ else:
+ bar_exp = bar_exp*exp_bar_width
+
if bar_exp <= 50:
- bar_exp = 50
+ bar_exp = 50
+ exp_bar_curve_custom = exp_bar_curve//2
- im = Image.new("RGBA", (620, 51))
+ im = Image.new("RGBA", (exp_bar_width+1, exp_bar_height+1))
draw = ImageDraw.Draw(im, "RGBA")
- draw.rounded_rectangle((0, 0, 619, 50), 30, fill=(255,255,255,225))
+ draw.rounded_rectangle((0, 0, exp_bar_width, exp_bar_height), exp_bar_curve, fill=(exp_bar_background_colour if type(exp_bar_background_colour) == tuple else ImageColor.getcolor(exp_bar_background_colour, "RGBA")))
if self.current_exp != 0:
- draw.rounded_rectangle((0, 0, bar_exp, 50), 30, fill=self.bar_color)
-
- background.paste(im, (330, 235), im.convert("RGBA"))
+ draw.rounded_rectangle((0, 0, bar_exp, exp_bar_height), exp_bar_curve_custom, fill=self.bar_color)
+
+ background.paste(im, exp_bar_position, im.convert("RGBA"))
image = BytesIO()
if resize != 100:
diff --git a/DiscordLevelingCard/tester.py b/DiscordLevelingCard/tester.py
index 6f7674d..dd6cdfc 100644
--- a/DiscordLevelingCard/tester.py
+++ b/DiscordLevelingCard/tester.py
@@ -1,10 +1,6 @@
-from io import BytesIO
-from typing import Optional, Union
+from typing import Optional, Union, List
-from aiohttp import ClientSession
-from PIL import Image, ImageDraw, ImageFont
-from .error import InvalidImageUrl
-from pathlib import Path
+from PIL import Image
from .card_settings import Settings
from . import RankCard, Sandbox
@@ -229,15 +225,17 @@ async def test_sandbox_card1(
Image.open(card).save(f"{self.path}.png", "PNG")
return
- async def test_sandbox_card3(
+ async def test_sandbox_custom_canvas(
self,
- resize:int = 100,
- senstivity:int = 200,
- card_colour: str = "black",
+ has_background: bool = True,
+ background_colour: str = "black",
+
+ canvas_size: tuple = (1000, 333),
- border_width: int = 25,
- border_height: int = 25,
+ resize:int = 100,
+
+ overlay: Union[None, List] = [[(1000-50, 333-50),(25, 25), "black", 200]],
avatar_frame: str = "curvedborder",
avatar_size: int = 260,
@@ -252,32 +250,39 @@ async def test_sandbox_card3(
level_font_size: int = 50,
exp_position: tuple = (775,130),
- exp_font_size: int = 50
+ exp_font_size: int = 50,
+ bar_exp: Union[None, int] = None,
+
+ exp_bar_width: int = 619,
+ exp_bar_height: int = 50,
+ exp_bar_background_colour: Union[str, tuple] = "white",
+ exp_bar_position:tuple = (330, 235),
+ exp_bar_curve: int = 30,
+ extra_text: Union[List, None] = None
)->None:
"""test card3 of Sandbox with this method
Parameters
----------
+ has_background: :class:`bool`
+ Whether to use a background image or not. Default is True
+
+ background_colour: :class:`str`
+ The colour of the background, only used if has_background is set to False. Default is black.
+
+ canvas_size: :class:`tuple`
+ The size of the canvas. Default is (1000, 333)
+
resize: :class:`int`
The percentage to resize the image to. Default is 100
-
- senstivity: :class:`int`
- Change the transparency of the black box over the background image.
- Default is 200.range - [0,255]
-
- border_width: :class:`int`
- width of the border. default is 25
-
- border_height: :class:`int`
- height of the border. default is 25
+
+ overlay: :class:`list`
+ A list of overlays to be placed on the background. Default is [[(1000-50, 333-50),(25, 25), "black", 200]].
avatar_frame: :class:`str`
`circle` `square` `curvedborder` `hexagon` or path to a self created mask.
- card_colour: :class:`str`
- colour of the translucent overlay. Default is black.
-
text_font: :class:`str`
Default is `levelfont.otf` or path to a custom otf or ttf file type font.
@@ -304,15 +309,37 @@ async def test_sandbox_card3(
exp_font_size: :class:`int`
font size of the exp. Default is 50.
+
+ exp_bar_width: :class:`int`
+ width of the exp bar. Default is 619.
+
+ exp_bar_height: :class:`int`
+ height of the exp bar. Default is 50.
+
+ exp_bar_background_colour: :class:`str`
+ colour of the exp bar. Default is white.
+
+ exp_bar_position: :class:`tuple`
+ pixel position of the exp bar to be placed at. Default is (330, 235)
+ exp_bar_curve: :class:`int`
+ curve of the exp bar. Default is 30.
+
+ extra_text: :class:`list`
+ list of tuples containing text and position of the text to be placed on the card. Default is None. eg ["string", (x-position, y-position), font-size, "colour"]
+
+ exp_bar: :class:`int`
+ The calculated exp of the user. Default is None.
+
+
Attributes
----------
+ - `has_background`
+ - `background_colour`
+ - `canvas_size`
- `resize`
- - `senstivity`
- - `border_width`
- - `border_height`
+ - `overlay`
- `avatar_frame`
- - `card_colour`
- `text_font`
- `avatar_size`
- `avatar_position`
@@ -322,6 +349,13 @@ async def test_sandbox_card3(
- `level_font_size`
- `exp_position`
- `exp_font_size`
+ - `exp_bar_width`
+ - `exp_bar_height`
+ - `exp_bar_background_colour`
+ - `exp_bar_position`
+ - `exp_bar_curve`
+ - `extra_text`
+ - `exp_bar`
Returns
-------
@@ -338,12 +372,12 @@ async def test_sandbox_card3(
rank=self.rank,
cacheing=self.cacheing
)
- card = await card.custom_card3(
+ card = await card.custom_canvas(
+ has_background=has_background,
+ background_colour=background_colour,
+ canvas_size=canvas_size,
resize=resize,
- card_colour=card_colour,
- senstivity=senstivity,
- border_width=border_width,
- border_height=border_height,
+ overlay=overlay,
avatar_frame=avatar_frame,
avatar_size=avatar_size,
avatar_position=avatar_position,
@@ -353,7 +387,15 @@ async def test_sandbox_card3(
level_position=level_position,
level_font_size=level_font_size,
exp_position=exp_position,
- exp_font_size=exp_font_size
+ exp_font_size=exp_font_size,
+ exp_bar_width=exp_bar_width,
+ exp_bar_height=exp_bar_height,
+ exp_bar_background_colour=exp_bar_background_colour,
+ exp_bar_position=exp_bar_position,
+ exp_bar_curve=exp_bar_curve,
+ extra_text=extra_text,
+ exp_bar=bar_exp
+
)
Image.open(card).save(f"{self.path}.png", "PNG")
return
\ No newline at end of file
diff --git a/Examples/custom card examples/extra canvas example.png b/Examples/custom card examples/extra canvas example.png
new file mode 100644
index 0000000..5e13268
Binary files /dev/null and b/Examples/custom card examples/extra canvas example.png differ
diff --git a/README.md b/README.md
index a334fc3..ec467ff 100644
--- a/README.md
+++ b/README.md
@@ -304,11 +304,11 @@ Sandbox.custom_card1(card_colour:str = "black", resize: int = 100)
- custom_card3 method
+ custom_canvas method
```py
-Sandbox.custom_card3(
+Sandbox.custom_canvas(
resize:int = 100,
senstivity:int = 200,
@@ -336,21 +336,29 @@ Sandbox.custom_card3(
```
## attribute
-- `resize` : resize the final image. (default is 100, treat it as a percentage.)
-- `senstivity` : senstivity of the avatar frame. (default is 200)
-- `card_colour` : color of the card. (default is black)
-- `border_width` : width of the border. (default is 25)
-- `border_height` : height of the border. (default is 25)
-- `avatar_frame` : avatar frame. (default is "curvedborder")
-- `avatar_size` : size of the avatar. (default is 260)
-- `avatar_position` : position of the avatar. (default is (53, 36))
-- `text_font` : font of the text. (default is "levelfont.otf")
-- `username_position` : position of the username. (default is (330,130))
-- `username_font_size` : font size of the username. (default is 50)
-- `level_position` : position of the level. (default is (500,40))
-- `level_font_size` : font size of the level. (default is 50)
-- `exp_position` : position of the exp. (default is (775,130))
-- `exp_font_size` : font size of the exp. (default is 50)
+ - `has_background` : if set to `True` then it will add a background to the image. (default is `True`)
+ - `background_colour` : color of the background. (default is `black`)
+ - `canvas_size` : size of the canvas. (default is `(1000, 333)`)
+ - `resize` : resize the final image. (default is 100, treat it as a percentage.)
+ - `overlay` : A list of overlays to be placed on the background. (Default is `[[(1000-50, 333-50),(25, 25), "black", 200]]`.)
+ - `avatar_frame` : `circle` `square` `curvedborder` `hexagon` or path to a self created mask. (Default is `curvedborder`.)
+ - `text_font` : Default is `levelfont.otf` or path to a custom otf or ttf file type font.
+ - `avatar_size` : size of the avatar. (default is `260`)
+ - `avatar_position` : position of the avatar. (default is `(53, 36)`)
+ - `username_position` : position of the username. (default is `(330,130)`)
+ - `username_font_size` : font size of the username. (default is `50`)
+ - `level_position` : position of the level. (default is `(500,40)`)
+ - `level_font_size` : font size of the level. (default is `50`)
+ - `exp_position` : position of the exp. (default is `(775,130)`)
+ - `exp_font_size` : font size of the exp. (default is `50`)
+ - `exp_bar_width` : width of the exp bar. (default is `619`)
+ - `exp_bar_height` : height of the exp bar. (default is `50`)
+ - `exp_bar_background_colour` : color of the exp bar background. (default is `white`)
+ - `exp_bar_position` : position of the exp bar. (default is `(330, 235)`)
+ - `exp_bar_curve` : curve of the exp bar. (default is `30`)
+ - `extra_text` : A list of extra text to be placed on the image. (Default is `None`.)
+ - `exp_bar` : The calculated exp of the user. (Default is `None`.)
+
## returns
- `bytes` which can directly be used within `discord.File` class.
@@ -358,9 +366,68 @@ Sandbox.custom_card3(
## examples
-![custom_card3](https://raw.githubusercontent.com/krishsharma0413/DiscordLevelingCard/main/Examples/custom%20card%20examples/custom%20card3%20example-1.png)
+![custom_canvas](https://raw.githubusercontent.com/krishsharma0413/DiscordLevelingCard/main/Examples/custom%20card%20examples/custom%20card3%20example-1.png)
+
+![custom_canvas](https://raw.githubusercontent.com/krishsharma0413/DiscordLevelingCard/main/Examples/custom%20card%20examples/custom%20card3%20unholy%20example-2.png)
+
+
+An Example that i really loved was this one, here is the code for it as well. (you might have to tweak a lot to make it work for you though. )
+
+```py
+from DiscordLevelingCard import Sandbox, Settings
+import asyncio
+from PIL import Image
+
+setting = Settings(
+ background="./bg.jpg",
+ bar_color="green",
+ text_color="white")
+
+async def main():
+ rank = Sandbox(
+ username="krishsharma0413",
+ level=1,
+ current_exp=10,
+ max_exp=400,
+ settings=setting,
+ avatar=Image.open("./avatarimg.png")
+ )
+ result = await rank.custom_canvas(
+ avatar_frame="square",
+ avatar_size=233,
+ avatar_position=(50, 50),
+ exp_bar_background_colour = "black",
+ exp_bar_height=50,
+ exp_bar_width=560,
+ exp_bar_curve=0,
+ exp_bar_position=(70, 400),
+ username_position=(320, 50),
+ level_position=(320, 225),
+ exp_position=(70, 330),
+ canvas_size=(700, 500),
+
+ overlay=[[(350, 233),(300, 50), "white", 100],
+ [(600, 170),(50, 300), "white", 100]],
+
+ extra_text=[
+ ["bio-", (320, 110), 25, "white"],
+ ["this can very well be a bio", (320, 140), 25, "white"],
+ ["even mutiple lines!", (320, 170), 25, "white"],
+ ["if we remove bio- even more!", (320, 200), 25, "white"],
+ ]
+
+ )
+
+ # you don't need this line if you are using this in discord.py
+ Image.open(result).save("result.png", "PNG")
+
+
+asyncio.run(main())
+```
+
+and this is how it looks :D
-![custom_card3](https://raw.githubusercontent.com/krishsharma0413/DiscordLevelingCard/main/Examples/custom%20card%20examples/custom%20card3%20unholy%20example-2.png)
+![custom_canvas](https://raw.githubusercontent.com/krishsharma0413/DiscordLevelingCard/main/Examples/custom%20card%20examples/extra%20canvas%20example.png)
diff --git a/pyproject.toml b/pyproject.toml
index 7fb747b..17338a2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "discordlevelingcard"
-version = "0.5.6"
+version = "0.6.0"
readme = "README.md"
description = "A library with leveling cards for your discord bot."
repository = "https://github.com/krishsharma0413/DiscordLevelingCard"