|
import re |
|
from datetime import datetime |
|
from flask import url_for |
|
from slugify import slugify |
|
|
|
def format_datetime(dt): |
|
"""Format datetime for display""" |
|
if not dt: |
|
return "" |
|
|
|
now = datetime.utcnow() |
|
diff = now - dt |
|
|
|
if diff.days == 0: |
|
|
|
if diff.seconds < 60: |
|
return "Just now" |
|
if diff.seconds < 3600: |
|
minutes = diff.seconds // 60 |
|
return f"{minutes} minute{'s' if minutes != 1 else ''} ago" |
|
else: |
|
hours = diff.seconds // 3600 |
|
return f"{hours} hour{'s' if hours != 1 else ''} ago" |
|
elif diff.days == 1: |
|
return "Yesterday" |
|
elif diff.days < 7: |
|
return f"{diff.days} days ago" |
|
else: |
|
return dt.strftime("%b %d, %Y") |
|
|
|
def get_username_for_mention(text): |
|
"""Extract username from a @mention""" |
|
pattern = r'@([a-zA-Z0-9_]+)' |
|
matches = re.findall(pattern, text) |
|
return matches |
|
|
|
def make_url_slug(text): |
|
"""Create a URL-friendly slug from text""" |
|
return slugify(text) |
|
|
|
def truncate_text(text, length=100): |
|
"""Truncate text to specified length and add ellipsis if needed""" |
|
if len(text) <= length: |
|
return text |
|
return text[:length].rsplit(' ', 1)[0] + '...' |
|
|
|
def get_avatar_url(avatar_filename): |
|
"""Get the URL for user avatar""" |
|
if not avatar_filename or avatar_filename == 'default.png': |
|
return url_for('static', filename='uploads/avatars/default.png') |
|
return url_for('static', filename=f'uploads/avatars/{avatar_filename}') |
|
|
|
def parse_bbcode(text): |
|
"""Convert basic BBCode to HTML (simple implementation)""" |
|
|
|
text = re.sub(r'\[b\](.*?)\[/b\]', r'<strong>\1</strong>', text) |
|
|
|
text = re.sub(r'\[i\](.*?)\[/i\]', r'<em>\1</em>', text) |
|
|
|
text = re.sub(r'\[u\](.*?)\[/u\]', r'<u>\1</u>', text) |
|
|
|
text = re.sub(r'\[url=(.*?)\](.*?)\[/url\]', r'<a href="\1" target="_blank">\2</a>', text) |
|
text = re.sub(r'\[url\](.*?)\[/url\]', r'<a href="\1" target="_blank">\1</a>', text) |
|
|
|
text = re.sub(r'\[img\](.*?)\[/img\]', r'<img src="\1" alt="User posted image" class="img-fluid">', text) |
|
|
|
text = re.sub(r'\[code\](.*?)\[/code\]', r'<pre><code>\1</code></pre>', text, flags=re.DOTALL) |
|
|
|
text = re.sub(r'\[quote\](.*?)\[/quote\]', r'<blockquote>\1</blockquote>', text, flags=re.DOTALL) |
|
text = re.sub(r'\[quote=(.*?)\](.*?)\[/quote\]', r'<blockquote>\2<footer>\1</footer></blockquote>', text, flags=re.DOTALL) |
|
|
|
return text |
|
|