import logging
from datetime import datetime, timezone
from fastapi import APIRouter, Request
from fastapi.responses import RedirectResponse
from devplacepy.database import get_table
from devplacepy.utils import generate_uid, require_user
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/{target_type}/{target_uid}")
async def vote(request: Request, target_type: str, target_uid: str):
user = require_user(request)
form = await request.form()
value = int(form.get("value", "1"))
if value not in (1, -1):
return RedirectResponse(url="/feed", status_code=302)
votes = get_table("votes")
existing = votes.find_one(user_uid=user["uid"], target_uid=target_uid, target_type=target_type)
if existing:
if int(existing["value"]) == value:
votes.delete(id=existing["id"])
else:
votes.update({"id": existing["id"], "value": value}, ["id"])
else:
votes.insert({
"uid": generate_uid(),
"user_uid": user["uid"],
"target_uid": target_uid,
"target_type": target_type,
"value": value,
"created_at": datetime.now(timezone.utc).isoformat(),
})
up_count = len(list(votes.find(target_uid=target_uid, value=1)))
down_count = len(list(votes.find(target_uid=target_uid, value=-1)))
net = up_count - down_count
if target_type == "post":
posts = get_table("posts")
posts.update({"uid": target_uid, "stars": net}, ["uid"])
elif target_type == "project":
projects = get_table("projects")
projects.update({"uid": target_uid, "stars": net}, ["uid"])
elif target_type == "gist":
gists = get_table("gists")
gists.update({"uid": target_uid, "stars": net}, ["uid"])
if value == 1:
target_owner_uid = None
if target_type == "post":
target_owner = posts.find_one(uid=target_uid)
if target_owner:
target_owner_uid = target_owner["user_uid"]
elif target_type == "comment":
comments = get_table("comments")
target_comment = comments.find_one(uid=target_uid)
if target_comment:
target_owner_uid = target_comment["user_uid"]
elif target_type == "gist":
gists = get_table("gists")
target_gist = gists.find_one(uid=target_uid)
if target_gist:
target_owner_uid = target_gist["user_uid"]
if target_owner_uid and target_owner_uid != user["uid"]:
label = {"post": "post", "comment": "comment", "gist": "gist"}.get(target_type, "gist")
notifications = get_table("notifications")
notifications.insert({
"uid": generate_uid(),
"user_uid": target_owner_uid,
"type": "vote",
"message": f"{user['username']} ++'d your {label}",
"related_uid": user["uid"],
"read": False,
"created_at": datetime.now(timezone.utc).isoformat(),
})
referer = request.headers.get("Referer", "/feed")
return RedirectResponse(url=referer, status_code=302)