daily-ai-art / app.py
3morixd's picture
Upload app.py with huggingface_hub
1749a54 verified
Raw
History Blame Contribute Delete
10.9 kB
"""
Dispatch AI — Daily AI Image Drop
Auto-generates a new AI art piece daily. Shows date, prompt used, image.
Archive of past 30 days. Uses FLUX.1-schnell.
"""
import os
import io
import json
import datetime
import hashlib
import gradio as gr
from huggingface_hub import InferenceClient
from PIL import Image, ImageDraw
# --- Configuration -----------------------------------------------------------
HF_TOKEN = os.environ.get("HF_TOKEN", None)
MODEL_ID = "black-forest-labs/FLUX.1-schnell"
client = InferenceClient(model=MODEL_ID, token=HF_TOKEN)
BG_COLOR = "#0A0F1A"
ACCENT = "#1FE0E6"
# Directory for archive
ARCHIVE_DIR = os.path.join(os.getcwd(), "archive")
os.makedirs(ARCHIVE_DIR, exist_ok=True)
# Daily prompts — 30 curated art prompts cycling through the month
DAILY_PROMPTS = [
"A majestic falcon soaring over the Dubai skyline at golden hour, Burj Khalifa in the background, cinematic, ultra detailed",
"An ancient pearl diver in the Arabian Gulf, traditional dhow boat, underwater scene with pearls glowing, ethereal lighting",
"Bedouin camp under a starry desert sky, campfire glowing, camels resting, Milky Way overhead, peaceful atmosphere",
"Modern Dubai at night from above, neon-lit skyscrapers, flying cars, cyberpunk meets Arabian luxury, blade runner style",
"Traditional Arabian wind tower (barjeel) architecture, old Dubai district, warm sunlight, golden hour, detailed stonework",
"A majestic falcon perched on a gloved hand in the desert, piercing eyes, feather detail, warm sunset, wildlife photography",
"Underwater pearl diving scene, traditional Emirati diver holding an oyster shell, bioluminescent water, dreamlike",
"A caravan of camels crossing the Empty Quarter desert at dawn, long shadows on sand dunes, golden light",
"Dubai Marina at blue hour, luxury yachts, modern architecture, reflections on water, ultra detailed cityscape",
"An old souk in Dubai, spices and textiles hanging, warm lantern light, bustling atmosphere, orientalist painting style",
"Arabian stallion galloping through the desert at sunset, dust kicking up, dramatic lighting, powerful, ultra detailed",
"A traditional Emirati coffee ceremony (gahwa), dallah pot pouring into finjan, dates on a brass tray, warm intimate lighting",
"Sheikh Zayed Grand Mosque at night, illuminated domes and minarets, reflecting pool, serene and majestic",
"Falconry scene in the UAE desert, falcon taking off from handler's wrist, motion blur, golden hour",
"Al Ain oasis with date palms and aflaj water channels, lush green in the desert, peaceful, golden afternoon light",
"Abu Dhabi Corniche at sunset, modern skyline, calm sea, families walking, warm and inviting atmosphere",
"Henna being applied in intricate patterns, close-up of hands, traditional Emirati setting, warm lighting, detailed",
"A dhow race in the Dubai Creek, traditional boats with white sails, dramatic sky, action shot",
"The Burj Al Arab sail-shaped hotel at sunset, glowing pink and gold sky, calm sea reflections, luxury aesthetic",
"Emirati women in traditional abayas and burqas walking through a date palm plantation, warm sunlight filtering through palms",
"Liwa desert sand dunes at sunrise, wind-rippled sand, golden orange glow, minimalist composition, fine art photography",
"Old Dubai wind tower district (Bastakiya), narrow alleyways, traditional courtyard, warm and inviting",
"Arabian oryx in the desert, elegant white antelope, pristine landscape, wildlife photography, golden hour",
"Dubai Frame at night, glowing golden frame structure, old and new city visible through it, dramatic",
"A traditional Emirati wedding celebration, henna, dancing, warm lantern light, joyous atmosphere, orientalist style",
"Sharjah's King Faisal Mosque at dawn, soft blue light, call to prayer atmosphere, peaceful and serene",
"Jebel Jais mountain range at sunrise, mist in the valleys, dramatic rock formations, cool blue tones",
"Arabic coffee (gahwa) and dates on a traditional rug in the desert, campfire, stars, intimate and warm",
"The UAE flag waving proudly against a clear blue sky, on top of a mountain, dramatic and patriotic",
"Sunset over the Empty Quarter, endless sand dunes, purple and orange sky, lone camel caravan, epic",
]
def get_daily_prompt(date_str=None):
"""Get the prompt for a specific date (or today)."""
if date_str is None:
date_str = datetime.date.today().isoformat()
# Use date to deterministically pick a prompt
day_hash = int(hashlib.md5(date_str.encode()).hexdigest(), 16)
return DAILY_PROMPTS[day_hash % len(DAILY_PROMPTS)]
def get_today_image():
"""Generate or load today's image."""
today = datetime.date.today().isoformat()
archive_path = os.path.join(ARCHIVE_DIR, f"{today}.png")
meta_path = os.path.join(ARCHIVE_DIR, f"{today}.json")
# If already generated, load from archive
if os.path.exists(archive_path) and os.path.exists(meta_path):
try:
img = Image.open(archive_path)
with open(meta_path) as f:
meta = json.load(f)
prompt = meta.get("prompt", "")
return img, f"📅 {today}", prompt, "✅ Loaded from archive"
except Exception:
pass
# Generate new
prompt = get_daily_prompt(today)
w, h = 1024, 1024
try:
image = client.text_to_image(prompt, width=w, height=h)
if not isinstance(image, Image.Image):
image = Image.open(io.BytesIO(image)) if hasattr(image, "read") else Image.open(image)
# Save to archive
image.save(archive_path)
with open(meta_path, "w") as f:
json.dump({"date": today, "prompt": prompt}, f, indent=2)
return image, f"📅 {today}", prompt, "✅ Today's image generated!"
except Exception as e:
img = Image.new("RGB", (w, h), BG_COLOR)
d = ImageDraw.Draw(img)
d.text((w // 4, h // 2), f"Error: {str(e)[:50]}", fill=ACCENT)
return img, f"📅 {today}", prompt, f"❌ Error: {str(e)}"
def get_archive():
"""Load all archived images."""
archives = []
if os.path.exists(ARCHIVE_DIR):
for f in sorted(os.listdir(ARCHIVE_DIR), reverse=True):
if f.endswith(".png"):
date_str = f.replace(".png", "")
meta_path = os.path.join(ARCHIVE_DIR, f"{date_str}.json")
prompt = ""
if os.path.exists(meta_path):
try:
with open(meta_path) as mf:
meta = json.load(mf)
prompt = meta.get("prompt", "")[:80] + "..." if len(meta.get("prompt", "")) > 80 else meta.get("prompt", "")
except Exception:
pass
archives.append({
"date": date_str,
"prompt": prompt,
"image_path": os.path.join(ARCHIVE_DIR, f),
})
return archives[:30] # Last 30
def build_archive_gallery():
"""Build gallery data for the archive tab."""
archives = get_archive()
if not archives:
return [], "No archived images yet. Click 'Generate Today's Image' first."
gallery_items = [(a["image_path"], a["date"]) for a in archives]
summary = f"### 📚 Archive — {len(archives)} image(s)\n\n"
for a in archives[:10]:
summary += f"- **{a['date']}** — {a['prompt']}\n"
if len(archives) > 10:
summary += f"\n...and {len(archives) - 10} more"
return gallery_items, summary
# --- UI -----------------------------------------------------------------------
CSS = """
#dispatch-header h1 {
color: #FFFFFF; font-size: 2.2rem; margin: 0;
background: linear-gradient(90deg, #1FE0E6 0%, #FFFFFF 60%);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
}
#dispatch-header p { color: #1FE0E6; font-size: 1.05rem; margin: 6px 0 0 0; }
.dispatch-footer { text-align: center; color: #8A8F9C; font-size: 0.9rem; padding-top: 8px; }
"""
with gr.Blocks(
title="Dispatch AI — Daily AI Image Drop",
theme=gr.themes.Base(
primary_hue="cyan", secondary_hue="cyan", neutral_hue="slate",
font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui"],
).set(
body_background_fill="#0A0F1A", body_background_fill_dark="#0A0F1A",
body_text_color="#FFFFFF", body_text_color_dark="#FFFFFF",
block_background_fill="#0E1424", block_background_fill_dark="#0E1424",
block_border_color="#1FE0E6", block_border_width="1px",
block_label_text_color="#1FE0E6", block_title_text_color="#1FE0E6",
button_primary_background_fill="#1FE0E6", button_primary_background_fill_dark="#1FE0E6",
button_primary_text_color="#0A0F1A", button_primary_border_color="#1FE0E6",
input_background_fill="#0E1424", input_background_fill_dark="#0E1424",
input_border_color="#1FE0E6", input_border_width="1px",
),
css=CSS,
) as demo:
with gr.Column(elem_id="dispatch-header"):
gr.Markdown(
"""
# Dispatch AI — Daily AI Image Drop
A new AI art piece every day · FLUX.1-schnell · Dispatch AI (FZE) · UAE
"""
)
with gr.Tab("🖼️ Today's Drop"):
with gr.Row():
generate_btn = gr.Button("🎨 Generate/Load Today's Image", variant="primary")
with gr.Row():
with gr.Column(scale=2):
today_image = gr.Image(label="Today's Art", type="pil", show_download_button=True)
with gr.Column(scale=1):
date_box = gr.Textbox(label="Date", interactive=False)
prompt_box = gr.Textbox(label="Prompt Used", interactive=False, lines=4)
status_box = gr.Textbox(label="Status", interactive=False)
with gr.Tab("📚 Archive (30 days)"):
with gr.Row():
refresh_archive_btn = gr.Button("🔄 Refresh Archive", variant="secondary")
archive_gallery = gr.Gallery(
label="Past Art Drops", show_label=True,
columns=4, height=600, object_fit="cover",
)
archive_summary = gr.Markdown()
# Events
generate_btn.click(
get_today_image,
outputs=[today_image, date_box, prompt_box, status_box],
)
refresh_archive_btn.click(
build_archive_gallery,
outputs=[archive_gallery, archive_summary],
)
gr.Markdown(
"""
<div class="dispatch-footer">
© 2026 Dispatch AI (FZE) · Sharjah, UAE · License 10818 ·
Model: FLUX.1-schnell · A new art piece is generated daily and archived for 30 days
</div>
"""
)
if __name__ == "__main__":
demo.queue()
demo.launch()