Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -40,13 +40,10 @@ CAMPAIGN_CONFIG_FILE = "campaign_rules.json"
|
|
| 40 |
# 1. CAMPAIGN MANAGER & LOGIC
|
| 41 |
# =====================================================
|
| 42 |
def load_campaign_rules():
|
| 43 |
-
"""Loads rules from JSON. Auto-migrates old list-based format to new include/exclude format."""
|
| 44 |
if os.path.exists(CAMPAIGN_CONFIG_FILE):
|
| 45 |
try:
|
| 46 |
with open(CAMPAIGN_CONFIG_FILE, "r") as f:
|
| 47 |
rules = json.load(f)
|
| 48 |
-
|
| 49 |
-
# Backward compatibility: Convert flat lists into include/exclude dicts
|
| 50 |
for campaign, config in rules.items():
|
| 51 |
if isinstance(config, list):
|
| 52 |
rules[campaign] = {
|
|
@@ -74,39 +71,32 @@ def get_campaign_match(text, rules):
|
|
| 74 |
if not text or not isinstance(text, str):
|
| 75 |
return None
|
| 76 |
|
| 77 |
-
#
|
| 78 |
-
|
| 79 |
-
search_text = " " + re.sub(r'[\-_/.,?=&+#]', ' ', text.lower()) + " "
|
| 80 |
|
| 81 |
for campaign_name, config in rules.items():
|
| 82 |
includes = config.get("include", [])
|
| 83 |
excludes = config.get("exclude", [])
|
| 84 |
|
| 85 |
-
# 1st: Check Exclusions (Exact
|
| 86 |
has_exclusion = False
|
| 87 |
for ex in excludes:
|
| 88 |
if not ex.strip(): continue
|
| 89 |
-
|
| 90 |
-
kw
|
| 91 |
-
if f" {kw} " in search_text:
|
| 92 |
has_exclusion = True
|
| 93 |
break
|
| 94 |
|
| 95 |
if has_exclusion:
|
| 96 |
continue
|
| 97 |
|
| 98 |
-
# 2nd: Check Inclusions (Exact
|
| 99 |
-
has_inclusion = False
|
| 100 |
for inc in includes:
|
| 101 |
if not inc.strip(): continue
|
| 102 |
-
kw = re.sub(r'[\-_/.,?=&+#]', ' ', inc.lower().strip())
|
| 103 |
-
if
|
| 104 |
-
|
| 105 |
-
break
|
| 106 |
|
| 107 |
-
if has_inclusion:
|
| 108 |
-
return campaign_name
|
| 109 |
-
|
| 110 |
return None
|
| 111 |
|
| 112 |
def apply_business_logic(df):
|
|
@@ -125,7 +115,7 @@ def apply_business_logic(df):
|
|
| 125 |
match = get_campaign_match(row["landing_page_path"], rules)
|
| 126 |
if match: return match
|
| 127 |
|
| 128 |
-
# Priority 2: Exit Page
|
| 129 |
if row.get("exit_page_path"):
|
| 130 |
match = get_campaign_match(row["exit_page_path"], rules)
|
| 131 |
if match: return match
|
|
@@ -348,10 +338,12 @@ def build_dashboard(df, preset, top_n):
|
|
| 348 |
if df is None or df.empty: return px.bar(title="No Data")
|
| 349 |
if "Campaign" not in df.columns: df = apply_business_logic(df)
|
| 350 |
|
| 351 |
-
# RESTORED EXACT ORIGINAL CHART LOGIC
|
| 352 |
if preset == "Key Campaigns Bifurcation (MS Tech, Fintech, Adtech)":
|
| 353 |
-
|
| 354 |
-
|
|
|
|
|
|
|
|
|
|
| 355 |
if filtered.empty: return px.bar(title="No Data for Key Campaigns")
|
| 356 |
|
| 357 |
agg = filtered.groupby("Campaign").agg(
|
|
@@ -530,16 +522,13 @@ with gr.Blocks(title="Leadfeeder Campaign Pro") as demo:
|
|
| 530 |
if not target_camp:
|
| 531 |
return "❌ Error: Campaign name cannot be empty.", gr.update()
|
| 532 |
|
| 533 |
-
# 1. Update the dictionary format
|
| 534 |
rules[target_camp] = {"include": clean_inc, "exclude": clean_exc}
|
| 535 |
|
| 536 |
-
# 2. Save file locally first
|
| 537 |
with open(CAMPAIGN_CONFIG_FILE, "w") as f:
|
| 538 |
json.dump(rules, f, indent=4)
|
| 539 |
|
| 540 |
status_message = f"✅ Saved locally! Updated keywords for '{target_camp}'."
|
| 541 |
|
| 542 |
-
# 3. Push to Hugging Face automatically
|
| 543 |
if HF_TOKEN and SPACE_ID:
|
| 544 |
try:
|
| 545 |
api = HfApi(token=HF_TOKEN)
|
|
|
|
| 40 |
# 1. CAMPAIGN MANAGER & LOGIC
|
| 41 |
# =====================================================
|
| 42 |
def load_campaign_rules():
|
|
|
|
| 43 |
if os.path.exists(CAMPAIGN_CONFIG_FILE):
|
| 44 |
try:
|
| 45 |
with open(CAMPAIGN_CONFIG_FILE, "r") as f:
|
| 46 |
rules = json.load(f)
|
|
|
|
|
|
|
| 47 |
for campaign, config in rules.items():
|
| 48 |
if isinstance(config, list):
|
| 49 |
rules[campaign] = {
|
|
|
|
| 71 |
if not text or not isinstance(text, str):
|
| 72 |
return None
|
| 73 |
|
| 74 |
+
# Clean text: replace all URL symbols with spaces and pad edges
|
| 75 |
+
clean_text = " " + re.sub(r'[\-_/.,?=&+#]', ' ', text.lower()) + " "
|
|
|
|
| 76 |
|
| 77 |
for campaign_name, config in rules.items():
|
| 78 |
includes = config.get("include", [])
|
| 79 |
excludes = config.get("exclude", [])
|
| 80 |
|
| 81 |
+
# 1st: Check Exclusions (Exact Match)
|
| 82 |
has_exclusion = False
|
| 83 |
for ex in excludes:
|
| 84 |
if not ex.strip(): continue
|
| 85 |
+
kw = " " + re.sub(r'[\-_/.,?=&+#]', ' ', ex.lower().strip()) + " "
|
| 86 |
+
if kw in clean_text:
|
|
|
|
| 87 |
has_exclusion = True
|
| 88 |
break
|
| 89 |
|
| 90 |
if has_exclusion:
|
| 91 |
continue
|
| 92 |
|
| 93 |
+
# 2nd: Check Inclusions (Exact Match)
|
|
|
|
| 94 |
for inc in includes:
|
| 95 |
if not inc.strip(): continue
|
| 96 |
+
kw = " " + re.sub(r'[\-_/.,?=&+#]', ' ', inc.lower().strip()) + " "
|
| 97 |
+
if kw in clean_text:
|
| 98 |
+
return campaign_name
|
|
|
|
| 99 |
|
|
|
|
|
|
|
|
|
|
| 100 |
return None
|
| 101 |
|
| 102 |
def apply_business_logic(df):
|
|
|
|
| 115 |
match = get_campaign_match(row["landing_page_path"], rules)
|
| 116 |
if match: return match
|
| 117 |
|
| 118 |
+
# Priority 2: Exit Page
|
| 119 |
if row.get("exit_page_path"):
|
| 120 |
match = get_campaign_match(row["exit_page_path"], rules)
|
| 121 |
if match: return match
|
|
|
|
| 338 |
if df is None or df.empty: return px.bar(title="No Data")
|
| 339 |
if "Campaign" not in df.columns: df = apply_business_logic(df)
|
| 340 |
|
|
|
|
| 341 |
if preset == "Key Campaigns Bifurcation (MS Tech, Fintech, Adtech)":
|
| 342 |
+
target_lower = ["ms tech", "fintech", "adtech"]
|
| 343 |
+
|
| 344 |
+
# Case Insensitive Matching (Fix for empty chart)
|
| 345 |
+
filtered = df[df["Campaign"].astype(str).str.lower().isin(target_lower)].copy()
|
| 346 |
+
|
| 347 |
if filtered.empty: return px.bar(title="No Data for Key Campaigns")
|
| 348 |
|
| 349 |
agg = filtered.groupby("Campaign").agg(
|
|
|
|
| 522 |
if not target_camp:
|
| 523 |
return "❌ Error: Campaign name cannot be empty.", gr.update()
|
| 524 |
|
|
|
|
| 525 |
rules[target_camp] = {"include": clean_inc, "exclude": clean_exc}
|
| 526 |
|
|
|
|
| 527 |
with open(CAMPAIGN_CONFIG_FILE, "w") as f:
|
| 528 |
json.dump(rules, f, indent=4)
|
| 529 |
|
| 530 |
status_message = f"✅ Saved locally! Updated keywords for '{target_camp}'."
|
| 531 |
|
|
|
|
| 532 |
if HF_TOKEN and SPACE_ID:
|
| 533 |
try:
|
| 534 |
api = HfApi(token=HF_TOKEN)
|