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: # Today 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)""" # Bold text = re.sub(r'\[b\](.*?)\[/b\]', r'\1', text) # Italic text = re.sub(r'\[i\](.*?)\[/i\]', r'\1', text) # Underline text = re.sub(r'\[u\](.*?)\[/u\]', r'\1', text) # URLs text = re.sub(r'\[url=(.*?)\](.*?)\[/url\]', r'\2', text) text = re.sub(r'\[url\](.*?)\[/url\]', r'\1', text) # Images text = re.sub(r'\[img\](.*?)\[/img\]', r'User posted image', text) # Code blocks text = re.sub(r'\[code\](.*?)\[/code\]', r'
\1
', text, flags=re.DOTALL) # Quotes text = re.sub(r'\[quote\](.*?)\[/quote\]', r'
\1
', text, flags=re.DOTALL) text = re.sub(r'\[quote=(.*?)\](.*?)\[/quote\]', r'
\2
', text, flags=re.DOTALL) return text