from flask import Flask, render_template_string, request, redirect, url_for, session, flash, jsonify from flask_caching import Cache import json import os import logging import threading import time from datetime import datetime, timedelta from huggingface_hub import HfApi, hf_hub_download from werkzeug.utils import secure_filename import random app = Flask(__name__) app.secret_key = os.getenv("FLASK_SECRET_KEY", "supersecretkey") DATA_FILE = 'data_adusis.json' REPO_ID = "Eluza133/A12d12s12" # Use your actual repo ID HF_TOKEN_WRITE = os.getenv("HF_TOKEN") HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE cache = Cache(app, config={'CACHE_TYPE': 'simple'}) logging.basicConfig(level=logging.INFO) @cache.memoize(timeout=300) def load_data(): try: download_db_from_hf() with open(DATA_FILE, 'r', encoding='utf-8') as file: data = json.load(file) if not isinstance(data, dict): logging.warning("Data is not in dict format, initializing an empty database") return {'posts': [], 'users': {}, 'general_chat': [], 'private_chats': {}} data.setdefault('posts', []) data.setdefault('users', {}) data.setdefault('general_chat', []) data.setdefault('private_chats', {}) for user in data['users']: data['users'][user].setdefault('last_chat_visit', '1970-01-01 00:00:00') data['users'][user].setdefault('last_private_visit', '1970-01-01 00:00:00') data['users'][user].setdefault('last_seen', '1970-01-01 00:00:00') logging.info("Data loaded successfully") return data except Exception as e: logging.error(f"Error loading data: {e}") return {'posts': [], 'users': {}, 'general_chat': [], 'private_chats': {}} def save_data(data): try: with open(DATA_FILE, 'w', encoding='utf-8') as file: json.dump(data, file, ensure_ascii=False, indent=4) upload_db_to_hf() cache.clear() logging.info("Data saved and uploaded to HF") except Exception as e: logging.error(f"Error saving data: {e}") raise def upload_db_to_hf(): try: api = HfApi() api.upload_file( path_or_fileobj=DATA_FILE, path_in_repo=DATA_FILE, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Backup {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" ) logging.info("Database uploaded to Hugging Face") except Exception as e: logging.error(f"Error uploading database: {e}") def download_db_from_hf(): try: hf_hub_download( repo_id=REPO_ID, filename=DATA_FILE, repo_type="dataset", token=HF_TOKEN_READ, local_dir=".", local_dir_use_symlinks=False ) logging.info("Database downloaded from Hugging Face") except Exception as e: logging.error(f"Error downloading database: {e}") if not os.path.exists(DATA_FILE): with open(DATA_FILE, 'w', encoding='utf-8') as f: json.dump({'posts': [], 'users': {}, 'general_chat': [], 'private_chats': {}}, f) def periodic_backup(): while True: upload_db_to_hf() time.sleep(1800) def get_unread_count(data, username): if username not in data['users']: return 0 last_visit = datetime.strptime(data['users'][username]['last_chat_visit'], '%Y-%m-%d %H:%M:%S') return sum(1 for msg in data['general_chat'] if datetime.strptime(msg['time'], '%Y-%m-%d %H:%M:%S') > last_visit) def get_private_unread_count(data, username): if username not in data['users']: return 0 last_visit = datetime.strptime(data['users'][username]['last_private_visit'], '%Y-%m-%d %H:%M:%S') unread = 0 for chat_key, messages in data['private_chats'].items(): users = chat_key.split('_') if username in users: unread += sum(1 for msg in messages if datetime.strptime(msg['time'], '%Y-%m-%d %H:%M:%S') > last_visit and msg['sender'] != username) return unread def is_user_online(data, username): if username not in data['users']: return False last_seen = datetime.strptime(data['users'][username]['last_seen'], '%Y-%m-%d %H:%M:%S') return (datetime.now() - last_seen).total_seconds() < 300 def update_last_seen(data, username): if username in data['users']: data['users'][username]['last_seen'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') save_data(data) BASE_STYLE = ''' :root { --primary: #ff4d6d; --secondary: #00ddeb; --accent: #8b5cf6; --background-light: #f5f6fa; --background-dark: #1a1625; --card-bg: rgba(255, 255, 255, 0.95); --card-bg-dark: rgba(40, 35, 60, 0.95); --text-light: #2a1e5a; --text-dark: #e8e1ff; --shadow: 0 10px 30px rgba(0, 0, 0, 0.2); --glass-bg: rgba(255, 255, 255, 0.15); --transition: all 0.3s ease; --online: #34c759; --offline: #ff3b30; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', sans-serif; background: var(--background-light); color: var(--text-light); line-height: 1.6; overflow-x: hidden; } body.dark { background: var(--background-dark); color: var(--text-dark); } .sidebar { position: fixed; top: 0; left: 0; width: 300px; height: 100%; background: var(--glass-bg); backdrop-filter: blur(20px); padding: 25px; box-shadow: var(--shadow); z-index: 1000; transition: transform var(--transition); } .sidebar.hidden { transform: translateX(-100%); } .sidebar-header { display: flex; align-items: center; gap: 15px; margin-bottom: 35px; } .nav-brand { font-size: 1.8em; font-weight: 900; background: linear-gradient(135deg, var(--primary), var(--accent)); -webkit-background-clip: text; color: transparent; } .logo { width: 40px; height: 40px; border-radius: 14px; box-shadow: var(--shadow); } .nav-links { display: flex; flex-direction: column; gap: 15px; } .nav-link { display: flex; align-items: center; gap: 15px; padding: 14px 25px; background: var(--card-bg); color: var(--text-light); text-decoration: none; border-radius: 14px; font-size: 1.1em; font-weight: 600; transition: var(--transition); position: relative; } body.dark .nav-link { background: var(--card-bg-dark); color: var(--text-dark); } .nav-link:hover { transform: translateX(5px); background: var(--primary); color: white; box-shadow: 0 6px 20px rgba(255, 77, 109, 0.4); } .nav-link .badge { position: absolute; right: 15px; background: var(--secondary); color: white; padding: 4px 10px; border-radius: 12px; font-size: 0.8em; font-weight: 700; } .logout-btn { background: var(--secondary); color: white; } .logout-btn:hover { background: #00b8c5; } .menu-btn { display: none; font-size: 28px; background: var(--glass-bg); border: none; color: var(--primary); cursor: pointer; position: fixed; top: 20px; left: 20px; z-index: 1001; padding: 12px; border-radius: 50%; box-shadow: var(--shadow); transition: var(--transition); } .menu-btn:hover { background: var(--primary); color: white; } .container { margin: 20px auto 20px 320px; max-width: 1200px; padding: 25px; transition: var(--transition); } .btn { padding: 14px 28px; background: var(--primary); color: white; border: none; border-radius: 14px; cursor: pointer; font-size: 1.1em; font-weight: 600; transition: var(--transition); display: inline-flex; align-items: center; gap: 10px; box-shadow: var(--shadow); } .btn:hover { transform: scale(1.05); background: #e6415f; box-shadow: 0 8px 25px rgba(255, 77, 109, 0.5); } input, textarea, select { width: 100%; padding: 14px; margin: 12px 0; border: none; border-radius: 14px; background: var(--glass-bg); color: var(--text-light); font-size: 1.1em; transition: var(--transition); box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.1); } body.dark input, body.dark textarea, body.dark select { color: var(--text-dark); } input:focus, textarea:focus, select:focus { outline: none; background: rgba(255, 255, 255, 0.2); box-shadow: 0 0 0 4px var(--primary); } .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.85); z-index: 2000; justify-content: center; align-items: center; transition: opacity var(--transition); } .modal img, .modal video { max-width: 95%; max-height: 95%; object-fit: contain; border-radius: 20px; box-shadow: var(--shadow); animation: zoomIn 0.3s ease; } .theme-toggle { position: fixed; top: 20px; right: 20px; background: var(--glass-bg); border: none; padding: 12px; border-radius: 50%; cursor: pointer; font-size: 24px; box-shadow: var(--shadow); transition: var(--transition); } .theme-toggle:hover { transform: rotate(90deg); background: var(--accent); color: white; } .status-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; margin-left: 8px; } .online { background: var(--online); } .offline { background: var(--offline); } @keyframes zoomIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } } @media (max-width: 900px) { .sidebar { width: 100%; max-width: 300px; transform: translateX(-100%); } .sidebar.active { transform: translateX(0); } .menu-btn { display: block; } .container { margin: 80px 20px 20px 20px; max-width: calc(100% - 40px); } .theme-toggle { top: 80px; } } @media (max-width: 480px) { .nav-brand { font-size: 1.5em; } .nav-link { font-size: 1em; padding: 12px 20px; } .btn { padding: 12px 20px; font-size: 1em; } } ''' NAV_HTML = ''' ''' @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') data = load_data() if username in data['users']: flash('User already exists!') return redirect(url_for('register')) data['users'][username] = { 'password': password, 'bio': '', 'link': '', 'avatar': None, 'last_chat_visit': '1970-01-01 00:00:00', 'last_private_visit': '1970-01-01 00:00:00', 'last_seen': datetime.now().strftime('%Y-%m-%d %H:%M:%S') } save_data(data) flash('Registration successful! Please login.') return redirect(url_for('login')) is_authenticated = 'username' in session username = session.get('username', None) data = load_data() unread_count = get_unread_count(data, username) if is_authenticated else 0 private_unread_count = get_private_unread_count(data, username) if is_authenticated else 0 user_count = len(data['users']) is_online = is_user_online(data, username) if is_authenticated else False html = ''' Register - Content Hub ''' + NAV_HTML + '''

