Explorer
/tmp/patch_filters_p4.py
← Zurück ↓ Download
from pathlib import Path

p=Path('/opt/struktur/social-media-agent/app.py')
s=p.read_text()
# Add source platform/type to the API select.
s=s.replace('            "SELECT signal_id, signal_category, radar_score, topic, extracted_hook,"\n', '            "SELECT signal_id, signal_category, source_type, source_platform, radar_score, topic, extracted_hook,"\n', 1)
# Replace status/competition/sort setup with explicit platform filters and real sort semantics.
old='''        comp_clause = "AND competition_signal = 1" if competition_only else ""\n\n        sort_map = {\n            "op_priority":  "pinned DESC, operational_priority DESC, radar_score DESC",\n            "relevance":    "pinned DESC, radar_score DESC",\n            "newest":       "pinned DESC, created_at DESC",\n            "virality":     "pinned DESC, virality_level DESC, radar_score DESC",\n            "emotionality": "pinned DESC, emotionality_level DESC, radar_score DESC",\n            "linkedin":     "pinned DESC, platform_linkedin DESC, radar_score DESC",\n            "facebook":     "pinned DESC, platform_facebook DESC, radar_score DESC",\n            "tiktok":       "pinned DESC, platform_tiktok DESC, radar_score DESC",\n        }\n        order_by = sort_map.get(sort, "pinned DESC, operational_priority DESC, radar_score DESC")\n'''
new='''        comp_clause = "AND competition_signal = 1" if competition_only else ""\n\n        # source_platform is the canonical read-time field; old rows with an\n        # empty value remain classifiable through source_type. LI/FB are real\n        # source filters, not merely sort orders.\n        platform_expr = "lower(COALESCE(NULLIF(source_platform,''), source_type))"\n        if sort == "facebook":\n            platform_clause = (\n                "AND (" + platform_expr + " IN ('facebook','meta','meta_ad') "\n                "OR source_type IN ('facebook_public','meta_ad'))"\n            )\n        elif sort == "linkedin":\n            platform_clause = (\n                "AND (" + platform_expr + " = 'linkedin' "\n                "OR source_type = 'linkedin')"\n            )\n        else:\n            platform_clause = ""\n\n        sort_map = {\n            "op_priority":  "pinned DESC, operational_priority DESC, radar_score DESC, observed_at DESC",\n            "relevance":    "pinned DESC, radar_score DESC, relevance_score DESC, observed_at DESC",\n            "newest":       "pinned DESC, COALESCE(observed_at, created_at, timestamp) DESC, radar_score DESC",\n            "virality":     "pinned DESC, virality_level DESC, radar_score DESC, observed_at DESC",\n            "emotionality": "pinned DESC, emotionality_level DESC, radar_score DESC, observed_at DESC",\n            "linkedin":     "pinned DESC, radar_score DESC, observed_at DESC",\n            "facebook":     "pinned DESC, radar_score DESC, observed_at DESC",\n            "tiktok":       "pinned DESC, platform_tiktok DESC, radar_score DESC",\n        }\n        order_by = sort_map.get(sort, "pinned DESC, operational_priority DESC, radar_score DESC, observed_at DESC")\n'''
if old not in s: raise SystemExit('filter setup anchor not found')
s=s.replace(old,new,1)
# Highlight must remain explicit; normal platform filter must be bypassed only for explicit deep links.
s=s.replace('''            st_clause = ""\n            st_params = []\n            comp_clause = ""\n''','''            st_clause = ""\n            st_params = []\n            comp_clause = ""\n            platform_clause = ""\n''',1)
s=s.replace('''            f" {st_clause} {comp_clause}"\n''','''            f" {st_clause} {comp_clause} {platform_clause}"\n''',1)
p.write_text(s)

p=Path('/opt/struktur/social-media-agent/templates/cockpit.html')
s=p.read_text()
# Backend order must be preserved inside category groups; sorting here erased every button's effect.
s=s.replace("    {% set cat_sigs = cat_grp|sort(attribute='radar_score', reverse=True) %}\n", "    {% set cat_sigs = cat_grp %}\n", 1)
# Make source/platform immediately visible on every card.
s=s.replace(".stag{", ".source-badge{display:inline-flex;align-items:center;padding:2px 5px;border-radius:3px;background:rgba(79,142,247,.15);color:#93c5fd;font-size:9px;font-weight:800;letter-spacing:.04em;margin-right:5px;} .stag{")
old="""        <span class=\"stag\" title=\"{{s.source_name}}\">{{s.source_name or '—'}}</span>\n"""
new="""        <span class=\"source-badge\">{{(s.source_platform or s.source_type or 'source')|replace('_',' ')|upper}}</span><span class=\"stag\" title=\"{{s.source_name}}\">{{s.source_name or '—'}}</span>\n"""
if old not in s: raise SystemExit('badge anchor not found')
s=s.replace(old,new,1)
p.write_text(s)