2026-07-04 19:22:11 +00:00
# retoor <retoor@molodetz.nl>
2026-07-27 11:17:48 +02:00
from .core import TTLCache , _in_clause , db , defaultdict
2026-07-04 19:22:11 +00:00
_comment_count_cache = TTLCache ( ttl = 15 , max_size = 10000 )
def get_comment_counts_by_post_uids ( post_uids ):
if not post_uids or "comments" not in db . tables :
return {}
result = {}
misses = []
for uid in post_uids :
cached = _comment_count_cache . get ( uid )
if cached is None :
misses . append ( uid )
else :
result [ uid ] = cached
if misses :
placeholders , params = _in_clause ( misses )
rows = db . query (
f "SELECT target_uid, COUNT(*) as c FROM comments WHERE target_type='post' AND target_uid IN ( { placeholders } ) AND deleted_at IS NULL GROUP BY target_uid" ,
** params ,
)
fetched = { r [ "target_uid" ]: r [ "c" ] for r in rows }
for uid in misses :
count = fetched . get ( uid , 0 )
_comment_count_cache . set ( uid , count )
result [ uid ] = count
return result
def get_post_counts_by_user_uids ( user_uids ):
if not user_uids or "posts" not in db . tables :
return {}
placeholders , params = _in_clause ( user_uids )
rows = db . query (
f "SELECT user_uid, COUNT(*) as c FROM posts WHERE user_uid IN ( { placeholders } ) AND deleted_at IS NULL GROUP BY user_uid" ,
** params ,
)
return { r [ "user_uid" ]: r [ "c" ] for r in rows }
def get_vote_counts ( target_uids ):
if not target_uids or "votes" not in db . tables :
return {}, {}
placeholders , params = _in_clause ( target_uids )
rows = db . query (
f "SELECT target_uid, value, COUNT(*) as c FROM votes WHERE target_uid IN ( { placeholders } ) AND deleted_at IS NULL GROUP BY target_uid, value" ,
** params ,
)
ups = {}
downs = {}
for r in rows :
if r [ "value" ] == 1 :
ups [ r [ "target_uid" ]] = r [ "c" ]
else :
downs [ r [ "target_uid" ]] = r [ "c" ]
return ups , downs
def get_user_votes ( user_uid , target_uids ):
if not user_uid or not target_uids or "votes" not in db . tables :
return {}
placeholders , params = _in_clause ( target_uids )
params [ "uid" ] = user_uid
rows = db . query (
f "SELECT target_uid, value FROM votes WHERE user_uid = :uid AND target_uid IN ( { placeholders } ) AND deleted_at IS NULL" ,
** params ,
)
return { r [ "target_uid" ]: r [ "value" ] for r in rows }
def get_reactions_by_targets ( target_type , target_uids , user = None ):
if not target_uids or "reactions" not in db . tables :
return {}
placeholders , params = _in_clause ( target_uids )
params [ "tt" ] = target_type
rows = db . query (
f "SELECT target_uid, emoji, COUNT(*) as c FROM reactions WHERE target_type=:tt AND target_uid IN ( { placeholders } ) AND deleted_at IS NULL GROUP BY target_uid, emoji" ,
** params ,
)
counts = defaultdict ( dict )
for row in rows :
counts [ row [ "target_uid" ]][ row [ "emoji" ]] = row [ "c" ]
mine = defaultdict ( list )
if user :
placeholders , params = _in_clause ( target_uids , prefix = "m" )
params [ "tt" ] = target_type
params [ "u" ] = user [ "uid" ]
for row in db . query (
f "SELECT target_uid, emoji FROM reactions WHERE user_uid=:u AND target_type=:tt AND target_uid IN ( { placeholders } ) AND deleted_at IS NULL" ,
** params ,
):
mine [ row [ "target_uid" ]] . append ( row [ "emoji" ])
result = {}
for uid in target_uids :
result [ uid ] = {
"counts" : dict ( counts . get ( uid , {})),
"mine" : list ( mine . get ( uid , [])),
}
return result
def get_user_bookmarks ( user_uid , target_type , target_uids ):
if not user_uid or not target_uids or "bookmarks" not in db . tables :
return set ()
placeholders , params = _in_clause ( target_uids )
params [ "u" ] = user_uid
params [ "tt" ] = target_type
rows = db . query (
f "SELECT target_uid FROM bookmarks WHERE user_uid=:u AND target_type=:tt AND target_uid IN ( { placeholders } ) AND deleted_at IS NULL" ,
** params ,
)
return { row [ "target_uid" ] for row in rows }
2026-09-12 20:32:31 +02:00
def get_user_notes ( user_uid , target_type , target_uids ):
if not user_uid or not target_uids or "notes" not in db . tables :
return {}
placeholders , params = _in_clause ( target_uids )
params [ "u" ] = user_uid
params [ "tt" ] = target_type
rows = db . query (
f "SELECT target_uid, content FROM notes WHERE user_uid=:u AND target_type=:tt AND target_uid IN ( { placeholders } ) AND deleted_at IS NULL" ,
** params ,
)
return { row [ "target_uid" ]: row [ "content" ] for row in rows }
2026-07-04 19:22:11 +00:00
def get_polls_by_post_uids ( post_uids , user = None ):
if not post_uids or "polls" not in db . tables :
return {}
placeholders , params = _in_clause ( post_uids )
polls = list (
db . query (
f "SELECT * FROM polls WHERE post_uid IN ( { placeholders } ) AND deleted_at IS NULL" ,
** params ,
)
)
if not polls :
return {}
poll_uids = [ poll [ "uid" ] for poll in polls ]
option_placeholders , option_params = _in_clause ( poll_uids , prefix = "o" )
options = list (
db . query (
f "SELECT * FROM poll_options WHERE poll_uid IN ( { option_placeholders } ) AND deleted_at IS NULL ORDER BY position" ,
** option_params ,
)
)
counts = defaultdict ( dict )
totals = defaultdict ( int )
if "poll_votes" in db . tables :
vote_placeholders , vote_params = _in_clause ( poll_uids , prefix = "v" )
for row in db . query (
f "SELECT poll_uid, option_uid, COUNT(*) as c FROM poll_votes WHERE poll_uid IN ( { vote_placeholders } ) AND deleted_at IS NULL GROUP BY poll_uid, option_uid" ,
** vote_params ,
):
counts [ row [ "poll_uid" ]][ row [ "option_uid" ]] = row [ "c" ]
totals [ row [ "poll_uid" ]] += row [ "c" ]
user_choice = {}
if user and "poll_votes" in db . tables :
placeholders , params = _in_clause ( poll_uids , prefix = "m" )
params [ "u" ] = user [ "uid" ]
for row in db . query (
f "SELECT poll_uid, option_uid FROM poll_votes WHERE user_uid=:u AND poll_uid IN ( { placeholders } ) AND deleted_at IS NULL" ,
** params ,
):
user_choice [ row [ "poll_uid" ]] = row [ "option_uid" ]
options_by_poll = defaultdict ( list )
for option in options :
options_by_poll [ option [ "poll_uid" ]] . append ( option )
result = {}
for poll in polls :
poll_uid = poll [ "uid" ]
total = totals . get ( poll_uid , 0 )
rendered = []
for option in options_by_poll . get ( poll_uid , []):
count = counts . get ( poll_uid , {}) . get ( option [ "uid" ], 0 )
rendered . append (
{
"uid" : option [ "uid" ],
"label" : option [ "label" ],
"count" : count ,
"pct" : round ( count * 100 / total ) if total else 0 ,
}
)
result [ poll [ "post_uid" ]] = {
"uid" : poll_uid ,
"question" : poll [ "question" ],
"options" : rendered ,
"total" : total ,
"my_choice" : user_choice . get ( poll_uid ),
}
return result
def get_poll_for_post ( post_uid , user = None ):
return get_polls_by_post_uids ([ post_uid ], user ) . get ( post_uid )
2026-07-26 20:50:56 +00:00