Spaces:
Running on Zero
Running on Zero
| import os | |
| import json | |
| from datetime import datetime, timedelta | |
| import gradio as gr | |
| import spaces | |
| DATA_FILE = "messages.json" | |
| UPLOAD_DIR = "uploads" | |
| os.makedirs(UPLOAD_DIR, exist_ok=True) | |
| # 保留留言的天數(設為 30 天) | |
| RETENTION_DAYS = 30 | |
| def cleanup_old_messages(messages): | |
| """清理超過 Retention Days 的舊留言與對應圖片檔""" | |
| now = datetime.now() | |
| valid_messages = [] | |
| for msg in messages: | |
| try: | |
| # 解析留言時間 (格式: YYYY-MM-DD HH:MM) | |
| msg_time = datetime.strptime(msg["time"], "%Y-%m-%d %H:%M") | |
| # 判斷是否在 30 天內 | |
| if now - msg_time <= timedelta(days=RETENTION_DAYS): | |
| valid_messages.append(msg) | |
| else: | |
| # 已過期,刪除相關圖片實體檔案以釋放空間 | |
| if msg.get("image") and os.path.exists(msg["image"]): | |
| try: | |
| os.remove(msg["image"]) | |
| except Exception as e: | |
| print(f"刪除舊圖片失敗: {e}") | |
| except Exception: | |
| # 若時間解析失敗,預設留存 | |
| valid_messages.append(msg) | |
| return valid_messages | |
| def load_messages(): | |
| if os.path.exists(DATA_FILE): | |
| with open(DATA_FILE, "r", encoding="utf-8") as f: | |
| try: | |
| messages = json.load(f) | |
| # 載入時自動執行一次清理 | |
| cleaned_messages = cleanup_old_messages(messages) | |
| if len(cleaned_messages) != len(messages): | |
| save_messages(cleaned_messages) | |
| return cleaned_messages | |
| except Exception: | |
| return [] | |
| return [] | |
| def save_messages(messages): | |
| with open(DATA_FILE, "w", encoding="utf-8") as f: | |
| json.dump(messages, f, ensure_ascii=False, indent=2) | |
| def dummy_gpu_task(): | |
| return True | |
| def add_post(author, text, image): | |
| author = author.strip() if author and author.strip() else "匿名成員" | |
| img_path = None | |
| if image is not None: | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| img_path = os.path.join(UPLOAD_DIR, f"{timestamp}.png") | |
| image.save(img_path) | |
| # 讀取並自動清理舊資料 | |
| messages = load_messages() | |
| messages.insert(0, { | |
| "author": author, | |
| "text": text, | |
| "image": img_path, | |
| "time": datetime.now().strftime("%Y-%m-%d %H:%M") | |
| }) | |
| # 儲存前再次確保只留 30 天內的資料 | |
| messages = cleanup_old_messages(messages) | |
| save_messages(messages) | |
| return "", "", None, *get_board_data() | |
| def get_board_data(): | |
| messages = load_messages() | |
| text_logs = [] | |
| gallery_images = [] | |
| for msg in messages: | |
| text_logs.append(f"📌 {msg['author']}({msg['time']})\n{msg['text']}\n" + "—"*25) | |
| if msg.get('image') and os.path.exists(msg['image']): | |
| gallery_images.append((msg['image'], f"{msg['author']} 的分享 ({msg['time']})")) | |
| full_text = "\n\n".join(text_logs) if text_logs else "目前尚無留言(近 30 天)。" | |
| return full_text, gallery_images | |
| with gr.Blocks(title="家庭佈告欄") as demo: | |
| gr.Markdown("# 🏡 家庭成員佈告欄") | |
| gr.Markdown("💡 *系統將自動保留最近 30 天內的留言與照片,過期內容會自動清除以清理空間。*") | |
| with gr.Row(): | |
| with gr.Column(): | |
| author_input = gr.Textbox(label="你的稱呼", placeholder="例如:媽媽、小明") | |
| text_input = gr.Textbox(label="留言內容", lines=3, placeholder="想跟大家說什麼?") | |
| image_input = gr.Image(label="上傳照片(可選)", type="pil") | |
| submit_btn = gr.Button("發布動態", variant="primary") | |
| with gr.Column(): | |
| init_text, init_gallery = get_board_data() | |
| board_text = gr.Textbox(value=init_text, label="留言記錄(近30天)", lines=8, interactive=False) | |
| board_gallery = gr.Gallery(value=init_gallery, label="照片牆") | |
| refresh_btn = gr.Button("🔄 重新整理") | |
| submit_btn.click( | |
| fn=add_post, | |
| inputs=[author_input, text_input, image_input], | |
| outputs=[author_input, text_input, image_input, board_text, board_gallery] | |
| ) | |
| refresh_btn.click( | |
| fn=get_board_data, | |
| outputs=[board_text, board_gallery] | |
| ) | |
| demo.launch() |