# retoor import logging from datetime import datetime, timezone from fastapi import APIRouter, Request from devplacepy.database import ( get_table, get_users_by_uids, get_user_votes, get_vote_counts, get_user_stars, ) from devplacepy.content import apply_vote, delete_comment_record, is_owner, is_admin from devplacepy.services.audit import record as audit from devplacepy.services.correction import schedule_correction from devplacepy.services.ai_modifier import schedule_modification from devplacepy.services.devrant.params import merge_params from devplacepy.services.devrant.tokens import resolve_user from devplacepy.services.devrant.ids import as_int, comment_by_id from devplacepy.services.devrant.serializers import serialize_comment from devplacepy.routers.devrant._shared import dr_ok, dr_error, unauthorized logger = logging.getLogger(__name__) router = APIRouter() def _rant_id_for(comment: dict) -> int: post = get_table("posts").find_one(uid=comment.get("target_uid")) return int(post["id"]) if post else 0 def _serialize_single(comment: dict, viewer) -> dict: authors = get_users_by_uids([comment["user_uid"]]) user_scores = {comment["user_uid"]: get_user_stars(comment["user_uid"])} ups, downs = get_vote_counts([comment["uid"]]) score_map = {comment["uid"]: ups.get(comment["uid"], 0) - downs.get(comment["uid"], 0)} my_votes = get_user_votes(viewer["uid"], [comment["uid"]]) if viewer else {} return serialize_comment( comment, _rant_id_for(comment), authors=authors, user_scores=user_scores, my_votes=my_votes, score_map=score_map, ) @router.get("/comments/{comment_id}") async def get_comment(request: Request, comment_id: str): params = await merge_params(request) viewer = resolve_user(params) comment = comment_by_id(comment_id) if not comment: return dr_error("Invalid comment specified in path.") return dr_ok(comment=_serialize_single(comment, viewer)) @router.post("/comments/{comment_id}") async def edit_comment(request: Request, comment_id: str): params = await merge_params(request) user = resolve_user(params) if not user: return unauthorized() comment = comment_by_id(comment_id) if not comment: return dr_error("Invalid comment specified in path.") if not is_owner(comment, user): return dr_error("You can only edit your own comments.", fail_reason="not_owner") text = (params.get("comment") or "").strip() if len(text) < 1 or len(text) > 1000: return dr_error("Invalid comment length.", fail_reason="length") get_table("comments").update( { "uid": comment["uid"], "content": text, "updated_at": datetime.now(timezone.utc).isoformat(), }, ["uid"], ) schedule_correction(user, "comments", comment["uid"], request) schedule_modification(user, "comments", comment["uid"], request) audit.record( request, "comment.edit", user=user, target_type="comment", target_uid=comment["uid"], origin="devrant", summary=f"{user['username']} edited comment {comment['id']}", links=[audit.target("comment", comment["uid"])], ) return dr_ok() @router.delete("/comments/{comment_id}") async def delete_comment(request: Request, comment_id: str): params = await merge_params(request) user = resolve_user(params) if not user: return unauthorized() comment = comment_by_id(comment_id) if not comment: return dr_error("Invalid comment specified in path.") if not (is_owner(comment, user) or is_admin(user)): return dr_error("You can only delete your own comments.") delete_comment_record(request, user, comment) return dr_ok() @router.post("/comments/{comment_id}/vote") async def vote_comment(request: Request, comment_id: str): params = await merge_params(request) user = resolve_user(params) if not user: return unauthorized() comment = comment_by_id(comment_id) if not comment: return dr_error("Invalid comment specified in path.") value = as_int(params.get("vote")) if value not in (-1, 0, 1): return dr_error("Invalid vote.") apply_vote(request, user, "comment", comment["uid"], value) return dr_ok()