Remove public scripts/ directory — secrets exposed on web root. Move working scripts to /root/scripts/ (non-public). Add .gitignore to prevent recurrence.
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
# Ignore working scripts with secrets
|
||||||
|
/scripts/
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Batch add 50 backlink targets to CRM
|
|
||||||
# Stage=Hold, strategy="Backlink outreach"
|
|
||||||
|
|
||||||
WEBHOOK="https://n8n.derez.ai/webhook/456e0ca0-b3f2-485e-91ee-861dd0d1f051"
|
|
||||||
AUTH="KEY: 5UpKtvmMla2My8"
|
|
||||||
|
|
||||||
add() {
|
|
||||||
local email="$1" name="$2" company="$3" history="$4"
|
|
||||||
curl -s -X POST "$WEBHOOK" \
|
|
||||||
-H "$AUTH" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{\"email\":\"$email\",\"Name\":\"$name\",\"Company\":\"$company\",\"Stage\":\"Hold\",\"strategy\":\"Backlink outreach\",\"category\":\"partner\",\"History\":\"$history\"}"
|
|
||||||
echo " → added $email"
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "=== AI DIRECTORIES ==="
|
|
||||||
|
|
||||||
add "ph@producthunt-backlink.local" "Product Hunt" "Product Hunt" "Backlink target — AI tools directory. Type: directory. Site: producthunt.com. Submission: producthunt.com/posts/new. Submit derez.ai listing."
|
|
||||||
add "bl@betalist-backlink.local" "BetaList" "BetaList" "Backlink target — Early-stage startup directory. Type: directory. Site: betalist.com. Submission: betalist.com/submit. Submit derez.ai."
|
|
||||||
add "at@alternativeto-backlink.local" "AlternativeTo" "AlternativeTo" "Backlink target — Software alternative finder. Type: directory. Site: alternativeto.net. Submission: alternativeto.net/submit-software/. List derez.ai as alternative."
|
|
||||||
add "g2@g2-backlink.local" "G2" "G2" "Backlink target — Business software reviews. Type: directory. Site: g2.com. Submission: g2.com/products/new. Create listing."
|
|
||||||
add "ga@getapp-backlink.local" "GetApp" "GetApp" "Backlink target — Business software directory. Type: directory. Site: getapp.com. Submission: getapp.com/submit-software/. Submit derez.ai."
|
|
||||||
add "hello@theresanaiforthat.com" "There's An AI For That" "There's An AI For That" "Backlink target — AI tool database. Type: directory. Site: theresanaiforthat.com. Contact: hello@theresanaiforthat.com. Submission: theresanaiforthat.com/submit/."
|
|
||||||
add "hello@futurepedia.io" "Futurepedia" "Futurepedia" "Backlink target — AI tools directory. Type: directory. Site: futurepedia.io. Contact: hello@futurepedia.io. Submission: futurepedia.io/submit-tool."
|
|
||||||
add "ac@aicyclopedia-backlink.local" "AIcyclopedia" "AIcyclopedia" "Backlink target — AI tools encyclopedia. Type: directory. Site: aicyclopedia.com. Submission: aicyclopedia.com/submit."
|
|
||||||
add "atd@aitoolsdirectory-backlink.local" "AI Tools Directory" "AI Tools Directory" "Backlink target — AI tool listings. Type: directory. Site: aitoolsdirectory.com. Submission: aitoolsdirectory.com/submit."
|
|
||||||
add "tf@toolify-backlink.local" "Toolify.ai" "Toolify.ai" "Backlink target — AI tools ranking. Type: directory. Site: toolify.ai. Submission: toolify.ai/submit."
|
|
||||||
add "hello@saasaitools.com" "SaaS AI Tools" "SaaS AI Tools" "Backlink target — AI SaaS directory. Type: directory. Site: saasaitools.com. Contact: hello@saasaitools.com. Submission: saasaitools.com/submit."
|
|
||||||
add "atl@aitoolslist-backlink.local" "AI Tools List" "AI Tools List" "Backlink target — AI tool aggregator. Type: directory. Site: aitoolslist.com. Submission: aitoolslist.com/submit."
|
|
||||||
add "ia@insidr-backlink.local" "Insidr.ai" "Insidr.ai" "Backlink target — AI tools discovery. Type: directory. Site: insidr.ai. Submission: insidr.ai/submit-ai-tool/."
|
|
||||||
add "ath@aitoolhunt-backlink.local" "AI Tool Hunt" "AI Tool Hunt" "Backlink target — AI tool search engine. Type: directory. Site: aitoolhunt.com. Submission: aitoolhunt.com/submit."
|
|
||||||
add "team@openfuture.ai" "OpenFuture AI" "OpenFuture AI" "Backlink target — AI tools platform. Type: directory. Site: openfuture.ai. Contact: team@openfuture.ai. Submission: openfuture.ai/submit."
|
|
||||||
|
|
||||||
echo "=== TECH BLOGS ==="
|
|
||||||
|
|
||||||
add "hn@hackernoon-backlink.local" "HackerNoon" "HackerNoon" "Backlink target — Tech publication accepting guest posts. Type: blog. Site: hackernoon.com. Guest post: hackernoon.com/guest-post. Pitch agent hosting article."
|
|
||||||
add "dv@devto-backlink.local" "Dev.to" "Dev.to" "Backlink target — Developer community platform. Type: blog. Site: dev.to. Write: dev.to/write. Cross-post tutorial articles."
|
|
||||||
add "editors@towardsdatascience.com" "Towards Data Science" "Towards Data Science" "Backlink target — Medium AI/DS publication. Type: blog. Site: towardsdatascience.com. Contact: editors@towardsdatascience.com. Guest post: towardsdatascience.com/guest-post."
|
|
||||||
add "betterprogramming.medium@gmail.com" "Better Programming" "Better Programming" "Backlink target — Medium dev publication. Type: blog. Site: betterprogramming.pub. Contact: betterprogramming.medium@gmail.com."
|
|
||||||
add "editors@freecodecamp.org" "FreeCodeCamp" "FreeCodeCamp" "Backlink target — Learn-to-code platform. Type: blog. Site: freecodecamp.org. Contact: editors@freecodecamp.org. Publish: freecodecamp.org/news/publish."
|
|
||||||
add "editorial@smashingmagazine.com" "Smashing Magazine" "Smashing Magazine" "Backlink target — Web dev magazine. Type: blog. Site: smashingmagazine.com. Contact: editorial@smashingmagazine.com. Write-for-us: smashingmagazine.com/write-for-us."
|
|
||||||
add "ct@csstricks-backlink.local" "CSS-Tricks" "CSS-Tricks" "Backlink target — Web dev blog. Type: blog. Site: css-tricks.com. Guest post: css-tricks.com/guest-posting."
|
|
||||||
add "codeburstofficial@gmail.com" "Codeburst" "Codeburst" "Backlink target — Medium dev publication. Type: blog. Site: codeburst.io. Contact: codeburstofficial@gmail.com. Write-for-us: codeburst.io/write-for-us."
|
|
||||||
add "info@aitrends.com" "AI Trends" "AI Trends" "Backlink target — AI industry publication. Type: blog. Site: aitrends.com. Contact: info@aitrends.com."
|
|
||||||
add "kdnuggets1@gmail.com" "KDnuggets" "KDnuggets" "Backlink target — Data science/AI blog. Type: blog. Site: kdnuggets.com. Contact: kdnuggets1@gmail.com."
|
|
||||||
add "contact@analyticsvidhya.com" "Analytics Vidhya" "Analytics Vidhya" "Backlink target — AI/data science community. Type: blog. Site: analyticsvidhya.com. Contact: contact@analyticsvidhya.com."
|
|
||||||
add "editors@infoq.com" "InfoQ" "InfoQ" "Backlink target — Software dev news. Type: blog. Site: infoq.com. Contact: editors@infoq.com."
|
|
||||||
add "editors@dzone.com" "DZone" "DZone" "Backlink target — Developer community. Type: blog. Site: dzone.com. Contact: editors@dzone.com. Guest post: dzone.com/guest-post."
|
|
||||||
add "editorial@thenewstack.io" "The New Stack" "The New Stack" "Backlink target — Cloud/DevOps publication. Type: blog. Site: thenewstack.io. Contact: editorial@thenewstack.io."
|
|
||||||
add "towardsaiteam@gmail.com" "Towards AI" "Towards AI" "Backlink target — AI community publication. Type: blog. Site: towardsai.net. Contact: towardsaiteam@gmail.com."
|
|
||||||
|
|
||||||
echo "=== YOUTUBE / NEWSLETTER ==="
|
|
||||||
|
|
||||||
add "ns@nicksweeney-backlink.local" "Nick Sweeney" "Nick Sweeney YouTube" "Backlink target — AI/tech YouTube creator. Type: youtube. Channel: youtube.com/@nicksweeney. Covers AI agents and dev tools."
|
|
||||||
add "fs@fireship-backlink.local" "Fireship" "Fireship YouTube" "Backlink target — High-production dev tutorials. Type: youtube. Channel: youtube.com/@fireship. 2M+ subs. Covers AI code, dev tooling."
|
|
||||||
add "nr@nicholasrenotte-backlink.local" "Nicholas Renotte" "Nicholas Renotte YouTube" "Backlink target — AI/ML YouTube creator. Type: youtube. Channel: youtube.com/@nicholasrenotte. Covers AI development."
|
|
||||||
add "aj@aijason-backlink.local" "AI Jason" "AI Jason YouTube" "Backlink target — AI tools/productivity YouTuber. Type: youtube. Channel: youtube.com/@aijason. Reviews AI tools, agent demos."
|
|
||||||
add "sw@samwitteveen-backlink.local" "Sam Witteveen" "Sam Witteveen YouTube" "Backlink target — AI/ML YouTuber. Type: youtube. Channel: youtube.com/@samwitteveen. Covers LLMs, agents."
|
|
||||||
add "lc@1littlecoder-backlink.local" "1littlecoder" "1littlecoder YouTube" "Backlink target — AI coding/code generation YouTuber. Type: youtube. Channel: youtube.com/@1littlecoder."
|
|
||||||
add "aaa@allaboutai-backlink.local" "All About AI" "All About AI YouTube" "Backlink target — AI news/tools YouTube channel. Type: youtube. Channel: youtube.com/@allaboutai."
|
|
||||||
add "ae@aiexplained-backlink.local" "AI Explained" "AI Explained YouTube" "Backlink target — AI deep-dive YouTube channel. Type: youtube. Channel: youtube.com/@aiexplainedtv. Covers LLMs, agents."
|
|
||||||
add "lc@langchain-backlink.local" "LangChain" "LangChain YouTube" "Backlink target — Official LangChain channel. Type: youtube. Channel: youtube.com/@langchain. Covers agent frameworks."
|
|
||||||
add "n8n@n8n-backlink.local" "n8n" "n8n YouTube" "Backlink target — n8n official YouTube. Type: youtube. Channel: youtube.com/@n8n-io. Covers automation workflows, AI agents integration."
|
|
||||||
add "as@assemblyai-backlink.local" "AssemblyAI" "AssemblyAI YouTube" "Backlink target — AI API company YouTube. Type: youtube. Channel: youtube.com/@assemblyai. Covers AI/ML dev, speech."
|
|
||||||
add "mw@mckaywrigley-backlink.local" "Mckay Wrigley" "Mckay Wrigley YouTube" "Backlink target — AI coding/building YouTuber. Type: youtube. Channel: youtube.com/@mckaywrigley. Covers AI apps, agents."
|
|
||||||
add "mw@mattwolfe-backlink.local" "Matt Wolfe" "Matt Wolfe YouTube" "Backlink target — AI tools/reviews YouTuber. Type: youtube. Channel: youtube.com/@mattwolfeyt. 700K+ subs. Reviews AI tools."
|
|
||||||
add "tab@theaibreakdown-backlink.local" "The AI Breakdown" "The AI Breakdown Newsletter" "Backlink target — AI news newsletter. Type: newsletter. Site: theaibreakdown.com. Daily AI analysis."
|
|
||||||
add "lw@lastweekinai-backlink.local" "LastWeekInAI" "LastWeekInAI Newsletter" "Backlink target — Weekly AI roundup newsletter. Type: newsletter. Site: lastweekin.ai. Covers AI agent developments."
|
|
||||||
add "tn@theneuron-backlink.local" "The Neuron" "The Neuron Newsletter" "Backlink target — AI newsletter. Type: newsletter. Site: theneurondaily.com. Daily AI updates. High reach."
|
|
||||||
add "tr@therundown-backlink.local" "The Rundown AI" "The Rundown AI Newsletter" "Backlink target — Daily AI newsletter. Type: newsletter. Site: therundown.ai. 500K+ readers. Major reach."
|
|
||||||
add "ab@aibreakfast-backlink.local" "AI Breakfast" "AI Breakfast Newsletter" "Backlink target — AI tools newsletter. Type: newsletter. Site: aibreakfast.com. Covers new AI tools weekly."
|
|
||||||
add "bb@bensbites-backlink.local" "Ben's Bites" "Ben's Bites Newsletter" "Backlink target — Daily AI newsletter. Type: newsletter. Site: bensbites.com. Covers AI tools, agents, LLMs. 100K+ readers."
|
|
||||||
add "mw@mattwilliams-backlink.local" "Matt Williams" "Matt Williams YouTube" "Backlink target — AI dev YouTube creator. Type: youtube. Covers AI coding, agent building."
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== ALL 50 ADDED ==="
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Check for Plausible analytics email and output raw content for cron analysis."""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
HERE = Path(__file__).resolve().parent.parent
|
|
||||||
INSIGHTS_FILE = HERE / "data" / "insights.json"
|
|
||||||
|
|
||||||
|
|
||||||
def run_cmd(*args, timeout=30):
|
|
||||||
result = subprocess.run(args, capture_output=True, text=True, timeout=timeout)
|
|
||||||
if result.returncode != 0:
|
|
||||||
return None, result.stderr
|
|
||||||
return result.stdout, None
|
|
||||||
|
|
||||||
|
|
||||||
def find_plausible_email():
|
|
||||||
"""Find the latest Plausible-related email in inbox."""
|
|
||||||
out, err = run_cmd("himalaya", "envelope", "list", "--page", "1", "--page-size", "30")
|
|
||||||
if not out:
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
best_id, best_subject = None, ""
|
|
||||||
current_id, current_subject = None, ""
|
|
||||||
for line in out.splitlines():
|
|
||||||
# himalaya format: "ID | DATE | FROM | SUBJECT"
|
|
||||||
if "|" not in line:
|
|
||||||
continue
|
|
||||||
parts = [p.strip() for p in line.split("|")]
|
|
||||||
if len(parts) < 4:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
current_id = int(parts[0])
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
current_subject = parts[-1] if len(parts) >= 4 else ""
|
|
||||||
|
|
||||||
subj_lower = current_subject.lower()
|
|
||||||
score = 0
|
|
||||||
if "plausible" in subj_lower:
|
|
||||||
score += 10
|
|
||||||
if "weekly" in subj_lower and ("report" in subj_lower or "analytics" in subj_lower or "stats" in subj_lower):
|
|
||||||
score += 5
|
|
||||||
if "analytics" in subj_lower and "summary" in subj_lower:
|
|
||||||
score += 5
|
|
||||||
if "site" in subj_lower and ("stats" in subj_lower or "report" in subj_lower):
|
|
||||||
score += 3
|
|
||||||
|
|
||||||
if score > 0 and score >= (10 if best_id is None else 0):
|
|
||||||
best_id = current_id
|
|
||||||
best_subject = current_subject
|
|
||||||
|
|
||||||
return best_id, best_subject
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
email_id, subject = find_plausible_email()
|
|
||||||
|
|
||||||
if email_id is None:
|
|
||||||
print("No Plausible email found in inbox.", file=sys.stderr)
|
|
||||||
# Still update last_check timestamp
|
|
||||||
insights = {}
|
|
||||||
if INSIGHTS_FILE.exists():
|
|
||||||
with open(INSIGHTS_FILE) as f:
|
|
||||||
insights = json.load(f)
|
|
||||||
insights["last_check"] = datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
||||||
with open(INSIGHTS_FILE, "w") as f:
|
|
||||||
json.dump(insights, f, indent=2)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
content, err = run_cmd("himalaya", "message", "read", str(email_id))
|
|
||||||
if not content:
|
|
||||||
print(f"Failed to read email {email_id}: {err}", file=sys.stderr)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
print(f"=== Plausible Email Found ===")
|
|
||||||
print(f"Subject: {subject}")
|
|
||||||
print(f"Email ID: {email_id}")
|
|
||||||
print(f"=== Full Content ===")
|
|
||||||
print(content[:6000])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Daily launch dashboard updater — runs at 03:00 PYST via cron.
|
|
||||||
|
|
||||||
Reads data/launch-status.json, updates KPIs from live sources,
|
|
||||||
advances the day counter, sets today's actions to 'today' status,
|
|
||||||
and writes back. Designed to be quiet (stdout only on error) so cron
|
|
||||||
delivery stays clean.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from datetime import date, datetime, timezone, timedelta
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
HERE = Path(__file__).resolve().parent.parent # repo root (scripts/ is a subdir)
|
|
||||||
DATA_FILE = HERE / "data" / "launch-status.json"
|
|
||||||
TZ_OFFSET = timedelta(hours=-4) # PYST (America/Asuncion)
|
|
||||||
|
|
||||||
# ── Day calculation ───────────────────────────────────────────────
|
|
||||||
LAUNCH_START = date(2026, 6, 9)
|
|
||||||
|
|
||||||
def current_day() -> int:
|
|
||||||
"""Return 1–14 based on days since launch start."""
|
|
||||||
today = date.today()
|
|
||||||
diff = (today - LAUNCH_START).days
|
|
||||||
return max(1, min(14, diff + 1))
|
|
||||||
|
|
||||||
|
|
||||||
# ── KPI probes ────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def probe_signups() -> int:
|
|
||||||
"""Read signups from the payment webhook log or n8n status."""
|
|
||||||
# TODO: wire up to n8n.derez.ai/webhook endpoint for count
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def probe_visitors() -> int:
|
|
||||||
"""Estimate landing page visitors via log analysis or a placeholder."""
|
|
||||||
# TODO: integrate with analytics or server log parsing
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def probe_emails() -> int:
|
|
||||||
"""Email list signups."""
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def probe_backlinks() -> int:
|
|
||||||
"""Check for new referring domains."""
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def probe_influencers() -> int:
|
|
||||||
"""Count confirmed influencer partnerships."""
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def probe_testimonials() -> int:
|
|
||||||
"""Count collected F&F testimonials."""
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def probe_impressions() -> int:
|
|
||||||
"""Google Search Console impressions (last 7 days)."""
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def probe_directory_listings() -> int:
|
|
||||||
"""Count live directory listings (Product Hunt, BetaList, etc.)."""
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
# ── Main update ───────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if not DATA_FILE.exists():
|
|
||||||
print(f"ERROR: data file not found at {DATA_FILE}", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
with open(DATA_FILE) as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
day = current_day()
|
|
||||||
|
|
||||||
# Update KPIs with real probes
|
|
||||||
kpi_map = {
|
|
||||||
"signups": probe_signups,
|
|
||||||
"visitors": probe_visitors,
|
|
||||||
"emails": probe_emails,
|
|
||||||
"backlinks": probe_backlinks,
|
|
||||||
"influencers": probe_influencers,
|
|
||||||
"testimonials": probe_testimonials,
|
|
||||||
"impressions": probe_impressions,
|
|
||||||
"directory": probe_directory_listings,
|
|
||||||
}
|
|
||||||
|
|
||||||
for kpi in data.get("kpis", []):
|
|
||||||
probe_fn = kpi_map.get(kpi["id"])
|
|
||||||
if probe_fn:
|
|
||||||
try:
|
|
||||||
kpi["current"] = probe_fn()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"WARN: probe failed for {kpi['id']}: {e}", file=sys.stderr)
|
|
||||||
|
|
||||||
# Update day number
|
|
||||||
data["day"] = day
|
|
||||||
|
|
||||||
# Mark today's actions as "today" if they're still pending
|
|
||||||
yesterday_actions = set()
|
|
||||||
for action in data.get("actions", []):
|
|
||||||
if action["day"] == day and action["status"] == "pending":
|
|
||||||
action["status"] = "today"
|
|
||||||
if action["status"] == "today":
|
|
||||||
yesterday_actions.add(action["action"])
|
|
||||||
|
|
||||||
# Timestamp
|
|
||||||
now = datetime.now(timezone.utc)
|
|
||||||
data["updated"] = now.strftime("%Y-%m-%dT%H:%M:%S") + "-04:00"
|
|
||||||
data["notes"] = f"Day {day} auto-update at {now.strftime('%H:%M')} UTC / {day}/14 complete."
|
|
||||||
|
|
||||||
with open(DATA_FILE, "w") as f:
|
|
||||||
json.dump(data, f, indent=2)
|
|
||||||
|
|
||||||
# Quiet success — no stdout so cron doesn't spam
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Reference in New Issue
Block a user