We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/princefishthrower/orly-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
import json, os, re, requests, random
from PIL import Image, ImageDraw, ImageFont
import datetime
from orly_generator.cache import get, set, clear # Import cache functions directly
from fontTools.ttLib import TTFont
def get_text_size(draw, text, font, multiline=False):
"""Helper function to get text size compatible with both old and new Pillow versions"""
if multiline:
# For multiline text, we need to handle it differently
lines = text.split('\n')
total_width = 0
total_height = 0
for line in lines:
bbox = draw.textbbox((0, 0), line, font=font)
line_width = bbox[2] - bbox[0]
line_height = bbox[3] - bbox[1]
total_width = max(total_width, line_width)
total_height += line_height
return total_width, total_height
else:
bbox = draw.textbbox((0, 0), text, font=font)
return bbox[2] - bbox[0], bbox[3] - bbox[1]
def generate_image(title, topText, author, image_code, theme, guide_text_placement='bottom_right', guide_text='The Definitive Guide', scale=1.0):
cache_string = title + "_" + topText + "_" + author + "_" + image_code + "_" + theme + "_" + guide_text_placement + "_" + guide_text + "_" + str(scale)
cached = get(cache_string)
if cached:
print("Cache hit")
try:
final_path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), ('%s.png'%datetime.datetime.now())))
width = int(500 * scale)
height = int(700 * scale)
im = Image.frombytes('RGBA', (width, height), cached)
im.save(final_path)
im.close()
return final_path
except Exception as e:
print(str(e))
else:
print("Cache miss")
themeColors = {
"0" : (85,19,93,255),
"1" : (113,112,110,255),
"2" : (128,27,42,255),
"3" : (184,7,33,255),
"4" : (101,22,28,255),
"5" : (80,61,189,255),
"6" : (225,17,5,255),
"7" : (6,123,176,255),
"8" : (247,181,0,255),
"9" : (0,15,118,255),
"10" : (168,0,155,255),
"11" : (0,132,69,255),
"12" : (0,153,157,255),
"13" : (1,66,132,255),
"14" : (177,0,52,255),
"15" : (55,142,25,255),
"16" : (133,152,0,255),
}
themeColor = themeColors[theme]
# Base dimensions: 500x700, scaled by the scale parameter
width = int(500 * scale)
height = int(700 * scale)
im = Image.new('RGBA', (width, height), "white")
font_path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'fonts', 'Garamond Light.ttf'))
font_path_helv = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'fonts', 'HelveticaNeue-Medium.otf'))
font_path_helv_bold = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'fonts', 'Helvetica Bold.ttf'))
font_path_italic = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'fonts', 'Garamond LightItalic.ttf'))
# Font sizes scaled by the scale parameter
topFont = ImageFont.truetype(font_path_italic, int(20 * scale))
subtitleFont = ImageFont.truetype(font_path_italic, int(34 * scale))
authorFont = ImageFont.truetype(font_path_italic, int(24 * scale))
titleFont = ImageFont.truetype(font_path, int(62 * scale))
oriellyFont = ImageFont.truetype(font_path_helv, int(28 * scale))
questionMarkFont = ImageFont.truetype(font_path_helv_bold, int(16 * scale))
dr = ImageDraw.Draw(im)
dr.rectangle(((int(20*scale),0),(width-int(20*scale),int(10*scale))), fill=themeColor)
topText = sanitzie_unicode(topText, font_path_italic)
textWidth, textHeight = get_text_size(dr, topText, topFont)
textPositionX = (width/2) - (textWidth/2)
dr.text((textPositionX,int(10*scale)), topText, fill='black', font=topFont)
author = sanitzie_unicode(author, font_path_italic)
textWidth, textHeight = get_text_size(dr, author, authorFont)
textPositionX = width - textWidth - int(20*scale)
textPositionY = height - textHeight - int(20*scale)
dr.text((textPositionX,textPositionY), author, fill='black', font=authorFont)
oreillyText = "O RLY"
textWidth, textHeight = get_text_size(dr, oreillyText, oriellyFont)
textPositionX = int(20*scale)
textPositionY = height - textHeight - int(20*scale)
dr.text((textPositionX,textPositionY), oreillyText, fill='black', font=oriellyFont)
oreillyText = "?"
textPositionX = textPositionX + textWidth
dr.text((textPositionX,textPositionY-1), oreillyText, fill=themeColor, font=questionMarkFont)
titleFont, newTitle = clamp_title_text(sanitzie_unicode(title, font_path), width-int(80*scale), scale)
if newTitle == None:
raise ValueError('Title too long')
textWidth, textHeight = get_text_size(dr, newTitle, titleFont, multiline=True)
title_box_y = int(400 * scale)
dr.rectangle([(int(20*scale),title_box_y),(width-int(20*scale),title_box_y + textHeight + int(40*scale))], fill=themeColor)
subtitle = sanitzie_unicode(guide_text, font_path_italic)
if guide_text_placement == 'top_left':
textWidth, textHeight = get_text_size(dr, subtitle, subtitleFont)
textPositionX = int(20*scale)
textPositionY = title_box_y - textHeight - int(2*scale)
elif guide_text_placement == 'top_right':
textWidth, textHeight = get_text_size(dr, subtitle, subtitleFont)
textPositionX = width - int(20*scale) - textWidth
textPositionY = title_box_y - textHeight - int(2*scale)
elif guide_text_placement == 'bottom_left':
textPositionY = title_box_y + textHeight + int(40*scale)
textWidth, textHeight = get_text_size(dr, subtitle, subtitleFont)
textPositionX = int(20*scale)
else:#bottom_right is default
textPositionY = title_box_y + textHeight + int(40*scale)
textWidth, textHeight = get_text_size(dr, subtitle, subtitleFont)
textPositionX = width - int(20*scale) - textWidth
dr.text((textPositionX,textPositionY), subtitle, fill='black', font=subtitleFont)
dr.multiline_text((int(40*scale),title_box_y + int(20*scale)), newTitle, fill='white', font=titleFont)
cover_image_path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'images', ('%s.png'%image_code)))
coverImage = Image.open(cover_image_path).convert('RGBA')
# Scale the animal image by the scale parameter
original_size = coverImage.size
scaled_size = (int(original_size[0] * scale), int(original_size[1] * scale))
coverImage = coverImage.resize(scaled_size, Image.LANCZOS)
offset = (int(80*scale),int(40*scale))
im.paste(coverImage, offset, coverImage)
final_path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), ('%s.png'%datetime.datetime.now())))
im.save(final_path)
set(cache_string, im.tobytes())
im.close()
return final_path
def clamp_title_text(title, width, scale=3.0):
im = Image.new('RGBA', (int(500*scale),int(500*scale)), "white")
dr = ImageDraw.Draw(im)
font_path_italic = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'fonts', 'Garamond Light.ttf'))
#try and fit title on one line
font = None
startFontSize = int(80 * scale)
endFontSize = int(61 * scale)
for fontSize in range(startFontSize,endFontSize,-1):
font = ImageFont.truetype(font_path_italic, fontSize)
w, h = get_text_size(dr, title, font)
if w < width:
return font, title
#try and fit title on two lines
startFontSize = int(80 * scale)
endFontSize = int(34 * scale)
for fontSize in range(startFontSize,endFontSize,-1):
font = ImageFont.truetype(font_path_italic, fontSize)
for match in list(re.finditer(r'\s',title, re.UNICODE)):
newTitle = ''.join((title[:match.start()], '\n', title[(match.start()+1):]))
substringWidth, h = get_text_size(dr, newTitle, font, multiline=True)
if substringWidth < width:
return font, newTitle
im.close()
return None, None
def sanitzie_unicode(string, font_file_path):
sanitized_string = ''
font = TTFont(font_file_path)
cmap = font['cmap'].getcmap(3,1).cmap
for char in string:
code_point = ord(char)
if code_point in cmap.keys():
sanitized_string = ''.join((sanitized_string,char))
return sanitized_string