Register

{% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}
''' return render_template_string(html, is_authenticated=is_authenticated, username=username, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online) @app.route('/login', methods=['GET', 'POST']) def login(): data = load_data() if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') if username in data['users'] and data['users'][username]['password'] == password: session['username'] = username session.permanent = True update_last_seen(data, username) return redirect(url_for('feed')) flash('Invalid username or password!') return redirect(url_for('login')) is_authenticated = 'username' in session username = session.get('username', None) if is_authenticated: update_last_seen(data, username) unread_count = get_unread_count(data, username) if is_authenticated else 0 private_unread_count = get_private_unread_count(data, username) if is_authenticated else 0 user_count = len(data['users']) is_online = is_user_online(data, username) if is_authenticated else False html = ''' Login - Content Hub ''' + NAV_HTML + '''

Login

{% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}
''' return render_template_string(html, is_authenticated=is_authenticated, username=username, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online) @app.route('/logout') def logout(): data = load_data() username = session.get('username', None) if username: update_last_seen(data, username) session.pop('username', None) return redirect(url_for('feed')) @app.route('/toggle_like/', methods=['POST']) def toggle_like(post_id): if 'username' not in session: return jsonify({'error': 'Not authenticated'}), 401 data = load_data() username = session['username'] post = next((p for p in data['posts'] if p['id'] == post_id), None) if not post: return jsonify({'error': 'Post not found'}), 404 likes = post.get('likes', []) if username in likes: post['likes'] = [u for u in likes if u != username] liked = False else: post['likes'] = likes + [username] liked = True save_data(data) return jsonify({'liked': liked, 'likes_count': len(post['likes'])}) @app.route('/increment_view/', methods=['POST']) def increment_view(post_id): data = load_data() post = next((p for p in data['posts'] if p['id'] == post_id), None) if post: post['views'] = post.get('views', 0) + 1 save_data(data) return jsonify({'views': post['views']}) return jsonify({'error': 'Post not found'}), 404 @app.route('/', methods=['GET', 'POST']) def feed(): data = load_data() username = session.get('username', None) if username: update_last_seen(data, username) posts = sorted(data.get('posts', []), key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True) is_authenticated = 'username' in session unread_count = get_unread_count(data, username) if is_authenticated else 0 private_unread_count = get_private_unread_count(data, username) if is_authenticated else 0 user_count = len(data['users']) is_online = is_user_online(data, username) if is_authenticated else False search_query = request.args.get('search', '').strip().lower() # Get search query from URL parameters if search_query: posts = [post for post in posts if search_query in post['title'].lower() or search_query in post['description'].lower()] if request.method == 'POST' and is_authenticated: post_id = request.form.get('post_id') post = next((p for p in data['posts'] if p['id'] == post_id), None) if not post: return "Post not found", 404 if 'comment' in request.form: comment_text = request.form.get('comment') if comment_text: post['comments'] = post.get('comments', []) + [{ 'user': username, 'text': comment_text, 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S') }] # Removed share handling save_data(data) return redirect(url_for('feed', search=search_query)) # Maintain search query html = ''' Adusis - QoS, BBC, BNWO HUB ''' + NAV_HTML + '''
{% for post in posts %}
{% if post['type'] == 'video' %} {% else %} {{ post['title'] }} {% endif %}

