190 lines
6.4 KiB
Python
190 lines
6.4 KiB
Python
from .common import (
|
|
MAX_FEED_MESSAGES,
|
|
current_user,
|
|
jsonify,
|
|
request,
|
|
get_db,
|
|
build_feed_payload,
|
|
room_by_id,
|
|
can_access_room,
|
|
get_channel_by_id,
|
|
can_access_channel,
|
|
validate_dm_access,
|
|
)
|
|
|
|
|
|
def register_feed_routes(app):
|
|
@app.route("/api/feed")
|
|
def get_feed():
|
|
user = current_user()
|
|
after_raw = request.args.get("after_id", "").strip()
|
|
after_id = 0
|
|
|
|
if after_raw:
|
|
try:
|
|
after_id = max(0, int(after_raw))
|
|
except ValueError:
|
|
return jsonify({"error": "after_id must be a non-negative integer."}), 400
|
|
|
|
base_select = f"""
|
|
SELECT
|
|
m.id,
|
|
m.room_id,
|
|
m.channel_id,
|
|
m.direct_conversation_id,
|
|
m.user_id,
|
|
m.username,
|
|
m.text,
|
|
m.created_at,
|
|
m.attachment_id,
|
|
m.parent_message_id,
|
|
(
|
|
SELECT COUNT(*)
|
|
FROM messages AS thread_reply
|
|
WHERE thread_reply.parent_message_id = m.id
|
|
) AS thread_reply_count,
|
|
r.slug AS room_slug,
|
|
r.name AS room_name,
|
|
r.visibility AS room_visibility,
|
|
c.slug AS channel_slug,
|
|
c.name AS channel_name,
|
|
t.slug AS team_slug,
|
|
t.name AS team_name,
|
|
a.original_name AS attachment_original_name,
|
|
a.mime_type AS attachment_mime_type,
|
|
a.size_bytes AS attachment_size_bytes,
|
|
u.role AS user_role,
|
|
us.name_color AS user_name_color
|
|
FROM messages AS m
|
|
JOIN users AS u
|
|
ON u.id = m.user_id
|
|
LEFT JOIN user_settings AS us
|
|
ON us.user_id = u.id
|
|
LEFT JOIN rooms AS r
|
|
ON r.id = m.room_id
|
|
LEFT JOIN channels AS c
|
|
ON c.id = m.channel_id
|
|
AND c.is_active = 1
|
|
LEFT JOIN teams AS t
|
|
ON t.id = c.team_id
|
|
AND t.is_active = 1
|
|
LEFT JOIN attachments AS a
|
|
ON a.id = m.attachment_id
|
|
"""
|
|
|
|
params = []
|
|
if user and user["role"] in {"moderator", "admin"}:
|
|
access_clause = """
|
|
(
|
|
(m.direct_conversation_id IS NULL AND r.id IS NOT NULL AND r.is_active = 1)
|
|
OR
|
|
(m.direct_conversation_id IS NULL AND c.id IS NOT NULL AND c.is_active = 1 AND t.is_active = 1)
|
|
OR
|
|
(
|
|
m.direct_conversation_id IS NOT NULL
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM direct_conversation_members AS dcm
|
|
WHERE dcm.direct_conversation_id = m.direct_conversation_id
|
|
AND dcm.user_id = ?
|
|
)
|
|
)
|
|
)
|
|
"""
|
|
params.append(user["id"])
|
|
elif user:
|
|
access_clause = """
|
|
(
|
|
(
|
|
m.direct_conversation_id IS NULL
|
|
AND r.id IS NOT NULL
|
|
AND r.is_active = 1
|
|
AND (
|
|
r.visibility = 'public'
|
|
OR EXISTS (
|
|
SELECT 1
|
|
FROM room_members AS rm
|
|
WHERE rm.room_id = r.id
|
|
AND rm.user_id = ?
|
|
)
|
|
)
|
|
)
|
|
OR
|
|
(
|
|
m.direct_conversation_id IS NULL
|
|
AND c.id IS NOT NULL
|
|
AND c.is_active = 1
|
|
AND t.is_active = 1
|
|
AND c.legacy_room_id IS NULL
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM team_members AS tm
|
|
WHERE tm.team_id = c.team_id
|
|
AND tm.user_id = ?
|
|
)
|
|
)
|
|
OR
|
|
(
|
|
m.direct_conversation_id IS NOT NULL
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM direct_conversation_members AS dcm
|
|
WHERE dcm.direct_conversation_id = m.direct_conversation_id
|
|
AND dcm.user_id = ?
|
|
)
|
|
)
|
|
)
|
|
"""
|
|
params.extend([user["id"], user["id"], user["id"]])
|
|
else:
|
|
access_clause = """
|
|
m.direct_conversation_id IS NULL
|
|
AND r.id IS NOT NULL
|
|
AND r.is_active = 1
|
|
AND r.visibility = 'public'
|
|
"""
|
|
|
|
if after_raw:
|
|
query = f"""
|
|
{base_select}
|
|
WHERE m.parent_message_id IS NULL
|
|
AND {access_clause}
|
|
AND m.id > ?
|
|
ORDER BY m.id ASC
|
|
LIMIT ?
|
|
"""
|
|
query_params = [*params, after_id, MAX_FEED_MESSAGES]
|
|
|
|
with get_db() as db:
|
|
rows = db.execute(query, tuple(query_params)).fetchall()
|
|
|
|
entries = [build_feed_payload(row, user) for row in rows]
|
|
latest_id = entries[-1]["id"] if entries else after_id
|
|
return jsonify(
|
|
{
|
|
"entries": entries,
|
|
"latest_id": latest_id,
|
|
"has_more": len(entries) == MAX_FEED_MESSAGES,
|
|
}
|
|
)
|
|
|
|
query = f"""
|
|
SELECT *
|
|
FROM (
|
|
{base_select}
|
|
WHERE m.parent_message_id IS NULL
|
|
AND {access_clause}
|
|
ORDER BY m.id DESC
|
|
LIMIT ?
|
|
)
|
|
ORDER BY id ASC
|
|
"""
|
|
query_params = [*params, MAX_FEED_MESSAGES]
|
|
|
|
with get_db() as db:
|
|
rows = db.execute(query, tuple(query_params)).fetchall()
|
|
|
|
entries = [build_feed_payload(row, user) for row in rows]
|
|
latest_id = entries[-1]["id"] if entries else 0
|
|
return jsonify({"entries": entries, "latest_id": latest_id, "has_more": False})
|