127 lines
4.0 KiB
Python
127 lines
4.0 KiB
Python
from flask import Flask, render_template, request, redirect, url_for
|
|
|
|
# 🌟 IMPORT THE content from separate files.
|
|
from content.posts import BLOG_POSTS
|
|
from content.about_text import ABOUT, TITLE
|
|
app = Flask(__name__)
|
|
|
|
|
|
import csv
|
|
import datetime
|
|
import os, math
|
|
|
|
COMMENT_FILE = 'content/comments.csv'
|
|
MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024 # 5 Megabytes
|
|
POSTS_PER_PAGE = 5 # posts per page limit here
|
|
|
|
def get_comments_for_post(post_id):
|
|
comments = []
|
|
if os.path.exists(COMMENT_FILE) and os.path.getsize(COMMENT_FILE) > MAX_FILE_SIZE_BYTES:
|
|
return ["Comment section full.", 507]
|
|
if not os.path.exists(COMMENT_FILE):
|
|
return comments
|
|
|
|
with open(COMMENT_FILE, 'r', encoding='utf-8') as f:
|
|
reader = csv.DictReader(f)
|
|
for row in reader:
|
|
if row['post_id'] == str(post_id):
|
|
comments.append(row)
|
|
return comments
|
|
|
|
@app.route('/post/<int:post_id>/comment', methods=['POST'])
|
|
def post_comment(post_id):
|
|
# 1. Security: Check Honeypot
|
|
if request.form.get('honeypot'):
|
|
return redirect(url_for('post_detail', post_id=post_id))
|
|
|
|
# 2. Get Data
|
|
author = request.form.get('author', 'Anonymous').strip()
|
|
content = request.form.get('content', '').strip()
|
|
|
|
# 3. Validation (Keep it lightweight)
|
|
if not content or len(content) > 1000: # Max 1000 chars to save disk/RAM
|
|
return redirect(url_for('post_detail', post_id=post_id))
|
|
|
|
# 4. Save to CSV
|
|
file_exists = os.path.isfile(COMMENT_FILE)
|
|
# check max size
|
|
if file_exists and os.path.getsize(COMMENT_FILE) > MAX_FILE_SIZE_BYTES:
|
|
return
|
|
|
|
with open(COMMENT_FILE, 'a', newline='', encoding='utf-8') as f:
|
|
writer = csv.DictWriter(f, fieldnames=['post_id', 'author', 'content', 'date'])
|
|
if not file_exists:
|
|
writer.writeheader()
|
|
|
|
writer.writerow({
|
|
'post_id': post_id,
|
|
'author': author[:50], # Truncate long names
|
|
'content': content,
|
|
'date': datetime.datetime.now().strftime("%B %d, %Y at %I:%M %p")
|
|
})
|
|
|
|
return redirect(url_for('post_detail', post_id=post_id))
|
|
# --- Routes ---
|
|
|
|
|
|
@app.route('/')
|
|
def home():
|
|
page = request.args.get('page', 1, type=int)
|
|
blog_title = TITLE
|
|
|
|
# 2. Sort posts by ID newest first
|
|
all_posts = sorted(BLOG_POSTS, key=lambda x: x['id'], reverse=True)
|
|
# Calculate totals
|
|
total_posts = len(all_posts)
|
|
total_pages = math.ceil(total_posts / POSTS_PER_PAGE)
|
|
# 3. Calculate start and end indices
|
|
start = (page - 1) * POSTS_PER_PAGE
|
|
end = start + POSTS_PER_PAGE
|
|
|
|
# 4. Slice the list for the current page
|
|
posts_to_show = all_posts[start:end]
|
|
|
|
# 5. Determine if there is a next or previous page
|
|
prev_url = url_for('home', page=page - 1) if page > 1 else None
|
|
next_url = url_for('home', page=page + 1) if end < len(all_posts) else None
|
|
|
|
return render_template('index.html',
|
|
posts=posts_to_show,
|
|
prev_url=prev_url,
|
|
next_url=next_url,
|
|
current_page=page,
|
|
blog_title=blog_title,
|
|
total_pages=total_pages)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/about')
|
|
def about():
|
|
about_txt = ABOUT
|
|
"""Renders the About page."""
|
|
return render_template('about.html', about_txt = about_txt, blog_title = TITLE)
|
|
|
|
|
|
@app.route('/post/<int:post_id>')
|
|
def post_detail(post_id):
|
|
"""Renders a single post detail page."""
|
|
|
|
# 1. Look up the post dictionary
|
|
post = next((p for p in BLOG_POSTS if p['id'] == post_id), None)
|
|
|
|
if post is None:
|
|
return "Post not found", 404
|
|
#get comments
|
|
comments = get_comments_for_post(post_id)
|
|
if post["id"] == 10:
|
|
|
|
post["template"] = "components/timeline_post.html"
|
|
|
|
|
|
# 2. Pass the post dictionary (with the raw HTML content) directly to the template
|
|
return render_template('post_detail.html', post=post, comments=comments, blog_title = TITLE)
|
|
if __name__ == '__main__':
|
|
app.run(debug=True) |