diff --git a/api.py b/api.py index 1dc54ac..53964f6 100644 --- a/api.py +++ b/api.py @@ -4132,6 +4132,40 @@ async def proxy_signup(provider: str = Body(...)) -> dict[str, Any]: url = pm.get_signup_link(provider) return {"success": True, "data": {"signup_url": url, "provider": provider}} +@app.get("/v1/proxy/referrals", tags=["Proxy"], summary="List proxy provider affiliate referrals") +async def list_proxy_referrals() -> dict[str, Any]: + """Return the curated proxy provider affiliate catalog (proxy_referrals.py). + + This is the marketing-friendly subset: commission, promo codes, tier + (premium/standard/budget), and referral URLs. Useful for a "Sign up via Pry + and we get a cut" UI, or for showing users premium options when their free + proxy fails. + + The full connection metadata (host, port, auth) lives in /v1/proxy/providers. + """ + from proxy_manager import ProxyManager + + pm = ProxyManager() + return { + "success": True, + "data": { + "providers": pm.list_proxy_referrals(), + "summary": pm.get_proxy_referral_summary(), + }, + } + + +@app.get("/v1/proxy/referrals/{tag}", tags=["Proxy"], summary="Get a single proxy provider referral") +async def get_proxy_referral(tag: str) -> dict[str, Any]: + """Return the affiliate info for a single proxy provider by tag.""" + from proxy_manager import ProxyManager + + pm = ProxyManager() + info = pm.get_proxy_referral(tag) + if not info: + return {"success": False, "error": f"No proxy referral found for tag: {tag}"} + return {"success": True, "data": {"tag": tag, **info}} + @app.post("/v1/proxy/configure", tags=["Proxy"], summary="Configure proxy credentials") async def proxy_configure( diff --git a/proxy_manager.py b/proxy_manager.py index 4d3985b..f1b140a 100644 --- a/proxy_manager.py +++ b/proxy_manager.py @@ -19,6 +19,11 @@ from typing import Any logger = logging.getLogger(__name__) +try: + from proxy_referrals import PROVIDER_REFERRALS as _PROXY_REFERRALS +except ImportError: # proxy_referrals module not always present in slim installs + _PROXY_REFERRALS = {} + PROXY_DIR = Path(os.path.expanduser("~/.pry/proxies")) PROXY_DIR.mkdir(parents=True, exist_ok=True) @@ -460,6 +465,45 @@ class ProxyManager: return [] + # ── Proxy referral catalog (from proxy_referrals.py) ──────────────── + def get_proxy_referral(self, provider_tag: str) -> dict[str, Any]: + """Get the curated referral info for a proxy provider. + + Returns the proxy_referrals.PROVIDER_REFERRALS entry for the given tag + (e.g., 'brightdata', 'iproyal'). Empty dict if not found. + + This is the affiliate-friendly subset: it gives the marketing-y details + (commission, promo code, tier) that are useful when prompting a user to + sign up for a premium proxy. The full proxy connection config + (host, port, auth) lives in PREMIUM_PROXY_PROVIDERS. + """ + return _PROXY_REFERRALS.get(provider_tag, {}) + + def get_proxy_referral_url(self, provider_tag: str) -> str: + """Get just the referral URL for a proxy provider.""" + entry = _PROXY_REFERRALS.get(provider_tag, {}) + return entry.get("referral_url", "") + + def list_proxy_referrals(self) -> list[dict[str, Any]]: + """List all proxy provider referrals (curated, marketing-friendly view).""" + return [ + {"tag": tag, **info} for tag, info in _PROXY_REFERRALS.items() + ] + + def get_proxy_referral_summary(self) -> dict[str, Any]: + """Return a per-tier summary of proxy referrals (count, providers, total commission ceiling).""" + tiers: dict[str, list[str]] = {"premium": [], "standard": [], "budget": []} + for tag, info in _PROXY_REFERRALS.items(): + tier = info.get("tier", "standard") + tiers.setdefault(tier, []).append(tag) + return { + "tiers": tiers, + "total_providers": len(_PROXY_REFERRALS), + "by_tag": _PROXY_REFERRALS, + } + + + def _parse_ts(ts: str) -> float: """Parse an ISO timestamp to epoch seconds. Returns 0 on error.""" if not ts: diff --git a/proxy_referrals.py b/proxy_referrals.py new file mode 100644 index 0000000..04f3bf7 --- /dev/null +++ b/proxy_referrals.py @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Rug Munch Media LLC +# +# Part of Pry - https://git.rugmunch.io/RugMunchMedia/pryscraper +# Licensed under MIT. See LICENSE. + +"""Proxy provider referral links — monetize Pry by referring users to proxy services.""" +from __future__ import annotations + +# Each provider has a referral URL and commission structure +# When a user configures a proxy through Pry, we can offer a discount link +# that earns us a commission on their subscription + +PROVIDER_REFERRALS = { + "brightdata": { + "name": "Bright Data", + "referral_url": "https://brightdata.com/cp/start?promo=munchcrawl", + "promo_code": "MUNCHCRAWL30", + "commission": "Up to $500/mo per referral (recurring)", + "description": "30% first payment bonus. Best residential proxies on the market.", + "tier": "premium", + }, + "oxylabs": { + "name": "Oxylabs", + "referral_url": "https://oxylabs.io/?tap_a=114931-8c3b7a&tap_s=3621085-4c2e5b", + "commission": "30% recurring commission", + "description": "Enterprise-grade proxies. Great for heavy scraping.", + "tier": "premium", + }, + "smartproxy": { + "name": "Smartproxy", + "referral_url": "https://smartproxy.com/?utm_source=partner&utm_medium=referral&partner=munchcrawl", + "commission": "20% recurring commission", + "description": "Good value residential and datacenter proxies.", + "tier": "standard", + }, + "iproyal": { + "name": "IPRoyal", + "referral_url": "https://iproyal.com/?r=munchcrawl", + "promo_code": "PRY20", + "commission": "25% recurring commission + $20 bonus for referred user", + "description": "Budget-friendly residential proxies. Pay-per-IP option.", + "tier": "budget", + }, + "webshare": { + "name": "Webshare", + "referral_url": "https://webshare.io/?referral=munchcrawl", + "promo_code": "PRYFREE10", + "commission": "$1 per referral + 10% recurring", + "description": "Free tier available. Cheap datacenter proxies.", + "tier": "budget", + }, +}