|
| 1 | +#!/usr/bin/env -S uv run --script |
| 2 | +# |
| 3 | +# /// script |
| 4 | +# requires-python = ">=3.12" |
| 5 | +# dependencies = ["requests"] |
| 6 | +# /// |
| 7 | + |
| 8 | +import requests |
| 9 | +import os |
| 10 | +import json |
| 11 | + |
| 12 | +username = 'your-username' # Replace with your Chart Studio username |
| 13 | +api_key = 'your-api-key' # Replace with your API key from Chart Studio |
| 14 | + |
| 15 | +headers = {"Plotly-Client-Platform": "Python 3 0.3.2"} |
| 16 | +auth = requests.auth.HTTPBasicAuth(username, api_key) |
| 17 | + |
| 18 | +# Fetch all plots with pagination |
| 19 | +all_plots = [] |
| 20 | +page = 1 |
| 21 | +per_page = 10 # Max items per page |
| 22 | + |
| 23 | +while True: |
| 24 | + url = f"https://api.plot.ly/v2/folders/home?user={username}&page={page}&per_page={per_page}" |
| 25 | + response = requests.get(url, auth=auth, headers=headers) |
| 26 | + |
| 27 | + if response.status_code != 200: |
| 28 | + print(f"❌ Error accessing plots: {response.status_code}") |
| 29 | + print(f"Response: {response.text}") |
| 30 | + exit(1) |
| 31 | + |
| 32 | + data = response.json() |
| 33 | + children = data.get("children", {}).get("results", []) |
| 34 | + |
| 35 | + if not children: |
| 36 | + break |
| 37 | + |
| 38 | + # Filter to only include plots (filetype == 'plot') |
| 39 | + plots = [p for p in children if p.get("filetype") == "plot"] |
| 40 | + all_plots.extend(plots) |
| 41 | + |
| 42 | + print(f"📄 Page {page}: Found {len(plots)} plots") |
| 43 | + |
| 44 | + # Check if there are more pages |
| 45 | + total_count = data.get("children", {}).get("count", 0) |
| 46 | + if len(all_plots) >= total_count or len(children) < per_page: |
| 47 | + break |
| 48 | + |
| 49 | + page += 1 |
| 50 | + |
| 51 | +print(f"\n✅ Total plots owned by {username}: {len(all_plots)}") |
| 52 | + |
| 53 | +if all_plots: |
| 54 | + print(f"First plot: {all_plots[0]}") |
| 55 | +fids = [p["fid"] for p in all_plots] |
| 56 | + |
| 57 | +# Create output directory if it doesn't exist |
| 58 | +os.makedirs("charts", exist_ok=True) |
| 59 | + |
| 60 | +for fid in fids: |
| 61 | + # Get the chart JSON data |
| 62 | + plot_url = f"https://api.plotly.com/v2/plots/{fid}/content?inline_data=true" |
| 63 | + plot_response = requests.get(plot_url, auth=auth, headers=headers) |
| 64 | + |
| 65 | + if plot_response.status_code == 200: |
| 66 | + # Parse the JSON response |
| 67 | + chart_data = plot_response.json() |
| 68 | + |
| 69 | + # Generate standalone HTML with Plotly.js 1.58.5 |
| 70 | + data_json = json.dumps(chart_data['data']) |
| 71 | + layout_json = json.dumps(chart_data['layout']) |
| 72 | + |
| 73 | + html_template = f"""<html> |
| 74 | + <head><meta charset="utf-8" /></head> |
| 75 | + <body> |
| 76 | + <div id="plotly-div"></div> |
| 77 | + <script src="https://cdn.plot.ly/plotly-1.58.5.min.js"></script> |
| 78 | + <script> |
| 79 | + var data = {data_json}; |
| 80 | + var layout = {layout_json}; |
| 81 | + Plotly.newPlot('plotly-div', data, layout); |
| 82 | + </script> |
| 83 | + </body> |
| 84 | +</html>""" |
| 85 | + |
| 86 | + # Save as HTML |
| 87 | + safe_filename = f"{fid}.html" |
| 88 | + filepath = os.path.join("charts", safe_filename) |
| 89 | + with open(filepath, "w") as f: |
| 90 | + f.write(html_template) |
| 91 | + print(f" ✅ Saved to {filepath}") |
| 92 | + else: |
| 93 | + print(f" ❌ Failed: HTTP {plot_response.status_code}") |
0 commit comments