{{ post['title'] }}

{{ post['description']|truncate(150) }}

By: {{ post['uploader'] }}

{{ post['likes']|length }} {{ post['comments']|length }} {{ post['views'] }}
{% for comment in post.get('comments', []) %}
{{ comment['user'] }}: {{ comment['text'] }}
{% endfor %} {% if is_authenticated %}
{% endif %}
{% endfor %}
Home {% if is_authenticated %} Upload Profile {% endif %} Search
''' return render_template_string(html, posts=posts, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online, is_user_online=lambda u: is_user_online(data, u), data=data) @app.route('/post/', methods=['GET', 'POST']) def post_page(post_id): data = load_data() username = session.get('username', None) if username: update_last_seen(data, username) post = next((p for p in data['posts'] if p['id'] == post_id), None) if not post: return "Post not found", 404 is_authenticated = 'username' in session unread_count = get_unread_count(data, username) if is_authenticated else 0 private_unread_count = get_private_unread_count(data, username) if is_authenticated else 0 user_count = len(data['users']) is_online = is_user_online(data, username) if is_authenticated else False post['views'] = post.get('views', 0) + 1 save_data(data) if request.method == 'POST' and is_authenticated: if 'comment' in request.form: comment_text = request.form.get('comment') if comment_text: post['comments'] = post.get('comments', []) + [{'user': username, 'text': comment_text, 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] save_data(data) html = ''' {{ post['title'] }} - Content Hub ''' + NAV_HTML + '''

