def GenerateImage(self, date: str, itemShop: dict): """ Generate the Item Shop image using the provided Item Shop. Return True if image sucessfully saved. """ try: featured = itemShop["featured"]["entries"] daily = itemShop["daily"]["entries"] if (len(featured) <= 0) or (len(daily) <= 0): raise Exception( f"Featured: {len(featured)}, Daily: {len(daily)}") if (len(featured) >= 1): width = 6 height = max(ceil(len(featured) / 3), ceil(len(daily) / 3)) rowsDaily = 3 rowsFeatured = 3 dailyStartX = ((340 * 3)) if (len(featured) >= 18): width = 9 height = max(ceil(len(featured) / 6), ceil(len(daily) / 6)) rowsDaily = 3 rowsFeatured = 6 dailyStartX = ((340 * 6)) if (len(featured) >= 18) and (len(daily) >= 18): width = 12 height = max(ceil(len(featured) / 6), ceil(len(daily) / 6)) rowsDaily = 6 rowsFeatured = 6 dailyStartX = ((340 * 6) + 100) except Exception as e: log.critical( f"Failed to parse Item Shop Featured and Daily items, {e}") return False # Determine the max amount of rows required for the current # Item Shop when there are 3 columns for both Featured and Daily. # This allows us to determine the image height. # rows = max(ceil(len(featured) / 3), ceil(len(daily) / 3)) shopImage = Image.new("RGB", (((340 * width) - 30), (530 * height) + 350)) try: background = ImageUtil.Open(self, "background.png").convert("RGBA") background = ImageUtil.RatioResize(self, background, shopImage.width, shopImage.height) shopImage.paste( background, ImageUtil.CenterX(self, background.width, shopImage.width)) except FileNotFoundError: log.warn("Failed to open background.png, defaulting to dark gray") shopImage.paste((18, 18, 18), [0, 0, shopImage.size[0], shopImage.size[1]]) logo = ImageUtil.Open(self, "logo.png").convert("RGBA") logo = ImageUtil.RatioResize(self, logo, 0, 210) shopImage.paste( logo, ImageUtil.CenterX(self, logo.width, shopImage.width, 20), logo) canvas = ImageDraw.Draw(shopImage) font = ImageUtil.Font(self, 48) textWidth, _ = font.getsize(date) canvas.text( ImageUtil.CenterX(self, textWidth, shopImage.width, 255), date, (255, 255, 255), font=font, ) canvas.text((20, 255), "Destacados", (255, 255, 255), font=font) textWidth, _ = font.getsize("Daily") canvas.text( (shopImage.width - (textWidth + 30), 255), "Diario", (255, 255, 255), font=font, ) # Track grid position i = 0 for item in featured: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (20 + ((i % rowsFeatured) * (310 + 20))), (350 + ((i // rowsFeatured) * (510 + 20))), ), card, ) i += 1 # Reset grid position i = 0 for item in daily: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (dailyStartX + ((i % rowsDaily) * (310 + 20))), (350 + ((i // rowsDaily) * (510 + 20))), ), card, ) i += 1 try: shopImage.save("itemshop.png") log.info("Imagen generada de la Tienda de Objetos") return True except Exception as e: log.critical(f"Failed to save Item Shop image, {e}")
def GenerateImage(self, date: str, itemShop: dict): """ Generate the Item Shop image using the provided Item Shop. Return True if image sucessfully saved. """ try: featured = itemShop["featured"] daily = itemShop["daily"] # Ensure both Featured and Daily have at least 1 item if (len(featured) <= 0) or (len(daily) <= 0): raise Exception( f"Featured: {len(featured)}, Daily: {len(daily)}") except Exception as e: log.critical( f"Failed to parse Item Shop Featured and Daily items, {e}") return False # Determine the max amount of rows required for the current # Item Shop when there are 3 columns for both Featured and Daily. # This allows us to determine the image height. featured_length = (FEATURED_COLUMNS * CARD_WIDTH) + ( (FEATURED_COLUMNS - 1) * CARD_OFFSET) daily_length = (DAILY_COLUMNS * CARD_WIDTH) + ( (DAILY_COLUMNS - 1) * CARD_OFFSET) columns_length = featured_length + daily_length rows = max(ceil(len(featured) / FEATURED_COLUMNS), ceil(len(daily) / DAILY_COLUMNS)) shopImage = Image.new( IMAGE_LOAD_TYPE, (columns_length + SECTION_SPACING, ((CARD_HEIGHT * rows) + 340) + (rows - 1) * CARD_OFFSET + logo_footer_offset + logo_footer_height)) try: background = ImageUtil.Open(self, "background.png") background = ImageUtil.RatioResize(self, background, shopImage.width, shopImage.height) shopImage.paste( background, ImageUtil.CenterX(self, background.width, shopImage.width)) except FileNotFoundError: log.warning( "Failed to open background.png, defaulting to dark gray") shopImage.paste((18, 18, 18), [0, 0, shopImage.size[0], shopImage.size[1]]) logo = ImageUtil.Open(self, logo_header_name) logo = ImageUtil.RatioResize(self, logo, 0, logo_header_height) shopImage.paste( logo, ImageUtil.CenterX(self, logo.width, shopImage.width, 20), logo) logo_footer = ImageUtil.Open(self, logo_footer_name) logo_footer = ImageUtil.RatioResize(self, logo_footer, 0, logo_footer_height) shopImage.paste( logo_footer, ImageUtil.CenterX(self, logo_footer.width, shopImage.width, shopImage.height - logo_footer.height - 20), logo_footer) canvas = ImageDraw.Draw(shopImage) font = ImageUtil.Font(self, 58) textWidth, _ = font.getsize(date.upper()) canvas.text( ImageUtil.CenterX(self, textWidth, shopImage.width, 255), date.upper(), (255, 255, 255), font=font, ) canvas.text((LEFT_OFFSET, 255), "IN EVIDENZA", (255, 255, 255), font=font) textWidth, _ = font.getsize("GIORNALIERO") canvas.text( (shopImage.width - (textWidth + LEFT_OFFSET), 255), "GIORNALIERO", (255, 255, 255), font=font, ) # Track grid position i = 0 for item in featured: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (LEFT_OFFSET + ((i % FEATURED_COLUMNS) * (card.width + CARD_OFFSET))), (LEADING_OFFSET + ((i // FEATURED_COLUMNS) * (card.height + CARD_OFFSET))), ), card, ) i += 1 # Reset grid position i = 0 DAILY_SPACING = SECTION_SPACING + featured_length - LEFT_OFFSET for item in daily: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (DAILY_SPACING + ((i % DAILY_COLUMNS) * (card.width + CARD_OFFSET))), (LEADING_OFFSET + ((i // DAILY_COLUMNS) * (card.height + CARD_OFFSET))), ), card, ) i += 1 try: shopImage.save(image_saved_name) log.info("Generated Item Shop image") return True except Exception as e: log.critical(f"Failed to save Item Shop image, {e}")
def GenerateCard(self, item: dict): """Return the card image for the provided Fortnite Item Shop item.""" try: name = item["items"][0]["name"] rarity = item["items"][0]["rarity"]["value"] category = item["items"][0]["type"]["value"] price = item["finalPrice"] if item["items"][0]["images"]["featured"] is not None: icon = item["items"][0]["images"]["featured"] else: icon = item["items"][0]["images"]["icon"] except Exception as e: log.error(f"Failed to parse item {name}, {e}") return if rarity == "frozen": blendColor = (148, 223, 255) elif rarity == "lava": blendColor = (234, 141, 35) elif rarity == "legendary": blendColor = (211, 120, 65) elif rarity == "dark": blendColor = (251, 34, 223) elif rarity == "starwars": blendColor = (231, 196, 19) elif rarity == "marvel": blendColor = (197, 51, 52) elif rarity == "slurp": blendColor = (0, 242, 213) elif rarity == "dc": blendColor = (84, 117, 199) elif rarity == "icon": blendColor = (54, 183, 183) elif rarity == "shadow": blendColor = (113, 113, 113) elif rarity == "epic": blendColor = (177, 91, 226) elif rarity == "rare": blendColor = (73, 172, 242) elif rarity == "uncommon": blendColor = (96, 170, 58) elif rarity == "common": blendColor = (190, 190, 190) elif rarity == "gaminglegends": blendColor = (42, 0, 168) else: blendColor = (255, 255, 255) card = Image.new("RGBA", (300, 545)) try: layer = ImageUtil.Open( self, f"shopitem_background_{rarity}.png").convert("RGBA") except FileNotFoundError: log.warn( f"Failed to open shopitem_background_{rarity}.png, defaulted to Common" ) layer = ImageUtil.Open(self, "shopitem_background_common.png") card.paste(layer) icon = ImageUtil.Download(self, icon).convert("RGBA") if (category == "outfit") or (category == "emote"): icon = ImageUtil.RatioResize(self, icon, 285, 365) elif category == "wrap": icon = ImageUtil.RatioResize(self, icon, 230, 310) else: icon = ImageUtil.RatioResize(self, icon, 310, 390) if (category == "outfit") or (category == "emote"): card.paste(icon, ImageUtil.CenterX(self, icon.width, card.width), icon) else: card.paste(icon, ImageUtil.CenterX(self, icon.width, card.width, 15), icon) if len(item["items"]) > 1: # Track grid position i = 0 # Start at position 1 in items array for extra in item["items"][1:]: try: extraRarity = extra["rarity"]["value"] extraIcon = extra["images"]["smallIcon"] except Exception as e: log.error(f"Failed to parse item {name}, {e}") return try: layer = ImageUtil.Open( self, f"box_bottom_{extraRarity}.png").convert("RGBA") except FileNotFoundError: log.warn( f"Failed to open box_bottom_{extraRarity}.png, defaulted to Common" ) layer = ImageUtil.Open(self, "box_bottom_common.png") card.paste( layer, ( (card.width - (layer.width + 9)), (9 + ((i // 1) * (layer.height))), ), ) extraIcon = ImageUtil.Download(self, extraIcon).convert("RGBA") extraIcon = ImageUtil.RatioResize(self, extraIcon, 75, 75) card.paste( extraIcon, ( (card.width - (layer.width + 9)), (9 + ((i // 1) * (extraIcon.height))), ), extraIcon, ) try: layer = ImageUtil.Open(self, f"box_faceplate_{extraRarity}.png") except FileNotFoundError: log.warn( f"Failed to open box_faceplate_{extraRarity}.png, defaulted to Common" ) layer = ImageUtil.Open(self, "box_faceplate_common.png") card.paste( layer, ( (card.width - (layer.width + 9)), (9 + ((i // 1) * (layer.height))), ), layer, ) i += 1 try: layer = ImageUtil.Open( self, f"shopitem_card_{rarity}.png").convert("RGBA") except FileNotFoundError: log.warn( f"Failed to open shopitem_card_{rarity}.png, defaulted to Common" ) layer = ImageUtil.Open(self, "cshopitem_card_common.png") card.paste(layer, layer) card.paste(layer, layer) canvas = ImageDraw.Draw(card) font = ImageUtil.Font(self, 33) textWidth, _ = font.getsize(f"{category} {rarity}") canvas.text( ImageUtil.CenterX(self, textWidth, card.width, 385), f"", blendColor, font=font, ) vbucks = ImageUtil.Open(self, "vbucks_card.png").convert("RGBA") vbucks = ImageUtil.RatioResize(self, vbucks, 49, 49) price = str(f"{price:,}") textWidth, _ = font.getsize(price) canvas.text( ImageUtil.CenterX(self, ((textWidth + 15) - vbucks.width), card.width, 450), price, blendColor, font=font, ) card.paste( vbucks, ImageUtil.CenterX(self, (vbucks.width + (textWidth - 290)), card.width, 436), vbucks, ) font = ImageUtil.Font(self, 56) textWidth, _ = font.getsize(name) change = 0 if textWidth >= 270: # Ensure that the item name does not overflow font, textWidth, change = ImageUtil.FitTextX(self, name, 56, 260) canvas.text( ImageUtil.CenterX(self, textWidth, card.width, (380 + (change / 2))), name, (255, 255, 255), font=font, ) return card
def GenerateImage(self, date: str, itemShop: dict): """ Generate the Item Shop image using the provided Item Shop. Return True if image sucessfully saved. """ try: featured = itemShop["featured"] daily = itemShop["daily"] # Ensure both Featured and Daily have at least 1 item if (len(featured) <= 0) or (len(daily) <= 0): raise Exception( f"Featured: {len(featured)}, Daily: {len(daily)}") except Exception as e: Log.Error( self, f"Failed to parse Item Shop Featured and Daily items, {e}") return False # Determine the max amount of rows required for the current # Item Shop when there are 3 columns for both Featured and Daily. # This allows us to determine the image height. rows = max(ceil(len(featured) / 3), ceil(len(daily) / 3)) shopImage = Image.new("RGB", (1920, ((545 * rows) + 340))) try: background = ImageUtil.Open(self, "background.png") background = ImageUtil.RatioResize(self, background, shopImage.width, shopImage.height) shopImage.paste( background, ImageUtil.CenterX(self, background.width, shopImage.width)) except FileNotFoundError: Log.Warn(self, "Failed to open background.png, defaulting to dark gray") shopImage.paste((18, 18, 18), [0, 0, shopImage.size[0], shopImage.size[1]]) logo = ImageUtil.Open(self, "logo.png") logo = ImageUtil.RatioResize(self, logo, 0, 210) shopImage.paste( logo, ImageUtil.CenterX(self, logo.width, shopImage.width, 20), logo) canvas = ImageDraw.Draw(shopImage) font = ImageUtil.Font(self, 48) textWidth, _ = font.getsize(date) canvas.text( ImageUtil.CenterX(self, textWidth, shopImage.width, 255), date, (255, 255, 255), font=font, ) canvas.text((20, 255), "Featured", (255, 255, 255), font=font) textWidth, _ = font.getsize("Daily") canvas.text( (shopImage.width - (textWidth + 20), 255), "Daily", (255, 255, 255), font=font, ) # Track grid position i = 0 for item in featured: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (20 + ((i % 3) * (card.width + 5))), (315 + ((i // 3) * (card.height + 5))), ), card, ) i += 1 # Reset grid position i = 0 for item in daily: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (990 + ((i % 3) * (card.width + 5))), (315 + ((i // 3) * (card.height + 5))), ), card, ) i += 1 try: shopImage.save("itemshop.png") Log.Success(self, "Generated Item Shop image") return True except Exception as e: Log.Error(self, f"Failed to save Item Shop image, {e}")
def GenerateCard(self, item: dict): """Return the card image for the provided Fortnite Item Shop item.""" try: name = item["items"][0]["name"] rarity = item["items"][0]["rarity"] displayrarity = item["items"][0]["displayRarity"] category = item["items"][0]["type"] price = str(item["finalPrice"]) if (category == "outfit") or (category == "wrap"): if item["items"][0]["images"]["featured"] is not None: icon = item["items"][0]["images"]["featured"]["url"] else: icon = item["items"][0]["images"]["icon"]["url"] else: icon = item["items"][0]["images"]["icon"]["url"] except Exception as e: Log.Error(self, f"Failed to parse item {name}, {e}") return if rarity == "common": blendColor = (190, 190, 190) elif rarity == "uncommon": blendColor = (96, 170, 58) elif rarity == "rare": blendColor = (73, 172, 242) elif rarity == "epic": blendColor = (177, 91, 226) elif rarity == "legendary": blendColor = (211, 120, 65) elif rarity == "marvel": blendColor = (197, 51, 52) elif rarity == "dark": blendColor = (251, 34, 223) elif rarity == "dc": blendColor = (84, 117, 199) else: blendColor = (255, 255, 255) card = Image.new("RGBA", (300, 545)) try: layer = ImageUtil.Open(self, f"card_top_{rarity.lower()}.png") except FileNotFoundError: Log.Warn( self, f"Failed to open card_top_{rarity.lower()}.png, defaulted to Common", ) layer = ImageUtil.Open(self, "card_top_common.png") card.paste(layer) if category == 'glider': x = 285 / 1.1 y = 365 / 1.8 distanceTop = 60 elif category == 'music': x = 285 / 1.1 y = 365 / 1.6 distanceTop = 55 elif category == 'pickaxe': x = 285 / 1.1 y = 365 / 1.3 distanceTop = 40 elif category == 'wrap': x = 285 / 1.1 y = 365 / 1.3 distanceTop = 40 else: x = 285 y = 365 distanceTop = 10 icon = ImageUtil.Download(self, icon) icon = ImageUtil.RatioResize(self, icon, x, y) card.paste( icon, ImageUtil.CenterX(self, icon.width, card.width, distanceTop=distanceTop), icon) if len(item["items"]) > 1: # Track grid position i = 0 # Start at position 1 in items array for extra in item["items"][1:]: try: extraRarity = extra["rarity"] extraIcon = extra["images"]["smallIcon"]["url"] except Exception as e: Log.Error(self, f"Failed to parse item {name}, {e}") return try: layer = ImageUtil.Open( self, f"box_bottom_{extraRarity.lower()}.png") except FileNotFoundError: Log.Warn( self, f"Failed to open box_bottom_{extraRarity.lower()}.png, defaulted to Common", ) layer = ImageUtil.Open(self, "box_bottom_common.png") card.paste(layer, (17, (17 + ((i // 1) * (layer.height))))) extraIcon = ImageUtil.Download(self, extraIcon) extraIcon = ImageUtil.RatioResize(self, extraIcon, 75, 75) card.paste(extraIcon, (17, (17 + ((i // 1) * (extraIcon.height)))), extraIcon) try: layer = ImageUtil.Open( self, f"box_faceplate_{extraRarity.lower()}.png") except FileNotFoundError: Log.Warn( self, f"Failed to open box_faceplate_{extraRarity.lower()}.png, defaulted to Common", ) layer = ImageUtil.Open(self, "box_faceplate_common.png") card.paste(layer, (17, (17 + ((i // 1) * (layer.height)))), layer) i += 1 try: layer = ImageUtil.Open(self, f"card_faceplate_{rarity.lower()}.png") except FileNotFoundError: Log.Warn( self, f"Failed to open card_faceplate_{rarity.lower()}.png, defaulted to Common", ) layer = ImageUtil.Open(self, "card_faceplate_common.png") card.paste(layer, layer) try: layer = ImageUtil.Open(self, f"card_bottom_{rarity.lower()}.png") except FileNotFoundError: Log.Warn( self, f"Failed to open card_bottom_{rarity.lower()}.png, defaulted to Common", ) layer = ImageUtil.Open(self, "card_bottom_common.png") card.paste(layer, layer) canvas = ImageDraw.Draw(card) font = ImageUtil.Font(self, 30) textWidth, _ = font.getsize(f"{displayrarity} {category.title()}") canvas.text( ImageUtil.CenterX(self, textWidth, card.width, 385), f"{displayrarity} {category.title()}", blendColor, font=font, ) vbucks = ImageUtil.Open(self, "vbucks.png") vbucks = ImageUtil.RatioResize(self, vbucks, 25, 25) textWidth, _ = font.getsize(price) canvas.text( ImageUtil.CenterX(self, ((textWidth - 5) - vbucks.width), card.width, 495), price, (255, 255, 255), font=font, ) card.paste( vbucks, ImageUtil.CenterX(self, (vbucks.width + (textWidth + 5)), card.width, 495), vbucks, ) font = ImageUtil.Font(self, 56) textWidth, _ = font.getsize(name) if textWidth >= 270: # Ensure that the item name does not overflow font, textWidth = ImageUtil.FitTextX(self, name, 56, 265) canvas.text( ImageUtil.CenterX(self, textWidth, card.width, 425), name, (255, 255, 255), font=font, ) return card
def GenerateImage(self, date: str, itemShop: dict): """ Generate the Item Shop image using the provided Item Shop. Return True if image sucessfully saved. """ try: featured = itemShop["featured"] + itemShop["specialFeatured"] daily = itemShop["daily"] + itemShop["specialDaily"] if (len(featured) <= 0) or (len(daily) <= 0): raise Exception( f"Featured: {len(featured)}, Daily: {len(daily)}") if (len(featured) >= 1): width = 6 height = max(ceil(len(featured) / 3), ceil(len(daily) / 3)) rowsDaily = 3 rowsFeatured = 3 dailyStartX = ((340 * 3)) if (len(featured) >= 18): width = 9 height = max(ceil(len(featured) / 6), ceil(len(daily) / 6)) rowsDaily = 3 rowsFeatured = 6 dailyStartX = ((340 * 6)) if (len(featured) >= 18) and (len(daily) >= 18): width = 12 height = max(ceil(len(featured) / 6), ceil(len(daily) / 6)) rowsDaily = 6 rowsFeatured = 6 dailyStartX = ((340 * 6) + 100) except Exception as e: log.critical(f"Failed to parse Item Shop Featured and Daily items, {e}") return False # Determine the max amount of rows required for the current # Item Shop when there are 3 columns for both Featured and Daily. # This allows us to determine the image height. shopImage = Image.new("RGB", (((340 * width) - 30), (530 * height) + 350)) try: background = ImageUtil.Open(self, "background.png") background = ImageUtil.RatioResize( self, background, shopImage.width, shopImage.height ) shopImage.paste( background, ImageUtil.CenterX( self, background.width, shopImage.width) ) except FileNotFoundError: log.warning( "Failed to open background.png, defaulting to dark gray") shopImage.paste( (34, 37, 40), [0, 0, shopImage.size[0], shopImage.size[1]]) canvas = ImageDraw.Draw(shopImage) font = ImageUtil.Font(self, 80) textWidth, _ = font.getsize("FORTNITE ITEM SHOP") canvas.text(ImageUtil.CenterX(self, textWidth, shopImage.width, 30), "FORTNITE ITEM SHOP", (255, 255, 255), font=font) textWidth, _ = font.getsize(date.upper()) canvas.text(ImageUtil.CenterX(self, textWidth, shopImage.width, 120), date.upper(), (255, 255, 255), font=font) canvas.text((20, 240), "FEATURED", (255, 255, 255), font=font, anchor=None, spacing=4, align="left") canvas.text((shopImage.width - 230, 240), "DAILY", (255, 255, 255), font=font, anchor=None, spacing=4, align="right") # Track grid position i = 0 for item in featured: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (20 + ((i % rowsFeatured) * (310 + 20))), (350 + ((i // rowsFeatured) * (510 + 20))), ), card, ) i += 1 # Reset grid position i = 0 for item in daily: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (dailyStartX + ((i % rowsDaily) * (310 + 20))), (350 + ((i // rowsDaily) * (510 + 20))), ), card, ) i += 1 try: shopImage.save("itemshop.jpeg", optimize=True,quality=85) if(itemShop["fullShop"] == False): log.info("Some cosmetics are missing from this shop!") log.info("Generated Item Shop image") return True except Exception as e: log.critical(f"Failed to save Item Shop image, {e}")
def GenerateCard(self, item: dict): """Return the card image for the provided Fortnite Item Shop item.""" try: name = item["name"].lower() rarity = item["rarity"].lower() category = item["type"].lower() price = item["price"] if (item["image"]): icon = item["image"] else: icon = item["icon"] except Exception as e: log.error(f"Failed to parse item {name}, {e}") return if rarity == "frozen series": blendColor = (148, 223, 255) rarity = "Frozen" elif rarity == "lava series": blendColor = (234, 141, 35) rarity = "Lava" elif rarity == "legendary": blendColor = (211, 120, 65) rarity = "Legendary" elif rarity == "slurp series": blendColor = (0, 233, 176) rarity = "Slurp" elif rarity == "dark": blendColor = (251, 34, 223) rarity = "Dark" elif rarity == "star wars series": blendColor = (231, 196, 19) rarity = "Star Wars" elif rarity == "marvel": blendColor = (197, 51, 52) rarity = "Marvel" elif rarity == "dc": blendColor = (84, 117, 199) rarity = "DC" elif rarity == "icon series": blendColor = (54, 183, 183) rarity = "Icon" elif rarity == "shadow series": blendColor = (113, 113, 113) rarity = "Shadow" elif rarity == "platform series": blendColor = (117,129,209) rarity = "GamingLegends" elif rarity == "epic": blendColor = (177, 91, 226) rarity = "Epic" elif rarity == "rare": blendColor = (73, 172, 242) rarity = "Rare" elif rarity == "uncommon": blendColor = (96, 170, 58) rarity = "Uncommon" elif rarity == "common": blendColor = (190, 190, 190) rarity = "Common" else: blendColor = (255, 255, 255) rarity = "Unknown" card = Image.new("RGBA", (310, 510)) try: layer = ImageUtil.Open( self, f"./shopTemplates/{rarity.capitalize()}BG.png") except FileNotFoundError: log.warn( f"Failed to open {rarity.capitalize()}BG.png, defaulted to Common") layer = ImageUtil.Open(self, "./shopTemplates/CommonBG.png") card.paste(layer) icon = ImageUtil.Download(self, icon) if (category == "outfit") or (category == "emote"): icon = ImageUtil.RatioResize(self, icon, 285, 365) elif category == "wrap": icon = ImageUtil.RatioResize(self, icon, 230, 310) else: icon = ImageUtil.RatioResize(self, icon, 310, 390) if (category == "outfit") or (category == "emote"): card.paste(icon, ImageUtil.CenterX(self, icon.width, card.width), icon) else: card.paste(icon, ImageUtil.CenterX(self, icon.width, card.width, 15), icon) try: layer = ImageUtil.Open( self, f"./shopTemplates/{rarity.capitalize()}OV.png") except FileNotFoundError: log.warn( f"Failed to open {rarity.capitalize()}OV.png, defaulted to Common") layer = ImageUtil.Open(self, "./shopTemplates/CommonOV.png") card.paste(layer, layer) canvas = ImageDraw.Draw(card) vbucks = ImageUtil.Open(self, "vbucks.png") vbucks = ImageUtil.RatioResize(self, vbucks, 40, 40) font = ImageUtil.Font(self, 40) price = str(f"{price:,}") textWidth, _ = font.getsize(price) canvas.text(ImageUtil.CenterX(self, ((textWidth - 5) - vbucks.width), card.width, 347), price, (255, 255, 255), font=font) card.paste(vbucks,ImageUtil.CenterX(self, (vbucks.width + (textWidth + 5)), card.width, 350),vbucks) font = ImageUtil.Font(self, 40) itemName = name.upper().replace(" OUTFIT", "").replace(" PICKAXE", "").replace(" BUNDLE", "") if(category == "bundle"): itemName = name.upper().replace(" BUNDLE", "") textWidth, _ = font.getsize(itemName) change = 0 if textWidth >= 280: # Ensure that the item name does not overflow font, textWidth, change = ImageUtil.FitTextX(self, itemName, 40, 260) canvas.text(ImageUtil.CenterX(self, textWidth, card.width, (400 + (change / 2))), itemName, (255, 255, 255), font=font) font = ImageUtil.Font(self, 40) textWidth, _ = font.getsize(f"{category.upper()}") change = 0 if textWidth >= 280: # Ensure that the item rarity/type does not overflow font, textWidth, change = ImageUtil.FitTextX(self, f"{category.upper()}", 30, 260) canvas.text(ImageUtil.CenterX(self, textWidth, card.width, (450 + (change / 2))), f"{category.upper()}", blendColor, font=font) return card
def GenerateImage(self, date: str, itemShop: dict): """ Generate the Item Shop image using the provided Item Shop. Return True if image sucessfully saved. """ if itemShop["featured"] != None: featured = itemShop["featured"]["entries"] else: featured = [] if itemShop["daily"] != None: daily = itemShop["daily"]["entries"] else: daily = [] if itemShop["specialFeatured"] != None: specialFeatured = itemShop["specialFeatured"]["entries"] else: specialFeatured = [] if itemShop["specialDaily"] != None: specialDaily = itemShop["specialDaily"]["entries"] else: specialDaily = [] # Determine the max amount of rows required for the current # Item Shop when there are 3 columns for both Featured and Daily. # This allows us to determine the image height. rows = max(ceil((len(featured) + len(specialFeatured)) / 3), ceil((len(daily) + len(specialDaily)) / 3)) shopImage = Image.new("RGB", (1920, ((545 * rows) + 340))) try: background = ImageUtil.Open(self, "background.png") background = ImageUtil.RatioResize(self, background, shopImage.width, shopImage.height) shopImage.paste( background, ImageUtil.CenterX(self, background.width, shopImage.width)) except FileNotFoundError: log.warn("Failed to open background.png, defaulting to dark gray") shopImage.paste((18, 18, 18), [0, 0, shopImage.size[0], shopImage.size[1]]) logo = ImageUtil.Open(self, "logo.png") logo = ImageUtil.RatioResize(self, logo, 0, 210) shopImage.paste( logo, ImageUtil.CenterX(self, logo.width, shopImage.width, 20), logo) canvas = ImageDraw.Draw(shopImage) font = ImageUtil.Font(self, 48) textWidth, _ = font.getsize(date) canvas.text( ImageUtil.CenterX(self, textWidth, shopImage.width, 255), date, (255, 255, 255), font=font, ) featureds = itemShop["featured"]["name"] dailys = itemShop["daily"]["name"] canvas.text((20, 255), f"{featureds}", (255, 255, 255), font=font) textWidth, _ = font.getsize(f"{dailys}") canvas.text( (shopImage.width - (textWidth + 20), 255), f"{dailys}", (255, 255, 255), font=font, ) # Track grid position i = 0 for item in specialFeatured: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (20 + ((i % 3) * (card.width + 5))), (315 + ((i // 3) * (card.height + 5))), ), card, ) i += 1 for item in featured: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (20 + ((i % 3) * (card.width + 5))), (315 + ((i // 3) * (card.height + 5))), ), card, ) i += 1 # Reset grid position i = 0 for item in specialDaily: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (990 + ((i % 3) * (card.width + 5))), (315 + ((i // 3) * (card.height + 5))), ), card, ) i += 1 for item in daily: card = Athena.GenerateCard(self, item) if card is not None: shopImage.paste( card, ( (990 + ((i % 3) * (card.width + 5))), (315 + ((i // 3) * (card.height + 5))), ), card, ) i += 1 try: shopImage.save("itemshop.png") log.info("Generated Item Shop image") return True except Exception as e: log.critical(f"Failed to save Item Shop image, {e}")