Spaces:
Build error
Build error
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,825 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
import time
|
| 4 |
+
import uuid
|
| 5 |
+
import datetime
|
| 6 |
+
import torch
|
| 7 |
+
import gradio as gr
|
| 8 |
+
import numpy as np
|
| 9 |
+
import nltk
|
| 10 |
+
from nltk.sentiment import SentimentIntensityAnalyzer
|
| 11 |
+
from sklearn.feature_extraction.text import TfidfVectorizer
|
| 12 |
+
from sklearn.metrics.pairwise import cosine_similarity
|
| 13 |
+
try:
|
| 14 |
+
from transformers import pipeline
|
| 15 |
+
except ImportError as e:
|
| 16 |
+
print(f"Failed to import transformers: {e}")
|
| 17 |
+
print("Attempting to use a fallback model or configuration...")
|
| 18 |
+
pipeline = None
|
| 19 |
+
|
| 20 |
+
# Download NLTK resources
|
| 21 |
+
nltk.download('vader_lexicon', quiet=True)
|
| 22 |
+
nltk.download('punkt', quiet=True)
|
| 23 |
+
nltk.download('stopwords', quiet=True)
|
| 24 |
+
|
| 25 |
+
# Check if GPU is available
|
| 26 |
+
print(f"GPU available: {torch.cuda.is_available()}")
|
| 27 |
+
if torch.cuda.is_available():
|
| 28 |
+
print(f"GPU name: {torch.cuda.get_device_name(0)}")
|
| 29 |
+
|
| 30 |
+
# Initialize sentiment analyzer
|
| 31 |
+
sia = SentimentIntensityAnalyzer()
|
| 32 |
+
|
| 33 |
+
# Data storage
|
| 34 |
+
class DataStore:
|
| 35 |
+
def __init__(self):
|
| 36 |
+
self.users = {}
|
| 37 |
+
self.blogs = {}
|
| 38 |
+
self.comments = {}
|
| 39 |
+
self.chats = {}
|
| 40 |
+
self.user_interactions = {}
|
| 41 |
+
self.current_user_id = None
|
| 42 |
+
self.create_sample_data()
|
| 43 |
+
|
| 44 |
+
def create_sample_data(self):
|
| 45 |
+
user_ids = [self.add_user("admin", "admin123", "admin@example.com", "Admin User", "admin")]
|
| 46 |
+
user_ids.extend([self.add_user(f"blogger{i}", f"password{i}", f"blogger{i}@example.com", f"Blogger {i}", "blogger") for i in range(1, 4)])
|
| 47 |
+
user_ids.extend([self.add_user(f"reader{i}", f"password{i}", f"reader{i}@example.com", f"Reader {i}", "reader") for i in range(1, 6)])
|
| 48 |
+
|
| 49 |
+
blog_topics = [
|
| 50 |
+
"Machine Learning Fundamentals",
|
| 51 |
+
"Web Development Best Practices",
|
| 52 |
+
"Data Science in Practice",
|
| 53 |
+
"Python Programming Tips",
|
| 54 |
+
"Neural Networks Explained",
|
| 55 |
+
"Modern JavaScript Frameworks",
|
| 56 |
+
"Cloud Computing Services"
|
| 57 |
+
]
|
| 58 |
+
|
| 59 |
+
blog_contents = [
|
| 60 |
+
"Machine learning is a branch of artificial intelligence that enables computers to learn from data without being explicitly programmed...",
|
| 61 |
+
"Web development involves creating websites and web applications using technologies like HTML, CSS, and JavaScript...",
|
| 62 |
+
"Data science combines domain expertise, programming skills, and knowledge of math and statistics to extract meaningful insights from data...",
|
| 63 |
+
"Python is a versatile programming language widely used in various domains including web development, data analysis, and artificial intelligence...",
|
| 64 |
+
"Neural networks are computing systems inspired by the biological neural networks that constitute animal brains...",
|
| 65 |
+
"Modern JavaScript frameworks like React, Vue, and Angular have revolutionized front-end web development...",
|
| 66 |
+
"Cloud computing services provide businesses with on-demand access to computing resources without direct active management by the user..."
|
| 67 |
+
]
|
| 68 |
+
|
| 69 |
+
blog_ids = []
|
| 70 |
+
for i in range(len(blog_topics)):
|
| 71 |
+
author_id = user_ids[1 + (i % 3)]
|
| 72 |
+
blog_id = self.add_blog(blog_topics[i], blog_contents[i], author_id, ["tech", "programming"])
|
| 73 |
+
blog_ids.append(blog_id)
|
| 74 |
+
for j in range(3):
|
| 75 |
+
commenter_id = user_ids[4 + (j % 5)]
|
| 76 |
+
self.add_comment(blog_id, f"Great article on {blog_topics[i]}!", commenter_id)
|
| 77 |
+
for user_id in user_ids[4:]:
|
| 78 |
+
self.record_interaction(user_id, blog_id, np.random.randint(1, 10))
|
| 79 |
+
|
| 80 |
+
def add_user(self, username, password, email, display_name, role):
|
| 81 |
+
user_id = str(uuid.uuid4())
|
| 82 |
+
self.users[user_id] = {
|
| 83 |
+
"id": user_id,
|
| 84 |
+
"username": username,
|
| 85 |
+
"password": password,
|
| 86 |
+
"email": email,
|
| 87 |
+
"display_name": display_name,
|
| 88 |
+
"role": role,
|
| 89 |
+
"created_at": datetime.datetime.now().isoformat(),
|
| 90 |
+
"badges": []
|
| 91 |
+
}
|
| 92 |
+
return user_id
|
| 93 |
+
|
| 94 |
+
def add_blog(self, title, content, author_id, tags):
|
| 95 |
+
blog_id = str(uuid.uuid4())
|
| 96 |
+
self.blogs[blog_id] = {
|
| 97 |
+
"id": blog_id,
|
| 98 |
+
"title": title,
|
| 99 |
+
"content": content,
|
| 100 |
+
"author_id": author_id,
|
| 101 |
+
"tags": tags,
|
| 102 |
+
"created_at": datetime.datetime.now().isoformat(),
|
| 103 |
+
"updated_at": datetime.datetime.now().isoformat(),
|
| 104 |
+
"comments": [],
|
| 105 |
+
"likes": 0,
|
| 106 |
+
"views": 0
|
| 107 |
+
}
|
| 108 |
+
return blog_id
|
| 109 |
+
|
| 110 |
+
def add_comment(self, blog_id, content, user_id):
|
| 111 |
+
comment_id = str(uuid.uuid4())
|
| 112 |
+
self.comments[comment_id] = {
|
| 113 |
+
"id": comment_id,
|
| 114 |
+
"blog_id": blog_id,
|
| 115 |
+
"content": content,
|
| 116 |
+
"user_id": user_id,
|
| 117 |
+
"created_at": datetime.datetime.now().isoformat()
|
| 118 |
+
}
|
| 119 |
+
self.blogs[blog_id]["comments"].append(comment_id)
|
| 120 |
+
return comment_id
|
| 121 |
+
|
| 122 |
+
def add_chat_message(self, chat_id, content, user_id):
|
| 123 |
+
if chat_id not in self.chats:
|
| 124 |
+
self.chats[chat_id] = {
|
| 125 |
+
"id": chat_id,
|
| 126 |
+
"messages": [],
|
| 127 |
+
"participants": []
|
| 128 |
+
}
|
| 129 |
+
message_id = str(uuid.uuid4())
|
| 130 |
+
message = {
|
| 131 |
+
"id": message_id,
|
| 132 |
+
"content": content,
|
| 133 |
+
"user_id": user_id,
|
| 134 |
+
"created_at": datetime.datetime.now().isoformat()
|
| 135 |
+
}
|
| 136 |
+
self.chats[chat_id]["messages"].append(message)
|
| 137 |
+
if user_id not in self.chats[chat_id]["participants"]:
|
| 138 |
+
self.chats[chat_id]["participants"].append(user_id)
|
| 139 |
+
return message_id
|
| 140 |
+
|
| 141 |
+
def record_interaction(self, user_id, blog_id, interaction_value):
|
| 142 |
+
if user_id not in self.user_interactions:
|
| 143 |
+
self.user_interactions[user_id] = {}
|
| 144 |
+
if blog_id not in self.user_interactions[user_id]:
|
| 145 |
+
self.user_interactions[user_id][blog_id] = 0
|
| 146 |
+
self.user_interactions[user_id][blog_id] += interaction_value
|
| 147 |
+
|
| 148 |
+
def authenticate_user(self, username, password):
|
| 149 |
+
for user_id, user in self.users.items():
|
| 150 |
+
if user["username"] == username and user["password"] == password:
|
| 151 |
+
return user_id
|
| 152 |
+
return None
|
| 153 |
+
|
| 154 |
+
def get_user_blogs(self, user_id):
|
| 155 |
+
return {blog_id: blog for blog_id, blog in self.blogs.items() if blog["author_id"] == user_id}
|
| 156 |
+
|
| 157 |
+
def get_all_blogs(self):
|
| 158 |
+
return self.blogs
|
| 159 |
+
|
| 160 |
+
def get_blog_by_id(self, blog_id):
|
| 161 |
+
return self.blogs.get(blog_id)
|
| 162 |
+
|
| 163 |
+
def get_user_by_id(self, user_id):
|
| 164 |
+
return self.users.get(user_id)
|
| 165 |
+
|
| 166 |
+
def get_chat_by_id(self, chat_id):
|
| 167 |
+
return self.chats.get(chat_id)
|
| 168 |
+
|
| 169 |
+
def get_comments_for_blog(self, blog_id):
|
| 170 |
+
blog = self.blogs.get(blog_id)
|
| 171 |
+
if not blog:
|
| 172 |
+
return []
|
| 173 |
+
comments = []
|
| 174 |
+
for comment_id in blog["comments"]:
|
| 175 |
+
comment = self.comments.get(comment_id)
|
| 176 |
+
if comment:
|
| 177 |
+
comments.append(comment)
|
| 178 |
+
return comments
|
| 179 |
+
|
| 180 |
+
# Initialize data store
|
| 181 |
+
data_store = DataStore()
|
| 182 |
+
|
| 183 |
+
# Machine Learning Models
|
| 184 |
+
class MLModels:
|
| 185 |
+
def __init__(self):
|
| 186 |
+
self.sentiment_model_name = "distilbert-base-uncased-finetuned-sst-2-english"
|
| 187 |
+
self.sentiment_analyzer = None
|
| 188 |
+
if pipeline is not None:
|
| 189 |
+
try:
|
| 190 |
+
self.sentiment_analyzer = pipeline("sentiment-analysis", model=self.sentiment_model_name, device=0 if torch.cuda.is_available() else -1)
|
| 191 |
+
except Exception as e:
|
| 192 |
+
print(f"Failed to initialize sentiment analyzer: {e}")
|
| 193 |
+
print("Falling back to NLTK sentiment analysis")
|
| 194 |
+
self.tfidf_vectorizer = TfidfVectorizer(max_features=1000)
|
| 195 |
+
self.blog_vectors = None
|
| 196 |
+
self.update_blog_vectors()
|
| 197 |
+
|
| 198 |
+
def update_blog_vectors(self):
|
| 199 |
+
blog_contents = [f"{blog['title']} {' '.join(blog['tags'])} {blog['content']}"
|
| 200 |
+
for blog in data_store.blogs.values()]
|
| 201 |
+
if blog_contents:
|
| 202 |
+
self.blog_vectors = self.tfidf_vectorizer.fit_transform(blog_contents)
|
| 203 |
+
else:
|
| 204 |
+
self.blog_vectors = None
|
| 205 |
+
|
| 206 |
+
def analyze_sentiment(self, text):
|
| 207 |
+
if self.sentiment_analyzer is not None:
|
| 208 |
+
try:
|
| 209 |
+
result = self.sentiment_analyzer(text, truncation=True, max_length=512)[0]
|
| 210 |
+
score = result["score"] if result["label"] == "POSITIVE" else 1 - result["score"]
|
| 211 |
+
return {
|
| 212 |
+
"score": float(score),
|
| 213 |
+
"label": result["label"].lower(),
|
| 214 |
+
"is_inappropriate": score < 0.2
|
| 215 |
+
}
|
| 216 |
+
except Exception as e:
|
| 217 |
+
print(f"Sentiment analysis failed: {e}")
|
| 218 |
+
vader_scores = sia.polarity_scores(text)
|
| 219 |
+
score = (vader_scores['compound'] + 1) / 2
|
| 220 |
+
return {
|
| 221 |
+
"score": float(score),
|
| 222 |
+
"label": "positive" if score > 0.5 else "negative",
|
| 223 |
+
"is_inappropriate": score < 0.2
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
def recommend_blogs(self, user_id, limit=5):
|
| 227 |
+
if user_id not in data_store.user_interactions or len(data_store.user_interactions[user_id]) < 2:
|
| 228 |
+
return self.content_based_recommendations(user_id, limit)
|
| 229 |
+
else:
|
| 230 |
+
return self.collaborative_filtering(user_id, limit)
|
| 231 |
+
|
| 232 |
+
def content_based_recommendations(self, user_id, limit=5):
|
| 233 |
+
user_blogs = data_store.user_interactions.get(user_id, {})
|
| 234 |
+
if not user_blogs:
|
| 235 |
+
blog_ids = list(data_store.blogs.keys())
|
| 236 |
+
np.random.shuffle(blog_ids)
|
| 237 |
+
return blog_ids[:limit]
|
| 238 |
+
user_profile = np.zeros(self.blog_vectors.shape[1])
|
| 239 |
+
total_interactions = 0
|
| 240 |
+
for blog_id, interaction_count in user_blogs.items():
|
| 241 |
+
blog_idx = list(data_store.blogs.keys()).index(blog_id)
|
| 242 |
+
user_profile += interaction_count
|
| 243 |
+
total_interactions += interaction_count
|
| 244 |
+
if total_interactions > 0:
|
| 245 |
+
user_profile /= total_interactions
|
| 246 |
+
similarities = []
|
| 247 |
+
for i, blog_id in enumerate(data_store.blogs.keys()):
|
| 248 |
+
if blog_id not in user_blogs:
|
| 249 |
+
blog_vector = self.blog_vectors[i].toarray()[0]
|
| 250 |
+
similarity = np.dot(user_profile, blog_vector) / (np.linalg.norm(user_profile) * np.linalg.norm(blog_vector) + 1e-8)
|
| 251 |
+
similarities.append((blog_id, similarity))
|
| 252 |
+
similarities.sort(key=lambda x: x[1], reverse=True)
|
| 253 |
+
return [blog_id for blog_id, _ in similarities[:limit]]
|
| 254 |
+
|
| 255 |
+
def collaborative_filtering(self, user_id, limit=5):
|
| 256 |
+
user_ids = list(data_store.user_interactions.keys())
|
| 257 |
+
blog_ids = list(data_store.blogs.keys())
|
| 258 |
+
if user_id not in user_ids:
|
| 259 |
+
return self.content_based_recommendations(user_id, limit)
|
| 260 |
+
interaction_matrix = np.zeros((len(user_ids), len(blog_ids)))
|
| 261 |
+
for i, u_id in enumerate(user_ids):
|
| 262 |
+
for j, b_id in enumerate(blog_ids):
|
| 263 |
+
interaction_matrix[i, j] = data_store.user_interactions.get(u_id, {}).get(b_id, 0)
|
| 264 |
+
user_similarity = cosine_similarity(interaction_matrix)
|
| 265 |
+
user_idx = user_ids.index(user_id)
|
| 266 |
+
similar_users = [(user_ids[i], user_similarity[user_idx, i])
|
| 267 |
+
for i in range(len(user_ids)) if i != user_idx]
|
| 268 |
+
similar_users.sort(key=lambda x: x[1], reverse=True)
|
| 269 |
+
recommendations = {}
|
| 270 |
+
for similar_user_id, similarity in similar_users[:5]:
|
| 271 |
+
similar_user_idx = user_ids.index(similar_user_id)
|
| 272 |
+
for j, blog_id in enumerate(blog_ids):
|
| 273 |
+
if blog_id in data_store.user_interactions.get(user_id, {}):
|
| 274 |
+
continue
|
| 275 |
+
if interaction_matrix[similar_user_idx, j] > 0:
|
| 276 |
+
if blog_id not in recommendations:
|
| 277 |
+
recommendations[blog_id] = 0
|
| 278 |
+
recommendations[blog_id] += similarity * interaction_matrix[similar_user_idx, j]
|
| 279 |
+
sorted_recommendations = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
|
| 280 |
+
return [blog_id for blog_id, _ in sorted_recommendations[:limit]]
|
| 281 |
+
|
| 282 |
+
def moderate_text(self, text):
|
| 283 |
+
sentiment_result = self.analyze_sentiment(text)
|
| 284 |
+
is_inappropriate = sentiment_result["is_inappropriate"]
|
| 285 |
+
banned_words = ["hate", "spam", "offensive", "racist", "sexist"]
|
| 286 |
+
contains_banned_words = any(word in text.lower() for word in banned_words)
|
| 287 |
+
return {
|
| 288 |
+
"is_flagged": is_inappropriate or contains_banned_words,
|
| 289 |
+
"sentiment": sentiment_result["label"],
|
| 290 |
+
"confidence": sentiment_result["score"]
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
# Initialize ML models
|
| 294 |
+
ml_models = MLModels()
|
| 295 |
+
|
| 296 |
+
# Custom CSS
|
| 297 |
+
custom_css = """
|
| 298 |
+
body {
|
| 299 |
+
font-family: 'Arial', sans-serif;
|
| 300 |
+
background-color: #f4f7fb;
|
| 301 |
+
}
|
| 302 |
+
.header {
|
| 303 |
+
background-color: #2c3e50;
|
| 304 |
+
color: white;
|
| 305 |
+
padding: 15px;
|
| 306 |
+
text-align: center;
|
| 307 |
+
border-radius: 8px;
|
| 308 |
+
margin-bottom: 20px;
|
| 309 |
+
}
|
| 310 |
+
.card {
|
| 311 |
+
background-color: white;
|
| 312 |
+
border-radius: 8px;
|
| 313 |
+
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
| 314 |
+
padding: 15px;
|
| 315 |
+
margin-bottom: 15px;
|
| 316 |
+
transition: transform 0.2s;
|
| 317 |
+
}
|
| 318 |
+
.card:hover {
|
| 319 |
+
transform: translateY(-2px);
|
| 320 |
+
}
|
| 321 |
+
.gr-button {
|
| 322 |
+
background-color: #3498db;
|
| 323 |
+
color: white;
|
| 324 |
+
border: none;
|
| 325 |
+
border-radius: 5px;
|
| 326 |
+
padding: 10px 20px;
|
| 327 |
+
font-size: 16px;
|
| 328 |
+
cursor: pointer;
|
| 329 |
+
transition: background-color 0.2s;
|
| 330 |
+
}
|
| 331 |
+
.gr-button:hover {
|
| 332 |
+
background-color: #2980b9;
|
| 333 |
+
}
|
| 334 |
+
.gr-button.secondary {
|
| 335 |
+
background-color: #7f8c8d;
|
| 336 |
+
}
|
| 337 |
+
.gr-button.secondary:hover {
|
| 338 |
+
background-color: #636e72;
|
| 339 |
+
}
|
| 340 |
+
.gr-textbox {
|
| 341 |
+
border-radius: 5px;
|
| 342 |
+
border: 1px solid #dcdcdc;
|
| 343 |
+
padding: 10px;
|
| 344 |
+
}
|
| 345 |
+
.tab-nav button {
|
| 346 |
+
border-radius: 5px 5px 0 0 !important;
|
| 347 |
+
}
|
| 348 |
+
.tab-nav button[aria-selected="true"] {
|
| 349 |
+
background-color: #3498db !important;
|
| 350 |
+
color: white !important;
|
| 351 |
+
}
|
| 352 |
+
@media (max-width: 768px) {
|
| 353 |
+
.card {
|
| 354 |
+
padding: 10px;
|
| 355 |
+
}
|
| 356 |
+
.gr-button {
|
| 357 |
+
padding: 8px 15px;
|
| 358 |
+
font-size: 14px;
|
| 359 |
+
}
|
| 360 |
+
}
|
| 361 |
+
"""
|
| 362 |
+
|
| 363 |
+
# Gradio Interface
|
| 364 |
+
def create_interface():
|
| 365 |
+
with gr.Blocks(css=custom_css) as interface:
|
| 366 |
+
user_id_state = gr.State("")
|
| 367 |
+
|
| 368 |
+
# Header
|
| 369 |
+
gr.Markdown("<div class='header'><h1>BlogSphere</h1><p>Your hub for tech insights and discussions</p></div>")
|
| 370 |
+
|
| 371 |
+
# Authentication
|
| 372 |
+
with gr.Group() as auth_group:
|
| 373 |
+
with gr.Row():
|
| 374 |
+
with gr.Column(scale=1, min_width=300):
|
| 375 |
+
gr.Markdown("## Sign In")
|
| 376 |
+
username_input = gr.Textbox(label="Username", placeholder="Enter your username")
|
| 377 |
+
password_input = gr.Textbox(label="Password", type="password", placeholder="Enter your password")
|
| 378 |
+
login_button = gr.Button("Login")
|
| 379 |
+
login_status = gr.Textbox(label="Status", interactive=False, placeholder="Login status will appear here")
|
| 380 |
+
|
| 381 |
+
# Main interface
|
| 382 |
+
with gr.Group(visible=False) as main_group:
|
| 383 |
+
current_blog_id = gr.State("")
|
| 384 |
+
current_chat_id = gr.State("")
|
| 385 |
+
|
| 386 |
+
# Navigation bar
|
| 387 |
+
with gr.Row():
|
| 388 |
+
refresh_button = gr.Button("Refresh Content", variant="secondary")
|
| 389 |
+
|
| 390 |
+
# Tabs
|
| 391 |
+
with gr.Tabs() as tabs:
|
| 392 |
+
# Blog Feed Tab
|
| 393 |
+
with gr.TabItem("Blog Feed"):
|
| 394 |
+
gr.Markdown("## Explore Blogs")
|
| 395 |
+
with gr.Row():
|
| 396 |
+
with gr.Column(scale=3):
|
| 397 |
+
blog_list = gr.HTML()
|
| 398 |
+
blog_refresh_button = gr.Button("Load More Blogs", variant="secondary")
|
| 399 |
+
|
| 400 |
+
with gr.Column(scale=1):
|
| 401 |
+
gr.Markdown("## Recommended For You")
|
| 402 |
+
recommended_blogs = gr.HTML()
|
| 403 |
+
|
| 404 |
+
with gr.Row():
|
| 405 |
+
with gr.Column():
|
| 406 |
+
gr.Markdown("## Blog Content")
|
| 407 |
+
blog_title = gr.Textbox(label="Title", interactive=False)
|
| 408 |
+
blog_author = gr.Textbox(label="Author", interactive=False)
|
| 409 |
+
blog_content = gr.Textbox(label="Content", lines=10, interactive=False)
|
| 410 |
+
blog_tags = gr.Textbox(label="Tags", interactive=False)
|
| 411 |
+
|
| 412 |
+
with gr.Accordion("Comments", open=False):
|
| 413 |
+
blog_comments = gr.HTML()
|
| 414 |
+
new_comment = gr.Textbox(label="Add a comment", placeholder="Write your comment here")
|
| 415 |
+
submit_comment = gr.Button("Submit Comment")
|
| 416 |
+
|
| 417 |
+
# My Blogs Tab
|
| 418 |
+
with gr.TabItem("My Blogs"):
|
| 419 |
+
gr.Markdown("## My Published Blogs")
|
| 420 |
+
my_blogs_list = gr.HTML()
|
| 421 |
+
|
| 422 |
+
with gr.Accordion("Create New Blog", open=False):
|
| 423 |
+
new_blog_title = gr.Textbox(label="Title", placeholder="Enter blog title")
|
| 424 |
+
new_blog_content = gr.Textbox(label="Content", lines=10, placeholder="Write your blog content here")
|
| 425 |
+
new_blog_tags = gr.Textbox(label="Tags", placeholder="Enter tags, separated by commas")
|
| 426 |
+
create_blog_button = gr.Button("Publish Blog")
|
| 427 |
+
blog_create_status = gr.Textbox(label="Status", interactive=False)
|
| 428 |
+
|
| 429 |
+
# Chat Tab
|
| 430 |
+
with gr.TabItem("Chat"):
|
| 431 |
+
with gr.Row():
|
| 432 |
+
with gr.Column(scale=1):
|
| 433 |
+
gr.Markdown("## Chat Rooms")
|
| 434 |
+
chat_list = gr.HTML()
|
| 435 |
+
new_chat_name = gr.Textbox(label="New Chat Room Name", placeholder="Enter chat room name")
|
| 436 |
+
create_chat_button = gr.Button("Create Chat Room")
|
| 437 |
+
|
| 438 |
+
with gr.Column(scale=2):
|
| 439 |
+
gr.Markdown("## Chat")
|
| 440 |
+
chat_messages = gr.Chatbot(label="Messages")
|
| 441 |
+
new_message = gr.Textbox(label="Message", placeholder="Type your message")
|
| 442 |
+
send_message_button = gr.Button("Send")
|
| 443 |
+
moderation_status = gr.Textbox(label="Moderation Status", interactive=False)
|
| 444 |
+
|
| 445 |
+
# Profile Tab
|
| 446 |
+
with gr.TabItem("Profile"):
|
| 447 |
+
gr.Markdown("## User Profile")
|
| 448 |
+
display_name = gr.Textbox(label="Display Name", placeholder="Enter display name")
|
| 449 |
+
email = gr.Textbox(label="Email", placeholder="Enter email")
|
| 450 |
+
user_role = gr.Textbox(label="Role", interactive=False)
|
| 451 |
+
user_badges = gr.Textbox(label="Badges", interactive=False)
|
| 452 |
+
update_profile_button = gr.Button("Update Profile")
|
| 453 |
+
profile_update_status = gr.Textbox(label="Status", interactive=False)
|
| 454 |
+
logout_button = gr.Button("Logout", variant="secondary")
|
| 455 |
+
|
| 456 |
+
# Helper functions
|
| 457 |
+
def format_blog_card(blog_id, blog, author_name, is_recommended=False):
|
| 458 |
+
title = blog["title"]
|
| 459 |
+
tags = ", ".join(blog["tags"])
|
| 460 |
+
likes = blog["likes"]
|
| 461 |
+
views = blog["views"]
|
| 462 |
+
snippet = blog["content"][:100] + "..." if len(blog["content"]) > 100 else blog["content"]
|
| 463 |
+
return f"""
|
| 464 |
+
<div class='card' onclick='selectBlog("{blog_id}")'>
|
| 465 |
+
<h3>{title}</h3>
|
| 466 |
+
<p><b>Author:</b> {author_name}</p>
|
| 467 |
+
<p>{snippet}</p>
|
| 468 |
+
<p><b>Tags:</b> {tags}</p>
|
| 469 |
+
<p><b>Likes:</b> {likes} | <b>Views:</b> {views}</p>
|
| 470 |
+
</div>
|
| 471 |
+
"""
|
| 472 |
+
|
| 473 |
+
def format_comment_card(comment, user_name):
|
| 474 |
+
content = comment["content"]
|
| 475 |
+
date = comment["created_at"]
|
| 476 |
+
return f"""
|
| 477 |
+
<div class='card'>
|
| 478 |
+
<p><b>{user_name}</b> - {date}</p>
|
| 479 |
+
<p>{content}</p>
|
| 480 |
+
</div>
|
| 481 |
+
"""
|
| 482 |
+
|
| 483 |
+
def format_chat_room_card(chat_id, participants):
|
| 484 |
+
return f"""
|
| 485 |
+
<div class='card' onclick='selectChat("{chat_id}")'>
|
| 486 |
+
<h4>Chat Room {chat_id[:8]}</h4>
|
| 487 |
+
<p><b>Participants:</b> {', '.join(participants)}</p>
|
| 488 |
+
</div>
|
| 489 |
+
"""
|
| 490 |
+
|
| 491 |
+
# Functions
|
| 492 |
+
def login(username, password):
|
| 493 |
+
user_id = data_store.authenticate_user(username, password)
|
| 494 |
+
if user_id:
|
| 495 |
+
user = data_store.get_user_by_id(user_id)
|
| 496 |
+
data_store.current_user_id = user_id
|
| 497 |
+
recommended = load_recommended_blogs(user_id)
|
| 498 |
+
user_blogs = load_user_blogs(user_id)
|
| 499 |
+
profile_data = load_user_profile(user_id)
|
| 500 |
+
chat_rooms = load_chat_rooms()
|
| 501 |
+
return (
|
| 502 |
+
user_id,
|
| 503 |
+
f"Welcome back, {user['display_name']}!",
|
| 504 |
+
gr.update(visible=False),
|
| 505 |
+
gr.update(visible=True),
|
| 506 |
+
recommended,
|
| 507 |
+
user_blogs,
|
| 508 |
+
chat_rooms,
|
| 509 |
+
profile_data[0],
|
| 510 |
+
profile_data[1],
|
| 511 |
+
profile_data[2],
|
| 512 |
+
profile_data[3]
|
| 513 |
+
)
|
| 514 |
+
else:
|
| 515 |
+
return "", "Invalid username or password", gr.update(visible=True), gr.update(visible=False), "", "", "", "", "", "", ""
|
| 516 |
+
|
| 517 |
+
def load_blogs():
|
| 518 |
+
blogs = data_store.get_all_blogs()
|
| 519 |
+
blog_html = ""
|
| 520 |
+
for blog_id, blog in blogs.items():
|
| 521 |
+
author = data_store.get_user_by_id(blog["author_id"])
|
| 522 |
+
author_name = author["display_name"] if author else "Unknown"
|
| 523 |
+
blog_html += format_blog_card(blog_id, blog, author_name)
|
| 524 |
+
return blog_html
|
| 525 |
+
|
| 526 |
+
def load_recommended_blogs(user_id):
|
| 527 |
+
if not user_id:
|
| 528 |
+
return ""
|
| 529 |
+
recommended_blog_ids = ml_models.recommend_blogs(user_id)
|
| 530 |
+
recommended_html = ""
|
| 531 |
+
for blog_id in recommended_blog_ids:
|
| 532 |
+
blog = data_store.get_blog_by_id(blog_id)
|
| 533 |
+
if blog:
|
| 534 |
+
author = data_store.get_user_by_id(blog["author_id"])
|
| 535 |
+
author_name = author["display_name"] if author else "Unknown"
|
| 536 |
+
recommended_html += format_blog_card(blog_id, blog, author_name, is_recommended=True)
|
| 537 |
+
return recommended_html
|
| 538 |
+
|
| 539 |
+
def view_blog(blog_id):
|
| 540 |
+
if not blog_id:
|
| 541 |
+
return "", "", "", "", ""
|
| 542 |
+
blog = data_store.get_blog_by_id(blog_id)
|
| 543 |
+
if not blog:
|
| 544 |
+
return "", "", "", "", ""
|
| 545 |
+
blog["views"] += 1
|
| 546 |
+
if data_store.current_user_id:
|
| 547 |
+
data_store.record_interaction(data_store.current_user_id, blog_id, 1)
|
| 548 |
+
author = data_store.get_user_by_id(blog["author_id"])
|
| 549 |
+
author_name = author["display_name"] if author else "Unknown"
|
| 550 |
+
comments_data = ""
|
| 551 |
+
for comment_id in blog["comments"]:
|
| 552 |
+
comment = data_store.comments.get(comment_id)
|
| 553 |
+
if comment:
|
| 554 |
+
comment_user = data_store.get_user_by_id(comment["user_id"])
|
| 555 |
+
user_name = comment_user["display_name"] if comment_user else "Unknown"
|
| 556 |
+
comments_data += format_comment_card(comment, user_name)
|
| 557 |
+
return (
|
| 558 |
+
blog_id,
|
| 559 |
+
blog["title"],
|
| 560 |
+
author_name,
|
| 561 |
+
blog["content"],
|
| 562 |
+
", ".join(blog["tags"]),
|
| 563 |
+
comments_data
|
| 564 |
+
)
|
| 565 |
+
|
| 566 |
+
def add_comment(blog_id, comment_text, user_id):
|
| 567 |
+
if not user_id:
|
| 568 |
+
return "Please log in to comment", ""
|
| 569 |
+
if not blog_id:
|
| 570 |
+
return "Please select a blog first", ""
|
| 571 |
+
moderation_result = ml_models.moderate_text(comment_text)
|
| 572 |
+
if moderation_result["is_flagged"]:
|
| 573 |
+
return "Your comment has been flagged for inappropriate content", ""
|
| 574 |
+
data_store.add_comment(blog_id, comment_text, user_id)
|
| 575 |
+
data_store.record_interaction(user_id, blog_id, 2)
|
| 576 |
+
comments_data = ""
|
| 577 |
+
blog = data_store.get_blog_by_id(blog_id)
|
| 578 |
+
for comment_id in blog["comments"]:
|
| 579 |
+
comment = data_store.comments.get(comment_id)
|
| 580 |
+
if comment:
|
| 581 |
+
comment_user = data_store.get_user_by_id(comment["user_id"])
|
| 582 |
+
user_name = comment_user["display_name"] if comment_user else "Unknown"
|
| 583 |
+
comments_data += format_comment_card(comment, user_name)
|
| 584 |
+
return "Comment added successfully", comments_data
|
| 585 |
+
|
| 586 |
+
def load_user_blogs(user_id):
|
| 587 |
+
if not user_id:
|
| 588 |
+
return ""
|
| 589 |
+
user_blogs = data_store.get_user_blogs(user_id)
|
| 590 |
+
blogs_html = ""
|
| 591 |
+
for blog_id, blog in user_blogs.items():
|
| 592 |
+
author = data_store.get_user_by_id(blog["author_id"])
|
| 593 |
+
author_name = author["display_name"] if author else "Unknown"
|
| 594 |
+
blogs_html += format_blog_card(blog_id, blog, author_name)
|
| 595 |
+
return blogs_html
|
| 596 |
+
|
| 597 |
+
def create_blog(title, content, tags, user_id):
|
| 598 |
+
if not user_id:
|
| 599 |
+
return "Please log in to create a blog"
|
| 600 |
+
if not title or not content:
|
| 601 |
+
return "Title and content are required"
|
| 602 |
+
moderation_result = ml_models.moderate_text(content)
|
| 603 |
+
if moderation_result["is_flagged"]:
|
| 604 |
+
return "Your blog has been flagged for inappropriate content"
|
| 605 |
+
tag_list = [tag.strip() for tag in tags.split(",") if tag.strip()]
|
| 606 |
+
blog_id = data_store.add_blog(title, content, user_id, tag_list)
|
| 607 |
+
ml_models.update_blog_vectors()
|
| 608 |
+
return f"Blog created successfully with ID: {blog_id}"
|
| 609 |
+
|
| 610 |
+
def load_chat_rooms():
|
| 611 |
+
chat_html = ""
|
| 612 |
+
for chat_id, chat in data_store.chats.items():
|
| 613 |
+
participants = []
|
| 614 |
+
for user_id in chat["participants"]:
|
| 615 |
+
user = data_store.get_user_by_id(user_id)
|
| 616 |
+
if user:
|
| 617 |
+
participants.append(user["display_name"])
|
| 618 |
+
chat_html += format_chat_room_card(chat_id, participants)
|
| 619 |
+
return chat_html
|
| 620 |
+
|
| 621 |
+
def create_chat_room(name, user_id):
|
| 622 |
+
if not user_id:
|
| 623 |
+
return "Please log in to create a chat room", ""
|
| 624 |
+
chat_id = str(uuid.uuid4())
|
| 625 |
+
data_store.chats[chat_id] = {
|
| 626 |
+
"id": chat_id,
|
| 627 |
+
"name": name,
|
| 628 |
+
"messages": [],
|
| 629 |
+
"participants": [user_id],
|
| 630 |
+
"created_at": datetime.datetime.now().isoformat()
|
| 631 |
+
}
|
| 632 |
+
return chat_id, load_chat_rooms()
|
| 633 |
+
|
| 634 |
+
def view_chat(chat_id):
|
| 635 |
+
if not chat_id:
|
| 636 |
+
return [], ""
|
| 637 |
+
chat = data_store.get_chat_by_id(chat_id)
|
| 638 |
+
if not chat:
|
| 639 |
+
return [], ""
|
| 640 |
+
messages_data = []
|
| 641 |
+
for message in chat["messages"]:
|
| 642 |
+
user = data_store.get_user_by_id(message["user_id"])
|
| 643 |
+
user_name = user["display_name"] if user else "Unknown"
|
| 644 |
+
messages_data.append([f"{user_name} ({message['created_at']})", message["content"]])
|
| 645 |
+
return messages_data, chat_id
|
| 646 |
+
|
| 647 |
+
def send_message(chat_id, message, user_id):
|
| 648 |
+
if not user_id:
|
| 649 |
+
return "Please log in to send messages", []
|
| 650 |
+
if not chat_id:
|
| 651 |
+
return "Please select a chat room first", []
|
| 652 |
+
moderation_result = ml_models.moderate_text(message)
|
| 653 |
+
if moderation_result["is_flagged"]:
|
| 654 |
+
return "Your message has been flagged for inappropriate content", []
|
| 655 |
+
data_store.add_chat_message(chat_id, message, user_id)
|
| 656 |
+
chat = data_store.get_chat_by_id(chat_id)
|
| 657 |
+
messages_data = []
|
| 658 |
+
for msg in chat["messages"]:
|
| 659 |
+
user = data_store.get_user_by_id(msg["user_id"])
|
| 660 |
+
user_name = user["display_name"] if user else "Unknown"
|
| 661 |
+
messages_data.append([f"{user_name} ({msg['created_at']})", msg["content"]])
|
| 662 |
+
return "Message sent successfully", messages_data
|
| 663 |
+
|
| 664 |
+
def load_user_profile(user_id):
|
| 665 |
+
if not user_id:
|
| 666 |
+
return "", "", "", ""
|
| 667 |
+
user = data_store.get_user_by_id(user_id)
|
| 668 |
+
if user:
|
| 669 |
+
return user["display_name"], user["email"], user["role"], ", ".join(user["badges"])
|
| 670 |
+
return "", "", "", ""
|
| 671 |
+
|
| 672 |
+
def update_profile(display_name, email, user_id):
|
| 673 |
+
if not user_id:
|
| 674 |
+
return "Please log in to update your profile"
|
| 675 |
+
user = data_store.get_user_by_id(user_id)
|
| 676 |
+
if user:
|
| 677 |
+
user["display_name"] = display_name
|
| 678 |
+
user["email"] = email
|
| 679 |
+
return "Profile updated successfully"
|
| 680 |
+
return "User not found"
|
| 681 |
+
|
| 682 |
+
def logout():
|
| 683 |
+
data_store.current_user_id = None
|
| 684 |
+
return "", gr.update(visible=True), gr.update(visible=False), "", "", "", "", "", "", ""
|
| 685 |
+
|
| 686 |
+
def refresh_content(user_id):
|
| 687 |
+
if not user_id:
|
| 688 |
+
return "", "", ""
|
| 689 |
+
return (
|
| 690 |
+
load_recommended_blogs(user_id),
|
| 691 |
+
load_user_blogs(user_id),
|
| 692 |
+
load_chat_rooms()
|
| 693 |
+
)
|
| 694 |
+
|
| 695 |
+
# JavaScript for click events
|
| 696 |
+
js_select_blog = """
|
| 697 |
+
function selectBlog(blogId) {
|
| 698 |
+
document.querySelector('input[name="blog_id"]').value = blogId;
|
| 699 |
+
document.querySelector('input[name="blog_id"]').dispatchEvent(new Event('input'));
|
| 700 |
+
}
|
| 701 |
+
"""
|
| 702 |
+
js_select_chat = """
|
| 703 |
+
function selectChat(chatId) {
|
| 704 |
+
document.querySelector('input[name="chat_id"]').value = chatId;
|
| 705 |
+
document.querySelector('input[name="chat_id"]').dispatchEvent(new Event('input'));
|
| 706 |
+
}
|
| 707 |
+
"""
|
| 708 |
+
|
| 709 |
+
# Hidden inputs for JavaScript events
|
| 710 |
+
blog_id_input = gr.Textbox(value="", label="Blog ID", name="blog_id", visible=False)
|
| 711 |
+
chat_id_input = gr.Textbox(value="", label="Chat ID", name="chat_id", visible=False)
|
| 712 |
+
|
| 713 |
+
# Connect events
|
| 714 |
+
login_button.click(
|
| 715 |
+
fn=login,
|
| 716 |
+
inputs=[username_input, password_input],
|
| 717 |
+
outputs=[
|
| 718 |
+
user_id_state,
|
| 719 |
+
login_status,
|
| 720 |
+
auth_group,
|
| 721 |
+
main_group,
|
| 722 |
+
recommended_blogs,
|
| 723 |
+
my_blogs_list,
|
| 724 |
+
chat_list,
|
| 725 |
+
display_name,
|
| 726 |
+
email,
|
| 727 |
+
user_role,
|
| 728 |
+
user_badges
|
| 729 |
+
],
|
| 730 |
+
show_progress=True
|
| 731 |
+
)
|
| 732 |
+
|
| 733 |
+
blog_refresh_button.click(
|
| 734 |
+
fn=load_blogs,
|
| 735 |
+
inputs=[],
|
| 736 |
+
outputs=[blog_list],
|
| 737 |
+
show_progress=True
|
| 738 |
+
)
|
| 739 |
+
|
| 740 |
+
blog_id_input.input(
|
| 741 |
+
fn=view_blog,
|
| 742 |
+
inputs=[blog_id_input],
|
| 743 |
+
outputs=[current_blog_id, blog_title, blog_author, blog_content, blog_tags, blog_comments],
|
| 744 |
+
_js=js_select_blog
|
| 745 |
+
)
|
| 746 |
+
|
| 747 |
+
submit_comment.click(
|
| 748 |
+
fn=add_comment,
|
| 749 |
+
inputs=[current_blog_id, new_comment, user_id_state],
|
| 750 |
+
outputs=[blog_create_status, blog_comments],
|
| 751 |
+
show_progress=True
|
| 752 |
+
)
|
| 753 |
+
|
| 754 |
+
create_blog_button.click(
|
| 755 |
+
fn=create_blog,
|
| 756 |
+
inputs=[new_blog_title, new_blog_content, new_blog_tags, user_id_state],
|
| 757 |
+
outputs=[blog_create_status],
|
| 758 |
+
show_progress=True
|
| 759 |
+
)
|
| 760 |
+
|
| 761 |
+
create_chat_button.click(
|
| 762 |
+
fn=create_chat_room,
|
| 763 |
+
inputs=[new_chat_name, user_id_state],
|
| 764 |
+
outputs=[current_chat_id, chat_list],
|
| 765 |
+
show_progress=True
|
| 766 |
+
)
|
| 767 |
+
|
| 768 |
+
chat_id_input.input(
|
| 769 |
+
fn=view_chat,
|
| 770 |
+
inputs=[chat_id_input],
|
| 771 |
+
outputs=[chat_messages, current_chat_id],
|
| 772 |
+
_js=js_select_chat
|
| 773 |
+
)
|
| 774 |
+
|
| 775 |
+
send_message_button.click(
|
| 776 |
+
fn=send_message,
|
| 777 |
+
inputs=[current_chat_id, new_message, user_id_state],
|
| 778 |
+
outputs=[moderation_status, chat_messages],
|
| 779 |
+
show_progress=True
|
| 780 |
+
)
|
| 781 |
+
|
| 782 |
+
update_profile_button.click(
|
| 783 |
+
fn=update_profile,
|
| 784 |
+
inputs=[display_name, email, user_id_state],
|
| 785 |
+
outputs=[profile_update_status],
|
| 786 |
+
show_progress=True
|
| 787 |
+
)
|
| 788 |
+
|
| 789 |
+
logout_button.click(
|
| 790 |
+
fn=logout,
|
| 791 |
+
inputs=[],
|
| 792 |
+
outputs=[
|
| 793 |
+
user_id_state,
|
| 794 |
+
auth_group,
|
| 795 |
+
main_group,
|
| 796 |
+
recommended_blogs,
|
| 797 |
+
my_blogs_list,
|
| 798 |
+
chat_list,
|
| 799 |
+
display_name,
|
| 800 |
+
email,
|
| 801 |
+
user_role,
|
| 802 |
+
user_badges
|
| 803 |
+
],
|
| 804 |
+
show_progress=True
|
| 805 |
+
)
|
| 806 |
+
|
| 807 |
+
refresh_button.click(
|
| 808 |
+
fn=refresh_content,
|
| 809 |
+
inputs=[user_id_state],
|
| 810 |
+
outputs=[recommended_blogs, my_blogs_list, chat_list],
|
| 811 |
+
show_progress=True
|
| 812 |
+
)
|
| 813 |
+
|
| 814 |
+
# Initial load
|
| 815 |
+
blog_list.value = load_blogs()
|
| 816 |
+
|
| 817 |
+
return interface
|
| 818 |
+
|
| 819 |
+
# Launch the interface
|
| 820 |
+
def launch_app():
|
| 821 |
+
interface = create_interface()
|
| 822 |
+
interface.launch(share=False, server_port=None)
|
| 823 |
+
|
| 824 |
+
if __name__ == "__main__":
|
| 825 |
+
launch_app()
|