generated from nathanwoodburn/python-webserver-template
parent
25280e9c02
commit
b38436deba
@ -2,4 +2,5 @@ flask
|
||||
gunicorn
|
||||
requests
|
||||
python-dotenv
|
||||
pytz
|
||||
pytz
|
||||
Pillow
|
93
server.py
93
server.py
@ -9,6 +9,7 @@ from flask import (
|
||||
render_template,
|
||||
send_from_directory,
|
||||
send_file,
|
||||
Response
|
||||
)
|
||||
import os
|
||||
import json
|
||||
@ -18,6 +19,9 @@ import dotenv
|
||||
from pytz import timezone
|
||||
import pytz
|
||||
import re
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import io
|
||||
import urllib.parse
|
||||
|
||||
|
||||
dotenv.load_dotenv()
|
||||
@ -78,7 +82,20 @@ def wellknown(path):
|
||||
# region Main routes
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template("index.html")
|
||||
from_tz = request.args.get('from_tz', '')
|
||||
time = request.args.get('time', '')
|
||||
to_tzs = request.args.get('to_tzs', '')
|
||||
|
||||
# Generate the OG image URL based on the parameters
|
||||
# Make sure to encode the parameters
|
||||
from_tz = urllib.parse.quote(from_tz)
|
||||
time = urllib.parse.quote(time)
|
||||
to_tzs = urllib.parse.quote(to_tzs)
|
||||
|
||||
|
||||
og_image = f"og_image?from_tz={from_tz}&time={time}&to_tzs={to_tzs}"
|
||||
|
||||
return render_template("index.html", og_image=og_image)
|
||||
|
||||
# Mapping of short timezone names to full names
|
||||
SHORT_TZ_MAP = {
|
||||
@ -193,6 +210,80 @@ def convert_multiple():
|
||||
|
||||
return jsonify(results)
|
||||
|
||||
@app.route("/og_image")
|
||||
def og_image():
|
||||
from_tz = request.args.get('from_tz', 'Unknown')
|
||||
time = request.args.get('time', 'Unknown')
|
||||
to_tzs = request.args.get('to_tzs', 'Unknown')
|
||||
|
||||
# Load the background image
|
||||
img_path = "templates/assets/img/og_image.webp"
|
||||
img = Image.open(img_path).convert("RGBA")
|
||||
d = ImageDraw.Draw(img)
|
||||
|
||||
# Convert time format to 12-hour format and add AM/PM
|
||||
try:
|
||||
input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S")
|
||||
except ValueError:
|
||||
input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M")
|
||||
time = input_time.strftime("%I:%M %p")
|
||||
|
||||
|
||||
|
||||
# Prepare text
|
||||
text = f"{time} {from_tz.replace("_","/")}"
|
||||
|
||||
from_tz = get_full_timezone(from_tz.replace("_", "/"))
|
||||
|
||||
# Check if multiple timezones are provided
|
||||
if "," in to_tzs:
|
||||
to_tzs = to_tzs.split(",")
|
||||
to_tz_list = [(tz, get_full_timezone(tz.replace("_", "/"))) for tz in to_tzs if len(tz) > 0]
|
||||
else:
|
||||
to_tz_list = [(to_tzs, get_full_timezone(to_tzs.replace("_", "/")))]
|
||||
|
||||
if from_tz is None or any(tz[1] is None for tz in to_tz_list):
|
||||
return send_from_directory("templates/assets/img", "og_image.webp")
|
||||
|
||||
|
||||
|
||||
for tz in to_tz_list:
|
||||
to_tz = tz[1]
|
||||
to_tz_time = from_tz.localize(input_time).astimezone(to_tz)
|
||||
text += f"\n{to_tz_time.strftime('%I:%M %p')} {tz[0].replace('_','/')}"
|
||||
|
||||
|
||||
|
||||
font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
|
||||
font_size = 200
|
||||
# Shrink font size if text is too long
|
||||
if (max(len(line) for line in text.split("\n")) > 13):
|
||||
font_size = 150
|
||||
|
||||
font_size -= (len(text.split("\n")) - 4) * 10
|
||||
|
||||
|
||||
|
||||
font = ImageFont.truetype(font_path, font_size)
|
||||
|
||||
text_bbox = d.textbbox((0, 0), text, font=font)
|
||||
text_width = text_bbox[2] - text_bbox[0]
|
||||
text_height = text_bbox[3] - text_bbox[1]
|
||||
|
||||
# Calculate text position
|
||||
x = (img.width - text_width) / 2
|
||||
y = (img.height - text_height) / 2
|
||||
|
||||
# Add text to the image
|
||||
d.text((x, y), text, fill=(255, 255, 255), font=font, align="center")
|
||||
|
||||
# Save the image to a BytesIO object in WebP format
|
||||
img_io = io.BytesIO()
|
||||
img.save(img_io, 'WEBP')
|
||||
img_io.seek(0)
|
||||
|
||||
return Response(img_io, mimetype='image/webp')
|
||||
|
||||
@app.route("/<path:path>")
|
||||
def catch_all(path: str):
|
||||
if os.path.isfile("templates/" + path):
|
||||
|
BIN
templates/assets/img/og_image.webp
Normal file
BIN
templates/assets/img/og_image.webp
Normal file
Binary file not shown.
After ![]() (image error) Size: 112 KiB |
@ -7,6 +7,22 @@
|
||||
<title>Time Converter</title>
|
||||
<link rel="icon" href="/assets/img/favicon.png" type="image/png">
|
||||
<link rel="stylesheet" href="/assets/css/index.css">
|
||||
<!-- og meta -->
|
||||
<meta property="og:type" value="website" />
|
||||
<meta property="og:title" value="Timezone Converter" />
|
||||
<meta property="og:description" value="Convert between timezone | Nathan.Woodburn/" />
|
||||
<meta property="og:url" value="https://time.c.woodburn.au" />
|
||||
<meta property="og:image" value="https://time.c.woodburn.au/{{ og_image }}" />
|
||||
<meta property="og:image:alt" value="Convert between timezone image" />
|
||||
|
||||
<!-- twitter meta -->
|
||||
<meta name="twitter:card" value="summary" />
|
||||
<meta name="twitter:site" value="@woodburn_nathan" />
|
||||
<meta name="twitter:creator" value="@woodburn_nathan" />
|
||||
<meta name="twitter:title" value="Timezone Converter" />
|
||||
<meta name="twitter:description" value="Convert between timezone | Nathan.Woodburn/" />
|
||||
<meta name="twitter:image" value="/{{ og_image }}" />
|
||||
<meta name="twitter:image:alt" value="Convert between timezone image" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
Loading…
Reference in New Issue
Block a user