forked from retoor/devplacepy
feat: add ISSLOP AI usage analysis CLI commands, game router, and politics topic
- Add `cmd_isslop_prune`, `cmd_isslop_clear`, `cmd_isslop_analyze` CLI commands for AI usage analysis job management - Register `/game` router with `index` and `farm` endpoints for Code Farm idle game - Add `politics` to allowed TOPICS constant replacing `signals` - Introduce `ISSLOP_DIR`, `ISSLOP_WORKSPACES_DIR`, `ISSLOP_RUNS_DIR`, `ISSLOP_MEDIA_DIR` config paths - Add `clear_user_stars` and `clear_user_projects_cache` calls on vote and project create/delete - Update `make prod` to use `nproc` workers via `DEVPLACE_WEB_WORKERS` env var - Convert `database.py` and `utils.py` to packages for modular structure - Add `devplace apikey` and `devplace token` CLI subcommands for API key and access token management
This commit is contained in:
@@ -17,7 +17,7 @@ from .notifications import NOTIFICATION_TYPES, NOTIFICATION_CHANNELS, _NOTIFICAT
|
||||
from .forks import record_fork, get_fork_parent, count_forks, soft_delete_fork_relations, delete_fork_relations
|
||||
from .follows import get_follow_counts, get_follow_list, get_following_among
|
||||
from .deepsearch import _ds_now, create_deepsearch_session, update_deepsearch_session, get_deepsearch_session, add_deepsearch_message, get_deepsearch_messages, get_cached_deepsearch_url, upsert_deepsearch_url_cache
|
||||
from .ranking import VOTABLE_TARGETS, STAR_TARGETS, _authors_cache, _ranked_authors, _rank_map, get_top_authors, get_leaderboard, get_user_rank, get_user_stars, update_target_stars, soft_delete_engagement, delete_engagement, get_target_owner_uid
|
||||
from .ranking import VOTABLE_TARGETS, STAR_TARGETS, _authors_cache, _ranked_authors, _rank_map, get_top_authors, get_leaderboard, get_user_rank, get_user_stars, clear_user_stars, update_target_stars, soft_delete_engagement, delete_engagement, get_target_owner_uid
|
||||
from .comments import _drop_blocked, _build_comment_items, load_comments, get_recent_comments_by_target_uids, get_recent_comments_by_post_uids, load_comments_by_target_uids
|
||||
from .content import resolve_by_slug, resolve_object_url, get_uids_by_username_match, text_search_clause, get_daily_topic, get_featured_news
|
||||
from .attachments_data import get_attachments, get_attachments_by_type, get_news_images_by_uids, delete_attachment_record, delete_attachments, _delete_attachment_file, get_user_media, get_deleted_media
|
||||
@@ -191,6 +191,7 @@ __all__ = [
|
||||
"get_leaderboard",
|
||||
"get_user_rank",
|
||||
"get_user_stars",
|
||||
"clear_user_stars",
|
||||
"update_target_stars",
|
||||
"soft_delete_engagement",
|
||||
"delete_engagement",
|
||||
|
||||
@@ -16,7 +16,10 @@ VOTABLE_TARGETS: dict[str, str] = {
|
||||
STAR_TARGETS: set[str] = {"post", "project", "gist"}
|
||||
|
||||
|
||||
_authors_cache = TTLCache(ttl=300, max_size=200)
|
||||
_authors_cache = TTLCache(ttl=15, max_size=200)
|
||||
|
||||
|
||||
_stars_cache = TTLCache(ttl=15, max_size=2000)
|
||||
|
||||
|
||||
def _ranked_authors() -> list:
|
||||
@@ -84,7 +87,14 @@ def get_user_rank(user_uid: str):
|
||||
return _rank_map().get(user_uid)
|
||||
|
||||
|
||||
def clear_user_stars(user_uid: str) -> None:
|
||||
_stars_cache.pop(user_uid)
|
||||
|
||||
|
||||
def get_user_stars(user_uid: str) -> int:
|
||||
cached = _stars_cache.get(user_uid)
|
||||
if cached is not None:
|
||||
return cached
|
||||
if "votes" not in db.tables:
|
||||
return 0
|
||||
target_union = " UNION ALL ".join(
|
||||
@@ -94,14 +104,17 @@ def get_user_stars(user_uid: str) -> int:
|
||||
)
|
||||
if not target_union:
|
||||
return 0
|
||||
total = 0
|
||||
for row in db.query(
|
||||
f"SELECT COALESCE(SUM(v.value), 0) AS s "
|
||||
f"FROM votes v JOIN ({target_union}) t ON v.target_uid = t.uid AND v.target_type = t.target_type "
|
||||
f"WHERE v.deleted_at IS NULL",
|
||||
u=user_uid,
|
||||
):
|
||||
return row["s"] or 0
|
||||
return 0
|
||||
total = row["s"] or 0
|
||||
break
|
||||
_stars_cache.set(user_uid, total)
|
||||
return total
|
||||
|
||||
|
||||
def update_target_stars(target_type: str, target_uid: str, net_stars: int) -> None:
|
||||
@@ -110,7 +123,6 @@ def update_target_stars(target_type: str, target_uid: str, net_stars: int) -> No
|
||||
return
|
||||
if target_type in STAR_TARGETS:
|
||||
get_table(table_name).update({"uid": target_uid, "stars": net_stars}, ["uid"])
|
||||
_authors_cache.clear()
|
||||
|
||||
|
||||
def soft_delete_engagement(target_type: str, target_uids: list, deleted_by: str) -> None:
|
||||
|
||||
@@ -37,9 +37,11 @@ def init_db():
|
||||
_index(db, "users", "idx_users_api_key", ["api_key"])
|
||||
_index(db, "users", "idx_users_role", ["role", "created_at"])
|
||||
_index(db, "users", "idx_users_last_seen", ["last_seen"])
|
||||
_index(db, "users", "idx_users_created_at", ["created_at"])
|
||||
_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, "posts", "idx_posts_slug", ["slug"])
|
||||
if "posts" in tables:
|
||||
posts_table = get_table("posts")
|
||||
if not posts_table.has_column("tags"):
|
||||
@@ -120,6 +122,15 @@ def init_db():
|
||||
_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, "messages", "idx_messages_conversation", ["sender_uid", "receiver_uid"]
|
||||
)
|
||||
_index(
|
||||
db,
|
||||
"messages",
|
||||
"idx_messages_conversation_rev",
|
||||
["receiver_uid", "sender_uid"],
|
||||
)
|
||||
_index(db, "notifications", "idx_notifications_user", ["user_uid"])
|
||||
_index(db, "notifications", "idx_notifications_user_read", ["user_uid", "read"])
|
||||
_index(db, "push_registration", "idx_push_registration_user", ["user_uid"])
|
||||
@@ -140,6 +151,7 @@ def init_db():
|
||||
projects.create_column_by_example(column, example)
|
||||
|
||||
_index(db, "projects", "idx_projects_user", ["user_uid"])
|
||||
_index(db, "projects", "idx_projects_slug", ["slug"])
|
||||
_index(db, "projects", "idx_projects_private", ["is_private"])
|
||||
_index(db, "projects", "idx_projects_stars", ["stars"])
|
||||
_index(db, "projects", "idx_projects_type", ["project_type"])
|
||||
@@ -170,6 +182,7 @@ def init_db():
|
||||
db, "project_files", "idx_project_files_parent", ["project_uid", "parent_path"]
|
||||
)
|
||||
_index(db, "badges", "idx_badges_user", ["user_uid"])
|
||||
_index(db, "badges", "idx_badges_user_name", ["user_uid", "badge_name"])
|
||||
_index(db, "follows", "idx_follows_follower", ["follower_uid"])
|
||||
_index(db, "follows", "idx_follows_following", ["following_uid"])
|
||||
user_relations = get_table("user_relations")
|
||||
@@ -189,6 +202,7 @@ def init_db():
|
||||
_index(db, "password_resets", "idx_password_resets_token", ["token"])
|
||||
_index(db, "gists", "idx_gists_user_uid", ["user_uid"])
|
||||
_index(db, "gists", "idx_gists_language", ["language"])
|
||||
_index(db, "gists", "idx_gists_slug", ["slug"])
|
||||
attachments = get_table("attachments")
|
||||
for column, example in (
|
||||
("uid", ""),
|
||||
@@ -244,6 +258,7 @@ def init_db():
|
||||
db["site_settings"].insert(
|
||||
{"uid": f"default_{key}", "key": key, "value": value}
|
||||
)
|
||||
_index(db, "site_settings", "idx_site_settings_key", ["key"])
|
||||
|
||||
news = get_table("news")
|
||||
for column, example in (
|
||||
@@ -272,6 +287,7 @@ def init_db():
|
||||
news.create_column_by_example(column, example)
|
||||
|
||||
_index(db, "news", "idx_news_external_id", ["external_id"])
|
||||
_index(db, "news", "idx_news_slug", ["slug"])
|
||||
_index(db, "news", "idx_news_synced_at", ["synced_at"])
|
||||
_index(db, "news", "idx_news_status", ["status"])
|
||||
_index(db, "news", "idx_news_featured", ["featured"])
|
||||
@@ -457,6 +473,8 @@ def init_db():
|
||||
instances.create_column_by_example(column, example)
|
||||
|
||||
_index(db, "instances", "idx_instances_project", ["project_uid"])
|
||||
_index(db, "instances", "idx_instances_slug", ["slug"])
|
||||
_index(db, "instances", "idx_instances_name", ["name"])
|
||||
_index(db, "instances", "idx_instances_state", ["desired_state", "status"])
|
||||
_index(db, "instances", "idx_instances_container", ["container_id"])
|
||||
_index(db, "instances", "idx_instances_ingress", ["ingress_slug"])
|
||||
@@ -791,6 +809,108 @@ def init_db():
|
||||
deepsearch_url_cache.create_column_by_example(column, example)
|
||||
_index(db, "deepsearch_url_cache", "idx_deepsearch_url_cache_hash", ["url_hash"])
|
||||
|
||||
isslop_analyses = get_table("isslop_analyses")
|
||||
for column, example in (
|
||||
("uid", ""),
|
||||
("owner_kind", ""),
|
||||
("owner_id", ""),
|
||||
("source_url", ""),
|
||||
("source_kind", ""),
|
||||
("status", ""),
|
||||
("created_at", ""),
|
||||
("finished_at", ""),
|
||||
("content_hash", ""),
|
||||
("grade", ""),
|
||||
("slop_score", 0.0),
|
||||
("origin_score", 0.0),
|
||||
("quality_deficit_score", 0.0),
|
||||
("human_percent", 0.0),
|
||||
("ai_percent", 0.0),
|
||||
("category", ""),
|
||||
("confidence", ""),
|
||||
("files_total", 0),
|
||||
("files_analyzed", 0),
|
||||
("error_message_text", ""),
|
||||
("detected_builder", ""),
|
||||
("dom_slop_score", 0.0),
|
||||
("deleted_at", ""),
|
||||
("deleted_by", ""),
|
||||
):
|
||||
if not isslop_analyses.has_column(column):
|
||||
isslop_analyses.create_column_by_example(column, example)
|
||||
_index(db, "isslop_analyses", "idx_isslop_analyses_owner", ["owner_kind", "owner_id", "created_at"])
|
||||
_index(db, "isslop_analyses", "idx_isslop_analyses_status", ["status"])
|
||||
_index(db, "isslop_analyses", "idx_isslop_analyses_hash", ["content_hash"])
|
||||
|
||||
isslop_events = get_table("isslop_events")
|
||||
for column, example in (
|
||||
("analysis_uid", ""),
|
||||
("seq", 0),
|
||||
("kind", ""),
|
||||
("message", ""),
|
||||
("payload", ""),
|
||||
("created_at", ""),
|
||||
):
|
||||
if not isslop_events.has_column(column):
|
||||
isslop_events.create_column_by_example(column, example)
|
||||
_index(db, "isslop_events", "idx_isslop_events_analysis", ["analysis_uid", "seq"])
|
||||
|
||||
isslop_file_results = get_table("isslop_file_results")
|
||||
for column, example in (
|
||||
("analysis_uid", ""),
|
||||
("path", ""),
|
||||
("language", ""),
|
||||
("lines", 0),
|
||||
("origin_score", 0.0),
|
||||
("quality_deficit_score", 0.0),
|
||||
("category", ""),
|
||||
("signals", ""),
|
||||
("source", ""),
|
||||
):
|
||||
if not isslop_file_results.has_column(column):
|
||||
isslop_file_results.create_column_by_example(column, example)
|
||||
_index(db, "isslop_file_results", "idx_isslop_file_results_analysis", ["analysis_uid"])
|
||||
|
||||
isslop_image_results = get_table("isslop_image_results")
|
||||
for column, example in (
|
||||
("analysis_uid", ""),
|
||||
("path", ""),
|
||||
("ai_probability", 0.0),
|
||||
("grade", ""),
|
||||
("verdict", ""),
|
||||
("image_kind", ""),
|
||||
("tells", ""),
|
||||
("description", ""),
|
||||
("thumb", ""),
|
||||
):
|
||||
if not isslop_image_results.has_column(column):
|
||||
isslop_image_results.create_column_by_example(column, example)
|
||||
_index(db, "isslop_image_results", "idx_isslop_image_results_analysis", ["analysis_uid"])
|
||||
|
||||
isslop_dom_results = get_table("isslop_dom_results")
|
||||
for column, example in (
|
||||
("analysis_uid", ""),
|
||||
("url", ""),
|
||||
("detected_builder", ""),
|
||||
("signal_count", 0),
|
||||
("screenshot", ""),
|
||||
("signals", ""),
|
||||
):
|
||||
if not isslop_dom_results.has_column(column):
|
||||
isslop_dom_results.create_column_by_example(column, example)
|
||||
_index(db, "isslop_dom_results", "idx_isslop_dom_results_analysis", ["analysis_uid"])
|
||||
|
||||
isslop_reports = get_table("isslop_reports")
|
||||
for column, example in (
|
||||
("analysis_uid", ""),
|
||||
("markdown", ""),
|
||||
("model_used", ""),
|
||||
("generated_at", ""),
|
||||
):
|
||||
if not isslop_reports.has_column(column):
|
||||
isslop_reports.create_column_by_example(column, example)
|
||||
_index(db, "isslop_reports", "idx_isslop_reports_analysis", ["analysis_uid"], unique=True)
|
||||
|
||||
game_farms = get_table("game_farms")
|
||||
for column, example in (
|
||||
("uid", ""),
|
||||
|
||||
@@ -35,6 +35,7 @@ SOFT_DELETE_TABLES = [
|
||||
"notification_preferences",
|
||||
"deepsearch_sessions",
|
||||
"deepsearch_messages",
|
||||
"isslop_analyses",
|
||||
"devrant_tokens",
|
||||
"access_tokens",
|
||||
"email_accounts",
|
||||
|
||||
Reference in New Issue
Block a user