2026-05-10 09:08:12 +02:00
import dataset
import logging
2026-05-11 00:41:41 +02:00
from datetime import datetime
2026-05-10 09:08:12 +02:00
from devplacepy . config import DATABASE_URL
logger = logging . getLogger ( __name__ )
2026-05-11 03:14:43 +02:00
db = dataset . connect (
DATABASE_URL ,
engine_kwargs = {
" connect_args " : {
" timeout " : 30 ,
" check_same_thread " : False ,
} ,
} ,
on_connect_statements = [
" PRAGMA journal_mode=WAL " ,
" PRAGMA synchronous=NORMAL " ,
" PRAGMA busy_timeout=30000 " ,
" PRAGMA cache_size=-8000 " ,
" PRAGMA temp_store=MEMORY " ,
" PRAGMA mmap_size=268435456 " ,
] ,
)
def _index ( db , table , name , columns ) :
try :
if table in db . tables :
cols = " , " . join ( columns )
db . query ( f " CREATE INDEX IF NOT EXISTS { name } ON { table } ( { cols } ) " )
except Exception as e :
logger . warning ( f " Could not create index { name } on { table } : { e } " )
2026-05-10 09:08:12 +02:00
def init_db ( ) :
tables = db . tables
2026-05-11 03:14:43 +02:00
_index ( db , " users " , " idx_users_username " , [ " username " ] )
_index ( db , " users " , " idx_users_email " , [ " email " ] )
_index ( db , " posts " , " idx_posts_user_uid " , [ " user_uid " ] )
_index ( db , " posts " , " idx_posts_created_at " , [ " created_at " ] )
_index ( db , " posts " , " idx_posts_topic " , [ " topic " ] )
_index ( db , " comments " , " idx_comments_post_uid " , [ " post_uid " ] )
2026-05-11 20:49:45 +02:00
_index ( db , " comments " , " idx_comments_target " , [ " target_type " , " target_uid " ] )
2026-05-11 03:14:43 +02:00
_index ( db , " comments " , " idx_comments_user_uid " , [ " user_uid " ] )
_index ( db , " votes " , " idx_votes_target " , [ " target_uid " , " target_type " ] )
_index ( db , " messages " , " idx_messages_sender " , [ " sender_uid " ] )
_index ( db , " messages " , " idx_messages_receiver " , [ " receiver_uid " ] )
_index ( db , " notifications " , " idx_notifications_user " , [ " user_uid " ] )
_index ( db , " notifications " , " idx_notifications_user_read " , [ " user_uid " , " read " ] )
_index ( db , " sessions " , " idx_sessions_token " , [ " session_token " ] )
_index ( db , " projects " , " idx_projects_user " , [ " user_uid " ] )
_index ( db , " badges " , " idx_badges_user " , [ " user_uid " ] )
_index ( db , " follows " , " idx_follows_follower " , [ " follower_uid " ] )
_index ( db , " follows " , " idx_follows_following " , [ " following_uid " ] )
_index ( db , " password_resets " , " idx_password_resets_token " , [ " token " ] )
2026-05-11 00:41:41 +02:00
if " daily_topics " in tables :
existing = db [ " daily_topics " ] . find_one ( )
if not existing :
db [ " daily_topics " ] . insert ( {
" uid " : " default " ,
" title " : " Anthropic details how it improved Claude ' s safety... " ,
" summary " : " New techniques in AI safety research show promising results for alignment of large language models with human values. " ,
" updated_at " : datetime . utcnow ( ) . isoformat ( ) ,
} )
2026-05-11 03:14:43 +02:00
2026-05-11 05:30:51 +02:00
if " site_settings " in tables :
defaults = { " site_name " : " DevPlace " , " site_description " : " The Developer Social Network " , " site_tagline " : " Track industry shifts. Discover bold releases. Share what you are building in an open, uncensored environment. " }
for key , value in defaults . items ( ) :
existing = db [ " site_settings " ] . find_one ( key = key )
if not existing :
db [ " site_settings " ] . insert ( { " uid " : f " default_ { key } " , " key " : key , " value " : value } )
2026-05-11 07:02:06 +02:00
_index ( db , " news " , " idx_news_external_id " , [ " external_id " ] )
_index ( db , " news " , " idx_news_synced_at " , [ " synced_at " ] )
_index ( db , " news_images " , " idx_news_images_news_uid " , [ " news_uid " ] )
_index ( db , " news_sync " , " idx_news_sync_external_id " , [ " external_id " ] )
if " site_settings " in tables :
news_defaults = {
" news_grade_threshold " : " 7 " ,
" news_api_url " : " https://news.app.molodetz.nl/api " ,
" news_ai_url " : " https://openai.app.molodetz.nl/v1/chat/completions " ,
" news_ai_model " : " molodetz " ,
}
for key , value in news_defaults . items ( ) :
existing = db [ " site_settings " ] . find_one ( key = key )
if not existing :
db [ " site_settings " ] . insert ( { " uid " : f " default_ { key } " , " key " : key , " value " : value } )
2026-05-10 09:08:12 +02:00
logger . info ( " Database initialized " )
def get_table ( name ) :
return db [ name ]
2026-05-11 00:41:41 +02:00
2026-05-11 03:14:43 +02:00
def get_users_by_uids ( uids ) :
if not uids :
return { }
seen = set ( )
unique = [ u for u in uids if u not in seen and not seen . add ( u ) ]
return { u [ " uid " ] : u for u in db [ " users " ] . find ( db [ " users " ] . table . columns . uid . in_ ( unique ) ) }
def get_comment_counts_by_post_uids ( post_uids ) :
if not post_uids or " comments " not in db . tables :
return { }
placeholders = " , " . join ( f " ' { u } ' " for u in post_uids )
rows = db . query ( f " SELECT post_uid, COUNT(*) as c FROM comments WHERE post_uid IN ( { placeholders } ) GROUP BY post_uid " )
return { r [ " post_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 = " , " . join ( f " ' { u } ' " for u in target_uids )
rows = db . query ( f " SELECT target_uid, value, COUNT(*) as c FROM votes WHERE target_uid IN ( { placeholders } ) GROUP BY target_uid, value " )
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
2026-05-11 20:49:45 +02:00
def load_comments ( target_type , target_uid ) :
if " comments " not in db . tables :
return [ ]
comments_table = db [ " comments " ]
raw = list ( comments_table . find ( target_type = target_type , target_uid = target_uid , order_by = [ " created_at " ] ) )
if not raw and target_type == " post " :
raw = list ( comments_table . find ( post_uid = target_uid , order_by = [ " created_at " ] ) )
if not raw :
return [ ]
uids = [ c [ " user_uid " ] for c in raw ]
cids = [ c [ " uid " ] for c in raw ]
users = get_users_by_uids ( uids )
ups , downs = get_vote_counts ( cids )
from devplacepy . utils import time_ago
cmap = { }
for c in raw :
cmap [ c [ " uid " ] ] = {
" comment " : c ,
" author " : users . get ( c [ " user_uid " ] ) ,
" time_ago " : time_ago ( c [ " created_at " ] ) ,
" votes " : { " up " : ups . get ( c [ " uid " ] , 0 ) , " down " : downs . get ( c [ " uid " ] , 0 ) } ,
" children " : [ ] ,
}
top = [ ]
for item in cmap . values ( ) :
parent = item [ " comment " ] . get ( " parent_uid " )
if parent and parent in cmap :
cmap [ parent ] [ " children " ] . append ( item )
else :
top . append ( item )
return top
2026-05-11 00:41:41 +02:00
def get_daily_topic ( ) :
topics = db [ " daily_topics " ]
topic = topics . find_one ( )
if topic :
return topic
return { " title " : " Anthropic details how it improved Claude ' s safety... " , " summary " : " New techniques in AI safety research show promising results. " }