feat(proxy): sync proxy_referrals.py from deploy; expose via API
The deploy at /srv/pry/ had a thin proxy_referrals.py with 5 curated
proxy provider affiliate entries (Bright Data, Oxylabs, Smartproxy,
IPRoyal, Webshare). The repo was missing this file, so deploy and repo
were out of sync.
Changes:
- Add proxy_referrals.py (MIT) with the 5-provider curated catalog
- proxy_manager.py: import PROVIDER_REFERRALS, add 4 helper methods:
get_proxy_referral(tag)
get_proxy_referral_url(tag)
list_proxy_referrals()
get_proxy_referral_summary() - per-tier breakdown
- api.py: expose 2 new endpoints
GET /v1/proxy/referrals - full catalog + summary
GET /v1/proxy/referrals/{tag} - single provider
- 12/12 existing proxy_manager tests still pass
- Total routes: 195 -> 197
This commit is contained in:
parent
465ff0bd55
commit
239543d695
3 changed files with 131 additions and 0 deletions
34
api.py
34
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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
53
proxy_referrals.py
Normal file
53
proxy_referrals.py
Normal file
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue