mirror of
https://github.com/tanrax/org-social-relay
synced 2026-01-10 15:03:33 +01:00
90 lines
2.6 KiB
Python
90 lines
2.6 KiB
Python
"""
|
|
Utility functions for working with posts and feeds
|
|
"""
|
|
|
|
from typing import List
|
|
from app.feeds.models import Post, Profile
|
|
|
|
|
|
def get_parent_chain(post: Post, max_depth: int = 100) -> List[str]:
|
|
"""
|
|
Calculate the parent chain for a post.
|
|
|
|
Returns a list of post URLs from the root ancestor to the immediate parent.
|
|
For example, if the chain is: Alice → Bob → Carol → Dave → Current post
|
|
This returns: [Alice_URL, Bob_URL, Carol_URL, Dave_URL]
|
|
|
|
Args:
|
|
post: The Post object to calculate the chain for
|
|
max_depth: Maximum depth to traverse (prevents infinite loops)
|
|
|
|
Returns:
|
|
List of post URLs in order from root to immediate parent
|
|
"""
|
|
if not post.reply_to:
|
|
# This post is a root post (no parent)
|
|
return []
|
|
|
|
chain = []
|
|
current_reply_to = post.reply_to
|
|
depth = 0
|
|
|
|
while current_reply_to and depth < max_depth:
|
|
# Add current parent to chain
|
|
chain.append(current_reply_to)
|
|
|
|
# Parse the reply_to URL to find the parent post
|
|
try:
|
|
if "#" not in current_reply_to:
|
|
break
|
|
feed_url, post_id = current_reply_to.split("#", 1)
|
|
|
|
# Find the parent post
|
|
profile = Profile.objects.filter(feed=feed_url).first()
|
|
if not profile:
|
|
break
|
|
|
|
parent_post = Post.objects.filter(profile=profile, post_id=post_id).first()
|
|
|
|
if not parent_post:
|
|
break
|
|
|
|
# Move up to the next parent
|
|
current_reply_to = parent_post.reply_to
|
|
depth += 1
|
|
|
|
except (ValueError, AttributeError):
|
|
break
|
|
|
|
# Reverse the chain so it goes from root to immediate parent
|
|
chain.reverse()
|
|
|
|
return chain
|
|
|
|
|
|
def add_relay_headers(response):
|
|
"""
|
|
Add global ETag and Last-Modified headers to a response.
|
|
This ensures all endpoints return consistent caching headers.
|
|
|
|
The headers are retrieved from the RelayMetadata model, which is updated
|
|
by the scan_feeds task after each scan. This way:
|
|
- All endpoints return the same ETag and Last-Modified
|
|
- Headers are added even when serving cached responses
|
|
- The ETag changes only when feeds are actually scanned
|
|
|
|
Args:
|
|
response: Django REST framework Response object
|
|
|
|
Returns:
|
|
The same response object with headers added
|
|
"""
|
|
from app.feeds.models import RelayMetadata
|
|
|
|
etag, last_modified = RelayMetadata.get_global_metadata()
|
|
|
|
response["ETag"] = f'"{etag}"'
|
|
response["Last-Modified"] = last_modified.strftime("%a, %d %b %Y %H:%M:%S GMT")
|
|
|
|
return response
|