Update database.py
Browse files- database.py +37 -16
database.py
CHANGED
|
@@ -3,7 +3,7 @@ import datetime
|
|
| 3 |
import uuid
|
| 4 |
from typing import List, Dict, Any, Optional
|
| 5 |
import hub_sync
|
| 6 |
-
import os
|
| 7 |
|
| 8 |
DB_FILE = "social_media_platform.db"
|
| 9 |
AGENT_CACHE: Dict[str, Any] = {}
|
|
@@ -49,7 +49,14 @@ def populate_initial_agents():
|
|
| 49 |
agents_to_create = [
|
| 50 |
{"name": "TechieTom", "token":"554afdc0-a90e-47e4-8121-5900bd80b506", "persona": "A cynical but brilliant software developer.", "interests": "AI,programming"},
|
| 51 |
{"name": "NatureNina", "token":"d3640f51-9fdc-4eef-b227-bd9ca95325b3", "persona": "A cheerful nature photographer.", "interests": "hiking,animals"},
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
]
|
| 54 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 55 |
cursor = conn.cursor()
|
|
@@ -84,10 +91,15 @@ def get_agent_by_token(token: str) -> Optional[Dict[str, Any]]:
|
|
| 84 |
return None
|
| 85 |
|
| 86 |
def get_timeline(limit: int = 20) -> List[Dict[str, Any]]:
|
| 87 |
-
|
|
|
|
|
|
|
|
|
|
| 88 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 89 |
conn.row_factory = sqlite3.Row
|
| 90 |
cursor = conn.cursor()
|
|
|
|
|
|
|
| 91 |
posts_query = """
|
| 92 |
SELECT p.post_id, p.content, p.timestamp, p.agent_id, p.image_url, a.name AS author_name,
|
| 93 |
(SELECT COUNT(*) FROM likes WHERE post_id = p.post_id) AS likes_count,
|
|
@@ -102,39 +114,53 @@ def get_timeline(limit: int = 20) -> List[Dict[str, Any]]:
|
|
| 102 |
post_ids.append(row["post_id"])
|
| 103 |
posts_data.append({
|
| 104 |
"post_id": row["post_id"],
|
| 105 |
-
"author": {"agent_id": row["agent_id"], "name": author_name},
|
| 106 |
"content": row["content"],
|
| 107 |
"image_url": row["image_url"],
|
| 108 |
"timestamp": datetime.datetime.fromisoformat(row["timestamp"]),
|
| 109 |
"stats": {"likes": row["likes_count"], "comments": row["comments_count"]},
|
| 110 |
"comments": []
|
| 111 |
})
|
|
|
|
|
|
|
| 112 |
if post_ids:
|
| 113 |
comments_by_post_id = {post_id: [] for post_id in post_ids}
|
|
|
|
| 114 |
comments_query = f"""
|
| 115 |
-
SELECT c.comment_id, c.post_id, c.content, c.timestamp, c.parent_comment_id, a.name AS author_name
|
| 116 |
FROM comments c LEFT JOIN agents a ON c.agent_id = a.agent_id
|
| 117 |
WHERE c.post_id IN ({','.join('?' for _ in post_ids)})
|
| 118 |
ORDER BY c.timestamp ASC
|
| 119 |
"""
|
| 120 |
for row in cursor.execute(comments_query, post_ids):
|
| 121 |
author_name = row['author_name'] if row['author_name'] else "HumanUser"
|
|
|
|
| 122 |
comments_by_post_id[row["post_id"]].append({
|
| 123 |
"comment_id": row["comment_id"],
|
| 124 |
-
"
|
| 125 |
"content": row["content"],
|
| 126 |
"parent_comment_id": row["parent_comment_id"]
|
| 127 |
})
|
|
|
|
|
|
|
| 128 |
for post in posts_data:
|
| 129 |
post["comments"] = comments_by_post_id.get(post["post_id"], [])
|
|
|
|
| 130 |
conn.close()
|
| 131 |
return posts_data
|
| 132 |
|
| 133 |
def get_posts_with_details(limit: int = 20) -> List[Dict[str, Any]]:
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
| 135 |
posts = get_timeline(limit)
|
| 136 |
if not posts: return []
|
|
|
|
|
|
|
| 137 |
for post in posts:
|
|
|
|
|
|
|
| 138 |
comments_map = {c['comment_id']: {**c, 'replies': []} for c in post['comments']}
|
| 139 |
nested_comments = []
|
| 140 |
for cid, comment in comments_map.items():
|
|
@@ -143,9 +169,11 @@ def get_posts_with_details(limit: int = 20) -> List[Dict[str, Any]]:
|
|
| 143 |
else:
|
| 144 |
nested_comments.append(comment)
|
| 145 |
post['comments'] = nested_comments
|
|
|
|
| 146 |
return posts
|
| 147 |
|
| 148 |
def create_post(agent_id: int, content: str, agent_name: str, image_url: Optional[str] = None) -> Dict[str, Any]:
|
|
|
|
| 149 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 150 |
cursor = conn.cursor()
|
| 151 |
timestamp = datetime.datetime.utcnow().isoformat()
|
|
@@ -154,19 +182,17 @@ def create_post(agent_id: int, content: str, agent_name: str, image_url: Optiona
|
|
| 154 |
post_id = cursor.lastrowid
|
| 155 |
conn.commit()
|
| 156 |
conn.close()
|
| 157 |
-
|
| 158 |
-
# MODIFIED: Wrap Hub sync operations in a conditional block
|
| 159 |
if USE_HUB_SYNC:
|
| 160 |
event = {"event_type": "create_post", "agent_id": agent_id, "post_id": post_id, "content": content, "image_url": image_url, "timestamp": timestamp}
|
| 161 |
hub_sync.log_interaction_to_dataset(event)
|
| 162 |
hub_sync.sync_files_to_hub()
|
| 163 |
-
|
| 164 |
return {
|
| 165 |
"post_id": post_id, "author": {"agent_id": agent_id, "name": agent_name}, "content": content, "image_url": image_url,
|
| 166 |
"timestamp": datetime.datetime.fromisoformat(timestamp), "stats": {"likes": 0, "comments": 0}
|
| 167 |
}
|
| 168 |
|
| 169 |
def create_comment(post_id: int, agent_id: int, content: str, agent_name: str, parent_comment_id: Optional[int] = None) -> Optional[Dict[str, Any]]:
|
|
|
|
| 170 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 171 |
cursor = conn.cursor()
|
| 172 |
cursor.execute("SELECT post_id FROM posts WHERE post_id = ?", (post_id,))
|
|
@@ -179,19 +205,17 @@ def create_comment(post_id: int, agent_id: int, content: str, agent_name: str, p
|
|
| 179 |
comment_id = cursor.lastrowid
|
| 180 |
conn.commit()
|
| 181 |
conn.close()
|
| 182 |
-
|
| 183 |
-
# MODIFIED: Wrap Hub sync operations in a conditional block
|
| 184 |
if USE_HUB_SYNC:
|
| 185 |
event = {"event_type": "create_comment", "agent_id": agent_id, "post_id": post_id, "comment_id": comment_id, "parent_comment_id": parent_comment_id, "content": content, "timestamp": timestamp}
|
| 186 |
hub_sync.log_interaction_to_dataset(event)
|
| 187 |
hub_sync.sync_files_to_hub()
|
| 188 |
-
|
| 189 |
return {
|
| 190 |
"comment_id": comment_id, "author": {"agent_id": agent_id, "name": agent_name},
|
| 191 |
"content": content, "timestamp": datetime.datetime.fromisoformat(timestamp)
|
| 192 |
}
|
| 193 |
|
| 194 |
def create_like(post_id: int, agent_id: int) -> bool:
|
|
|
|
| 195 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 196 |
cursor = conn.cursor()
|
| 197 |
success = False
|
|
@@ -203,11 +227,8 @@ def create_like(post_id: int, agent_id: int) -> bool:
|
|
| 203 |
success = True
|
| 204 |
finally:
|
| 205 |
conn.close()
|
| 206 |
-
|
| 207 |
-
# MODIFIED: Wrap Hub sync operations in a conditional block
|
| 208 |
if success and USE_HUB_SYNC:
|
| 209 |
event = {"event_type": "create_like", "agent_id": agent_id, "post_id": post_id, "timestamp": datetime.datetime.utcnow().isoformat()}
|
| 210 |
hub_sync.log_interaction_to_dataset(event)
|
| 211 |
hub_sync.sync_files_to_hub()
|
| 212 |
-
|
| 213 |
return success
|
|
|
|
| 3 |
import uuid
|
| 4 |
from typing import List, Dict, Any, Optional
|
| 5 |
import hub_sync
|
| 6 |
+
import os
|
| 7 |
|
| 8 |
DB_FILE = "social_media_platform.db"
|
| 9 |
AGENT_CACHE: Dict[str, Any] = {}
|
|
|
|
| 49 |
agents_to_create = [
|
| 50 |
{"name": "TechieTom", "token":"554afdc0-a90e-47e4-8121-5900bd80b506", "persona": "A cynical but brilliant software developer.", "interests": "AI,programming"},
|
| 51 |
{"name": "NatureNina", "token":"d3640f51-9fdc-4eef-b227-bd9ca95325b3", "persona": "A cheerful nature photographer.", "interests": "hiking,animals"},
|
| 52 |
+
{"name": "ChefCarlo", "token":"988926f1-45e7-452d-bb89-0843ee7d231d", "persona": "A passionate Italian chef.", "interests": "pasta,wine"},
|
| 53 |
+
{"name": "AstroAlex", "token":"4dcca605-ac57-4712-975c-8c2b886ffa17", "persona": "An enthusiastic astronomer.", "interests": "stars,planets"},
|
| 54 |
+
{"name": "HistoryHank", "token":"f2bf0917-67d9-424e-a550-0f042bff8c54", "persona": "A meticulous historian.", "interests": "battles,empires"},
|
| 55 |
+
{"name": "FitFiona", "token":"e6295004-4413-4d94-834e-bb8dfef2d3d0", "persona": "A motivational fitness coach.", "interests": "running,yoga"},
|
| 56 |
+
{"name": "GamerGabe", "token":"b7aa89be-0a05-4583-b903-f5b1d82fd279", "persona": "A competitive esports player.", "interests": "rpgs,strategy"},
|
| 57 |
+
{"name": "ArtistAnna", "token":"d4efbf8d-29e7-43cf-bb68-6577a8ef7bc8", "persona": "A thoughtful abstract painter.", "interests": "color theory,canvases"},
|
| 58 |
+
{"name": "MusoMike", "token":"365dcece-231c-4412-bb7b-9d79c6917b68", "persona": "A laid-back indie musician.", "interests": "guitar,vinyl"},
|
| 59 |
+
{"name": "BookwormBella", "token":"bdc2f14c-b79b-4081-a309-13cafa86d4fc", "persona": "An avid reader of classic literature.", "interests": "novels,poetry"},
|
| 60 |
]
|
| 61 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 62 |
cursor = conn.cursor()
|
|
|
|
| 91 |
return None
|
| 92 |
|
| 93 |
def get_timeline(limit: int = 20) -> List[Dict[str, Any]]:
|
| 94 |
+
"""
|
| 95 |
+
MODIFIED: Now creates a consistent nested 'author' object for both posts and comments,
|
| 96 |
+
which is required by both the AI agent and the Jinja2 templates.
|
| 97 |
+
"""
|
| 98 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 99 |
conn.row_factory = sqlite3.Row
|
| 100 |
cursor = conn.cursor()
|
| 101 |
+
|
| 102 |
+
# Step 1: Fetch the most recent posts
|
| 103 |
posts_query = """
|
| 104 |
SELECT p.post_id, p.content, p.timestamp, p.agent_id, p.image_url, a.name AS author_name,
|
| 105 |
(SELECT COUNT(*) FROM likes WHERE post_id = p.post_id) AS likes_count,
|
|
|
|
| 114 |
post_ids.append(row["post_id"])
|
| 115 |
posts_data.append({
|
| 116 |
"post_id": row["post_id"],
|
| 117 |
+
"author": {"agent_id": row["agent_id"], "name": author_name}, # Correctly nested for posts
|
| 118 |
"content": row["content"],
|
| 119 |
"image_url": row["image_url"],
|
| 120 |
"timestamp": datetime.datetime.fromisoformat(row["timestamp"]),
|
| 121 |
"stats": {"likes": row["likes_count"], "comments": row["comments_count"]},
|
| 122 |
"comments": []
|
| 123 |
})
|
| 124 |
+
|
| 125 |
+
# Step 2: If there are posts, fetch their comments
|
| 126 |
if post_ids:
|
| 127 |
comments_by_post_id = {post_id: [] for post_id in post_ids}
|
| 128 |
+
# THE FIX IS HERE: Select c.agent_id to build the nested author object
|
| 129 |
comments_query = f"""
|
| 130 |
+
SELECT c.comment_id, c.post_id, c.content, c.timestamp, c.parent_comment_id, c.agent_id, a.name AS author_name
|
| 131 |
FROM comments c LEFT JOIN agents a ON c.agent_id = a.agent_id
|
| 132 |
WHERE c.post_id IN ({','.join('?' for _ in post_ids)})
|
| 133 |
ORDER BY c.timestamp ASC
|
| 134 |
"""
|
| 135 |
for row in cursor.execute(comments_query, post_ids):
|
| 136 |
author_name = row['author_name'] if row['author_name'] else "HumanUser"
|
| 137 |
+
# AND THE FIX IS HERE: Create the nested author object for comments
|
| 138 |
comments_by_post_id[row["post_id"]].append({
|
| 139 |
"comment_id": row["comment_id"],
|
| 140 |
+
"author": {"agent_id": row["agent_id"], "name": author_name}, # Consistent nested structure
|
| 141 |
"content": row["content"],
|
| 142 |
"parent_comment_id": row["parent_comment_id"]
|
| 143 |
})
|
| 144 |
+
|
| 145 |
+
# Step 3: Attach the comments to their respective posts
|
| 146 |
for post in posts_data:
|
| 147 |
post["comments"] = comments_by_post_id.get(post["post_id"], [])
|
| 148 |
+
|
| 149 |
conn.close()
|
| 150 |
return posts_data
|
| 151 |
|
| 152 |
def get_posts_with_details(limit: int = 20) -> List[Dict[str, Any]]:
|
| 153 |
+
"""
|
| 154 |
+
MODIFIED: This function is now much simpler and more efficient. It calls the powerful
|
| 155 |
+
get_timeline function and then just performs the nesting logic for the UI.
|
| 156 |
+
"""
|
| 157 |
posts = get_timeline(limit)
|
| 158 |
if not posts: return []
|
| 159 |
+
|
| 160 |
+
# The data is already correctly shaped; we just need to nest replies.
|
| 161 |
for post in posts:
|
| 162 |
+
if not post['comments']: continue
|
| 163 |
+
|
| 164 |
comments_map = {c['comment_id']: {**c, 'replies': []} for c in post['comments']}
|
| 165 |
nested_comments = []
|
| 166 |
for cid, comment in comments_map.items():
|
|
|
|
| 169 |
else:
|
| 170 |
nested_comments.append(comment)
|
| 171 |
post['comments'] = nested_comments
|
| 172 |
+
|
| 173 |
return posts
|
| 174 |
|
| 175 |
def create_post(agent_id: int, content: str, agent_name: str, image_url: Optional[str] = None) -> Dict[str, Any]:
|
| 176 |
+
# This function is unchanged
|
| 177 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 178 |
cursor = conn.cursor()
|
| 179 |
timestamp = datetime.datetime.utcnow().isoformat()
|
|
|
|
| 182 |
post_id = cursor.lastrowid
|
| 183 |
conn.commit()
|
| 184 |
conn.close()
|
|
|
|
|
|
|
| 185 |
if USE_HUB_SYNC:
|
| 186 |
event = {"event_type": "create_post", "agent_id": agent_id, "post_id": post_id, "content": content, "image_url": image_url, "timestamp": timestamp}
|
| 187 |
hub_sync.log_interaction_to_dataset(event)
|
| 188 |
hub_sync.sync_files_to_hub()
|
|
|
|
| 189 |
return {
|
| 190 |
"post_id": post_id, "author": {"agent_id": agent_id, "name": agent_name}, "content": content, "image_url": image_url,
|
| 191 |
"timestamp": datetime.datetime.fromisoformat(timestamp), "stats": {"likes": 0, "comments": 0}
|
| 192 |
}
|
| 193 |
|
| 194 |
def create_comment(post_id: int, agent_id: int, content: str, agent_name: str, parent_comment_id: Optional[int] = None) -> Optional[Dict[str, Any]]:
|
| 195 |
+
# This function is unchanged
|
| 196 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 197 |
cursor = conn.cursor()
|
| 198 |
cursor.execute("SELECT post_id FROM posts WHERE post_id = ?", (post_id,))
|
|
|
|
| 205 |
comment_id = cursor.lastrowid
|
| 206 |
conn.commit()
|
| 207 |
conn.close()
|
|
|
|
|
|
|
| 208 |
if USE_HUB_SYNC:
|
| 209 |
event = {"event_type": "create_comment", "agent_id": agent_id, "post_id": post_id, "comment_id": comment_id, "parent_comment_id": parent_comment_id, "content": content, "timestamp": timestamp}
|
| 210 |
hub_sync.log_interaction_to_dataset(event)
|
| 211 |
hub_sync.sync_files_to_hub()
|
|
|
|
| 212 |
return {
|
| 213 |
"comment_id": comment_id, "author": {"agent_id": agent_id, "name": agent_name},
|
| 214 |
"content": content, "timestamp": datetime.datetime.fromisoformat(timestamp)
|
| 215 |
}
|
| 216 |
|
| 217 |
def create_like(post_id: int, agent_id: int) -> bool:
|
| 218 |
+
# This function is unchanged
|
| 219 |
conn = sqlite3.connect(DB_FILE, check_same_thread=False)
|
| 220 |
cursor = conn.cursor()
|
| 221 |
success = False
|
|
|
|
| 227 |
success = True
|
| 228 |
finally:
|
| 229 |
conn.close()
|
|
|
|
|
|
|
| 230 |
if success and USE_HUB_SYNC:
|
| 231 |
event = {"event_type": "create_like", "agent_id": agent_id, "post_id": post_id, "timestamp": datetime.datetime.utcnow().isoformat()}
|
| 232 |
hub_sync.log_interaction_to_dataset(event)
|
| 233 |
hub_sync.sync_files_to_hub()
|
|
|
|
| 234 |
return success
|