Files
org-social-relay/app/groups/views.py
2025-11-05 15:03:20 +01:00

153 lines
5.0 KiB
Python

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from django.conf import settings
from django.core.cache import cache
from app.feeds.models import Post, Profile
class GroupsView(APIView):
"""List all groups configured in the relay."""
def get(self, request):
"""GET /groups/ - List all groups from the relay."""
# Check if groups are configured
if not settings.ENABLED_GROUPS:
return Response(
{
"type": "Error",
"errors": ["No groups configured in this relay"],
"data": [],
},
status=status.HTTP_404_NOT_FOUND,
)
# Return group names (not slugs)
groups_data = list(settings.GROUPS_MAP.values())
# Build individual group links (name + slug in href)
group_links = []
for slug, name in settings.GROUPS_MAP.items():
group_links.append(
{"name": name, "href": f"/groups/{slug}/", "method": "GET"}
)
return Response(
{
"type": "Success",
"errors": [],
"data": groups_data,
"_links": {
"self": {"href": "/groups/", "method": "GET"},
"groups": group_links,
},
},
status=status.HTTP_200_OK,
)
class GroupMessagesView(APIView):
"""Get messages from a group."""
def get(self, request, group_slug):
"""GET /groups/{group_slug}/ - Get messages from a group."""
# Validate group_slug
if group_slug not in settings.ENABLED_GROUPS:
return Response(
{
"type": "Error",
"errors": [f"Group '{group_slug}' does not exist"],
"data": [],
"meta": {},
},
status=status.HTTP_404_NOT_FOUND,
)
# Get display name from slug
group_display_name = settings.GROUPS_MAP[group_slug]
# Try to get from cache
cache_key = f"group_messages:{group_slug}"
cached_data = cache.get(cache_key)
if cached_data:
return Response(cached_data, status=status.HTTP_200_OK)
# Get all posts for this group
group_posts = (
Post.objects.filter(group=group_slug)
.select_related("profile")
.order_by("-created_at")
)
# Build tree structure for messages (similar to replies)
messages_tree = []
posts_dict = {}
# First pass: Create post URLs and dict
for post in group_posts:
post_url = f"{post.profile.feed}#{post.post_id}"
posts_dict[post_url] = {
"post": post_url,
"children": [],
"reply_to": post.reply_to if post.reply_to else None,
}
# Second pass: Build tree structure
for post_url, post_data in posts_dict.items():
if post_data["reply_to"]:
# This is a reply, add it to parent's children
parent_url = post_data["reply_to"]
if parent_url in posts_dict:
posts_dict[parent_url]["children"].append(
{
"post": post_url,
"children": post_data["children"],
}
)
else:
# Parent not in group, add as top-level
messages_tree.append(
{
"post": post_url,
"children": post_data["children"],
}
)
else:
# Top-level post
messages_tree.append(
{
"post": post_url,
"children": post_data["children"],
}
)
# Get group members (unique profiles that have posted in this group)
member_profiles = Profile.objects.filter(posts__group=group_slug).distinct()
members_list = [profile.feed for profile in member_profiles]
# URL encode the group_slug for the join link template
from urllib.parse import quote
encoded_group_slug = quote(group_slug, safe="")
response_data = {
"type": "Success",
"errors": [],
"data": messages_tree,
"meta": {
"group": group_display_name,
"members": members_list,
},
"_links": {
"self": {"href": f"/groups/{encoded_group_slug}/", "method": "GET"},
"group-list": {"href": "/groups/", "method": "GET"},
},
}
# Cache permanently (will be cleared by scan_feeds task)
cache.set(cache_key, response_data, timeout=None)
return Response(response_data, status=status.HTTP_200_OK)