{{ post['title'] }}

{% if post['type'] == 'video' %} {% else %} {{ post['title'] }} {% endif %}

{{ post['description'] }}

By: {{ post['uploader'] }} | {{ post['upload_date'] }}

Views: {{ post['views'] }} | Likes: {{ post['likes']|length }}

{% if is_authenticated %}
{% endif %}

Comments

{% for comment in post.get('comments', []) %}

{{ comment['user'] }} ({{ comment['date'] }}): {{ comment['text'] }}

{% endfor %} Back to Feed {% if not is_authenticated %}

Login to like and comment.

{% endif %}
''' return render_template_string(html, post=post, repo_id=REPO_ID, is_authenticated=is_authenticated, username=username, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online, is_user_online=lambda u: is_user_online(data, u)) @app.route('/profile', methods=['GET', 'POST']) def profile(): if 'username' not in session: flash('Login to view your profile!') return redirect(url_for('login')) data = load_data() username = session['username'] update_last_seen(data, username) user_posts = sorted([p for p in data['posts'] if p['uploader'] == username], key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True) is_authenticated = 'username' in session unread_count = get_unread_count(data, username) private_unread_count = get_private_unread_count(data, username) user_count = len(data['users']) is_online = is_user_online(data, username) total_views = sum(post.get('views', 0) for post in user_posts) total_likes = sum(len(post.get('likes', [])) for post in user_posts) user_data = data['users'].get(username, {}) bio = user_data.get('bio', '') link = user_data.get('link', '') avatar = user_data.get('avatar', None) last_seen = user_data.get('last_seen', 'Never') if request.method == 'POST': if 'delete_post' in request.form: post_id = request.form.get('post_id') if post_id: data['posts'] = [p for p in data['posts'] if p['id'] != post_id or p['uploader'] != username] save_data(data) return redirect(url_for('profile')) elif 'update_profile' in request.form: bio = request.form.get('bio', '') link = request.form.get('link', '') avatar_file = request.files.get('avatar') if avatar_file and avatar_file.filename: filename = secure_filename(avatar_file.filename) temp_path = os.path.join('uploads', filename) os.makedirs('uploads', exist_ok=True) avatar_file.save(temp_path) api = HfApi() avatar_path = f"avatars/{username}/{filename}" api.upload_file( path_or_fileobj=temp_path, path_in_repo=avatar_path, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Uploaded avatar for {username}" ) data['users'][username]['avatar'] = avatar_path if os.path.exists(temp_path): os.remove(temp_path) data['users'][username]['bio'] = bio data['users'][username]['link'] = link save_data(data) return redirect(url_for('profile')) html = ''' Profile - {{ username }} - Content Hub ''' + NAV_HTML + '''
{% if avatar %} Avatar {% else %}
{% endif %}

{{ username }}

{{ bio }}

{% if link %}

{{ link }}

{% endif %}

Total Views: {{ total_views }} | Total Likes: {{ total_likes }}

Last Seen: {{ last_seen }}

Edit Profile

My Posts

{% for post in user_posts %}
{% if post['type'] == 'video' %} {% else %} {{ post['title'] }} {% endif %}

{{ post['title'] }}

{{ post['description']|truncate(100) }}

{{ post['upload_date'] }} | Views: {{ post['views'] }} | Likes: {{ post['likes']|length }}

{% endfor %} {% if not user_posts %}

You haven't uploaded any posts yet.

{% endif %}
''' return render_template_string(html, username=username, user_posts=user_posts, bio=bio, link=link, avatar=avatar, total_views=total_views, total_likes=total_likes, last_seen=last_seen, is_authenticated=is_authenticated, repo_id=REPO_ID, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online) @app.route('/user/', methods=['GET']) def user_profile(username): data = load_data() current_user = session.get('username', None) if current_user: update_last_seen(data, current_user) if username not in data['users']: return "User not found", 404 user_posts = sorted([p for p in data['posts'] if p['uploader'] == username], key=lambda x: datetime.strptime(x['upload_date'], '%Y-%m-%d %H:%M:%S'), reverse=True) is_authenticated = 'username' in session unread_count = get_unread_count(data, current_user) if is_authenticated else 0 private_unread_count = get_private_unread_count(data, current_user) if is_authenticated else 0 user_count = len(data['users']) is_online = is_user_online(data, current_user) if is_authenticated else False total_views = sum(post.get('views', 0) for post in user_posts) total_likes = sum(len(post.get('likes', [])) for post in user_posts) user_data = data['users'].get(username, {}) bio = user_data.get('bio', '') link = user_data.get('link', '') avatar = user_data.get('avatar', None) last_seen = user_data.get('last_seen', 'Never') user_online = is_user_online(data, username) html = ''' {{ username }}'s Profile - Content Hub ''' + NAV_HTML + '''
{% if avatar %} Avatar {% else %}
{% endif %}

{{ username }}

{{ bio }}

{% if link %}

{{ link }}

{% endif %}

Total Views: {{ total_views }} | Total Likes: {{ total_likes }}

Last Seen: {{ last_seen }}

{% if is_authenticated and current_user != username %} Send Message {% endif %}

Posts

{% for post in user_posts %}
{% if post['type'] == 'video' %} {% else %} {{ post['title'] }} {% endif %}

{{ post['title'] }}

{{ post['description']|truncate(100) }}

{{ post['upload_date'] }} | Views: {{ post['views'] }} | Likes: {{ post['likes']|length }}

{% endfor %} {% if not user_posts %}

This user hasn't uploaded any posts yet.

{% endif %}
''' return render_template_string(html, username=username, user_posts=user_posts, bio=bio, link=link, avatar=avatar, total_views=total_views, total_likes=total_likes, last_seen=last_seen, is_authenticated=is_authenticated, current_user=current_user, repo_id=REPO_ID, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online, user_online=user_online) @app.route('/upload', methods=['GET', 'POST']) def upload(): if 'username' not in session: flash('Login to upload content!') return redirect(url_for('login')) data = load_data() username = session['username'] update_last_seen(data, username) is_authenticated = 'username' in session unread_count = get_unread_count(data, username) private_unread_count = get_private_unread_count(data, username) user_count = len(data['users']) is_online = is_user_online(data, username) if request.method == 'POST': title = request.form.get('title') description = request.form.get('description') file = request.files.get('file') if not file or not title: flash('Title and file are required!') return redirect(url_for('upload')) filename = secure_filename(file.filename) temp_path = os.path.join('uploads', filename) os.makedirs('uploads', exist_ok=True) file.save(temp_path) file_type = 'video' if filename.lower().endswith(('.mp4', '.mov', '.avi')) else 'photo' api = HfApi() file_path = f"{file_type}s/{username}/{filename}" api.upload_file( path_or_fileobj=temp_path, path_in_repo=file_path, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Uploaded {file_type} by {username}" ) post_id = str(random.randint(100000, 999999)) while any(p['id'] == post_id for p in data['posts']): post_id = str(random.randint(100000, 999999)) data['posts'].append({ 'id': post_id, 'title': title, 'description': description, 'filename': f"{username}/{filename}", 'type': file_type, 'uploader': username, 'upload_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'views': 0, 'likes': [], 'comments': [] }) save_data(data) if os.path.exists(temp_path): os.remove(temp_path) return redirect(url_for('profile')) html = ''' Upload Content - Content Hub ''' + NAV_HTML + '''

Upload Content

{% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}
''' return render_template_string(html, username=username, is_authenticated=is_authenticated, repo_id=REPO_ID, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online) @app.route('/chat', methods=['GET', 'POST']) def chat(): data = load_data() username = session.get('username', None) if username: update_last_seen(data, username) is_authenticated = 'username' in session chat_messages = data['general_chat'] if is_authenticated: data['users'][username]['last_chat_visit'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') save_data(data) unread_count = get_unread_count(data, username) if is_authenticated else 0 private_unread_count = get_private_unread_count(data, username) if is_authenticated else 0 user_count = len(data['users']) is_online = is_user_online(data, username) if is_authenticated else False if request.method == 'POST' and is_authenticated: message = request.form.get('message') file = request.files.get('file') post_id = request.form.get('post_id') message_data = { 'sender': username, 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') } if message: message_data['text'] = message if file and file.filename: filename = secure_filename(file.filename) temp_path = os.path.join('uploads', filename) os.makedirs('uploads', exist_ok=True) file.save(temp_path) file_type = 'video' if filename.lower().endswith(('.mp4', '.mov', '.avi')) else 'photo' api = HfApi() file_path = f"chat_files/general/{filename}" api.upload_file( path_or_fileobj=temp_path, path_in_repo=file_path, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Uploaded chat file by {username}" ) message_data['file'] = file_path message_data['file_type'] = file_type if os.path.exists(temp_path): os.remove(temp_path) if post_id: post = next((p for p in data['posts'] if p['id'] == post_id and p['uploader'] == username), None) if post: message_data['post_id'] = post_id if 'text' in message_data or 'file' in message_data or 'post_id' in message_data: data['general_chat'].append(message_data) save_data(data) return redirect(url_for('chat')) html = ''' General Chat - Content Hub ''' + NAV_HTML + '''

General Chat

{% for message in chat_messages %}
{% if message['sender'] == username %} {% if avatar %} Your Avatar {% else %}
{% endif %} {% else %} {% if data['users'][message['sender']].get('avatar') %} {{ message['sender'] }} Avatar {% else %}
{% endif %} {% endif %}
{{ message['sender'] }} {% if 'text' in message %}

{{ message['text'] }}

{% endif %} {% if 'file' in message %} {% if message['file_type'] == 'video' %} {% else %} Chat file {% endif %} {% endif %} {% if 'post_id' in message %} {% with post = posts|selectattr('id', 'equalto', message['post_id'])|first %} {% if post %}

Shared: {{ post['title'] }}

{% endif %} {% endwith %} {% endif %} {{ message['time'] }}
{% endfor %}
{% if is_authenticated %}
{% else %}

Login to send messages.

{% endif %}
''' user_posts = [p for p in data['posts'] if p['uploader'] == username] if is_authenticated else [] avatar = data['users'][username].get('avatar') if is_authenticated else None return render_template_string(html, chat_messages=chat_messages, username=username, is_authenticated=is_authenticated, repo_id=REPO_ID, posts=data['posts'], user_posts=user_posts, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online, is_user_online=lambda u: is_user_online(data, u), data=data, avatar=avatar) @app.route('/users', methods=['GET', 'POST']) def users(): data = load_data() username = session.get('username', None) if username: update_last_seen(data, username) is_authenticated = 'username' in session unread_count = get_unread_count(data, username) if is_authenticated else 0 private_unread_count = get_private_unread_count(data, username) if is_authenticated else 0 user_count = len(data['users']) is_online = is_user_online(data, username) if is_authenticated else False search_query = request.form.get('search', '').strip().lower() if request.method == 'POST' else '' user_list = [(user, data['users'][user].get('avatar'), is_user_online(data, user)) for user in data['users'] if not search_query or search_query in user.lower()] html = ''' Users - Content Hub ''' + NAV_HTML + '''

Users ({{ user_count }})

{% for user, avatar, online in user_list %} {% if user != username %}
{% if avatar %} {{ user }} Avatar {% else %}
{% endif %}
{% endif %} {% endfor %}
''' return render_template_string(html, user_list=user_list, username=username, is_authenticated=is_authenticated, repo_id=REPO_ID, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online, search_query=search_query) @app.route('/messages', methods=['GET']) def messages(): if 'username' not in session: flash('Login to view messages!') return redirect(url_for('login')) data = load_data() username = session['username'] update_last_seen(data, username) is_authenticated = 'username' in session unread_count = get_unread_count(data, username) private_unread_count = get_private_unread_count(data, username) user_count = len(data['users']) is_online = is_user_online(data, username) dialogs = {} for chat_key, messages in data['private_chats'].items(): user1, user2 = chat_key.split('_') if username not in (user1, user2): continue other_user = user1 if user2 == username else user2 last_message = messages[-1] if messages else None unread = sum(1 for msg in messages if datetime.strptime(msg['time'], '%Y-%m-%d %H:%M:%S') > datetime.strptime(data['users'][username]['last_private_visit'], '%Y-%m-%d %H:%M:%S') and msg['sender'] != username) dialogs[other_user] = { 'last_message': last_message, 'unread': unread, 'avatar': data['users'][other_user].get('avatar'), 'online': is_user_online(data, other_user) } html = ''' Messages - Content Hub ''' + NAV_HTML + '''

Messages

{% for other_user, info in dialogs.items() %}
{% if info.avatar %} {{ other_user }} Avatar {% else %}
{% endif %}
{{ other_user }} {% if info.last_message %}

{{ info.last_message['time'] }}: {% if 'text' in info.last_message %}{{ info.last_message['text']|truncate(30) }}{% elif 'file' in info.last_message %}File{% elif 'post_id' in info.last_message %}Post{% endif %}

{% endif %}
{% if info.unread > 0 %} {{ info.unread }} {% endif %}
{% endfor %} {% if not dialogs %}

No messages yet.

{% endif %}
''' return render_template_string(html, dialogs=dialogs, username=username, is_authenticated=is_authenticated, repo_id=REPO_ID, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online) @app.route('/chat/', methods=['GET', 'POST']) def private_chat(recipient): if 'username' not in session: flash('Login to start a chat!') return redirect(url_for('login')) data = load_data() username = session['username'] update_last_seen(data, username) if recipient not in data['users']: return "User not found", 404 is_authenticated = 'username' in session unread_count = get_unread_count(data, username) private_unread_count = get_private_unread_count(data, username) user_count = len(data['users']) is_online = is_user_online(data, username) data['users'][username]['last_private_visit'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') save_data(data) chat_key = f"{min(username, recipient)}_{max(username, recipient)}" if chat_key not in data['private_chats']: data['private_chats'][chat_key] = [] private_messages = data['private_chats'][chat_key] if request.method == 'POST': message = request.form.get('message') file = request.files.get('file') post_id = request.form.get('post_id') message_data = { 'sender': username, 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') } if message: message_data['text'] = message if file and file.filename: filename = secure_filename(file.filename) temp_path = os.path.join('uploads', filename) os.makedirs('uploads', exist_ok=True) file.save(temp_path) file_type = 'video' if filename.lower().endswith(('.mp4', '.mov', '.avi')) else 'photo' api = HfApi() file_path = f"chat_files/private/{chat_key}/{filename}" api.upload_file( path_or_fileobj=temp_path, path_in_repo=file_path, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN_WRITE, commit_message=f"Uploaded private chat file by {username} to {recipient}" ) message_data['file'] = file_path message_data['file_type'] = file_type if os.path.exists(temp_path): os.remove(temp_path) if post_id: post = next((p for p in data['posts'] if p['id'] == post_id and p['uploader'] == username), None) if post: message_data['post_id'] = post_id if 'text' in message_data or 'file' in message_data or 'post_id' in message_data: data['private_chats'][chat_key].append(message_data) save_data(data) return redirect(url_for('private_chat', recipient=recipient)) recipient_avatar = data['users'][recipient].get('avatar') recipient_online = is_user_online(data, recipient) avatar = data['users'][username].get('avatar') if is_authenticated else None html = ''' Chat with {{ recipient }} - Content Hub ''' + NAV_HTML + '''

{% if recipient_avatar %} {{ recipient }} Avatar {% else %}
{% endif %} Chat with {{ recipient }}

{% for message in private_messages %}
{% if message['sender'] == username %} {% if avatar %} Your Avatar {% else %}
{% endif %} {% else %} {% if recipient_avatar %} {{ recipient }} Avatar {% endif %} {% endif %}
{{ message['sender'] }} {% if 'text' in message %}

{{ message['text'] }}

{% endif %} {% if 'file' in message %} {% if message['file_type'] == 'video' %} {% else %} Chat file {% endif %} {% endif %} {% if 'post_id' in message %} {% with post = posts|selectattr('id', 'equalto', message['post_id'])|first %} {% if post %}

Shared: {{ post['title'] }}

{% endif %} {% endwith %} {% endif %} {{ message['time'] }}
{% endfor %}
''' user_posts = [p for p in data['posts'] if p['uploader'] == username] return render_template_string(html, private_messages=private_messages, recipient=recipient, username=username, is_authenticated=is_authenticated, repo_id=REPO_ID, posts=data['posts'], user_posts=user_posts, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online, is_user_online=lambda u: is_user_online(data, u), recipient_avatar=recipient_avatar, recipient_online=recipient_online, avatar=avatar) if __name__ == '__main__': threading.Thread(target=periodic_backup, daemon=True).start() app.run(debug=False, host='0.0.0.0', port=7860)